diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj index abdbe0bb7..61d392857 100644 --- a/Subsurface/Barotrauma.csproj +++ b/Subsurface/Barotrauma.csproj @@ -134,6 +134,7 @@ + diff --git a/Subsurface/Source/Characters/AI/EnemyAIController.cs b/Subsurface/Source/Characters/AI/EnemyAIController.cs index d79b4b2fc..0a14ac5bc 100644 --- a/Subsurface/Source/Characters/AI/EnemyAIController.cs +++ b/Subsurface/Source/Characters/AI/EnemyAIController.cs @@ -143,8 +143,15 @@ namespace Barotrauma private void UpdateNone(float deltaTime) { //wander around randomly - steeringManager.SteeringWander(0.8f); - steeringManager.SteeringAvoid(deltaTime, 1.0f); + if (Character.Submarine==null && SimPosition.Y < ConvertUnits.ToSimUnits(SubmarineBody.DamageDepth*0.5f)) + { + steeringManager.SteeringManual(deltaTime, Vector2.UnitY); + } + else + { + steeringManager.SteeringWander(0.8f); + steeringManager.SteeringAvoid(deltaTime, 1.0f); + } attackingLimb = null; attackTimer = 0.0f; diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index df18d9434..e4a8d8c8c 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -107,7 +107,11 @@ namespace Barotrauma //which AIstate each sound is for private AIController.AiState[] soundStates; - private Entity viewTarget; + public Entity ViewTarget + { + get; + private set; + } private CharacterInfo info; @@ -1085,7 +1089,17 @@ namespace Barotrauma public virtual AttackResult AddDamage(IDamageable attacker, Vector2 worldPosition, Attack attack, float deltaTime, bool playSound = false) { - return AddDamage(worldPosition, attack.DamageType, attack.GetDamage(deltaTime), attack.GetBleedingDamage(deltaTime), attack.Stun, playSound); + + + var attackResult = AddDamage(worldPosition, attack.DamageType, attack.GetDamage(deltaTime), attack.GetBleedingDamage(deltaTime), attack.Stun, playSound); + + var attackingCharacter = attacker as Character; + if (attackingCharacter != null && attackingCharacter.AIController == null) + { + GameServer.Log(Name + " attacked by " + attackingCharacter.Name+". Damage: "+attackResult.Damage+" Bleeding damage: "+attackResult.Bleeding); + } + + return attackResult; } public AttackResult AddDamage(Vector2 simPosition, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound) @@ -1245,6 +1259,8 @@ namespace Barotrauma } } + GameServer.Log(Name+" has died (cause of death: "+causeOfDeath+")"); + if (OnDeath != null) OnDeath(this, causeOfDeath); //CoroutineManager.StartCoroutine(DeathAnim(GameMain.GameScreen.Cam)); @@ -1384,19 +1400,19 @@ namespace Barotrauma { if (Character.controlled==this) { - viewTarget = Lights.LightManager.ViewTarget == null ? this : Lights.LightManager.ViewTarget; + ViewTarget = Lights.LightManager.ViewTarget == null ? this : Lights.LightManager.ViewTarget; } - if (viewTarget == null) viewTarget = this; + if (ViewTarget == null) ViewTarget = this; Vector2 relativeCursorPosition = cursorPosition; - relativeCursorPosition -= viewTarget.Position; + relativeCursorPosition -= ViewTarget.Position; if (relativeCursorPosition.Length()>500.0f) { relativeCursorPosition = Vector2.Normalize(relativeCursorPosition) * 495.0f; } - message.Write(viewTarget.ID); + message.Write(ViewTarget.ID); message.WriteRangedSingle(relativeCursorPosition.X, -500.0f, 500.0f, 8); message.WriteRangedSingle(relativeCursorPosition.Y, -500.0f, 500.0f, 8); @@ -1432,7 +1448,7 @@ namespace Barotrauma switch (type) { case NetworkEventType.PickItem: - System.Diagnostics.Debug.WriteLine("**************** PickItem networkevent received"); + ushort itemId = message.ReadUInt16(); @@ -1444,7 +1460,18 @@ namespace Barotrauma System.Diagnostics.Debug.WriteLine("item id: "+itemId); Item item = FindEntityByID(itemId) as Item; - if (item != null) item.Pick(this, false, pickHit, actionHit); + if (item != null) + { + if (item == selectedConstruction) + { + GameServer.Log(Name + " deselected " + item.Name); + } + else + { + GameServer.Log(Name + " selected " + item.Name); + } + item.Pick(this, false, pickHit, actionHit); + } return; case NetworkEventType.SelectCharacter: @@ -1565,7 +1592,7 @@ namespace Barotrauma Vector2 pos = Vector2.Zero; ushort viewTargetID = 0; - viewTarget = null; + ViewTarget = null; try { @@ -1609,10 +1636,10 @@ namespace Barotrauma { cursorPosition = MathUtils.IsValid(relativeCursorPos) ? relativeCursorPos : Vector2.Zero; - viewTarget = viewTargetID == 0 ? this : Entity.FindEntityByID(viewTargetID); - if (viewTarget == null) viewTarget = this; + ViewTarget = viewTargetID == 0 ? this : Entity.FindEntityByID(viewTargetID); + if (ViewTarget == null) ViewTarget = this; - cursorPosition += viewTarget.Position; + cursorPosition += ViewTarget.Position; } else { diff --git a/Subsurface/Source/Events/Quests/Quest.cs b/Subsurface/Source/Events/Quests/Quest.cs index fdd956b9a..2fe76a0b4 100644 --- a/Subsurface/Source/Events/Quests/Quest.cs +++ b/Subsurface/Source/Events/Quests/Quest.cs @@ -173,9 +173,12 @@ namespace Barotrauma { if (index >= headers.Count && index >= messages.Count) return; - new GUIMessageBox( - index < headers.Count ? headers[index] : "", - index < messages.Count ? messages[index] : ""); + string header = index < headers.Count ? headers[index] : ""; + string message = index < messages.Count ? messages[index] : ""; + + Barotrauma.Networking.GameServer.Log("Mission info: " + header + " - " + message); + + new GUIMessageBox(header, message); } /// diff --git a/Subsurface/Source/GameSession/GameModes/QuestMode.cs b/Subsurface/Source/GameSession/GameModes/QuestMode.cs index 1bfce67a2..80aaefdf3 100644 --- a/Subsurface/Source/GameSession/GameModes/QuestMode.cs +++ b/Subsurface/Source/GameSession/GameModes/QuestMode.cs @@ -38,6 +38,9 @@ namespace Barotrauma new GUIMessageBox(mission.Name, mission.Description, 400, 400); + Networking.GameServer.Log("Mission: " + mission.Name); + Networking.GameServer.Log(mission.Description); + //quest.Start(Level.Loaded); } diff --git a/Subsurface/Source/Items/CharacterInventory.cs b/Subsurface/Source/Items/CharacterInventory.cs index 6791f1133..7a5e62b20 100644 --- a/Subsurface/Source/Items/CharacterInventory.cs +++ b/Subsurface/Source/Items/CharacterInventory.cs @@ -100,15 +100,19 @@ namespace Barotrauma /// public override bool TryPutItem(Item item, List allowedSlots, bool createNetworkEvent = true) { + bool alreadyInInventory = Array.Find(Items, i => i == item)!=null; + //try to place the item in LimBlot.Any slot if that's allowed if (allowedSlots.Contains(LimbSlot.Any)) { for (int i = 0; i < capacity; i++) { if (Items[i] != null || limbSlots[i] != LimbSlot.Any) continue; + + GameServer.Log(character.Name + " picked up " + item.Name); PutItem(item, i, createNetworkEvent); item.Unequip(character); - return true; + return true; } } @@ -138,7 +142,11 @@ namespace Barotrauma } } - if (placed) return true; + if (placed) + { + if (!alreadyInInventory) GameServer.Log(character.Name + " picked up " + item.Name); + return true; + } } @@ -368,7 +376,7 @@ namespace Barotrauma for (int i = 0; i(); if (connectionPanel == null) return; @@ -173,7 +173,7 @@ namespace Barotrauma.Items.Components if (w == null) continue; w.Item.Drop(character); - w.Item.SetTransform(character.SimPosition, 0.0f); + w.Item.SetTransform(pos, 0.0f); } } } diff --git a/Subsurface/Source/Items/Components/ItemComponent.cs b/Subsurface/Source/Items/Components/ItemComponent.cs index cd6e4e2b4..18cf9fcc5 100644 --- a/Subsurface/Source/Items/Components/ItemComponent.cs +++ b/Subsurface/Source/Items/Components/ItemComponent.cs @@ -731,7 +731,7 @@ namespace Barotrauma.Items.Components return false; } - public virtual void ReadNetworkData(NetworkEventType type, NetBuffer message, float sendingTime) + public virtual void ReadNetworkData(NetworkEventType type, NetIncomingMessage message, float sendingTime) { } } diff --git a/Subsurface/Source/Items/Components/Machines/Controller.cs b/Subsurface/Source/Items/Components/Machines/Controller.cs index 646a15cbf..c9d9a6442 100644 --- a/Subsurface/Source/Items/Components/Machines/Controller.cs +++ b/Subsurface/Source/Items/Components/Machines/Controller.cs @@ -152,7 +152,10 @@ namespace Barotrauma.Items.Components return; } - if (character!=null) item.SendSignal(ToolBox.Vector2ToString(character.CursorWorldPosition), "position_out"); + Entity focusTarget = null; + + if (character == null) return; + foreach (Connection c in item.Connections) { @@ -162,17 +165,28 @@ namespace Barotrauma.Items.Components { if (c2 == null || c2.Item == null || !c2.Item.Prefab.FocusOnSelected) continue; - Vector2 centerPos = c2.Item.WorldPosition; - - if (character == Character.Controlled && cam != null) - { - Lights.LightManager.ViewTarget = c2.Item; - cam.TargetPos = c2.Item.WorldPosition; - } + focusTarget = c2.Item; break; } } + + if (focusTarget == null) + { + item.SendSignal(ToolBox.Vector2ToString(character.CursorWorldPosition), "position_out"); + return; + } + + if (character == Character.Controlled && cam != null) + { + Lights.LightManager.ViewTarget = focusTarget; + cam.TargetPos = focusTarget.WorldPosition; + } + + if (!character.IsNetworkPlayer || character.ViewTarget == focusTarget) + { + item.SendSignal(ToolBox.Vector2ToString(character.CursorWorldPosition), "position_out"); + } } public override bool Pick(Character picker) diff --git a/Subsurface/Source/Items/Components/Machines/Deconstructor.cs b/Subsurface/Source/Items/Components/Machines/Deconstructor.cs index 0b777ed80..674eb491b 100644 --- a/Subsurface/Source/Items/Components/Machines/Deconstructor.cs +++ b/Subsurface/Source/Items/Components/Machines/Deconstructor.cs @@ -138,7 +138,7 @@ namespace Barotrauma.Items.Components return true; } - public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message, float sendingTime) + public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message, float sendingTime) { if (sendingTime < lastNetworkUpdate) return; diff --git a/Subsurface/Source/Items/Components/Machines/Fabricator.cs b/Subsurface/Source/Items/Components/Machines/Fabricator.cs index 136c49bc5..e4eae4bb7 100644 --- a/Subsurface/Source/Items/Components/Machines/Fabricator.cs +++ b/Subsurface/Source/Items/Components/Machines/Fabricator.cs @@ -309,7 +309,7 @@ namespace Barotrauma.Items.Components return true; } - public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message, float sendingTime) + public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message, float sendingTime) { if (sendingTime < lastNetworkUpdate) return; diff --git a/Subsurface/Source/Items/Components/Machines/Pump.cs b/Subsurface/Source/Items/Components/Machines/Pump.cs index 473684e99..3920c3131 100644 --- a/Subsurface/Source/Items/Components/Machines/Pump.cs +++ b/Subsurface/Source/Items/Components/Machines/Pump.cs @@ -205,7 +205,7 @@ namespace Barotrauma.Items.Components return true; } - public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message, float sendingTime) + public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message, float sendingTime) { float newFlow = 0.0f; bool newActive; @@ -230,6 +230,15 @@ namespace Barotrauma.Items.Components IsActive = newActive; lastUpdate = sendingTime; + + if (GameMain.Server == null) return; + + var sender = GameMain.Server.ConnectedClients.Find(c => c.Connection == message.SenderConnection); + if (sender != null) + { + Networking.GameServer.Log("Pump settings adjusted by " + sender.name); + Networking.GameServer.Log("Active: " + (IsActive ? "yes" : "no ") + " Pumping speed: " + (int)flowPercentage + " %"); + } } } } diff --git a/Subsurface/Source/Items/Components/Machines/Radar.cs b/Subsurface/Source/Items/Components/Machines/Radar.cs index e730bdc80..6ef73dd3c 100644 --- a/Subsurface/Source/Items/Components/Machines/Radar.cs +++ b/Subsurface/Source/Items/Components/Machines/Radar.cs @@ -327,7 +327,7 @@ namespace Barotrauma.Items.Components return true; } - public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message, float sendingTime) + public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message, float sendingTime) { try { diff --git a/Subsurface/Source/Items/Components/Machines/Reactor.cs b/Subsurface/Source/Items/Components/Machines/Reactor.cs index e43a4a1dd..51f610e27 100644 --- a/Subsurface/Source/Items/Components/Machines/Reactor.cs +++ b/Subsurface/Source/Items/Components/Machines/Reactor.cs @@ -361,6 +361,8 @@ namespace Barotrauma.Items.Components private void MeltDown() { if (item.Condition <= 0.0f) return; + + GameServer.Log("Reactor meltdown!"); new RepairTask(item, 60.0f, "Reactor meltdown!"); item.Condition = 0.0f; @@ -539,7 +541,7 @@ namespace Barotrauma.Items.Components return true; } - public override void ReadNetworkData(NetworkEventType type, NetBuffer message, float sendingTime) + public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message, float sendingTime) { if (sendingTime < lastUpdate) return; @@ -574,6 +576,17 @@ namespace Barotrauma.Items.Components FissionRate = newFissionRate; lastUpdate = sendingTime; + + + if (GameMain.Server == null) return; + + var sender = GameMain.Server.ConnectedClients.Find(c => c.Connection == message.SenderConnection); + if (sender != null) + { + Networking.GameServer.Log("Reactor settings adjusted by " + sender.name); + Networking.GameServer.Log("Autotemp: " +(autoTemp ? "ON " : "OFF") + " Shutdown temp: "+shutDownTemp+" Cooling rate: "+coolingRate+" Fission rate: "+fissionRate); + } + } } } diff --git a/Subsurface/Source/Items/Components/Machines/Steering.cs b/Subsurface/Source/Items/Components/Machines/Steering.cs index 3f67f543d..5781a17db 100644 --- a/Subsurface/Source/Items/Components/Machines/Steering.cs +++ b/Subsurface/Source/Items/Components/Machines/Steering.cs @@ -313,7 +313,7 @@ namespace Barotrauma.Items.Components return true; } - public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message, float sendingTime) + public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message, float sendingTime) { Vector2 newTargetVelocity = Vector2.Zero; bool newAutoPilot = false; diff --git a/Subsurface/Source/Items/Components/Power/PowerContainer.cs b/Subsurface/Source/Items/Components/Power/PowerContainer.cs index 48005e690..bf88d5be3 100644 --- a/Subsurface/Source/Items/Components/Power/PowerContainer.cs +++ b/Subsurface/Source/Items/Components/Power/PowerContainer.cs @@ -261,7 +261,7 @@ namespace Barotrauma.Items.Components return true; } - public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message, float sendingTime) + public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message, float sendingTime) { float newRechargeSpeed = 0f; float newCharge = 0.0f; diff --git a/Subsurface/Source/Items/Components/Signal/Connection.cs b/Subsurface/Source/Items/Components/Signal/Connection.cs index cf16ab31d..e79e562b5 100644 --- a/Subsurface/Source/Items/Components/Signal/Connection.cs +++ b/Subsurface/Source/Items/Components/Signal/Connection.cs @@ -15,7 +15,7 @@ namespace Barotrauma.Items.Components private static Sprite wireCorner, wireVertical, wireHorizontal; //how many wires can be linked to a single connector - private const int MaxLinked = 5; + public const int MaxLinked = 5; public readonly string Name; diff --git a/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs b/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs index 4f1b81a86..5e0f15b23 100644 --- a/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs +++ b/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs @@ -129,7 +129,7 @@ namespace Barotrauma.Items.Components foreach (Connection c in Connections) { Wire[] wires = Array.FindAll(c.Wires, w => w != null); - message.Write((byte)wires.Length); + message.WriteRangedInteger(0, Connection.MaxLinked, wires.Length); for (int i = 0 ; i < wires.Length; i++) { message.Write(wires[i].Item.ID); @@ -139,15 +139,24 @@ namespace Barotrauma.Items.Components return true; } - public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message, float sendingTime) + public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message, float sendingTime) { + if (GameMain.Server != null) + { + var sender = GameMain.Server.ConnectedClients.Find(c => c.Connection == message.SenderConnection); + if (sender != null) + { + Networking.GameServer.Log(item.Name + " rewired by " + sender.name); + } + } + System.Diagnostics.Debug.WriteLine("connectionpanel update"); foreach (Connection c in Connections) { //int wireCount = c.Wires.Length; c.ClearConnections(); - byte wireCount = message.ReadByte(); + int wireCount = message.ReadRangedInteger(0, Connection.MaxLinked); for (int i = 0; i < wireCount; i++) { @@ -161,6 +170,9 @@ namespace Barotrauma.Items.Components c.Wires[i] = wireComponent; wireComponent.Connect(c, false); + + var otherConnection = c.Wires[i].OtherConnection(c); + Networking.GameServer.Log(c.Name + " -> " + (otherConnection == null ? "none" : otherConnection.Name)); } c.UpdateRecipients(); } diff --git a/Subsurface/Source/Items/Components/Signal/Wire.cs b/Subsurface/Source/Items/Components/Signal/Wire.cs index 0b3150248..8f1821305 100644 --- a/Subsurface/Source/Items/Components/Signal/Wire.cs +++ b/Subsurface/Source/Items/Components/Signal/Wire.cs @@ -480,7 +480,7 @@ namespace Barotrauma.Items.Components return true; } - public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message, float sendingTime) + public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message, float sendingTime) { Nodes.Clear(); diff --git a/Subsurface/Source/Items/Item.cs b/Subsurface/Source/Items/Item.cs index a9d2bcc10..ebc309689 100644 --- a/Subsurface/Source/Items/Item.cs +++ b/Subsurface/Source/Items/Item.cs @@ -833,7 +833,7 @@ namespace Barotrauma public virtual void DrawHUD(SpriteBatch spriteBatch, Character character) { - if (condition<=0.0f) + if (condition <= 0.0f) { FixRequirement.DrawHud(spriteBatch, this, character); return; @@ -1123,6 +1123,9 @@ namespace Barotrauma { //if (dropper == Character.Controlled) // new NetworkEvent(NetworkEventType.DropItem, ID, true); + + + if (dropper != null) GameServer.Log(dropper.Name + " dropped " + Name); foreach (ItemComponent ic in components) ic.Drop(dropper); diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index c5cd7fc62..89982fd94 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -20,7 +20,7 @@ namespace Barotrauma.Networking private NetStats netStats; private int roundStartSeed; - + //is the server running private bool started; @@ -32,6 +32,8 @@ namespace Barotrauma.Networking private bool masterServerResponded; + private ServerLog log; + public TraitorManager TraitorManager; public GameServer(string name, int port, bool isPublic = false, string password = "", bool attemptUPnP = false, int maxPlayers = 10) @@ -41,6 +43,8 @@ namespace Barotrauma.Networking banList = new BanList(); + log = new ServerLog(name); + this.name = name; this.password = password; @@ -78,12 +82,14 @@ namespace Barotrauma.Networking { try { + Log("Starting the server..."); server = new NetServer(config); netPeer = server; server.Start(); } catch (Exception e) { + Log("Error while starting the server ("+e.Message+")"); DebugConsole.ThrowError("Couldn't start the server", e); } @@ -166,8 +172,8 @@ namespace Barotrauma.Networking request.AddParameter("action", "refreshserver"); request.AddParameter("gamestarted", gameStarted ? 1 : 0); request.AddParameter("playercount", PlayerCountToByte(ConnectedClients.Count, config.MaximumConnections)); - - System.Diagnostics.Debug.WriteLine("refreshing master"); + + Log("Refreshing connection with master server..."); var sw = new Stopwatch(); sw.Start(); @@ -182,6 +188,9 @@ namespace Barotrauma.Networking { restRequestHandle.Abort(); DebugConsole.NewMessage("Couldn't connect to master server (request timed out)", Color.Red); + + Log("Couldn't connect to master server (request timed out)"); + break; //registeredToMaster = false; } @@ -201,14 +210,18 @@ namespace Barotrauma.Networking if (response.ErrorException != null) { DebugConsole.NewMessage("Error while registering to master server (" + response.ErrorException + ")", Color.Red); + Log("Error while registering to master server (" + response.ErrorException + ")"); return; } if (response.StatusCode != System.Net.HttpStatusCode.OK) { DebugConsole.NewMessage("Error while reporting to master server (" + response.StatusCode + ": " + response.StatusDescription + ")", Color.Red); + Log("Error while reporting to master server (" + response.StatusCode + ": " + response.StatusDescription + ")"); return; } + + Log("Master server responded"); } public override void Update(float deltaTime) @@ -233,6 +246,15 @@ namespace Barotrauma.Networking || (endRoundAtLevelEnd && Submarine.Loaded!=null && Submarine.Loaded.AtEndPosition)) { + if (AutoRestart && isCrewDead) + { + Log("Ending round (entire crew dead)"); + } + else + { + Log("Ending round (submarine reached the end of the level)"); + } + EndButtonHit(null, null); UpdateNetLobby(null,null); return; @@ -474,10 +496,10 @@ namespace Barotrauma.Networking case (byte)PacketTypes.Vote: Voting.RegisterVote(inc, ConnectedClients); - if (Voting.AllowEndVoting && EndVoteMax > 0 && - + if (Voting.AllowEndVoting && EndVoteMax > 0 && ((float)EndVoteCount / (float)EndVoteMax) >= EndVoteRequiredRatio) { + Log("Ending round by votes ("+EndVoteCount+"/"+(EndVoteMax-EndVoteCount)+")"); EndButtonHit(null,null); } break; @@ -673,8 +695,10 @@ namespace Barotrauma.Networking { yield return new WaitForSeconds(3.0f); + //save all the current events to a list and clear them var existingEvents = NetworkEvent.Events; NetworkEvent.Events.Clear(); + foreach (Hull hull in Hull.hullList) { if (!hull.FireSources.Any() && hull.Volume < 0.01f) continue; @@ -703,13 +727,18 @@ namespace Barotrauma.Networking List syncMessages = new List(NetworkEvent.Events); while (syncMessages.Any()) { + //put 5 events in the message and send them to the spectator NetworkEvent.Events = syncMessages.GetRange(0, Math.Min(syncMessages.Count, 5)); SendNetworkEvents(new List() { sender }); syncMessages.RemoveRange(0, Math.Min(syncMessages.Count, 5)); + //restore "normal" events NetworkEvent.Events = existingEvents; yield return new WaitForSeconds(0.1f); + + //save "normal" events again + existingEvents = NetworkEvent.Events; } yield return CoroutineStatus.Success; @@ -762,6 +791,11 @@ namespace Barotrauma.Networking GameMain.GameSession = new GameSession(selectedSub, "", selectedMode); GameMain.GameSession.StartShift(GameMain.NetLobbyScreen.LevelSeed); + GameServer.Log("Starting a new round..."); + GameServer.Log("Submarine: " + selectedSub.Name); + GameServer.Log("Game mode: " + selectedMode.Name); + GameServer.Log("Level seed: " + GameMain.NetLobbyScreen.LevelSeed); + yield return CoroutineStatus.Running; List characterInfos = new List(); @@ -972,6 +1006,8 @@ namespace Barotrauma.Networking if (string.IsNullOrWhiteSpace(msg)) msg = client.name + " has left the server"; if (string.IsNullOrWhiteSpace(targetmsg)) targetmsg = "You have left the server"; + + Log(msg); NetOutgoingMessage outmsg = server.CreateMessage(); outmsg.Write((byte)PacketTypes.KickedOut); @@ -1079,6 +1115,8 @@ namespace Barotrauma.Networking return; } + Log(traitor.Info.Name + " is the traitor and the target is " + target.Info.Name); + Client traitorClient = null; foreach (Client c in ConnectedClients) { @@ -1196,8 +1234,6 @@ namespace Barotrauma.Networking banButton.OnClicked += GameMain.NetLobbyScreen.BanPlayer; } - - return true; } @@ -1392,6 +1428,13 @@ namespace Barotrauma.Networking return preferredClient; } + public static void Log(string line) + { + if (GameMain.Server == null || GameMain.Server.saveServerLogs) return; + + GameMain.Server.log.WriteLine(line); + } + /// /// sends some random data to the clients /// use for debugging purposes @@ -1432,6 +1475,13 @@ namespace Barotrauma.Networking public override void Disconnect() { banList.Save(); + + if (saveServerLogs) + { + Log("Shutting down server..."); + log.Save(); + } + server.Shutdown("The server has shut down"); } } diff --git a/Subsurface/Source/Networking/GameServerSettings.cs b/Subsurface/Source/Networking/GameServerSettings.cs index ea7640a3c..4a1af6c77 100644 --- a/Subsurface/Source/Networking/GameServerSettings.cs +++ b/Subsurface/Source/Networking/GameServerSettings.cs @@ -43,6 +43,8 @@ namespace Barotrauma.Networking private bool endRoundAtLevelEnd = true; + private bool saveServerLogs = true; + public bool AutoRestart { get { return (ConnectedClients.Count == 0) ? false : autoRestart; } @@ -97,7 +99,11 @@ namespace Barotrauma.Networking var randomizeLevelBox = new GUITickBox(new Rectangle(0, 30, 20, 20), "Randomize level seed between rounds", Alignment.Left, innerFrame); randomizeLevelBox.Selected = randomizeSeed; - randomizeLevelBox.OnSelected = ToggleRandomizeSeed; + randomizeLevelBox.OnSelected = (GUITickBox) => + { + randomizeSeed = GUITickBox.Selected; + return true; + }; var endBox = new GUITickBox(new Rectangle(0, 60, 20, 20), "End round when destination reached", Alignment.Left, innerFrame); endBox.Selected = endRoundAtLevelEnd; @@ -116,6 +122,7 @@ namespace Barotrauma.Networking var votesRequiredSlider = new GUIScrollBar(new Rectangle(150,115, 100, 10), GUI.Style, 0.1f, innerFrame); votesRequiredSlider.UserData = votesRequiredText; + votesRequiredSlider.BarScroll = (EndVoteRequiredRatio - 0.5f) * 2.0f; votesRequiredSlider.OnMoved = (GUIScrollBar scrollBar, float barScroll) => { GUITextBlock voteText = scrollBar.UserData as GUITextBlock; @@ -125,7 +132,8 @@ namespace Barotrauma.Networking voteText.Text = "Votes required: " + (int)MathUtils.Round(EndVoteRequiredRatio * 100.0f, 10.0f) + " %"; return true; }; - + votesRequiredSlider.OnMoved(votesRequiredSlider, votesRequiredSlider.BarScroll); + new GUITextBlock(new Rectangle(0, 95+50, 100, 20), "Submarine selection:", GUI.Style, innerFrame); var selectionFrame = new GUIFrame(new Rectangle(0, 120 + 50, 300, 20), null, innerFrame); for (int i = 0; i<3; i++) @@ -147,8 +155,20 @@ namespace Barotrauma.Networking } var allowSpecBox = new GUITickBox(new Rectangle(0, 210 + 50, 20, 20), "Allow spectating", Alignment.Left, innerFrame); - allowSpecBox.Selected = true; - allowSpecBox.OnSelected = ToggleAllowSpectating; + allowSpecBox.Selected = allowSpectating; + allowSpecBox.OnSelected = (GUITickBox) => + { + allowSpectating = GUITickBox.Selected; + return true; + }; + + var saveLogsBox = new GUITickBox(new Rectangle(0, 240 + 50, 20, 20), "Save server logs", Alignment.Left, innerFrame); + saveLogsBox.Selected = saveServerLogs; + saveLogsBox.OnSelected = (GUITickBox) => + { + saveServerLogs = GUITickBox.Selected; + return true; + }; ; var closeButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Close", Alignment.BottomRight, GUI.Style, innerFrame); closeButton.OnClicked = ToggleSettingsFrame; @@ -194,17 +214,6 @@ namespace Barotrauma.Networking return true; } - private bool ToggleRandomizeSeed(GUITickBox tickBox) - { - randomizeSeed = tickBox.Selected; - return true; - } - - private bool ToggleAllowSpectating(GUITickBox tickBox) - { - allowSpectating = tickBox.Selected; - return true; - } public bool ToggleSettingsFrame(GUIButton button, object obj) { diff --git a/Subsurface/Source/Networking/NetworkMember.cs b/Subsurface/Source/Networking/NetworkMember.cs index 4690236a1..1c6916fe7 100644 --- a/Subsurface/Source/Networking/NetworkMember.cs +++ b/Subsurface/Source/Networking/NetworkMember.cs @@ -186,6 +186,8 @@ namespace Barotrauma.Networking { GameMain.NetLobbyScreen.NewChatMessage(message, messageColor[(int)messageType]); + GameServer.Log(message); + while (chatBox.CountChildren > 20) { chatBox.RemoveChild(chatBox.children[1]); diff --git a/Subsurface/Source/Networking/ServerLog.cs b/Subsurface/Source/Networking/ServerLog.cs new file mode 100644 index 000000000..7d1c5cb7b --- /dev/null +++ b/Subsurface/Source/Networking/ServerLog.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace Barotrauma.Networking +{ + class ServerLog + { + const int LinesPerFile = 500; + + const string SavePath = "ServerLogs"; + + private string serverName; + + private Queue lines; + + public ServerLog(string serverName) + { + this.serverName = serverName; + + lines = new Queue(); + } + + public void WriteLine(string line) + { + string logLine = "[" + DateTime.Now.ToLongTimeString() + "] " + line; + + lines.Enqueue(logLine); + + if (lines.Count>=LinesPerFile) + { + Save(); + } + } + + public void Save() + { + if (!Directory.Exists(SavePath)) + { + try + { + Directory.CreateDirectory(SavePath); + } + catch (Exception e) + { + DebugConsole.ThrowError("Failed to create a folder for server logs", e); + return; + } + } + + string fileName = serverName+"_"+DateTime.Now.ToShortDateString()+"_"+DateTime.Now.ToShortTimeString()+".txt"; + + fileName = fileName.Replace(":", ""); + + string filePath = Path.Combine(SavePath, fileName); + + try + { + File.WriteAllLines(filePath, lines); + } + catch (Exception e) + { + DebugConsole.ThrowError("Saving the server log to " + filePath + " failed", e); + } + } + } +} diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index 8e982b8c9..0bdc51fff 100644 Binary files a/Subsurface_Solution.v12.suo and b/Subsurface_Solution.v12.suo differ