diff --git a/Subsurface/Source/Items/Components/Door.cs b/Subsurface/Source/Items/Components/Door.cs index 7dc28b9ee..d47418319 100644 --- a/Subsurface/Source/Items/Components/Door.cs +++ b/Subsurface/Source/Items/Components/Door.cs @@ -514,7 +514,7 @@ namespace Barotrauma.Items.Components PlaySound(ActionType.OnUse, item.WorldPosition); predictedState = open; - resetPredictionTimer = 1.0f; + resetPredictionTimer = CorrectionDelay; } else { @@ -523,7 +523,6 @@ namespace Barotrauma.Items.Components isOpen = open; } - //opening a partially stuck door makes it less stuck if (isOpen) stuck = MathHelper.Clamp(stuck - 30.0f, 0.0f, 100.0f); diff --git a/Subsurface/Source/Items/Components/ItemComponent.cs b/Subsurface/Source/Items/Components/ItemComponent.cs index 5564b0809..ed5dd2841 100644 --- a/Subsurface/Source/Items/Components/ItemComponent.cs +++ b/Subsurface/Source/Items/Components/ItemComponent.cs @@ -59,9 +59,7 @@ namespace Barotrauma.Items.Components public bool WasUsed; public readonly Dictionary> statusEffectLists; - - protected bool updated; - + public List requiredItems; public List requiredSkills; @@ -72,6 +70,10 @@ namespace Barotrauma.Items.Components public ItemComponent Parent; + protected const float CorrectionDelay = 1.0f; + protected CoroutineHandle delayedCorrectionCoroutine; + protected float correctionTimer; + private string msg; [HasDefaultValue(0.0f, false)] @@ -86,15 +88,7 @@ namespace Barotrauma.Items.Components { get { return properties; } } - //has the component already been updated this frame - public bool Updated - { - get { return updated; } - set { updated = value; } - } - - public bool NetworkUpdateSent; - + public virtual bool IsActive { get { return isActive; } @@ -535,6 +529,12 @@ namespace Barotrauma.Items.Components Sounds.SoundManager.Stop(loopingSoundIndex); } + if (delayedCorrectionCoroutine != null) + { + CoroutineManager.StopCoroutines(delayedCorrectionCoroutine); + delayedCorrectionCoroutine = null; + } + RemoveComponentSpecific(); } @@ -680,6 +680,30 @@ namespace Barotrauma.Items.Components } } + //Starts a coroutine that will read the correct state of the component from the NetBuffer when correctionTimer reaches zero. + protected void StartDelayedCorrection(ServerNetObject type, NetBuffer buffer, float sendingTime) + { + if (delayedCorrectionCoroutine != null) CoroutineManager.StopCoroutines(delayedCorrectionCoroutine); + + delayedCorrectionCoroutine = CoroutineManager.StartCoroutine(DoDelayedCorrection(type, buffer, sendingTime)); + } + + private IEnumerable DoDelayedCorrection(ServerNetObject type, NetBuffer buffer, float sendingTime) + { + while (correctionTimer > 0.0f) + { + correctionTimer -= CoroutineManager.DeltaTime; + yield return CoroutineStatus.Running; + } + + ((IServerSerializable)this).ClientRead(type, buffer, sendingTime); + + correctionTimer = 0.0f; + delayedCorrectionCoroutine = null; + + yield return CoroutineStatus.Success; + } + public virtual XElement Save(XElement parentElement) { XElement componentElement = new XElement(name); diff --git a/Subsurface/Source/Items/Components/Machines/Pump.cs b/Subsurface/Source/Items/Components/Machines/Pump.cs index 3cae88913..dba76a360 100644 --- a/Subsurface/Source/Items/Components/Machines/Pump.cs +++ b/Subsurface/Source/Items/Components/Machines/Pump.cs @@ -80,6 +80,7 @@ namespace Barotrauma.Items.Components } else if (GameMain.Client != null) { + correctionTimer = CorrectionDelay; item.CreateClientEvent(this); } @@ -97,6 +98,7 @@ namespace Barotrauma.Items.Components } else if (GameMain.Client != null) { + correctionTimer = CorrectionDelay; item.CreateClientEvent(this); } @@ -114,6 +116,7 @@ namespace Barotrauma.Items.Components } else if (GameMain.Client != null) { + correctionTimer = CorrectionDelay; item.CreateClientEvent(this); } @@ -234,7 +237,7 @@ namespace Barotrauma.Items.Components msg.Write(IsActive); } - public void ServerRead(ClientNetObject type, Lidgren.Network.NetBuffer msg, Barotrauma.Networking.Client c) + public void ServerRead(ClientNetObject type, Lidgren.Network.NetBuffer msg, Client c) { float flowPercentage = msg.ReadRangedInteger(-10, 10) * 10.0f; bool isActive = msg.ReadBoolean(); @@ -243,9 +246,12 @@ namespace Barotrauma.Items.Components FlowPercentage = flowPercentage; IsActive = isActive; + + //notify all clients of the changed state + item.CreateServerEvent(this); } - public void ServerWrite(Lidgren.Network.NetBuffer msg, Barotrauma.Networking.Client c, object[] extraData = null) + public void ServerWrite(Lidgren.Network.NetBuffer msg, Client c, object[] extraData = null) { //flowpercentage can only be adjusted at 10% intervals -> no need for more accuracy than this msg.WriteRangedInteger(-10, 10, (int)(flowPercentage / 10.0f)); @@ -254,6 +260,12 @@ namespace Barotrauma.Items.Components public void ClientRead(ServerNetObject type, Lidgren.Network.NetBuffer msg, float sendingTime) { + if (correctionTimer > 0.0f) + { + StartDelayedCorrection(type, msg.ExtractBits(5 + 1), sendingTime); + return; + } + 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 8da8d9e75..1564d6bef 100644 --- a/Subsurface/Source/Items/Components/Machines/Radar.cs +++ b/Subsurface/Source/Items/Components/Machines/Radar.cs @@ -64,6 +64,7 @@ namespace Barotrauma.Items.Components else if (GameMain.Client != null) { item.CreateClientEvent(this); + correctionTimer = CorrectionDelay; } IsActive = box.Selected; @@ -450,6 +451,12 @@ namespace Barotrauma.Items.Components public void ClientRead(ServerNetObject type, Lidgren.Network.NetBuffer msg, float sendingTime) { + if (correctionTimer > 0.0f) + { + StartDelayedCorrection(type, msg.ExtractBits(1), sendingTime); + return; + } + 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 a73289e56..d01c9de65 100644 --- a/Subsurface/Source/Items/Components/Machines/Reactor.cs +++ b/Subsurface/Source/Items/Components/Machines/Reactor.cs @@ -10,7 +10,7 @@ namespace Barotrauma.Items.Components { class Reactor : Powered, IDrawableComponent, IServerSerializable, IClientSerializable { - const float NetworkUpdateInterval = 3.0f; + const float NetworkUpdateInterval = 0.5f; //the rate at which the reactor is being run un //higher rates generate more power (and heat) @@ -553,16 +553,18 @@ namespace Barotrauma.Items.Components public void ClientWrite(NetBuffer msg, object[] extraData = null) { msg.Write(autoTemp); - msg.WriteRangedSingle(shutDownTemp, 0.0f, 10000.0f, 8); + msg.WriteRangedSingle(shutDownTemp, 0.0f, 10000.0f, 15); msg.WriteRangedSingle(coolingRate, 0.0f, 100.0f, 8); msg.WriteRangedSingle(fissionRate, 0.0f, 100.0f, 8); + + correctionTimer = CorrectionDelay; } public void ServerRead(ClientNetObject type, NetBuffer msg, Client c) { bool autoTemp = msg.ReadBoolean(); - float shutDownTemp = msg.ReadRangedSingle(0.0f, 10000.0f, 8); + float shutDownTemp = msg.ReadRangedSingle(0.0f, 10000.0f, 15); float coolingRate = msg.ReadRangedSingle(0.0f, 100.0f, 8); float fissionRate = msg.ReadRangedSingle(0.0f, 100.0f, 8); @@ -583,7 +585,7 @@ namespace Barotrauma.Items.Components msg.WriteRangedSingle(temperature, 0.0f, 10000.0f, 16); msg.Write(autoTemp); - msg.WriteRangedSingle(shutDownTemp, 0.0f, 10000.0f, 8); + msg.WriteRangedSingle(shutDownTemp, 0.0f, 10000.0f, 15); msg.WriteRangedSingle(coolingRate, 0.0f, 100.0f, 8); msg.WriteRangedSingle(fissionRate, 0.0f, 100.0f, 8); @@ -591,10 +593,16 @@ namespace Barotrauma.Items.Components public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime) { + if (correctionTimer > 0.0f) + { + StartDelayedCorrection(type, msg.ExtractBits(16 + 1 + 15 + 8 + 8), sendingTime); + return; + } + Temperature = msg.ReadRangedSingle(0.0f, 10000.0f, 16); AutoTemp = msg.ReadBoolean(); - ShutDownTemp = msg.ReadRangedSingle(0.0f, 10000.0f, 8); + ShutDownTemp = msg.ReadRangedSingle(0.0f, 10000.0f, 15); CoolingRate = msg.ReadRangedSingle(0.0f, 100.0f, 8); FissionRate = msg.ReadRangedSingle(0.0f, 100.0f, 8); diff --git a/Subsurface/Source/Items/Components/Machines/Steering.cs b/Subsurface/Source/Items/Components/Machines/Steering.cs index 9f941a761..53be9de36 100644 --- a/Subsurface/Source/Items/Components/Machines/Steering.cs +++ b/Subsurface/Source/Items/Components/Machines/Steering.cs @@ -146,6 +146,7 @@ namespace Barotrauma.Items.Components if (GameMain.Client != null) { item.CreateClientEvent(this); + correctionTimer = CorrectionDelay; } else if (GameMain.Server != null) { @@ -597,6 +598,8 @@ namespace Barotrauma.Items.Components public void ClientRead(ServerNetObject type, Lidgren.Network.NetBuffer msg, float sendingTime) { + long msgStartPos = msg.Position; + bool autoPilot = msg.ReadBoolean(); Vector2 newTargetVelocity = targetVelocity; bool maintainPos = false; @@ -622,6 +625,14 @@ namespace Barotrauma.Items.Components newTargetVelocity = new Vector2(msg.ReadFloat(), msg.ReadFloat()); } + if (correctionTimer > 0.0f) + { + int msgLength = (int)(msg.Position - msgStartPos); + msg.Position = msgStartPos; + StartDelayedCorrection(type, msg.ExtractBits(msgLength), sendingTime); + return; + } + AutoPilot = autoPilot; if (!AutoPilot) diff --git a/Subsurface/Source/Items/Components/Power/PowerContainer.cs b/Subsurface/Source/Items/Components/Power/PowerContainer.cs index 55d587769..3334b2c7c 100644 --- a/Subsurface/Source/Items/Components/Power/PowerContainer.cs +++ b/Subsurface/Source/Items/Components/Power/PowerContainer.cs @@ -100,9 +100,14 @@ namespace Barotrauma.Items.Components RechargeSpeed = rechargeSpeed - maxRechargeSpeed * 0.1f; if (GameMain.Server != null) + { item.CreateServerEvent(this); + } else if (GameMain.Client != null) + { item.CreateClientEvent(this); + correctionTimer = CorrectionDelay; + } return true; }; @@ -113,9 +118,14 @@ namespace Barotrauma.Items.Components RechargeSpeed = rechargeSpeed + maxRechargeSpeed * 0.1f; if (GameMain.Server != null) + { item.CreateServerEvent(this); + } else if (GameMain.Client != null) + { item.CreateClientEvent(this); + correctionTimer = CorrectionDelay; + } return true; }; @@ -269,7 +279,6 @@ namespace Barotrauma.Items.Components public void ClientWrite(NetBuffer msg, object[] extraData) { - DebugConsole.NewMessage("writing recharge speed " + (rechargeSpeed / MaxRechargeSpeed * 10), Color.White); msg.WriteRangedInteger(0, 10, (int)(rechargeSpeed / MaxRechargeSpeed * 10)); } @@ -277,8 +286,6 @@ namespace Barotrauma.Items.Components { float newRechargeSpeed = msg.ReadRangedInteger(0,10) / 10.0f * maxRechargeSpeed; - DebugConsole.NewMessage("received recharge speed " + newRechargeSpeed, Color.White); - if (item.CanClientAccess(c)) { RechargeSpeed = newRechargeSpeed; @@ -297,6 +304,12 @@ namespace Barotrauma.Items.Components public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime) { + if (correctionTimer > 0.0f) + { + StartDelayedCorrection(type, msg.ExtractBits(4 + 8), sendingTime); + return; + } + RechargeSpeed = msg.ReadRangedInteger(0, 10) / 10.0f * maxRechargeSpeed; Charge = msg.ReadRangedSingle(0.0f, 1.0f, 8) * capacity; } diff --git a/Subsurface/Source/Utils/ToolBox.cs b/Subsurface/Source/Utils/ToolBox.cs index 2e60c0b6a..bbf2aa6c5 100644 --- a/Subsurface/Source/Utils/ToolBox.cs +++ b/Subsurface/Source/Utils/ToolBox.cs @@ -1,4 +1,5 @@ -using Microsoft.Xna.Framework; +using Lidgren.Network; +using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; using System.Globalization; @@ -593,5 +594,19 @@ namespace Barotrauma return ""; } } + + /// + /// Reads a number of bits from the buffer and inserts them to a new NetBuffer instance + /// + public static NetBuffer ExtractBits(this NetBuffer originalBuffer, int numberOfBits) + { + var buffer = new NetBuffer(); + byte[] data = new byte[(int)Math.Ceiling(numberOfBits / (double)8)]; + + originalBuffer.ReadBits(data, 0, numberOfBits); + buffer.Write(data); + + return buffer; + } } }