fixed most of the sheisse
This commit is contained in:
@@ -35,9 +35,9 @@ const MAX_BUFFER_SIZE: int = 2 * 1024 * 1024 # 2MB buffer threshold
|
||||
var last_buffer_check_time: float = 0.0
|
||||
const BUFFER_CHECK_INTERVAL: float = 0.1 # Check buffer every 100ms
|
||||
var client_buffer_states: Dictionary = {} # peer_id -> {buffered: int, last_check: float, skip_until: float}
|
||||
const CLIENT_BUFFER_CHECK_INTERVAL: float = 0.2 # Check client buffers every 200ms
|
||||
const CLIENT_BUFFER_SKIP_THRESHOLD: int = 1024 * 512 # Skip sending if buffer > 512KB
|
||||
const CLIENT_BUFFER_SKIP_DURATION: float = 2.0 # Skip sending for 2 seconds if buffer is full
|
||||
const CLIENT_BUFFER_CHECK_INTERVAL: float = 0.1 # Check client buffers every 100ms (more frequent)
|
||||
const CLIENT_BUFFER_SKIP_THRESHOLD: int = 1024 * 256 # Skip sending if buffer > 256KB (lower threshold to catch earlier)
|
||||
const CLIENT_BUFFER_SKIP_DURATION: float = 3.0 # Skip sending for 3 seconds if buffer is full (longer duration)
|
||||
var fog_node: Node2D = null
|
||||
var cached_corridor_mask: PackedInt32Array = PackedInt32Array()
|
||||
var cached_corridor_rooms: Array = []
|
||||
@@ -193,12 +193,18 @@ func _send_gameworld_ready():
|
||||
if retry_count < 50: # Try up to 50 times (10 seconds total)
|
||||
set_meta("gameworld_ready_retry_count", retry_count + 1)
|
||||
LogManager.log("GameWorld: Host peer (1) not in peers and Matchbox not connected yet, retrying (" + str(retry_count + 1) + "/50)...", LogManager.CATEGORY_NETWORK)
|
||||
get_tree().create_timer(0.2).timeout.connect(func(): _send_gameworld_ready())
|
||||
get_tree().create_timer(0.2).timeout.connect(func():
|
||||
if is_instance_valid(self) and is_inside_tree():
|
||||
_send_gameworld_ready()
|
||||
)
|
||||
return
|
||||
else:
|
||||
# After max retries, log warning and continue retrying (but less frequently)
|
||||
LogManager.log("GameWorld: Max retries reached for gameworld_ready, continuing with slower retries (every 1 second)...", LogManager.CATEGORY_NETWORK)
|
||||
get_tree().create_timer(1.0).timeout.connect(func(): _send_gameworld_ready())
|
||||
get_tree().create_timer(1.0).timeout.connect(func():
|
||||
if is_instance_valid(self) and is_inside_tree():
|
||||
_send_gameworld_ready()
|
||||
)
|
||||
return
|
||||
|
||||
# Peer is in list OR Matchbox connection is ready - try to send RPC
|
||||
@@ -328,6 +334,7 @@ func _schedule_gameworld_ready_check(peer_id: int, local_count: int, attempts: i
|
||||
return
|
||||
|
||||
get_tree().create_timer(0.2).timeout.connect(func():
|
||||
if is_instance_valid(self) and is_inside_tree():
|
||||
_schedule_gameworld_ready_check(peer_id, local_count, attempts + 1)
|
||||
)
|
||||
|
||||
@@ -630,6 +637,10 @@ func _rpc_node_to_ready_peers(node: Node, method: String, args: Array = []):
|
||||
client_gameworld_ready.erase(peer_id)
|
||||
continue
|
||||
|
||||
# Check if client's buffer is full - skip sending if so (CRITICAL to prevent buffer overflow errors)
|
||||
if _should_skip_client_due_to_buffer(peer_id):
|
||||
continue # Skip sending to this client - their buffer is full
|
||||
|
||||
# All checks passed, send RPC
|
||||
# Note: Even with all checks, there's still a tiny race condition window,
|
||||
# but this minimizes it significantly. If channel closes between check and send,
|
||||
@@ -852,7 +863,10 @@ func _notify_client_ready(peer_id: int):
|
||||
# Wait a bit longer to ensure the client has fully loaded the game scene and spawned all players
|
||||
if not dungeon_data.is_empty():
|
||||
# Delay positioning to ensure client scene is fully loaded
|
||||
get_tree().create_timer(0.5).timeout.connect(func(): _position_new_joiner_and_sync_positions(peer_id))
|
||||
get_tree().create_timer(0.5).timeout.connect(func():
|
||||
if is_instance_valid(self) and is_inside_tree():
|
||||
_position_new_joiner_and_sync_positions(peer_id)
|
||||
)
|
||||
|
||||
# Notify all players that a client is ready (so server players can check if all are ready)
|
||||
_rpc_to_ready_peers("_client_ready_status_changed", [clients_ready.duplicate()])
|
||||
@@ -1479,7 +1493,7 @@ func _check_tab_visibility():
|
||||
if OS.get_name() == "Web":
|
||||
# Use DisplayServer to check if window is focused/visible
|
||||
# This is a simple check - on web, when tab is inactive, window loses focus
|
||||
var is_visible = DisplayServer.window_get_mode() != DisplayServer.WINDOW_MODE_MINIMIZED
|
||||
var window_visible = DisplayServer.window_get_mode() != DisplayServer.WINDOW_MODE_MINIMIZED
|
||||
# Also check if we can poll (if process is running, tab is likely active)
|
||||
# On web, when tab is inactive, _process may still run but less frequently
|
||||
# We'll track time between _process calls as a proxy for tab activity
|
||||
@@ -1495,7 +1509,7 @@ func _check_tab_visibility():
|
||||
if time_since_last_process > 1000:
|
||||
return false
|
||||
|
||||
return is_visible
|
||||
return window_visible
|
||||
return true # Always visible on non-web platforms
|
||||
|
||||
func _process(_delta):
|
||||
@@ -1824,6 +1838,7 @@ func _update_fog_of_war(delta: float) -> void:
|
||||
var room_id = str(room.x) + "," + str(room.y) + "," + str(room.w) + "," + str(room.h)
|
||||
cached_corridor_allowed_room_ids[room_id] = true
|
||||
|
||||
# Use the rebuilt data
|
||||
corridor_mask = cached_corridor_mask
|
||||
corridor_rooms = cached_corridor_rooms
|
||||
allowed_room_ids = cached_corridor_allowed_room_ids
|
||||
@@ -3766,6 +3781,12 @@ func _reassemble_dungeon_blob():
|
||||
_update_camera()
|
||||
print("GameWorld: Client - Camera updated")
|
||||
|
||||
# Update fog of war to reveal area around player (CRITICAL for joiner to see the map)
|
||||
await get_tree().process_frame
|
||||
print("GameWorld: Client - Updating fog of war after player positioning...")
|
||||
_update_fog_of_war(0.0) # Pass 0.0 for delta since we're in async context
|
||||
print("GameWorld: Client - Fog of war updated")
|
||||
|
||||
# Load HUD
|
||||
print("=== GameWorld: Client - About to load HUD (call_deferred) ===")
|
||||
call_deferred("_load_hud")
|
||||
@@ -4323,14 +4344,17 @@ func _spawn_interactable_objects():
|
||||
# Check broken_objects after object is fully spawned
|
||||
if broken_objects.has(i):
|
||||
print("GameWorld: Object at index ", i, " (name: ", obj.name, ") is marked as broken, breaking it now")
|
||||
print("GameWorld: Object state - is_broken: ", obj.is_broken if "is_broken" in obj else "N/A", ", has _sync_break: ", obj.has_method("_sync_break"))
|
||||
# Use timer to break after object is fully ready (wait a bit to ensure sprite is set up)
|
||||
# Use call_deferred as well, but with a timer backup to ensure it happens
|
||||
print("GameWorld: Object state - is_broken: ", obj.is_broken if "is_broken" in obj else "N/A", ", has _sync_break: ", obj.has_method("_sync_break"), ", is_destroyable: ", obj.is_destroyable if "is_destroyable" in obj else "N/A")
|
||||
# Use both call_deferred and timer to ensure object is fully initialized
|
||||
var obj_ref = obj # Capture reference
|
||||
var obj_index = i # Capture index for logging
|
||||
# Use timer to ensure object is fully initialized (wait 2 frames worth of time)
|
||||
get_tree().create_timer(0.05).timeout.connect(func():
|
||||
if is_instance_valid(obj_ref):
|
||||
# First try with call_deferred (runs at end of frame)
|
||||
call_deferred("_break_spawned_object", obj_ref, obj_index)
|
||||
# Also use timer as backup (wait longer to ensure sprite and all components are ready)
|
||||
get_tree().create_timer(0.1).timeout.connect(func():
|
||||
if is_instance_valid(obj_ref) and not obj_ref.is_queued_for_deletion():
|
||||
if "is_broken" in obj_ref and not obj_ref.is_broken:
|
||||
print("GameWorld: Timer backup - breaking object at index ", obj_index, " (name: ", obj_ref.name, ")")
|
||||
_break_spawned_object(obj_ref, obj_index)
|
||||
)
|
||||
|
||||
@@ -4347,6 +4371,10 @@ func _break_spawned_object(obj: Node, obj_index: int):
|
||||
if "is_broken" in obj and obj.is_broken:
|
||||
print("GameWorld: Object at index ", obj_index, " (name: ", obj.name, ") is already broken")
|
||||
return
|
||||
# Check if object is destroyable (chests and pillars are not destroyable)
|
||||
if "is_destroyable" in obj and not obj.is_destroyable:
|
||||
print("GameWorld: Object at index ", obj_index, " (name: ", obj.name, ") is not destroyable, skipping break")
|
||||
return
|
||||
if obj.has_method("_sync_break"):
|
||||
print("GameWorld: Breaking object at index ", obj_index, " (name: ", obj.name, ")")
|
||||
print("GameWorld: Object state before break - is_broken: ", obj.is_broken if "is_broken" in obj else "N/A", ", is_queued_for_deletion: ", obj.is_queued_for_deletion(), ", has sprite: ", "sprite" in obj and obj.sprite != null)
|
||||
|
||||
@@ -380,6 +380,12 @@ func _on_peer_disconnected(id: int):
|
||||
players_info.erase(id)
|
||||
player_disconnected.emit(id, player_info)
|
||||
|
||||
# If joiner and host (peer ID 1) disconnected, trigger server disconnection logic
|
||||
if not is_hosting and id == 1:
|
||||
log_print("NetworkManager: Host (peer ID 1) disconnected, triggering reconnection...")
|
||||
_on_server_disconnected()
|
||||
return
|
||||
|
||||
# Update room registry if hosting (player count changed)
|
||||
if is_hosting and room_registry and not room_id.is_empty():
|
||||
var player_count = get_all_player_ids().size()
|
||||
@@ -745,6 +751,21 @@ func _attempt_reconnect():
|
||||
log_print("NetworkManager: Cannot reconnect - is_hosting: " + str(is_hosting) + ", reconnection_room_id: " + reconnection_room_id)
|
||||
return
|
||||
|
||||
# Check if we're already connected to Matchbox (host might have reconnected and we're waiting for peer ID)
|
||||
if matchbox_client and matchbox_client.has("is_network_connected") and matchbox_client.is_network_connected:
|
||||
log_print("NetworkManager: Already connected to Matchbox, waiting for host to assign peer ID...")
|
||||
# Cancel reconnection attempt - we're already connected, just waiting for host
|
||||
reconnection_attempting = false
|
||||
reconnection_timer = 0.0
|
||||
|
||||
# Show chat message
|
||||
var game_world_waiting = get_tree().get_first_node_in_group("game_world")
|
||||
if game_world_waiting:
|
||||
var chat_ui = game_world_waiting.get_node_or_null("ChatUI")
|
||||
if chat_ui and chat_ui.has_method("add_local_message"):
|
||||
chat_ui.add_local_message("System", "Waiting for host to reconnect...")
|
||||
return
|
||||
|
||||
log_print("NetworkManager: Attempting to reconnect to room: " + reconnection_room_id)
|
||||
|
||||
# Show chat message for reconnection attempt
|
||||
|
||||
Reference in New Issue
Block a user