protected abstract void WriteEvent(IWriteMessage buffer, NetEntityEvent entityEvent, Client recipient = null);
public void ServerWriteSpawn(IWriteMessage msg) { msg.Write(Prefab.Identifier); msg.Write(Offset.X); msg.Write(Offset.Y); }
public override void Send(IWriteMessage msg, DeliveryMethod deliveryMethod) { if (!isActive) { return; } byte[] buf = new byte[msg.LengthBytes + 4]; buf[0] = (byte)deliveryMethod; byte[] bufAux = new byte[msg.LengthBytes]; bool isCompressed; int length; msg.PrepareForSending(ref bufAux, out isCompressed, out length); buf[1] = (byte)(isCompressed ? PacketHeader.IsCompressed : PacketHeader.None); buf[2] = (byte)(length & 0xff); buf[3] = (byte)((length >> 8) & 0xff); Array.Copy(bufAux, 0, buf, 4, length); Facepunch.Steamworks.Networking.SendType sendType; switch (deliveryMethod) { case DeliveryMethod.Reliable: case DeliveryMethod.ReliableOrdered: //the documentation seems to suggest that the Reliable send type //enforces packet order (TODO: verify) sendType = Facepunch.Steamworks.Networking.SendType.Reliable; break; default: sendType = Facepunch.Steamworks.Networking.SendType.Unreliable; break; } if (length + 8 >= MsgConstants.MTU) { DebugConsole.Log("WARNING: message length comes close to exceeding MTU, forcing reliable send (" + length.ToString() + " bytes)"); sendType = Facepunch.Steamworks.Networking.SendType.Reliable; } heartbeatTimer = 5.0; #if DEBUG CoroutineManager.InvokeAfter(() => { if (GameMain.Client == null) { return; } if (Rand.Range(0.0f, 1.0f) < GameMain.Client.SimulatedLoss && sendType != Facepunch.Steamworks.Networking.SendType.Reliable) { return; } int count = Rand.Range(0.0f, 1.0f) < GameMain.Client.SimulatedDuplicatesChance ? 2 : 1; for (int i = 0; i < count; i++) { Send(buf, length + 4, sendType); } }, GameMain.Client.SimulatedMinimumLatency + Rand.Range(0.0f, GameMain.Client.SimulatedRandomLatency)); #else Send(buf, length + 4, sendType); #endif }
/// <summary> /// Write the events to the outgoing message. The recipient parameter is only needed for ServerEntityEventManager /// </summary> protected void Write(IWriteMessage msg, List <NetEntityEvent> eventsToSync, out List <NetEntityEvent> sentEvents, Client recipient = null) { //write into a temporary buffer so we can write the number of events before the actual data IWriteMessage tempBuffer = new WriteOnlyMessage(); sentEvents = new List <NetEntityEvent>(); int eventCount = 0; foreach (NetEntityEvent e in eventsToSync) { //write into a temporary buffer so we can write the length before the actual data IWriteMessage tempEventBuffer = new WriteOnlyMessage(); try { WriteEvent(tempEventBuffer, e, recipient); } catch (Exception exception) { DebugConsole.ThrowError("Failed to write an event for the entity \"" + e.Entity + "\"", exception); GameAnalyticsManager.AddErrorEventOnce("NetEntityEventManager.Write:WriteFailed" + e.Entity.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, "Failed to write an event for the entity \"" + e.Entity + "\"\n" + exception.StackTrace); //write an empty event to avoid messing up IDs //(otherwise the clients might read the next event in the message and think its ID //is consecutive to the previous one, even though we skipped over this broken event) tempBuffer.Write(Entity.NullEntityID); tempBuffer.WritePadBits(); eventCount++; continue; } //the length of the data is written as a byte, so the data needs to be less than 255 bytes long if (tempEventBuffer.LengthBytes > 255) { DebugConsole.ThrowError("Too much data in network event for entity \"" + e.Entity.ToString() + "\" (" + tempEventBuffer.LengthBytes + " bytes, event ID " + e.ID + ")"); GameAnalyticsManager.AddErrorEventOnce("NetEntityEventManager.Write:TooLong" + e.Entity.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, "Too much data in network event for entity \"" + e.Entity.ToString() + "\" (" + tempEventBuffer.LengthBytes + " bytes, event ID " + e.ID + ")"); //write an empty event to prevent breaking the event syncing tempBuffer.Write(Entity.NullEntityID); tempBuffer.WritePadBits(); eventCount++; continue; } if (msg.LengthBytes + tempBuffer.LengthBytes + tempEventBuffer.LengthBytes > MaxEventBufferLength) { //no more room in this packet break; } tempBuffer.Write(e.EntityID); tempBuffer.Write((byte)tempEventBuffer.LengthBytes); tempBuffer.Write(tempEventBuffer.Buffer, 0, tempEventBuffer.LengthBytes); tempBuffer.WritePadBits(); sentEvents.Add(e); eventCount++; } if (eventCount > 0) { msg.Write(eventsToSync[0].ID); msg.Write((byte)eventCount); msg.Write(tempBuffer.Buffer, 0, tempBuffer.LengthBytes); } }
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null) { Item item = (Item)extraData[2]; msg.Write(item.Removed ? (ushort)0 : item.ID); }
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null) { ClientWrite(msg, extraData); }
public void Serialize(IWriteMessage msg) { msg.Write(RadiationEnabled); msg.Write(MaxMissionCount); }
public void ServerWrite(IWriteMessage msg) { if (GameMain.Server == null) { return; } msg.Write(allowSubVoting); if (allowSubVoting) { List <Pair <object, int> > voteList = GetVoteList(VoteType.Sub, GameMain.Server.ConnectedClients); msg.Write((byte)voteList.Count); foreach (Pair <object, int> vote in voteList) { msg.Write((byte)vote.Second); msg.Write(((SubmarineInfo)vote.First).Name); } } msg.Write(AllowModeVoting); if (allowModeVoting) { List <Pair <object, int> > voteList = GetVoteList(VoteType.Mode, GameMain.Server.ConnectedClients); msg.Write((byte)voteList.Count); foreach (Pair <object, int> vote in voteList) { msg.Write((byte)vote.Second); msg.Write(((GameModePreset)vote.First).Identifier); } } msg.Write(AllowEndVoting); if (AllowEndVoting) { msg.Write((byte)GameMain.Server.ConnectedClients.Count(c => c.HasSpawned && c.GetVote <bool>(VoteType.EndRound))); msg.Write((byte)GameMain.Server.ConnectedClients.Count(c => c.HasSpawned)); } msg.Write(AllowVoteKick); msg.Write((byte)SubVote.State); if (SubVote.State != VoteState.None) { msg.Write((byte)SubVote.VoteType); if (SubVote.VoteType != VoteType.Unknown) { var yesClients = GameMain.Server.ConnectedClients.FindAll(c => c.GetVote <int>(SubVote.VoteType) == 2); msg.Write((byte)yesClients.Count); foreach (Client c in yesClients) { msg.Write(c.ID); } var noClients = GameMain.Server.ConnectedClients.FindAll(c => c.GetVote <int>(SubVote.VoteType) == 1); msg.Write((byte)noClients.Count); foreach (Client c in noClients) { msg.Write(c.ID); } msg.Write((byte)GameMain.Server.SubmarineVoteMax); switch (SubVote.State) { case VoteState.Started: msg.Write(SubVote.Sub.Name); msg.Write(SubVote.VoteStarter.ID); msg.Write((byte)GameMain.Server.ServerSettings.SubmarineVoteTimeout); break; case VoteState.Running: // Nothing specific break; case VoteState.Passed: case VoteState.Failed: msg.Write(SubVote.State == VoteState.Passed); msg.Write(SubVote.Sub.Name); if (SubVote.State == VoteState.Passed) { msg.Write((short)SubVote.DeliveryFee); } break; } } } var readyClients = GameMain.Server.ConnectedClients.FindAll(c => c.GetVote <bool>(VoteType.StartRound)); msg.Write((byte)readyClients.Count); foreach (Client c in readyClients) { msg.Write(c.ID); } msg.WritePadBits(); }
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null) { msg.Write(user == null ? (ushort)0 : user.ID); ClientWrite(msg, extraData); }
public void ClientWrite(IWriteMessage msg, VoteType voteType, object data) { msg.Write((byte)voteType); switch (voteType) { case VoteType.Sub: if (!(data is SubmarineInfo sub)) { return; } msg.Write(sub.EqualityCheckVal); if (sub.EqualityCheckVal == 0) { //sub doesn't exist client-side, use hash to let the server know which one we voted for msg.Write(sub.MD5Hash.Hash); } break; case VoteType.Mode: if (!(data is GameModePreset gameMode)) { return; } msg.Write(gameMode.Identifier); break; case VoteType.EndRound: if (!(data is bool)) { return; } msg.Write((bool)data); break; case VoteType.Kick: if (!(data is Client votedClient)) { return; } msg.Write(votedClient.ID); break; case VoteType.StartRound: if (!(data is bool)) { return; } msg.Write((bool)data); break; case VoteType.PurchaseAndSwitchSub: case VoteType.PurchaseSub: case VoteType.SwitchSub: if (!VoteRunning) { SubmarineInfo voteSub = data as SubmarineInfo; if (voteSub == null) { return; } msg.Write(true); msg.Write(voteSub.Name); } else { if (!(data is int)) { return; } msg.Write(false); msg.Write((int)data); } break; } msg.WritePadBits(); }
protected abstract void SendMsgInternal(DeliveryMethod deliveryMethod, IWriteMessage msg);
public abstract void Send(IWriteMessage msg, DeliveryMethod deliveryMethod);
public void ClientWrite(IWriteMessage msg, object[] extraData = null) { msg.Write((string)extraData[2]); }