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 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; } }