protected void StreamReceived(NetworkingPlayer sender, BMSByte bytes) { if (TrackBandwidth) BandwidthIn += (ulong)bytes.Size; lock (tmp) { bytes.MoveStartIndex(1); readStream.Reset(); if (base.ProcessReceivedData(sender, bytes, bytes[0])) return; // TODO: Not needed after initialization readStream.SetProtocolType(Networking.ProtocolType.TCP); if (readStream.Consume(this, sender, bytes) == null) return; // Do not process player because it is processed through the listener if (readStream.identifierType == NetworkingStream.IdentifierType.Player) { if (!Connected) OnConnected(); return; } if (readStream.Ready) { // TODO: These need to be done better since there are many of them if (readStream.Bytes.Size < 22) { try { if (ObjectMapper.Compare<string>(readStream, "update")) UpdateNewPlayer(sender); if (ObjectMapper.Compare<string>(readStream, "disconnect")) { // TODO: If this eventually sends something to the player they will not exist Disconnect(sender); return; } } catch { throw new NetworkException(12, "Mal-formed defalut communication"); } } } if (ReadStream(sender, readStream) && IsServer) RelayStream(readStream); DataRead(sender, readStream); } }
public virtual void SceneReady(Scene scene, LoadSceneMode mode) { // The NetworkManager has not yet been initialized with a Networker. if (!initialized) { return; } // If we are loading a completely new scene then we will need // to clear out all the old objects that were stored as they // are no longer needed if (mode != LoadSceneMode.Additive) { pendingObjects.Clear(); pendingNetworkObjects.Clear(); loadedScenes.Clear(); } lock (NetworkObject.PendingCreatesLock) { loadingScenes.Remove(scene.buildIndex); } loadedScenes.Add(scene.buildIndex); if (networkSceneLoaded != null) { networkSceneLoaded(scene, mode); } BMSByte data = ObjectMapper.BMSByte(scene.buildIndex, (int)mode); Binary frame = new Binary(Networker.Time.Timestep, false, data, Networker is IServer ? Receivers.All : Receivers.Server, MessageGroupIds.VIEW_CHANGE, Networker is BaseTCP); // Send the binary frame to either the server or the clients SendFrame(Networker, frame); // Go through all of the current NetworkBehaviors in the order that Unity finds them in // and associate them with the id that the network will be giving them as a lookup int currentAttachCode = 1; var behaviors = FindObjectsOfType <NetworkBehavior>().Where(b => !b.Initialized) .OrderBy(b => b.GetType().ToString()) .OrderBy(b => b.name) .OrderBy(b => Vector3.Distance(Vector3.zero, b.transform.position)) .ToList(); if (behaviors.Count == 0) { if (Networker is IClient) { if (loadingScenes.Count > 0) { NetworkObject.Flush(Networker, loadingScenes, CreatePendingObjects); } else { NetworkObject.Flush(Networker, loadingScenes); if (pendingObjects.Count == 0) { Networker.objectCreated -= CreatePendingObjects; } } } return; } foreach (NetworkBehavior behavior in behaviors) { behavior.TempAttachCode = scene.buildIndex << 16; behavior.TempAttachCode += currentAttachCode++; behavior.TempAttachCode = -behavior.TempAttachCode; } if (Networker is IClient) { // This would occur if objects in the additive scene arrives at the same time as the // "single" scene and were flushed. if (mode == LoadSceneMode.Additive && pendingNetworkObjects.Count > 0) { NetworkObject foundNetworkObject; for (int i = 0; i < behaviors.Count; i++) { if (pendingNetworkObjects.TryGetValue(behaviors[i].TempAttachCode, out foundNetworkObject)) { behaviors[i].Initialize(foundNetworkObject); pendingNetworkObjects.Remove(behaviors[i].TempAttachCode); behaviors.RemoveAt(i--); } } } foreach (NetworkBehavior behavior in behaviors) { pendingObjects.Add(behavior.TempAttachCode, behavior); } NetworkObject.Flush(Networker, loadingScenes, CreatePendingObjects); if (pendingObjects.Count == 0 && loadingScenes.Count == 0) { Networker.objectCreated -= CreatePendingObjects; } else if (pendingObjects.Count != 0 && loadingScenes.Count == 0) { // Pending network behavior list is not empty when there are no more scenes to load. // Probably network behaviours that were placed in the scene have already been destroyed on the server and other clients! List <GameObject> objetsToDestroy = new List <GameObject>(pendingObjects.Count); foreach (var behavior in pendingObjects.Values) { var gameObject = ((NetworkBehavior)behavior).gameObject; if (!objetsToDestroy.Contains(gameObject)) { objetsToDestroy.Add(gameObject); } } pendingObjects.Clear(); foreach (var o in objetsToDestroy) { Destroy(o); } objetsToDestroy.Clear(); } } else { // Go through all of the pending NetworkBehavior objects and initialize them on the network foreach (INetworkBehavior behavior in behaviors) { behavior.Initialize(Networker); } } }
private void OwningNetWorker_rawDataRead(NetworkingPlayer sender, BMSByte data) { // In this test we are just writing a string across the network string message = System.Text.Encoding.UTF8.GetString(data.byteArr, data.StartIndex(), data.Size); Debug.Log("Hello " + message); }
/// <summary> /// Tells the client to change their scene to the given scene. This is often called /// after the server has changed to that scene to ensure that the server will always /// load up the scene before the client does /// </summary> /// <param name="netWorker">The current <see cref="NetWorker"/> that will be sending the message</param> /// <param name="targetPlayer">The particular player that will be receiving this message</param> /// <param name="sceneName">The name of the scene in which the client should load</param> public static void ChangeClientScene(NetWorker netWorker, NetworkingPlayer targetPlayer, string sceneName) { if (!netWorker.IsServer) throw new NetworkException("Only the server can call this method, the specified NetWorker is not a server"); BMSByte data = new BMSByte(); data.Clone(Encryptor.Encoding.GetBytes(sceneName)); data.InsertRange(0, new byte[1] { 2 }); netWorker.WriteRaw(targetPlayer, data); }
/// <summary> /// TODO /// </summary> /// <param name="id">Unique identifier to be used</param> /// <param name="netWorker">The NetWorker(Socket) to write with</param> /// <param name="data">Data to send over</param> /// <param name="reliableUDP">If this be a reliable UDP</param> public static void WriteCustom(string id, NetWorker netWorker, BMSByte data, bool reliableUDP = false, NetworkReceivers recievers = NetworkReceivers.All) { if (netWorker is CrossPlatformUDP) { netWorker.Write(id, new NetworkingStream().Prepare( netWorker, NetworkingStream.IdentifierType.Custom, null, data, recievers, reliableUDP, id ), reliableUDP); } else { netWorker.Write(new NetworkingStream().Prepare( netWorker, NetworkingStream.IdentifierType.Custom, null, data, recievers, reliableUDP, id )); } }
protected void RelayRawStream(NetworkingPlayer sender, BMSByte bytes) { if (Networking.ControlledRaw) return; WriteRaw(bytes, false); }
protected void OnRawDataRead(NetworkingPlayer sender, BMSByte data) { if (rawDataReadInvoker != null) { data.MoveStartIndex(sizeof(byte)); rawDataReadInvoker(sender, data); } }
/// <summary> /// Write a custom raw byte message with a 1 byte header across the network /// </summary> /// <param name="id"></param> /// <param name="netWorker"></param> /// <param name="data"></param> public static void WriteRaw(NetWorker netWorker, BMSByte data, string uniqueId, bool reliable) { if (data == null) { netWorker.ThrowException(new NetworkException(1000, "The data being written can not be null")); return; } if (data.Size == 0) { netWorker.ThrowException(new NetworkException(1001, "The data being sent can't be empty")); return; } netWorker.WriteRaw(data, uniqueId, true, reliable); }
/// <summary> /// Creates the frame data using the passed in payload /// </summary> private void CreateFrame(bool useMask, ulong timestep, byte[] payload, Receivers receivers, int groupId, byte routerId, bool isStream) { // If we are to use a mask then generate a random mask if (useMask) { mask = new byte[4]; new Random().NextBytes(mask); } StreamData = new BMSByte(); TimeStep = timestep; GroupId = groupId; RouterId = routerId; Receivers = receivers; UniqueId = UniqueMessageIdCounter++; // Generate the frame identity byte[] frame = new byte[10]; // The first byte of the data is always the control byte, which dictates the message type frame[0] = ControlByte; int length = payload.Length; if (isStream) { length += 21; // Group id (4), receivers (1), time step (8), unique id (8) } if (frame[0] == Binary.CONTROL_BYTE) { length += 1; } // Determine the length of the payload int dataStartIndex = 0; if (length <= 125) { frame[1] = (byte)length; dataStartIndex = 2; } else if (length >= 126 && length <= 65535) { dataStartIndex = 4; frame[1] = 126; } else { dataStartIndex = 10; frame[1] = 127; } // If the payload is greater than a byte (255) then set the order of the bytes for the length if (dataStartIndex > 2) { int i = 0, j = 2, largestBitIndex = (dataStartIndex - 3) * 8; // Little endian / Big endian reversal based on mask if (mask.Length == 0) { for (i = largestBitIndex; i >= 0; i -= 8) { frame[j++] = (byte)((payload.Length >> i) & 255); } } else { for (i = 0; i <= largestBitIndex; i += 8) { frame[j++] = (byte)((payload.Length >> i) & 255); } } } // Prepare the stream data with the size so that it doesn't have to keep resizing StreamData.SetSize(dataStartIndex + mask.Length + payload.Length); StreamData.Clear(); // Add the frame bytes StreamData.BlockCopy(frame, 0, dataStartIndex); // Add the mask bytes StreamData.BlockCopy(mask, 0, mask.Length); // Setup the int that tracks where the payload begins payloadStart = dataStartIndex + mask.Length; // If we are on a stream then use groupId if (isStream) { StreamData.BlockCopy(BitConverter.GetBytes(groupId), 0, sizeof(int)); payloadStart += sizeof(int); } // Copy the routerId if this is a binary frame if (frame[0] == Binary.CONTROL_BYTE) { StreamData.BlockCopy(new byte[1] { routerId }, 0, sizeof(byte)); payloadStart += 1; } // Add the initial payload bytes StreamData.BlockCopy(payload, 0, payload.Length); if (isStream) { StreamData.Append(new byte[] { (byte)Receivers }); } // Add the time step to the end of the frame StreamData.BlockCopy <ulong>(TimeStep, sizeof(ulong)); // Add the unique message id for this frame just before the timestep frame StreamData.BlockCopy <ulong>(UniqueId, sizeof(ulong)); if (mask.Length > 0) { for (int i = dataStartIndex + mask.Length, j = 0; i < StreamData.Size; i++, j++) { StreamData.byteArr[i] = (byte)(StreamData.byteArr[i] ^ mask[j % 4]); } } }
private void SetupClient(BMSByte packet, string incomingEndpoint, IPEndPoint groupEP) { // Check for a local listing request if (packet.Size.Between(2, 4) && packet[0] == BROADCAST_LISTING_REQUEST_1 && packet[1] == BROADCAST_LISTING_REQUEST_2 && packet[2] == BROADCAST_LISTING_REQUEST_3) { // Don't reply if the server is not currently accepting connections if (!AcceptingConnections) { return; } // This may be a local listing request so respond with the server flag byte Client.Send(new byte[] { SERVER_BROADCAST_CODE }, 1, groupEP); return; } if (Players.Count == MaxConnections) { // Tell the client why they are being disconnected var frame = Error.CreateErrorMessage(Time.Timestep, "Max Players Reached On Server", false, MessageGroupIds.MAX_CONNECTIONS, true); var playerToDisconnect = new UDPNetworkingPlayer(ServerPlayerCounter++, incomingEndpoint, false, groupEP, this); var composer = new UDPPacketComposer(this, playerToDisconnect, frame, false); // Send the close connection frame to the client composer = new UDPPacketComposer(this, playerToDisconnect, new ConnectionClose(Time.Timestep, false, Receivers.Target, MessageGroupIds.DISCONNECT, false), false); return; } else if (!AcceptingConnections) { // Tell the client why they are being disconnected var frame = Error.CreateErrorMessage(Time.Timestep, "The server is busy and not accepting connections", false, MessageGroupIds.NOT_ACCEPT_CONNECTIONS, true); var playerToDisconnect = new UDPNetworkingPlayer(ServerPlayerCounter++, incomingEndpoint, false, groupEP, this); var composer = new UDPPacketComposer(this, playerToDisconnect, frame, false); // Send the close connection frame to the client composer = new UDPPacketComposer(this, playerToDisconnect, new ConnectionClose(Time.Timestep, false, Receivers.Target, MessageGroupIds.DISCONNECT, false), false); return; } // Validate that the connection headers are properly formatted byte[] response = Websockets.ValidateConnectionHeader(packet.CompressBytes()); // The response will be null if the header sent is invalid, if so then disconnect client as they are sending invalid headers if (response == null) { return; } UDPNetworkingPlayer player = new UDPNetworkingPlayer(ServerPlayerCounter++, incomingEndpoint, false, groupEP, this); // If all is in order then send the validated response to the client Client.Send(response, response.Length, groupEP); OnPlayerConnected(player); udpPlayers.Add(incomingEndpoint, player); // The player has successfully connected player.Connected = true; }
/// <summary> /// Infinite loop listening for new data from all connected clients on a separate thread. /// This loop breaks when readThreadCancel is set to true /// </summary> private void ReadClients() { IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 0); string incomingEndpoint = string.Empty; BMSByte packet = null; // Intentional infinite loop while (IsBound) { // If the read has been flagged to be canceled then break from this loop if (readThreadCancel) { return; } try { // Read a packet from the network packet = Client.Receive(ref groupEP, ref incomingEndpoint); if (PacketLossSimulation > 0.0f && new Random().NextDouble() <= PacketLossSimulation) { // Skip this message continue; } BandwidthIn += (ulong)packet.Size; } catch { UDPNetworkingPlayer player; if (udpPlayers.TryGetValue(incomingEndpoint, out player)) { FinalizeRemovePlayer(player, true); } continue; } // Check to make sure a message was received if (packet == null || packet.Size <= 0) { continue; } if (!udpPlayers.ContainsKey(incomingEndpoint)) { SetupClient(packet, incomingEndpoint, groupEP); continue; } else { currentReadingPlayer = udpPlayers[incomingEndpoint]; if (!currentReadingPlayer.Accepted && !currentReadingPlayer.PendingAccepted) { // It is possible that the response validation was dropped so // check if the client is resending for a response byte[] response = Websockets.ValidateConnectionHeader(packet.CompressBytes()); // The client has sent the connection request again if (response != null) { Client.Send(response, response.Length, groupEP); continue; } else { currentReadingPlayer.PendingAccepted = true; ReadPacket(packet); } } else { currentReadingPlayer.Ping(); ReadPacket(packet); } } } }
/// <summary> /// Called when the network as interpreted that a cache message has been sent from the server /// </summary> /// <param name="player">The server</param> /// <param name="frame">The data that was received</param> private void BinaryMessageReceived(NetworkingPlayer player, Binary frame, NetWorker sender) { if (frame.GroupId != MessageGroupIds.CACHE) { return; } if (sender is IServer) { byte type = ObjectMapper.Instance.Map <byte>(frame.StreamData); int responseHookId = ObjectMapper.Instance.Map <int>(frame.StreamData); string key = ObjectMapper.Instance.Map <string>(frame.StreamData); object obj = Get(key); // TODO: Let the client know it is null if (obj == null) { return; } BMSByte data = ObjectMapper.BMSByte(type, responseHookId, obj); Binary sendFrame = new Binary(sender.Time.Timestep, sender is TCPClient, data, Receivers.Target, MessageGroupIds.CACHE, sender is BaseTCP); if (sender is BaseTCP) { ((TCPServer)sender).Send(player.TcpClientHandle, sendFrame); } else { ((UDPServer)sender).Send(player, sendFrame, true); } } else { byte type = ObjectMapper.Instance.Map <byte>(frame.StreamData); int responseHookId = ObjectMapper.Instance.Map <int>(frame.StreamData); object obj = null; if (typeMap[type] == typeof(string)) { obj = ObjectMapper.Instance.Map <string>(frame.StreamData); } /*else if (typeMap[type] == typeof(Vector2)) * obj = ObjectMapper.Map<Vector2>(stream); * else if (typeMap[type] == typeof(Vector3)) * obj = ObjectMapper.Map<Vector3>(stream); * else if (typeMap[type] == typeof(Vector4)) * obj = ObjectMapper.Map<Vector4>(stream); * else if (typeMap[type] == typeof(Color)) * obj = ObjectMapper.Map<Color>(stream); * else if (typeMap[type] == typeof(Quaternion)) * obj = ObjectMapper.Map<Quaternion>(stream);*/ else { obj = ObjectMapper.Instance.Map(typeMap[type], frame.StreamData); } if (responseHooks.ContainsKey(responseHookId)) { responseHooks[responseHookId](obj); responseHooks.Remove(responseHookId); } } }
protected override void ReadDirtyFields(BMSByte data, ulong timestep) { Buffer.BlockCopy(data.byteArr, data.StartIndex(), readDirtyFlags, 0, readDirtyFlags.Length); data.MoveStartIndex(readDirtyFlags.Length); }
protected override void ReadDirtyFields(BMSByte data, ulong timestep) { if (readDirtyFlags == null) { Initialize(); } Buffer.BlockCopy(data.byteArr, data.StartIndex(), readDirtyFlags, 0, readDirtyFlags.Length); data.MoveStartIndex(readDirtyFlags.Length); if ((0x1 & readDirtyFlags[0]) != 0) { if (RotationInterpolation.Enabled) { RotationInterpolation.target = UnityObjectMapper.Instance.Map <float>(data); RotationInterpolation.Timestep = timestep; } else { _Rotation = UnityObjectMapper.Instance.Map <float>(data); RunChange_Rotation(timestep); } } if ((0x2 & readDirtyFlags[0]) != 0) { if (FromInterpolation.Enabled) { FromInterpolation.target = UnityObjectMapper.Instance.Map <int>(data); FromInterpolation.Timestep = timestep; } else { _From = UnityObjectMapper.Instance.Map <int>(data); RunChange_From(timestep); } } if ((0x4 & readDirtyFlags[0]) != 0) { if (ToInterpolation.Enabled) { ToInterpolation.target = UnityObjectMapper.Instance.Map <int>(data); ToInterpolation.Timestep = timestep; } else { _To = UnityObjectMapper.Instance.Map <int>(data); RunChange_To(timestep); } } if ((0x8 & readDirtyFlags[0]) != 0) { if (ResponderInterpolation.Enabled) { ResponderInterpolation.target = UnityObjectMapper.Instance.Map <int>(data); ResponderInterpolation.Timestep = timestep; } else { _Responder = UnityObjectMapper.Instance.Map <int>(data); RunChange_Responder(timestep); } } if ((0x10 & readDirtyFlags[0]) != 0) { if (MovingInterpolation.Enabled) { MovingInterpolation.target = UnityObjectMapper.Instance.Map <bool>(data); MovingInterpolation.Timestep = timestep; } else { _Moving = UnityObjectMapper.Instance.Map <bool>(data); RunChange_Moving(timestep); } } }
/// <summary> /// This will set the message group for the specified socket connection /// </summary> /// <param name="socket">The NetWorker to assign the message group for</param> /// <param name="groupId">The unique identifier for the message group</param> public static void SetMyMessageGroup(NetWorker socket, ushort groupId) { socket.Me.SetMessageGroup(groupId); BMSByte data = new BMSByte(); data.Append(new byte[] { 6 }); ObjectMapper.MapBytes(data, groupId); socket.WriteRaw(data, "BMS_INTERNAL_Set_MessageGroup", true, true); }
/// <summary> /// Callback for user auth. Sends an authentication response to the server. /// </summary> private void AuthServer(BMSByte buffer) { Send( new Binary(Time.Timestep, false, buffer, Receivers.Server, MessageGroupIds.AUTHENTICATION_RESPONSE, false), true); }
/// <summary> /// Tells the client to change their scene to the given scene. This is often called /// after the server has changed to that scene to ensure that the server will always /// load up the scene before the client does /// </summary> /// <param name="port">The port of the <see cref="NetWorker"/> that is to send the message</param> /// <param name="sceneName">The name of the scene in which the client should load</param> public static void ChangeClientScene(ushort port, string sceneName) { if (!Sockets.ContainsKey(port)) throw new NetworkException("There isn't a server running using the specified port on this machine"); if (!Sockets[port].IsServer) throw new NetworkException("Only the server can call this method, the NetWorker on the specified port is not a server"); BMSByte data = new BMSByte(); data.Append(new byte[] { 2 }); ObjectMapper.MapBytes(data, sceneName); Sockets[port].WriteRaw(data, "BMS_INTERNAL_Change_Client_Scene", false, true); }
/// <summary> /// Infinite loop listening for new data from all connected clients on a separate thread. /// This loop breaks when readThreadCancel is set to true /// </summary> private void ReadClients() { CSteamID messageFrom = default(CSteamID); BMSByte packet = null; // Intentional infinite loop while (IsBound) { // If the read has been flagged to be canceled then break from this loop if (readThreadCancel) { return; } try { // Read a packet from the network uint msgSize = 0; if (SteamNetworking.IsP2PPacketAvailable(out msgSize)) { packet = Client.Receive(msgSize, out messageFrom); } else { Thread.Sleep(1); continue; } if (PacketLossSimulation > 0.0f && new Random().NextDouble() <= PacketLossSimulation) { // Skip this message continue; } BandwidthIn += (ulong)packet.Size; } catch (Exception e) { Logging.BMSLog.LogException(e); SteamNetworkingPlayer player; if (steamPlayers.TryGetValue(messageFrom, out player)) { FinalizeRemovePlayer(player, true); } continue; } // Check to make sure a message was received if (packet == null || packet.Size <= 0) { continue; } if (!steamPlayers.ContainsKey(messageFrom)) { SetupClient(packet, messageFrom); continue; } else { currentReadingPlayer = steamPlayers[messageFrom]; if (!currentReadingPlayer.Accepted && !currentReadingPlayer.PendingAccepted) { // It is possible that the response validation was dropped so // check if the client is resending for a response byte[] response = Websockets.ValidateConnectionHeader(packet.CompressBytes()); // The client has sent the connection request again if (response != null) { Client.Send(response, response.Length, messageFrom, EP2PSend.k_EP2PSendReliable); continue; } else { currentReadingPlayer.PendingAccepted = true; ReadPacket(packet); } } else { // Due to the Forge Networking protocol, the only time that packet 1 // will be 71 and the second packet be 69 is a forced disconnect reconnect if (packet[0] == 71 && packet[1] == 69) { Logging.BMSLog.LogFormat("Received packet[0]=71 & packet[1]=69"); steamPlayers.Remove(messageFrom); FinalizeRemovePlayer(currentReadingPlayer, true); continue; } currentReadingPlayer.Ping(); ReadPacket(packet); } } } }
/// <summary> /// This allows you to write custom data across the network and is useful for serializing entire classes if needed /// </summary> /// <param name="id">Unique identifier to be used</param> /// <param name="netWorker">The NetWorker(Socket) to write with</param> /// <param name="data">Data to send over</param> /// <param name="reliableUDP">If this be a reliable UDP</param> public static void WriteCustom(uint id, NetWorker netWorker, BMSByte data, bool reliableUDP = false, NetworkReceivers recievers = NetworkReceivers.All) { NetworkingStream stream = new NetworkingStream(netWorker is CrossPlatformUDP ? ProtocolType.UDP : ProtocolType.TCP).Prepare(netWorker, NetworkingStream.IdentifierType.Custom, null, data, recievers, netWorker is CrossPlatformUDP && reliableUDP, id); if (netWorker.IsServer) { switch (recievers) { case NetworkReceivers.Server: case NetworkReceivers.All: case NetworkReceivers.AllBuffered: case NetworkReceivers.AllProximity: BMSByte returnBytes = stream.Bytes; netWorker.ExecuteCustomRead(id, netWorker.Me, new NetworkingStream().Consume(netWorker, netWorker.Me, returnBytes)); break; } if (recievers == NetworkReceivers.Server || recievers == NetworkReceivers.ServerAndOwner) // If only sending to the server, then just execute it itself. return; } if (netWorker is CrossPlatformUDP) netWorker.Write("BMS_INTERNAL_Write_Custom_" + id.ToString(), stream, reliableUDP); else netWorker.Write(stream); }
/// <summary> /// Infinite loop listening for new data from all connected clients on a separate thread. /// This loop breaks when readThreadCancel is set to true /// </summary> private void ReadNetwork() { IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 0); string incomingEndpoint = string.Empty; try { BMSByte packet = null; // Intentional infinite loop while (IsBound) { // If the read has been flagged to be canceled then break from this loop if (readThreadCancel) { return; } try { // Read a packet from the network packet = Client.Receive(ref groupEP, ref incomingEndpoint); if (PacketLossSimulation > 0.0f && new Random().NextDouble() <= PacketLossSimulation) { // Skip this message continue; } BandwidthIn += (ulong)packet.Size; } catch (SocketException /*ex*/) { // This is a common exception when we exit the blocking call //Logging.BMSLog.LogException(ex); Disconnect(true); } // This message was not from the server if (groupEP.Address != Server.IPEndPointHandle.Address && groupEP.Port != Server.IPEndPointHandle.Port) { if (packet.Size == 1 && (packet[0] == SERVER_BROADCAST_CODE || packet[1] == CLIENT_BROADCAST_CODE)) { } else if (packet.Size.Between(2, 4) && packet[0] == BROADCAST_LISTING_REQUEST_1 && packet[1] == BROADCAST_LISTING_REQUEST_2 && packet[2] == BROADCAST_LISTING_REQUEST_3) { // This may be a local listing request so respond with the client flag byte Client.Send(new byte[] { CLIENT_BROADCAST_CODE }, 1, groupEP); } continue; } // Check to make sure a message was received if (packet == null || packet.Size <= 0) { continue; } // Check to see if the headers have been exchanged if (!headerExchanged) { if (Websockets.ValidateResponseHeader(headerHash, packet.CompressBytes())) { headerExchanged = true; // TODO: When getting the user id, it should also get the server time // by using the current time in the payload and getting it back along with server time // Ping the server to finalize the player's connection Send(Text.CreateFromString(Time.Timestep, InstanceGuid.ToString(), false, Receivers.Server, MessageGroupIds.NETWORK_ID_REQUEST, false), true); } else if (packet.Size != 1 || packet[0] != 0) { Disconnect(true); break; } else { continue; } } else { if (packet.Size < 17) { continue; } // Format the byte data into a UDPPacket struct UDPPacket formattedPacket = TranscodePacket(Server, packet); // Check to see if this is a confirmation packet, which is just // a packet to say that the reliable packet has been read if (formattedPacket.isConfirmation) { if (formattedPacket.groupId == MessageGroupIds.DISCONNECT) { CloseConnection(); return; } OnMessageConfirmed(server, formattedPacket); continue; } // Add the packet to the manager so that it can be tracked and executed on complete packetManager.AddPacket(formattedPacket, PacketSequenceComplete); } } } catch (Exception ex) { Logging.BMSLog.LogException(ex); Disconnect(true); } }
public virtual void WriteRaw(NetworkingPlayer player, BMSByte data, string reliableId = "") { }
private void SceneReady(Scene scene, LoadSceneMode mode) { // If we are loading a completely new scene then we will need // to clear out all the old objects that were stored as they // are no longer needed if (mode != LoadSceneMode.Additive) { pendingObjects.Clear(); pendingNetworkObjects.Clear(); loadedScenes.Clear(); } loadedScenes.Add(scene.buildIndex); if (networkSceneLoaded != null) { networkSceneLoaded(scene, mode); } BMSByte data = ObjectMapper.BMSByte(scene.buildIndex, (int)mode); Binary frame = new Binary(Networker.Time.Timestep, false, data, Networker is IServer ? Receivers.All : Receivers.Server, MessageGroupIds.VIEW_CHANGE, Networker is BaseTCP); // Send the binary frame to either the server or the clients SendFrame(Networker, frame); // Go through all of the current NetworkBehaviors in the order that Unity finds them in // and associate them with the id that the network will be giving them as a lookup int currentAttachCode = 1; var behaviors = FindObjectsOfType <NetworkBehavior>().Where(b => !b.Initialized) .OrderBy(b => b.GetType().ToString()) .OrderBy(b => b.name) .OrderBy(b => Vector3.Distance(Vector3.zero, b.transform.position)) .ToList(); if (behaviors.Count == 0) { if (Networker is IClient) { NetworkObject.Flush(Networker); } return; } foreach (NetworkBehavior behavior in behaviors) { behavior.TempAttachCode = scene.buildIndex << 16; behavior.TempAttachCode += currentAttachCode++; behavior.TempAttachCode = -behavior.TempAttachCode; } if (Networker is IClient) { NetworkObject.Flush(Networker); NetworkObject foundNetworkObject; for (int i = 0; i < behaviors.Count; i++) { if (pendingNetworkObjects.TryGetValue(behaviors[i].TempAttachCode, out foundNetworkObject)) { behaviors[i].Initialize(foundNetworkObject); pendingNetworkObjects.Remove(behaviors[i].TempAttachCode); behaviors.RemoveAt(i--); } } if (behaviors.Count == 0) { return; } } if (Networker is IServer) { // Go through all of the pending NetworkBehavior objects and initialize them on the network foreach (INetworkBehavior behavior in behaviors) { behavior.Initialize(Networker); } return; } foreach (NetworkBehavior behavior in behaviors) { pendingObjects.Add(behavior.TempAttachCode, behavior); } if (pendingNetworkObjects.Count == 0) { Networker.objectCreated -= CreatePendingObjects; } }
/// <summary> /// Constructor for the NetworkingStream with a passed in stream /// </summary> /// <param name="stream">The stream passed in to be used</param> public NetworkingStreamRPC(NetworkingStream stream, bool skipCall = false) { // TODO: Check for null NetworkedBehavior or if it is the base class if (!skipCall && ReferenceEquals(stream.NetworkedBehavior, null)) return; #if NETFX_CORE IEnumerable<PropertyInfo> properties = stream.GetType().GetRuntimeProperties(); #else PropertyInfo[] properties = stream.GetType().GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); #endif foreach (PropertyInfo property in properties) { if (property.CanRead && property.CanWrite) property.SetValue(this, property.GetValue(stream, null), null); } if (!skipCall) NetworkedBehavior.InvokeRPC(this); else { Bytes = new BMSByte().Clone(stream.Bytes); } }
/// <summary> /// Sends binary message to the specific tcp client(s) /// </summary> /// <param name="client">The client to receive the message</param> /// <param name="receivers">Receiver's type</param> /// <param name="messageGroupId">The Binary.GroupId of the massage, use MessageGroupIds.START_OF_GENERIC_IDS + desired_id</param> /// <param name="objectsToSend">Array of vars to be sent, read them with Binary.StreamData.GetBasicType<typeOfObject>()</param> /// <summary> ///发送二进制消息到特定的tcp客户端 /// </ summary> /// <param name =“client”>接收消息的客户端</ param> /// <param name =“receivers”>接收者类型</ param> /// <param name =“messageGroupId”>按摩的Binary.GroupId,使用MessageGroupIds.START_OF_GENERIC_IDS + desired_id </ param> /// <param name =“objectsToSend”>要发送的变量数组,使用Binary.StreamData.GetBasicType <typeOfObject>()</ param> public bool Send(TcpClient client, Receivers receivers = Receivers.Target, int messageGroupId = MessageGroupIds.START_OF_GENERIC_IDS, params object[] objectsToSend) { BMSByte data = ObjectMapper.BMSByte(objectsToSend); Binary sendFrame = new Binary(Time.Timestep, false, data, Receivers.Target, messageGroupId, false);
/// <summary> /// Allows the server to send a raw message to a particular player /// </summary> /// <param name="netWorker"></param> /// <param name="targetPlayer"></param> /// <param name="data"></param> public static void WriteRaw(NetWorker netWorker, NetworkingPlayer targetPlayer, BMSByte data) { data.InsertRange(0, new byte[1] { 1 }); netWorker.WriteRaw(targetPlayer, data); }
protected override BMSByte WritePayload(BMSByte data) { UnityObjectMapper.Instance.MapBytes(data, _TowerEntityNetID); return(data); }
/// <summary> /// Disconnect from the server /// </summary> public override void Disconnect() { BMSByte tmp = new BMSByte(); ObjectMapper.MapBytes(tmp, "disconnect"); lock (writeMutex) { writeStream.SetProtocolType(Networking.ProtocolType.TCP); writeStream.Prepare(this, NetworkingStream.IdentifierType.Disconnect, null, tmp, NetworkReceivers.Server); Write(writeStream); } if (readWorker != null) #if UNITY_IOS readWorker.Interrupt(); #else readWorker.Abort(); #endif if (netStream != null) netStream.Close(); if (client != null) client.Close(); OnDisconnected(); }
public override void Initialize(NetworkObject obj) { // We have already initialized this object if (networkObject != null && networkObject.AttachedBehavior != null) { return; } networkObject = (PlayerNetworkObject)obj; networkObject.AttachedBehavior = this; base.SetupHelperRpcs(networkObject); networkObject.RegisterRpc("SetupPlayer", SetupPlayer, typeof(ulong), typeof(string)); networkObject.onDestroy += DestroyGameObject; if (!obj.IsOwner) { if (!skipAttachIds.ContainsKey(obj.NetworkId)) { uint newId = obj.NetworkId + 1; ProcessOthers(gameObject.transform, ref newId); } else { skipAttachIds.Remove(obj.NetworkId); } } if (obj.Metadata != null) { byte transformFlags = obj.Metadata[0]; if (transformFlags != 0) { BMSByte metadataTransform = new BMSByte(); metadataTransform.Clone(obj.Metadata); metadataTransform.MoveStartIndex(1); bool changePos = (transformFlags & 0x01) != 0; bool changeRotation = (transformFlags & 0x02) != 0; if (changePos || changeRotation) { MainThreadManager.Run(() => { if (changePos) { transform.position = ObjectMapper.Instance.Map <Vector3>(metadataTransform); } if (changeRotation) { transform.rotation = ObjectMapper.Instance.Map <Quaternion>(metadataTransform); } }); } } } MainThreadManager.Run(() => { NetworkStart(); networkObject.Networker.FlushCreateActions(networkObject); }); }
protected void AuthoritativeInitialize(BMSByte data) { newData.Reset(); newData.Bytes.Clone(data); newData.ManualReady(); try { Deserialize(newData); } catch (Exception ex) { if (ex is IndexOutOfRangeException) Debug.LogError("The object " + gameObject.name + "'s serialization patterns do not match"); else throw ex; } DataInitialized = true; }
public Pong(ulong timestep, bool useMask, BMSByte payload, Receivers receivers, int groupId, bool isStream) : base(timestep, useMask, payload, receivers, groupId, isStream) { }
void HandleData (MessageType messageType, NetworkingStream stream) { LSUtility.bufferBytes.FastClear (); for (int i = 0; i < stream.Bytes.Size - 1; i++) { LSUtility.bufferBytes.Add (stream.Bytes [stream.Bytes.StartIndex (i)]); } byte[] data = LSUtility.bufferBytes.ToArray (); switch (messageType) { } BMSByte bufferBites = new BMSByte ();
protected override BMSByte WritePayload(BMSByte data) { UnityObjectMapper.Instance.MapBytes(data, _weaponIndex); return(data); }
/// <summary> /// Tells the client to change their scene to the given scene. This is often called /// after the server has changed to that scene to ensure that the server will always /// load up the scene before the client does /// </summary> /// <param name="netWorker">The current <see cref="NetWorker"/> that will be sending the message</param> /// <param name="targetPlayer">The particular player that will be receiving this message</param> /// <param name="sceneName">The name of the scene in which the client should load</param> public static void ChangeClientScene(NetWorker netWorker, NetworkingPlayer targetPlayer, string sceneName) { if (!netWorker.IsServer) throw new NetworkException("Only the server can call this method, the specified NetWorker is not a server"); BMSByte data = new BMSByte(); data.Append(new byte[] { 2 }); ObjectMapper.MapBytes(data, sceneName); netWorker.WriteRaw(targetPlayer, data, "BMS_INTERNAL_Change_Client_Scene", true); }
/// <summary> /// Get a mapped basic type of object from the BMSByte /// </summary> /// <param name="type">Type of object to be mapped</param> /// <param name="stream">BMSByte to be used</param> /// <returns>Returns a mapped object of the given type</returns> public object MapBasicType(Type type, BMSByte stream) { if (type == typeof(sbyte)) { return(unchecked ((sbyte)stream.GetBasicType <byte>())); } else if (type == typeof(byte)) { return(stream.GetBasicType <byte>()); } else if (type == typeof(char)) { return(unchecked ((char)stream.GetBasicType <byte>())); } else if (type == typeof(short)) { return(stream.GetBasicType <short>()); } else if (type == typeof(ushort)) { return(stream.GetBasicType <ushort>()); } else if (type == typeof(bool)) { return(stream.GetBasicType <bool>()); } else if (type == typeof(int)) { return(stream.GetBasicType <int>()); } else if (type == typeof(uint)) { return(stream.GetBasicType <uint>()); } else if (type == typeof(float)) { return(stream.GetBasicType <float>()); } else if (type == typeof(long)) { return(stream.GetBasicType <long>()); } else if (type == typeof(ulong)) { return(stream.GetBasicType <ulong>()); } else if (type == typeof(double)) { return(stream.GetBasicType <double>()); } else if (type == typeof(string)) { return(stream.GetBasicType <string>()); } else if (type == typeof(Vector)) { return(stream.GetBasicType <Vector>()); } else { // TODO: Make this an object mapper exception throw new BaseNetworkException("The type " + type.ToString() + " is not allowed to be sent over the Network (yet)"); } }
/// <summary> /// Tells the client to change their scene to the given scene. This is often called /// after the server has changed to that scene to ensure that the server will always /// load up the scene before the client does /// </summary> /// <param name="port">The port of the <see cref="NetWorker"/> that is to send the message</param> /// <param name="targetPlayer">The particular player that will be receiving this message</param> /// <param name="sceneName">The name of the scene in which the client should load</param> public static void ChangeClientScene(ushort port, NetworkingPlayer targetPlayer, string sceneName) { if (!Sockets.ContainsKey(port)) throw new NetworkException("There isn't a server running using the specified port on this machine"); if (!Sockets[port].IsServer) throw new NetworkException("Writing to particular players can only be done by the server, the NetWorker on the specified port is not a server"); BMSByte data = new BMSByte(); data.Append(new byte[] { 2 }); ObjectMapper.MapBytes(data, sceneName); Sockets[port].WriteRaw(targetPlayer, data, "BMS_INTERNAL_Change_Client_Scene", true); }
/// <summary> /// Map a generic array from the BMSBytes /// </summary> /// <param name="type">The type of the array</param> /// <param name="bytes">The bytes to read from</param> /// <returns>The array that was found</returns> public object MapArray(Type type, BMSByte bytes) { int rank = type.GetArrayRank(); Type targetType = type.GetElementType(); if (targetType != typeof(byte)) { throw new Exception("Currently only byte arrays can be sent as arrays"); } if (rank > 4) { throw new Exception("Currently the system only supports up to 4 dimensions in an array"); } int i, j, k, l; // Read each dimension length first int[] lengths = new int[rank]; for (i = 0; i < rank; i++) { lengths[i] = bytes.GetBasicType <int>(); } switch (rank) { case 1: byte[] arr1 = new byte[lengths[0]]; for (i = 0; i < lengths[0]; i++) { arr1[i] = bytes.GetBasicType <byte>(); } return(arr1); case 2: byte[,] arr2 = new byte[lengths[0], lengths[1]]; for (i = 0; i < lengths[0]; i++) { for (j = 0; j < lengths[1]; j++) { arr2[i, j] = bytes.GetBasicType <byte>(); } } return(arr2); case 3: byte[,,] arr3 = new byte[lengths[0], lengths[1], lengths[2]]; for (i = 0; i < lengths[0]; i++) { for (j = 0; j < lengths[1]; j++) { for (k = 0; k < lengths[2]; k++) { arr3[i, j, k] = bytes.GetBasicType <byte>(); } } } return(arr3); case 4: byte[,,,] arr4 = new byte[lengths[0], lengths[1], lengths[2], lengths[3]]; for (i = 0; i < lengths[0]; i++) { for (j = 0; j < lengths[1]; j++) { for (k = 0; k < lengths[2]; k++) { for (l = 0; l < lengths[3]; l++) { arr4[i, j, k, l] = bytes.GetBasicType <byte>(); } } } } return(arr4); } return(null); }
/// <summary> /// Allows the server to send a raw message to a particular player /// </summary> /// <param name="netWorker"></param> /// <param name="targetPlayer"></param> /// <param name="data"></param> public static void WriteRaw(NetWorker netWorker, NetworkingPlayer targetPlayer, BMSByte data, string uniqueId, bool reliable = false) { data.InsertRange(0, new byte[1] { 1 }); netWorker.WriteRaw(targetPlayer, data, uniqueId, reliable); }
/// <summary> /// Get a BMSByte out of a BMSByte /// </summary> /// <param name="type">Type of object to be mapped</param> /// <param name="stream">BMSByte to be used</param> /// <returns>A BMSByte that was read from the BMSByte</returns> public object MapBMSByte(BMSByte stream) { size = Map <int>(stream); return(new BMSByte().Clone(Map <byte[]>(stream))); }
public static void DynamicCommand(NetWorker socket, string command, bool relayOnServer = true, bool reliable = true) { BMSByte data = new BMSByte(); data.Append(new byte[] { 7 }); ObjectMapper.MapBytes(data, command); socket.WriteRaw(data, "BMS_INTERNAL_Command_" + command, relayOnServer, reliable); }
/// <summary> /// Gets the bytes for the Instance of an Object and appends them to a <c>BMSByte</c>. /// </summary> /// <param name="o">The Instance of the Object.</param> /// <param name="type">The Type of the Object.</param> /// <param name="bytes"><c>BMSByte</c> to which the bytes should be added.</param> protected virtual void GetBytes(object o, Type type, ref BMSByte bytes) { if (type == typeof(string)) { var strBytes = Encoding.UTF8.GetBytes(o == null ? string.Empty : (string)o); // TODO: Need to make custom string serialization to binary bytes.Append(BitConverter.GetBytes(strBytes.Length)); if (strBytes.Length > 0) { bytes.Append(strBytes); } } else if (type == typeof(Vector)) { Vector vec = (Vector)o; bytes.Append(BitConverter.GetBytes(vec.x)); bytes.Append(BitConverter.GetBytes(vec.y)); bytes.Append(BitConverter.GetBytes(vec.z)); } else if (type == null) //TODO: Check if this causes other issues { bytes.Append(new byte[1] { 0 }); } else if (type == typeof(sbyte)) { bytes.BlockCopy <sbyte>(o, 1); } else if (type == typeof(byte)) { bytes.BlockCopy <byte>(o, 1); } else if (type == typeof(char)) { bytes.BlockCopy <char>(o, 1); } else if (type == typeof(bool)) { bytes.Append(BitConverter.GetBytes((bool)o)); } else if (type == typeof(short)) { bytes.Append(BitConverter.GetBytes((short)o)); } else if (type == typeof(ushort)) { bytes.Append(BitConverter.GetBytes((ushort)o)); } else if (type == typeof(int)) { bytes.Append(BitConverter.GetBytes((int)o)); } else if (type == typeof(uint)) { bytes.Append(BitConverter.GetBytes((uint)o)); } else if (type == typeof(long)) { bytes.Append(BitConverter.GetBytes((long)o)); } else if (type == typeof(ulong)) { bytes.Append(BitConverter.GetBytes((ulong)o)); } else if (type == typeof(float)) { bytes.Append(BitConverter.GetBytes((float)o)); } else if (type == typeof(double)) { bytes.Append(BitConverter.GetBytes((double)o)); } else if (type.IsArray) { int rank = type.GetArrayRank(); Type targetType = type.GetElementType(); if (targetType != typeof(byte)) { throw new Exception("Currently only byte arrays can be sent as arrays"); } if (rank > 4) { throw new Exception("Currently the system only supports up to 4 dimensions in an array"); } int i, j, k, l; // Write each dimension length first int[] lengths = new int[rank]; for (i = 0; i < rank; i++) { lengths[i] = ((Array)o).GetLength(i); bytes.Append(BitConverter.GetBytes(lengths[i])); } switch (rank) { case 1: for (i = 0; i < lengths[0]; i++) { GetBytes(((Array)o).GetValue(i), targetType, ref bytes); } break; case 2: for (i = 0; i < lengths[0]; i++) { for (j = 0; j < lengths[1]; j++) { GetBytes(((Array)o).GetValue(i, j), targetType, ref bytes); } } break; case 3: for (i = 0; i < lengths[0]; i++) { for (j = 0; j < lengths[1]; j++) { for (k = 0; k < lengths[2]; k++) { GetBytes(((Array)o).GetValue(i, j, k), targetType, ref bytes); } } } break; case 4: for (i = 0; i < lengths[0]; i++) { for (j = 0; j < lengths[1]; j++) { for (k = 0; k < lengths[2]; k++) { for (l = 0; l < lengths[3]; l++) { GetBytes(((Array)o).GetValue(i, j, k, l), targetType, ref bytes); } } } } break; } } else if (type == typeof(BMSByte)) { bytes.Append(BitConverter.GetBytes(((BMSByte)o).Size)); bytes.BlockCopy(((BMSByte)o).byteArr, ((BMSByte)o).StartIndex(), ((BMSByte)o).Size); } else if (type.IsEnum) { GetBytes(o, Enum.GetUnderlyingType(type), ref bytes); } else { // TODO: Make this a more appropriate exception throw new BaseNetworkException("The type " + type.ToString() + " is not allowed to be sent over the Network (yet)"); } }
public StreamRead Prepare(int c, BMSByte b) { clientIndex = c; bytes.Clone(b); return this; }
protected override void ReadDirtyFields(BMSByte data, ulong timestep) { if (readDirtyFlags == null) { Initialize(); } Buffer.BlockCopy(data.byteArr, data.StartIndex(), readDirtyFlags, 0, readDirtyFlags.Length); data.MoveStartIndex(readDirtyFlags.Length); if ((0x1 & readDirtyFlags[0]) != 0) { if (fieldByteInterpolation.Enabled) { fieldByteInterpolation.target = UnityObjectMapper.Instance.Map <byte>(data); fieldByteInterpolation.Timestep = timestep; } else { _fieldByte = UnityObjectMapper.Instance.Map <byte>(data); RunChange_fieldByte(timestep); } } if ((0x2 & readDirtyFlags[0]) != 0) { if (fieldCharInterpolation.Enabled) { fieldCharInterpolation.target = UnityObjectMapper.Instance.Map <char>(data); fieldCharInterpolation.Timestep = timestep; } else { _fieldChar = UnityObjectMapper.Instance.Map <char>(data); RunChange_fieldChar(timestep); } } if ((0x4 & readDirtyFlags[0]) != 0) { if (fieldShortInterpolation.Enabled) { fieldShortInterpolation.target = UnityObjectMapper.Instance.Map <short>(data); fieldShortInterpolation.Timestep = timestep; } else { _fieldShort = UnityObjectMapper.Instance.Map <short>(data); RunChange_fieldShort(timestep); } } if ((0x8 & readDirtyFlags[0]) != 0) { if (fieldUShortInterpolation.Enabled) { fieldUShortInterpolation.target = UnityObjectMapper.Instance.Map <ushort>(data); fieldUShortInterpolation.Timestep = timestep; } else { _fieldUShort = UnityObjectMapper.Instance.Map <ushort>(data); RunChange_fieldUShort(timestep); } } if ((0x10 & readDirtyFlags[0]) != 0) { if (fieldBoolInterpolation.Enabled) { fieldBoolInterpolation.target = UnityObjectMapper.Instance.Map <bool>(data); fieldBoolInterpolation.Timestep = timestep; } else { _fieldBool = UnityObjectMapper.Instance.Map <bool>(data); RunChange_fieldBool(timestep); } } if ((0x20 & readDirtyFlags[0]) != 0) { if (fieldIntInterpolation.Enabled) { fieldIntInterpolation.target = UnityObjectMapper.Instance.Map <int>(data); fieldIntInterpolation.Timestep = timestep; } else { _fieldInt = UnityObjectMapper.Instance.Map <int>(data); RunChange_fieldInt(timestep); } } if ((0x40 & readDirtyFlags[0]) != 0) { if (fieldUIntInterpolation.Enabled) { fieldUIntInterpolation.target = UnityObjectMapper.Instance.Map <uint>(data); fieldUIntInterpolation.Timestep = timestep; } else { _fieldUInt = UnityObjectMapper.Instance.Map <uint>(data); RunChange_fieldUInt(timestep); } } if ((0x80 & readDirtyFlags[0]) != 0) { if (fieldFloatInterpolation.Enabled) { fieldFloatInterpolation.target = UnityObjectMapper.Instance.Map <float>(data); fieldFloatInterpolation.Timestep = timestep; } else { _fieldFloat = UnityObjectMapper.Instance.Map <float>(data); RunChange_fieldFloat(timestep); } } if ((0x1 & readDirtyFlags[1]) != 0) { if (fieldFloatInterpolateInterpolation.Enabled) { fieldFloatInterpolateInterpolation.target = UnityObjectMapper.Instance.Map <float>(data); fieldFloatInterpolateInterpolation.Timestep = timestep; } else { _fieldFloatInterpolate = UnityObjectMapper.Instance.Map <float>(data); RunChange_fieldFloatInterpolate(timestep); } } if ((0x2 & readDirtyFlags[1]) != 0) { if (fieldLongInterpolation.Enabled) { fieldLongInterpolation.target = UnityObjectMapper.Instance.Map <long>(data); fieldLongInterpolation.Timestep = timestep; } else { _fieldLong = UnityObjectMapper.Instance.Map <long>(data); RunChange_fieldLong(timestep); } } if ((0x4 & readDirtyFlags[1]) != 0) { if (fieldULongInterpolation.Enabled) { fieldULongInterpolation.target = UnityObjectMapper.Instance.Map <ulong>(data); fieldULongInterpolation.Timestep = timestep; } else { _fieldULong = UnityObjectMapper.Instance.Map <ulong>(data); RunChange_fieldULong(timestep); } } if ((0x8 & readDirtyFlags[1]) != 0) { if (fieldDoubleInterpolation.Enabled) { fieldDoubleInterpolation.target = UnityObjectMapper.Instance.Map <double>(data); fieldDoubleInterpolation.Timestep = timestep; } else { _fieldDouble = UnityObjectMapper.Instance.Map <double>(data); RunChange_fieldDouble(timestep); } } }
public virtual void WriteRaw(BMSByte data, bool relayToServer = true, string reliableId = "") { }
protected override void ReadDirtyFields(BMSByte data, ulong timestep) { if (readDirtyFlags == null) { Initialize(); } Buffer.BlockCopy(data.byteArr, data.StartIndex(), readDirtyFlags, 0, readDirtyFlags.Length); data.MoveStartIndex(readDirtyFlags.Length); if ((0x1 & readDirtyFlags[0]) != 0) { if (positionInterpolation.Enabled) { positionInterpolation.target = UnityObjectMapper.Instance.Map <Vector3>(data); positionInterpolation.Timestep = timestep; } else { _position = UnityObjectMapper.Instance.Map <Vector3>(data); RunChange_position(timestep); } } if ((0x2 & readDirtyFlags[0]) != 0) { if (rotationInterpolation.Enabled) { rotationInterpolation.target = UnityObjectMapper.Instance.Map <Quaternion>(data); rotationInterpolation.Timestep = timestep; } else { _rotation = UnityObjectMapper.Instance.Map <Quaternion>(data); RunChange_rotation(timestep); } } if ((0x4 & readDirtyFlags[0]) != 0) { if (xInterpolation.Enabled) { xInterpolation.target = UnityObjectMapper.Instance.Map <float>(data); xInterpolation.Timestep = timestep; } else { _x = UnityObjectMapper.Instance.Map <float>(data); RunChange_x(timestep); } } if ((0x8 & readDirtyFlags[0]) != 0) { if (yInterpolation.Enabled) { yInterpolation.target = UnityObjectMapper.Instance.Map <float>(data); yInterpolation.Timestep = timestep; } else { _y = UnityObjectMapper.Instance.Map <float>(data); RunChange_y(timestep); } } if ((0x10 & readDirtyFlags[0]) != 0) { if (ramInterpolation.Enabled) { ramInterpolation.target = UnityObjectMapper.Instance.Map <float>(data); ramInterpolation.Timestep = timestep; } else { _ram = UnityObjectMapper.Instance.Map <float>(data); RunChange_ram(timestep); } } }
public async void ConnectAndRead(string hostAddress, ushort port, NetworkingStream stream) { try { serverHost = new HostName(hostAddress); // Try to connect asynchronously await socket.ConnectAsync(serverHost, port.ToString()); Connected = true; OnConnected(); SendAsync(stream); byte[] bytes = null; Task tReadResponse = Task.Run(async () => { DataReader reader = new DataReader(socket.InputStream); uint messageSize = await reader.LoadAsync(sizeof(uint)); if (messageSize != sizeof(uint)) { Disconnect(); // socket was closed return; } bytes = new byte[messageSize]; reader.ReadBytes(bytes); messageSize = BitConverter.ToUInt32(bytes, 0); await reader.LoadAsync(messageSize); bytes = new byte[messageSize]; // TODO: This may read the first 4 bytes again for the size, make sure it doesn't reader.ReadBytes(bytes); }); tReadResponse.Wait(); Disconnect(); BMSByte tmp = new BMSByte(); tmp.Clone(bytes); //return new NetworkingStream(Networking.ProtocolType.TCP).Consume(this, null, tmp); } catch (Exception e) { ErrorDisconnect(e.Message); } }
protected override void ReadDirtyFields(BMSByte data, ulong timestep) { if (readDirtyFlags == null) { Initialize(); } Buffer.BlockCopy(data.byteArr, data.StartIndex(), readDirtyFlags, 0, readDirtyFlags.Length); data.MoveStartIndex(readDirtyFlags.Length); if ((0x1 & readDirtyFlags[0]) != 0) { if (positionInterpolation.Enabled) { positionInterpolation.target = UnityObjectMapper.Instance.Map <Vector2>(data); positionInterpolation.Timestep = timestep; } else { _position = UnityObjectMapper.Instance.Map <Vector2>(data); RunChange_position(timestep); } } if ((0x2 & readDirtyFlags[0]) != 0) { if (rotationInterpolation.Enabled) { rotationInterpolation.target = UnityObjectMapper.Instance.Map <Quaternion>(data); rotationInterpolation.Timestep = timestep; } else { _rotation = UnityObjectMapper.Instance.Map <Quaternion>(data); RunChange_rotation(timestep); } } if ((0x4 & readDirtyFlags[0]) != 0) { if (speedInterpolation.Enabled) { speedInterpolation.target = UnityObjectMapper.Instance.Map <float>(data); speedInterpolation.Timestep = timestep; } else { _speed = UnityObjectMapper.Instance.Map <float>(data); RunChange_speed(timestep); } } if ((0x8 & readDirtyFlags[0]) != 0) { if (damageInterpolation.Enabled) { damageInterpolation.target = UnityObjectMapper.Instance.Map <int>(data); damageInterpolation.Timestep = timestep; } else { _damage = UnityObjectMapper.Instance.Map <int>(data); RunChange_damage(timestep); } } if ((0x10 & readDirtyFlags[0]) != 0) { if (ownerNumInterpolation.Enabled) { ownerNumInterpolation.target = UnityObjectMapper.Instance.Map <int>(data); ownerNumInterpolation.Timestep = timestep; } else { _ownerNum = UnityObjectMapper.Instance.Map <int>(data); RunChange_ownerNum(timestep); } } }
/// <summary> /// TODO /// </summary> /// <param name="id">Unique identifier to be used</param> /// <param name="port">Port to be written to</param> /// <param name="data">Data to send over</param> public static void WriteCustom(string id, ushort port, BMSByte data, NetworkReceivers recievers = NetworkReceivers.All) { WriteCustom(id, Sockets[port], data, false, recievers); }
protected override BMSByte WritePayload(BMSByte data) { UnityObjectMapper.Instance.MapBytes(data, _position); return(data); }
/// <summary> /// Write a custom raw byte message with a 1 byte header across the network /// </summary> /// <param name="id"></param> /// <param name="netWorker"></param> /// <param name="data"></param> public static void WriteRaw(NetWorker netWorker, BMSByte data) { if (data == null) { netWorker.ThrowException(new NetworkException(1000, "The data being written can not be null")); return; } if (data.Size == 0) { netWorker.ThrowException(new NetworkException(1001, "The data being sent can't be empty")); return; } data.InsertRange(0, rawTypeIndicator); netWorker.WriteRaw(data); }
protected override void ReadDirtyFields(BMSByte data, ulong timestep) { if (readDirtyFlags == null) { Initialize(); } Buffer.BlockCopy(data.byteArr, data.StartIndex(), readDirtyFlags, 0, readDirtyFlags.Length); data.MoveStartIndex(readDirtyFlags.Length); if ((0x1 & readDirtyFlags[0]) != 0) { if (team0ScoreInterpolation.Enabled) { team0ScoreInterpolation.target = UnityObjectMapper.Instance.Map <int>(data); team0ScoreInterpolation.Timestep = timestep; } else { _team0Score = UnityObjectMapper.Instance.Map <int>(data); RunChange_team0Score(timestep); } } if ((0x2 & readDirtyFlags[0]) != 0) { if (team1ScoreInterpolation.Enabled) { team1ScoreInterpolation.target = UnityObjectMapper.Instance.Map <int>(data); team1ScoreInterpolation.Timestep = timestep; } else { _team1Score = UnityObjectMapper.Instance.Map <int>(data); RunChange_team1Score(timestep); } } if ((0x4 & readDirtyFlags[0]) != 0) { if (timerInterpolation.Enabled) { timerInterpolation.target = UnityObjectMapper.Instance.Map <float>(data); timerInterpolation.Timestep = timestep; } else { _timer = UnityObjectMapper.Instance.Map <float>(data); RunChange_timer(timestep); } } if ((0x8 & readDirtyFlags[0]) != 0) { if (originalTimerInterpolation.Enabled) { originalTimerInterpolation.target = UnityObjectMapper.Instance.Map <float>(data); originalTimerInterpolation.Timestep = timestep; } else { _originalTimer = UnityObjectMapper.Instance.Map <float>(data); RunChange_originalTimer(timestep); } } }
/// <summary> /// TODO /// </summary> /// <param name="id">Unique identifier to be used</param> /// <param name="netWorker">The NetWorker(Socket) to write with</param> /// <param name="data">Data to send over</param> /// <param name="reliableUDP">If this be a reliable UDP</param> public static void WriteCustom(string id, NetWorker netWorker, BMSByte data, NetworkingPlayer target, bool reliableUDP = false) { if (!netWorker.IsServer) throw new NetworkException("Currently this overload of WriteCustom is only supported being called on the server."); if (netWorker is CrossPlatformUDP) { netWorker.Write(id, target, new NetworkingStream().Prepare( netWorker, NetworkingStream.IdentifierType.Custom, null, data, NetworkReceivers.Others, reliableUDP, id ), reliableUDP); } else { netWorker.Write(target, new NetworkingStream().Prepare( netWorker, NetworkingStream.IdentifierType.Custom, null, data, NetworkReceivers.Others, reliableUDP, id )); } }
protected override BMSByte WritePayload(BMSByte data) { return(data); }
/// <summary> /// Tells the client to change their scene to the given scene. This is often called /// after the server has changed to that scene to ensure that the server will always /// load up the scene before the client does /// </summary> /// <param name="port">The port of the <see cref="NetWorker"/> that is to send the message</param> /// <param name="targetPlayer">The particular player that will be receiving this message</param> /// <param name="sceneName">The name of the scene in which the client should load</param> public static void ChangeClientScene(ushort port, NetworkingPlayer targetPlayer, string sceneName) { if (!Sockets.ContainsKey(port)) throw new NetworkException("There isn't a server running using the specified port on this machine"); if (!Sockets[port].IsServer) throw new NetworkException("Writing to particular players can only be done by the server, the NetWorker on the specified port is not a server"); BMSByte data = new BMSByte(); data.Clone(Encryptor.Encoding.GetBytes(sceneName)); data.InsertRange(0, new byte[1] { 2 }); Sockets[port].WriteRaw(data, false); }
protected override void ReadPayload(BMSByte payload, ulong timestep) { }
/// <summary> /// Get all the new player updates /// </summary> public override void GetNewPlayerUpdates() { Me = new NetworkingPlayer(Uniqueidentifier, "127.0.0.1", null, string.Empty); BMSByte tmp = new BMSByte(); ObjectMapper.MapBytes(tmp, "update"); lock(writeMutex) { writeStream.SetProtocolType(Networking.ProtocolType.TCP); writeStream.Prepare(this, NetworkingStream.IdentifierType.None, null, tmp, NetworkReceivers.Server); Write(writeStream); } }
public override void Initialize(NetworkObject obj) { // We have already initialized this object if (networkObject != null && networkObject.AttachedBehavior != null) { return; } networkObject = (GameModeNetworkObject)obj; networkObject.AttachedBehavior = this; base.SetupHelperRpcs(networkObject); networkObject.onDestroy += DestroyGameObject; if (!obj.IsOwner) { if (!skipAttachIds.ContainsKey(obj.NetworkId)) { ProcessOthers(gameObject.transform, obj.NetworkId + 1); } else { skipAttachIds.Remove(obj.NetworkId); } } if (obj.Metadata != null) { byte transformFlags = obj.Metadata[0]; if (transformFlags != 0) { BMSByte metadataTransform = new BMSByte(); metadataTransform.Clone(obj.Metadata); metadataTransform.MoveStartIndex(1); if ((transformFlags & 0x01) != 0 && (transformFlags & 0x02) != 0) { MainThreadManager.Run(() => { transform.position = ObjectMapper.Instance.Map <Vector3>(metadataTransform); transform.rotation = ObjectMapper.Instance.Map <Quaternion>(metadataTransform); }); } else if ((transformFlags & 0x01) != 0) { MainThreadManager.Run(() => { transform.position = ObjectMapper.Instance.Map <Vector3>(metadataTransform); }); } else if ((transformFlags & 0x02) != 0) { MainThreadManager.Run(() => { transform.rotation = ObjectMapper.Instance.Map <Quaternion>(metadataTransform); }); } } } MainThreadManager.Run(() => { NetworkStart(); networkObject.Networker.FlushCreateActions(networkObject); }); }
protected override void OwnerUpdate() { base.OwnerUpdate(); if (Input.GetKeyDown(KeyCode.B)) AssignName("Brent"); else if (Input.GetKeyDown(KeyCode.F)) AssignName("Farris"); if (Input.GetKey(KeyCode.UpArrow)) transform.position += Vector3.up * 5.0f * Time.deltaTime; if (Input.GetKey(KeyCode.DownArrow)) transform.position += Vector3.down * 5.0f * Time.deltaTime; if (Input.GetKey(KeyCode.LeftArrow)) transform.position += Vector3.left * 5.0f * Time.deltaTime; if (Input.GetKey(KeyCode.RightArrow)) transform.position += Vector3.right * 5.0f * Time.deltaTime; if (Input.GetKeyDown(KeyCode.T)) { cachedData = ServerSerialze(testNum++); Networking.WriteCustom(SERVER_ONLY, Networking.PrimarySocket, cachedData, true, NetworkReceivers.Server); } if (Input.GetKeyDown(KeyCode.Space)) { number++; cat += "Cat"; } else if (Input.GetKeyDown(KeyCode.V)) floatNumber += 50.35f; if (Input.GetKeyDown(KeyCode.S)) Cache.Set<int>("test", 9); if (Input.GetKeyDown(KeyCode.G)) { Cache.Request<int>("test", (object x) => { Debug.Log(x); }); } if (OwningNetWorker.IsServer && Input.GetKeyDown(KeyCode.N)) { Networking.ChangeClientScene(OwningNetWorker, "ForgeWriteCustom"); Application.LoadLevel("ForgeWriteCustom"); } else if (OwningNetWorker.IsServer && Input.GetKeyDown(KeyCode.M)) { Networking.ChangeClientScene(OwningNetWorker, "ForgeHelloCubeResources"); Application.LoadLevel("ForgeHelloCubeResources"); } if (Input.GetKeyDown(KeyCode.L)) dontLerp += 5.35f; if (Input.GetKeyDown(KeyCode.C)) RPC("MessageGroupTest", NetworkReceivers.MessageGroup, (byte)9); if (Input.GetKeyDown(KeyCode.Alpha0)) { Debug.Log("Setting message group to 0"); Networking.SetMyMessageGroup(OwningNetWorker, (ushort)0); } else if (Input.GetKeyDown(KeyCode.Alpha1)) { Debug.Log("Setting message group to 1"); Networking.SetMyMessageGroup(OwningNetWorker, (ushort)1); } else if (Input.GetKeyDown(KeyCode.Alpha2)) { Debug.Log("Setting message group to 2"); Networking.SetMyMessageGroup(OwningNetWorker, (ushort)2); } else if (Input.GetKeyDown(KeyCode.Alpha3)) { Debug.Log("Setting message group to 3"); Networking.SetMyMessageGroup(OwningNetWorker, (ushort)3); } }
public override void Initialize(NetworkObject obj) { // We have already initialized this object if (networkObject != null && networkObject.AttachedBehavior != null) { return; } networkObject = (TestNetworkObject)obj; networkObject.AttachedBehavior = this; base.SetupHelperRpcs(networkObject); networkObject.RegisterRpc("FuncBlank", FuncBlank); networkObject.RegisterRpc("FuncByte", FuncByte, typeof(byte)); networkObject.RegisterRpc("FuncChar", FuncChar, typeof(char)); networkObject.RegisterRpc("FuncShort", FuncShort, typeof(short)); networkObject.RegisterRpc("FuncUShort", FuncUShort, typeof(ushort)); networkObject.RegisterRpc("FuncBool", FuncBool, typeof(bool)); networkObject.RegisterRpc("FuncInt", FuncInt, typeof(int)); networkObject.RegisterRpc("FuncUInt", FuncUInt, typeof(uint)); networkObject.RegisterRpc("FuncFloat", FuncFloat, typeof(float)); networkObject.RegisterRpc("FuncLong", FuncLong, typeof(long)); networkObject.RegisterRpc("FuncULong", FuncULong, typeof(ulong)); networkObject.RegisterRpc("FuncDouble", FuncDouble, typeof(double)); networkObject.RegisterRpc("FuncString", FuncString, typeof(string)); networkObject.RegisterRpc("FuncByteArray", FuncByteArray, typeof(byte[])); networkObject.RegisterRpc("FuncAll", FuncAll, typeof(byte), typeof(char), typeof(short), typeof(ushort), typeof(bool), typeof(int), typeof(uint), typeof(float), typeof(long), typeof(ulong), typeof(double), typeof(string), typeof(byte[])); MainThreadManager.Run(() => { NetworkStart(); networkObject.Networker.FlushCreateActions(networkObject); }); networkObject.onDestroy += DestroyGameObject; if (!obj.IsOwner) { if (!skipAttachIds.ContainsKey(obj.NetworkId)) { ProcessOthers(gameObject.transform, obj.NetworkId + 1); } else { skipAttachIds.Remove(obj.NetworkId); } } if (obj.Metadata == null) { return; } byte transformFlags = obj.Metadata[0]; if (transformFlags == 0) { return; } BMSByte metadataTransform = new BMSByte(); metadataTransform.Clone(obj.Metadata); metadataTransform.MoveStartIndex(1); if ((transformFlags & 0x01) != 0 && (transformFlags & 0x02) != 0) { MainThreadManager.Run(() => { transform.position = ObjectMapper.Instance.Map <Vector3>(metadataTransform); transform.rotation = ObjectMapper.Instance.Map <Quaternion>(metadataTransform); }); } else if ((transformFlags & 0x01) != 0) { MainThreadManager.Run(() => { transform.position = ObjectMapper.Instance.Map <Vector3>(metadataTransform); }); } else if ((transformFlags & 0x02) != 0) { MainThreadManager.Run(() => { transform.rotation = ObjectMapper.Instance.Map <Quaternion>(metadataTransform); }); } }
private void DoSerialize() { serializedBuffer = Serialized(); if (OwningNetWorker is CrossPlatformUDP) { writeStream.SetProtocolType(Networking.ProtocolType.UDP); Networking.WriteUDP(OwningNetWorker, myUniqueId, writeStream.Prepare(OwningNetWorker, NetworkingStream.IdentifierType.NetworkedBehavior, this, serializedBuffer, (OwningNetWorker.ProximityBasedMessaging ? NetworkReceivers.OthersProximity : NetworkReceivers.Others)), isReliable); } else { writeStream.SetProtocolType(Networking.ProtocolType.TCP); Networking.WriteTCP(OwningNetWorker, writeStream.Prepare(OwningNetWorker, NetworkingStream.IdentifierType.NetworkedBehavior, this, serializedBuffer, OwningNetWorker.ProximityBasedMessaging ? NetworkReceivers.OthersProximity : NetworkReceivers.Others)); } HasSerialized = true; UpdateValues(); }
protected override void ReadDirtyFields(BMSByte data, ulong timestep) { if (readDirtyFlags == null) { Initialize(); } Buffer.BlockCopy(data.byteArr, data.StartIndex(), readDirtyFlags, 0, readDirtyFlags.Length); data.MoveStartIndex(readDirtyFlags.Length); if ((0x1 & readDirtyFlags[0]) != 0) { if (PositionInterpolation.Enabled) { PositionInterpolation.target = UnityObjectMapper.Instance.Map <Vector3>(data); PositionInterpolation.Timestep = timestep; } else { _Position = UnityObjectMapper.Instance.Map <Vector3>(data); RunChange_Position(timestep); } } if ((0x2 & readDirtyFlags[0]) != 0) { if (RotationInterpolation.Enabled) { RotationInterpolation.target = UnityObjectMapper.Instance.Map <Quaternion>(data); RotationInterpolation.Timestep = timestep; } else { _Rotation = UnityObjectMapper.Instance.Map <Quaternion>(data); RunChange_Rotation(timestep); } } if ((0x4 & readDirtyFlags[0]) != 0) { if (NetworkIDInterpolation.Enabled) { NetworkIDInterpolation.target = UnityObjectMapper.Instance.Map <int>(data); NetworkIDInterpolation.Timestep = timestep; } else { _NetworkID = UnityObjectMapper.Instance.Map <int>(data); RunChange_NetworkID(timestep); } } if ((0x8 & readDirtyFlags[0]) != 0) { if (AnimationInterpolation.Enabled) { AnimationInterpolation.target = UnityObjectMapper.Instance.Map <int>(data); AnimationInterpolation.Timestep = timestep; } else { _Animation = UnityObjectMapper.Instance.Map <int>(data); RunChange_Animation(timestep); } } }