Removed Fill/ReadNetworkData
These functions needed to be replaced because they rely heavily on reliability. Instead, new functions called (Write/Read)Data(Server/Client) will be added. Separating client and server code into completely separate functions will help ensure that proper security checks are performed.
This commit is contained in:
@@ -575,74 +575,6 @@ namespace Barotrauma
|
|||||||
spriteBatch.DrawString(GUI.Font, "updatetargets: "+updateTargetsTimer, pos - Vector2.UnitY * 100.0f, Color.Red);
|
spriteBatch.DrawString(GUI.Font, "updatetargets: "+updateTargetsTimer, pos - Vector2.UnitY * 100.0f, Color.Red);
|
||||||
spriteBatch.DrawString(GUI.Font, "cooldown: " + coolDownTimer, pos - Vector2.UnitY * 120.0f, Color.Red);
|
spriteBatch.DrawString(GUI.Font, "cooldown: " + coolDownTimer, pos - Vector2.UnitY * 120.0f, Color.Red);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void FillNetworkData(NetBuffer message)
|
|
||||||
{
|
|
||||||
message.WriteRangedInteger(0, Enum.GetValues(typeof(AiState)).Length-1, (int)state);
|
|
||||||
|
|
||||||
//bool wallAttack = (wallAttackPos != Vector2.Zero && state == AiState.Attack);
|
|
||||||
|
|
||||||
//message.Write(wallAttack);
|
|
||||||
|
|
||||||
message.Write(MathUtils.AngleToByte(steeringManager.WanderAngle));
|
|
||||||
|
|
||||||
coolDownTimer = MathHelper.Clamp(coolDownTimer, 0.0f, 30.0f);
|
|
||||||
message.WriteRangedSingle(coolDownTimer, 0.0f, 30.0f, 8);
|
|
||||||
|
|
||||||
message.Write(targetEntity==null ? (ushort)0 : (targetEntity as Entity).ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ReadNetworkData(NetIncomingMessage message)
|
|
||||||
{
|
|
||||||
AiState newState = AiState.None;
|
|
||||||
Vector2 newWallAttackPos = Vector2.Zero;
|
|
||||||
float wanderAngle;
|
|
||||||
|
|
||||||
ushort targetID;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
newState = (AiState)message.ReadRangedInteger(0, Enum.GetValues(typeof(AiState)).Length - 1);
|
|
||||||
|
|
||||||
//bool wallAttack = message.ReadBoolean();
|
|
||||||
|
|
||||||
//if (wallAttack)
|
|
||||||
//{
|
|
||||||
// newWallAttackPos = new Vector2(
|
|
||||||
// message.ReadRangedSingle(-50.0f, 50.0f, 10),
|
|
||||||
// message.ReadRangedSingle(-50.0f, 50.0f, 10));
|
|
||||||
|
|
||||||
// newWallAttackPos += Submarine.Loaded.SimPosition;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//newVelocity = new Vector2(message.ReadFloat(), message.ReadFloat());
|
|
||||||
|
|
||||||
//targetPosition = new Vector2(message.ReadFloat(), message.ReadFloat());
|
|
||||||
|
|
||||||
wanderAngle = MathUtils.ByteToAngle(message.ReadByte());
|
|
||||||
|
|
||||||
coolDownTimer = message.ReadRangedSingle(0.0f, 30.0f, 8);
|
|
||||||
|
|
||||||
targetID = message.ReadUInt16();
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
DebugConsole.ThrowError("Failed to read enemy ai update message", e);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
steeringManager.WanderAngle = wanderAngle;
|
|
||||||
|
|
||||||
if (targetID > 0) targetEntity = Entity.FindEntityByID(targetID) as IDamageable;
|
|
||||||
//updateTargetsTimer = UpdateTargetsInterval;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//the "memory" of the Character
|
//the "memory" of the Character
|
||||||
|
|||||||
@@ -86,180 +86,5 @@ namespace Barotrauma
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool FillNetworkData(NetworkEventType type, NetBuffer message, object data)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case NetworkEventType.KillCharacter:
|
|
||||||
return true;
|
|
||||||
case NetworkEventType.ImportantEntityUpdate:
|
|
||||||
|
|
||||||
message.Write(AnimController.RefLimb.SimPosition.X);
|
|
||||||
message.Write(AnimController.RefLimb.SimPosition.Y);
|
|
||||||
|
|
||||||
//message.Write(AnimController.RefLimb.Rotation);
|
|
||||||
|
|
||||||
message.Write((byte)((health / maxHealth) * 255.0f));
|
|
||||||
|
|
||||||
message.Write(AnimController.StunTimer > 0.0f);
|
|
||||||
if (AnimController.StunTimer > 0.0f)
|
|
||||||
{
|
|
||||||
message.WriteRangedSingle(MathHelper.Clamp(AnimController.StunTimer, 0.0f, 60.0f), 0.0f, 60.0f, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DoesBleed)
|
|
||||||
{
|
|
||||||
Bleeding = MathHelper.Clamp(Bleeding, 0.0f, 5.0f);
|
|
||||||
message.WriteRangedSingle(Bleeding, 0.0f, 5.0f, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
aiController.FillNetworkData(message);
|
|
||||||
return true;
|
|
||||||
case NetworkEventType.EntityUpdate:
|
|
||||||
|
|
||||||
message.Write(AnimController.Dir > 0.0f);
|
|
||||||
message.WriteRangedSingle(MathHelper.Clamp(AnimController.TargetMovement.X, -1.0f, 1.0f), -1.0f, 1.0f, 4);
|
|
||||||
message.WriteRangedSingle(MathHelper.Clamp(AnimController.TargetMovement.Y, -1.0f, 1.0f), -1.0f, 1.0f, 4);
|
|
||||||
|
|
||||||
if (AnimController.CanEnterSubmarine) message.Write(Submarine != null);
|
|
||||||
|
|
||||||
message.Write(AnimController.RefLimb.SimPosition.X);
|
|
||||||
message.Write(AnimController.RefLimb.SimPosition.Y);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
case NetworkEventType.InventoryUpdate:
|
|
||||||
return base.FillNetworkData(type, message, data);
|
|
||||||
default:
|
|
||||||
#if DEBUG
|
|
||||||
DebugConsole.ThrowError("AICharacter network event had a wrong type ("+type+")");
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool ReadNetworkData(NetworkEventType type, NetIncomingMessage message, float sendingTime, out object data)
|
|
||||||
{
|
|
||||||
data = null;
|
|
||||||
Enabled = true;
|
|
||||||
|
|
||||||
//server doesn't accept AICharacter updates from the clients
|
|
||||||
if (GameMain.Server != null) return false;
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case NetworkEventType.KillCharacter:
|
|
||||||
|
|
||||||
Kill(CauseOfDeath.Damage, true);
|
|
||||||
break;
|
|
||||||
case NetworkEventType.InventoryUpdate:
|
|
||||||
return base.ReadNetworkData(type, message, sendingTime, out data);
|
|
||||||
case NetworkEventType.ImportantEntityUpdate:
|
|
||||||
|
|
||||||
Vector2 limbPos = AnimController.RefLimb.SimPosition;
|
|
||||||
float rotation = AnimController.RefLimb.Rotation;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
limbPos.X = message.ReadFloat();
|
|
||||||
limbPos.Y = message.ReadFloat();
|
|
||||||
|
|
||||||
//rotation = message.ReadFloat();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
DebugConsole.ThrowError("Failed to read AICharacter update message", e);
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AnimController.RefLimb.body != null)
|
|
||||||
{
|
|
||||||
AnimController.RefLimb.body.TargetPosition = limbPos;
|
|
||||||
//AnimController.RefLimb.body.TargetRotation = rotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
float newStunTimer = 0.0f, newHealth = 0.0f, newBleeding = 0.0f;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
newHealth = (message.ReadByte() / 255.0f) * maxHealth;
|
|
||||||
|
|
||||||
if (message.ReadBoolean())
|
|
||||||
{
|
|
||||||
newStunTimer = message.ReadRangedSingle(0.0f, 60.0f, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DoesBleed)
|
|
||||||
{
|
|
||||||
newBleeding = message.ReadRangedSingle(0.0f, 5.0f, 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
DebugConsole.ThrowError("Failed to read AICharacter update message", e);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimController.StunTimer = newStunTimer;
|
|
||||||
health = newHealth;
|
|
||||||
|
|
||||||
Bleeding = newBleeding;
|
|
||||||
|
|
||||||
aiController.ReadNetworkData(message);
|
|
||||||
break;
|
|
||||||
case NetworkEventType.EntityUpdate:
|
|
||||||
if (sendingTime <= LastNetworkUpdate) return false;
|
|
||||||
|
|
||||||
Vector2 targetMovement = Vector2.Zero, pos = Vector2.Zero;
|
|
||||||
bool targetDir = false,inSub = false;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
targetDir = message.ReadBoolean();
|
|
||||||
targetMovement.X = message.ReadRangedSingle(-1.0f, 1.0f, 4);
|
|
||||||
targetMovement.Y = message.ReadRangedSingle(-1.0f, 1.0f, 4);
|
|
||||||
|
|
||||||
if (AnimController.CanEnterSubmarine) inSub = message.ReadBoolean();
|
|
||||||
|
|
||||||
pos.X = message.ReadFloat();
|
|
||||||
pos.Y = message.ReadFloat();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
DebugConsole.ThrowError("Failed to read AICharacter update message", e);
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimController.TargetDir = (targetDir) ? Direction.Right : Direction.Left;
|
|
||||||
AnimController.TargetMovement = targetMovement;
|
|
||||||
|
|
||||||
AnimController.RefLimb.body.TargetPosition = pos;
|
|
||||||
//AnimController.EstimateCurrPosition(pos, (float)(NetTime.Now) - sendingTime);
|
|
||||||
|
|
||||||
if (inSub)
|
|
||||||
{
|
|
||||||
Hull newHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(pos), AnimController.CurrentHull, false);
|
|
||||||
if (newHull != null)
|
|
||||||
{
|
|
||||||
AnimController.CurrentHull = newHull;
|
|
||||||
Submarine = newHull.Submarine;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LastNetworkUpdate = sendingTime;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1448,436 +1448,7 @@ namespace Barotrauma
|
|||||||
GameMain.GameSession.ReviveCharacter(this);
|
GameMain.GameSession.ReviveCharacter(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool FillNetworkData(NetworkEventType type, NetBuffer message, object data)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case NetworkEventType.PickItem:
|
|
||||||
int[] pickData = (int[])data;
|
|
||||||
if (pickData.Length != 3) return false;
|
|
||||||
|
|
||||||
message.Write((ushort)pickData[0]);
|
|
||||||
message.Write((int)pickData[1] == 1);
|
|
||||||
message.Write((int)pickData[2] == 1);
|
|
||||||
|
|
||||||
var pickedItem = Entity.FindEntityByID((ushort)pickData[0]);
|
|
||||||
message.Write(pickedItem != null && selectedConstruction == pickedItem);
|
|
||||||
|
|
||||||
message.WritePadBits();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
case NetworkEventType.SelectCharacter:
|
|
||||||
message.Write(AnimController.Anim == AnimController.Animation.CPR);
|
|
||||||
message.Write((ushort)data);
|
|
||||||
return true;
|
|
||||||
case NetworkEventType.KillCharacter:
|
|
||||||
CauseOfDeath causeOfDeath = CauseOfDeath.Damage;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
causeOfDeath = (CauseOfDeath)data;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
causeOfDeath = CauseOfDeath.Damage;
|
|
||||||
}
|
|
||||||
|
|
||||||
message.Write((byte)causeOfDeath);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
case NetworkEventType.InventoryUpdate:
|
|
||||||
if (inventory == null) return false;
|
|
||||||
return inventory.FillNetworkData(NetworkEventType.InventoryUpdate, message, data);
|
|
||||||
case NetworkEventType.ApplyStatusEffect:
|
|
||||||
message.Write((ushort)data);
|
|
||||||
return true;
|
|
||||||
case NetworkEventType.ImportantEntityUpdate:
|
|
||||||
|
|
||||||
message.WriteRangedSingle(health, minHealth, maxHealth, 8);
|
|
||||||
|
|
||||||
//if (health > 0.0f)
|
|
||||||
//{
|
|
||||||
// message.Write(Math.Max((byte)((health / maxHealth) * 255.0f), (byte)1));
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// message.Write((byte)0);
|
|
||||||
// message.WriteRangedInteger(0, Enum.GetValues(typeof(CauseOfDeath)).Length-1, (int)lastAttackCauseOfDeath);
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (AnimController.StunTimer <= 0.0f && bleeding <= 0.0f && oxygen > 99.0f)
|
|
||||||
{
|
|
||||||
message.Write(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
message.Write(false);
|
|
||||||
|
|
||||||
message.WriteRangedSingle(MathHelper.Clamp(AnimController.StunTimer, 0.0f, 60.0f), 0.0f, 60.0f, 8);
|
|
||||||
|
|
||||||
message.WriteRangedSingle(oxygen, -100.0f, 100.0f, 8);
|
|
||||||
|
|
||||||
bleeding = MathHelper.Clamp(bleeding, 0.0f, 5.0f);
|
|
||||||
message.WriteRangedSingle(bleeding, 0.0f, 5.0f, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
case NetworkEventType.EntityUpdate:
|
|
||||||
message.Write(keys[(int)InputType.Use].GetHeldQueue);
|
|
||||||
|
|
||||||
bool secondaryHeld = keys[(int)InputType.Aim].GetHeldQueue;
|
|
||||||
message.Write(secondaryHeld);
|
|
||||||
|
|
||||||
message.Write(keys[(int)InputType.Left].Held);
|
|
||||||
message.Write(keys[(int)InputType.Right].Held);
|
|
||||||
|
|
||||||
message.Write(keys[(int)InputType.Up].Held);
|
|
||||||
message.Write(keys[(int)InputType.Down].Held);
|
|
||||||
|
|
||||||
message.Write(keys[(int)InputType.Run].Held);
|
|
||||||
|
|
||||||
message.Write(((HumanoidAnimController)AnimController).Crouching);
|
|
||||||
|
|
||||||
|
|
||||||
if (secondaryHeld)
|
|
||||||
{
|
|
||||||
if (Character.controlled==this)
|
|
||||||
{
|
|
||||||
ViewTarget = Lights.LightManager.ViewTarget == null ? this : Lights.LightManager.ViewTarget;
|
|
||||||
}
|
|
||||||
if (ViewTarget == null) ViewTarget = this;
|
|
||||||
|
|
||||||
Vector2 relativeCursorPosition = cursorPosition;
|
|
||||||
relativeCursorPosition -= ViewTarget.Position;
|
|
||||||
|
|
||||||
if (relativeCursorPosition.Length()>500.0f)
|
|
||||||
{
|
|
||||||
relativeCursorPosition = Vector2.Normalize(relativeCursorPosition) * 495.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
message.Write(ViewTarget.ID);
|
|
||||||
|
|
||||||
message.WriteRangedSingle(relativeCursorPosition.X, -500.0f, 500.0f, 8);
|
|
||||||
message.WriteRangedSingle(relativeCursorPosition.Y, -500.0f, 500.0f, 8);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
message.Write(AnimController.Dir > 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GameMain.Server != null)
|
|
||||||
{
|
|
||||||
message.Write(Submarine != null);
|
|
||||||
|
|
||||||
//Vector2 position = Submarine == null ? SimPosition : SimPosition - Submarine.SimPosition;
|
|
||||||
|
|
||||||
//if ((AnimController.RefLimb.SimPosition - Submarine.Loaded.SimPosition).Length() > NetConfig.CharacterIgnoreDistance) return true;
|
|
||||||
|
|
||||||
message.Write(SimPosition.X);
|
|
||||||
message.Write(SimPosition.Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
networkUpdateSent = true;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
#if DEBUG
|
|
||||||
DebugConsole.ThrowError("Character "+this+" tried to fill a networkevent of the wrong type: "+type);
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool ReadNetworkData(NetworkEventType type, NetIncomingMessage message, float sendingTime, out object data)
|
|
||||||
{
|
|
||||||
Enabled = true;
|
|
||||||
data = null;
|
|
||||||
|
|
||||||
if (GameMain.Server != null && type != NetworkEventType.InventoryUpdate)
|
|
||||||
{
|
|
||||||
Client sender = GameMain.Server.ConnectedClients.Find(c => c.Connection == message.SenderConnection);
|
|
||||||
if (sender == null || sender.Character != this)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
DebugConsole.ThrowError("Received a character update message from someone else than the client controlling the Character!");
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case NetworkEventType.PickItem:
|
|
||||||
|
|
||||||
ushort itemId = message.ReadUInt16();
|
|
||||||
|
|
||||||
bool pickHit = message.ReadBoolean();
|
|
||||||
bool actionHit = message.ReadBoolean();
|
|
||||||
|
|
||||||
bool isSelected = message.ReadBoolean();
|
|
||||||
|
|
||||||
data = new int[] { (int)itemId, pickHit ? 1 : 0, actionHit ? 1: 0 };
|
|
||||||
|
|
||||||
System.Diagnostics.Debug.WriteLine("item id: "+itemId);
|
|
||||||
|
|
||||||
Item pickedItem = FindEntityByID(itemId) as Item;
|
|
||||||
if (pickedItem != null)
|
|
||||||
{
|
|
||||||
if (!CanAccessItem(pickedItem)) return false;
|
|
||||||
|
|
||||||
if (pickedItem == selectedConstruction)
|
|
||||||
{
|
|
||||||
GameServer.Log(Name + " deselected " + pickedItem.Name, Color.Orange);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GameServer.Log(Name + " selected " + pickedItem.Name, Color.Orange);
|
|
||||||
}
|
|
||||||
pickedItem.Pick(this, false, pickHit, actionHit);
|
|
||||||
selectedConstruction = isSelected ? pickedItem : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case NetworkEventType.SelectCharacter:
|
|
||||||
bool performingCPR = message.ReadBoolean();
|
|
||||||
|
|
||||||
ushort characterId = message.ReadUInt16();
|
|
||||||
data = characterId;
|
|
||||||
|
|
||||||
if (characterId==0)
|
|
||||||
{
|
|
||||||
DeselectCharacter(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Character character = FindEntityByID(characterId) as Character;
|
|
||||||
if (character == null || !character.IsHumanoid) return true;
|
|
||||||
|
|
||||||
SelectCharacter(character, false);
|
|
||||||
if (performingCPR)
|
|
||||||
{
|
|
||||||
AnimController.Anim = AnimController.Animation.CPR;
|
|
||||||
|
|
||||||
foreach (Limb limb in selectedCharacter.AnimController.Limbs)
|
|
||||||
{
|
|
||||||
limb.pullJoint.Enabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (AnimController.Anim == AnimController.Animation.CPR)
|
|
||||||
{
|
|
||||||
AnimController.Anim = AnimController.Animation.None;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case NetworkEventType.KillCharacter:
|
|
||||||
CauseOfDeath causeOfDeath = CauseOfDeath.Damage;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
byte causeOfDeathByte = message.ReadByte();
|
|
||||||
causeOfDeath = (CauseOfDeath)causeOfDeathByte;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
causeOfDeath = CauseOfDeath.Damage;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = causeOfDeath;
|
|
||||||
|
|
||||||
if (causeOfDeath == CauseOfDeath.Pressure)
|
|
||||||
{
|
|
||||||
Implode(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Kill(causeOfDeath, true);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NetworkEventType.InventoryUpdate:
|
|
||||||
if (inventory == null) return false;
|
|
||||||
|
|
||||||
inventory.ReadNetworkData(NetworkEventType.InventoryUpdate, message, sendingTime);
|
|
||||||
return true;
|
|
||||||
case NetworkEventType.ApplyStatusEffect:
|
|
||||||
ushort id = message.ReadUInt16();
|
|
||||||
|
|
||||||
data = id;
|
|
||||||
|
|
||||||
var item = FindEntityByID(id) as Item;
|
|
||||||
if (item == null) return false;
|
|
||||||
|
|
||||||
item.ApplyStatusEffects(ActionType.OnUse, 1.0f, this);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case NetworkEventType.ImportantEntityUpdate:
|
|
||||||
|
|
||||||
if (GameMain.Server != null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
health = message.ReadRangedSingle(minHealth, 100.0f, 8);
|
|
||||||
|
|
||||||
bool allOk = message.ReadBoolean();
|
|
||||||
if (allOk)
|
|
||||||
{
|
|
||||||
bleeding = 0.0f;
|
|
||||||
Oxygen = 100.0f;
|
|
||||||
AnimController.StunTimer = 0.0f;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
float newStunTimer = message.ReadRangedSingle(0.0f, 60.0f, 8);
|
|
||||||
StartStun(newStunTimer, true);
|
|
||||||
|
|
||||||
Oxygen = message.ReadRangedSingle(-100.0f,100.0f, 8);
|
|
||||||
Bleeding = message.ReadRangedSingle(0.0f, 5.0f, 8);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case NetworkEventType.EntityUpdate:
|
|
||||||
Vector2 relativeCursorPos = Vector2.Zero;
|
|
||||||
|
|
||||||
bool actionKeyState, secondaryKeyState;
|
|
||||||
bool leftKeyState, rightKeyState, upKeyState, downKeyState;
|
|
||||||
bool runState, crouchState;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (sendingTime > LastNetworkUpdate) ClearInputs();
|
|
||||||
|
|
||||||
actionKeyState = message.ReadBoolean();
|
|
||||||
secondaryKeyState = message.ReadBoolean();
|
|
||||||
|
|
||||||
leftKeyState = message.ReadBoolean();
|
|
||||||
rightKeyState = message.ReadBoolean();
|
|
||||||
upKeyState = message.ReadBoolean();
|
|
||||||
downKeyState = message.ReadBoolean();
|
|
||||||
|
|
||||||
runState = message.ReadBoolean();
|
|
||||||
crouchState = message.ReadBoolean();
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
DebugConsole.ThrowError("Error in Character.ReadNetworkData: " + e.Message);
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GameMain.Server != null && (isDead || IsUnconscious)) return false;
|
|
||||||
|
|
||||||
keys[(int)InputType.Use].Held = actionKeyState;
|
|
||||||
keys[(int)InputType.Use].SetState(false, actionKeyState);
|
|
||||||
|
|
||||||
keys[(int)InputType.Aim].Held = secondaryKeyState;
|
|
||||||
keys[(int)InputType.Aim].SetState(false, secondaryKeyState);
|
|
||||||
|
|
||||||
if (sendingTime <= LastNetworkUpdate) return false;
|
|
||||||
|
|
||||||
keys[(int)InputType.Left].Held = leftKeyState;
|
|
||||||
keys[(int)InputType.Right].Held = rightKeyState;
|
|
||||||
|
|
||||||
keys[(int)InputType.Up].Held = upKeyState;
|
|
||||||
keys[(int)InputType.Down].Held = downKeyState;
|
|
||||||
|
|
||||||
keys[(int)InputType.Run].Held = runState;
|
|
||||||
|
|
||||||
keys[(int)InputType.Crouch].Held = crouchState;
|
|
||||||
|
|
||||||
|
|
||||||
float dir = 1.0f;
|
|
||||||
Vector2 pos = Vector2.Zero;
|
|
||||||
|
|
||||||
ushort viewTargetID = 0;
|
|
||||||
ViewTarget = null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (secondaryKeyState)
|
|
||||||
{
|
|
||||||
viewTargetID = message.ReadUInt16();
|
|
||||||
|
|
||||||
relativeCursorPos = new Vector2(
|
|
||||||
message.ReadRangedSingle(-500.0f, 500.0f, 8),
|
|
||||||
message.ReadRangedSingle(-500.0f, 500.0f, 8));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dir = message.ReadBoolean() ? 1.0f : -1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
DebugConsole.ThrowError("Failed to read networkevent for "+this.ToString());
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GameMain.Server == null)
|
|
||||||
{
|
|
||||||
bool inSub = message.ReadBoolean();
|
|
||||||
|
|
||||||
pos.X = message.ReadFloat();
|
|
||||||
pos.Y = message.ReadFloat();
|
|
||||||
|
|
||||||
if (inSub != (Submarine != null))
|
|
||||||
{
|
|
||||||
AnimController.Teleport(pos - SimPosition, Vector2.Zero);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inSub)
|
|
||||||
{
|
|
||||||
//AnimController.FindHull(ConvertUnits.ToDisplayUnits(pos) - Submarine.Loaded.WorldPosition);
|
|
||||||
|
|
||||||
Hull newHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(pos), AnimController.CurrentHull, false);
|
|
||||||
if (newHull != null)
|
|
||||||
{
|
|
||||||
AnimController.CurrentHull = newHull;
|
|
||||||
Submarine = newHull.Submarine;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AnimController.CurrentHull = null;
|
|
||||||
Submarine = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (secondaryKeyState)
|
|
||||||
{
|
|
||||||
cursorPosition = MathUtils.IsValid(relativeCursorPos) ? relativeCursorPos : Vector2.Zero;
|
|
||||||
ViewTarget = viewTargetID == 0 ? this : Entity.FindEntityByID(viewTargetID);
|
|
||||||
if (ViewTarget == null) ViewTarget = this;
|
|
||||||
|
|
||||||
cursorPosition += ViewTarget.Position;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cursorPosition = Position + new Vector2(1000.0f, 0.0f) * dir;
|
|
||||||
|
|
||||||
AnimController.TargetDir = dir < 0 ? Direction.Left : Direction.Right;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GameMain.Server == null)
|
|
||||||
{
|
|
||||||
AnimController.RefLimb.body.TargetPosition =
|
|
||||||
AnimController.EstimateCurrPosition(pos, (float)(NetTime.Now) - sendingTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
LastNetworkUpdate = sendingTime;
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
#if DEBUG
|
|
||||||
DebugConsole.ThrowError("Character " + this + " tried to read a networkevent of the wrong type: " + type);
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Remove()
|
public override void Remove()
|
||||||
{
|
{
|
||||||
base.Remove();
|
base.Remove();
|
||||||
|
|||||||
@@ -498,89 +498,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool FillNetworkData(NetworkEventType type, NetBuffer message, object data)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < capacity; i++)
|
|
||||||
{
|
|
||||||
message.Write(Items[i]==null ? (ushort)0 : (ushort)Items[i].ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message, float sendingTime)
|
|
||||||
{
|
|
||||||
if (sendingTime < lastUpdate) return;
|
|
||||||
|
|
||||||
character.ClearInput(InputType.Use);
|
|
||||||
|
|
||||||
List<Item> droppedItems = new List<Item>();
|
|
||||||
List<Item> prevItems = new List<Item>(Items);
|
|
||||||
|
|
||||||
for (int i = 0; i<capacity; i++)
|
|
||||||
{
|
|
||||||
ushort itemId = message.ReadUInt16();
|
|
||||||
if (itemId == 0)
|
|
||||||
{
|
|
||||||
if (Items[i] != null)
|
|
||||||
{
|
|
||||||
droppedItems.Add(Items[i]);
|
|
||||||
Items[i].Drop(character, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Item item = Entity.FindEntityByID(itemId) as Item;
|
|
||||||
if (item == null) continue;
|
|
||||||
|
|
||||||
//item already in the right slot, no need to do anything
|
|
||||||
if (Items[i] == item) continue;
|
|
||||||
|
|
||||||
//if the item is in the inventory of some other character and said character isn't dead/unconscious,
|
|
||||||
//don't let this character pick it up
|
|
||||||
if (GameMain.Server != null)
|
|
||||||
{
|
|
||||||
var owner = item.ParentInventory == null ? null : item.ParentInventory.Owner as Character;
|
|
||||||
if (owner != null && owner != character)
|
|
||||||
{
|
|
||||||
if (!character.CanAccessItem(item)) return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//some other item already in the slot -> drop it
|
|
||||||
if (Items[i] != null) Items[i].Drop(character, false);
|
|
||||||
|
|
||||||
if (TryPutItem(item, i, false, false))
|
|
||||||
{
|
|
||||||
if (droppedItems.Contains(item)) droppedItems.Remove(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lastUpdate = sendingTime;
|
|
||||||
|
|
||||||
if (GameMain.Server == null) return;
|
|
||||||
|
|
||||||
var sender = GameMain.Server.ConnectedClients.Find(c => c.Connection == message.SenderConnection);
|
|
||||||
if (sender != null && sender.Character != null)
|
|
||||||
{
|
|
||||||
foreach (Item item in droppedItems)
|
|
||||||
{
|
|
||||||
GameServer.Log(sender.Character == character ?
|
|
||||||
character.Name + " dropped " + item.Name :
|
|
||||||
sender.Character + " removed " + item.Name + " from " + character + "'s inventory", Color.Orange);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (Item item in Items)
|
|
||||||
{
|
|
||||||
if (item == null || prevItems.Contains(item)) continue;
|
|
||||||
GameServer.Log(sender.Character == character ?
|
|
||||||
character.Name + " picked up " + item.Name :
|
|
||||||
sender.Character + " placed " + item.Name + " in " + character + "'s inventory", Color.Orange);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -651,65 +651,6 @@ namespace Barotrauma.Items.Components
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message)
|
|
||||||
{
|
|
||||||
message.Write(docked);
|
|
||||||
|
|
||||||
if (docked)
|
|
||||||
{
|
|
||||||
message.Write(dockingTarget.item.ID);
|
|
||||||
message.Write((ushort)hullIds[0]);
|
|
||||||
message.Write((ushort)hullIds[1]);
|
|
||||||
|
|
||||||
message.Write((ushort)gapId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message, float sendingTime)
|
|
||||||
{
|
|
||||||
bool isDocked = message.ReadBoolean();
|
|
||||||
|
|
||||||
if (isDocked)
|
|
||||||
{
|
|
||||||
ushort dockingTargetID = message.ReadUInt16();
|
|
||||||
Entity targetEntity = Entity.FindEntityByID(dockingTargetID);
|
|
||||||
if (targetEntity == null || !(targetEntity is Item))
|
|
||||||
{
|
|
||||||
DebugConsole.ThrowError("Invalid docking port network event (can't dock to "+targetEntity.ToString()+")");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dockingTarget = (targetEntity as Item).GetComponent<DockingPort>();
|
|
||||||
|
|
||||||
if (dockingTarget == null)
|
|
||||||
{
|
|
||||||
DebugConsole.ThrowError("Invalid docking port network event ("+targetEntity+" doesn't have a docking port component)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hullIds[0] = message.ReadUInt16();
|
|
||||||
hullIds[1] = message.ReadUInt16();
|
|
||||||
|
|
||||||
gapId = message.ReadUInt16();
|
|
||||||
if (hulls != null)
|
|
||||||
{
|
|
||||||
if (hulls[0] != null) hulls[0].ID = (ushort)hullIds[0];
|
|
||||||
if (hulls[1] != null) hulls[1].ID = (ushort)hullIds[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (gap != null) gap.ID = (ushort)gapId;
|
|
||||||
|
|
||||||
Dock(dockingTarget);
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Undock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -476,21 +476,6 @@ namespace Barotrauma.Items.Components
|
|||||||
item.NewComponentEvent(this, false, true);
|
item.NewComponentEvent(this, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message)
|
|
||||||
{
|
|
||||||
message.Write(isOpen);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message, float sendingTime)
|
|
||||||
{
|
|
||||||
if (sendingTime < lastReceivedMessage) return;
|
|
||||||
|
|
||||||
lastReceivedMessage = sendingTime;
|
|
||||||
|
|
||||||
SetState(message.ReadBoolean(), true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -286,42 +286,6 @@ namespace Barotrauma.Items.Components
|
|||||||
Msg = "";
|
Msg = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message)
|
|
||||||
{
|
|
||||||
message.Write(item.SimPosition.X);
|
|
||||||
message.Write(item.SimPosition.Y);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message, float sendingTime)
|
|
||||||
{
|
|
||||||
Vector2 newPos = Vector2.Zero;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
newPos = new Vector2(message.ReadFloat(), message.ReadFloat());
|
|
||||||
}
|
|
||||||
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
item.SetTransform(newPos, 0.0f);
|
|
||||||
if (!attached)
|
|
||||||
{
|
|
||||||
Use(1.0f);
|
|
||||||
|
|
||||||
if (GameMain.Server == null) return;
|
|
||||||
|
|
||||||
var sender = GameMain.Server.ConnectedClients.Find(c => c.Connection == message.SenderConnection);
|
|
||||||
if (sender != null && sender.Character != null)
|
|
||||||
{
|
|
||||||
Networking.GameServer.Log(sender.characterInfo.Name+" attached a "+item.Name+" on a wall", Color.Orange);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -789,14 +789,6 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
return ic;
|
return ic;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool FillNetworkData(NetworkEventType type, NetBuffer message)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void ReadNetworkData(NetworkEventType type, NetIncomingMessage message, float sendingTime)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,30 +125,6 @@ namespace Barotrauma.Items.Components
|
|||||||
container.Inventory.Locked = IsActive;
|
container.Inventory.Locked = IsActive;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message)
|
|
||||||
{
|
|
||||||
|
|
||||||
var containers = item.GetComponents<ItemContainer>();
|
|
||||||
containers[0].Inventory.FillNetworkData(type, message, null);
|
|
||||||
containers[1].Inventory.FillNetworkData(type, message, null);
|
|
||||||
|
|
||||||
message.Write(IsActive);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message, float sendingTime)
|
|
||||||
{
|
|
||||||
if (sendingTime < lastNetworkUpdate) return;
|
|
||||||
|
|
||||||
var containers = item.GetComponents<ItemContainer>();
|
|
||||||
containers[0].Inventory.ReadNetworkData(type, message, sendingTime);
|
|
||||||
containers[1].Inventory.ReadNetworkData(type, message, sendingTime);
|
|
||||||
|
|
||||||
SetActive(message.ReadBoolean());
|
|
||||||
|
|
||||||
lastNetworkUpdate = sendingTime;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -367,46 +367,6 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message)
|
|
||||||
{
|
|
||||||
int itemIndex = fabricatedItem == null ? -1 : fabricableItems.IndexOf(fabricatedItem);
|
|
||||||
|
|
||||||
message.WriteRangedInteger(-1, fabricableItems.Count-1, itemIndex);
|
|
||||||
|
|
||||||
var containers = item.GetComponents<ItemContainer>();
|
|
||||||
containers[0].Inventory.FillNetworkData(type, message, null);
|
|
||||||
containers[1].Inventory.FillNetworkData(type, message, null);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message, float sendingTime)
|
|
||||||
{
|
|
||||||
if (sendingTime < lastNetworkUpdate) return;
|
|
||||||
|
|
||||||
int itemIndex = message.ReadRangedInteger(-1, fabricableItems.Count-1);
|
|
||||||
|
|
||||||
var containers = item.GetComponents<ItemContainer>();
|
|
||||||
containers[0].Inventory.ReadNetworkData(type, message, sendingTime);
|
|
||||||
containers[1].Inventory.ReadNetworkData(type, message, sendingTime);
|
|
||||||
|
|
||||||
if (itemIndex == -1)
|
|
||||||
{
|
|
||||||
CancelFabricating();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//if already fabricating the selected item, return
|
|
||||||
if (fabricatedItem != null && fabricableItems.IndexOf(fabricatedItem) != itemIndex) return;
|
|
||||||
|
|
||||||
if (itemIndex < 0 || itemIndex >= fabricableItems.Count) return;
|
|
||||||
|
|
||||||
SelectItem(null, fabricableItems[itemIndex]);
|
|
||||||
StartFabricating(fabricableItems[itemIndex]);
|
|
||||||
}
|
|
||||||
|
|
||||||
lastNetworkUpdate = sendingTime;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,50 +194,6 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (!IsActive) currPowerConsumption = 0.0f;
|
if (!IsActive) currPowerConsumption = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message)
|
|
||||||
{
|
|
||||||
message.WriteRangedInteger(-10, 10, (int)(flowPercentage / 10.0f));
|
|
||||||
message.Write(IsActive);
|
|
||||||
message.WritePadBits();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message, float sendingTime)
|
|
||||||
{
|
|
||||||
float newFlow = 0.0f;
|
|
||||||
bool newActive;
|
|
||||||
|
|
||||||
if (sendingTime < lastUpdate) return;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
newFlow = message.ReadRangedInteger(-10,10)*10.0f;
|
|
||||||
newActive = message.ReadBoolean();
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
DebugConsole.ThrowError("invalid network message", e);
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FlowPercentage = newFlow;
|
|
||||||
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, Color.Orange);
|
|
||||||
Networking.GameServer.Log("Active: " + (IsActive ? "yes" : "no ") + " Pumping speed: " + (int)flowPercentage + " %", Color.Orange);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -405,26 +405,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (screenOverlay != null) screenOverlay.Remove();
|
if (screenOverlay != null) screenOverlay.Remove();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message)
|
|
||||||
{
|
|
||||||
message.Write(IsActive);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message, float sendingTime)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
IsActive = message.ReadBoolean();
|
|
||||||
isActiveTickBox.Selected = IsActive;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class RadarBlip
|
class RadarBlip
|
||||||
|
|||||||
@@ -535,72 +535,6 @@ namespace Barotrauma.Items.Components
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool FillNetworkData(NetworkEventType type, NetBuffer message)
|
|
||||||
{
|
|
||||||
message.Write(autoTemp);
|
|
||||||
if (GameMain.Server != null)
|
|
||||||
{
|
|
||||||
message.WriteRangedSingle(temperature, 0.0f, 10000.0f, 16);
|
|
||||||
}
|
|
||||||
message.WriteRangedSingle(shutDownTemp, 0.0f, 10000.0f, 8);
|
|
||||||
|
|
||||||
message.WriteRangedSingle(coolingRate, 0.0f, 100.0f, 8);
|
|
||||||
message.WriteRangedSingle(fissionRate, 0.0f, 100.0f, 8);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message, float sendingTime)
|
|
||||||
{
|
|
||||||
if (sendingTime < lastUpdate) return;
|
|
||||||
|
|
||||||
bool newAutoTemp;
|
|
||||||
float newTemperature = Temperature, newShutDownTemp;
|
|
||||||
float newCoolingRate, newFissionRate;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
newAutoTemp = message.ReadBoolean();
|
|
||||||
if (GameMain.Server == null)
|
|
||||||
{
|
|
||||||
newTemperature = message.ReadRangedSingle(0.0f, 10000.0f, 16);
|
|
||||||
}
|
|
||||||
newShutDownTemp = message.ReadRangedSingle(0.0f, 10000.0f, 8);
|
|
||||||
newShutDownTemp = MathUtils.RoundTowardsClosest(newShutDownTemp, 100.0f);
|
|
||||||
|
|
||||||
newCoolingRate = message.ReadRangedSingle(0.0f, 100.0f, 8);
|
|
||||||
newFissionRate = message.ReadRangedSingle(0.0f, 100.0f, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
DebugConsole.ThrowError("invalid network message", e);
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AutoTemp = newAutoTemp;
|
|
||||||
Temperature = newTemperature;
|
|
||||||
ShutDownTemp = newShutDownTemp;
|
|
||||||
|
|
||||||
CoolingRate = newCoolingRate;
|
|
||||||
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+": \n"+
|
|
||||||
"Autotemp: " + (autoTemp ? "ON " : "OFF") + " Shutdown temp: " + shutDownTemp +
|
|
||||||
" Cooling rate: " + (int)coolingRate + " Fission rate: " + (int)fissionRate,
|
|
||||||
Color.Orange);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -329,59 +329,6 @@ namespace Barotrauma.Items.Components
|
|||||||
base.ReceiveSignal(stepsTaken, signal, connection, sender, power);
|
base.ReceiveSignal(stepsTaken, signal, connection, sender, power);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message)
|
|
||||||
{
|
|
||||||
message.Write(targetVelocity.X);
|
|
||||||
message.Write(targetVelocity.Y);
|
|
||||||
|
|
||||||
message.Write(autoPilot);
|
|
||||||
if (autoPilot)
|
|
||||||
{
|
|
||||||
message.Write(posToMaintain != null);
|
|
||||||
if (posToMaintain != null)
|
|
||||||
{
|
|
||||||
message.Write(((Vector2)posToMaintain).X);
|
|
||||||
message.Write(((Vector2)posToMaintain).Y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message, float sendingTime)
|
|
||||||
{
|
|
||||||
Vector2 newTargetVelocity = Vector2.Zero;
|
|
||||||
bool newAutoPilot = false;
|
|
||||||
|
|
||||||
Vector2? newPosToMaintain = null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
newTargetVelocity = new Vector2(message.ReadFloat(), message.ReadFloat());
|
|
||||||
newAutoPilot = message.ReadBoolean();
|
|
||||||
if (newAutoPilot)
|
|
||||||
{
|
|
||||||
bool maintainPos = message.ReadBoolean();
|
|
||||||
if (maintainPos)
|
|
||||||
{
|
|
||||||
newPosToMaintain = new Vector2(
|
|
||||||
message.ReadFloat(),
|
|
||||||
message.ReadFloat());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TargetVelocity = newTargetVelocity;
|
|
||||||
AutoPilot = newAutoPilot;
|
|
||||||
|
|
||||||
maintainPosTickBox.Selected = newPosToMaintain != null;
|
|
||||||
posToMaintain = newPosToMaintain;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -245,32 +245,6 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
spriteBatch.DrawString(GUI.Font, "Recharge rate: " + (int)((rechargeSpeed / maxRechargeSpeed) * 100.0f) + " %", new Vector2(x + 30, y + 95), Color.White);
|
spriteBatch.DrawString(GUI.Font, "Recharge rate: " + (int)((rechargeSpeed / maxRechargeSpeed) * 100.0f) + " %", new Vector2(x + 30, y + 95), Color.White);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message)
|
|
||||||
{
|
|
||||||
message.WriteRangedSingle(MathHelper.Clamp(rechargeSpeed / MaxRechargeSpeed, 0.0f, 1.0f), 0.0f, 1.0f, 8);
|
|
||||||
message.WriteRangedSingle(MathHelper.Clamp(charge / capacity, 0.0f, 1.0f), 0.0f, 1.0f, 8);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message, float sendingTime)
|
|
||||||
{
|
|
||||||
float newRechargeSpeed = 0f;
|
|
||||||
float newCharge = 0.0f;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
newRechargeSpeed = message.ReadRangedSingle(0.0f, 1.0f, 8);
|
|
||||||
newRechargeSpeed *= MaxRechargeSpeed;
|
|
||||||
newCharge = message.ReadRangedSingle(0.0f, 1.0f, 8);
|
|
||||||
newCharge *= capacity;
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
|
|
||||||
RechargeSpeed = newRechargeSpeed;
|
|
||||||
Charge = newCharge;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,60 +141,5 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message)
|
|
||||||
{
|
|
||||||
foreach (Connection c in Connections)
|
|
||||||
{
|
|
||||||
Wire[] wires = Array.FindAll(c.Wires, w => w != null);
|
|
||||||
message.WriteRangedInteger(0, Connection.MaxLinked, wires.Length);
|
|
||||||
for (int i = 0 ; i < wires.Length; i++)
|
|
||||||
{
|
|
||||||
message.Write(wires[i].Item.ID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
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, Color.Orange);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
System.Diagnostics.Debug.WriteLine("connectionpanel update");
|
|
||||||
foreach (Connection c in Connections)
|
|
||||||
{
|
|
||||||
//int wireCount = c.Wires.Length;
|
|
||||||
c.ClearConnections();
|
|
||||||
|
|
||||||
int wireCount = message.ReadRangedInteger(0, Connection.MaxLinked);
|
|
||||||
|
|
||||||
for (int i = 0; i < wireCount; i++)
|
|
||||||
{
|
|
||||||
ushort wireId = message.ReadUInt16();
|
|
||||||
|
|
||||||
Item wireItem = MapEntity.FindEntityByID(wireId) as Item;
|
|
||||||
if (wireItem == null) continue;
|
|
||||||
|
|
||||||
Wire wireComponent = wireItem.GetComponent<Wire>();
|
|
||||||
if (wireComponent == null) continue;
|
|
||||||
|
|
||||||
c.Wires[i] = wireComponent;
|
|
||||||
wireComponent.Connect(c, false);
|
|
||||||
|
|
||||||
var otherConnection = c.Wires[i].OtherConnection(c);
|
|
||||||
Networking.GameServer.Log(
|
|
||||||
item.Name+" ("+ c.Name + ") -> " +
|
|
||||||
(otherConnection == null ? "none" : otherConnection.Item.Name+" ("+(otherConnection.Name)+")"), Color.Orange);
|
|
||||||
}
|
|
||||||
c.UpdateRecipients();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -525,35 +525,6 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
base.RemoveComponentSpecific();
|
base.RemoveComponentSpecific();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message)
|
|
||||||
{
|
|
||||||
message.Write((byte)Math.Min(Nodes.Count, 10));
|
|
||||||
for (int i = 0; i < Math.Min(Nodes.Count,10); i++)
|
|
||||||
{
|
|
||||||
message.Write(Nodes[i].X);
|
|
||||||
message.Write(Nodes[i].Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message, float sendingTime)
|
|
||||||
{
|
|
||||||
Nodes.Clear();
|
|
||||||
|
|
||||||
List<Vector2> newNodes = new List<Vector2>();
|
|
||||||
int nodeCount = message.ReadByte();
|
|
||||||
for (int i = 0; i<nodeCount; i++)
|
|
||||||
{
|
|
||||||
Vector2 newNode = new Vector2(message.ReadFloat(), message.ReadFloat());
|
|
||||||
if (!MathUtils.IsValid(newNode)) return;
|
|
||||||
newNodes.Add(newNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
Nodes = newNodes;
|
|
||||||
|
|
||||||
Drawable = Nodes.Any();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -385,75 +385,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
item.Sprite.Draw(spriteBatch, new Vector2(rect.X + rect.Width / 2, rect.Y + rect.Height / 2), item.Color);
|
item.Sprite.Draw(spriteBatch, new Vector2(rect.X + rect.Width / 2, rect.Y + rect.Height / 2), item.Color);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool FillNetworkData(NetworkEventType type, NetBuffer message, object data)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < capacity; i++)
|
|
||||||
{
|
|
||||||
message.Write((ushort)(Items[i]==null ? 0 : Items[i].ID));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void ReadNetworkData(NetworkEventType type, NetIncomingMessage message, float sendingTime)
|
|
||||||
{
|
|
||||||
if (sendingTime < lastUpdate) return;
|
|
||||||
|
|
||||||
//List<ushort> newItemIDs = new List<ushort>();
|
|
||||||
//List<Item> droppedItems = new List<Item>();
|
|
||||||
List<Item> prevItems = new List<Item>(Items);
|
|
||||||
|
|
||||||
Client sender = GameMain.Server == null ? null : GameMain.Server.ConnectedClients.Find(c => c.Connection == message.SenderConnection);
|
|
||||||
|
|
||||||
for (int i = 0; i < capacity; i++)
|
|
||||||
{
|
|
||||||
ushort itemId = message.ReadUInt16();
|
|
||||||
if (itemId == 0)
|
|
||||||
{
|
|
||||||
if (Items[i] != null) Items[i].Drop();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var item = Entity.FindEntityByID(itemId) as Item;
|
|
||||||
if (item == null) continue;
|
|
||||||
|
|
||||||
//if the item is in the inventory of some other character and said character isn't dead/unconscious,
|
|
||||||
//don't let this character pick it up
|
|
||||||
if (GameMain.Server != null)
|
|
||||||
{
|
|
||||||
if (sender == null || sender.Character == null) return;
|
|
||||||
|
|
||||||
if (!sender.Character.CanAccessItem(item)) continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
TryPutItem(item, i, true, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lastUpdate = sendingTime;
|
|
||||||
|
|
||||||
if (GameMain.Server == null) return;
|
|
||||||
if (sender != null && sender.Character != null)
|
|
||||||
{
|
|
||||||
foreach (Item item in Items)
|
|
||||||
{
|
|
||||||
if (item == null) continue;
|
|
||||||
if (!prevItems.Contains(item))
|
|
||||||
{
|
|
||||||
GameServer.Log(sender.Character + " placed " + item.Name + " in " + Owner, Color.Orange);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (Item item in prevItems)
|
|
||||||
{
|
|
||||||
if (item == null) continue;
|
|
||||||
if (!Items.Contains(item))
|
|
||||||
{
|
|
||||||
GameServer.Log(sender.Character + " removed " + item.Name + " from " + Owner.ToString(), Color.Orange);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1624,216 +1624,7 @@ namespace Barotrauma
|
|||||||
new NetworkEvent(isImportant ?
|
new NetworkEvent(isImportant ?
|
||||||
NetworkEventType.ImportantComponentUpdate : NetworkEventType.ComponentUpdate, ID, isClient, index);
|
NetworkEventType.ImportantComponentUpdate : NetworkEventType.ComponentUpdate, ID, isClient, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool FillNetworkData(NetworkEventType type, NetBuffer message, object data)
|
|
||||||
{
|
|
||||||
message.Write((byte)MathHelper.Clamp(condition*2.55f,0.0f,255.0f));
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case NetworkEventType.DropItem:
|
|
||||||
if (body != null) body.FillNetworkData(message);
|
|
||||||
break;
|
|
||||||
case NetworkEventType.PhysicsBodyPosition:
|
|
||||||
#if DEBUG
|
|
||||||
System.Diagnostics.Debug.Assert(body != null, "Tried to send a PhysicsBodyPosition message for an item that has no physics body ("+Name+")");
|
|
||||||
#else
|
|
||||||
if (body == null) return false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
body.FillNetworkData(message);
|
|
||||||
break;
|
|
||||||
case NetworkEventType.ItemFixed:
|
|
||||||
byte requirementIndex = (byte)data;
|
|
||||||
|
|
||||||
message.Write(requirementIndex);
|
|
||||||
break;
|
|
||||||
case NetworkEventType.InventoryUpdate:
|
|
||||||
var itemContainers = GetComponents<ItemContainer>();
|
|
||||||
if (itemContainers == null || !itemContainers.Any()) return false;
|
|
||||||
|
|
||||||
message.WriteRangedInteger(1, ItemContainer.MaxInventoryCount, itemContainers.Count);
|
|
||||||
foreach (ItemContainer container in itemContainers)
|
|
||||||
{
|
|
||||||
container.Inventory.FillNetworkData(NetworkEventType.InventoryUpdate, message, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
case NetworkEventType.ComponentUpdate:
|
|
||||||
case NetworkEventType.ImportantComponentUpdate:
|
|
||||||
|
|
||||||
int componentIndex = (int)data;
|
|
||||||
if (componentIndex < 0 || componentIndex >= components.Count) return false;
|
|
||||||
|
|
||||||
message.Write((byte)componentIndex);
|
|
||||||
bool sent = components[componentIndex].FillNetworkData(type, message);
|
|
||||||
if (sent) components[componentIndex].NetworkUpdateSent = true;
|
|
||||||
return sent;
|
|
||||||
case NetworkEventType.ApplyStatusEffect:
|
|
||||||
|
|
||||||
ActionType actionType = (ActionType)data;
|
|
||||||
message.WriteRangedInteger(0, Enum.GetValues(typeof(ActionType)).Length, (int)actionType);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
case NetworkEventType.UpdateProperty:
|
|
||||||
var allProperties = GetProperties<InGameEditable>();
|
|
||||||
|
|
||||||
ObjectProperty objectProperty = allProperties.Find(op => op.Name == (string)data);
|
|
||||||
if (objectProperty != null)
|
|
||||||
{
|
|
||||||
message.Write((string)data);
|
|
||||||
object value = objectProperty.GetValue();
|
|
||||||
if (value is string)
|
|
||||||
{
|
|
||||||
message.Write((byte)0);
|
|
||||||
message.Write((string)value);
|
|
||||||
}
|
|
||||||
else if (value is float)
|
|
||||||
{
|
|
||||||
message.Write((byte)1);
|
|
||||||
message.Write((float)value);
|
|
||||||
}
|
|
||||||
else if (value is int)
|
|
||||||
{
|
|
||||||
message.Write((byte)2);
|
|
||||||
message.Write((int)value);
|
|
||||||
}
|
|
||||||
else if (value is bool)
|
|
||||||
{
|
|
||||||
message.Write((byte)3);
|
|
||||||
message.Write((bool)value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
message.Write((byte)200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool ReadNetworkData(NetworkEventType type, NetIncomingMessage message, float sendingTime, out object data)
|
|
||||||
{
|
|
||||||
data = null;
|
|
||||||
|
|
||||||
Condition = (float)message.ReadByte()/2.55f;
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case NetworkEventType.DropItem:
|
|
||||||
if (GameMain.Server != null)
|
|
||||||
{
|
|
||||||
Client sender = GameMain.Server.ConnectedClients.Find(c => c.Connection == message.SenderConnection);
|
|
||||||
if (sender == null || sender.Character == null || !sender.Character.CanAccessItem(this))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Drop(null, false);
|
|
||||||
if (body != null)
|
|
||||||
{
|
|
||||||
body.ReadNetworkData(message, sendingTime);
|
|
||||||
body.MoveToTargetPosition();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NetworkEventType.PhysicsBodyPosition:
|
|
||||||
//clients don't have authority over item positions
|
|
||||||
if (GameMain.Server != null) return false;
|
|
||||||
if (body != null) body.ReadNetworkData(message, sendingTime);
|
|
||||||
|
|
||||||
FindHull();
|
|
||||||
break;
|
|
||||||
case NetworkEventType.ItemFixed:
|
|
||||||
byte requirementIndex = message.ReadByte();
|
|
||||||
data = requirementIndex;
|
|
||||||
|
|
||||||
if (requirementIndex >= FixRequirements.Count) return false;
|
|
||||||
|
|
||||||
FixRequirements[requirementIndex].Fixed = true;
|
|
||||||
break;
|
|
||||||
case NetworkEventType.InventoryUpdate:
|
|
||||||
var itemContainers = GetComponents<ItemContainer>();
|
|
||||||
if (itemContainers == null || !itemContainers.Any()) return false;
|
|
||||||
|
|
||||||
int containerCount = message.ReadRangedInteger(1, ItemContainer.MaxInventoryCount);
|
|
||||||
for (int i = 0; i < containerCount;i++ )
|
|
||||||
{
|
|
||||||
itemContainers[i].Inventory.ReadNetworkData(type, message, sendingTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case NetworkEventType.ComponentUpdate:
|
|
||||||
case NetworkEventType.ImportantComponentUpdate:
|
|
||||||
int componentIndex = message.ReadByte();
|
|
||||||
|
|
||||||
data = componentIndex;
|
|
||||||
|
|
||||||
if (componentIndex < 0 || componentIndex > components.Count - 1) return false;
|
|
||||||
|
|
||||||
components[componentIndex].NetworkUpdateSent = true;
|
|
||||||
components[componentIndex].ReadNetworkData(type, message, sendingTime);
|
|
||||||
break;
|
|
||||||
case NetworkEventType.ApplyStatusEffect:
|
|
||||||
|
|
||||||
ActionType actionType = (ActionType)message.ReadRangedInteger(0, Enum.GetValues(typeof(ActionType)).Length);
|
|
||||||
|
|
||||||
data = actionType;
|
|
||||||
|
|
||||||
ApplyStatusEffects(actionType, 1.0f);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case NetworkEventType.UpdateProperty:
|
|
||||||
string propertyName = "";
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
propertyName = message.ReadString();
|
|
||||||
data = propertyName;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var allProperties = GetProperties<InGameEditable>();
|
|
||||||
ObjectProperty property = allProperties.Find(op => op.Name == propertyName);
|
|
||||||
if (property == null) return false;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
switch (message.ReadByte())
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
property.TrySetValue(message.ReadString());
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
property.TrySetValue(message.ReadFloat());
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
property.TrySetValue(message.ReadInt32());
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
property.TrySetValue(message.ReadBoolean());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Remove()
|
public override void Remove()
|
||||||
{
|
{
|
||||||
base.Remove();
|
base.Remove();
|
||||||
|
|||||||
@@ -89,113 +89,6 @@ namespace Barotrauma
|
|||||||
spawnItems.Add(item);
|
spawnItems.Add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FillNetworkData(Lidgren.Network.NetBuffer message, List<Item> items)
|
|
||||||
{
|
|
||||||
message.Write((byte)items.Count);
|
|
||||||
|
|
||||||
for (int i = 0; i < items.Count; i++)
|
|
||||||
{
|
|
||||||
message.Write(items[i].Prefab.Name);
|
|
||||||
message.Write(items[i].ID);
|
|
||||||
|
|
||||||
if (items[i].ParentInventory == null || items[i].ParentInventory.Owner == null)
|
|
||||||
{
|
|
||||||
message.Write((ushort)0);
|
|
||||||
|
|
||||||
message.Write(items[i].Position.X);
|
|
||||||
message.Write(items[i].Position.Y);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
message.Write(items[i].ParentInventory.Owner.ID);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ReadNetworkData(Lidgren.Network.NetBuffer message)
|
|
||||||
{
|
|
||||||
var itemCount = message.ReadByte();
|
|
||||||
for (int i = 0; i < itemCount; i++)
|
|
||||||
{
|
|
||||||
string itemName = message.ReadString();
|
|
||||||
ushort itemId = message.ReadUInt16();
|
|
||||||
|
|
||||||
Vector2 pos = Vector2.Zero;
|
|
||||||
ushort inventoryId = message.ReadUInt16();
|
|
||||||
|
|
||||||
Submarine sub = null;
|
|
||||||
|
|
||||||
int inventorySlotIndex = -1;
|
|
||||||
|
|
||||||
if (inventoryId > 0)
|
|
||||||
{
|
|
||||||
inventorySlotIndex = message.ReadByte();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pos = new Vector2(message.ReadSingle(), message.ReadSingle());
|
|
||||||
}
|
|
||||||
|
|
||||||
string tags = "";
|
|
||||||
if (itemName == "ID Card")
|
|
||||||
{
|
|
||||||
tags = message.ReadString();
|
|
||||||
}
|
|
||||||
|
|
||||||
var prefab = MapEntityPrefab.list.Find(me => me.Name == itemName);
|
|
||||||
if (prefab == null) continue;
|
|
||||||
|
|
||||||
var itemPrefab = prefab as ItemPrefab;
|
|
||||||
if (itemPrefab == null) continue;
|
|
||||||
|
|
||||||
Inventory inventory = null;
|
|
||||||
|
|
||||||
var inventoryOwner = Entity.FindEntityByID(inventoryId);
|
|
||||||
if (inventoryOwner != null)
|
|
||||||
{
|
|
||||||
if (inventoryOwner is Character)
|
|
||||||
{
|
|
||||||
inventory = (inventoryOwner as Character).Inventory;
|
|
||||||
}
|
|
||||||
else if (inventoryOwner is Item)
|
|
||||||
{
|
|
||||||
var containers = (inventoryOwner as Item).GetComponents<Items.Components.ItemContainer>();
|
|
||||||
if (containers!=null && containers.Any())
|
|
||||||
{
|
|
||||||
inventory = containers.Last().Inventory;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var item = new Item(itemPrefab, pos, null);
|
|
||||||
|
|
||||||
item.ID = itemId;
|
|
||||||
item.CurrentHull = Hull.FindHull(pos, null, false);
|
|
||||||
item.Submarine = item.CurrentHull == null ? null : item.CurrentHull.Submarine;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(tags)) item.Tags = tags;
|
|
||||||
|
|
||||||
if (inventory != null)
|
|
||||||
{
|
|
||||||
if (inventorySlotIndex >= 0 && inventorySlotIndex < 255 &&
|
|
||||||
inventory.TryPutItem(item, inventorySlotIndex, false, false))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
inventory.TryPutItem(item, item.AllowedSlots, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
spawnQueue.Clear();
|
spawnQueue.Clear();
|
||||||
@@ -243,30 +136,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (GameMain.Server != null) GameMain.Server.SendItemRemoveMessage(items);
|
if (GameMain.Server != null) GameMain.Server.SendItemRemoveMessage(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FillNetworkData(Lidgren.Network.NetBuffer message, List<Item> items)
|
|
||||||
{
|
|
||||||
message.Write((byte)items.Count);
|
|
||||||
foreach (Item item in items)
|
|
||||||
{
|
|
||||||
message.Write(item.ID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ReadNetworkData(Lidgren.Network.NetBuffer message)
|
|
||||||
{
|
|
||||||
var itemCount = message.ReadByte();
|
|
||||||
for (int i = 0; i<itemCount; i++)
|
|
||||||
{
|
|
||||||
ushort itemId = message.ReadUInt16();
|
|
||||||
|
|
||||||
var item = MapEntity.FindEntityByID(itemId) as Item;
|
|
||||||
if (item == null) continue;
|
|
||||||
|
|
||||||
item.Remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
removeQueue.Clear();
|
removeQueue.Clear();
|
||||||
|
|||||||
@@ -92,31 +92,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
dictionary.Add(id, this);
|
dictionary.Add(id, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Writes the state of the entity into the message
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="data">some data that was saved when the networkevent was created</param>
|
|
||||||
/// <returns>false if something went wrong when filling the message, true if the msg is ready to be sent</returns>
|
|
||||||
public virtual bool FillNetworkData(NetworkEventType type, NetBuffer message, object data)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Updates the state of the entity based on the data in the message
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
/// <param name="sendingTime"></param>
|
|
||||||
/// <param name="data"></param>
|
|
||||||
/// <returns>false if the message is not valid (client trying to change something they're not authorized to, corrupt data, etc) and should be ignored</returns>
|
|
||||||
public virtual bool ReadNetworkData(NetworkEventType type, NetIncomingMessage message, float sendingTime, out object data)
|
|
||||||
{
|
|
||||||
data = null;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Find an entity based on the ID
|
/// Find an entity based on the ID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -801,120 +801,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
h.ID = (ushort)int.Parse(element.Attribute("ID").Value);
|
h.ID = (ushort)int.Parse(element.Attribute("ID").Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool FillNetworkData(Networking.NetworkEventType type, NetBuffer message, object data)
|
|
||||||
{
|
|
||||||
message.WriteRangedSingle(MathHelper.Clamp(volume/FullVolume, 0.0f, 1.5f), 0.0f, 1.5f, 6);
|
|
||||||
message.WriteRangedSingle(MathHelper.Clamp(OxygenPercentage, 0.0f, 100.0f), 0.0f, 100.0f, 8);
|
|
||||||
|
|
||||||
message.Write(fireSources.Count > 0);
|
|
||||||
if (fireSources.Count > 0)
|
|
||||||
{
|
|
||||||
message.Write((byte)fireSources.Count);
|
|
||||||
for (int i = 0; i < Math.Min(fireSources.Count, 16); i++)
|
|
||||||
{
|
|
||||||
var fireSource = fireSources[i];
|
|
||||||
|
|
||||||
Vector2 normalizedPos = new Vector2(
|
|
||||||
(fireSource.Position.X - rect.X) / rect.Width,
|
|
||||||
(fireSource.Position.Y - (rect.Y - rect.Height)) / rect.Height);
|
|
||||||
message.WriteRangedSingle(MathHelper.Clamp(normalizedPos.X, 0.0f, 1.0f), 0.0f, 1.0f, 4);
|
|
||||||
message.WriteRangedSingle(MathHelper.Clamp(normalizedPos.Y, 0.0f, 1.0f), 0.0f, 1.0f, 4);
|
|
||||||
|
|
||||||
message.WriteRangedSingle(MathHelper.Clamp(fireSource.Size.X / rect.Width, 0.0f, 1.0f), 0, 1.0f, 6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lastSentVolume = volume;
|
|
||||||
lastSentOxygen = OxygenPercentage;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message, float sendingTime, out object data)
|
|
||||||
{
|
|
||||||
data = null;
|
|
||||||
|
|
||||||
if (GameMain.Server != null) return false;
|
|
||||||
|
|
||||||
if (sendingTime < lastNetworkUpdate) return false;
|
|
||||||
|
|
||||||
float newVolume = this.volume;
|
|
||||||
float newOxygen = this.OxygenPercentage;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
float newPercentage = message.ReadRangedSingle(0.0f, 1.5f, 6);
|
|
||||||
newVolume = newPercentage * FullVolume;
|
|
||||||
|
|
||||||
newOxygen = message.ReadRangedSingle(0.0f, 100.0f, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
DebugConsole.Log("Failed to read network message for Hull {" + ID + "}! " + e.Message);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Volume = newVolume;
|
|
||||||
OxygenPercentage = newOxygen;
|
|
||||||
|
|
||||||
bool hasFireSources = message.ReadBoolean();
|
|
||||||
|
|
||||||
|
|
||||||
List<FireSource> newFireSources = new List<FireSource>();
|
|
||||||
if (hasFireSources)
|
|
||||||
{
|
|
||||||
int fireSourceCount = message.ReadByte();
|
|
||||||
for (int i = 0; i < fireSourceCount; i++)
|
|
||||||
{
|
|
||||||
Vector2 pos = Vector2.Zero;
|
|
||||||
float size = 0.0f;
|
|
||||||
pos.X = message.ReadRangedSingle(0.0f, 1.0f, 4);
|
|
||||||
pos.Y = message.ReadRangedSingle(0.0f, 1.0f, 4);
|
|
||||||
size = message.ReadRangedSingle(0.0f, 1.0f, 6);
|
|
||||||
if (!MathUtils.IsValid(pos)) continue;
|
|
||||||
|
|
||||||
pos.X = MathHelper.Clamp(pos.X, 0.05f, 0.95f);
|
|
||||||
pos.Y = MathHelper.Clamp(pos.Y, 0.05f, 0.95f);
|
|
||||||
|
|
||||||
pos = new Vector2(rect.X + rect.Width * pos.X, rect.Y - rect.Height + (rect.Height * pos.Y));
|
|
||||||
|
|
||||||
var existingFire = fireSources.Find(fs => fs.Contains(pos));
|
|
||||||
if (existingFire!=null)
|
|
||||||
{
|
|
||||||
newFireSources.Add(existingFire);
|
|
||||||
existingFire.Position = pos;
|
|
||||||
existingFire.Size = new Vector2(
|
|
||||||
existingFire.Hull == null ? size : size*existingFire.Hull.rect.Width,
|
|
||||||
existingFire.Size.Y);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var newFire = new FireSource(pos + Submarine.Position, this, true);
|
|
||||||
newFire.Size = new Vector2(
|
|
||||||
newFire.Hull == null ? size : size * newFire.Hull.rect.Width,
|
|
||||||
newFire.Size.Y);
|
|
||||||
|
|
||||||
//ignore if the fire wasn't added to this room (invalid position)?
|
|
||||||
if (!fireSources.Contains(newFire)) continue;
|
|
||||||
newFireSources.Add(newFire);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var toBeRemoved = fireSources.FindAll(fs => !newFireSources.Contains(fs));
|
|
||||||
for (int i = toBeRemoved.Count - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
toBeRemoved[i].Remove(true);
|
|
||||||
}
|
|
||||||
fireSources = newFireSources;
|
|
||||||
|
|
||||||
lastNetworkUpdate = sendingTime;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -769,54 +769,6 @@ namespace Barotrauma
|
|||||||
if (s.gap != null) s.gap.ConnectedWall = this;
|
if (s.gap != null) s.gap.ConnectedWall = this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool FillNetworkData(NetworkEventType type, NetBuffer message, object data)
|
|
||||||
{
|
|
||||||
//var updateSections = Array.FindAll(sections, s => s != null && Math.Abs(s.damage - s.lastSentDamage) > 0.01f);
|
|
||||||
|
|
||||||
//if (updateSections.Length == 0) return false;
|
|
||||||
|
|
||||||
//Debug.Assert(updateSections.Length<255);
|
|
||||||
|
|
||||||
// message.Write((byte)updateSections.Length);
|
|
||||||
|
|
||||||
for (int i = 0; i < sections.Length; i++)
|
|
||||||
{
|
|
||||||
//if (Math.Abs(sections[i].damage - sections[i].lastSentDamage) < 0.01f) continue;
|
|
||||||
|
|
||||||
//message.Write((byte)i);
|
|
||||||
message.WriteRangedSingle(sections[i].damage / Health, 0.0f, 1.0f, 8);
|
|
||||||
|
|
||||||
sections[i].lastSentDamage = sections[i].damage;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool ReadNetworkData(NetworkEventType type, NetIncomingMessage message, float sendingTime, out object data)
|
|
||||||
{
|
|
||||||
data = null;
|
|
||||||
|
|
||||||
if (GameMain.Server != null) return false;
|
|
||||||
|
|
||||||
if (sendingTime < lastUpdate) return false;
|
|
||||||
|
|
||||||
// int sectionCount = message.ReadByte();
|
|
||||||
|
|
||||||
for (int i = 0; i<sections.Count(); i++)
|
|
||||||
{
|
|
||||||
//byte sectionIndex = message.ReadByte();
|
|
||||||
float damage = message.ReadRangedSingle(0.0f, 1.0f, 8) * Health;
|
|
||||||
|
|
||||||
//if (sectionIndex < 0 || sectionIndex >= sections.Length) continue;
|
|
||||||
|
|
||||||
SetDamage(i, damage);
|
|
||||||
}
|
|
||||||
|
|
||||||
lastUpdate = sendingTime;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -537,55 +537,6 @@ namespace Barotrauma
|
|||||||
return closest;
|
return closest;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool FillNetworkData(Networking.NetworkEventType type, NetBuffer message, object data)
|
|
||||||
{
|
|
||||||
if (subBody == null) return false;
|
|
||||||
|
|
||||||
message.Write(subBody.Position.X);
|
|
||||||
message.Write(subBody.Position.Y);
|
|
||||||
|
|
||||||
message.Write(Velocity.X);
|
|
||||||
message.Write(Velocity.Y);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool ReadNetworkData(Networking.NetworkEventType type, NetIncomingMessage message, float sendingTime, out object data)
|
|
||||||
{
|
|
||||||
data = null;
|
|
||||||
|
|
||||||
if (GameMain.Server != null) return false;
|
|
||||||
|
|
||||||
Vector2 newTargetPosition, newSpeed;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (sendingTime <= lastNetworkUpdate) return false;
|
|
||||||
|
|
||||||
newTargetPosition = new Vector2(message.ReadFloat(), message.ReadFloat());
|
|
||||||
newSpeed = new Vector2(message.ReadFloat(), message.ReadFloat());
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
DebugConsole.ThrowError("invalid network message", e);
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!newSpeed.IsValid() || !newTargetPosition.IsValid()) return false;
|
|
||||||
|
|
||||||
//newTargetPosition = newTargetPosition + newSpeed * (float)(NetTime.Now - sendingTime);
|
|
||||||
|
|
||||||
subBody.TargetPosition = newTargetPosition;
|
|
||||||
subBody.Velocity = newSpeed;
|
|
||||||
|
|
||||||
lastNetworkUpdate = sendingTime;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//saving/loading ----------------------------------------------------
|
//saving/loading ----------------------------------------------------
|
||||||
|
|
||||||
public bool Save()
|
public bool Save()
|
||||||
|
|||||||
@@ -61,10 +61,7 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
if (!permissions.HasFlag(ClientPermissions.EndRound)) return false;
|
if (!permissions.HasFlag(ClientPermissions.EndRound)) return false;
|
||||||
|
|
||||||
var msg = client.CreateMessage();
|
//TODO: tell server that client requested round end
|
||||||
|
|
||||||
msg.Write((byte)PacketTypes.EndGame);
|
|
||||||
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -232,126 +229,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Switch based on the message types
|
//TODO: read message data
|
||||||
switch (inc.MessageType)
|
|
||||||
{
|
|
||||||
// All manually sent messages are type of "Data"
|
|
||||||
case NetIncomingMessageType.Data:
|
|
||||||
byte packetType = inc.ReadByte();
|
|
||||||
if (packetType == (byte)PacketTypes.LoggedIn)
|
|
||||||
{
|
|
||||||
myID = inc.ReadByte();
|
|
||||||
permissions = (ClientPermissions)inc.ReadInt32();
|
|
||||||
gameStarted = inc.ReadBoolean();
|
|
||||||
bool hasCharacter = inc.ReadBoolean();
|
|
||||||
bool allowSpectating = inc.ReadBoolean();
|
|
||||||
|
|
||||||
endRoundButton.Visible = permissions.HasFlag(ClientPermissions.EndRound);
|
|
||||||
|
|
||||||
if (gameStarted && Screen.Selected != GameMain.GameScreen)
|
|
||||||
{
|
|
||||||
new GUIMessageBox("Please wait",
|
|
||||||
(allowSpectating) ?
|
|
||||||
"A round is already running, but you can spectate the game while waiting for a respawn shuttle or a new round." :
|
|
||||||
"A round is already running and the admin has disabled spectating. You will have to wait for a new round to start.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gameStarted && !hasCharacter && myCharacter != null)
|
|
||||||
{
|
|
||||||
GameMain.NetLobbyScreen.Select();
|
|
||||||
|
|
||||||
new GUIMessageBox("Connection timed out", "You were disconnected for too long and your character was deleted. Please wait for another round to start.");
|
|
||||||
}
|
|
||||||
|
|
||||||
GameMain.NetLobbyScreen.ClearPlayers();
|
|
||||||
|
|
||||||
//add the names of other connected clients to the lobby screen
|
|
||||||
int clientCount = inc.ReadByte();
|
|
||||||
for (int i = 0; i < clientCount; i++)
|
|
||||||
{
|
|
||||||
Client otherClient = new Client(inc.ReadString(), inc.ReadByte());
|
|
||||||
|
|
||||||
GameMain.NetLobbyScreen.AddPlayer(otherClient.name);
|
|
||||||
otherClients.Add(otherClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Submarine> submarines = new List<Submarine>();
|
|
||||||
int subCount = inc.ReadByte();
|
|
||||||
for (int i = 0; i < subCount; i++ )
|
|
||||||
{
|
|
||||||
string subName = inc.ReadString();
|
|
||||||
string subHash = inc.ReadString();
|
|
||||||
|
|
||||||
var matchingSub = Submarine.SavedSubmarines.Find(s => s.Name == subName);
|
|
||||||
if (matchingSub != null)
|
|
||||||
{
|
|
||||||
submarines.Add(matchingSub);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
submarines.Add(new Submarine(Path.Combine(Submarine.SavePath, subName), subHash, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
GameMain.NetLobbyScreen.UpdateSubList(GameMain.NetLobbyScreen.SubList, submarines);
|
|
||||||
GameMain.NetLobbyScreen.UpdateSubList(GameMain.NetLobbyScreen.ShuttleList.ListBox, submarines);
|
|
||||||
|
|
||||||
//add the name of own client to the lobby screen
|
|
||||||
GameMain.NetLobbyScreen.AddPlayer(name);
|
|
||||||
|
|
||||||
CanStart = true;
|
|
||||||
|
|
||||||
NetOutgoingMessage lobbyUpdateRequest = client.CreateMessage();
|
|
||||||
lobbyUpdateRequest.Write((byte)PacketTypes.RequestNetLobbyUpdate);
|
|
||||||
client.SendMessage(lobbyUpdateRequest, NetDeliveryMethod.ReliableUnordered);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NetIncomingMessageType.StatusChanged:
|
|
||||||
|
|
||||||
NetConnectionStatus connectionStatus = (NetConnectionStatus)inc.ReadByte();
|
|
||||||
DebugConsole.NewMessage("Connection status changed: " + connectionStatus.ToString(), Color.Orange);
|
|
||||||
|
|
||||||
if (connectionStatus == NetConnectionStatus.Disconnected)
|
|
||||||
{
|
|
||||||
string denyMessage = inc.ReadString();
|
|
||||||
|
|
||||||
if (denyMessage == "Password required!" || denyMessage == "Wrong password!")
|
|
||||||
{
|
|
||||||
GameMain.ServerListScreen.JoinServer(serverIP, true, denyMessage);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
new GUIMessageBox("Couldn't connect to server", denyMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
connectCanceled = true;
|
|
||||||
}
|
|
||||||
else if (connectionStatus == NetConnectionStatus.Connected)
|
|
||||||
{
|
|
||||||
int nonce = inc.SenderConnection.RemoteHailMessage.ReadInt32();
|
|
||||||
|
|
||||||
var outmsg = client.CreateMessage();
|
|
||||||
|
|
||||||
NetEncryption algo = new NetXtea(client, password);
|
|
||||||
outmsg.Write((byte)PacketTypes.Login);
|
|
||||||
outmsg.Write(nonce);
|
|
||||||
outmsg.Write(myID);
|
|
||||||
outmsg.Write(GameMain.Version.ToString());
|
|
||||||
outmsg.Write(GameMain.SelectedPackage.Name);
|
|
||||||
outmsg.Write(GameMain.SelectedPackage.MD5hash.Hash);
|
|
||||||
outmsg.Write(name);
|
|
||||||
|
|
||||||
outmsg.Encrypt(algo);
|
|
||||||
|
|
||||||
client.SendMessage(outmsg, NetDeliveryMethod.ReliableUnordered);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Console.WriteLine(inc.ReadString() + " Strange message");
|
|
||||||
connectCanceled = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -445,14 +323,6 @@ namespace Barotrauma.Networking
|
|||||||
new NetworkEvent(NetworkEventType.EntityUpdate, myCharacter.ID, true);
|
new NetworkEvent(NetworkEventType.EntityUpdate, myCharacter.ID, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var message = ComposeNetworkEventMessage(NetworkEventDeliveryMethod.Unreliable);
|
|
||||||
if (message != null) client.SendMessage(message, NetDeliveryMethod.Unreliable);
|
|
||||||
|
|
||||||
message = ComposeNetworkEventMessage(NetworkEventDeliveryMethod.ReliableLidgren);
|
|
||||||
if (message != null) client.SendMessage(message, NetDeliveryMethod.ReliableUnordered);
|
|
||||||
|
|
||||||
NetworkEvent.Events.Clear();
|
|
||||||
|
|
||||||
// Update current time
|
// Update current time
|
||||||
updateTimer = DateTime.Now + updateInterval;
|
updateTimer = DateTime.Now + updateInterval;
|
||||||
@@ -478,209 +348,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
while ((inc = client.ReadMessage()) != null)
|
while ((inc = client.ReadMessage()) != null)
|
||||||
{
|
{
|
||||||
if (inc.MessageType == NetIncomingMessageType.StatusChanged)
|
//TODO: read message data
|
||||||
{
|
|
||||||
NetConnectionStatus connectionStatus = (NetConnectionStatus)inc.ReadByte();
|
|
||||||
DebugConsole.NewMessage("Connection status changed: " + connectionStatus.ToString(), Color.Orange);
|
|
||||||
|
|
||||||
if (connectionStatus == NetConnectionStatus.Disconnected)
|
|
||||||
{
|
|
||||||
string disconnectMessage = inc.ReadString();
|
|
||||||
if (string.IsNullOrEmpty(disconnectMessage) || disconnectMessage == "Connection timed out")
|
|
||||||
{
|
|
||||||
if (reconnectBox == null)
|
|
||||||
{
|
|
||||||
reconnectBox = new GUIMessageBox("CONNECTION LOST", "You have been disconnected from the server. Reconnecting...", new string[0]);
|
|
||||||
connected = false;
|
|
||||||
ConnectToServer(serverIP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
new GUIMessageBox("Disconnected", disconnectMessage);
|
|
||||||
|
|
||||||
Disconnect();
|
|
||||||
GameMain.ServerListScreen.Select();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inc.MessageType != NetIncomingMessageType.Data) continue;
|
|
||||||
|
|
||||||
byte packetType = inc.ReadByte();
|
|
||||||
|
|
||||||
switch (packetType)
|
|
||||||
{
|
|
||||||
case (byte)PacketTypes.CanStartGame:
|
|
||||||
string subName = inc.ReadString();
|
|
||||||
string subHash = inc.ReadString();
|
|
||||||
|
|
||||||
string shuttleName = inc.ReadString();
|
|
||||||
string shuttleHash = inc.ReadString();
|
|
||||||
|
|
||||||
if (GameMain.NetLobbyScreen.TrySelectSub(subName,subHash,GameMain.NetLobbyScreen.SubList) &&
|
|
||||||
GameMain.NetLobbyScreen.TrySelectSub(shuttleName, shuttleHash, GameMain.NetLobbyScreen.ShuttleList.ListBox))
|
|
||||||
{
|
|
||||||
NetOutgoingMessage readyToStartMsg = client.CreateMessage();
|
|
||||||
readyToStartMsg.Write((byte)PacketTypes.StartGame);
|
|
||||||
client.SendMessage(readyToStartMsg, NetDeliveryMethod.ReliableUnordered);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case (byte)PacketTypes.StartGame:
|
|
||||||
if (Screen.Selected == GameMain.GameScreen) continue;
|
|
||||||
|
|
||||||
startGameCoroutine = GameMain.ShowLoading(StartGame(inc), false);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case (byte)PacketTypes.EndGame:
|
|
||||||
string endMessage = inc.ReadString();
|
|
||||||
CoroutineManager.StartCoroutine(EndGame(endMessage));
|
|
||||||
break;
|
|
||||||
case (byte)PacketTypes.Respawn:
|
|
||||||
if (gameStarted && respawnManager != null) respawnManager.ReadNetworkEvent(inc);
|
|
||||||
break;
|
|
||||||
case (byte)PacketTypes.PlayerJoined:
|
|
||||||
|
|
||||||
Client otherClient = new Client(inc.ReadString(), inc.ReadByte());
|
|
||||||
|
|
||||||
GameMain.NetLobbyScreen.AddPlayer(otherClient.name);
|
|
||||||
otherClients.Add(otherClient);
|
|
||||||
|
|
||||||
AddChatMessage(otherClient.name + " has joined the server", ChatMessageType.Server);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case (byte)PacketTypes.Permissions:
|
|
||||||
ClientPermissions newPermissions = (ClientPermissions)inc.ReadInt32();
|
|
||||||
|
|
||||||
if (newPermissions != permissions)
|
|
||||||
{
|
|
||||||
if (GUIMessageBox.MessageBoxes.Count > 0)
|
|
||||||
{
|
|
||||||
var existingMsgBox = GUIMessageBox.MessageBoxes.Peek();
|
|
||||||
if (existingMsgBox.UserData as string == "permissions")
|
|
||||||
{
|
|
||||||
GUIMessageBox.MessageBoxes.Dequeue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//new GUIMessageBox("The host has changed you permissions. New permissions")
|
|
||||||
string msg = "";
|
|
||||||
if (newPermissions == ClientPermissions.None)
|
|
||||||
{
|
|
||||||
msg = "The host has removed all your special permissions.";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
msg = "Your current permissions:\n";
|
|
||||||
foreach (ClientPermissions permission in Enum.GetValues(typeof(ClientPermissions)))
|
|
||||||
{
|
|
||||||
if (!newPermissions.HasFlag(permissions) || permission == ClientPermissions.None) continue;
|
|
||||||
|
|
||||||
System.Reflection.FieldInfo fi = typeof(ClientPermissions).GetField(permission.ToString());
|
|
||||||
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
|
||||||
|
|
||||||
msg += " - " + attributes[0].Description+"\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
new GUIMessageBox("Permissions changed", msg).UserData = "permissions";
|
|
||||||
}
|
|
||||||
|
|
||||||
endRoundButton.Visible = permissions.HasFlag(ClientPermissions.EndRound);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case (byte)PacketTypes.RequestFile:
|
|
||||||
bool accepted = inc.ReadBoolean();
|
|
||||||
|
|
||||||
if (!accepted)
|
|
||||||
{
|
|
||||||
new GUIMessageBox("File transfer canceled", inc.ReadString());
|
|
||||||
|
|
||||||
if (fileStreamReceiver!=null)
|
|
||||||
{
|
|
||||||
fileStreamReceiver.DeleteFile();
|
|
||||||
fileStreamReceiver.Dispose();
|
|
||||||
fileStreamReceiver = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case (byte)PacketTypes.FileStream:
|
|
||||||
if (fileStreamReceiver == null)
|
|
||||||
{
|
|
||||||
//todo: unexpected file
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fileStreamReceiver.ReadMessage(inc);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case (byte)PacketTypes.PlayerLeft:
|
|
||||||
byte leavingID = inc.ReadByte();
|
|
||||||
|
|
||||||
AddChatMessage(inc.ReadString(), ChatMessageType.Server);
|
|
||||||
Client disconnectedClient = otherClients.Find(c => c.ID == leavingID);
|
|
||||||
|
|
||||||
if (disconnectedClient != null)
|
|
||||||
{
|
|
||||||
otherClients.Remove(disconnectedClient);
|
|
||||||
GameMain.NetLobbyScreen.RemovePlayer(disconnectedClient.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gameStarted) return;
|
|
||||||
|
|
||||||
List<Character> crew = new List<Character>();
|
|
||||||
foreach (Character c in Character.CharacterList)
|
|
||||||
{
|
|
||||||
if (!c.IsNetworkPlayer || !c.IsHumanoid || c.Info==null) continue;
|
|
||||||
crew.Add(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
//GameMain.GameSession.CrewManager.CreateCrewFrame(crew);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case (byte)PacketTypes.Chatmessage:
|
|
||||||
//ChatMessageType messageType = (ChatMessageType)inc.ReadByte();
|
|
||||||
|
|
||||||
AddChatMessage(ChatMessage.ReadNetworkMessage(inc));
|
|
||||||
break;
|
|
||||||
case (byte)PacketTypes.NetworkEvent:
|
|
||||||
//read the data from the message and update client state accordingly
|
|
||||||
if (!gameStarted) break;
|
|
||||||
|
|
||||||
NetworkEvent.ReadMessage(inc);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case (byte)PacketTypes.UpdateNetLobby:
|
|
||||||
//if (gameStarted) continue;
|
|
||||||
GameMain.NetLobbyScreen.ReadData(inc);
|
|
||||||
break;
|
|
||||||
case (byte)PacketTypes.Traitor:
|
|
||||||
string targetName = inc.ReadString();
|
|
||||||
|
|
||||||
TraitorManager.CreateStartPopUp(targetName);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case (byte)PacketTypes.ResendRequest:
|
|
||||||
break;
|
|
||||||
case (byte)PacketTypes.LatestMessageID:
|
|
||||||
break;
|
|
||||||
case (byte)PacketTypes.VoteStatus:
|
|
||||||
Voting.ReadData(inc);
|
|
||||||
break;
|
|
||||||
case (byte)PacketTypes.NewItem:
|
|
||||||
Item.Spawner.ReadNetworkData(inc);
|
|
||||||
break;
|
|
||||||
case (byte)PacketTypes.NewCharacter:
|
|
||||||
ReadCharacterSpawnMessage(inc);
|
|
||||||
break;
|
|
||||||
case (byte)PacketTypes.RemoveItem:
|
|
||||||
Item.Remover.ReadNetworkData(inc);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packetType == (byte)PacketTypes.StartGame) break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -894,10 +562,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
public override void Disconnect()
|
public override void Disconnect()
|
||||||
{
|
{
|
||||||
NetOutgoingMessage msg = client.CreateMessage();
|
//TODO: tell server
|
||||||
msg.Write((byte)PacketTypes.PlayerLeft);
|
|
||||||
|
|
||||||
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
|
||||||
client.Shutdown("");
|
client.Shutdown("");
|
||||||
GameMain.NetworkMember = null;
|
GameMain.NetworkMember = null;
|
||||||
}
|
}
|
||||||
@@ -1168,8 +833,6 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
character.ID = ID;
|
character.ID = ID;
|
||||||
|
|
||||||
Item.Spawner.ReadNetworkData(inc);
|
|
||||||
|
|
||||||
if (isMyCharacter)
|
if (isMyCharacter)
|
||||||
{
|
{
|
||||||
myCharacter = character;
|
myCharacter = character;
|
||||||
|
|||||||
@@ -1579,7 +1579,6 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
message.Write(character.Info.Job.Name);
|
message.Write(character.Info.Job.Name);
|
||||||
|
|
||||||
Item.Spawner.FillNetworkData(message, character.SpawnItems);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendCharacterSpawnMessage(Character character, List<NetConnection> recipients = null)
|
public void SendCharacterSpawnMessage(Character character, List<NetConnection> recipients = null)
|
||||||
@@ -1610,8 +1609,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
NetOutgoingMessage message = server.CreateMessage();
|
NetOutgoingMessage message = server.CreateMessage();
|
||||||
message.Write((byte)PacketTypes.NewItem);
|
message.Write((byte)PacketTypes.NewItem);
|
||||||
|
|
||||||
Item.Spawner.FillNetworkData(message, items);
|
|
||||||
|
|
||||||
SendMessage(message, NetDeliveryMethod.ReliableOrdered, recipients);
|
SendMessage(message, NetDeliveryMethod.ReliableOrdered, recipients);
|
||||||
}
|
}
|
||||||
@@ -1622,8 +1620,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
NetOutgoingMessage message = server.CreateMessage();
|
NetOutgoingMessage message = server.CreateMessage();
|
||||||
message.Write((byte)PacketTypes.RemoveItem);
|
message.Write((byte)PacketTypes.RemoveItem);
|
||||||
Item.Remover.FillNetworkData(message, items);
|
|
||||||
|
|
||||||
SendMessage(message, NetDeliveryMethod.ReliableOrdered, recipients);
|
SendMessage(message, NetDeliveryMethod.ReliableOrdered, recipients);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!e.FillNetworkData(eventType, message, data)) return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
@@ -227,10 +227,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!e.ReadNetworkData(eventType, message, sendingTime, out data))
|
|
||||||
{
|
|
||||||
resend = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -378,60 +378,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
body.ApplyTorque(torque);
|
body.ApplyTorque(torque);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void FillNetworkData(NetBuffer message)
|
|
||||||
{
|
|
||||||
message.Write(body.Position.X);
|
|
||||||
message.Write(body.Position.Y);
|
|
||||||
message.Write(body.LinearVelocity.X);
|
|
||||||
message.Write(body.LinearVelocity.Y);
|
|
||||||
|
|
||||||
message.Write(body.Rotation);
|
|
||||||
message.Write(body.AngularVelocity);
|
|
||||||
|
|
||||||
LastSentPosition = body.Position;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ReadNetworkData(NetIncomingMessage message, float sendingTime)
|
|
||||||
{
|
|
||||||
if (sendingTime < lastNetworkUpdateTime) return;
|
|
||||||
|
|
||||||
Vector2 newTargetPos = Vector2.Zero;
|
|
||||||
Vector2 newTargetVel = Vector2.Zero;
|
|
||||||
|
|
||||||
float newTargetRotation = 0.0f, newTargetAngularVel = 0.0f;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
newTargetPos = new Vector2(message.ReadFloat(), message.ReadFloat());
|
|
||||||
newTargetVel = new Vector2(message.ReadFloat(), message.ReadFloat());
|
|
||||||
|
|
||||||
newTargetRotation = message.ReadFloat();
|
|
||||||
newTargetAngularVel = message.ReadFloat();
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
DebugConsole.ThrowError("invalid network message", e);
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!MathUtils.IsValid(newTargetPos) || !MathUtils.IsValid(newTargetVel) ||
|
|
||||||
!MathUtils.IsValid(newTargetRotation) || !MathUtils.IsValid(newTargetAngularVel))
|
|
||||||
return;
|
|
||||||
|
|
||||||
targetPosition = newTargetPos;
|
|
||||||
LinearVelocity = newTargetVel;
|
|
||||||
|
|
||||||
targetRotation = newTargetRotation;
|
|
||||||
AngularVelocity = newTargetAngularVel;
|
|
||||||
|
|
||||||
lastNetworkUpdateTime = sendingTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void Remove()
|
public void Remove()
|
||||||
{
|
{
|
||||||
list.Remove(this);
|
list.Remove(this);
|
||||||
|
|||||||
Reference in New Issue
Block a user