Skip to content

Commit a156f96

Browse files
authored
Added networked variants of the entity listeners. (Source-Python-Dev-Team#351)
* Added networked variants of the entity listeners. * Added missing entries to listeners.__all__. * Networked entity listeners now pass an Entity instance to the callbacks rather than an index. * Fixed a prototype mixup. * Improved the logic so that we don't retrieve the entity index if there is no callback registered.
1 parent d76325c commit a156f96

File tree

7 files changed

+177
-35
lines changed

7 files changed

+177
-35
lines changed

addons/source-python/docs/source-python/source/developing/module_tutorials/listeners.rst

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,20 @@ Called when an entity has been created.
202202
pass
203203
204204
205+
OnNetworkedEntityCreated
206+
---------------
207+
208+
Called when a networked entity has been created.
209+
210+
.. code-block:: python
211+
212+
from listeners import OnNetworkedEntityCreated
213+
214+
@OnNetworkedEntityCreated
215+
def on_networked_entity_created(entity):
216+
pass
217+
218+
205219
OnEntityDeleted
206220
---------------
207221

@@ -216,6 +230,20 @@ Called when an entity gets deleted.
216230
pass
217231
218232
233+
OnNetworkedEntityDeleted
234+
---------------
235+
236+
Called when a networked entity gets deleted.
237+
238+
.. code-block:: python
239+
240+
from listeners import OnNetworkedEntityDeleted
241+
242+
@OnNetworkedEntityDeleted
243+
def on_networked_entity_deleted(entity):
244+
pass
245+
246+
219247
OnEntityOutput
220248
--------------
221249

@@ -252,6 +280,22 @@ Called before an entity has been spawned.
252280
.. note:: This listener gets only called in Black Mesa: Source.
253281

254282

283+
OnNetworkedEntityPreSpawned
284+
------------------
285+
286+
Called before a networked entity has been spawned.
287+
288+
.. code-block:: python
289+
290+
from listeners import OnNetworkedEntityPreSpawned
291+
292+
@OnNetworkedEntityPreSpawned
293+
def on_networked_entity_pre_spawned(entity):
294+
pass
295+
296+
.. note:: This listener gets only called in Black Mesa: Source.
297+
298+
255299
OnEntitySpawned
256300
---------------
257301

@@ -266,6 +310,20 @@ Called when an entity has been spawned.
266310
pass
267311
268312
313+
OnNetworkedEntitySpawned
314+
---------------
315+
316+
Called when a networked entity has been spawned.
317+
318+
.. code-block:: python
319+
320+
from listeners import OnNetworkedEntitySpawned
321+
322+
@OnNetworkedEntitySpawned
323+
def on_networked_entity_spawned(entity):
324+
pass
325+
326+
269327
OnLevelInit
270328
-----------
271329

addons/source-python/packages/source-python/entities/_base.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -785,18 +785,12 @@ def set_parent(self, parent, attachment=INVALID_ATTACHMENT_INDEX):
785785
# =============================================================================
786786
# NOTE: This callback is called by sp_main.cpp after all registered entity
787787
# deletion listeners have been called.
788-
def _on_entity_deleted(base_entity):
789-
"""Called when an entity is removed.
788+
def _on_networked_entity_deleted(index):
789+
"""Called when a networked entity is removed.
790790
791-
:param BaseEntity base_entity:
792-
The removed entity.
791+
:param int index:
792+
The removed entity index.
793793
"""
794-
try:
795-
# Get the index of the entity...
796-
index = base_entity.index
797-
except ValueError:
798-
return
799-
800794
# Loop through all delays...
801795
for delay in _entity_delays.pop(index, ()):
802796

addons/source-python/packages/source-python/entities/dictionary.py

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from entities.entity import Entity
1717
from entities.helpers import index_from_inthandle
1818
# Listeners
19-
from listeners import on_entity_deleted_listener_manager
19+
from listeners import on_networked_entity_deleted_listener_manager
2020

2121

2222
# ============================================================================
@@ -42,8 +42,8 @@ def __init__(self, factory=Entity, *args, **kwargs):
4242
self._kwargs = kwargs
4343

4444
# Register our OnEntityDeleted listener...
45-
on_entity_deleted_listener_manager.register_listener(
46-
self._on_entity_deleted)
45+
on_networked_entity_deleted_listener_manager.register_listener(
46+
self._on_networked_entity_deleted)
4747

4848
# Initialize the dictionary...
4949
super().__init__()
@@ -79,22 +79,27 @@ def from_inthandle(self, inthandle):
7979
def on_automatically_removed(self, index):
8080
"""Called when an index is automatically removed."""
8181

82-
def _on_entity_deleted(self, base_entity):
83-
"""OnEntityDeleted listener callback."""
84-
try:
85-
# Get the index of the entity...
86-
index = base_entity.index
87-
except ValueError:
82+
def _on_networked_entity_deleted(self, entity):
83+
"""Internal networked entity deletion callback.
84+
85+
:param Entity entity:
86+
The networked entity being removed.
87+
"""
88+
# Get the index of the entity
89+
index = entity.index
90+
91+
# No need to go further if there is no object associated to this index
92+
if index not in self:
8893
return
8994

90-
if index in self:
95+
try:
9196
# Call the deletion callback for the index...
9297
self.on_automatically_removed(index)
93-
98+
finally:
9499
# Remove the index from the dictionary...
95100
super().__delitem__(index)
96101

97102
def _unload_instance(self):
98-
"""Unregister our OnEntityDeleted listener."""
99-
on_entity_deleted_listener_manager.unregister_listener(
100-
self._on_entity_deleted)
103+
"""Unregister our networked entity deletion listener."""
104+
on_networked_entity_deleted_listener_manager.unregister_listener(
105+
self._on_networked_entity_deleted)

addons/source-python/packages/source-python/entities/hooks.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
# Filters
1515
from filters.entities import EntityIter
1616
# Listeners
17-
from listeners import OnEntityCreated
17+
from listeners import OnNetworkedEntityCreated
1818
# Entities
1919
from entities.entity import Entity
2020
# Players
@@ -219,9 +219,7 @@ def initialize(self, index):
219219
# =============================================================================
220220
# >> LISTENERS
221221
# =============================================================================
222-
@OnEntityCreated
223-
def on_entity_created(base_entity):
224-
"""Called when a new entity has been created."""
225-
if not base_entity.is_networked():
226-
return
227-
_waiting_entity_hooks.initialize(base_entity.index)
222+
@OnNetworkedEntityCreated
223+
def on_networked_entity_created(entity):
224+
"""Called when a new networked entity has been created."""
225+
_waiting_entity_hooks.initialize(entity.index)

addons/source-python/packages/source-python/listeners/__init__.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,13 @@
5858
from _listeners import on_edict_allocated_listener_manager
5959
from _listeners import on_edict_freed_listener_manager
6060
from _listeners import on_entity_pre_spawned_listener_manager
61+
from _listeners import on_networked_entity_pre_spawned_listener_manager
6162
from _listeners import on_entity_created_listener_manager
63+
from _listeners import on_networked_entity_created_listener_manager
6264
from _listeners import on_entity_spawned_listener_manager
65+
from _listeners import on_networked_entity_spawned_listener_manager
6366
from _listeners import on_entity_deleted_listener_manager
67+
from _listeners import on_networked_entity_deleted_listener_manager
6468
from _listeners import on_data_loaded_listener_manager
6569
from _listeners import on_combiner_pre_cache_listener_manager
6670
from _listeners import on_data_unloaded_listener_manager
@@ -91,11 +95,15 @@
9195
'OnEdictAllocated',
9296
'OnEdictFreed',
9397
'OnEntityCreated',
98+
'OnNetworkedEntityCreated',
9499
'OnEntityDeleted',
100+
'OnNetworkedEntityDeleted',
95101
'OnEntityOutput',
96102
'OnEntityOutputListenerManager',
97103
'OnEntityPreSpawned',
104+
'OnNetworkedEntityPreSpawned',
98105
'OnEntitySpawned',
106+
'OnNetworkedEntitySpawned',
99107
'OnLevelInit',
100108
'OnLevelShutdown',
101109
'OnLevelEnd',
@@ -125,10 +133,14 @@
125133
'on_edict_allocated_listener_manager',
126134
'on_edict_freed_listener_manager',
127135
'on_entity_created_listener_manager',
136+
'on_networked_entity_created_listener_manager',
128137
'on_entity_deleted_listener_manager',
138+
'on_networked_entity_deleted_listener_manager',
129139
'on_entity_output_listener_manager',
130140
'on_entity_pre_spawned_listener_manager',
141+
'on_networked_entity_pre_spawned_listener_manager',
131142
'on_entity_spawned_listener_manager',
143+
'on_networked_entity_spawned_listener_manager',
132144
'on_level_end_listener_manager',
133145
'on_level_init_listener_manager',
134146
'on_level_shutdown_listener_manager',
@@ -355,24 +367,48 @@ class OnEntityPreSpawned(ListenerManagerDecorator):
355367
manager = on_entity_pre_spawned_listener_manager
356368

357369

370+
class OnNetworkedEntityPreSpawned(ListenerManagerDecorator):
371+
"""Register/unregister a OnNetworkedEntityPreSpawned listener."""
372+
373+
manager = on_networked_entity_pre_spawned_listener_manager
374+
375+
358376
class OnEntityCreated(ListenerManagerDecorator):
359377
"""Register/unregister a OnEntityCreated listener."""
360378

361379
manager = on_entity_created_listener_manager
362380

363381

382+
class OnNetworkedEntityCreated(ListenerManagerDecorator):
383+
"""Register/unregister a OnNetworkedEntityCreated listener."""
384+
385+
manager = on_networked_entity_created_listener_manager
386+
387+
364388
class OnEntitySpawned(ListenerManagerDecorator):
365389
"""Register/unregister a OnEntitySpawned listener."""
366390

367391
manager = on_entity_spawned_listener_manager
368392

369393

394+
class OnNetworkedEntitySpawned(ListenerManagerDecorator):
395+
"""Register/unregister a OnNetworkedEntitySpawned listener."""
396+
397+
manager = on_networked_entity_spawned_listener_manager
398+
399+
370400
class OnEntityDeleted(ListenerManagerDecorator):
371401
"""Register/unregister a OnEntityDeleted listener."""
372402

373403
manager = on_entity_deleted_listener_manager
374404

375405

406+
class OnNetworkedEntityDeleted(ListenerManagerDecorator):
407+
"""Register/unregister a OnNetworkedEntityDeleted listener."""
408+
409+
manager = on_networked_entity_deleted_listener_manager
410+
411+
376412
class OnDataLoaded(ListenerManagerDecorator):
377413
"""Register/unregister a OnDataLoaded listener."""
378414

src/core/modules/listeners/listeners_wrap.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,13 @@ DEFINE_MANAGER_ACCESSOR(OnQueryCvarValueFinished)
5151
DEFINE_MANAGER_ACCESSOR(OnServerActivate)
5252
DEFINE_MANAGER_ACCESSOR(OnTick)
5353
DEFINE_MANAGER_ACCESSOR(OnEntityPreSpawned)
54+
DEFINE_MANAGER_ACCESSOR(OnNetworkedEntityPreSpawned)
5455
DEFINE_MANAGER_ACCESSOR(OnEntityCreated)
56+
DEFINE_MANAGER_ACCESSOR(OnNetworkedEntityCreated)
5557
DEFINE_MANAGER_ACCESSOR(OnEntitySpawned)
58+
DEFINE_MANAGER_ACCESSOR(OnNetworkedEntitySpawned)
5659
DEFINE_MANAGER_ACCESSOR(OnEntityDeleted)
60+
DEFINE_MANAGER_ACCESSOR(OnNetworkedEntityDeleted)
5761
DEFINE_MANAGER_ACCESSOR(OnDataLoaded)
5862
DEFINE_MANAGER_ACCESSOR(OnCombinerPreCache)
5963
DEFINE_MANAGER_ACCESSOR(OnDataUnloaded)
@@ -153,9 +157,13 @@ void export_listener_managers(scope _listeners)
153157
_listeners.attr("on_tick_listener_manager") = object(ptr(GetOnTickListenerManager()));
154158

155159
_listeners.attr("on_entity_pre_spawned_listener_manager") = object(ptr(GetOnEntityPreSpawnedListenerManager()));
160+
_listeners.attr("on_networked_entity_pre_spawned_listener_manager") = object(ptr(GetOnNetworkedEntityPreSpawnedListenerManager()));
156161
_listeners.attr("on_entity_created_listener_manager") = object(ptr(GetOnEntityCreatedListenerManager()));
162+
_listeners.attr("on_networked_entity_created_listener_manager") = object(ptr(GetOnNetworkedEntityCreatedListenerManager()));
157163
_listeners.attr("on_entity_spawned_listener_manager") = object(ptr(GetOnEntitySpawnedListenerManager()));
164+
_listeners.attr("on_networked_entity_spawned_listener_manager") = object(ptr(GetOnNetworkedEntitySpawnedListenerManager()));
158165
_listeners.attr("on_entity_deleted_listener_manager") = object(ptr(GetOnEntityDeletedListenerManager()));
166+
_listeners.attr("on_networked_entity_deleted_listener_manager") = object(ptr(GetOnNetworkedEntityDeletedListenerManager()));
159167

160168
_listeners.attr("on_data_loaded_listener_manager") = object(ptr(GetOnDataLoadedListenerManager()));
161169
_listeners.attr("on_combiner_pre_cache_listener_manager") = object(ptr(GetOnCombinerPreCacheListenerManager()));

src/core/sp_main.cpp

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,17 @@ void CSourcePython::OnEdictFreed( const edict_t *edict )
604604
void CSourcePython::OnEntityPreSpawned( CBaseEntity *pEntity )
605605
{
606606
CALL_LISTENERS(OnEntityPreSpawned, ptr((CBaseEntityWrapper*) pEntity));
607+
608+
GET_LISTENER_MANAGER(OnNetworkedEntityPreSpawned, on_networked_entity_pre_spawned_manager);
609+
if (!on_networked_entity_pre_spawned_manager->GetCount())
610+
return;
611+
612+
unsigned int uiIndex;
613+
if (!IndexFromBaseEntity(pEntity, uiIndex))
614+
return;
615+
616+
static object Entity = import("entities").attr("entity").attr("Entity");
617+
CALL_LISTENERS_WITH_MNGR(on_networked_entity_pre_spawned_manager, Entity(uiIndex));
607618
}
608619
#endif
609620

@@ -619,21 +630,53 @@ void CSourcePython::OnEntityCreated( CBaseEntity *pEntity )
619630
InitHooks(pEntity);
620631

621632
CALL_LISTENERS(OnEntityCreated, ptr((CBaseEntityWrapper*) pEntity));
633+
634+
GET_LISTENER_MANAGER(OnNetworkedEntityCreated, on_networked_entity_created_manager);
635+
if (!on_networked_entity_created_manager->GetCount())
636+
return;
637+
638+
unsigned int uiIndex;
639+
if (!IndexFromBaseEntity(pEntity, uiIndex))
640+
return;
641+
642+
static object Entity = import("entities").attr("entity").attr("Entity");
643+
CALL_LISTENERS_WITH_MNGR(on_networked_entity_created_manager, Entity(uiIndex));
622644
}
623645

624646
void CSourcePython::OnEntitySpawned( CBaseEntity *pEntity )
625647
{
626648
CALL_LISTENERS(OnEntitySpawned, ptr((CBaseEntityWrapper*) pEntity));
649+
650+
GET_LISTENER_MANAGER(OnNetworkedEntitySpawned, on_networked_entity_spawned_manager);
651+
if (!on_networked_entity_spawned_manager->GetCount())
652+
return;
653+
654+
unsigned int uiIndex;
655+
if (!IndexFromBaseEntity(pEntity, uiIndex))
656+
return;
657+
658+
static object Entity = import("entities").attr("entity").attr("Entity");
659+
CALL_LISTENERS_WITH_MNGR(on_networked_entity_spawned_manager, Entity(uiIndex));
627660
}
628661

629662
void CSourcePython::OnEntityDeleted( CBaseEntity *pEntity )
630663
{
631-
object oEntity(ptr((CBaseEntityWrapper*) pEntity));
632-
CALL_LISTENERS(OnEntityDeleted, oEntity);
664+
CALL_LISTENERS(OnEntityDeleted, ptr((CBaseEntityWrapper*) pEntity));
665+
666+
unsigned int uiIndex;
667+
if (!IndexFromBaseEntity(pEntity, uiIndex))
668+
return;
669+
670+
GET_LISTENER_MANAGER(OnNetworkedEntityDeleted, on_networked_entity_deleted_manager);
671+
if (on_networked_entity_deleted_manager->GetCount())
672+
{
673+
static object Entity = import("entities").attr("entity").attr("Entity");
674+
CALL_LISTENERS_WITH_MNGR(on_networked_entity_deleted_manager, Entity(uiIndex));
675+
}
633676

634677
// Invalidate the internal entity cache once all callbacks have been called.
635-
static object _on_entity_deleted = import("entities").attr("_base").attr("_on_entity_deleted");
636-
_on_entity_deleted(oEntity);
678+
static object _on_networked_entity_deleted = import("entities").attr("_base").attr("_on_networked_entity_deleted");
679+
_on_networked_entity_deleted(uiIndex);
637680
}
638681

639682
void CSourcePython::OnDataLoaded( MDLCacheDataType_t type, MDLHandle_t handle )

0 commit comments

Comments
 (0)