private async Task SendPump(CancellationToken cancellation) { using (var session = this.serializerSessionPool.GetSession()) { while (!cancellation.IsCancellationRequested && await this.outgoingReader.WaitToReadAsync(cancellation)) { while (this.outgoingReader.TryRead(out var item)) { WriteMessage(item, session); if (item.Body is IDisposable disposable) { disposable.Dispose(); } MessagePool.Return(item); session.PartialReset(); var flushResult = await this.connection.Output.FlushAsync(cancellation); if (flushResult.IsCanceled || flushResult.IsCompleted) { return; } } } } void WriteMessage(Message message, SerializerSession session) { var writer = new Writer <PipeWriter>(this.connection.Output, session); this.messageSerializer.Serialize(ref writer, message); } }
private void GrabController_OnGrabNothing(ControllerGrabberData controller, IHandleGrabbing grabbedObj) { if (NetServices.isNetworked && NetServices.isClient) { // spawn! // or if networked, ask server for permission to spawn. // also give spawn request feedback, and success/fail feedback... but in separate feedback class. var msgReq = MessagePool.Get <SpawnGrabRequestMessage>(); msgReq.isLeft = controller.isLeft; msgReq.prefabType = GetSpawnType(controller.isLeft); ClientNetSender.instance.Send(msgReq, UnityEngine.Networking.QosType.ReliableSequenced); MessagePool.Return(msgReq); } else if (!NetServices.isNetworked) { // spawn! but beware: it might get out of sync with server... so upon reconnect, all those objects must be destroyed or re-synced! :( how the f**k to do that??? var newObj = PrefabManager.instance.Spawn(prefabType, controller.grabPointGO.transform.position, controller.grabPointGO.transform.rotation); var grabber = newObj.gameObject.GetComponent <IHandleGrabbing>(); if (grabber != null) { controller.Grab(grabber); } Debug.Log("<color=#aa6000>Spawned non-synced object</color>", newObj.gameObject); } }
public override void ClientHandleMessageFromServer(NetMessageType messageType, byte[] buffer) { // if message from server to clients if (messageType == NetMessageType.VRBodyUpdateS2C) { var msg = MessagePool.Get <VRBodyUpdateS2CMessage>(buffer); var remotePlayer = NetServices.playerManager.players.GetValueOrDefault(msg.netId); if (remotePlayer != null) { var bodyData = new VRBodyUpdateData() { position = msg.position, //RemotePos(senderPlayer.netId, msg.position), headPosition = msg.headPosition, headRotation = msg.headRotation, leftHandPosition = msg.leftHandPosition, leftHandRotation = msg.leftHandRotation, rightHandPosition = msg.rightHandPosition, rightHandRotation = msg.rightHandRotation }; (remotePlayer as NetPlayerBase).GetComponent <VRBodyUpdateSync>().HandleUpdate(bodyData); } MessagePool.Return(msg); } }
public override void ServerHandleMessageFromClient(NetMessageType messageType, byte[] buffer, short clientPlayerNetId) { // if message is from a client to server if (messageType == NetMessageType.VRBodyUpdateC2S) { var senderPlayer = NetServices.playerManager.players.GetValueOrDefault(clientPlayerNetId); if (senderPlayer != null) { // deserialize message and have the player sync script handle it further var msg = MessagePool.Get <VRBodyUpdateC2SMessage>(buffer); var bodyData = new VRBodyUpdateData() { position = msg.position, //ServerPos(senderPlayer.netId, msg.position), headPosition = msg.headPosition, headRotation = msg.headRotation, leftHandPosition = msg.leftHandPosition, leftHandRotation = msg.leftHandRotation, rightHandPosition = msg.rightHandPosition, rightHandRotation = msg.rightHandRotation }; // this smells like bad performance. but it keeps dependencies separate. // perhaps instead of GetComponent<> it can be optimized via some local VRPlayerManager that handles references of VR components on all players. // every new system which has dependencies on previous systems can use this paradigm: a manager with references to connect the dependency to the new system, for efficiency, without compromising the dependency. // for now we use the shitty method below because there are bigger bottlenecks (senderPlayer as NetPlayerBase).GetComponent <VRBodyUpdateSync>().HandleUpdate(bodyData); MessagePool.Return(msg); } } }
public override void ServerHandleMessageFromClient(NetMessageType messageType, byte[] buffer, short clientPlayerNetId) { switch (messageType) { case NetMessageType.Grab: { var msg = MessagePool.Get <GrabMessage>(buffer); var player = NetServices.playerManager.GetPlayer(msg.netId); if (player != null) { RigidbodySyncComponent rbc = RbSyncManager.instance.Get(msg.syncId); if (rbc != null) { var grabSystem = player.gameObject.GetComponent <VRPlayerGrabSystem>(); var cgd = grabSystem.GetControllerGrabberData(msg.leftHand); cgd.Grab(rbc.GetComponent <IHandleGrabbing>()); rbc.StopUpdating(cgd.controller); ServerNetSender.instance.SendToAll(msg, UnityEngine.Networking.QosType.ReliableSequenced, msg.netId); } } MessagePool.Return(msg); break; } case NetMessageType.Throw: { var msg = MessagePool.Get <ThrowMessage>(buffer); var player = NetServices.playerManager.GetPlayer(msg.netId); if (player != null) { RigidbodySyncComponent rbc = RbSyncManager.instance.Get(msg.syncId); if (rbc != null) { var grabSystem = player.gameObject.GetComponent <VRPlayerGrabSystem>(); var cgd = grabSystem.GetControllerGrabberData(msg.leftHand); cgd.Ungrab(); rbc.ContinueUpdating(cgd.controller); var rb = rbc.rigidbody; rb.position = msg.position; rb.rotation = msg.rotation; rb.velocity = msg.velocity; rb.maxAngularVelocity = Mathf.Max(rb.maxAngularVelocity, msg.angularVelocity.magnitude); rb.angularVelocity = msg.angularVelocity; // send to clients now ServerNetSender.instance.SendToAll(msg, UnityEngine.Networking.QosType.ReliableSequenced, msg.netId); } } MessagePool.Return(msg); break; } } }
private void HandlePlayerLocalStart(byte[] buffer) { var msg = MessagePool.Get <PlayerLocalStartMessage>(buffer); var id = msg.netId; if (GetPlayer(id) != null) { Debug.LogError(this.ToString() + " HandlePlayerStart another player is already registered with net id == " + id.ToString()); MessagePool.Return(msg); return; } //var serverOS = msg.serverOriginShift; //NetOriginShiftManager.instance.SetServerOriginShift(serverOS); // msg.position is serverpos. local player must know about serverOS before it can perform RemotePos //var pos = RemotePos(msg.position); var pos = msg.position; var color = msg.color; var playerType = msg.playerType; // do not use a pool for the local player, since there will only ever be one of those var localPlayer = PlayerTypeManager.instance.InstantiatePlayer <INetPlayer>(playerType, GameType.Local, pos); localPlayer.SetIsLocal(); localPlayer.gameObject.name = GetPlayerName(); // how to set color on player? //localPlayer.color = color; AddPlayer(localPlayer, id); // old code from old system = player rigidbodies were spawned and the rigidbody sync system was used to sync their wobble instead of the player messages. Required for impaling arrows in player's head //if (msg.headRbSyncId >= 0 && msg.bodyRbSyncId >= 0) //{ // localPlayer.SetupRigidbodies(msg.headRbSyncId, msg.bodyRbSyncId); //} Debug.Log("<color=#dd9922>" + this.ToString() + " HandlePlayerStart created local player" + "</color>" + " by id == " + localPlayer.netId.ToString() + " and name == " + localPlayer.gameObject.name); MessagePool.Return(msg); if (ConnectUIHandler.instance != null) { ConnectUIHandler.instance.Disable(); } }
// only used by debug shit private void HandleRigidbodySyncSpawn(byte[] buffer) { var msg = MessagePool.Get <RigidbodySyncSpawnMessage>(buffer); var manager = ClientRbSyncManager.instance; if (manager.Has(msg.data.syncId)) { Debug.LogWarning(this.ToString() + " already has a synced rigidbody by id == " + msg.data.syncId.ToString() + ", aborting creation of a new one"); MessagePool.Return(msg); return; } var data = msg.data; // we don't use this for now //data.position = RemotePos(data.position); NewRigidbodySync(data); MessagePool.Return(msg); }
public override void ServerHandleMessageFromClient(NetMessageType messageType, byte[] buffer, short clientPlayerNetId) { // WE ARE SERVER if (messageType == NetMessageType.SpawnGrabRequest) { var msg = MessagePool.Get <SpawnGrabRequestMessage>(buffer); // spawn on server, assign id and tell everyone to also spawn. and tell player to grab... maybe client should grab and then continue with a separate message for that? var player = NetServices.playerManager.GetPlayer(clientPlayerNetId); if (player != null) { var isLeft = msg.isLeft; var spawnPrefabType = msg.prefabType; // grab stuff var grabSystem = player.gameObject.GetComponent <VRPlayerGrabSystem>(); var hand = grabSystem.GetControllerGrabberData(isLeft); // definitely spawn new object var newObj = PrefabManager.instance.Spawn(spawnPrefabType, hand.grabPointGO.transform.position, hand.grabPointGO.transform.rotation); // initialize new object with a cool new id var rsc = newObj.gameObject.GetComponent <RigidbodySyncComponent>(); var nextId = ServerRbSyncManager.instance.GetNextSyncId(); rsc.Initialize(nextId); var grabber = newObj.gameObject.GetComponent <IHandleGrabbing>(); if (grabber != null) { hand.Grab(grabber); } // send response so the grab happens across the network var responseMsg = MessagePool.Get <SpawnGrabResponseMessage>(); responseMsg.prefabType = msg.prefabType; responseMsg.isLeft = msg.isLeft; responseMsg.syncId = nextId; responseMsg.playerId = clientPlayerNetId; // send to ALL incl. request client ServerNetSender.instance.SendToAll(responseMsg, UnityEngine.Networking.QosType.ReliableSequenced); MessagePool.Return(responseMsg); } MessagePool.Return(msg); } }
public override void ClientHandleMessageFromServer(NetMessageType messageType, byte[] buffer) { if (messageType == NetMessageType.SpawnGrabResponse) { var msg = MessagePool.Get <SpawnGrabResponseMessage>(buffer); // if player not null, spawn the object and grab it. var player = NetServices.playerManager.GetPlayer(msg.playerId); if (player != null) { var grabSystem = player.gameObject.GetComponent <VRPlayerGrabSystem>(); var hand = grabSystem.GetControllerGrabberData(msg.isLeft); RigidbodySyncComponent rsc; // first, check if object already exists rsc = ClientRbSyncManager.instance.Get(msg.syncId); if (rsc == null) { // spawn obj and sync it var newObj = PrefabManager.instance.Spawn(msg.prefabType, hand.grabPointGO.transform.position, hand.grabPointGO.transform.rotation); rsc = newObj.gameObject.GetComponent <RigidbodySyncComponent>(); rsc.Initialize(msg.syncId); } else { if (rsc.prefabType != msg.prefabType) { Debug.LogError("[SpawnSystem] Error: the object " + rsc + " with id " + rsc.syncId + " already exists, but is not of the requested type " + msg.prefabType); } } // grab it var grabber = rsc.GetComponent <IHandleGrabbing>(); if (grabber != null) { hand.Grab(grabber); } } MessagePool.Return(msg); } }
private void HandlePlayerRemoteConnect(byte[] buffer) { var msg = MessagePool.Get <PlayerRemoteConnectMessage>(buffer); var id = msg.netId; if (GetPlayer(id) != null) { Debug.LogError(this.ToString() + " HandlePlayerConnect another player is already registered with net id == " + id.ToString()); MessagePool.Return(msg); return; } ////Debug.Log(this.ToString() + " HandlePlayerConnect create remote player by id == " + id.ToString() + ", name == " + msg.name.ToString() + ", at position == " + msg.position.ToString()); var os = msg.originShift; // remote connect = a new player connected. his origin shift is startingPos on his start. //NetOriginShiftManager.instance.SetPlayerOriginShift(id, os); // if using origin shift, server position data must be calculated with server origin shift. //var pos = RemotePos(msg.position); var pos = msg.position; var color = msg.color; var name = msg.name; // use the pool for remotes, they are all the same var player = PlayerTypeManager.instance.InstantiatePlayer <INetPlayer>(msg.playerType, GameType.Remote, pos); //player.color = color; player.gameObject.name = name; AddPlayer(player, id); //if (msg.headRbSyncId >= 0 && msg.bodyRbSyncId >= 0) //{ // player.SetupRigidbodies(msg.headRbSyncId, msg.bodyRbSyncId); //} Debug.Log("<color=#dd9922>" + this.ToString() + " HandlePlayerConnect created remote player" + "</color>" + " by id == " + player.netId.ToString() + " and name == " + player.gameObject.name); MessagePool.Return(msg); }
public override void OnConnect(int connectionId, NetworkError error) { if (error != NetworkError.Ok) { Debug.LogError("<color=red>" + this.ToString() + " OnConnect could not establish a connection to server" + "</color>" + ", error == " + error.ToString()); return; } // if reconnect, send a reconnect message with the previous netId so the server reestablishes the same player as this client // {} // else { // Connection to server established, send a name message var nameMessage = MessagePool.Get <PlayerLocalConnectMessage>(); nameMessage.name = GetPlayerName(); nameMessage.playerType = PlayerTypeManager.instance.GetCurrentPlayerType(); // PlayerType.Normal; // TODO: get player type choice? _network.Send(nameMessage, QosType.Reliable); MessagePool.Return(nameMessage); // } Debug.Log("<color=#339900>" + this.ToString() + " OnConnect. Connection Id == " + connectionId.ToString() + "</color>" + ", error == " + error.ToString()); }
private void HandlePlayerDisconnect(byte[] buffer) { var msg = MessagePool.Get <PlayerDisconnectMessageDefault>(buffer); var player = GetPlayer <INetPlayer>(msg.netId); if (player == null) { Debug.LogError(this.ToString() + " HandlePlayerDisconnect received disconnect message for unknown player with net id == " + msg.netId.ToString()); MessagePool.Return(msg); return; } Debug.Log(this.ToString() + " HandlePlayerDisconnect for player by netId == " + msg.netId.ToString() + ", player name == " + player.gameObject.name.ToString()); //NetOriginShiftManager.instance.RemovePlayer(msg.netId); if (!RemovePlayer(msg.netId)) { Debug.LogWarning(this.ToString() + " found player by id == " + msg.netId.ToString() + ", removal was unsuccessful"); } PlayerTypeManager.instance.Return(player.gameObject); MessagePool.Return(msg); }
private void HandleRigidbodySyncUpdate(byte[] buffer) { var msg = MessagePool.Get <RigidbodySyncUpdateMessage>(buffer); var manager = ClientRbSyncManager.instance; var initial = msg.initial; var data = msg.data; var count = data.Count; for (int i = 0; i < count; i++) { var d = data[i]; //d.position = RemotePos(d.position); var rb = manager.Get(d.syncId); if (rb == null) { // if the client does not have the synced rigidbody, create if from the data received rb = NewRigidbodySync(d); } rb.HandleUpdate(d, initial); } MessagePool.Return(msg); }
public override void OnDisconnect(int connectionId, NetworkError error) { var player = GetPlayer <INetPlayer>(connectionId); if (player == null) { Debug.LogWarning(this.ToString() + " OnDisconnect received disconnect from unknown player with connection ID == " + connectionId.ToString()); return; } Debug.Log(this.ToString() + " OnDisconnect. Removing player (" + player.ToString() + ") by net id == " + player.netId.ToString() + ". Connection Id == " + connectionId.ToString() + ", error == " + error.ToString()); // Remove disconnected players - before sending out message, to avoid sending to the leaver var netId = player.netId; RemovePlayer(player); PlayerTypeManager.instance.Return(player.gameObject); // inform all other clients of the leaver, except the one actually leaving (since he is already disconnected) var msg = MessagePool.Get <PlayerDisconnectMessageDefault>(netId); _network.SendToAll(msg, QosType.Reliable); MessagePool.Return(msg); }
private void HandlePlayerLocalConnect(int connectionId, byte[] buffer) { var localConnectMsg = MessagePool.Get <PlayerLocalConnectMessage>(buffer); var name = localConnectMsg.name; var playerType = localConnectMsg.playerType; MessagePool.Return(localConnectMsg); var player = GetPlayer <INetPlayer>(connectionId); if (player != null) { Debug.LogWarning(this.ToString() + " HandlePlayerName another player is already registered with connection id == " + connectionId.ToString() + ", existing player name == " + player.gameObject.name + ", new player's desired name == " + name); return; } if (string.IsNullOrEmpty(name)) { name = "Random Name"; // TODO: what to do about players with no name? (can it even happen?) } var netId = GetNextPlayerId(); var pos = _startPositions[netId % _startPositions.Count].transform.position; // send a special 'start message' to the new player so that the local player prefab can be set up. also tells it about the server origin shift var startMsg = MessagePool.Get <PlayerLocalStartMessage>(netId); startMsg.position = pos; startMsg.playerType = playerType; _network.Send(connectionId, startMsg, QosType.ReliableSequenced); MessagePool.Return(startMsg); // a new client has connected - inform all other clients of the new player. and don't send this to the new player. var connectMsg = MessagePool.Get <PlayerRemoteConnectMessage>(netId); connectMsg.position = pos; connectMsg.name = name; connectMsg.playerType = playerType; _network.SendToAll(connectMsg, QosType.Reliable, netId); // Inform the new player of all the existing client players (if there are any). if (_players.Count > 0) { var enumerator = _players.GetEnumerator(); try { while (enumerator.MoveNext()) // AddPlayer() adds the player at the end of the function, so don't worry. { // send to the new connecting player, but send a connect message containing details of all the other existing clients var p = (INetPlayer)enumerator.Current.Value; connectMsg.netId = p.netId; connectMsg.position = p.gameObject.transform.position; // position on the server. the client receiver will handle the trasformation using RemotePos(), though it needs the server OS which is why the start message is reliable sequenced. //connectMsg.originShift = NetOriginShiftManager.instance.GetPlayerOriginShift(p.netId); //connectMsg.color = p.color; connectMsg.name = p.gameObject.name; //connectMsg.playerType = p.playerType; //connectMsg.headRbSyncId = p.headSync.syncId; //connectMsg.bodyRbSyncId = p.bodySync.syncId; _network.Send(connectionId, connectMsg, QosType.Reliable); } } finally { enumerator.Dispose(); } } MessagePool.Return(connectMsg); // actually create and add the new player var newPlayer = PlayerTypeManager.instance.InstantiatePlayer <INetPlayer>(playerType, GameType.Server, pos); //newPlayer.color = color; newPlayer.gameObject.name = name; AddPlayer(newPlayer, connectionId, netId); Debug.Log(this.ToString() + " HandlePlayerName() - added new player by net id == " + netId.ToString() + " and name == " + name + " for connection id == " + connectionId.ToString()); }