Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_PingEditorComponent.c
Go to the documentation of this file.
1 [ComponentEditorProps(category: "GameScripted/Editor", description: "", icon: "WBData/ComponentEditorProps/componentEditor.png")]
3 {
4  [Attribute(category: "Effects: Send Ping")]
5  private ref array<ref SCR_BaseEditorEffect> m_EffectsSendPingFromPlayer;
6 
7  [Attribute(category: "Effects: Send Ping")]
8  private ref array<ref SCR_BaseEditorEffect> m_EffectsSendPingFromEditor;
9 
10  [Attribute(category: "Effects: Send Ping")]
11  private ref array<ref SCR_BaseEditorEffect> m_EffectsSendPingUnlimitedOnlyFromPlayer;
12 
13  [Attribute(category: "Effects: Send Ping")]
14  private ref array<ref SCR_BaseEditorEffect> m_EffectsSendPingUnlimitedOnlyFromEditor;
15 
16  [Attribute(category: "Effects: Receive Ping")]
17  private ref array<ref SCR_BaseEditorEffect> m_EffectsReceivePingFromPlayer;
18 
19  [Attribute(category: "Effects: Receive Ping")]
20  private ref array<ref SCR_BaseEditorEffect> m_EffectsReceivePingFromEditor;
21 
22  [Attribute(category: "Effects: Receive Ping")]
23  private ref array<ref SCR_BaseEditorEffect> m_EffectsReceivePingUnlimitedOnlyFromPlayer;
24 
25  [Attribute(category: "Effects: Receive Ping")]
26  private ref array<ref SCR_BaseEditorEffect> m_EffectsReceivePingUnlimitedOnlyFromEditor;
27 
28  void ActivateEffects(SCR_PingEditorComponent component, bool isReceiver, int reporterID, bool reporterInEditor, bool unlimitedOnly, vector position, set<SCR_EditableEntityComponent> targets)
29  {
30  if (isReceiver)
31  {
32  if (unlimitedOnly)
33  {
34  if (reporterInEditor)
35  SCR_BaseEditorEffect.Activate(m_EffectsReceivePingUnlimitedOnlyFromEditor, component, position, targets);
36  else
37  SCR_BaseEditorEffect.Activate(m_EffectsReceivePingUnlimitedOnlyFromPlayer, component, position, targets);
38  }
39  else
40  {
41  if (reporterInEditor)
42  SCR_BaseEditorEffect.Activate(m_EffectsReceivePingFromEditor, component, position, targets);
43  else
44  SCR_BaseEditorEffect.Activate(m_EffectsReceivePingFromPlayer, component, position, targets);
45  }
46  }
47  else
48  {
49  if (unlimitedOnly)
50  {
51  if (reporterInEditor)
52  SCR_BaseEditorEffect.Activate(m_EffectsSendPingUnlimitedOnlyFromEditor, component, position, targets);
53  else
54  SCR_BaseEditorEffect.Activate(m_EffectsSendPingUnlimitedOnlyFromPlayer, component, position, targets);
55  }
56  else
57  {
58  if (reporterInEditor)
59  SCR_BaseEditorEffect.Activate(m_EffectsSendPingFromEditor, component, position, targets);
60  else
61  SCR_BaseEditorEffect.Activate(m_EffectsSendPingFromPlayer, component, position, targets);
62  }
63  }
64  }
65 };
66 
71 {
72  [Attribute(defvalue: "10", desc: "How long (in seconds) a ping entity exists before being deleted. Fading is done speratly from this value in SCR_PingEffectsEditorUIComponent.")]
73  protected float m_fPingEntityLifetime;
74 
75  [Attribute(defvalue: "0.75", desc: "How long (in seconds) is the ping on cooldown to prevent spamming.", params: "0, inf, 0.05")]
76  protected float m_fCooldownTime;
77 
78  //~ Time left for cooldown
79  protected float m_fCurrentCooldownTime;
80 
81  //~ In mili seconds what is the update freq for the cooldown update. If changed updated the step param for m_fCooldownTime (m_fCooldownUpdateFreq / 1000)
82  protected float m_fCooldownUpdateFreq = 50;
83 
84  protected bool m_bIsOnCooldown;
85 
86  protected SCR_EditorManagerCore m_Core;
87  protected ref map<int, SCR_EditableEntityComponent> m_PlayerPings = new map<int, SCR_EditableEntityComponent>;
88  protected SCR_EditableEntityComponent m_LastPingEntity;
89 
90  protected ref ScriptInvoker Event_OnPingSend = new ScriptInvoker;
91  protected ref ScriptInvoker Event_OnPingReceive = new ScriptInvoker;
92  protected ref ScriptInvoker Event_OnPingEntityRegister = new ScriptInvoker;
93  protected ref ScriptInvoker Event_OnPingEntityUnregister = new ScriptInvoker;
94 
102  void SendPing(bool unlimitedOnly = false, vector position = vector.Zero, SCR_EditableEntityComponent target = null)
103  {
104  //~ Check if on cooldown. If true send notification informing player
105  if (IsPingOnCooldown())
106  {
107  SCR_NotificationsComponent.SendLocal(ENotification.ACTION_ON_COOLDOWN, m_fCurrentCooldownTime * 100);
108  return;
109  }
110 
111  SCR_EditorManagerEntity manager = GetManager();
112  if (!manager)
113  return;
114 
115  //~ If Unlimited only ping
116  if (unlimitedOnly)
117  {
118  //~ Limited editor so cannot send GM only ping
119  if (manager.IsLimited())
120  {
121  SCR_NotificationsComponent.SendLocal(ENotification.EDITOR_GM_ONLY_PING_LIMITED_RIGHTS);
122  return;
123  }
124  //~ Never send editor only ping if editor is not opened
125  else if (!manager.IsOpened())
126  {
127  return;
128  }
129  }
130 
131  //~ If no GM do not send out ping
133  if (playerDelegateManager && !playerDelegateManager.HasPlayerWithUnlimitedEditor())
134  {
135  SCR_NotificationsComponent.SendLocal(ENotification.EDITOR_PING_NO_GM_TO_PING);
136  return;
137  }
138 
139  int reporterID = manager.GetPlayerID();
140  bool reporterInEditor = manager.IsOpened() && !manager.IsLimited();
141 
142  if (target) target.GetPos(position);
143  CallEvents(manager, false, reporterID, reporterInEditor, unlimitedOnly, position, target);
144 
145  //--- Send the ping to server
146  Rpc(SendPingServer, unlimitedOnly, position, Replication.FindId(target));
147 
148  //~ Ping cooldown to prevent spamming
149  ActivateCooldown();
150  }
151 
152  //~ Start Cooldown
153  protected void ActivateCooldown()
154  {
155  m_fCurrentCooldownTime = m_fCooldownTime;
156  m_bIsOnCooldown = true;
157 
158  //~ Add to callqueue to remove cooldown
159  GetGame().GetCallqueue().CallLater(UpdateCooldown, m_fCooldownUpdateFreq, true);
160  }
161 
162  //~ Update current cooldown
163  protected void UpdateCooldown()
164  {
165  m_fCurrentCooldownTime -= m_fCooldownUpdateFreq / 1000;
166 
167  if (m_fCurrentCooldownTime <= 0)
168  OnCooldownDone();
169  }
170 
171  //~ Executed after delay if Cooldown is done
172  protected void OnCooldownDone()
173  {
174  m_bIsOnCooldown = false;
175  GetGame().GetCallqueue().Remove(UpdateCooldown);
176  }
177 
178  [RplRpc(RplChannel.Reliable, RplRcver.Server)]
179  protected void SendPingServer(bool unlimitedOnly, vector position, RplId targetID)
180  {
181  if (!m_Core) return;
182 
183  SCR_EditorManagerEntity manager = GetManager();
184  if (!manager) return;
185 
186  int reporterID = manager.GetPlayerID();
187  bool reporterInEditor = manager.IsOpened() && !manager.IsLimited();
188 
189  //--- Exit when player's entity doesn't exist
190  SCR_EditableEntityComponent reporterEntity = SCR_EditableEntityComponent.GetEditableEntity(GetGame().GetPlayerManager().GetPlayerControlledEntity(reporterID));
191  //if (!reporterEntity) return;
192 
193  //--- Send the ping to editor managers of all players
194  m_Core.Event_OnEditorManagerPing.Invoke(reporterID, reporterInEditor, reporterEntity, unlimitedOnly, position, targetID);
195  }
196  protected void ReceivePing(int reporterID, bool reporterInEditor, SCR_EditableEntityComponent reporterEntity, bool unlimitedOnly, vector position, RplId targetID)
197  {
198  //--- Don't ping yourself
199  SCR_EditorManagerEntity manager = GetManager();
200  if (!manager || manager.GetPlayerID() == reporterID)
201  return;
202 
203  if (unlimitedOnly && manager.IsLimited())
204  return;
205 
206  //--- Extra conditions when the reporter is not in unlimited editor (i.e., is not GM who can ping everyone)
207  if (!reporterInEditor)
208  {
209  //--- Ignore when receiver is not in unlimited editor (i.e., no player to player ping allowed, or pinging limited photo mode)
210  if (!manager.IsOpened() || manager.IsLimited())
211  return;
212 
213  //--- Ignore when reporter's entity is not accessible from receiver's editor
214  SCR_AccessKeysEditorComponent accessKeysManager = SCR_AccessKeysEditorComponent.Cast(manager.FindComponent(SCR_AccessKeysEditorComponent));
215  if (accessKeysManager && reporterEntity && !reporterEntity.HasAccessInHierarchy(accessKeysManager.GetAccessKey()))
216  return;
217  }
218 
219  //--- Send the ping to the editor user
220  Rpc(ReceivePingOwner, reporterID, reporterInEditor, unlimitedOnly, position, targetID);
221  }
222  [RplRpc(RplChannel.Reliable, RplRcver.Owner)]
223  protected void ReceivePingOwner(int reporterID, bool reporterInEditor, bool unlimitedOnly, vector position, RplId targetID)
224  {
225  SCR_EditorManagerEntity manager = GetManager();
226  if (!manager) return;
227 
228  if (unlimitedOnly && manager.IsLimited())
229  return;
230 
231  SCR_EditableEntityComponent target = SCR_EditableEntityComponent.Cast(Replication.FindItem(targetID));
232  CallEvents(manager, false, reporterID, reporterInEditor, unlimitedOnly, position, target);
233  }
234 
240  int GetPlayerPings(out notnull map<int, SCR_EditableEntityComponent> outPlayerPings)
241  {
242  return outPlayerPings.Copy(m_PlayerPings);
243  }
244 
250  ScriptInvoker GetOnPingSend()
251  {
252  return Event_OnPingSend;
253  }
259  ScriptInvoker GetOnPingReceive()
260  {
261  return Event_OnPingReceive;
262  }
268  ScriptInvoker GetOnPingEntityRegister()
269  {
270  return Event_OnPingEntityRegister;
271  }
277  ScriptInvoker GetOnPingEntityUnregister()
278  {
279  return Event_OnPingEntityUnregister;
280  }
281 
286  bool IsPingOnCooldown()
287  {
288  return m_bIsOnCooldown;
289  }
290 
291  protected void CallEvents(SCR_EditorManagerEntity manager, bool isReceiver, int reporterID, bool reporterInEditor, bool unlimitedOnly, vector position, SCR_EditableEntityComponent target)
292  {
293  set<SCR_EditableEntityComponent> targets = new set<SCR_EditableEntityComponent>;
294  if (target) targets.Insert(target);
295 
296  m_LastPingEntity = target;
297 
298  //--- Invoke handlers
299  if (isReceiver)
300  Event_OnPingReceive.Invoke(reporterID, reporterInEditor, unlimitedOnly, position, target);
301  else
302  Event_OnPingSend.Invoke(reporterID, reporterInEditor, unlimitedOnly, position, target);
303 
304  //--- Call effects defined in prefab
305  SCR_PingEditorComponentClass prefabData = SCR_PingEditorComponentClass.Cast(GetEditorComponentData());
306  if (prefabData) prefabData.ActivateEffects(this, isReceiver, reporterID, reporterInEditor, unlimitedOnly, position, targets);
307 
308  if (m_LastPingEntity)
309  {
310  SCR_EditableEntityComponent prevPingEntity;
311  if (m_PlayerPings.Find(reporterID, prevPingEntity))
312  Expire(reporterID, prevPingEntity);
313 
314  m_PlayerPings.Set(reporterID, m_LastPingEntity);
315  Event_OnPingEntityRegister.Invoke(reporterID, m_LastPingEntity);
316 
317  GetGame().GetCallqueue().CallLater(Expire, m_fPingEntityLifetime * 1000, false, reporterID, m_LastPingEntity);
318  }
319 
320  SCR_NotificationData newNotificationData;
321  int targetPlayerID = 0;
322  int targetID
323 
324  //Check if has target
325  if (target)
326  {
327  targetID = Replication.FindId(target);
328  targetPlayerID = SCR_PossessingManagerComponent.GetPlayerIdFromMainEntity(target.GetOwner());
329  }
330 
331  //Send out notification if not unlimitedOnly
332  if (!unlimitedOnly)
333  {
334  //If pinger has editor rights
335  if (reporterInEditor)
336  {
337  //No target
338  if (!target || target.HasEntityFlag(EEditableEntityFlag.LOCAL))
339  SCR_NotificationsComponent.SendLocal(ENotification.EDITOR_PING_GM, position, reporterID);
340  //Player target
341  else if (targetPlayerID > 0)
342  SCR_NotificationsComponent.SendLocal(ENotification.EDITOR_PING_GM_TARGET_PLAYER, reporterID, targetPlayerID);
343  //EditableEntity target
344  else
345  SCR_NotificationsComponent.SendLocal(ENotification.EDITOR_PING_GM_TARGET_ENTITY, reporterID, targetID);
346  }
347  else {
348  //No target
349  if (!target || target.HasEntityFlag(EEditableEntityFlag.LOCAL))
350  SCR_NotificationsComponent.SendLocal(ENotification.EDITOR_PING_PLAYER, position, reporterID);
351  //Player target
352  else if (targetPlayerID > 0)
353  SCR_NotificationsComponent.SendLocal(ENotification.EDITOR_PING_PLAYER_TARGET_PLAYER, reporterID, targetPlayerID);
354  //EditableEntity target
355  else
356  SCR_NotificationsComponent.SendLocal(ENotification.EDITOR_PING_PLAYER_TARGET_ENTITY, reporterID, targetID);
357  }
358  }
359  else
360  {
361  //No target
362  if (!target || target.HasEntityFlag(EEditableEntityFlag.LOCAL))
363  SCR_NotificationsComponent.SendLocalUnlimitedEditor(ENotification.EDITOR_GM_ONLY_PING, position, reporterID);
364  //Player target
365  else if (targetPlayerID > 0)
366  SCR_NotificationsComponent.SendLocalUnlimitedEditor(ENotification.EDITOR_GM_ONLY_PING_TARGET_PLAYER, reporterID, targetPlayerID);
367  //EditableEntity target
368  else
369  SCR_NotificationsComponent.SendLocalUnlimitedEditor(ENotification.EDITOR_GM_ONLY_PING_TARGET_ENTITY, reporterID, targetID);
370  }
371  }
372 
373  protected void Expire(int reporterID, SCR_EditableEntityComponent pingEntity)
374  {
375  SCR_EditableEntityComponent currentPingEntity;
376  if (pingEntity && m_PlayerPings.Find(reporterID, currentPingEntity) && pingEntity == currentPingEntity)
377  {
378  m_PlayerPings.Remove(reporterID);
379  Event_OnPingEntityUnregister.Invoke(reporterID, pingEntity);
380 
381  if (pingEntity.GetOwner() && pingEntity.GetOwner().IsInherited(SCR_EditorPingEntity))
382  pingEntity.Delete();
383  }
384  }
385  override void EOnEffect(SCR_BaseEditorEffect effect)
386  {
387  SCR_EntityEditorEffect entityEffect = SCR_EntityEditorEffect.Cast(effect);
388  if (entityEffect) m_LastPingEntity = SCR_EditableEntityComponent.GetEditableEntity(entityEffect.GetEntity());
389  }
390 
391  //--- Server init
392  void SCR_PingEditorComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
393  {
394  if (!Replication.IsServer()) return;
395 
397  if (m_Core)
398  m_Core.Event_OnEditorManagerPing.Insert(ReceivePing);
399  }
401  {
402  if (m_bIsOnCooldown)
403  OnCooldownDone();
404 
405  if (m_Core) m_Core.Event_OnEditorManagerPing.Remove(ReceivePing);
406  }
407 };
ComponentEditorProps
SCR_FragmentEntityClass ComponentEditorProps
EEditableEntityFlag
EEditableEntityFlag
Unique flags of the entity.
Definition: EEditableEntityFlag.c:5
SCR_EditorPingEntity
Definition: SCR_EditorPingEntity.c:13
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
desc
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
Definition: SCR_RespawnBriefingComponent.c:17
RplRpc
SCR_AchievementsHandlerClass ScriptComponentClass RplRpc(RplChannel.Reliable, RplRcver.Owner)] void UnlockOnClient(AchievementId achievement)
Definition: SCR_AchievementsHandler.c:11
SCR_PlayerDelegateEditorComponent
Definition: SCR_PlayerDelegateEditorComponent.c:9
ENotification
ENotification
Definition: ENotification.c:4
SCR_BaseEditorComponent
Definition: SCR_BaseEditorComponent.c:119
Attribute
typedef Attribute
Post-process effect of scripted camera.
SCR_EditorManagerCore
Core component to manage SCR_EditorManagerEntity.
Definition: SCR_EditorManagerCore.c:5
SCR_PingEditorComponent
Definition: SCR_PingEditorComponent.c:70
SCR_BaseEditorComponentClass
Definition: SCR_BaseEditorComponent.c:2
SCR_EditableEntityComponent
Definition: SCR_EditableEntityComponent.c:13
SCR_EntityEditorEffect
Definition: SCE_EntityEditorEffect.c:7
SCR_NotificationData
Definition: SCR_NotificationData.c:6
params
Configs ServerBrowser KickDialogs params
Definition: SCR_NotificationSenderComponent.c:24
SCR_PingEditorComponentClass
Definition: SCR_PingEditorComponent.c:2
position
vector position
Definition: SCR_DestructibleTreeV2.c:30
SCR_BaseEditorEffect
Definition: SCR_BaseEditorEffect.c:7
category
params category
Definition: SCR_VehicleDamageManagerComponent.c:180
SCR_EditorManagerEntity
Definition: SCR_EditorManagerEntity.c:26