Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_EditorManagerCore.c
Go to the documentation of this file.
1
2
4[BaseContainerProps(configRoot: true)]
5class SCR_EditorManagerCore : SCR_GameCoreBase
6{
7 [Attribute("", UIWidgets.ResourceNamePicker, "Individual editor manager", "et")]
8 private ResourceName m_EditorManagerPrefab;
9
10 [Attribute("", UIWidgets.ResourceNamePicker, "Server entity prefab", "et")]
11 private ResourceName m_EditorServerPrefab;
12
13 [Attribute(desc: "Editor mode prefabs")]
14 private ref array<ref SCR_EditorModePrefab> m_ModePrefabs;
15
16 [Attribute("300", desc: "When player disconnects, editor modes will be restored if the player reconnects with this timeout (in seconds).")]
18
19 private SCR_EditorManagerEntity m_EditorManager;
20 private ref map<int, SCR_EditorManagerEntity> m_aEditorEntities;
21 private SCR_EditorSettingsEntity m_SettingsEntity;
22 private SCR_EditorServerEntity m_ServerEntity;
23 private ref SCR_SortedArray<SCR_EditorModePrefab> m_ModePrefabsSorted = new SCR_SortedArray<SCR_EditorModePrefab>;
24 private ref array<ref SCR_EditorManagerDisconnectData> m_DisconnectedModes;
25
28 ref ScriptInvoker Event_OnEditorManagerCreatedServer = new ScriptInvoker;
29
32 ref ScriptInvoker Event_OnEditorManagerDeletedServer = new ScriptInvoker;
33
36 ref ScriptInvoker Event_OnEditorManagerInitOwner = new ScriptInvoker;
37
40 ref ScriptInvoker Event_OnEditorManagerPing = new ScriptInvoker;
41
43 //--- Custom functions
45
46 //------------------------------------------------------------------------------------------------
48 {
49 if (RplSession.Mode() == RplMode.Client || (m_SettingsEntity && m_SettingsEntity.IsEditorDisabled()))
50 return null;
51
52 if (m_aEditorEntities && m_aEditorEntities.Contains(playerID))
53 {
54 Debug.Error2("SCR_EditorManagerCore.CreateEditorManager()", string.Format("Attempt for duplicate registration of editor manager for playerID = %1!", playerID));
55 return null;
56 }
57
58 PlayerController playerController = GetGame().GetPlayerManager().GetPlayerController(playerID);
59 if (!playerController)
60 {
61 Debug.Error2("SCR_EditorManagerCore.CreateEditorManager()", string.Format("Cannot create editor manager entity, PlayerController for playerID = %1 does not exist yet!", playerID));
62 return null;
63 }
64
65 //--- Get player replication ID (not identical to player ID!)
66 RplIdentity playerRplID = playerController.GetRplIdentity();
67
68 //--- Check for duplicates, exit when found
69 for (int i = 0; i < m_aEditorEntities.Count(); i++)
70 {
71 PlayerController compareController = GetGame().GetPlayerManager().GetPlayerController(m_aEditorEntities.GetKey(i));
72 if (compareController && compareController.GetRplIdentity() == playerRplID)
73 {
74 Debug.Error2("SCR_EditorManagerCore.CreateEditorManager()", string.Format("Cannot register editor manager for playerID = %1 because manager for playerID = %2 is already registered on the same machine!", playerID, m_aEditorEntities.GetKey(i)));
75 return null;
76 }
77 }
78
79 //--- Create the entity
80 ResourceName prefab = m_EditorManagerPrefab;
81 if (m_SettingsEntity)
82 prefab = m_SettingsEntity.GetPrefab(m_EditorManagerPrefab);
83
84 SCR_EditorManagerEntity editorManager = SCR_EditorManagerEntity.Cast(GetGame().SpawnEntityPrefab(Resource.Load(prefab)));
85 if (!editorManager)
86 {
87 Debug.Error2("SCR_EditorManagerCore.CreateEditorManager()", string.Format("Prefab %1 is not SCR_EditorManagerEntity!", prefab.GetPath()));
88 delete editorManager;
89 return null;
90 }
91
92 //--- Set entity ownership (not for editor of host player)
93 if (playerRplID != RplIdentity.Local())
94 {
95 RplComponent rpl = RplComponent.Cast(editorManager.FindComponent(RplComponent));
96 if (!rpl)
97 {
98 Debug.Error2("SCR_EditorManagerCore.CreateEditorManager()", string.Format("Prefab %1 is missing RplComponent component!", prefab.GetPath()));
99 delete editorManager;
100 return null;
101 }
102 rpl.Give(playerRplID);
103 }
104 m_aEditorEntities.Insert(playerID, editorManager);
105
106 //--- Initialize the entity
107 editorManager.InitServer(playerID);
108 Event_OnEditorManagerCreatedServer.Invoke(editorManager);
109
110 //--- Get active player roles
111 EPlayerRole playerRoles;
112 array<EPlayerRole> allRoles = {};
113 for(int i, count = SCR_Enum.GetEnumValues(EPlayerRole, allRoles); i < count; i++)
114 {
115 if (GetGame().GetPlayerManager().HasPlayerRole(playerID, allRoles[i]))
116 playerRoles |= allRoles[i];
117 }
118 OnPlayerRoleChange(playerID, playerRoles);
119
120 //--- Set base editor modes. If player reconnects, restore their previous modes.
122
123 //--- Restore modes player had before disconnecting
124 if (m_DisconnectedModes)
125 {
126 ChimeraWorld world = GetGame().GetWorld();
127 WorldTimestamp currentTime = world.GetServerTimestamp();
128 for (int i = m_DisconnectedModes.Count() - 1; i >= 0; i--)
129 {
130 if (currentTime.Greater(m_DisconnectedModes[i].m_Time.PlusSeconds(m_iRestoreOnReconnectTimeout)))
131 {
132 //--- Expired, ignore
133 m_DisconnectedModes.Remove(i);
134 }
135 else if (m_DisconnectedModes[i].m_iPlayerID == playerID)
136 {
137 //--- Not expired, restore modes
138 modes = m_DisconnectedModes[i].m_Modes;
139 m_DisconnectedModes.Remove(i);
140 }
141 }
142 if (m_DisconnectedModes.IsEmpty())
143 m_DisconnectedModes = null;
144 }
145
146 editorManager.AddEditorModes(EEditorModeAccess.BASE, modes, true);
147
148 //--- Finish initualization
149 editorManager.PostInitServer();
150
151 return editorManager;
152 }
153
154 //------------------------------------------------------------------------------------------------
155 protected void DeleteEditorManager(int playerID)
156 {
157 if (RplSession.Mode() == RplMode.Client)
158 return;
159
160 if (m_aEditorEntities.Contains(playerID))
161 {
162 SCR_EditorManagerEntity editorManager = m_aEditorEntities.Get(playerID);
163
164 //--- Remember editor modes so they can be restored upon reconnection
165 if (!m_DisconnectedModes)
166 m_DisconnectedModes = {};
167
168 bool isAdmin = SCR_Global.IsAdmin(playerID);
169
170 EEditorMode modes = editorManager.GetModes();
171 EEditorMode persistentModes;
172 foreach (SCR_EditorModePrefab prefab: m_ModePrefabs)
173 {
174 if (
175 SCR_Enum.HasFlag(modes, prefab.GetMode()) //--- Player has the mode
176 && SCR_Enum.HasFlag(prefab.GetFlags(), EEditorModeFlag.PERSISTENT) //--- Mode is marked as persistent
177 && (!isAdmin || !SCR_Enum.HasFlag(prefab.GetFlags(), EEditorModeFlag.ADMIN)) //--- If player is admin, don't preserve modes added with admin rights
178 )
179 {
180 persistentModes |= prefab.GetMode();
181 }
182 }
183
184 if (persistentModes != 0)
185 m_DisconnectedModes.Insert(new SCR_EditorManagerDisconnectData(playerID, persistentModes));
186
187 m_aEditorEntities.Remove(playerID);
188 Event_OnEditorManagerDeletedServer.Invoke(editorManager);
189 editorManager.DeleteAllEditors();
190 delete editorManager;
191 }
192 }
193
194 //------------------------------------------------------------------------------------------------
197 int GetEditorEntities(out notnull array<SCR_EditorManagerEntity> outEditorEntities)
198 {
199 outEditorEntities.Clear();
200 if (m_aEditorEntities)
201 {
202 for (int i = 0; i < m_aEditorEntities.Count(); i++)
203 {
204 SCR_EditorManagerEntity editorManager = m_aEditorEntities.GetElement(i);
205 if (editorManager)
206 outEditorEntities.Insert(editorManager);
207 }
208 }
209 return outEditorEntities.Count();
210 }
211
212 //------------------------------------------------------------------------------------------------
216 {
217 if (m_EditorManager)
218 {
219 Print("Attempting to define multiple instances of SCR_EditorManagerEntity!", LogLevel.ERROR);
220 return false;
221 }
222 m_EditorManager = entity;
223 return true;
224 }
225
226 //------------------------------------------------------------------------------------------------
230 {
231 return m_EditorManager;
232 }
233
234 //------------------------------------------------------------------------------------------------
239 {
240 if (m_aEditorEntities && m_aEditorEntities.Contains(playerID))
241 return m_aEditorEntities.Get(playerID);
242 else
243 return null;
244 }
245
246 //------------------------------------------------------------------------------------------------
250 {
251 if (Replication.IsClient())
252 {
253 Debug.Error2("SCR_EditorManagerCore.GetEditorServer()", "Editor server entity is available only on server!");
254 return null;
255 }
256 return m_ServerEntity;
257 }
258
259 //------------------------------------------------------------------------------------------------
264 {
265 if (m_SettingsEntity)
266 return;
267
268 m_SettingsEntity = entity;
269 }
270
271 //------------------------------------------------------------------------------------------------
275 {
276 return m_SettingsEntity;
277 }
278
279 //------------------------------------------------------------------------------------------------
284 {
285 array<SCR_EditorModePrefab> prefabs = {};
286 GetBaseModePrefabs(prefabs);
287 foreach (SCR_EditorModePrefab modePrefab: prefabs)
288 {
289 if (modePrefab.GetMode() == modeType)
290 return modePrefab;
291 }
292 return null;
293 }
294
295 //------------------------------------------------------------------------------------------------
300 EEditorMode GetBaseModes(EEditorModeFlag flags = -1, bool coreOnly = false)
301 {
302 EEditorMode modes;
303 array<SCR_EditorModePrefab> prefabs = {};
304 for (int i, count = GetBaseModePrefabs(prefabs, flags, coreOnly); i < count; i++)
305 {
306 modes |= prefabs[i].GetMode();
307 }
308 return modes;
309 }
310
311 //------------------------------------------------------------------------------------------------
316 int GetBaseModePrefabs(out notnull array<SCR_EditorModePrefab> outPrefabs, EEditorModeFlag flags = -1, bool coreOnly = false)
317 {
318 EEditorMode defaultModes;
319 bool isOverride = !coreOnly && m_SettingsEntity && m_SettingsEntity.GetBaseModes(defaultModes);
320
321 int count = m_ModePrefabs.Count();
322 foreach (SCR_EditorModePrefab prefab: m_ModePrefabs)
323 {
324 if (isOverride)
325 {
326 //--- Override, use mode even when flags are not matching
327 if (SCR_Enum.HasFlag(defaultModes, prefab.GetMode()))
328 outPrefabs.Insert(prefab);
329 }
330 else
331 {
332 //--- No override, check by flags
333 if (flags == -1 || SCR_Enum.HasPartialFlag(prefab.GetFlags(), flags))
334 outPrefabs.Insert(prefab);
335 }
336 }
337 return outPrefabs.Count();
338 }
339
340 //------------------------------------------------------------------------------------------------
345 int GetBaseModePrefabs(out notnull SCR_SortedArray<SCR_EditorModePrefab> outPrefabs, EEditorModeFlag flags = -1, bool coreOnly = false)
346 {
347 EEditorMode defaultModes;
348 bool isOverride = !coreOnly && m_SettingsEntity && m_SettingsEntity.GetBaseModes(defaultModes);
349
351 int count = m_ModePrefabsSorted.Count();
352 for (int i; i < count; i++)
353 {
354 prefab = m_ModePrefabsSorted[i];
355 if (
356 (!isOverride || SCR_Enum.HasFlag(defaultModes, prefab.GetMode()))
357 && (flags == -1 || SCR_Enum.HasPartialFlag(prefab.GetFlags(), flags))
358 )
359 {
360 outPrefabs.Insert(m_ModePrefabsSorted.GetOrder(i), prefab);
361 }
362 }
363 return outPrefabs.Count();
364 }
365
366 //------------------------------------------------------------------------------------------------
371 {
372 foreach (SCR_EditorModePrefab modeEntity: m_ModePrefabs)
373 {
374 if (modeEntity.GetMode() == modeType)
375 return modeEntity.GetInfo();
376 }
377 return null;
378 }
379
381 //--- Event handlers
383
384 //------------------------------------------------------------------------------------------------
385 protected void OnPlayerRegistered(int playerID)
386 {
387 //--- Create and register editor manager
388 CreateEditorManager(playerID);
389
390 //--- If an entity was already created for player, initialize it (e.g., when there is no respawn menu)
391 IEntity controlledEntity = GetGame().GetPlayerManager().GetPlayerControlledEntity(playerID);
392 if (controlledEntity)
393 OnPlayerSpawn(playerID, controlledEntity);
394 }
395
396 //------------------------------------------------------------------------------------------------
397 protected void OnPlayerDisconnected(int playerID)
398 {
399 //--- Delete and unregister editor manager
400 DeleteEditorManager(playerID);
401 }
402
403 //------------------------------------------------------------------------------------------------
405 protected void OnPlayerSpawn(int playerID, IEntity controlledEntity)
406 {
407 SCR_EditorManagerEntity editorManager = GetEditorManager(playerID);
408 if (editorManager)
409 {
410 editorManager.SetCanOpen(true, EEditorCanOpen.ALIVE);
411 editorManager.AutoInit();
412 }
413 }
414
415 //------------------------------------------------------------------------------------------------
416 protected void OnPlayerKilled(notnull SCR_InstigatorContextData instigatorContextData)
417 {
418 SCR_EditorManagerEntity editorManager = GetEditorManager(instigatorContextData.GetVictimPlayerID());
419 if (editorManager)
420 editorManager.SetCanOpen(false, EEditorCanOpen.ALIVE);
421 }
422
423 //------------------------------------------------------------------------------------------------
424 protected void OnPlayerDeleted(int playerID, IEntity player)
425 {
426 OnPlayerKilled(new SCR_InstigatorContextData(playerID, player, null, Instigator.CreateInstigatorGM(), true));
427 }
428
429 //------------------------------------------------------------------------------------------------
430 protected void OnPlayerRoleChange(int playerId, EPlayerRole roleFlags)
431 {
432 SCR_EditorManagerEntity editorManager = GetEditorManager(playerId);
433 if (editorManager)
434 {
436
437 //--- Game running in Workbench and player ID is host
438#ifdef WORKBENCH
439 if (playerId == SCR_PlayerController.GetLocalPlayerId())
440 flags |= EEditorModeFlag.WORKBENCH;
441#endif
442 //--- User is admin in multiplayer (suppress it in SP to avoid MP-specific modes)
443 if (SCR_Global.IsAdminRole(roleFlags) && Replication.IsRunning())
444 flags |= EEditorModeFlag.ADMIN;
445
446 EEditorMode modes = GetBaseModes(flags, true);
447 editorManager.SetEditorModes(EEditorModeAccess.ROLE, modes, false);
448 }
449 }
450
451#ifdef WORKBENCH
452 //------------------------------------------------------------------------------------------------
454 void OnPlayFromCameraPos()
455 {
456 //--- Ignore when the world contains game mode, player is registered by it alrady
457 if (GetGame().GetGameMode())
458 return;
459
460 PlayerController playerController = GetGame().GetPlayerController();
461 if (playerController)
462 {
463 int playerID = playerController.GetPlayerId();
464 if (playerID > 0)
465 {
466 CreateEditorManager(playerID);
467 return;
468 }
469 //--- Player not initialized yet, try again next frame
470 GetGame().GetCallqueue().CallLater(OnPlayFromCameraPos, 1);
471 }
472 }
473#endif
474
476 //--- Default Functions
478
479 //------------------------------------------------------------------------------------------------
480 override void OnGameStart()
481 {
482 //--- Server only
483 if (RplSession.Mode() == RplMode.Client)
484 return;
485
486 //--- Create server entity
487 m_ServerEntity = SCR_EditorServerEntity.Cast(GetGame().SpawnEntityPrefab(Resource.Load(m_EditorServerPrefab)));
488
489 //--- Create settings entity, unless it exists in the world
490 if (!m_SettingsEntity)
491 {
493 m_SettingsEntity.SetBaseModes(GetBaseModes(EEditorModeFlag.DEFAULT, true), false);
494 //m_SettingsEntity.EnableBaseOverride(true);
495 }
496
497 //--- Initialize entity list (ignore if already done)
498 if (m_aEditorEntities)
499 return;
500
501 m_aEditorEntities = new map<int, SCR_EditorManagerEntity>();
502
503 //--- Get lobby
505 if (gameMode)
506 {
507 //--- Add game mode event handlers
508 gameMode.GetOnPlayerRegistered().Insert(OnPlayerRegistered);
510 gameMode.GetOnPlayerSpawned().Insert(OnPlayerSpawn);
511 gameMode.GetOnPlayerKilled().Insert(OnPlayerKilled);
512 gameMode.GetOnPlayerDeleted().Insert(OnPlayerDeleted);
513 gameMode.GetOnPlayerRoleChange().Insert(OnPlayerRoleChange);
514 }
515 else
516 {
517 //--- No game mode detected, run on local player
518 PlayerController controller = GetGame().GetPlayerController();
519 if (controller && controller.GetPlayerId() > 0)
520 {
521 OnPlayerRegistered(controller.GetPlayerId());
522 }
523 else
524 {
525 //--- No local player found, force the editor
526 //OnPlayerRegistered(-1); //--- Disabled, there should be a chance to have an empty world for debugging purposes
527 return;
528 }
529 }
530 }
531
532 //------------------------------------------------------------------------------------------------
533 override void OnGameEnd()
534 {
535 m_EditorManager = null;
536 m_aEditorEntities = null;
537 Event_OnEditorManagerCreatedServer = new ScriptInvoker;
538 Event_OnEditorManagerDeletedServer = new ScriptInvoker;
539 Event_OnEditorManagerInitOwner = new ScriptInvoker;
540 }
541
542 //------------------------------------------------------------------------------------------------
543 // constructor
545 {
546 //--- Cache array of modes sorted by custom order
547 foreach (SCR_EditorModePrefab prefabData: m_ModePrefabs)
548 {
549 m_ModePrefabsSorted.Insert(prefabData.GetInfo().GetOrder(), prefabData);
550 }
551
552 DiagMenu.RegisterMenu(SCR_DebugMenuID.DEBUGUI_EDITOR, "Editor", "");
553 }
554
555 //------------------------------------------------------------------------------------------------
556 // destructor
558 {
559 Event_OnEditorManagerCreatedServer = null;
560 Event_OnEditorManagerDeletedServer = null;
561 Event_OnEditorManagerInitOwner = null;
562 DiagMenu.Unregister(SCR_DebugMenuID.DEBUGUI_EDITOR);
563 }
564}
565
567{
571
572 //------------------------------------------------------------------------------------------------
574 {
575 m_iPlayerID = playerID;
576 m_Modes = modes;
577 ChimeraWorld world = GetGame().GetWorld();
578 m_Time = world.GetServerTimestamp(); //--- Can use absolute value, we don't need precision
579 }
580}
SCR_EAIThreatSectorFlags flags
SCR_DebugMenuID
This enum contains all IDs for DiagMenu entries added in script.
Definition DebugMenuID.c:4
EEditorModeAccess
EEditorModeFlag
EPlayerRole
Definition EPlayerRole.c:8
ArmaReforgerScripted GetGame()
Definition game.c:1398
RplMode
Mode of replication.
Definition RplMode.c:9
SCR_AIAnimation_Loitering BaseContainerProps
Commanding menu commanding element class.
SCR_BaseGameMode GetGameMode()
IEntity SpawnEntity(ResourceName entityResourceName, notnull IEntity slotOwner)
void SCR_EditorManagerDisconnectData(int playerID, EEditorMode modes)
EEditorMode m_Modes
WorldTimestamp m_Time
void SCR_EditorManagerEntity(IEntitySource src, IEntity parent)
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
Definition Debug.c:13
Diagnostic and developer menu system.
Definition DiagMenu.c:18
Main replication API.
Definition Replication.c:14
Object holding reference to resource. In destructor release the resource.
Definition Resource.c:25
Replication connection identity.
Definition RplIdentity.c:14
ScriptInvokerBase< SCR_BaseGameMode_OnPlayerDisconnected > GetOnPostCompPlayerDisconnected()
ScriptInvokerBase< SCR_BaseGameMode_PlayerIdAndEntity > GetOnPlayerSpawned()
ScriptInvokerBase< SCR_BaseGameMode_PlayerIdAndEntity > GetOnPlayerDeleted()
ScriptInvokerBase< SCR_BaseGameMode_OnControllableDestroyed > GetOnPlayerKilled()
ScriptInvokerBase< SCR_BaseGameMode_PlayerId > GetOnPlayerRegistered()
ScriptInvokerBase< SCR_BaseGameMode_OnPlayerRoleChanged > GetOnPlayerRoleChange()
SCR_EditorSettingsEntity GetSettingsEntity()
int GetEditorEntities(out notnull array< SCR_EditorManagerEntity > outEditorEntities)
void SetSettingsEntity(SCR_EditorSettingsEntity entity)
EEditorMode GetBaseModes(EEditorModeFlag flags=-1, bool coreOnly=false)
void OnPlayerSpawn(int playerID, IEntity controlledEntity)
bool SetEditorManager(SCR_EditorManagerEntity entity)
SCR_EditorManagerEntity CreateEditorManager(int playerID)
SCR_EditorModePrefab GetBaseModePrefab(EEditorMode modeType)
SCR_EditorManagerEntity GetEditorManager(int playerID)
SCR_EditorModeUIInfo GetDefaultModeInfo(EEditorMode modeType)
int GetBaseModePrefabs(out notnull SCR_SortedArray< SCR_EditorModePrefab > outPrefabs, EEditorModeFlag flags=-1, bool coreOnly=false)
SCR_EditorManagerEntity GetEditorManager()
void OnPlayerDeleted(int playerID, IEntity player)
void OnPlayerDisconnected(int playerID)
void DeleteEditorManager(int playerID)
void OnPlayerRegistered(int playerID)
int GetBaseModePrefabs(out notnull array< SCR_EditorModePrefab > outPrefabs, EEditorModeFlag flags=-1, bool coreOnly=false)
void OnPlayerRoleChange(int playerId, EPlayerRole roleFlags)
SCR_EditorServerEntity GetEditorServer()
void OnPlayerKilled(notnull SCR_InstigatorContextData instigatorContextData)
void SetBaseModes(EEditorMode modes, bool validate=true)
static bool IsAdmin(int playerID)
Definition Functions.c:1927
static bool IsAdminRole(EPlayerRole role)
Definition Functions.c:1916
static int GetLocalPlayerId()
Returns either a valid ID of local player or 0.
Definition Types.c:486
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
SCR_FieldOfViewSettings Attribute
EEditorMode
Editor mode that defines overall functionality.
Definition EEditorMode.c:6
EEditorCanOpen
Layers allowing editor to be opened. All of them have to be activated (certain exceptions may apply w...
SCR_EditorManagerCore m_iPlayerID
ScriptInvokerBase< func > ScriptInvoker
Definition tools.c:134