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