From ac3539da63247b871303da9af963e095949e8421 Mon Sep 17 00:00:00 2001 From: Regalis Date: Wed, 12 Oct 2016 18:29:44 +0300 Subject: [PATCH] Item spawn syncing --- Subsurface/Source/Items/ItemSpawner.cs | 77 +++++++++++++++---- Subsurface/Source/Networking/Client.cs | 7 ++ Subsurface/Source/Networking/GameClient.cs | 4 + Subsurface/Source/Networking/GameServer.cs | 57 +++++++------- Subsurface/Source/Networking/NetworkMember.cs | 4 +- 5 files changed, 101 insertions(+), 48 deletions(-) diff --git a/Subsurface/Source/Items/ItemSpawner.cs b/Subsurface/Source/Items/ItemSpawner.cs index 6d94aa17c..8924029d8 100644 --- a/Subsurface/Source/Items/ItemSpawner.cs +++ b/Subsurface/Source/Items/ItemSpawner.cs @@ -1,11 +1,19 @@ using Microsoft.Xna.Framework; using System.Collections.Generic; using System.Linq; +using Barotrauma.Networking; +using System; namespace Barotrauma { - class ItemSpawner + class ItemSpawner : IServerSerializable { + public UInt32 NetStateID + { + get; + private set; + } + class ItemSpawnInfo { public readonly ItemPrefab Prefab; @@ -99,15 +107,30 @@ namespace Barotrauma //if (GameMain.Server != null) GameMain.Server.SendItemSpawnMessage(items); } + public void AddToSpawnedList(List items) + { + foreach (Item item in items) + { + AddToSpawnedList(item); + } + } + public void AddToSpawnedList(Item item) { spawnItems.Add(item); + NetStateID = (UInt32)spawnItems.Count; } - public void FillNetworkData(Lidgren.Network.NetBuffer message, List items) + public void ServerWrite(Lidgren.Network.NetOutgoingMessage message, Client client) { - message.Write((byte)items.Count); + if (GameMain.Server == null) return; + //skip items that the client already knows about + List items = spawnItems.Skip((int)client.lastRecvItemSpawnID).ToList(); + + message.Write((UInt32)spawnItems.Count); + + message.Write((byte)items.Count); for (int i = 0; i < items.Count; i++) { message.Write(items[i].Prefab.Name); @@ -128,7 +151,7 @@ namespace Barotrauma int index = items[i].ParentInventory.FindIndex(items[i]); message.Write(index < 0 ? (byte)255 : (byte)index); } - + if (items[i].Name == "ID Card") { message.Write(items[i].Tags); @@ -136,18 +159,22 @@ namespace Barotrauma } } - public void ReadNetworkData(Lidgren.Network.NetBuffer message) + public void ClientRead(Lidgren.Network.NetIncomingMessage message) { + if (GameMain.Server != null) return; + + UInt32 ID = message.ReadUInt32(); + var itemCount = message.ReadByte(); for (int i = 0; i < itemCount; i++) { string itemName = message.ReadString(); ushort itemId = message.ReadUInt16(); - Vector2 pos = Vector2.Zero; - Submarine sub = null; ushort inventoryId = message.ReadUInt16(); + Vector2 pos = Vector2.Zero; + Submarine sub = null; int inventorySlotIndex = -1; if (inventoryId > 0) @@ -157,6 +184,7 @@ namespace Barotrauma else { pos = new Vector2(message.ReadSingle(), message.ReadSingle()); + ushort subID = message.ReadUInt16(); if (subID > 0) { @@ -168,7 +196,11 @@ namespace Barotrauma if (itemName == "ID Card") { tags = message.ReadString(); - } + } + + if (ID - itemCount + i < NetStateID) continue; + + //---------------------------------------- var prefab = MapEntityPrefab.list.Find(me => me.Name == itemName); if (prefab == null) continue; @@ -215,19 +247,28 @@ namespace Barotrauma } inventory.TryPutItem(item, item.AllowedSlots); } - } + + NetStateID = Math.Max(ID, NetStateID); } public void Clear() { + NetStateID = 0; + spawnQueue.Clear(); spawnItems.Clear(); } } - class ItemRemover + class ItemRemover : IServerSerializable { + public UInt32 NetStateID + { + get; + private set; + } + private readonly Queue removeQueue; public List removedItems = new List(); @@ -267,16 +308,16 @@ namespace Barotrauma //if (GameMain.Server != null) GameMain.Server.SendItemRemoveMessage(items); } - public void FillNetworkData(Lidgren.Network.NetBuffer message, List items) + public void ServerWrite(Lidgren.Network.NetOutgoingMessage message, Client client) { - message.Write((byte)items.Count); - foreach (Item item in items) - { - message.Write(item.ID); - } + //message.Write((byte)items.Count); + //foreach (Item item in items) + //{ + // message.Write(item.ID); + //} } - public void ReadNetworkData(Lidgren.Network.NetBuffer message) + public void ClientRead(Lidgren.Network.NetIncomingMessage message) { var itemCount = message.ReadByte(); for (int i = 0; i ChatMessages = new List(); public float ChatSpamSpeed; public float ChatSpamTimer; @@ -58,6 +62,9 @@ namespace Barotrauma.Networking { lastSentChatMsgID = 0; lastRecvChatMsgID = ChatMessage.LastID; + + lastRecvItemSpawnID = 0; + lastRecvItemRemoveID = 0; } public int KickVoteCount diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index e12aaa02b..78ed11e19 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -704,6 +704,9 @@ namespace Barotrauma.Networking case ServerNetObject.CHAT_MESSAGE: ChatMessage.ClientRead(inc); break; + case ServerNetObject.ITEM_SPAWN: + Item.Spawner.ClientRead(inc); + break; } } } @@ -738,6 +741,7 @@ namespace Barotrauma.Networking outmsg.Write((byte)ClientNetObject.SYNC_IDS); outmsg.Write(GameMain.NetLobbyScreen.LastUpdateID); outmsg.Write(ChatMessage.LastID); + outmsg.Write(Item.Spawner.NetStateID); ChatMessage removeMsg; while ((removeMsg = chatMsgQueue.Find(cMsg => cMsg.NetStateID <= lastSentChatMsgID)) != null) { diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index a65996c24..5c0a436d7 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -568,16 +568,8 @@ namespace Barotrauma.Networking { case ClientNetObject.SYNC_IDS: //TODO: might want to use a clever class for this - UInt32 lastGeneralUpdID = inc.ReadUInt32(); - if (lastGeneralUpdID > c.lastRecvGeneralUpdate) - { - c.lastRecvGeneralUpdate = lastGeneralUpdID; - } - UInt32 lastChatID = inc.ReadUInt32(); - if (lastChatID > c.lastRecvChatMsgID) - { - c.lastRecvChatMsgID = lastChatID; - } + c.lastRecvGeneralUpdate = Math.Max(c.lastRecvGeneralUpdate, inc.ReadUInt32()); + c.lastRecvChatMsgID = Math.Max(c.lastRecvChatMsgID, inc.ReadUInt32()); break; case ClientNetObject.CHAT_MESSAGE: ChatMessage.ServerRead(inc, c); @@ -606,16 +598,11 @@ namespace Barotrauma.Networking { case ClientNetObject.SYNC_IDS: //TODO: might want to use a clever class for this - UInt32 lastGeneralUpdID = inc.ReadUInt32(); - if (lastGeneralUpdID > c.lastRecvGeneralUpdate) - { - c.lastRecvGeneralUpdate = lastGeneralUpdID; - } - UInt32 lastChatID = inc.ReadUInt32(); - if (lastChatID > c.lastRecvChatMsgID) - { - c.lastRecvChatMsgID = lastChatID; - } + + c.lastRecvGeneralUpdate = Math.Max(c.lastRecvGeneralUpdate, inc.ReadUInt32()); + c.lastRecvChatMsgID = Math.Max(c.lastRecvChatMsgID, inc.ReadUInt32()); + c.lastRecvItemSpawnID = Math.Max(c.lastRecvItemSpawnID, inc.ReadUInt32()); + break; case ClientNetObject.CHAT_MESSAGE: ChatMessage.ServerRead(inc, c); @@ -656,6 +643,7 @@ namespace Barotrauma.Networking } } + outmsg.Write((byte)ServerNetObject.CHARACTER_POSITION); if (c.Character != null && !c.Character.IsDead) { @@ -668,6 +656,13 @@ namespace Barotrauma.Networking outmsg.WritePadBits(); } + if (Item.Spawner.NetStateID > c.lastRecvItemSpawnID) + { + outmsg.Write((byte)ServerNetObject.ITEM_SPAWN); + Item.Spawner.ServerWrite(outmsg, c); + outmsg.WritePadBits(); + } + outmsg.Write((byte)ServerNetObject.END_OF_MESSAGE); server.SendMessage(outmsg, c.Connection, NetDeliveryMethod.Unreliable); } @@ -876,17 +871,13 @@ namespace Barotrauma.Networking WayPoint[] assignedWayPoints = WayPoint.SelectCrewSpawnPoints(characterInfos, Submarine.MainSub); - - for (int i = 0; i < connectedClients.Count; i++) { - WayPoint spawnPoint = WayPoint.GetRandom(SpawnType.Human, null, selectedSub); - Vector2 spawnPosition = spawnPoint.WorldPosition; - - DebugConsole.NewMessage(spawnPosition.ToString(), Color.Lime); Character spawnedCharacter = Character.Create(connectedClients[i].characterInfo, assignedWayPoints[i].WorldPosition, true, false); spawnedCharacter.AnimController.Frozen = true; - connectedClients[i].Character = spawnedCharacter; + spawnedCharacter.GiveJobItems(assignedWayPoints[i]); + + connectedClients[i].Character = spawnedCharacter; GameMain.GameSession.CrewManager.characters.Add(spawnedCharacter); } @@ -894,11 +885,17 @@ namespace Barotrauma.Networking if (characterInfo != null) { myCharacter = Character.Create(characterInfo, assignedWayPoints[assignedWayPoints.Length - 1].WorldPosition, false, false); + myCharacter.GiveJobItems(assignedWayPoints.Last()); Character.Controlled = myCharacter; GameMain.GameSession.CrewManager.characters.Add(myCharacter); } + foreach (Character c in GameMain.GameSession.CrewManager.characters) + { + Item.Spawner.AddToSpawnedList(c.SpawnItems); + } + SendStartMessage(roundStartSeed, Submarine.MainSub, GameMain.GameSession.gameMode.Preset, connectedClients); //var startMessage = CreateStartMessage(roundStartSeed, Submarine.MainSub, GameMain.GameSession.gameMode.Preset); //server.SendMessage(startMessage, connectedClients.Select(c => c.Connection).ToList(), NetDeliveryMethod.ReliableUnordered, 0); @@ -947,8 +944,8 @@ namespace Barotrauma.Networking msg.Write(selectedMode.Name); - msg.Write(AllowRespawn); - msg.Write(Submarine.MainSubs[1] != null); //loadSecondSub + msg.Write(AllowRespawn); + msg.Write(Submarine.MainSubs[1] != null); //loadSecondSub var clientsWithCharacter = clients.FindAll(c => c.Character != null); @@ -1321,7 +1318,7 @@ namespace Barotrauma.Networking if (jobPrefab != null) jobPreferences.Add(jobPrefab); } - sender.characterInfo = new CharacterInfo(Character.HumanConfigFile, name, gender); + sender.characterInfo = new CharacterInfo(Character.HumanConfigFile, sender.name, gender); sender.characterInfo.HeadSpriteId = headSpriteId; sender.jobPreferences = jobPreferences; } diff --git a/Subsurface/Source/Networking/NetworkMember.cs b/Subsurface/Source/Networking/NetworkMember.cs index b586898e7..36c26a497 100644 --- a/Subsurface/Source/Networking/NetworkMember.cs +++ b/Subsurface/Source/Networking/NetworkMember.cs @@ -45,7 +45,9 @@ namespace Barotrauma.Networking CHAT_MESSAGE, VOTE, CHARACTER_POSITION, - ITEM_STATE + ITEM_STATE, + + ITEM_SPAWN } enum VoteType