Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_EditorManagerCore.c
Go to the documentation of this file.
1 
4 [BaseContainerProps(configRoot: true)]
5 class 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).")]
17  protected int m_iRestoreOnReconnectTimeout;
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  //------------------------------------------------------------------------------------------------
47  protected SCR_EditorManagerEntity CreateEditorManager(int playerID)
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.
121  EEditorMode modes = GetBaseModes(EEditorModeFlag.DEFAULT);
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  delete editorManager;
190  }
191  }
192 
193  //------------------------------------------------------------------------------------------------
196  int GetEditorEntities(out notnull array<SCR_EditorManagerEntity> outEditorEntities)
197  {
198  outEditorEntities.Clear();
199  if (m_aEditorEntities)
200  {
201  for (int i = 0; i < m_aEditorEntities.Count(); i++)
202  {
203  SCR_EditorManagerEntity editorManager = m_aEditorEntities.GetElement(i);
204  if (editorManager)
205  outEditorEntities.Insert(editorManager);
206  }
207  }
208  return outEditorEntities.Count();
209  }
210 
211  //------------------------------------------------------------------------------------------------
214  bool SetEditorManager(SCR_EditorManagerEntity entity)
215  {
216  if (m_EditorManager)
217  {
218  Print("Attempting to define multiple instances of SCR_EditorManagerEntity!", LogLevel.ERROR);
219  return false;
220  }
221  m_EditorManager = entity;
222  return true;
223  }
224 
225  //------------------------------------------------------------------------------------------------
228  SCR_EditorManagerEntity GetEditorManager()
229  {
230  return m_EditorManager;
231  }
232 
233  //------------------------------------------------------------------------------------------------
237  SCR_EditorManagerEntity GetEditorManager(int playerID)
238  {
239  if (m_aEditorEntities && m_aEditorEntities.Contains(playerID))
240  return m_aEditorEntities.Get(playerID);
241  else
242  return null;
243  }
244 
245  //------------------------------------------------------------------------------------------------
248  SCR_EditorServerEntity GetEditorServer()
249  {
250  if (Replication.IsClient())
251  {
252  Debug.Error2("SCR_EditorManagerCore.GetEditorServer()", "Editor server entity is available only on server!");
253  return null;
254  }
255  return m_ServerEntity;
256  }
257 
258  //------------------------------------------------------------------------------------------------
262  void SetSettingsEntity(SCR_EditorSettingsEntity entity)
263  {
264  if (m_SettingsEntity)
265  return;
266 
267  m_SettingsEntity = entity;
268  }
269 
270  //------------------------------------------------------------------------------------------------
273  SCR_EditorSettingsEntity GetSettingsEntity()
274  {
275  return m_SettingsEntity;
276  }
277 
278  //------------------------------------------------------------------------------------------------
282  SCR_EditorModePrefab GetBaseModePrefab(EEditorMode modeType)
283  {
284  array<SCR_EditorModePrefab> prefabs = {};
285  GetBaseModePrefabs(prefabs);
286  foreach (SCR_EditorModePrefab modePrefab: prefabs)
287  {
288  if (modePrefab.GetMode() == modeType)
289  return modePrefab;
290  }
291  return null;
292  }
293 
294  //------------------------------------------------------------------------------------------------
299  EEditorMode GetBaseModes(EEditorModeFlag flags = -1, bool coreOnly = false)
300  {
301  EEditorMode modes;
302  array<SCR_EditorModePrefab> prefabs = {};
303  for (int i, count = GetBaseModePrefabs(prefabs, flags, coreOnly); i < count; i++)
304  {
305  modes |= prefabs[i].GetMode();
306  }
307  return modes;
308  }
309 
310  //------------------------------------------------------------------------------------------------
315  int GetBaseModePrefabs(out notnull array<SCR_EditorModePrefab> outPrefabs, EEditorModeFlag flags = -1, bool coreOnly = false)
316  {
317  EEditorMode defaultModes;
318  bool isOverride = !coreOnly && m_SettingsEntity && m_SettingsEntity.GetBaseModes(defaultModes);
319 
320  int count = m_ModePrefabs.Count();
321  foreach (SCR_EditorModePrefab prefab: m_ModePrefabs)
322  {
323  if (isOverride)
324  {
325  //--- Override, use mode even when flags are not matching
326  if (SCR_Enum.HasFlag(defaultModes, prefab.GetMode()))
327  outPrefabs.Insert(prefab);
328  }
329  else
330  {
331  //--- No override, check by flags
332  if (flags == -1 || SCR_Enum.HasPartialFlag(prefab.GetFlags(), flags))
333  outPrefabs.Insert(prefab);
334  }
335  }
336  return outPrefabs.Count();
337  }
338 
339  //------------------------------------------------------------------------------------------------
344  int GetBaseModePrefabs(out notnull SCR_SortedArray<SCR_EditorModePrefab> outPrefabs, EEditorModeFlag flags = -1, bool coreOnly = false)
345  {
346  EEditorMode defaultModes;
347  bool isOverride = !coreOnly && m_SettingsEntity && m_SettingsEntity.GetBaseModes(defaultModes);
348 
349  SCR_EditorModePrefab prefab;
350  int count = m_ModePrefabsSorted.Count();
351  for (int i; i < count; i++)
352  {
353  prefab = m_ModePrefabsSorted[i];
354  if (
355  (!isOverride || SCR_Enum.HasFlag(defaultModes, prefab.GetMode()))
356  && (flags == -1 || SCR_Enum.HasPartialFlag(prefab.GetFlags(), flags))
357  )
358  {
359  outPrefabs.Insert(m_ModePrefabsSorted.GetOrder(i), prefab);
360  }
361  }
362  return outPrefabs.Count();
363  }
364 
365  //------------------------------------------------------------------------------------------------
369  SCR_EditorModeUIInfo GetDefaultModeInfo(EEditorMode modeType)
370  {
371  foreach (SCR_EditorModePrefab modeEntity: m_ModePrefabs)
372  {
373  if (modeEntity.GetMode() == modeType)
374  return modeEntity.GetInfo();
375  }
376  return null;
377  }
378 
380  //--- Event handlers
382 
383  //------------------------------------------------------------------------------------------------
384  protected void OnPlayerRegistered(int playerID)
385  {
386  //--- Create and register editor manager
387  CreateEditorManager(playerID);
388 
389  //--- If an entity was already created for player, initialize it (e.g., when there is no respawn menu)
390  IEntity controlledEntity = GetGame().GetPlayerManager().GetPlayerControlledEntity(playerID);
391  if (controlledEntity)
392  OnPlayerSpawn(playerID, controlledEntity);
393  }
394 
395  //------------------------------------------------------------------------------------------------
396  protected void OnPlayerDisconnected(int playerID)
397  {
398  //--- Delete and unregister editor manager
399  DeleteEditorManager(playerID);
400  }
401 
402  //------------------------------------------------------------------------------------------------
403  protected void OnPlayerSpawn(int playerID, IEntity controlledEntity)
404  {
405  SCR_EditorManagerEntity editorManager = GetEditorManager(playerID);
406  if (editorManager)
407  {
408  editorManager.SetCanOpen(true, EEditorCanOpen.ALIVE);
409  editorManager.AutoInit();
410  }
411  }
412 
413  //------------------------------------------------------------------------------------------------
414  protected void OnPlayerKilled(int playerId, IEntity playerEntity, IEntity killerEntity, notnull Instigator killer)
415  {
416  SCR_EditorManagerEntity editorManager = GetEditorManager(playerId);
417  if (editorManager)
418  editorManager.SetCanOpen(false, EEditorCanOpen.ALIVE);
419  }
420 
421  //------------------------------------------------------------------------------------------------
422  protected void OnPlayerDeleted(int playerID, IEntity player)
423  {
424  OnPlayerKilled(playerID, player, null, Instigator.CreateInstigator(null));
425  }
426 
427  //------------------------------------------------------------------------------------------------
428  protected void OnPlayerRoleChange(int playerId, EPlayerRole roleFlags)
429  {
430  SCR_EditorManagerEntity editorManager = GetEditorManager(playerId);
431  if (editorManager)
432  {
433  EEditorModeFlag flags;
434 
435  //--- Game running in Workbench and player ID is host
436 #ifdef WORKBENCH
437  if (playerId == SCR_PlayerController.GetLocalPlayerId())
438  flags |= EEditorModeFlag.WORKBENCH;
439 #endif
440  //--- User is admin in multiplayer (suppress it in SP to avoid MP-specific modes)
441  if (SCR_Global.IsAdminRole(roleFlags) && Replication.IsRunning())
442  flags |= EEditorModeFlag.ADMIN;
443 
444  EEditorMode modes = GetBaseModes(flags, true);
445  editorManager.SetEditorModes(EEditorModeAccess.ROLE, modes, false);
446  }
447  }
448 
449 #ifdef WORKBENCH
450  //------------------------------------------------------------------------------------------------
452  void OnPlayFromCameraPos()
453  {
454  //--- Ignore when the world contains game mode, player is registered by it alrady
455  if (GetGame().GetGameMode())
456  return;
457 
458  PlayerController playerController = GetGame().GetPlayerController();
459  if (playerController)
460  {
461  int playerID = playerController.GetPlayerId();
462  if (playerID > 0)
463  {
464  CreateEditorManager(playerID);
465  return;
466  }
467  //--- Player not initialized yet, try again next frame
468  GetGame().GetCallqueue().CallLater(OnPlayFromCameraPos, 1);
469  }
470  }
471 #endif
472 
473  //------------------------------------------------------------------------------------------------
474  protected void OnReconnectOnPreviousCharacter(notnull SCR_ReconnectData reconnectData)
475  {
476  int playerID = reconnectData.m_iPlayerId;
477 
478  IEntity controlledEntity = GetGame().GetPlayerManager().GetPlayerControlledEntity(playerID);
479  if (controlledEntity)
480  OnPlayerSpawn(playerID, controlledEntity);
481  }
482 
484  //--- Default Functions
486 
487  //------------------------------------------------------------------------------------------------
488  override void OnGameStart()
489  {
490  //--- Server only
491  if (RplSession.Mode() == RplMode.Client)
492  return;
493 
494  //--- Create server entity
495  m_ServerEntity = SCR_EditorServerEntity.Cast(GetGame().SpawnEntityPrefab(Resource.Load(m_EditorServerPrefab)));
496 
497  //--- Create settings entity, unless it exists in the world
498  if (!m_SettingsEntity)
499  {
501  m_SettingsEntity.SetBaseModes(GetBaseModes(EEditorModeFlag.DEFAULT, true), false);
502  //m_SettingsEntity.EnableBaseOverride(true);
503  }
504 
505  //--- Initialize entity list (ignore if already done)
506  if (m_aEditorEntities)
507  return;
508 
509  m_aEditorEntities = new map<int, SCR_EditorManagerEntity>();
510 
511  //--- Get lobby
513  if (gameMode)
514  {
515  //--- Add game mode event handlers
516  gameMode.GetOnPlayerRegistered().Insert(OnPlayerRegistered);
517  gameMode.GetOnPostCompPlayerDisconnected().Insert(OnPlayerDisconnected);
518  gameMode.GetOnPlayerSpawned().Insert(OnPlayerSpawn);
519  gameMode.GetOnPlayerKilled().Insert(OnPlayerKilled);
520  gameMode.GetOnPlayerDeleted().Insert(OnPlayerDeleted);
521  gameMode.GetOnPlayerRoleChange().Insert(OnPlayerRoleChange);
522  }
523  else
524  {
525  //--- No game mode detected, run on local player
526  PlayerController controller = GetGame().GetPlayerController();
527  if (controller && controller.GetPlayerId() > 0)
528  {
529  OnPlayerRegistered(controller.GetPlayerId());
530  }
531  else
532  {
533  //--- No local player found, force the editor
534  //OnPlayerRegistered(-1); //--- Disabled, there should be a chance to have an empty world for debugging purposes
535  return;
536  }
537  }
538 
539  // Listen to reconnect
540  if (SCR_ReconnectComponent.GetInstance())
541  SCR_ReconnectComponent.GetInstance().GetOnReconnect().Insert(OnReconnectOnPreviousCharacter);
542  }
543 
544  //------------------------------------------------------------------------------------------------
545  override void OnGameEnd()
546  {
547  m_EditorManager = null;
548  m_aEditorEntities = null;
549  Event_OnEditorManagerCreatedServer = new ScriptInvoker;
550  Event_OnEditorManagerDeletedServer = new ScriptInvoker;
551  Event_OnEditorManagerInitOwner = new ScriptInvoker;
552  }
553 
554  //------------------------------------------------------------------------------------------------
555  // constructor
556  void SCR_EditorManagerCore()
557  {
558  //--- Cache array of modes sorted by custom order
559  foreach (SCR_EditorModePrefab prefabData: m_ModePrefabs)
560  {
561  m_ModePrefabsSorted.Insert(prefabData.GetInfo().GetOrder(), prefabData);
562  }
563 
564  DiagMenu.RegisterMenu(SCR_DebugMenuID.DEBUGUI_EDITOR, "Editor", "");
565  }
566 
567  //------------------------------------------------------------------------------------------------
568  // destructor
569  void ~SCR_EditorManagerCore()
570  {
571  Event_OnEditorManagerCreatedServer = null;
572  Event_OnEditorManagerDeletedServer = null;
573  Event_OnEditorManagerInitOwner = null;
574  DiagMenu.Unregister(SCR_DebugMenuID.DEBUGUI_EDITOR);
575  }
576 }
577 
579 {
580  int m_iPlayerID;
581  WorldTimestamp m_Time;
583 
584  //------------------------------------------------------------------------------------------------
586  {
587  m_iPlayerID = playerID;
588  m_Modes = modes;
589  ChimeraWorld world = GetGame().GetWorld();
590  m_Time = world.GetServerTimestamp(); //--- Can use absolute value, we don't need precision
591  }
592 }
ChimeraWorld
Definition: ChimeraWorld.c:12
SCR_BaseGameMode
Definition: SCR_BaseGameMode.c:137
SpawnEntity
protected IEntity SpawnEntity(ResourceName entityResourceName, notnull IEntity slotOwner)
Definition: SCR_CatalogEntitySpawnerComponent.c:1008
SCR_EditorManagerDisconnectData
void SCR_EditorManagerDisconnectData(int playerID, EEditorMode modes)
Definition: SCR_EditorManagerCore.c:585
SCR_PlayerController
Definition: SCR_PlayerController.c:31
SCR_Enum
Definition: SCR_Enum.c:1
EPlayerRole
EPlayerRole
Definition: EPlayerRole.c:7
EEditorModeAccess
EEditorModeAccess
Definition: EEditorModeAccess.c:1
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
desc
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
Definition: SCR_RespawnBriefingComponent.c:17
m_Modes
EEditorMode m_Modes
Definition: SCR_EditorManagerCore.c:582
Instigator
Definition: Instigator.c:6
SCR_EditorSettingsEntity
Definition: SCR_EditorSettingsEntity.c:12
GetGameMode
SCR_BaseGameMode GetGameMode()
Definition: SCR_BaseGameModeComponent.c:15
Attribute
typedef Attribute
Post-process effect of scripted camera.
SCR_ReconnectData
Data class for reconnecting players.
Definition: SCR_ReconnectComponent.c:2
SCR_EditorManagerCore
Core component to manage SCR_EditorManagerEntity.
Definition: SCR_EditorManagerCore.c:5
m_Time
WorldTimestamp m_Time
Definition: SCR_EditorManagerCore.c:581
m_EditorManager
protected SCR_EditorManagerEntity m_EditorManager
Definition: SCR_VotingEditor.c:5
EEditorModeFlag
EEditorModeFlag
Definition: EEditorModeFlag.c:1
EEditorMode
EEditorMode
Editor mode that defines overall functionality.
Definition: EEditorMode.c:5
SCR_Global
Definition: Functions.c:6
EEditorCanOpen
EEditorCanOpen
Layers allowing editor to be opened. All of them have to be activated (certain exceptions may apply w...
Definition: EEditorCanOpen.c:5
m_iPlayerID
SCR_EditorManagerCore m_iPlayerID
SCR_EditorModePrefab
Definition: SCR_EditorManagerEntity.c:1888
SCR_EditorServerEntity
Definition: SCR_EditorServerEntity.c:5
SCR_DebugMenuID
SCR_DebugMenuID
This enum contains all IDs for DiagMenu entries added in script.
Definition: DebugMenuID.c:3
SCR_ReconnectComponent
Definition: SCR_ReconnectComponent.c:41
BaseContainerProps
SCR_AIGoalReaction_Follow BaseContainerProps
Handles insects that are supposed to be spawned around selected prefabs defined in prefab names array...
Definition: SCR_AIGoalReaction.c:468
SCR_EditorModeUIInfo
Definition: SCR_EditorModeUIInfo.c:2
SCR_EditorManagerEntity
Definition: SCR_EditorManagerEntity.c:26