Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_ReconnectComponent.c
Go to the documentation of this file.
3{
5 WorldTimestamp m_ValidUntil;
6
8 IEntity m_ReservedEntity;
9
10 // Add modded properties here from e.g. player controller that should be reapplied on reconnect onto the new controller.
11}
12
13[EntityEditorProps(category: "GameScripted/GameMode", description: "")]
14class SCR_ReconnectComponentClass : SCR_BaseGameModeComponentClass
16}
17
21{
22 // How many seconds a player has time to reconnect before the data expires and the character is removed.
23 protected int m_iReconnectTime = 120;
24
26
28
29 //------------------------------------------------------------------------------------------------
31 {
32 return s_Instance;
33 }
34
35 //------------------------------------------------------------------------------------------------
36 override protected void OnPostInit(IEntity owner)
37 {
38 SetEventMask(owner, EntityEvent.INIT);
39 }
40
41 //------------------------------------------------------------------------------------------------
42 override protected void EOnInit(IEntity owner)
43 {
44 RplComponent rplComp = RplComponent.Cast(owner.FindComponent(RplComponent));
45 if (!GetGame().InPlayMode() || !rplComp || rplComp.IsProxy())
46 return;
47
48 s_Instance = this;
49
50 SCR_DSConfig config();
51 if (GetGame().GetBackendApi().GetRunningDSConfig(config))
52 m_iReconnectTime = config.operating.slotReservationTimeout;
53 }
54
55 //------------------------------------------------------------------------------------------------
58 {
59 return m_iReconnectTime;
60 }
61
62 //------------------------------------------------------------------------------------------------
64 {
65 ScriptCallQueue callqueue = GetGame().GetCallqueue();
66 if (m_mReconnectData.IsEmpty())
67 {
68 callqueue.Remove(CheckExpiery);
69 return;
70 }
71
72 // Remove expired data and associated char every second (config is in seconds interval. Less frequent check leads to inaccuracy)
73 if (callqueue.GetRemainingTime(CheckExpiery) < 0)
74 callqueue.CallLater(CheckExpiery, 1000, true);
75 }
76
77 //------------------------------------------------------------------------------------------------
79 protected void CheckExpiery()
80 {
81 if (m_mReconnectData.IsEmpty())
82 return;
83
84 const WorldTimestamp timestamp = GetGame().GetWorld().GetTimestamp();
85
86 array<UUID> expired = {};
87 foreach (UUID identity, SCR_ReconnectData data : m_mReconnectData)
88 {
89 if (!IsDataExpired(data, timestamp))
90 continue;
91
93 expired.Insert(identity);
94 }
95
96 if (!expired.IsEmpty())
97 {
98 foreach (UUID identity : expired)
99 {
100 m_mReconnectData.Remove(identity);
101 }
102
104 }
105 }
106
107 //------------------------------------------------------------------------------------------------
109 bool HandlePlayerDisconnect(int playerId, KickCauseCode cause)
110 {
111 const KickCauseGroup2 group = KickCauseCodeAPI.GetGroup(cause);
112 if (group != RplKickCauseGroup.REPLICATION)
113 return false;
114
115 const int reason = KickCauseCodeAPI.GetReason(cause);
116 if (reason == RplError.SHUTDOWN)
117 return false;
118
119 const SCR_ReconnectData data = StoreData(playerId);
120 if (!IsDataRelevant(data))
121 return false;
122
123 const UUID identity = SCR_PlayerIdentityUtils.GetPlayerIdentityId(playerId);
124 m_mReconnectData.Set(identity, data);
125
127 return true;
128 }
129
130 //------------------------------------------------------------------------------------------------
133 bool HandlePlayerReconnect(int playerId)
134 {
135 const UUID identity = SCR_PlayerIdentityUtils.GetPlayerIdentityId(playerId);
137 if (!m_mReconnectData.Take(identity, data))
138 return false;
139
140 if (IsDataRelevant(data))
141 ApplyData(playerId, data);
142
144 return GetGame().GetPlayerManager().GetPlayerControlledEntity(playerId) != null;
145 }
146
147 //------------------------------------------------------------------------------------------------
149 protected notnull SCR_ReconnectData StoreData(int playerId)
150 {
152 data.m_ReservedEntity = GetGame().GetPlayerManager().GetPlayerControlledEntity(playerId);
153 if (m_iReconnectTime > 0)
154 data.m_ValidUntil = GetGame().GetWorld().GetTimestamp().PlusSeconds(m_iReconnectTime);
155
156 return data;
157 }
158
159 //------------------------------------------------------------------------------------------------
161 protected bool IsDataRelevant(notnull SCR_ReconnectData data)
162 {
163 const ChimeraCharacter character = ChimeraCharacter.Cast(data.m_ReservedEntity);
164 return character && !character.GetCharacterController().IsDead();
165 }
166
167 //------------------------------------------------------------------------------------------------
169 protected bool IsDataExpired(notnull SCR_ReconnectData data, WorldTimestamp timestamp)
170 {
171 return data.m_ValidUntil && data.m_ValidUntil.Less(timestamp);
172 }
173
174 //------------------------------------------------------------------------------------------------
177 {
178 if (!IsDataRelevant(data))
179 return; // Not relevant anymore, so we are not going to do anything with it.
180
181 auto respawn = SCR_RespawnSystemComponent.GetInstance();
182 if (respawn)
183 respawn.OnPlayerEntityCleanup_S(data.m_ReservedEntity);
184
185 RplComponent.DeleteRplEntity(data.m_ReservedEntity, false);
186 }
187
188 //------------------------------------------------------------------------------------------------
190 protected void ApplyData(int playerId, notnull SCR_ReconnectData data)
191 {
192 SCR_PlayerController playerController = SCR_PlayerController.Cast(GetGame().GetPlayerManager().GetPlayerController(playerId));
193 const ChimeraCharacter character = ChimeraCharacter.Cast(data.m_ReservedEntity);
194 playerController.SetInitialMainEntity(character);
195
196 const Faction faction = SCR_FactionManager.SGetFaction(character);
197 if (faction)
198 {
200 if (playerFactionComp)
201 playerFactionComp.SetFaction_S(faction);
202 }
203
204 SCR_RespawnSystemComponent.GetInstance().EmitPlayerEntityChange_S(playerId, null, character);
205
206 SCR_ReconnectSynchronizationComponent syncComp = SCR_ReconnectSynchronizationComponent.Cast(playerController.FindComponent(SCR_ReconnectSynchronizationComponent));
207 if (syncComp)
208 syncComp.CreateReconnectDialog();
209
211 if (core)
212 core.OnPlayerSpawn(playerId, character);
213 }
214}
ArmaReforgerScripted GetGame()
Definition game.c:1398
RplKickCauseGroup
void SCR_BaseGameModeComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
Get all prefabs that have the spawner data
void SCR_FactionManager(IEntitySource src, IEntity parent)
class SCR_ReconnectData EntityEditorProps(category:"GameScripted/GameMode", description:"")
proto external Managed FindComponent(typename typeName)
ref SCR_DSOperating operating
Core component to manage SCR_EditorManagerEntity.
void OnPlayerSpawn(int playerID, IEntity controlledEntity)
void SetInitialMainEntity(notnull IEntity entity)
void OnPostInit(IEntity owner)
void CheckExpiery()
Remove any data that has exceeded the max reconnect time window.
bool IsDataExpired(notnull SCR_ReconnectData data, WorldTimestamp timestamp)
Check if the reconnect time window has been exceeded.
bool HandlePlayerReconnect(int playerId)
static SCR_ReconnectComponent s_Instance
bool HandlePlayerDisconnect(int playerId, KickCauseCode cause)
Returns true if the players entity has been taken over for reconnection.
static SCR_ReconnectComponent GetInstance()
void HandleDataExpiery(notnull SCR_ReconnectData data)
Data has expired, handle graceful removal of presence in the world.
int GetReconnectTimeout()
For how many seconds a player can reconnect before the controlled character is removed.
ref map< UUID, ref SCR_ReconnectData > m_mReconnectData
notnull SCR_ReconnectData StoreData(int playerId)
Collect information relevant to reapply after reconnection to player controller / character.
void ApplyData(int playerId, notnull SCR_ReconnectData data)
Apply still relevant data back on successful reconnect.
bool IsDataRelevant(notnull SCR_ReconnectData data)
Returns true if the data is relevant for reconnect and we should store it in the system.
Data class for reconnecting players.
ScriptCallQueue Class provide "lazy" calls - when we don't want to execute function immediately but l...
Definition tools.c:53
Definition UUID.c:28
Definition Types.c:486
EntityEvent
Various entity events.
Definition EntityEvent.c:14
proto external PlayerController GetPlayerController()
KickCauseGroup2
Extends KickCauseGroup by adding game-specific groups.
RplError
Definition RplError.c:13