//bolt 3 float properties compressed the same (18 bits each = 54 bits) //20 packets per second, means 1080 bits or 135 bytes per second or 0.135 bytes per second public override void Serialize(UdpStream stream) { SerializerUtils.WriteFloat(stream, this.transform.position.x, -100f, 100f, 0.0001f); SerializerUtils.WriteFloat(stream, this.transform.position.y, -100f, 100f, 0.0001f); SerializerUtils.WriteFloat(stream, this.transform.position.z, -100f, 100f, 0.0001f); SerializerUtils.WriteQuaterinion(stream, this.transform.rotation, 0.001f); }
internal void SendCommand(UdpCommandType cmd) { if (CheckCanSend(true) == UdpSendFailReason.None) { UdpStream stream = socket.GetWriteStream(mtu << 3, UdpSocket.HeaderBitSize); stream.WriteByte((byte)cmd, 8); UdpHeader header = MakeHeader(false); header.Pack(stream, socket); UdpHandle handle = MakeHandle(ref header); handle.Object = null; if (SendStream(stream, handle, false)) { // track stats stats.PacketSent((uint)stream.Ptr >> 3); socket.Statistics.PacketSent((uint)stream.Ptr >> 3); } else { // should we do something here????? } } }
public override void Deserialize(UdpStream stream, int prefabId, int networkId, int owner, int controller) { //deserialize any state data. float x = SerializerUtils.ReadFloat(stream, -100f, 100f, 0.0001f); float y = SerializerUtils.ReadFloat(stream, -100f, 100f, 0.0001f); float z = SerializerUtils.ReadFloat(stream, -100f, 100f, 0.0001f); int iValue = SerializerUtils.ReadInt(stream, -100, 100); float fValue = SerializerUtils.ReadFloat(stream, -100f, 100f, 0.001f); Quaternion rotation = SerializerUtils.ReadQuaternion(stream, 0.001f); //we have to do this after the deseralize, otherwise the data will be corrupted //we can't do this here because this call to priority would be on the prefab, not the instance because //this is on the receiver. and we usually want to use this.transform.position in the priority check //and it would always be 0,0,0! //at this point, we don't know if this entity is even instantiated in the world //we don't do that check until inside of ProcessEntityMessage, but in some cases we don't //want to process it because then it will get instantiated when we don't want it to (eg, in a different scene) //so we need to make some compromises with how the priority system will work for entities //eg, we can only use prefab values as we don't have an entity instance to work with //but we can push in any extra data if we really need to, we just need to modify it //we could pass in args, too.. //ProcessDeserialize(); //how can we simplify this? //Process(prefabId, networkId, owner, controller, entityProps....) //can we assume xyz are the first three entity props? //will an entity ALWAYS have a position? ProcessDeserialize(prefabId, networkId, owner, controller, x, y, z, iValue, fValue, rotation); }
void PackAckSequence(UdpStream buffer, bool sendNow) { ushort sequence = AckSequence; sequence <<= SEQ_PADD; sequence |= (ushort)(sendNow ? ((1U << SEQ_PADD) - 1U) : 0); buffer.WriteUShort(sequence, SEQ_BITS + SEQ_PADD); }
internal void SendObject(object o) { serializer.SendNext(o); while (serializer.HasQueuedObjects) { UdpSendFailReason reason = CheckCanSend(false); if (reason != UdpSendFailReason.None) { while (serializer.HasQueuedObjects) { socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, serializer.NextObject(), reason); } break; } UdpStream stream = socket.GetWriteStream(mtu << 3, UdpSocket.HeaderBitSize); var initialPtr = stream.Ptr; // Erhune: added info object obj = serializer.NextObject(); if (serializer.Pack(stream, ref obj)) { if (stream.Overflowing && (socket.Config.AllowPacketOverflow == false)) { UdpLog.Error("Stream to {0} is overflowing (InitialPtr={1} Ptr={2} Len={3}), not sending {4}", endpoint.ToString(), initialPtr, stream.Ptr, stream.Length, obj); // Erhune: added info socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, obj, UdpSendFailReason.StreamOverflow); return; } UdpHeader header = MakeHeader(true); header.Pack(stream, socket, shouldSendClock); UdpHandle handle = MakeHandle(ref header); handle.Object = obj; if (SendStream(stream, handle, alwaysSendMtu)) { // track stats stats.PacketSent((uint)stream.Ptr >> 3); socket.Statistics.PacketSent((uint)stream.Ptr >> 3); // push object to user thread socket.Raise(UdpEvent.PUBLIC_OBJECT_SENT, this, obj); } else { socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, obj, UdpSendFailReason.SocketError); } } else { socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, obj, UdpSendFailReason.SerializerReturnedFalse); } } }
public override void Deserialize(UdpStream stream, int prefabId, int networkId, int owner, int controller) { //deserialize any state data. float x = SerializerUtils.ReadFloat(stream, -10f, 10f, 0.0001f); float y = SerializerUtils.ReadFloat(stream, -10f, 10f, 0.0001f); float z = SerializerUtils.ReadFloat(stream, -10f, 10f, 0.0001f); Core.net.ProcessEntityMessage(prefabId, networkId, owner, controller, x, y, z); }
protected override void Dispose(bool disposing) { if (stream != null) { stream.Close(); stream = null; } base.Dispose(disposing); }
void OnCommandDisconnected(UdpStream buffer) { EnsureClientIsConnected(); if (CheckState(UdpConnectionState.Connected)) { ChangeState(UdpConnectionState.Disconnected); } }
public override bool Unpack(UdpStream stream, ref object o) { // read length and create array, then read bytes into array byte[] bytes = new byte[stream.ReadInt()]; stream.ReadByteArray(bytes); // convert bytes to string o = Encoding.UTF8.GetString(bytes); return true; }
public override IStream <UdpPacket> GetSocketStream() { CheckDisposed(); if (stream == null) { stream = new UdpStream(this); } return(stream); }
public override bool Unpack(UdpStream stream, ref object o) { // read length and create array, then read bytes into array byte[] bytes = new byte[stream.ReadInt()]; stream.ReadByteArray(bytes); // convert bytes to string o = Encoding.UTF8.GetString(bytes); return(true); }
public override bool Pack(UdpStream stream, ref object o) { // cast to string and get bytes byte[] bytes = (byte[])(o); // write length and bytes into buffer stream.WriteInt(bytes.Length); stream.WriteByteArray(bytes); return(true); }
public override bool Unpack(UdpStream stream, out NetMessage received) { var readOffset = UdpMath.BytesRequired(stream.Position); var readLength = UdpMath.BytesRequired(stream.Size - stream.Position); // allocate a new stream and copy data received = NetMessage.GetMessage(readLength); received.Write(stream.ByteBuffer, readOffset, readLength); received.Position = 0; return(true); }
public void Unpack(UdpStream buffer, UdpSocket socket) { buffer.Position = 0; ObjSequence = TrimSequence(buffer.ReadUShort(SEQ_BITS + SEQ_PADD)); AckSequence = TrimSequence(buffer.ReadUShort(SEQ_BITS + SEQ_PADD)); AckHistory = buffer.ReadULong(UdpSocket.AckRedundancy); if (UdpSocket.CalculateNetworkPing) { AckTime = buffer.ReadUShort(NETPING_BITS); } }
internal void Release(UdpStream stream) { UdpAssert.Assert(stream.IsPooled == false); lock (pool) { stream.Size = 0; stream.Position = 0; stream.IsPooled = true; pool.Push(stream); } }
public override bool Pack(UdpStream stream, ref object o) { // cast to string and get bytes string msg = (string) o; byte[] bytes = Encoding.UTF8.GetBytes(msg); // write length and bytes into buffer stream.WriteInt(bytes.Length); stream.WriteByteArray(bytes); return true; }
public void Unpack(UdpStream buffer, UdpSocket socket) { buffer.Position = 0; ObjSequence = TrimSequence(buffer.ReadUShort(16)); AckSequence = TrimSequence(buffer.ReadUShort(16)); AckHistory = buffer.ReadULong(UdpSocket.AckRedundancy); if (UdpSocket.CalculateNetworkPing) { AckTime = buffer.ReadUShort(16); } }
public override bool Pack(UdpStream stream, ref object o) { // cast to string and get bytes string msg = (string)o; byte[] bytes = Encoding.UTF8.GetBytes(msg); // write length and bytes into buffer stream.WriteInt(bytes.Length); stream.WriteByteArray(bytes); return(true); }
void OnCommandConnect(UdpStream buffer) { if (IsServer) { if (CheckState(UdpConnectionState.Connected)) { SendCommand(UdpCommandType.Accepted); } } else { ConnectionError(UdpConnectionError.IncorrectCommand); } }
void OnCommandAccepted(UdpStream buffer) { if (IsClient) { if (CheckState(UdpConnectionState.Connecting)) { ChangeState(UdpConnectionState.Connected); } } else { ConnectionError(UdpConnectionError.IncorrectCommand); } }
void UnpackAckSequence(UdpStream buffer) { ushort sequence = buffer.ReadUShort(SEQ_BITS + SEQ_PADD); bool recvNow = 1 == (sequence & 1); if (recvNow) { int pos = buffer.Position; buffer.Position = buffer.Length - 32; Now = buffer.ReadUInt(); buffer.Position = pos; } sequence >>= SEQ_PADD; AckSequence = sequence; }
public void Pack(UdpStream buffer, UdpSocket socket) { int pos = buffer.Position; buffer.Position = 0; buffer.WriteUShort(PadSequence(ObjSequence), SEQ_BITS + SEQ_PADD); buffer.WriteUShort(PadSequence(AckSequence), SEQ_BITS + SEQ_PADD); buffer.WriteULong(AckHistory, UdpSocket.AckRedundancy); if (UdpSocket.CalculateNetworkPing) { buffer.WriteUShort(AckTime, NETPING_BITS); } buffer.Position = pos; }
public void Pack(UdpStream buffer, UdpSocket socket) { var pos = buffer.Position; buffer.Position = 0; buffer.WriteUShort(PadSequence(ObjSequence), 16); buffer.WriteUShort(PadSequence(AckSequence), 16); buffer.WriteULong(AckHistory, UdpSocket.AckRedundancy); if (UdpSocket.CalculateNetworkPing) { buffer.WriteUShort(AckTime, 16); } buffer.Position = pos; }
bool SendStream(UdpStream stream, UdpHandle handle, bool expandToMtu) { int bytesToSend = UdpMath.BytesRequired(stream.Ptr); if (bytesToSend < mtu && expandToMtu) { bytesToSend = mtu; } sendTime = handle.SendTime; sendSequence = handle.ObjSequence; sendWindow.Enqueue(handle); recvSinceLastSend = 0; return(socket.Send(endpoint, stream.Data, bytesToSend)); }
void OnCommandRefused(UdpStream buffer) { if (IsClient) { if (CheckState(UdpConnectionState.Connecting)) { socket.Raise(UdpEvent.PUBLIC_CONNECT_REFUSED, endpoint); // destroy this connection on next timeout check ChangeState(UdpConnectionState.Destroy); } } else { ConnectionError(UdpConnectionError.IncorrectCommand); } }
bool ParseHeader(UdpStream stream) { // we should always start at ptr 0 UdpAssert.Assert(stream.Ptr == 0); UdpHeader header = new UdpHeader(); header.Unpack(stream, socket); // after unpacking the header, the pointer should be at the header size UdpAssert.Assert(stream.Ptr == UdpSocket.HeaderBitSize); int seqDistance = UdpMath.SeqDistance(header.ObjSequence, recvSequence, UdpHeader.SEQ_PADD); // we have to be within window size if (seqDistance > socket.Config.PacketWindow || seqDistance < -socket.Config.PacketWindow) { ConnectionError(UdpConnectionError.SequenceOutOfBounds, string.Format("seqDistance: {0}, socket.Config.PacketWindow: {1}, header.ObjSequence: {2}, recvSequence: {3}", seqDistance, socket.Config.PacketWindow, header.ObjSequence, recvSequence)); return(false); } // this is an old packet if (seqDistance <= 0) { return(false); } // update receive history if (seqDistance >= UdpSocket.AckRedundancy) { recvHistory = 1UL; } else { recvHistory = (recvHistory << seqDistance) | 1UL; } // update our receive stats recvSequence = header.ObjSequence; recvSinceLastSend += 1; // ack sent objects AckHandles(header, true); return(true); }
public override void Deserialize(UdpStream stream, int prefabId, int networkId, int owner, int controller) { //deserialize any state data. //!important, can only use data that we deserialize here //we can NOT use this.prefabId. Because in this method call (this) refers to the PREFAB //NOT the instance. And as such, will return the prefab values. //this is because we don't know if this entity even exists in our local world yet, (it might need to be spawned) //and if that's the case, it doesn't even have an instance to get values for! //we do know after we serialize the data though what the position WOULD be if we spawn it float x = SerializerUtils.ReadFloat(stream, -100f, 100f, 0.0001f); float y = SerializerUtils.ReadFloat(stream, -100f, 100f, 0.0001f); float z = SerializerUtils.ReadFloat(stream, -100f, 100f, 0.0001f); Quaternion rotation = SerializerUtils.ReadQuaternion(stream, 0.001f); ProcessDeserialize(prefabId, networkId, owner, controller, x, y, z, rotation); }
internal void OnPacket(UdpStream buffer) { // track stats stats.PacketReceived((uint)buffer.Length >> 3); socket.Statistics.PacketReceived((uint)buffer.Length >> 3); // set recv time of for last packet recvTime = socket.GetCurrentTime(); if ((buffer.Data[0] & 1) == 1) { OnObjectReceived(buffer); } else { OnCommandReceived(buffer); } }
void OnCommandAccepted(UdpStream buffer) { if (IsClient) { if (CheckState(UdpConnectionState.Connecting)) { if (buffer.CanRead(8) && buffer.ReadByte(8) == UdpEvent.INTERNAL_COMMAND_HASOBJECT) { serializer.Unpack(buffer, ref hailMessage); } ChangeState(UdpConnectionState.Connected); } } else { ConnectionError(UdpConnectionError.IncorrectCommand); } }
void OnObjectReceived(UdpStream buffer) { EnsureClientIsConnected(); if (CheckState(UdpConnectionState.Connected) == false) { return; } if (ParseHeader(buffer)) { object obj = null; buffer.Ptr = UdpSocket.HeaderBitSize; if (serializer.Unpack(buffer, ref obj)) { socket.Raise(UdpEvent.PUBLIC_OBJECT_RECEIVED, this, obj); } } }
public void Pack(UdpStream buffer, UdpSocket socket, bool sendNow) { int pos = buffer.Position; sendNow &= buffer.CanWrite (32); if (sendNow) { buffer.WriteUInt (this.Now); pos = buffer.Position; } buffer.Position = 0; buffer.WriteUShort(PadSequence(ObjSequence), SEQ_BITS + SEQ_PADD); PackAckSequence (buffer, sendNow); buffer.WriteULong(AckHistory, UdpSocket.AckRedundancy); if (UdpSocket.CalculateNetworkPing) { buffer.WriteUShort(AckTime, NETPING_BITS); } buffer.Position = pos; }
void Start() { byte[] b = new byte[1024 * 2]; //packetsize *2, why *2? That's what udpSocket.cs does. idk int packetSize = 32; UdpStream writeStream = new UdpStream(new byte[packetSize * 2]); UdpStream readStream = new UdpStream(new byte[packetSize * 2]); int maxValue = 4095; int value = 256; //writeStream.WriteInt(value); //writes as 32 bit //writeStream.WriteInt(value); SerializerUtils.WriteInt(writeStream, 255, 0, 255); SerializerUtils.WriteInt(writeStream, 256, 0, 256); //SerializerUtils.WriteInt(writeStream, value,); readStream = new UdpStream(writeStream.Data, writeStream.Position); Debug.Log("0: " + SerializerUtils.ReadInt(readStream, 0, 255)); Debug.Log("1: " + SerializerUtils.ReadInt(readStream, 0, 256)); //Debug.Log("read: " + SerializerUtils.ReadInt(readStream)); //Debug.Log("255: " + BitTools.BitDisplay.BytesToString(writeStream.Data)); //this sends the entire packetSize of bytes, doesn't trim any of them off... //Debug.Log("256: " + BitTools.BitDisplay.BytesToString(readStream.Data)); //this sends the entire packetSize of bytes, doesn't trim any of them off... // Debug.Log(writeStream.Data.Length + " : " + writeStream.Ptr + " : " + writeStream.Position); //Debug.Log("read: " + BitTools.BitDisplay.BytesToString(readStream.Data)); //Debug.Log(readStream.Data.Length + " : " + readStream.Ptr + " : " + readStream.Position); //we could arrayCopy it to the appropriate size and send that? idk //steam does this internally I }
public void Pack(UdpStream buffer, UdpSocket socket, bool sendNow) { int pos = buffer.Position; sendNow &= buffer.CanWrite(32); if (sendNow) { buffer.WriteUInt(this.Now); pos = buffer.Position; } buffer.Position = 0; buffer.WriteUShort(PadSequence(ObjSequence), SEQ_BITS + SEQ_PADD); PackAckSequence(buffer, sendNow); buffer.WriteULong(AckHistory, UdpSocket.AckRedundancy); if (UdpSocket.CalculateNetworkPing) { buffer.WriteUShort(AckTime, NETPING_BITS); } buffer.Position = pos; }
void OnCommandReceived(UdpStream buffer) { if (ParseHeader(buffer)) { buffer.Ptr = UdpSocket.HeaderBitSize; UdpCommandType cmd = (UdpCommandType)buffer.ReadByte(8); switch (cmd) { case UdpCommandType.Connect: OnCommandConnect(buffer); break; case UdpCommandType.Accepted: OnCommandAccepted(buffer); break; case UdpCommandType.Refused: OnCommandRefused(buffer); break; case UdpCommandType.Disconnected: OnCommandDisconnected(buffer); break; case UdpCommandType.Ping: OnCommandPing(buffer); break; default: ConnectionError(UdpConnectionError.IncorrectCommand); break; } } }
public UdpStream Acquire() { UdpStream stream = null; lock (pool) { if (pool.Count > 0) { stream = pool.Pop(); } } if (stream == null) { stream = new UdpStream(new byte[socket.Config.PacketSize * 2]); stream.Pool = this; } UdpAssert.Assert(stream.IsPooled); stream.IsPooled = false; stream.Position = 0; stream.Size = (socket.Config.PacketSize - UdpMath.BytesRequired(UdpSocket.HeaderBitSize)) << 3; return stream; }
public abstract bool Unpack(UdpStream stream, ref object o);
void OnCommandReceived(UdpStream buffer) { if (ParseHeader(buffer)) { buffer.Ptr = UdpSocket.HeaderBitSize; UdpCommandType cmd = (UdpCommandType) buffer.ReadByte(8); switch (cmd) { case UdpCommandType.Connect: OnCommandConnect(buffer); break; case UdpCommandType.Accepted: OnCommandAccepted(buffer); break; case UdpCommandType.Refused: OnCommandRefused(buffer); break; case UdpCommandType.Disconnected: OnCommandDisconnected(buffer); break; case UdpCommandType.Ping: OnCommandPing(buffer); break; default: ConnectionError(UdpConnectionError.IncorrectCommand); break; } } }
void OnCommandAccepted(UdpStream buffer) { if (IsClient) { if (CheckState(UdpConnectionState.Connecting)) { if (buffer.CanRead(8) && buffer.ReadByte(8) == UdpEvent.INTERNAL_COMMAND_HASOBJECT) serializer.Unpack(buffer, ref hailMessage); ChangeState(UdpConnectionState.Connected); } } else { ConnectionError(UdpConnectionError.IncorrectCommand); } }
void OnObjectReceived(UdpStream buffer) { EnsureClientIsConnected(); if (CheckState(UdpConnectionState.Connected) == false) return; if (ParseHeader(buffer)) { object obj = null; buffer.Ptr = UdpSocket.HeaderBitSize; if (serializer.Unpack(buffer, ref obj)) { socket.Raise(UdpEvent.PUBLIC_OBJECT_RECEIVED, this, obj); } } }
bool ParseHeader(UdpStream stream) { // we should always start at ptr 0 UdpAssert.Assert(stream.Ptr == 0); UdpHeader header = new UdpHeader(); header.Unpack(stream, socket); // after unpacking the header, the pointer should be at the header size UdpAssert.Assert(stream.Ptr == UdpSocket.HeaderBitSize); int seqDistance = UdpMath.SeqDistance(header.ObjSequence, recvSequence, UdpHeader.SEQ_PADD); // we have to be within window size if (seqDistance > socket.Config.PacketWindow || seqDistance < -socket.Config.PacketWindow) { ConnectionError(UdpConnectionError.SequenceOutOfBounds, string.Format("seqDistance: {0}, socket.Config.PacketWindow: {1}, header.ObjSequence: {2}, recvSequence: {3}", seqDistance, socket.Config.PacketWindow, header.ObjSequence, recvSequence)); return false; } // this is an old packet if (seqDistance <= 0) return false; // update receive history if (seqDistance >= UdpSocket.AckRedundancy) { recvHistory = 1UL; } else { recvHistory = (recvHistory << seqDistance) | 1UL; } // update our receive stats recvSequence = header.ObjSequence; recvSinceLastSend += 1; // ack sent objects AckHandles(header, true); return true; }
void OnCommandPing(UdpStream buffer) { EnsureClientIsConnected(); }
bool SendStream(UdpStream stream, UdpHandle handle, bool expandToMtu) { int bytesToSend = UdpMath.BytesRequired(stream.Ptr); if (bytesToSend < mtu && expandToMtu) { bytesToSend = mtu; } sendTime = handle.SendTime; sendSequence = handle.ObjSequence; sendWindow.Enqueue(handle); recvSinceLastSend = 0; return socket.Send(endpoint, stream.Data, bytesToSend); }
public override bool Pack(UdpStream stream, ref object o) { throw new System.NotImplementedException(); }
internal void OnPacket(UdpStream buffer) { // track stats stats.PacketReceived((uint) buffer.Length >> 3); socket.Statistics.PacketReceived((uint) buffer.Length >> 3); // set recv time of for last packet recvTime = socket.GetCurrentTime(); if ((buffer.Data[0] & 1) == 1) { OnObjectReceived(buffer); } else { OnCommandReceived(buffer); } }
void UnpackAckSequence(UdpStream buffer) { ushort sequence = buffer.ReadUShort(SEQ_BITS + SEQ_PADD); bool recvNow = 1 == (sequence & 1); if (recvNow) { int pos = buffer.Position; buffer.Position = buffer.Length - 32; Now = buffer.ReadUInt (); buffer.Position = pos; } sequence >>= SEQ_PADD; AckSequence = sequence; }