Files
EscapistsReintroduced/docs/evidence/terrain-takeover-feature-2026-10-01/client-experiment-13/ERR_TerrainClientGate.c.txt
T
jakub 6a667d8deb Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
2026-10-13 22:52:53 +02:00

90 lines
3.3 KiB
Plaintext

modded class RplSessionErrorHandler
{
override void EOnConnected(RplIdentity identity)
{
super.EOnConnected(identity);
if (!Replication.IsServer()) return;
ERR_GameMode mode = ERR_GameMode.Get();
if (!mode || !mode.ERR_TerrainTakenOver()) return;
PrintFormat("ERR GATE: hold connection %1", identity);
ERR_TerrainClientGate.Stream(mode, identity, false);
ERR_TerrainClientGate gate = ERR_TerrainClientGate.Cast(GetGame().SpawnEntityPrefab(Resource.Load("{EA9D38B04C6F8521}Prefabs/ERR/TerrainClientGate.et"), GetGame().GetWorld()));
if (gate) gate.Assign(identity);
}
}
class ERR_TerrainClientGateClass : GenericEntityClass {}
class ERR_TerrainClientGate : GenericEntity
{
protected RplIdentity m_Target;
protected bool m_Drained;
protected bool m_Ready;
protected float m_Elapsed;
static void Stream(IEntity entity, RplIdentity identity, bool enabled)
{
if (!entity) return;
RplComponent rpl = RplComponent.Cast(entity.FindComponent(RplComponent));
if (rpl) { rpl.EnableSpatialRelevancy(false); rpl.EnableStreamingConNode(identity, enabled); }
IEntity child = entity.GetChildren();
while (child)
{
Stream(child, identity, enabled);
child = child.GetSibling();
}
}
void Assign(RplIdentity identity)
{
m_Target = identity;
RplComponent rpl = RplComponent.Cast(FindComponent(RplComponent));
rpl.Give(identity);
}
override void EOnFrame(IEntity owner, float timeSlice)
{
if (Replication.IsServer() || m_Ready) return;
RplComponent rpl = RplComponent.Cast(FindComponent(RplComponent));
if (!rpl || !rpl.IsOwner()) return;
if (!m_Drained)
{
GetGame().ERR_ClientGateDrain();
m_Drained = true;
}
m_Elapsed += timeSlice;
if (m_Elapsed < 0.5 || !GetGame().ERR_ClientGateEmpty()) return;
m_Ready = true;
Print("ERR GATE: client drained, requesting managers");
Rpc(RpcAsk_Ready);
}
[RplRpc(RplChannel.Reliable, RplRcver.Server)]
protected void RpcAsk_Ready()
{
if (!Replication.IsServer() || m_Ready) return;
m_Ready = true;
PrintFormat("ERR GATE: release connection %1", m_Target);
Stream(ERR_GameMode.Get(), m_Target, true);
}
void ERR_TerrainClientGate(IEntitySource src, IEntity parent)
{
SetEventMask(EntityEvent.FRAME);
}
}
modded class ArmaReforgerScripted
{
void ERR_ClientGateDrain()
{
PrintFormat("ERR GATE: client drain old mode=%1 runtime=%2", GetGameMode(), Replication.Runtime());
SCR_BaseGameMode mode = SCR_BaseGameMode.Cast(GetGameMode());
if (ERR_GameMode.Cast(mode)) { Print("ERR GATE: too late", LogLevel.ERROR); return; }
if (mode) mode.OnGameEnd();
if (m_DataCollectorComponent) m_DataCollectorComponent = null;
SCR_EntityCatalogManagerComponent.ERR_ReleaseTerrainCatalog(mode);
array<IEntity> managers = {mode, GetLoadoutManager(), GetFactionManager(), GetPerceptionManager(), GetChat()};
ChimeraWorld chimera = ChimeraWorld.CastFrom(GetWorld());
if (chimera) managers.Insert(chimera.GetRadioManager());
foreach (IEntity manager : managers) if (manager) SCR_EntityHelper.DeleteEntityAndChildren(manager);
}
bool ERR_ClientGateEmpty()
{
ChimeraWorld chimera = ChimeraWorld.CastFrom(GetWorld());
return !GetGameMode() && !GetLoadoutManager() && !GetFactionManager() && !GetPerceptionManager() && !GetChat() && (!chimera || !chimera.GetRadioManager()) && !SCR_EntityCatalogManagerComponent.GetInstance() && !m_DataCollectorComponent;
}
}