瀏覽代碼

Merge pull request #57033 from lawnjelly/gameplay_monitor_unload

Portals - fix gameplay monitor unloading
Rémi Verschelde 3 年之前
父節點
當前提交
c6480e2166

+ 89 - 0
servers/visual/portals/portal_gameplay_monitor.cpp

@@ -74,6 +74,95 @@ bool PortalGameplayMonitor::_source_rooms_changed(const int *p_source_room_ids,
 	return source_rooms_changed;
 	return source_rooms_changed;
 }
 }
 
 
+void PortalGameplayMonitor::unload(PortalRenderer &p_portal_renderer) {
+	// First : send gameplay exit signals for any objects still in gameplay
+	////////////////////////////////////////////////////////////////////
+	// lock output
+	VisualServerCallbacks *callbacks = VSG::scene->get_callbacks();
+	callbacks->lock();
+
+	// Remove any movings
+	for (int n = 0; n < _active_moving_pool_ids_prev->size(); n++) {
+		int pool_id = (*_active_moving_pool_ids_prev)[n];
+		PortalRenderer::Moving &moving = p_portal_renderer.get_pool_moving(pool_id);
+		moving.last_gameplay_tick_hit = 0;
+
+		VisualServerCallbacks::Message msg;
+		msg.object_id = VSG::scene->_instance_get_object_ID(moving.instance);
+		msg.type = _exit_callback_type;
+		callbacks->push_message(msg);
+	}
+
+	// Remove any roaming ghosts
+	for (int n = 0; n < _active_rghost_pool_ids_prev->size(); n++) {
+		int pool_id = (*_active_rghost_pool_ids_prev)[n];
+		PortalRenderer::RGhost &moving = p_portal_renderer.get_pool_rghost(pool_id);
+		moving.last_gameplay_tick_hit = 0;
+
+		VisualServerCallbacks::Message msg;
+		msg.object_id = moving.object_id;
+		msg.type = VisualServerCallbacks::CALLBACK_NOTIFICATION_EXIT_GAMEPLAY;
+		callbacks->push_message(msg);
+	}
+
+	// Rooms
+	for (int n = 0; n < _active_room_ids_prev->size(); n++) {
+		int room_id = (*_active_room_ids_prev)[n];
+		VSRoom &room = p_portal_renderer.get_room(room_id);
+		room.last_gameplay_tick_hit = 0;
+
+		VisualServerCallbacks::Message msg;
+		msg.object_id = room._godot_instance_ID;
+		msg.type = _exit_callback_type;
+		callbacks->push_message(msg);
+	}
+
+	// RoomGroups
+	for (int n = 0; n < _active_roomgroup_ids_prev->size(); n++) {
+		int roomgroup_id = (*_active_roomgroup_ids_prev)[n];
+		VSRoomGroup &roomgroup = p_portal_renderer.get_roomgroup(roomgroup_id);
+		roomgroup.last_gameplay_tick_hit = 0;
+
+		VisualServerCallbacks::Message msg;
+		msg.object_id = roomgroup._godot_instance_ID;
+		msg.type = _exit_callback_type;
+		callbacks->push_message(msg);
+	}
+
+	// Static Ghosts
+	for (int n = 0; n < _active_sghost_ids_prev->size(); n++) {
+		int id = (*_active_sghost_ids_prev)[n];
+		VSStaticGhost &ghost = p_portal_renderer.get_static_ghost(id);
+		ghost.last_gameplay_tick_hit = 0;
+
+		VisualServerCallbacks::Message msg;
+		msg.object_id = ghost.object_id;
+		msg.type = VisualServerCallbacks::CALLBACK_NOTIFICATION_EXIT_GAMEPLAY;
+		callbacks->push_message(msg);
+	}
+
+	// unlock
+	callbacks->unlock();
+
+	// Clear all remaining data
+	for (int n = 0; n < 2; n++) {
+		_active_moving_pool_ids[n].clear();
+		_active_rghost_pool_ids[n].clear();
+		_active_room_ids[n].clear();
+		_active_roomgroup_ids[n].clear();
+		_active_sghost_ids[n].clear();
+	}
+
+	_source_rooms_prev.clear();
+
+	// Lets not reset this just in case because it may be possible to have a moving outside the room system
+	// which is preserved between levels, and has a stored gameplay tick. And with uint32_t this should take
+	// a *long* time to rollover... (828 days?). And I don't think a rollover would actually cause a problem in practice.
+	// But can revisit this in the case of e.g. servers running continuously.
+	// We could alternatively go through all movings (not just active) etc and reset the last_gameplay_tick_hit to 0.
+	// _gameplay_tick = 1;
+}
+
 void PortalGameplayMonitor::set_params(bool p_use_secondary_pvs, bool p_use_signals) {
 void PortalGameplayMonitor::set_params(bool p_use_secondary_pvs, bool p_use_signals) {
 	_use_secondary_pvs = p_use_secondary_pvs;
 	_use_secondary_pvs = p_use_secondary_pvs;
 	_use_signals = p_use_signals;
 	_use_signals = p_use_signals;

+ 2 - 0
servers/visual/portals/portal_gameplay_monitor.h

@@ -43,6 +43,8 @@ class PortalGameplayMonitor {
 public:
 public:
 	PortalGameplayMonitor();
 	PortalGameplayMonitor();
 
 
+	void unload(PortalRenderer &p_portal_renderer);
+
 	// entering and exiting gameplay notifications (requires PVS)
 	// entering and exiting gameplay notifications (requires PVS)
 	void update_gameplay(PortalRenderer &p_portal_renderer, const int *p_source_room_ids, int p_num_source_rooms);
 	void update_gameplay(PortalRenderer &p_portal_renderer, const int *p_source_room_ids, int p_num_source_rooms);
 	void set_params(bool p_use_secondary_pvs, bool p_use_signals);
 	void set_params(bool p_use_secondary_pvs, bool p_use_signals);

+ 12 - 0
servers/visual/portals/portal_renderer.cpp

@@ -996,6 +996,7 @@ void PortalRenderer::sprawl_roaming(uint32_t p_mover_pool_id, MovingBase &r_movi
 void PortalRenderer::_ensure_unloaded(String p_reason) {
 void PortalRenderer::_ensure_unloaded(String p_reason) {
 	if (_loaded) {
 	if (_loaded) {
 		_loaded = false;
 		_loaded = false;
+		_gameplay_monitor.unload(*this);
 
 
 		String str;
 		String str;
 		if (p_reason != String()) {
 		if (p_reason != String()) {
@@ -1014,6 +1015,17 @@ void PortalRenderer::_ensure_unloaded(String p_reason) {
 
 
 void PortalRenderer::rooms_and_portals_clear() {
 void PortalRenderer::rooms_and_portals_clear() {
 	_loaded = false;
 	_loaded = false;
+
+	// N.B. We want to make sure all the tick counters on movings rooms etc to zero,
+	// so that on loading the next level gameplay entered signals etc will be
+	// correctly sent and everything is fresh.
+	// This is mostly done by the gameplay_monitor, but rooms_and_portals_clear()
+	// will also clear tick counters where possible
+	// (there is no TrackedList for the RoomGroup pool for example).
+	// This could be made neater by moving everything to TrackedPooledLists, but this
+	// may be overkill.
+	_gameplay_monitor.unload(*this);
+
 	_statics.clear();
 	_statics.clear();
 	_static_ghosts.clear();
 	_static_ghosts.clear();
 
 

+ 3 - 0
servers/visual/portals/portal_renderer.h

@@ -87,6 +87,9 @@ public:
 		void destroy() {
 		void destroy() {
 			_rooms.clear();
 			_rooms.clear();
 			room_id = -1;
 			room_id = -1;
+
+			last_tick_hit = 0;
+			last_gameplay_tick_hit = 0;
 		}
 		}
 
 
 		// the expanded aabb allows objects to move on most frames
 		// the expanded aabb allows objects to move on most frames

+ 1 - 0
servers/visual/portals/portal_types.h

@@ -257,6 +257,7 @@ struct VSRoom {
 		_secondary_pvs_size = 0;
 		_secondary_pvs_size = 0;
 		_priority = 0;
 		_priority = 0;
 		_contains_internal_rooms = false;
 		_contains_internal_rooms = false;
+		last_gameplay_tick_hit = 0;
 	}
 	}
 
 
 	void cleanup_after_conversion() {
 	void cleanup_after_conversion() {