Skip to content

Commit

Permalink
Less shitty disposal hack
Browse files Browse the repository at this point in the history
  • Loading branch information
metalgearsloth committed Nov 19, 2023
1 parent 44bfa5e commit abad5a1
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 53 deletions.
31 changes: 21 additions & 10 deletions Robust.Server/GameStates/ServerGameStateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ private void PrintPvsAckInfo(IConsoleShell shell, string argstr, string[] args)
Actual oldest: {ack}
Oldest acked clients: {string.Join(", ", players)}
");

_nentListPool.Return(deletedNents);
}

Expand Down Expand Up @@ -409,7 +409,7 @@ private void SendStateUpdate(int i,
#endif
}

_networkManager.ServerSendMessage(stateUpdateMessage, channel);
var canDispose = _networkManager.ServerSendMessage(stateUpdateMessage, channel);

if (stateUpdateMessage.ShouldSendReliably())
{
Expand All @@ -423,23 +423,34 @@ private void SendStateUpdate(int i,
// Send PVS detach / left-view messages separately and reliably. This is not resistant to packet loss, but
// unlike game state it doesn't really matter. This also significantly reduces the size of game state
// messages as PVS chunks get moved out of view.
bool leavePvsDispose = true;

if (leftPvs.Count > 0)
{
var pvsMessage = new MsgStateLeavePvs {Entities = leftPvs, Tick = _gameTiming.CurTick};
_networkManager.ServerSendMessage(pvsMessage, channel);
leavePvsDispose = _networkManager.ServerSendMessage(pvsMessage, channel);
}

// Release resources
// Assume everything has been serialized and we're free to rugpull.
foreach (var eState in entStates)
if (canDispose)
{
_pvs.ReturnEntityState(eState);
}
// Should this just happen inside PvsSystem instead and store the pools there?
// At either rate it needs doing so.
foreach (var eState in entStates)
{
_pvs.ReturnEntityState(eState);
}

_nentListPool.Return(leftPvs);
_nentListPool.Return(deletions);
_entStatePool.Return(entStates);
_playerStatePool.Return(playerStates);
_nentListPool.Return(deletions);
_entStatePool.Return(entStates);
_playerStatePool.Return(playerStates);

if (leavePvsDispose)
{
_nentListPool.Return(leftPvs);
}
}
}

[EventSource(Name = "Robust.Pvs")]
Expand Down
3 changes: 2 additions & 1 deletion Robust.Shared/Network/INetManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ public interface INetManager
/// </summary>
/// <param name="message">Message to send.</param>
/// <param name="recipient">Channel to send the message over.</param>
void ServerSendMessage(NetMessage message, INetChannel recipient);
/// <returns>True if the message is sent and can be disposed.</returns>
bool ServerSendMessage(NetMessage message, INetChannel recipient);

/// <summary>
/// Sends a message to a collection of channels.
Expand Down
5 changes: 3 additions & 2 deletions Robust.Shared/Network/NetManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1005,12 +1005,12 @@ public void ServerSendToAll(NetMessage message)
}

/// <inheritdoc />
public void ServerSendMessage(NetMessage message, INetChannel recipient)
public bool ServerSendMessage(NetMessage message, INetChannel recipient)
{
// TODO: Does the entity manager HAVE to shut down after network manager?
// Though tbf theres no real point in sending messages anymore at that point.
if (!_initialized)
return;
return true;

DebugTools.Assert(IsServer);
if (recipient is not NetChannel channel)
Expand All @@ -1024,6 +1024,7 @@ public void ServerSendMessage(NetMessage message, INetChannel recipient)
var method = message.DeliveryMethod;
peer.SendMessage(packet, channel.Connection, method);
LogSend(message, method, packet);
return true;
}

private static void LogSend(NetMessage message, NetDeliveryMethod method, NetOutgoingMessage packet)
Expand Down
42 changes: 2 additions & 40 deletions Robust.UnitTesting/RobustIntegrationTest.NetManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -248,53 +248,14 @@ public void ServerSendToAll(NetMessage message)
}
}

public void ServerSendMessage(NetMessage message, INetChannel recipient)
public bool ServerSendMessage(NetMessage message, INetChannel recipient)
{
DebugTools.Assert(IsServer);

// MsgState sending method depends on the size of the possible compressed buffer. But tests bypass buffer read/write.
if (message is MsgState stateMsg)
{
stateMsg._hasWritten = true;

// Clone the message as it gets queued and the data needs to persist for a bit.
var oldState = stateMsg.State;

var entStates = new List<EntityState>(oldState.EntityStates.Value?.Count ?? 0);
var sesStates = new List<SessionState>(oldState.PlayerStates.Value?.Count ?? 0);
var deletions = new List<NetEntity>(oldState.EntityDeletions.Value?.Count ?? 0);

if (oldState.EntityStates.Value != null)
{
foreach (var state in oldState.EntityStates.Value)
{
entStates.Add(state.Clone());
}
}

if (oldState.PlayerStates.Value != null)
{
foreach (var state in oldState.PlayerStates.Value)
{
sesStates.Add(state.Clone());
}
}

if (oldState.EntityDeletions.Value != null)
{
foreach (var nent in oldState.EntityDeletions.Value)
{
deletions.Add(nent);
}
}

stateMsg.State = new GameState(
oldState.FromSequence,
oldState.ToSequence,
oldState.LastProcessedInput,
entStates.Count == 0 ? null : entStates,
sesStates.Count == 0 ? null : sesStates,
deletions.Count == 0 ? null : deletions);
}

// Clone as above because we don't write immediately in tests.
Expand All @@ -305,6 +266,7 @@ public void ServerSendMessage(NetMessage message, INetChannel recipient)

var channel = (IntegrationNetChannel) recipient;
channel.OtherChannel.TryWrite(new DataMessage(message, channel.RemoteUid));
return false;
}

public void ServerSendToMany(NetMessage message, List<INetChannel> recipients)
Expand Down

0 comments on commit abad5a1

Please sign in to comment.