/// <summary> /// Returns a base64 encoded version of the config /// </summary> /// <returns></returns> public string ToBase64() { NetworkConfig config = this; using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed(config.ProtocolVersion); writer.WriteBits((byte)config.Transport, 5); writer.WriteUInt16Packed((ushort)config.Channels.Count); for (int i = 0; i < config.Channels.Count; i++) { writer.WriteString(config.Channels[i].Name); writer.WriteBits((byte)config.Channels[i].Type, 5); } writer.WriteUInt16Packed((ushort)config.RegisteredScenes.Count); for (int i = 0; i < config.RegisteredScenes.Count; i++) { writer.WriteString(config.RegisteredScenes[i]); } writer.WriteUInt16Packed((ushort)config.NetworkedPrefabs.Count); for (int i = 0; i < config.NetworkedPrefabs.Count; i++) { writer.WriteBool(config.NetworkedPrefabs[i].playerPrefab); writer.WriteString(config.NetworkedPrefabs[i].name); } writer.WriteInt32Packed(config.MessageBufferSize); writer.WriteInt32Packed(config.ReceiveTickrate); writer.WriteInt32Packed(config.MaxReceiveEventsPerTickRate); writer.WriteInt32Packed(config.SendTickrate); writer.WriteInt32Packed(config.EventTickrate); writer.WriteInt32Packed(config.MaxConnections); writer.WriteInt32Packed(config.ConnectPort); writer.WriteString(config.ConnectAddress); writer.WriteInt32Packed(config.ClientConnectionBufferTimeout); writer.WriteBool(config.ConnectionApproval); writer.WriteInt32Packed(config.SecondsHistory); writer.WriteBool(config.HandleObjectSpawning); writer.WriteBool(config.EnableEncryption); writer.WriteBool(config.SignKeyExchange); writer.WriteBool(config.EnableSceneSwitching); writer.WriteInt32Packed(config.LoadSceneTimeOut); writer.WriteBool(config.EnableTimeResync); writer.WriteBits((byte)config.RpcHashSize, 3); stream.PadStream(); return(Convert.ToBase64String(stream.ToArray())); } } }
/// <inheritdoc /> public void WriteDelta(Stream stream) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed((ushort)dirtyEvents.Count); for (int i = 0; i < dirtyEvents.Count; i++) { writer.WriteBits((byte)dirtyEvents[i].eventType, 2); switch (dirtyEvents[i].eventType) { case NetworkedSetEvent <T> .EventType.Add: { writer.WriteObjectPacked(dirtyEvents[i].value); //BOX } break; case NetworkedSetEvent <T> .EventType.Remove: { writer.WriteObjectPacked(dirtyEvents[i].value); //BOX } break; case NetworkedSetEvent <T> .EventType.Clear: { //Nothing has to be written } break; } } } }
internal void SendClientRPCPerformance(ulong hash, uint clientId, Stream messageStream, string channel, SecuritySendFlags security) { if (!IsServer && IsRunning) { //We are NOT a server. if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("Only clients and host can invoke ClientRPC"); } return; } using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt32Packed(NetworkId); writer.WriteUInt16Packed(NetworkedObject.GetOrderIndex(this)); writer.WriteUInt64Packed(hash); stream.CopyFrom(messageStream); if (IsHost && clientId == NetworkingManager.Singleton.LocalClientId) { messageStream.Position = 0; InvokeClientRPCLocal(hash, NetworkingManager.Singleton.LocalClientId, messageStream); } else { InternalMessageHandler.Send(clientId, MLAPIConstants.MLAPI_CLIENT_RPC, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, stream, security); } } } }
/// <summary> /// Returns a base64 encoded version of the config /// </summary> /// <returns></returns> public string ToBase64() { NetworkConfig config = this; using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed(config.ProtocolVersion); writer.WriteUInt16Packed((ushort)config.RegisteredScenes.Count); for (int i = 0; i < config.RegisteredScenes.Count; i++) { writer.WriteString(config.RegisteredScenes[i]); } writer.WriteInt32Packed(config.ServerTargetFramerate); writer.WriteInt32Packed(config.NetworkedTransformTickrate); writer.WriteInt32Packed(config.ClientCommandTickrate); writer.WriteInt32Packed(config.MaxReceiveEventsPerTickRate); writer.WriteInt32Packed(config.LagCompensationTickRate); writer.WriteInt32Packed(config.EventTickrate); writer.WriteInt32Packed(config.ClientConnectionBufferTimeout); writer.WriteBool(config.ConnectionApproval); writer.WriteInt32Packed(config.SecondsHistory); writer.WriteBool(config.EnableEncryption); writer.WriteBool(config.SignKeyExchange); writer.WriteInt32Packed(config.LoadSceneTimeOut); writer.WriteBool(config.EnableTimeResync); writer.WriteBool(config.EnsureNetworkedVarLengthSafety); writer.WriteBits((byte)config.RpcHashSize, 2); writer.WriteBool(ForceSamePrefabs); writer.WriteBool(UsePrefabSync); writer.WriteBool(EnableSceneManagement); writer.WriteBool(RecycleNetworkIds); writer.WriteSinglePacked(NetworkIdRecycleDelay); writer.WriteBool(EnableNetworkedVar); writer.WriteBool(AllowRuntimeSceneChanges); writer.WriteBool(EnableNetworkLogs); stream.PadStream(); return(Convert.ToBase64String(stream.ToArray())); } } }
/// <summary> /// Gets a SHA256 hash of parts of the NetworkingConfiguration instance /// </summary> /// <param name="cache"></param> /// <returns></returns> public ulong GetConfig(bool cache = true) { if (ConfigHash != null && cache) { return(ConfigHash.Value); } Sort(); using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed(ProtocolVersion); writer.WriteString(MLAPIConstants.MLAPI_PROTOCOL_VERSION); for (int i = 0; i < Channels.Count; i++) { writer.WriteString(Channels[i].Name); writer.WriteByte((byte)Channels[i].Type); } if (EnableSceneSwitching) { for (int i = 0; i < RegisteredScenes.Count; i++) { writer.WriteString(RegisteredScenes[i]); } } if (HandleObjectSpawning && ForceSamePrefabs) { List <NetworkedPrefab> sortedPrefabList = NetworkedPrefabs.OrderBy(x => x.hash).ToList(); for (int i = 0; i < sortedPrefabList.Count; i++) { writer.WriteUInt64Packed(sortedPrefabList[i].hash); } } writer.WriteBool(ForceSamePrefabs); writer.WriteBool(HandleObjectSpawning); writer.WriteBool(EnableEncryption); writer.WriteBool(EnableSceneSwitching); writer.WriteBool(SignKeyExchange); writer.WriteBits((byte)RpcHashSize, 3); writer.WriteBits((byte)PrefabHashSize, 3); stream.PadStream(); if (cache) { ConfigHash = stream.ToArray().GetStableHash64(); return(ConfigHash.Value); } return(stream.ToArray().GetStableHash64()); } } }
public void Write(Stream stream) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteByte((byte)ImposterCount); writer.WriteSinglePacked(MovementSpeed); writer.WriteSinglePacked(VoteDuration); writer.WriteUInt16Packed((ushort)TaskCount); } }
/// <summary> /// Gets a SHA256 hash of parts of the NetworkingConfiguration instance /// </summary> /// <param name="cache"></param> /// <returns></returns> public ulong GetConfig(bool cache = true) { if (ConfigHash != null && cache) { return(ConfigHash.Value); } Sort(); using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed(ProtocolVersion); writer.WriteString(MLAPIConstants.MLAPI_PROTOCOL_VERSION); for (int i = 0; i < Channels.Count; i++) { writer.WriteString(Channels[i].Name); writer.WriteByte((byte)Channels[i].Type); } if (EnableSceneSwitching) { for (int i = 0; i < RegisteredScenes.Count; i++) { writer.WriteString(RegisteredScenes[i]); } } if (HandleObjectSpawning && RequireNetworkedPrefabsAreSyncronized) { for (int i = 0; i < NetworkedPrefabs.Count; i++) { writer.WriteString(NetworkedPrefabs[i].name); } } writer.WriteBool(HandleObjectSpawning); writer.WriteBool(EnableEncryption); writer.WriteBool(EnableSceneSwitching); writer.WriteBool(SignKeyExchange); writer.WriteBits((byte)AttributeMessageMode, 3); // Returns a 160 bit / 20 byte / 5 int checksum of the config if (cache) { ConfigHash = stream.ToArray().GetStableHash64(); return(ConfigHash.Value); } return(stream.ToArray().GetStableHash64()); } } }
/// <inheritdoc /> public void WriteField(Stream stream) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed((ushort)list.Count); for (int i = 0; i < list.Count; i++) { writer.WriteObjectPacked(list[i]); //BOX } } }
/// <summary> /// Writes the current ProfilerTick to the stream /// </summary> /// <param name="stream">The stream containing</param> public void SerializeToStream(Stream stream) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed((ushort)Events.Count); for (int i = 0; i < Events.Count; i++) { Events[i].SerializeToStream(stream); } } }
/// <inheritdoc /> public void WriteField(Stream stream) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed((ushort)set.Count); foreach (T value in set) { writer.WriteObjectPacked(value); //BOX } } }
/// <inheritdoc /> public void WriteField(Stream stream) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed((ushort)dictionary.Count); foreach (KeyValuePair <TKey, TValue> pair in dictionary) { writer.WriteObjectPacked(pair.Key); writer.WriteObjectPacked(pair.Value); } } }
/// <inheritdoc /> public void WriteDelta(Stream stream) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed((ushort)dirtyEvents.Count); for (int i = 0; i < dirtyEvents.Count; i++) { writer.WriteBits((byte)dirtyEvents[i].eventType, 3); switch (dirtyEvents[i].eventType) { //F**k me these signatures are proper aids case NetworkedListEvent <T> .EventType.Add: { writer.WriteObjectPacked(dirtyEvents[i].value); //BOX } break; case NetworkedListEvent <T> .EventType.Insert: { writer.WriteInt32Packed(dirtyEvents[i].index); writer.WriteObjectPacked(dirtyEvents[i].value); //BOX } break; case NetworkedListEvent <T> .EventType.Remove: { writer.WriteObjectPacked(dirtyEvents[i].value); //BOX } break; case NetworkedListEvent <T> .EventType.RemoveAt: { writer.WriteInt32Packed(dirtyEvents[i].index); } break; case NetworkedListEvent <T> .EventType.Value: { writer.WriteInt32Packed(dirtyEvents[i].index); writer.WriteObjectPacked(dirtyEvents[i].value); //BOX } break; case NetworkedListEvent <T> .EventType.Clear: { //Nothing has to be written } break; } } } }
/// <summary> /// Gets a SHA256 hash of parts of the NetworkingConfiguration instance /// </summary> /// <param name="cache"></param> /// <returns></returns> public ulong GetConfig(bool cache = true) { if (ConfigHash != null && cache) { return(ConfigHash.Value); } Sort(); using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed(ProtocolVersion); writer.WriteString(MLAPIConstants.MLAPI_PROTOCOL_VERSION); if (EnableSceneManagement && !AllowRuntimeSceneChanges) { for (int i = 0; i < RegisteredScenes.Count; i++) { writer.WriteString(RegisteredScenes[i]); } } if (ForceSamePrefabs) { List <NetworkedPrefab> sortedPrefabList = NetworkedPrefabs.OrderBy(x => x.Hash).ToList(); for (int i = 0; i < sortedPrefabList.Count; i++) { writer.WriteUInt64Packed(sortedPrefabList[i].Hash); } } writer.WriteBool(EnableNetworkedVar); writer.WriteBool(ForceSamePrefabs); writer.WriteBool(UsePrefabSync); writer.WriteBool(EnableSceneManagement); writer.WriteBool(EnsureNetworkedVarLengthSafety); writer.WriteBool(EnableEncryption); writer.WriteBool(SignKeyExchange); writer.WriteBits((byte)RpcHashSize, 2); stream.PadStream(); if (cache) { ConfigHash = stream.ToArray().GetStableHash64(); return(ConfigHash.Value); } return(stream.ToArray().GetStableHash64()); } } }
/// <summary> /// Returns a base64 encoded version of the config /// </summary> /// <returns></returns> public string ToBase64() { NetworkConfig config = this; using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed(config.ProtocolVersion); writer.WriteUInt16Packed((ushort)config.RegisteredScenes.Count); for (int i = 0; i < config.RegisteredScenes.Count; i++) { writer.WriteString(config.RegisteredScenes[i]); } writer.WriteInt32Packed(config.ReceiveTickrate); writer.WriteInt32Packed(config.MaxReceiveEventsPerTickRate); writer.WriteInt32Packed(config.SendTickrate); writer.WriteInt32Packed(config.EventTickrate); writer.WriteInt32Packed(config.ClientConnectionBufferTimeout); writer.WriteBool(config.ConnectionApproval); writer.WriteInt32Packed(config.SecondsHistory); writer.WriteBool(config.EnableEncryption); writer.WriteBool(config.SignKeyExchange); writer.WriteInt32Packed(config.LoadSceneTimeOut); writer.WriteBool(config.EnableTimeResync); writer.WriteBits((byte)config.RpcHashSize, 3); writer.WriteBool(ForceSamePrefabs); writer.WriteBool(UsePrefabSync); writer.WriteBool(EnableNetworkedVar); stream.PadStream(); return(Convert.ToBase64String(stream.ToArray())); } } }
/// <inheritdoc /> public void WriteDelta(Stream stream) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed((ushort)dirtyEvents.Count); for (int i = 0; i < dirtyEvents.Count; i++) { writer.WriteBits((byte)dirtyEvents[i].eventType, 3); switch (dirtyEvents[i].eventType) { case NetworkedDictionaryEvent <TKey, TValue> .NetworkedListEventType.Add: { writer.WriteObjectPacked(dirtyEvents[i].key); writer.WriteObjectPacked(dirtyEvents[i].value); } break; case NetworkedDictionaryEvent <TKey, TValue> .NetworkedListEventType.Remove: { writer.WriteObjectPacked(dirtyEvents[i].key); } break; case NetworkedDictionaryEvent <TKey, TValue> .NetworkedListEventType.RemovePair: { writer.WriteObjectPacked(dirtyEvents[i].key); writer.WriteObjectPacked(dirtyEvents[i].value); } break; case NetworkedDictionaryEvent <TKey, TValue> .NetworkedListEventType.Clear: { //write nothing } break; case NetworkedDictionaryEvent <TKey, TValue> .NetworkedListEventType.Value: { writer.WriteObjectPacked(dirtyEvents[i].key); writer.WriteObjectPacked(dirtyEvents[i].value); } break; default: break; } } } }
/// <summary> /// Hides a list of objects from a client /// </summary> /// <param name="networkedObjects">The objects to hide</param> /// <param name="clientId">The client to hide the objects from</param> public static void NetworkHide(List <NetworkedObject> networkedObjects, ulong clientId) { if (!NetworkingManager.Singleton.IsServer) { throw new NotServerException("Only server can change visibility"); } if (clientId == NetworkingManager.Singleton.ServerClientId) { throw new VisibilityChangeException("Cannot hide an object from the server"); } // Do the safety loop first to prevent putting the MLAPI in an invalid state. for (int i = 0; i < networkedObjects.Count; i++) { if (!networkedObjects[i].IsSpawned) { throw new SpawnStateException("Object is not spawned"); } if (!networkedObjects[i].observers.Contains(clientId)) { throw new VisibilityChangeException("NetworkedObject with NetworkId: " + networkedObjects[i].NetworkId + " is already hidden"); } } using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed((ushort)networkedObjects.Count); for (int i = 0; i < networkedObjects.Count; i++) { // Send destroy call networkedObjects[i].observers.Remove(clientId); writer.WriteUInt64Packed(networkedObjects[i].NetworkId); } } InternalMessageSender.Send(clientId, MLAPIConstants.MLAPI_DESTROY_OBJECTS, "MLAPI_INTERNAL", stream, SecuritySendFlags.None, null); } }
/// <summary> /// Shows a list of previously hidden objects to a client /// </summary> /// <param name="networkedObjects">The objects to show</param> /// <param name="clientId">The client to show the objects to</param> /// <param name="payload">An optional payload to send as part of the spawns</param> public static void NetworkShow(List <NetworkedObject> networkedObjects, ulong clientId, Stream payload = null) { if (!NetworkingManager.Singleton.IsServer) { throw new NotServerException("Only server can change visibility"); } // Do the safety loop first to prevent putting the MLAPI in an invalid state. for (int i = 0; i < networkedObjects.Count; i++) { if (!networkedObjects[i].IsSpawned) { throw new SpawnStateException("Object is not spawned"); } if (networkedObjects[i].observers.Contains(clientId)) { throw new VisibilityChangeException("NetworkedObject with NetworkId: " + networkedObjects[i].NetworkId + " is already visible"); } } using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed((ushort)networkedObjects.Count); } for (int i = 0; i < networkedObjects.Count; i++) { // Send spawn call networkedObjects[i].observers.Add(clientId); SpawnManager.WriteSpawnCallForObject(stream, clientId, networkedObjects[i], payload); } InternalMessageSender.Send(clientId, MLAPIConstants.MLAPI_ADD_OBJECTS, "MLAPI_INTERNAL", stream, SecuritySendFlags.None, null); } }
internal void NetworkedVarUpdate() { if (!networkedVarInit) { NetworkedVarInit(); } //TODO: Do this efficiently. if (!CouldHaveDirtyVars()) { return; } networkedVarIndexesToReset.Clear(); networkedVarIndexesToResetSet.Clear(); for (int i = 0; i < NetworkingManager.Singleton.ConnectedClientsList.Count; i++) { //This iterates over every "channel group". for (int j = 0; j < channelMappedVarIndexes.Count; j++) { using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt32Packed(NetworkId); writer.WriteUInt16Packed(NetworkedObject.GetOrderIndex(this)); uint clientId = NetworkingManager.Singleton.ConnectedClientsList[i].ClientId; bool writtenAny = false; for (int k = 0; k < networkedVarFields.Count; k++) { if (!channelMappedVarIndexes[j].Contains(k)) { //This var does not belong to the currently iterating channel group. writer.WriteBool(false); continue; } bool isDirty = networkedVarFields[k].IsDirty(); //cache this here. You never know what operations users will do in the dirty methods writer.WriteBool(isDirty); if (isDirty && (!IsServer || networkedVarFields[k].CanClientRead(clientId))) { writtenAny = true; networkedVarFields[k].WriteDelta(stream); if (!networkedVarIndexesToResetSet.Contains(k)) { networkedVarIndexesToResetSet.Add(k); networkedVarIndexesToReset.Add(k); } } } if (writtenAny) { if (IsServer) { InternalMessageHandler.Send(clientId, MLAPIConstants.MLAPI_NETWORKED_VAR_DELTA, channelsForVarGroups[j], stream, SecuritySendFlags.None); } else { InternalMessageHandler.Send(NetworkingManager.Singleton.ServerClientId, MLAPIConstants.MLAPI_NETWORKED_VAR_DELTA, channelsForVarGroups[j], stream, SecuritySendFlags.None); } } } } } } for (int i = 0; i < networkedVarIndexesToReset.Count; i++) { networkedVarFields[networkedVarIndexesToReset[i]].ResetDirty(); } }