From bea523187b09e56f153089a4cd4794a846073579 Mon Sep 17 00:00:00 2001 From: Regalis Date: Fri, 9 Dec 2016 16:45:08 +0200 Subject: [PATCH 1/7] The host can send chat messages, fixed client not being passed to ServerRead methods --- Subsurface/Source/Characters/Character.cs | 2 +- Subsurface/Source/Networking/GameServer.cs | 15 +++++++++++++-- .../NetEntityEvent/NetEntityEventManager.cs | 4 ++-- .../NetEntityEvent/ServerEntityEventManager.cs | 6 +++++- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index f2abe4374..5e3b47dd2 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -1328,7 +1328,7 @@ namespace Barotrauma { isStillCountdown = 15; } - DebugConsole.NewMessage(Convert.ToString(memInput.Count), Color.Lime); + //DebugConsole.NewMessage(Convert.ToString(memInput.Count), Color.Lime); } else { diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index e05cca670..9ecdb1859 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -1200,8 +1200,19 @@ namespace Barotrauma.Networking if (c.Character != traitor) continue; traitorClient = c; break; - } - + } + } + + public override void SendChatMessage(string message, ChatMessageType? type = null) + { + type = ChatMessageType.Default; + + ChatMessage chatMessage = ChatMessage.Create( + gameStarted && myCharacter != null ? myCharacter.Name : name, + message, (ChatMessageType)type, gameStarted ? myCharacter : null); + + + AddChatMessage(chatMessage); } public override void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch) diff --git a/Subsurface/Source/Networking/NetEntityEvent/NetEntityEventManager.cs b/Subsurface/Source/Networking/NetEntityEvent/NetEntityEventManager.cs index 9df9f32b8..3ba54cd6e 100644 --- a/Subsurface/Source/Networking/NetEntityEvent/NetEntityEventManager.cs +++ b/Subsurface/Source/Networking/NetEntityEvent/NetEntityEventManager.cs @@ -52,7 +52,7 @@ namespace Barotrauma.Networking /// /// Read the events from the message, ignoring ones we've already received /// - protected void Read(NetIncomingMessage msg, float sendingTime, ref UInt32 lastReceivedID) + protected void Read(NetIncomingMessage msg, float sendingTime, ref UInt32 lastReceivedID, Client sender = null) { UInt32 firstEventID = msg.ReadUInt32(); int eventCount = msg.ReadByte(); @@ -75,7 +75,7 @@ namespace Barotrauma.Networking { DebugConsole.NewMessage("received msg "+thisEventID, Microsoft.Xna.Framework.Color.Green); lastReceivedID++; - ReadEvent(msg, entity, sendingTime); + ReadEvent(msg, entity, sendingTime, sender); } msg.ReadPadBits(); } diff --git a/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs b/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs index 720c2491c..c0fe0d818 100644 --- a/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs +++ b/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs @@ -12,10 +12,14 @@ namespace Barotrauma.Networking private List events; private UInt32 ID; + + private GameServer server; public ServerEntityEventManager(GameServer server) { events = new List(); + + this.server = server; } public void CreateEvent(IServerSerializable entity, object[] extraData = null) @@ -91,7 +95,7 @@ namespace Barotrauma.Networking public void Read(NetIncomingMessage msg, Client client) { - base.Read(msg, 0.0f, ref client.lastSentEntityEventID); + base.Read(msg, 0.0f, ref client.lastSentEntityEventID, client); } public void Clear() From fa712e010246e9a885efcf3144671d303d06c2fc Mon Sep 17 00:00:00 2001 From: Regalis Date: Fri, 9 Dec 2016 16:56:17 +0200 Subject: [PATCH 2/7] Checking if a client can access an item in the itemcomponent serialization methods --- .../Source/Items/Components/Machines/Pump.cs | 9 +++++++-- .../Source/Items/Components/Machines/Radar.cs | 6 +++++- .../Source/Items/Components/Machines/Reactor.cs | 15 +++++++++++---- .../Source/Items/Components/Machines/Steering.cs | 6 +++++- Subsurface/Source/Items/Item.cs | 5 +++++ 5 files changed, 33 insertions(+), 8 deletions(-) diff --git a/Subsurface/Source/Items/Components/Machines/Pump.cs b/Subsurface/Source/Items/Components/Machines/Pump.cs index 97911bfa5..cf7def032 100644 --- a/Subsurface/Source/Items/Components/Machines/Pump.cs +++ b/Subsurface/Source/Items/Components/Machines/Pump.cs @@ -236,8 +236,13 @@ namespace Barotrauma.Items.Components public void ServerRead(Lidgren.Network.NetIncomingMessage msg, Barotrauma.Networking.Client c) { - FlowPercentage = msg.ReadRangedInteger(-10, 10) * 10.0f; - IsActive = msg.ReadBoolean(); + float flowPercentage = msg.ReadRangedInteger(-10, 10) * 10.0f; + bool isActive = msg.ReadBoolean(); + + if (!item.CanClientAccess(c)) return; + + FlowPercentage = flowPercentage; + IsActive = isActive; } public void ServerWrite(Lidgren.Network.NetBuffer msg, Barotrauma.Networking.Client c, object[] extraData = null) diff --git a/Subsurface/Source/Items/Components/Machines/Radar.cs b/Subsurface/Source/Items/Components/Machines/Radar.cs index c1903dbc3..c7c6a449a 100644 --- a/Subsurface/Source/Items/Components/Machines/Radar.cs +++ b/Subsurface/Source/Items/Components/Machines/Radar.cs @@ -433,7 +433,11 @@ namespace Barotrauma.Items.Components public void ServerRead(Lidgren.Network.NetIncomingMessage msg, Barotrauma.Networking.Client c) { - IsActive = msg.ReadBoolean(); + bool isActive = msg.ReadBoolean(); + + if (!item.CanClientAccess(c)) return; + + IsActive = isActive; isActiveTickBox.Selected = IsActive; item.CreateServerEvent(this); diff --git a/Subsurface/Source/Items/Components/Machines/Reactor.cs b/Subsurface/Source/Items/Components/Machines/Reactor.cs index fff852a7b..6c4a5f286 100644 --- a/Subsurface/Source/Items/Components/Machines/Reactor.cs +++ b/Subsurface/Source/Items/Components/Machines/Reactor.cs @@ -563,11 +563,18 @@ namespace Barotrauma.Items.Components public void ServerRead(NetIncomingMessage msg, Client c) { - AutoTemp = msg.ReadBoolean(); - ShutDownTemp = msg.ReadRangedSingle(0.0f, 10000.0f, 8); + bool autoTemp = msg.ReadBoolean(); + float shutDownTemp = msg.ReadRangedSingle(0.0f, 10000.0f, 8); + float coolingRate = msg.ReadRangedSingle(0.0f, 100.0f, 8); + float fissionRate = msg.ReadRangedSingle(0.0f, 100.0f, 8); - CoolingRate = msg.ReadRangedSingle(0.0f, 100.0f, 8); - FissionRate = msg.ReadRangedSingle(0.0f, 100.0f, 8); + if (!item.CanClientAccess(c)) return; + + AutoTemp = autoTemp; + ShutDownTemp = shutDownTemp; + + CoolingRate = coolingRate; + FissionRate = fissionRate; //need to create a server event to notify all clients of the changed state unsentChanges = true; diff --git a/Subsurface/Source/Items/Components/Machines/Steering.cs b/Subsurface/Source/Items/Components/Machines/Steering.cs index 3b198e660..e34a28b4c 100644 --- a/Subsurface/Source/Items/Components/Machines/Steering.cs +++ b/Subsurface/Source/Items/Components/Machines/Steering.cs @@ -488,7 +488,11 @@ namespace Barotrauma.Items.Components public void ServerRead(Lidgren.Network.NetIncomingMessage msg, Barotrauma.Networking.Client c) { - AutoPilot = msg.ReadBoolean(); + bool autoPilot = msg.ReadBoolean(); + + if (!item.CanClientAccess(c)) return; + + AutoPilot = autoPilot; if (!AutoPilot) { diff --git a/Subsurface/Source/Items/Item.cs b/Subsurface/Source/Items/Item.cs index 4ea7d2100..930cd9810 100644 --- a/Subsurface/Source/Items/Item.cs +++ b/Subsurface/Source/Items/Item.cs @@ -1356,6 +1356,11 @@ namespace Barotrauma return Vector2.Distance(WorldPosition, worldPosition) < PickDistance; } + public bool CanClientAccess(Client c) + { + return c != null && c.Character != null && c.Character.CanAccessItem(this); + } + public bool Pick(Character picker, bool ignoreRequiredItems=false, bool forceSelectKey=false, bool forceActionKey=false) { bool hasRequiredSkills = true; From 63ca7254b2069bba54b3eb7d04570762dae232da Mon Sep 17 00:00:00 2001 From: Regalis Date: Fri, 9 Dec 2016 17:42:52 +0200 Subject: [PATCH 3/7] Fixed steering syncing --- .../Items/Components/Machines/Steering.cs | 117 +++++++++++------- 1 file changed, 75 insertions(+), 42 deletions(-) diff --git a/Subsurface/Source/Items/Components/Machines/Steering.cs b/Subsurface/Source/Items/Components/Machines/Steering.cs index e34a28b4c..4b856330a 100644 --- a/Subsurface/Source/Items/Components/Machines/Steering.cs +++ b/Subsurface/Source/Items/Components/Machines/Steering.cs @@ -488,7 +488,30 @@ namespace Barotrauma.Items.Components public void ServerRead(Lidgren.Network.NetIncomingMessage msg, Barotrauma.Networking.Client c) { - bool autoPilot = msg.ReadBoolean(); + bool autoPilot = msg.ReadBoolean(); + Vector2 newTargetVelocity = targetVelocity; + bool maintainPos = false; + Vector2? newPosToMaintain = null; + bool headingToStart = false; + + if (autoPilot) + { + maintainPos = msg.ReadBoolean(); + if (maintainPos) + { + newPosToMaintain = new Vector2( + msg.ReadFloat(), + msg.ReadFloat()); + } + else + { + headingToStart = msg.ReadBoolean(); + } + } + else + { + newTargetVelocity = new Vector2(msg.ReadFloat(), msg.ReadFloat()); + } if (!item.CanClientAccess(c)) return; @@ -496,31 +519,24 @@ namespace Barotrauma.Items.Components if (!AutoPilot) { - targetVelocity = new Vector2(msg.ReadFloat(), msg.ReadFloat()); + targetVelocity = newTargetVelocity; } else { - bool maintainPos = msg.ReadBoolean(); - if (posToMaintain == null && maintainPos) + + maintainPosTickBox.Selected = newPosToMaintain != null; + posToMaintain = newPosToMaintain; + + if (posToMaintain == null) { - posToMaintain = item.Submarine.WorldPosition; - maintainPosTickBox.Selected = true; + levelStartTickBox.Selected = headingToStart; + levelEndTickBox.Selected = !headingToStart; + UpdatePath(); } else { - posToMaintain = null; - maintainPosTickBox.Selected = false; - bool maintainPoss = msg.ReadBoolean(); - if (maintainPoss) - { - Vector2 newPosToMaintain = new Vector2( - msg.ReadFloat(), - msg.ReadFloat()); - } - else - { - bool headingToStart = msg.ReadBoolean(); - } + levelStartTickBox.Selected = false; + levelEndTickBox.Selected = false; } } @@ -546,47 +562,64 @@ namespace Barotrauma.Items.Components msg.Write(((Vector2)posToMaintain).X); msg.Write(((Vector2)posToMaintain).Y); } + else + { + msg.Write(levelStartTickBox.Selected); + } } } public void ClientRead(Lidgren.Network.NetIncomingMessage msg, float sendingTime) { - AutoPilot = msg.ReadBoolean(); + bool autoPilot = msg.ReadBoolean(); + Vector2 newTargetVelocity = targetVelocity; + bool maintainPos = false; + Vector2? newPosToMaintain = null; + bool headingToStart = false; - if (!AutoPilot) + if (autoPilot) { - targetVelocity = new Vector2(msg.ReadFloat(), msg.ReadFloat()); - } - else - { - bool maintainPos = msg.ReadBoolean(); + maintainPos = msg.ReadBoolean(); if (maintainPos) { - posToMaintain = new Vector2(msg.ReadSingle(), msg.ReadSingle()); - maintainPosTickBox.Selected = true; + newPosToMaintain = new Vector2( + msg.ReadFloat(), + msg.ReadFloat()); } else { - posToMaintain = null; - maintainPosTickBox.Selected = false; + headingToStart = msg.ReadBoolean(); } } - maintainPosTickBox.Selected = posToMaintain != null; - //posToMaintain = newPosToMaintain; - - if (posToMaintain == null && autoPilot) - { - levelStartTickBox.Selected = false;//headingToStart; - levelEndTickBox.Selected = true;//!headingToStart; - - UpdatePath(); - } else { - levelStartTickBox.Selected = false; - levelEndTickBox.Selected = false; + newTargetVelocity = new Vector2(msg.ReadFloat(), msg.ReadFloat()); } + AutoPilot = autoPilot; + + if (!AutoPilot) + { + targetVelocity = newTargetVelocity; + } + else + { + + maintainPosTickBox.Selected = newPosToMaintain != null; + posToMaintain = newPosToMaintain; + + if (posToMaintain == null) + { + levelStartTickBox.Selected = headingToStart; + levelEndTickBox.Selected = !headingToStart; + UpdatePath(); + } + else + { + levelStartTickBox.Selected = false; + levelEndTickBox.Selected = false; + } + } } } } From 9192dad6eaf725ac757d1ca70cff285c2db0ac1c Mon Sep 17 00:00:00 2001 From: Regalis Date: Fri, 9 Dec 2016 20:00:41 +0200 Subject: [PATCH 4/7] EntityEventManagers wait for 1.5*roundtriptime before resending messages (less unnecessary resends), skipping to the next event in a packet if an exception is thrown while reading an event --- .../NetEntityEvent/ClientEntityEventManager.cs | 3 ++- .../NetEntityEvent/NetEntityEventManager.cs | 15 ++++++++++++++- .../NetEntityEvent/ServerEntityEventManager.cs | 3 ++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Subsurface/Source/Networking/NetEntityEvent/ClientEntityEventManager.cs b/Subsurface/Source/Networking/NetEntityEvent/ClientEntityEventManager.cs index cd75c1291..b2c26331b 100644 --- a/Subsurface/Source/Networking/NetEntityEvent/ClientEntityEventManager.cs +++ b/Subsurface/Source/Networking/NetEntityEvent/ClientEntityEventManager.cs @@ -59,7 +59,8 @@ namespace Barotrauma.Networking float lastSent = 0; eventLastSent.TryGetValue(events[i].ID, out lastSent); - if (lastSent > NetTime.Now - serverConnection.AverageRoundtripTime) + //wait for 1.5f * roundtriptime until resending + if (lastSent > NetTime.Now - serverConnection.AverageRoundtripTime * 1.5f) { break; } diff --git a/Subsurface/Source/Networking/NetEntityEvent/NetEntityEventManager.cs b/Subsurface/Source/Networking/NetEntityEvent/NetEntityEventManager.cs index 3ba54cd6e..dd136c14e 100644 --- a/Subsurface/Source/Networking/NetEntityEvent/NetEntityEventManager.cs +++ b/Subsurface/Source/Networking/NetEntityEvent/NetEntityEventManager.cs @@ -73,9 +73,22 @@ namespace Barotrauma.Networking } else { + long msgPosition = msg.Position; + DebugConsole.NewMessage("received msg "+thisEventID, Microsoft.Xna.Framework.Color.Green); lastReceivedID++; - ReadEvent(msg, entity, sendingTime, sender); + try + { + ReadEvent(msg, entity, sendingTime, sender); + } + + catch (Exception e) + { +#if DEBUG + DebugConsole.ThrowError("Failed to read event for entity \""+entity.ToString()+"\"!", e); +#endif + msg.Position = msgPosition + msgLength * 8; + } } msg.ReadPadBits(); } diff --git a/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs b/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs index c0fe0d818..612af11f3 100644 --- a/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs +++ b/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs @@ -58,7 +58,8 @@ namespace Barotrauma.Networking float lastSent = 0; client.entityEventLastSent.TryGetValue(events[i].ID, out lastSent); - if (lastSent > NetTime.Now - client.Connection.AverageRoundtripTime) + //wait for 1.5f * roundtriptime until resending + if (lastSent > NetTime.Now - client.Connection.AverageRoundtripTime * 1.5f) { break; } From 108dddf08222e48a5caa8d6da8418fefd14b6c60 Mon Sep 17 00:00:00 2001 From: Regalis Date: Sat, 10 Dec 2016 13:06:17 +0200 Subject: [PATCH 5/7] Wall damage syncing, inventory serialization methods --- Subsurface/Source/Items/Inventory.cs | 97 ++++++++++++++++++++++++++-- Subsurface/Source/Map/Structure.cs | 10 ++- 2 files changed, 96 insertions(+), 11 deletions(-) diff --git a/Subsurface/Source/Items/Inventory.cs b/Subsurface/Source/Items/Inventory.cs index a07715f69..7b453022a 100644 --- a/Subsurface/Source/Items/Inventory.cs +++ b/Subsurface/Source/Items/Inventory.cs @@ -68,7 +68,7 @@ namespace Barotrauma } } - class Inventory + class Inventory : IServerSerializable, IClientSerializable { public static InventorySlot draggingSlot; public static Item draggingItem; @@ -76,9 +76,7 @@ namespace Barotrauma public static Item doubleClickedItem; public readonly Entity Owner; - - protected float lastUpdate; - + private int slotsPerRow; public int SlotsPerRow @@ -525,6 +523,95 @@ namespace Barotrauma item.Sprite.Draw(spriteBatch, new Vector2(rect.X + rect.Width / 2, rect.Y + rect.Height / 2), item.Color); } - + + public void ClientWrite(Lidgren.Network.NetBuffer msg, object[] extraData = null) + { + ServerWrite(msg, null); + } + + public void ServerRead(Lidgren.Network.NetIncomingMessage msg, Barotrauma.Networking.Client c) + { + List prevItems = new List(Items); + ushort[] newItemIDs = new ushort[capacity]; + + for (int i = 0; i < capacity; i++) + { + newItemIDs[i] = msg.ReadUInt16(); + } + + if (c == null || c.Character == null || !c.Character.CanAccessInventory(this)) + { + return; + } + + for (int i = 0; i < capacity; i++) + { + if (newItemIDs[i] == 0) + { + if (Items[i] != null) Items[i].Drop(); + } + else + { + var item = Entity.FindEntityByID(newItemIDs[i]) as Item; + if (item == null) continue; + + if (GameMain.Server != null) + { + if (!c.Character.CanAccessItem(item)) continue; + } + TryPutItem(item, i, true); + } + } + + foreach (Item item in Items) + { + if (item == null) continue; + if (!prevItems.Contains(item)) + { + GameServer.Log(c.Character + " placed " + item.Name + " in " + Owner, Color.Orange); + } + } + foreach (Item item in prevItems) + { + if (item == null) continue; + if (!Items.Contains(item)) + { + GameServer.Log(c.Character + " removed " + item.Name + " from " + Owner.ToString(), Color.Orange); + } + } + } + + public void ServerWrite(Lidgren.Network.NetBuffer msg, Barotrauma.Networking.Client c, object[] extraData = null) + { + for (int i = 0; i < capacity; i++) + { + msg.Write((ushort)(Items[i] == null ? 0 : Items[i].ID)); + } + } + + public void ClientRead(Lidgren.Network.NetIncomingMessage msg, float sendingTime) + { + ushort[] newItemIDs = new ushort[capacity]; + + for (int i = 0; i < capacity; i++) + { + newItemIDs[i] = msg.ReadUInt16(); + } + + for (int i = 0; i < capacity; i++) + { + if (newItemIDs[i] == 0) + { + if (Items[i] != null) Items[i].Drop(); + } + else + { + var item = Entity.FindEntityByID(newItemIDs[i]) as Item; + if (item == null) continue; + + TryPutItem(item, i, true); + } + } + } } } diff --git a/Subsurface/Source/Map/Structure.cs b/Subsurface/Source/Map/Structure.cs index a07a9256e..eda1f080a 100644 --- a/Subsurface/Source/Map/Structure.cs +++ b/Subsurface/Source/Map/Structure.cs @@ -733,10 +733,10 @@ namespace Barotrauma if (!MathUtils.IsValid(damage)) return; - //if (damage != sections[sectionIndex].damage && Math.Abs(sections[sectionIndex].lastSentDamage - damage) > 5.0f) - //{ - // sections[sectionIndex].lastSentDamage = damage; - //} + if (GameMain.Server != null && damage != sections[sectionIndex].damage) + { + GameMain.Server.CreateEntityEvent(this); + } if (damage < prefab.MaxHealth*0.5f) { @@ -852,8 +852,6 @@ namespace Barotrauma for (int i = 0; i < sections.Length; i++) { msg.WriteRangedSingle(sections[i].damage / Health, 0.0f, 1.0f, 8); - - //sections[i].lastSentDamage = sections[i].damage; } } From 1f454d593e4c5adbce10825996d50692f52ba018 Mon Sep 17 00:00:00 2001 From: Regalis Date: Sat, 10 Dec 2016 16:39:58 +0200 Subject: [PATCH 6/7] Inventory syncing, objHeader is passed to the ClientRead/ServerRead methods so they can determine how to read the msg (is it an inventory update, position, input, etc) --- Subsurface/Source/Characters/Character.cs | 208 ++++++++++-------- Subsurface/Source/Items/CharacterInventory.cs | 34 +-- Subsurface/Source/Items/Components/Door.cs | 2 +- .../Source/Items/Components/ItemContainer.cs | 2 +- .../Source/Items/Components/Machines/Pump.cs | 4 +- .../Source/Items/Components/Machines/Radar.cs | 4 +- .../Items/Components/Machines/Reactor.cs | 4 +- .../Items/Components/Machines/Steering.cs | 4 +- Subsurface/Source/Items/Inventory.cs | 47 ++-- Subsurface/Source/Items/Item.cs | 80 +++++-- Subsurface/Source/Items/ItemInventory.cs | 8 +- Subsurface/Source/Map/Hull.cs | 2 +- Subsurface/Source/Map/Structure.cs | 2 +- Subsurface/Source/Map/Submarine.cs | 2 +- Subsurface/Source/Networking/EntitySpawner.cs | 2 +- Subsurface/Source/Networking/GameClient.cs | 4 +- Subsurface/Source/Networking/GameServer.cs | 2 +- .../Source/Networking/INetSerializable.cs | 4 +- .../ClientEntityEventManager.cs | 4 +- .../NetEntityEvent/NetEntityEvent.cs | 5 + .../ServerEntityEventManager.cs | 4 +- 21 files changed, 262 insertions(+), 166 deletions(-) diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index 5e3b47dd2..3748bd367 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -623,7 +623,7 @@ namespace Barotrauma if (item == null) continue; item.Pick(this, true, true, true); - inventory.TryPutItem(item, i, false); + inventory.TryPutItem(item, i, false, false); } } } @@ -1926,60 +1926,77 @@ namespace Barotrauma { if (GameMain.Server != null) return; - msg.Write((byte)ClientNetObject.CHARACTER_INPUT); - - if (memInput.Count > 60) + if (extraData != null && (NetEntityEvent.Type)extraData[0] == NetEntityEvent.Type.InventoryState) { - memInput.RemoveRange(60,memInput.Count - 60); - memMousePos.RemoveRange(60,memMousePos.Count - 60); + inventory.ClientWrite(msg, extraData); } - - msg.Write(LastNetworkUpdateID); - byte inputCount = Math.Min((byte)memInput.Count, (byte)60); - msg.Write(inputCount); - for (int i = 0; i < inputCount; i++) + else { - msg.Write(memInput[i]); - if ((memInput[i] & 0x40) > 0) + msg.Write((byte)ClientNetObject.CHARACTER_INPUT); + + if (memInput.Count > 60) { - msg.Write(memMousePos[i].X); - msg.Write(memMousePos[i].Y); + memInput.RemoveRange(60,memInput.Count - 60); + memMousePos.RemoveRange(60,memMousePos.Count - 60); + } + + msg.Write(LastNetworkUpdateID); + byte inputCount = Math.Min((byte)memInput.Count, (byte)60); + msg.Write(inputCount); + for (int i = 0; i < inputCount; i++) + { + msg.Write(memInput[i]); + if ((memInput[i] & 0x40) > 0) + { + msg.Write(memMousePos[i].X); + msg.Write(memMousePos[i].Y); + } } } } - public virtual void ServerRead(NetIncomingMessage msg, Client c) + public virtual void ServerRead(ClientNetObject type, NetIncomingMessage msg, Client c) { if (GameMain.Server == null) return; - UInt32 networkUpdateID = msg.ReadUInt32(); - byte inputCount = msg.ReadByte(); + switch (type) + { + case ClientNetObject.CHARACTER_INPUT: + + UInt32 networkUpdateID = msg.ReadUInt32(); + byte inputCount = msg.ReadByte(); + + for (int i = 0; i < inputCount; i++) + { + byte newInput = msg.ReadByte(); + Vector2 newMousePos = Position; + if ((newInput & 0x40) > 0) + { + newMousePos.X = msg.ReadSingle(); + newMousePos.Y = msg.ReadSingle(); + } + if ((i < ((long)networkUpdateID - (long)LastNetworkUpdateID)) && (i < 60)) + { + memInput.Insert(i, newInput); + memMousePos.Insert(i, newMousePos); + } + } - for (int i = 0; i < inputCount; i++) - { - byte newInput = msg.ReadByte(); - Vector2 newMousePos = Position; - if ((newInput & 0x40) > 0) - { - newMousePos.X = msg.ReadSingle(); - newMousePos.Y = msg.ReadSingle(); - } - if ((i < ((long)networkUpdateID - (long)LastNetworkUpdateID)) && (i < 60)) - { - memInput.Insert(i, newInput); - memMousePos.Insert(i, newMousePos); - } - } - - if (networkUpdateID > LastNetworkUpdateID) - { - LastNetworkUpdateID = networkUpdateID; - } - if (memInput.Count > 60) - { - //deleting inputs from the queue here means the server is way behind and data needs to be dropped - //we'll make the server drop down to 30 inputs for good measure - memInput.RemoveRange(30, memInput.Count - 30); - memMousePos.RemoveRange(30, memMousePos.Count - 30); + if (networkUpdateID > LastNetworkUpdateID) + { + LastNetworkUpdateID = networkUpdateID; + } + if (memInput.Count > 60) + { + //deleting inputs from the queue here means the server is way behind and data needs to be dropped + //we'll make the server drop down to 30 inputs for good measure + memInput.RemoveRange(30, memInput.Count - 30); + memMousePos.RemoveRange(30, memMousePos.Count - 30); + } + break; + + case ClientNetObject.ENTITY_STATE: + inventory.ServerRead(type, msg, c); + break; } } @@ -1987,65 +2004,80 @@ namespace Barotrauma { if (GameMain.Server == null) return; - msg.Write(ID); - - if (this == c.Character) + if (extraData != null && (NetEntityEvent.Type)extraData[0] == NetEntityEvent.Type.InventoryState) { - //length of the message - msg.Write((byte)(4+4+4+1)); - msg.Write(true); - msg.Write((UInt32)(LastNetworkUpdateID - memInput.Count)); + inventory.ServerWrite(msg, c, extraData); } else { - //length of the message - msg.Write((byte)(4+4+1)); - msg.Write(false); + msg.Write(ID); + + if (this == c.Character) + { + //length of the message + msg.Write((byte)(4+4+4+1)); + msg.Write(true); + msg.Write((UInt32)(LastNetworkUpdateID - memInput.Count)); + } + else + { + //length of the message + msg.Write((byte)(4+4+1)); + msg.Write(false); + } + + msg.Write(AnimController.TargetDir == Direction.Right); + + msg.Write(SimPosition.X); + msg.Write(SimPosition.Y); + + msg.WritePadBits(); } - - msg.Write(AnimController.TargetDir == Direction.Right); - - msg.Write(SimPosition.X); - msg.Write(SimPosition.Y); - - msg.WritePadBits(); } - public virtual void ClientRead(NetIncomingMessage msg, float sendingTime) + public virtual void ClientRead(ServerNetObject type, NetIncomingMessage msg, float sendingTime) { if (GameMain.Server != null) return; - UInt32 networkUpdateID = 0; - if (msg.ReadBoolean()) + switch (type) { - networkUpdateID = msg.ReadUInt32(); - } + case ServerNetObject.ENTITY_POSITION: + UInt32 networkUpdateID = 0; + if (msg.ReadBoolean()) + { + networkUpdateID = msg.ReadUInt32(); + } - bool facingRight = msg.ReadBoolean(); - Vector2 pos = new Vector2(msg.ReadFloat(), msg.ReadFloat()); + bool facingRight = msg.ReadBoolean(); + Vector2 pos = new Vector2(msg.ReadFloat(), msg.ReadFloat()); - var posInfo = - GameMain.NetworkMember.Character == this ? - new PosInfo(pos, facingRight ? Direction.Right : Direction.Left, networkUpdateID) : - new PosInfo(pos, facingRight ? Direction.Right : Direction.Left, sendingTime); + var posInfo = + GameMain.NetworkMember.Character == this ? + new PosInfo(pos, facingRight ? Direction.Right : Direction.Left, networkUpdateID) : + new PosInfo(pos, facingRight ? Direction.Right : Direction.Left, sendingTime); - int index = 0; - if (GameMain.NetworkMember.Character == this) - { - while (index < memPos.Count && posInfo.ID > memPos[index].ID) - { - index++; - } - } - else - { - while (index < memPos.Count && posInfo.Timestamp > memPos[index].Timestamp) - { - index++; - } - } + int index = 0; + if (GameMain.NetworkMember.Character == this) + { + while (index < memPos.Count && posInfo.ID > memPos[index].ID) + { + index++; + } + } + else + { + while (index < memPos.Count && posInfo.Timestamp > memPos[index].Timestamp) + { + index++; + } + } - memPos.Insert(index, posInfo); + memPos.Insert(index, posInfo); + break; + case ServerNetObject.ENTITY_STATE: + inventory.ClientRead(type, msg, sendingTime); + break; + } } public void WriteSpawnData(NetBuffer msg) diff --git a/Subsurface/Source/Items/CharacterInventory.cs b/Subsurface/Source/Items/CharacterInventory.cs index d26e28d29..08f4d584e 100644 --- a/Subsurface/Source/Items/CharacterInventory.cs +++ b/Subsurface/Source/Items/CharacterInventory.cs @@ -141,7 +141,7 @@ namespace Barotrauma /// /// If there is room, puts the item in the inventory and returns true, otherwise returns false /// - public override bool TryPutItem(Item item, List allowedSlots = null) + public override bool TryPutItem(Item item, List allowedSlots = null, bool createNetworkEvent = true) { if (allowedSlots == null || ! allowedSlots.Any()) return false; @@ -152,7 +152,7 @@ namespace Barotrauma { if (Items[i] != null || limbSlots[i] != InvSlotType.Any) continue; - PutItem(item, i); + PutItem(item, i, true, createNetworkEvent); item.Unequip(character); return true; } @@ -178,7 +178,7 @@ namespace Barotrauma { if (allowedSlot.HasFlag(limbSlots[i]) && Items[i] == null) { - PutItem(item, i, !placed); + PutItem(item, i, !placed, createNetworkEvent); item.Equip(character); placed = true; } @@ -194,7 +194,7 @@ namespace Barotrauma return placed; } - public override bool TryPutItem(Item item, int index, bool allowSwapping) + public override bool TryPutItem(Item item, int index, bool allowSwapping, bool createNetworkEvent = true) { //there's already an item in the slot if (Items[index] != null) @@ -224,8 +224,8 @@ namespace Barotrauma Items[currentIndex] = null; Items[index] = null; //if the item in the slot can be moved to the slot of the moved item - if (TryPutItem(existingItem, currentIndex, false) && - TryPutItem(item, index, false)) + if (TryPutItem(existingItem, currentIndex, false, createNetworkEvent) && + TryPutItem(item, index, false, createNetworkEvent)) { } @@ -235,8 +235,8 @@ namespace Barotrauma Items[index] = null; //swapping the items failed -> move them back to where they were - TryPutItem(item, currentIndex, false); - TryPutItem(existingItem, index, false); + TryPutItem(item, currentIndex, false, createNetworkEvent); + TryPutItem(existingItem, index, false, createNetworkEvent); } } @@ -248,7 +248,7 @@ namespace Barotrauma if (!item.AllowedSlots.Contains(InvSlotType.Any)) return false; if (Items[index] != null) return Items[index] == item; - PutItem(item, index, true); + PutItem(item, index, true, createNetworkEvent); return true; } @@ -274,12 +274,12 @@ namespace Barotrauma if (!slotsFree) return false; - return TryPutItem(item, new List() {placeToSlots}); + return TryPutItem(item, new List() {placeToSlots}, createNetworkEvent); } - protected override void PutItem(Item item, int i, bool removeItem = true) + protected override void PutItem(Item item, int i, bool removeItem = true, bool createNetworkEvent = true) { - base.PutItem(item, i, removeItem); + base.PutItem(item, i, removeItem, createNetworkEvent); CreateSlots(); } @@ -321,7 +321,7 @@ namespace Barotrauma { if (doubleClickedItem.ParentInventory != this) { - TryPutItem(doubleClickedItem, doubleClickedItem.AllowedSlots); + TryPutItem(doubleClickedItem, doubleClickedItem.AllowedSlots, true); } else { @@ -330,24 +330,24 @@ namespace Barotrauma var selectedContainer = character.SelectedConstruction.GetComponent(); if (selectedContainer != null && selectedContainer.Inventory != null) { - selectedContainer.Inventory.TryPutItem(doubleClickedItem, doubleClickedItem.AllowedSlots); + selectedContainer.Inventory.TryPutItem(doubleClickedItem, doubleClickedItem.AllowedSlots, true); } } else if (character.SelectedCharacter != null && character.SelectedCharacter.Inventory != null) { - character.SelectedCharacter.Inventory.TryPutItem(doubleClickedItem, doubleClickedItem.AllowedSlots); + character.SelectedCharacter.Inventory.TryPutItem(doubleClickedItem, doubleClickedItem.AllowedSlots, true); } else //doubleclicked and no other inventory is selected { //not equipped -> attempt to equip if (IsInLimbSlot(doubleClickedItem, InvSlotType.Any)) { - TryPutItem(doubleClickedItem, doubleClickedItem.AllowedSlots.FindAll(i => i != InvSlotType.Any)); + TryPutItem(doubleClickedItem, doubleClickedItem.AllowedSlots.FindAll(i => i != InvSlotType.Any), true); } //equipped -> attempt to unequip else if (doubleClickedItem.AllowedSlots.Contains(InvSlotType.Any)) { - TryPutItem(doubleClickedItem, new List() { InvSlotType.Any }); + TryPutItem(doubleClickedItem, new List() { InvSlotType.Any }, true); } } } diff --git a/Subsurface/Source/Items/Components/Door.cs b/Subsurface/Source/Items/Components/Door.cs index fc2e60560..b26cee5e7 100644 --- a/Subsurface/Source/Items/Components/Door.cs +++ b/Subsurface/Source/Items/Components/Door.cs @@ -505,7 +505,7 @@ namespace Barotrauma.Items.Components msg.WriteRangedSingle(stuck, 0.0f, 100.0f, 8); } - public void ClientRead(Lidgren.Network.NetIncomingMessage msg, float sendingTime) + public void ClientRead(ServerNetObject type, Lidgren.Network.NetIncomingMessage msg, float sendingTime) { SetState(msg.ReadBoolean(), true); Stuck = msg.ReadRangedSingle(0.0f, 100.0f, 8); diff --git a/Subsurface/Source/Items/Components/ItemContainer.cs b/Subsurface/Source/Items/Components/ItemContainer.cs index 8846f70c6..d9d4c4c68 100644 --- a/Subsurface/Source/Items/Components/ItemContainer.cs +++ b/Subsurface/Source/Items/Components/ItemContainer.cs @@ -263,7 +263,7 @@ namespace Barotrauma.Items.Components Item item = MapEntity.FindEntityByID(itemIds[i]) as Item; if (item == null) continue; - Inventory.TryPutItem(item, i, false); + Inventory.TryPutItem(item, i, false, false); } itemIds = null; diff --git a/Subsurface/Source/Items/Components/Machines/Pump.cs b/Subsurface/Source/Items/Components/Machines/Pump.cs index cf7def032..9f1292aea 100644 --- a/Subsurface/Source/Items/Components/Machines/Pump.cs +++ b/Subsurface/Source/Items/Components/Machines/Pump.cs @@ -234,7 +234,7 @@ namespace Barotrauma.Items.Components msg.Write(IsActive); } - public void ServerRead(Lidgren.Network.NetIncomingMessage msg, Barotrauma.Networking.Client c) + public void ServerRead(ClientNetObject type, Lidgren.Network.NetIncomingMessage msg, Barotrauma.Networking.Client c) { float flowPercentage = msg.ReadRangedInteger(-10, 10) * 10.0f; bool isActive = msg.ReadBoolean(); @@ -252,7 +252,7 @@ namespace Barotrauma.Items.Components msg.Write(IsActive); } - public void ClientRead(Lidgren.Network.NetIncomingMessage msg, float sendingTime) + public void ClientRead(ServerNetObject type, Lidgren.Network.NetIncomingMessage msg, float sendingTime) { FlowPercentage = msg.ReadRangedInteger(-10, 10) * 10.0f; IsActive = msg.ReadBoolean(); diff --git a/Subsurface/Source/Items/Components/Machines/Radar.cs b/Subsurface/Source/Items/Components/Machines/Radar.cs index c7c6a449a..ba1ab4797 100644 --- a/Subsurface/Source/Items/Components/Machines/Radar.cs +++ b/Subsurface/Source/Items/Components/Machines/Radar.cs @@ -431,7 +431,7 @@ namespace Barotrauma.Items.Components msg.Write(IsActive); } - public void ServerRead(Lidgren.Network.NetIncomingMessage msg, Barotrauma.Networking.Client c) + public void ServerRead(ClientNetObject type, Lidgren.Network.NetIncomingMessage msg, Barotrauma.Networking.Client c) { bool isActive = msg.ReadBoolean(); @@ -448,7 +448,7 @@ namespace Barotrauma.Items.Components msg.Write(IsActive); } - public void ClientRead(Lidgren.Network.NetIncomingMessage msg, float sendingTime) + public void ClientRead(ServerNetObject type, Lidgren.Network.NetIncomingMessage msg, float sendingTime) { IsActive = msg.ReadBoolean(); isActiveTickBox.Selected = IsActive; diff --git a/Subsurface/Source/Items/Components/Machines/Reactor.cs b/Subsurface/Source/Items/Components/Machines/Reactor.cs index 6c4a5f286..e3a33ffe8 100644 --- a/Subsurface/Source/Items/Components/Machines/Reactor.cs +++ b/Subsurface/Source/Items/Components/Machines/Reactor.cs @@ -561,7 +561,7 @@ namespace Barotrauma.Items.Components msg.WriteRangedSingle(fissionRate, 0.0f, 100.0f, 8); } - public void ServerRead(NetIncomingMessage msg, Client c) + public void ServerRead(ClientNetObject type, NetIncomingMessage msg, Client c) { bool autoTemp = msg.ReadBoolean(); float shutDownTemp = msg.ReadRangedSingle(0.0f, 10000.0f, 8); @@ -591,7 +591,7 @@ namespace Barotrauma.Items.Components msg.WriteRangedSingle(fissionRate, 0.0f, 100.0f, 8); } - public void ClientRead(NetIncomingMessage msg, float sendingTime) + public void ClientRead(ServerNetObject type, NetIncomingMessage msg, float sendingTime) { Temperature = msg.ReadRangedSingle(0.0f, 10000.0f, 16); diff --git a/Subsurface/Source/Items/Components/Machines/Steering.cs b/Subsurface/Source/Items/Components/Machines/Steering.cs index 4b856330a..f0a685afa 100644 --- a/Subsurface/Source/Items/Components/Machines/Steering.cs +++ b/Subsurface/Source/Items/Components/Machines/Steering.cs @@ -486,7 +486,7 @@ namespace Barotrauma.Items.Components } } - public void ServerRead(Lidgren.Network.NetIncomingMessage msg, Barotrauma.Networking.Client c) + public void ServerRead(ClientNetObject type, Lidgren.Network.NetIncomingMessage msg, Barotrauma.Networking.Client c) { bool autoPilot = msg.ReadBoolean(); Vector2 newTargetVelocity = targetVelocity; @@ -569,7 +569,7 @@ namespace Barotrauma.Items.Components } } - public void ClientRead(Lidgren.Network.NetIncomingMessage msg, float sendingTime) + public void ClientRead(ServerNetObject type, Lidgren.Network.NetIncomingMessage msg, float sendingTime) { bool autoPilot = msg.ReadBoolean(); Vector2 newTargetVelocity = targetVelocity; diff --git a/Subsurface/Source/Items/Inventory.cs b/Subsurface/Source/Items/Inventory.cs index 7b453022a..e2d6b85b3 100644 --- a/Subsurface/Source/Items/Inventory.cs +++ b/Subsurface/Source/Items/Inventory.cs @@ -172,31 +172,31 @@ namespace Barotrauma /// /// If there is room, puts the item in the inventory and returns true, otherwise returns false /// - public virtual bool TryPutItem(Item item, List allowedSlots = null) + public virtual bool TryPutItem(Item item, List allowedSlots = null, bool createNetworkEvent = true) { int slot = FindAllowedSlot(item); if (slot < 0) return false; - PutItem(item, slot); + PutItem(item, slot, true, createNetworkEvent); return true; } - public virtual bool TryPutItem(Item item, int i, bool allowSwapping) + public virtual bool TryPutItem(Item item, int i, bool allowSwapping, bool createNetworkEvent = true) { if (Owner == null) return false; if (CanBePut(item,i)) { - PutItem(item, i); + PutItem(item, i, true, createNetworkEvent); return true; } else { - if (slots != null) slots[i].ShowBorderHighlight(Color.Red, 0.1f, 0.9f); + if (slots != null && createNetworkEvent) slots[i].ShowBorderHighlight(Color.Red, 0.1f, 0.9f); return false; } } - protected virtual void PutItem(Item item, int i, bool removeItem = true) + protected virtual void PutItem(Item item, int i, bool removeItem = true, bool createNetworkEvent = true) { if (Owner == null) return; @@ -215,6 +215,23 @@ namespace Barotrauma { item.body.Enabled = false; } + + if (createNetworkEvent) + { + CreateNetworkEvent(); + } + } + + private void CreateNetworkEvent() + { + if (GameMain.Server != null) + { + GameMain.Server.CreateEntityEvent(Owner as IServerSerializable, new object[] { NetEntityEvent.Type.InventoryState }); + } + else if (GameMain.Client != null) + { + GameMain.Client.CreateEntityEvent(Owner as IClientSerializable, new object[] { NetEntityEvent.Type.InventoryState }); + } } public Item FindItem(string itemName) @@ -232,8 +249,9 @@ namespace Barotrauma for (int n = 0; n < capacity; n++) { if (Items[n] != item) continue; + Items[n] = null; - item.ParentInventory = null; + item.ParentInventory = null; } } @@ -285,10 +303,7 @@ namespace Barotrauma { if (!PlayerInput.LeftButtonHeld()) { - if (Owner != null) - { - - } + CreateNetworkEvent(); DropItem(draggingItem); } @@ -529,7 +544,7 @@ namespace Barotrauma ServerWrite(msg, null); } - public void ServerRead(Lidgren.Network.NetIncomingMessage msg, Barotrauma.Networking.Client c) + public void ServerRead(ClientNetObject type, Lidgren.Network.NetIncomingMessage msg, Barotrauma.Networking.Client c) { List prevItems = new List(Items); ushort[] newItemIDs = new ushort[capacity]; @@ -559,10 +574,12 @@ namespace Barotrauma { if (!c.Character.CanAccessItem(item)) continue; } - TryPutItem(item, i, true); + TryPutItem(item, i, true, false); } } + GameMain.Server.CreateEntityEvent(Owner as IServerSerializable, new object[] { NetEntityEvent.Type.InventoryState }); + foreach (Item item in Items) { if (item == null) continue; @@ -589,7 +606,7 @@ namespace Barotrauma } } - public void ClientRead(Lidgren.Network.NetIncomingMessage msg, float sendingTime) + public void ClientRead(ServerNetObject type, Lidgren.Network.NetIncomingMessage msg, float sendingTime) { ushort[] newItemIDs = new ushort[capacity]; @@ -609,7 +626,7 @@ namespace Barotrauma var item = Entity.FindEntityByID(newItemIDs[i]) as Item; if (item == null) continue; - TryPutItem(item, i, true); + TryPutItem(item, i, true, false); } } } diff --git a/Subsurface/Source/Items/Item.cs b/Subsurface/Source/Items/Item.cs index 930cd9810..1742e6832 100644 --- a/Subsurface/Source/Items/Item.cs +++ b/Subsurface/Source/Items/Item.cs @@ -1638,36 +1638,78 @@ namespace Barotrauma public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null) { - if (extraData == null) return; + if (extraData == null || extraData.Length == 0 || !(extraData[0] is NetEntityEvent.Type)) + { + return; + } + else if ((NetEntityEvent.Type)extraData[0] == NetEntityEvent.Type.ComponentState) + { + msg.Write(true); - int componentIndex = (int)extraData[0]; - msg.Write((byte)componentIndex); + int componentIndex = (int)extraData[1]; + msg.Write((byte)componentIndex); - (components[componentIndex] as IServerSerializable).ServerWrite(msg, c, extraData); + (components[componentIndex] as IServerSerializable).ServerWrite(msg, c, extraData); + } + else if ((NetEntityEvent.Type)extraData[0] == NetEntityEvent.Type.InventoryState) + { + msg.Write(false); + + ownInventory.ServerWrite(msg, c, extraData); + } } - public void ClientRead(NetIncomingMessage msg, float sendingTime) + public void ClientRead(ServerNetObject type, NetIncomingMessage msg, float sendingTime) { - int componentIndex = msg.ReadByte(); + bool isComponentUpdate = msg.ReadBoolean(); - (components[componentIndex] as IServerSerializable).ClientRead(msg, sendingTime); + if (isComponentUpdate) + { + int componentIndex = msg.ReadByte(); + (components[componentIndex] as IServerSerializable).ClientRead(type, msg, sendingTime); + } + else + { + ownInventory.ClientRead(type, msg, sendingTime); + } } public void ClientWrite(NetBuffer msg, object[] extraData = null) { - if (extraData == null) return; + if (extraData == null || extraData.Length == 0 || !(extraData[0] is NetEntityEvent.Type)) + { + return; + } + else if ((NetEntityEvent.Type)extraData[0] == NetEntityEvent.Type.ComponentState) + { + msg.Write(true); - int componentIndex = (int)extraData[0]; - msg.Write((byte)componentIndex); + int componentIndex = (int)extraData[1]; + msg.Write((byte)componentIndex); - (components[componentIndex] as IClientSerializable).ClientWrite(msg, extraData); + (components[componentIndex] as IClientSerializable).ClientWrite(msg, extraData); + } + else if ((NetEntityEvent.Type)extraData[0] == NetEntityEvent.Type.InventoryState) + { + msg.Write(false); + + ownInventory.ClientWrite(msg, extraData); + } } - public void ServerRead(NetIncomingMessage msg, Client c) + public void ServerRead(ClientNetObject type, NetIncomingMessage msg, Client c) { - int componentIndex = msg.ReadByte(); - - (components[componentIndex] as IClientSerializable).ServerRead(msg, c); + bool isComponentUpdate = msg.ReadBoolean(); + + if (isComponentUpdate) + { + int componentIndex = msg.ReadByte(); + (components[componentIndex] as IClientSerializable).ServerRead(type, msg, c); + } + else + { + ownInventory.ServerRead(type, msg, c); + } } public void WriteSpawnData(NetBuffer msg) @@ -1773,11 +1815,11 @@ namespace Barotrauma if (inventory != null) { if (inventorySlotIndex >= 0 && inventorySlotIndex < 255 && - inventory.TryPutItem(item, inventorySlotIndex, false)) + inventory.TryPutItem(item, inventorySlotIndex, false, false)) { return null; } - inventory.TryPutItem(item, item.AllowedSlots); + inventory.TryPutItem(item, item.AllowedSlots, false); } return item; @@ -1896,7 +1938,7 @@ namespace Barotrauma if (GameMain.Server == null) return; int index = components.IndexOf(ic); - GameMain.Server.CreateEntityEvent(this, new object[] { index }); + GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.ComponentState, index }); } public void CreateClientEvent(T ic) where T : ItemComponent, IClientSerializable @@ -1904,7 +1946,7 @@ namespace Barotrauma if (GameMain.Client == null) return; int index = components.IndexOf(ic); - GameMain.Client.CreateEntityEvent(this, new object[] { index }); + GameMain.Client.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.ComponentState, index }); } public override void ShallowRemove() diff --git a/Subsurface/Source/Items/ItemInventory.cs b/Subsurface/Source/Items/ItemInventory.cs index 18e8a1cde..a583dee83 100644 --- a/Subsurface/Source/Items/ItemInventory.cs +++ b/Subsurface/Source/Items/ItemInventory.cs @@ -45,9 +45,9 @@ namespace Barotrauma } - public override bool TryPutItem(Item item, System.Collections.Generic.List allowedSlots = null) + public override bool TryPutItem(Item item, System.Collections.Generic.List allowedSlots = null, bool createNetworkEvent = true) { - bool wasPut = base.TryPutItem(item, allowedSlots); + bool wasPut = base.TryPutItem(item, allowedSlots, createNetworkEvent); if (wasPut) { @@ -66,9 +66,9 @@ namespace Barotrauma return wasPut; } - public override bool TryPutItem(Item item, int i, bool allowSwapping) + public override bool TryPutItem(Item item, int i, bool allowSwapping, bool createNetworkEvent = true) { - bool wasPut = base.TryPutItem(item, i, allowSwapping); + bool wasPut = base.TryPutItem(item, i, allowSwapping, createNetworkEvent); if (wasPut) { diff --git a/Subsurface/Source/Map/Hull.cs b/Subsurface/Source/Map/Hull.cs index 7aa4533c8..d68135eaf 100644 --- a/Subsurface/Source/Map/Hull.cs +++ b/Subsurface/Source/Map/Hull.cs @@ -843,7 +843,7 @@ namespace Barotrauma lastSentOxygen = OxygenPercentage; } - public void ClientRead(NetIncomingMessage message, float sendingTime) + public void ClientRead(ServerNetObject type, NetIncomingMessage message, float sendingTime) { Volume = message.ReadRangedSingle(0.0f, 1.5f, 8) * FullVolume; OxygenPercentage = message.ReadRangedSingle(0.0f, 100.0f, 8); diff --git a/Subsurface/Source/Map/Structure.cs b/Subsurface/Source/Map/Structure.cs index eda1f080a..8f35e98ab 100644 --- a/Subsurface/Source/Map/Structure.cs +++ b/Subsurface/Source/Map/Structure.cs @@ -855,7 +855,7 @@ namespace Barotrauma } } - public void ClientRead(NetIncomingMessage msg, float sendingTime) + public void ClientRead(ServerNetObject type, NetIncomingMessage msg, float sendingTime) { for (int i = 0; i < sections.Count(); i++) { diff --git a/Subsurface/Source/Map/Submarine.cs b/Subsurface/Source/Map/Submarine.cs index 359043c35..060612c36 100644 --- a/Subsurface/Source/Map/Submarine.cs +++ b/Subsurface/Source/Map/Submarine.cs @@ -1176,7 +1176,7 @@ namespace Barotrauma msg.Write(PhysicsBody.SimPosition.Y); } - public void ClientRead(NetIncomingMessage msg, float sendingTime) + public void ClientRead(ServerNetObject type, NetIncomingMessage msg, float sendingTime) { var newTargetPosition = new Vector2( msg.ReadFloat(), diff --git a/Subsurface/Source/Networking/EntitySpawner.cs b/Subsurface/Source/Networking/EntitySpawner.cs index 2e0baeca6..3eb6a8d35 100644 --- a/Subsurface/Source/Networking/EntitySpawner.cs +++ b/Subsurface/Source/Networking/EntitySpawner.cs @@ -186,7 +186,7 @@ namespace Barotrauma } } - public void ClientRead(Lidgren.Network.NetIncomingMessage message, float sendingTime) + public void ClientRead(ServerNetObject type, Lidgren.Network.NetIncomingMessage message, float sendingTime) { if (GameMain.Server != null) return; diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index 5c5844c19..820bcc16e 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -724,7 +724,7 @@ namespace Barotrauma.Networking } else { - entity.ClientRead(inc, sendingTime); + entity.ClientRead(objHeader, inc, sendingTime); } inc.ReadPadBits(); @@ -736,7 +736,7 @@ namespace Barotrauma.Networking ChatMessage.ClientRead(inc); break; case ServerNetObject.ENTITY_SPAWN: - Item.Spawner.ClientRead(inc, sendingTime); + Item.Spawner.ClientRead(objHeader, inc, sendingTime); inc.ReadPadBits(); break; default: diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index 9ecdb1859..3a2860e97 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -638,7 +638,7 @@ namespace Barotrauma.Networking case ClientNetObject.CHARACTER_INPUT: if (c.Character != null && !c.Character.IsDead && !c.Character.IsUnconscious) { - c.Character.ServerRead(inc, c); + c.Character.ServerRead(objHeader, inc, c); } break; case ClientNetObject.ENTITY_STATE: diff --git a/Subsurface/Source/Networking/INetSerializable.cs b/Subsurface/Source/Networking/INetSerializable.cs index f54d34854..cecc8c72d 100644 --- a/Subsurface/Source/Networking/INetSerializable.cs +++ b/Subsurface/Source/Networking/INetSerializable.cs @@ -11,7 +11,7 @@ namespace Barotrauma.Networking interface IClientSerializable : INetSerializable { void ClientWrite(NetBuffer msg, object[] extraData = null); - void ServerRead(NetIncomingMessage msg, Client c); + void ServerRead(ClientNetObject type, NetIncomingMessage msg, Client c); } /// @@ -20,6 +20,6 @@ namespace Barotrauma.Networking interface IServerSerializable : INetSerializable { void ServerWrite(NetBuffer msg, Client c, object[] extraData = null); - void ClientRead(NetIncomingMessage msg, float sendingTime); + void ClientRead(ServerNetObject type, NetIncomingMessage msg, float sendingTime); } } diff --git a/Subsurface/Source/Networking/NetEntityEvent/ClientEntityEventManager.cs b/Subsurface/Source/Networking/NetEntityEvent/ClientEntityEventManager.cs index b2c26331b..a6ef737b3 100644 --- a/Subsurface/Source/Networking/NetEntityEvent/ClientEntityEventManager.cs +++ b/Subsurface/Source/Networking/NetEntityEvent/ClientEntityEventManager.cs @@ -65,7 +65,7 @@ namespace Barotrauma.Networking break; } - eventsToSync.Add(events[i]); + eventsToSync.Insert(0, events[i]); } if (eventsToSync.Count == 0) return; @@ -96,7 +96,7 @@ namespace Barotrauma.Networking var serverEntity = entity as IServerSerializable; if (serverEntity == null) return; - serverEntity.ClientRead(buffer, sendingTime); + serverEntity.ClientRead(ServerNetObject.ENTITY_STATE, buffer, sendingTime); } public void Clear() diff --git a/Subsurface/Source/Networking/NetEntityEvent/NetEntityEvent.cs b/Subsurface/Source/Networking/NetEntityEvent/NetEntityEvent.cs index 0abc69fda..6e5a43e86 100644 --- a/Subsurface/Source/Networking/NetEntityEvent/NetEntityEvent.cs +++ b/Subsurface/Source/Networking/NetEntityEvent/NetEntityEvent.cs @@ -9,6 +9,11 @@ namespace Barotrauma.Networking { abstract class NetEntityEvent { + public enum Type + { + Default, ComponentState, InventoryState + } + public readonly Entity Entity; public readonly UInt32 ID; diff --git a/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs b/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs index 612af11f3..326aa71ae 100644 --- a/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs +++ b/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs @@ -24,7 +24,7 @@ namespace Barotrauma.Networking public void CreateEvent(IServerSerializable entity, object[] extraData = null) { - if (!(entity is Entity)) + if (entity == null || !(entity is Entity)) { DebugConsole.ThrowError("Can't create an entity event for " + entity + "!"); return; @@ -91,7 +91,7 @@ namespace Barotrauma.Networking var clientEntity = entity as IClientSerializable; if (clientEntity == null) return; - clientEntity.ServerRead(buffer, sender); + clientEntity.ServerRead(ClientNetObject.ENTITY_STATE, buffer, sender); } public void Read(NetIncomingMessage msg, Client client) From 3411448ae8509cb545ce8723e2c976c42b207c0c Mon Sep 17 00:00:00 2001 From: Regalis Date: Sat, 10 Dec 2016 19:53:35 +0200 Subject: [PATCH 7/7] Submarine position syncing improvements --- Subsurface/Source/Map/Submarine.cs | 7 +++++ Subsurface/Source/Map/SubmarineBody.cs | 28 +++++++------------ .../NetEntityEvent/NetEntityEventManager.cs | 9 +++++- Subsurface/Source/Physics/PhysicsBody.cs | 14 ++++++++-- 4 files changed, 36 insertions(+), 22 deletions(-) diff --git a/Subsurface/Source/Map/Submarine.cs b/Subsurface/Source/Map/Submarine.cs index 060612c36..213c30924 100644 --- a/Subsurface/Source/Map/Submarine.cs +++ b/Subsurface/Source/Map/Submarine.cs @@ -1194,6 +1194,13 @@ namespace Barotrauma index++; } + //position with the same timestamp already in the buffer (duplicate packet?) + // -> no need to add again + if (index < subBody.MemPos.Count && sendingTime == subBody.MemPos[index].Timestamp) + { + return; + } + subBody.MemPos.Insert(index, new PosInfo(newTargetPosition, Direction.Right, sendingTime)); } } diff --git a/Subsurface/Source/Map/SubmarineBody.cs b/Subsurface/Source/Map/SubmarineBody.cs index c9c904ef9..6a0f6906b 100644 --- a/Subsurface/Source/Map/SubmarineBody.cs +++ b/Subsurface/Source/Map/SubmarineBody.cs @@ -35,7 +35,7 @@ namespace Barotrauma public readonly PhysicsBody Body; - List memPos = new List(); + private List memPos = new List(); public Rectangle Borders { @@ -186,22 +186,7 @@ namespace Barotrauma { if (GameMain.Client != null) { - //if (memPos.Count > 1 && Vector2.Distance(memPos[1].Position, Body.SimPosition) > 5.0f) - //{ - // Vector2 moveAmount = ConvertUnits.ToDisplayUnits(memPos[1].Position - Body.SimPosition); - - // ForceTranslate(moveAmount); - // DisplaceCharacters(moveAmount); - - // foreach (Submarine sub in submarine.DockedTo) - // { - // sub.SubBody.ForceTranslate(moveAmount); - // sub.SubBody.DisplaceCharacters(moveAmount); - // } - - // memPos.RemoveRange(0, 2); - //} - //else + if (memPos.Count == 0) return; Vector2 newVelocity = Body.LinearVelocity; Vector2 newPosition = Body.SimPosition; @@ -212,10 +197,17 @@ namespace Barotrauma List subsToMove = new List() { this.submarine }; subsToMove.AddRange(submarine.DockedTo); + foreach (Submarine dockedSub in submarine.DockedTo) + { + //clear the position buffer of the docked sub to prevent unnecessary position corrections + dockedSub.SubBody.memPos.Clear(); + subsToMove.Add(dockedSub); + } + Submarine closestSub = null; if (Character.Controlled == null) { - closestSub= Submarine.GetClosest(GameMain.GameScreen.Cam.WorldViewCenter); + closestSub = Submarine.GetClosest(GameMain.GameScreen.Cam.WorldViewCenter); } else { diff --git a/Subsurface/Source/Networking/NetEntityEvent/NetEntityEventManager.cs b/Subsurface/Source/Networking/NetEntityEvent/NetEntityEventManager.cs index dd136c14e..04aba20e6 100644 --- a/Subsurface/Source/Networking/NetEntityEvent/NetEntityEventManager.cs +++ b/Subsurface/Source/Networking/NetEntityEvent/NetEntityEventManager.cs @@ -68,7 +68,14 @@ namespace Barotrauma.Networking //skip the event if we've already received it or if the entity isn't found if (thisEventID != lastReceivedID + 1 || entity == null) { - DebugConsole.NewMessage("received msg "+thisEventID, Microsoft.Xna.Framework.Color.Red); + if (thisEventID != lastReceivedID + 1) + { + DebugConsole.NewMessage("received msg "+thisEventID, Microsoft.Xna.Framework.Color.Red); + } + else if (entity == null) + { + DebugConsole.NewMessage("received msg " + thisEventID+", entity "+entityID+" not found", Microsoft.Xna.Framework.Color.Red); + } msg.Position += msgLength * 8; } else diff --git a/Subsurface/Source/Physics/PhysicsBody.cs b/Subsurface/Source/Physics/PhysicsBody.cs index dbde6a2db..495b12425 100644 --- a/Subsurface/Source/Physics/PhysicsBody.cs +++ b/Subsurface/Source/Physics/PhysicsBody.cs @@ -511,10 +511,18 @@ namespace Barotrauma float speedMultiplier = 0.9f + (float)Math.Pow((positionBuffer.Count - 2) / 5.0f, 2.0f); netInterpolationState += (deltaTime * speedMultiplier) / (next.Timestamp - prev.Timestamp); - newPosition = Vector2.Lerp(prev.Position, next.Position, netInterpolationState); - //override the targetMovement to make the character play the walking/running animation - newVelocity = (next.Position - prev.Position) / (next.Timestamp - prev.Timestamp); + newPosition = Vector2.Lerp(prev.Position, next.Position, Math.Min(netInterpolationState, 1.0f)); + + if (next.Timestamp == prev.Timestamp) + { + newVelocity = Vector2.Zero; + } + else + { + //override the targetMovement to make the character play the walking/running animation + newVelocity = (next.Position - prev.Position) / (next.Timestamp - prev.Timestamp); + } } else {