private void OnPlayerUpdate(On.HeroController.orig_Update orig, HeroController self) { // Make sure the original method executes orig(self); // Ignore player position updates on non-gameplay scenes var currentSceneName = SceneUtil.GetCurrentSceneName(); if (SceneUtil.IsNonGameplayScene(currentSceneName)) { return; } // If we are not connected, there is nothing to send to if (!_netClient.IsConnected) { return; } var heroTransform = HeroController.instance.transform; var newPosition = heroTransform.position; // If the position changed since last check if (newPosition != _lastPosition) { // Update the last position, since it changed _lastPosition = newPosition; if (_sceneChanged) { _sceneChanged = false; // Set some default values for the packet variables in case we don't have a HeroController instance // This might happen when we are in a non-gameplay scene without the knight var position = Vector3.zero; var scale = Vector3.zero; ushort animationClipId = 0; // If we do have a HeroController instance, use its values if (HeroController.instance != null) { var transform = HeroController.instance.transform; position = transform.position; scale = transform.localScale; animationClipId = (ushort)_animationManager.GetCurrentAnimationClip(); } // Create the EnterScene packet var packet = new ServerPlayerEnterScenePacket { NewSceneName = SceneUtil.GetCurrentSceneName(), Position = position, Scale = scale, AnimationClipId = animationClipId }; packet.CreatePacket(); Logger.Info(this, "Sending EnterScene packet"); // Send it to the server _netClient.SendTcp(packet); } else { // If this was not the first position update after a scene change, // we can simply send a position update packet _netClient.SendPositionUpdate(newPosition); } } var newScale = heroTransform.localScale; // If the scale changed since last check if (newScale != _lastScale) { _netClient.SendScaleUpdate(newScale); // Update the last scale, since it changed _lastScale = newScale; } }
private void OnClientEnterScene(ushort id, ServerPlayerEnterScenePacket packet) { if (!_playerData.TryGetValue(id, out var playerData)) { Logger.Warn(this, $"Received EnterScene packet from {id}, but player is not in mapping"); return; } // Read the values in from the packet var newSceneName = packet.NewSceneName; var position = packet.Position; var scale = packet.Scale; var animationClipId = packet.AnimationClipId; Logger.Info(this, $"Received EnterScene packet from ID {id}, new scene: {newSceneName}"); // Store it in their PlayerData object playerData.CurrentScene = newSceneName; playerData.LastPosition = position; playerData.LastScale = scale; playerData.LastAnimationClip = animationClipId; // Create a PlayerEnterScene packet containing the ID // of the player entering the scene and the respective values var enterScenePacket = new ClientPlayerEnterScenePacket { ScenePlayerData = new ScenePlayerData { Id = id, Username = playerData.Username, Position = position, Scale = scale, Team = playerData.Team, AnimationClipId = animationClipId, } }; enterScenePacket.CreatePacket(); // Create the AlreadyInScene packet var alreadyInScenePacket = new ClientAlreadyInScenePacket(); foreach (var idPlayerDataPair in _playerData.GetCopy()) { // Skip source player if (idPlayerDataPair.Key == id) { continue; } var otherPlayerData = idPlayerDataPair.Value; // Send the packet to all clients on the new scene // to indicate that this client has entered their scene if (otherPlayerData.CurrentScene.Equals(newSceneName)) { Logger.Info(this, $"Sending enter scene packet to {idPlayerDataPair.Key}"); _netServer.SendTcp(idPlayerDataPair.Key, enterScenePacket); Logger.Info(this, $"Sending that {idPlayerDataPair.Key} is already in scene to {id}"); // Also send a packet to the client that switched scenes, // notifying that these players are already in this new scene. // We do this by adding a new player data instance to the AlreadyInScene packet alreadyInScenePacket.ScenePlayerData.Add(new ScenePlayerData { Id = idPlayerDataPair.Key, Username = otherPlayerData.Username, Position = otherPlayerData.LastPosition, Scale = otherPlayerData.LastScale, Team = otherPlayerData.Team, AnimationClipId = otherPlayerData.LastAnimationClip, }); } } // Now we send the AlreadyInScene packet after it is completely populated, // or not in case of no players in the scene already _netServer.SendTcp(id, alreadyInScenePacket.CreatePacket()); }