private void OnServerRpcReply(INetworkPlayer player, ServerRpcReply reply) { // find the callback that was waiting for this and invoke it. if (callbacks.TryGetValue(reply.replyId, out Action <NetworkReader> action)) { callbacks.Remove(replyId); using (PooledNetworkReader reader = NetworkReaderPool.GetReader(reply.payload)) { reader.ObjectLocator = Client.World; action(reader); } } else { throw new MethodAccessException("Received reply but no handler was registered"); } }
void ApplySpawnPayload(NetworkIdentity identity, SpawnMessage msg) { if (msg.assetId != Guid.Empty) { identity.AssetId = msg.assetId; } if (!identity.gameObject.activeSelf) { identity.gameObject.SetActive(true); } // apply local values for VR support identity.transform.localPosition = msg.position; identity.transform.localRotation = msg.rotation; identity.transform.localScale = msg.scale; identity.HasAuthority = msg.isOwner; identity.NetId = msg.netId; identity.Client = Client; identity.ClientObjectManager = this; if (msg.isLocalPlayer) { InternalAddPlayer(identity); } // deserialize components if any payload // (Count is 0 if there were no components) if (msg.payload.Count > 0) { using (PooledNetworkReader payloadReader = NetworkReaderPool.GetReader(msg.payload)) { identity.OnDeserializeAllSafely(payloadReader, true); } } SpawnedObjects[msg.netId] = identity; // objects spawned as part of initial state are started on a second pass identity.NotifyAuthority(); identity.StartClient(); CheckForLocalPlayer(identity); }
private void OnServerRpc(INetworkPlayer player, uint netId, int componentIndex, int functionIndex, ArraySegment <byte> payload, int replyId) { if (!Server.World.TryGetIdentity(netId, out var identity)) { if (logger.WarnEnabled()) { logger.LogWarning($"Spawned object not found when handling ServerRpc message [netId={netId}]"); } return; } var behaviour = identity.NetworkBehaviours[componentIndex]; var remoteCall = behaviour.remoteCallCollection.Get(functionIndex); if (remoteCall.InvokeType != RpcInvokeType.ServerRpc) { throw new MethodInvocationException($"Invalid ServerRpc for index {functionIndex}"); } // ServerRpcs can be for player objects, OR other objects with client-authority // -> so if this connection's controller has a different netId then // only allow the ServerRpc if clientAuthorityOwner if (remoteCall.RequireAuthority && identity.Owner != player) { if (logger.WarnEnabled()) { logger.LogWarning($"ServerRpc for object without authority [netId={netId}]"); } return; } if (logger.LogEnabled()) { logger.Log($"OnServerRpcMessage for netId={netId} conn={player}"); } using (var reader = NetworkReaderPool.GetReader(payload, Server.World)) { remoteCall.Invoke(reader, behaviour, player, replyId); } }
void CmdOnAnimationServerMessage(int stateHash, float normalizedTime, int layerId, float weight, byte[] parameters) { // Ignore messages from client if not in client authority mode if (!ClientAuthority) { return; } if (logger.LogEnabled()) { logger.Log("OnAnimationMessage for netId=" + NetId); } // handle and broadcast using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(parameters)) { HandleAnimMsg(stateHash, normalizedTime, layerId, weight, networkReader); RpcOnAnimationClientMessage(stateHash, normalizedTime, layerId, weight, parameters); } }
void OnUpdateVarsMessage(UpdateVarsMessage msg) { if (logger.LogEnabled()) { logger.Log("ClientScene.OnUpdateVarsMessage " + msg.netId); } if (objectLocator.TryGetIdentity(msg.netId, out NetworkIdentity localObject)) { using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(msg.payload)) localObject.OnDeserializeAll(networkReader, false); } else { if (logger.WarnEnabled()) { logger.LogWarning("Did not find target for sync message for " + msg.netId + " . Note: this can be completely normal because UDP messages may arrive out of order, so this message might have arrived after a Destroy message."); } } }
public void ReadBytesCountTooBigTest() { // calling ReadBytes with a count bigger than what is in Reader // should throw an exception byte[] bytes = { 0x00, 0x01 }; using (PooledNetworkReader reader = NetworkReaderPool.GetReader(bytes)) { try { reader.ReadBytes(bytes, bytes.Length + 1); // BAD: IF WE GOT HERE, THEN NO EXCEPTION WAS THROWN Assert.Fail(); } catch (EndOfStreamException) { // GOOD } } }
public void ShrinkCapacity() { NetworkReaderPool.Capacity = 2; // get Reader and recycle so we have 2 in there, hence 'next' is at limit PooledNetworkReader a = NetworkReaderPool.GetReader(default(ArraySegment <byte>)); PooledNetworkReader b = NetworkReaderPool.GetReader(default(ArraySegment <byte>)); NetworkReaderPool.Recycle(a); NetworkReaderPool.Recycle(b); // shrink NetworkReaderPool.Capacity = 1; // get one. should return the only one which is still in there. PooledNetworkReader c = NetworkReaderPool.GetReader(default(ArraySegment <byte>)); Assert.That(c, !Is.Null); Assert.That(c == a || c == b); }
/// <summary> /// Handle ServerRpc from specific player, this could be one of multiple players on a single client /// </summary> /// <param name="conn"></param> /// <param name="msg"></param> void OnServerRpcMessage(INetworkConnection conn, ServerRpcMessage msg) { if (!SpawnedObjects.TryGetValue(msg.netId, out NetworkIdentity identity) || identity is null) { if (logger.WarnEnabled()) { logger.LogWarning("Spawned object not found when handling ServerRpc message [netId=" + msg.netId + "]"); } return; } Skeleton skeleton = RemoteCallHelper.GetSkeleton(msg.functionHash); if (skeleton.invokeType != MirageInvokeType.ServerRpc) { throw new MethodInvocationException($"Invalid ServerRpc for id {msg.functionHash}"); } // ServerRpcs can be for player objects, OR other objects with client-authority // -> so if this connection's controller has a different netId then // only allow the ServerRpc if clientAuthorityOwner if (skeleton.cmdRequireAuthority && identity.ConnectionToClient != conn) { if (logger.WarnEnabled()) { logger.LogWarning("ServerRpc for object without authority [netId=" + msg.netId + "]"); } return; } if (logger.LogEnabled()) { logger.Log("OnServerRpcMessage for netId=" + msg.netId + " conn=" + conn); } using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(msg.payload)) { networkReader.ObjectLocator = this; identity.HandleRemoteCall(skeleton, msg.componentIndex, networkReader, conn, msg.replyId); } }
internal void OnRpcMessage(RpcMessage msg) { if (logger.LogEnabled()) { logger.Log("ClientScene.OnRPCMessage hash:" + msg.functionHash + " netId:" + msg.netId); } Skeleton skeleton = RemoteCallHelper.GetSkeleton(msg.functionHash); if (skeleton.invokeType != RpcInvokeType.ClientRpc) { throw new MethodInvocationException($"Invalid RPC call with id {msg.functionHash}"); } if (Client.World.TryGetIdentity(msg.netId, out NetworkIdentity identity)) { using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(msg.payload)) { networkReader.ObjectLocator = Client.World; identity.HandleRemoteCall(skeleton, msg.componentIndex, networkReader); } } }
void CmdClientToServerSync(byte[] payload) { // Ignore messages from client if not in client authority mode if (!ClientAuthority) { return; } // deserialize payload using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(payload)) DeserializeFromReader(networkReader); // server-only mode does no interpolation to save computations, // but let's set the position directly if (IsServer && !IsClient) { ApplyPositionRotationScale(goal.LocalPosition, goal.LocalRotation, goal.LocalScale); } // set dirty so that OnSerialize broadcasts it SetDirtyBit(1UL); }
public void PoolReUsesReadersUpToSizeLimit() { NetworkReaderPool.Capacity = 1; // get 2 Readers PooledNetworkReader a = NetworkReaderPool.GetReader(default(ArraySegment <byte>)); PooledNetworkReader b = NetworkReaderPool.GetReader(default(ArraySegment <byte>)); // recycle all NetworkReaderPool.Recycle(a); NetworkReaderPool.Recycle(b); // get 2 new ones PooledNetworkReader c = NetworkReaderPool.GetReader(default(ArraySegment <byte>)); PooledNetworkReader d = NetworkReaderPool.GetReader(default(ArraySegment <byte>)); // exactly one should be reused, one should be new bool cReused = c == a || c == b; bool dReused = d == a || d == b; Assert.That((cReused && !dReused) || (!cReused && dReused)); }
void RpcOnAnimationParametersClientMessage(byte[] parameters) { using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(parameters)) HandleAnimParamsMsg(networkReader); }
void RpcOnAnimationClientMessage(int stateHash, float normalizedTime, int layerId, float weight, byte[] parameters) { using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(parameters)) HandleAnimMsg(stateHash, normalizedTime, layerId, weight, networkReader); }
private void RpcOnAnimationParametersClientMessage(ArraySegment <byte> parameters) { using (var networkReader = NetworkReaderPool.GetReader(parameters, null)) HandleAnimParamsMsg(networkReader); }
private void RpcOnAnimationClientMessage(int stateHash, float normalizedTime, int layerId, float weight, ArraySegment <byte> parameters) { using (var networkReader = NetworkReaderPool.GetReader(parameters, null)) HandleAnimMsg(stateHash, normalizedTime, layerId, weight, networkReader); }
public void Dispose() { NetworkReaderPool.Recycle(this); }