From 16a46d7e76d315c31cca82283d06896d979b7e22 Mon Sep 17 00:00:00 2001 From: Yogi Wiguna Date: Tue, 3 Feb 2026 12:20:02 +0800 Subject: [PATCH] feat: Introduce an EnhancedGridMap with advanced grid generation, randomization, and data serialization features, along with a default MeshLibrary and a new main scene script. --- addons/enhanced_gridmap/enhanced_gridmap.gd | 32 +++++++++++++++++++ .../enhanced_gridmap/meshlibrary/default.tres | 5 ++- scenes/main.gd | 30 +++++++++++++++++ 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/addons/enhanced_gridmap/enhanced_gridmap.gd b/addons/enhanced_gridmap/enhanced_gridmap.gd index 22c22a4..5bf83da 100644 --- a/addons/enhanced_gridmap/enhanced_gridmap.gd +++ b/addons/enhanced_gridmap/enhanced_gridmap.gd @@ -182,6 +182,38 @@ func clear_grid(floor_index: int = -1): clear_floor(floor_index) update_grid_data() +# ============================================================================= +# Data Serialization Helpers (For Networking) +# ============================================================================= + +func get_floor_data(floor_index: int) -> PackedInt32Array: + # Returns a flat PackedInt32Array [x, z, item_id, ...] for the specified floor. + var data = PackedInt32Array() + # Use get_used_cells() as the source of truth from the GridMap itself + for cell in get_used_cells(): + if cell.y == floor_index: + data.append(cell.x) + data.append(cell.z) + data.append(get_cell_item(cell)) + return data + +func set_floor_data(floor_index: int, data: PackedInt32Array): + # Sets the floor items from a flat PackedInt32Array. Clears existing items on that floor first. + clear_floor(floor_index) + # Iterate by triplets [x, z, item] + var count = data.size() + if count % 3 != 0: + print("[EnhancedGridMap] Error: Malformed grid data array (size %d not divisible by 3)" % count) + return + + for i in range(0, count, 3): + var x = data[i] + var z = data[i+1] + var item = data[i+2] + set_cell_item(Vector3i(x, floor_index, z), item) + + update_grid_data() + func fill_grid(item_index: int, floor_index: int = -1): if not mesh_library: print("No MeshLibrary assigned to GridMap") diff --git a/addons/enhanced_gridmap/meshlibrary/default.tres b/addons/enhanced_gridmap/meshlibrary/default.tres index 8d6adbe..ca68458 100644 --- a/addons/enhanced_gridmap/meshlibrary/default.tres +++ b/addons/enhanced_gridmap/meshlibrary/default.tres @@ -6,8 +6,7 @@ [ext_resource type="ArrayMesh" uid="uid://brevl3ab0tdqe" path="res://assets/models/tiles/tile_wall.tres" id="4_8v5xv"] [ext_resource type="ArrayMesh" uid="uid://b5ta7tcw0iscd" path="res://assets/models/tiles/tile_coin.tres" id="4_76xkl"] [ext_resource type="ArrayMesh" uid="uid://d4himvyb81in8" path="res://assets/models/meshes/non-walkable.res" id="4_sx8rm"] -[ext_resource type="ArrayMesh" uid="uid://dr80txgr61irt" path="res://assets/models/tiles/tile_diamond.tres" id="5_j2mx0"] -[ext_resource type="ArrayMesh" uid="uid://dr80txgr61irt" path="res://assets/models/tiles/tile_area_freeze.tres" id="5_sx8rm"] +[ext_resource type="ArrayMesh" uid="uid://dr80txgr61irt" path="res://assets/models/tiles/tile_diamond.tres" id="5_sx8rm"] [ext_resource type="ArrayMesh" uid="uid://bqvqj3fhf5x51" path="res://assets/models/tiles/tile_ghost.tres" id="6_r32il"] [ext_resource type="ArrayMesh" uid="uid://cv4bedhida00g" path="res://assets/models/tiles/tile_star.tres" id="7_p5epg"] @@ -151,7 +150,7 @@ item/7/shapes = [] item/7/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) item/7/navigation_layers = 1 item/8/name = "tile_diamond" -item/8/mesh = ExtResource("5_j2mx0") +item/8/mesh = ExtResource("5_sx8rm") item/8/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) item/8/mesh_cast_shadow = 1 item/8/shapes = [] diff --git a/scenes/main.gd b/scenes/main.gd index 8bb4a80..998461e 100644 --- a/scenes/main.gd +++ b/scenes/main.gd @@ -463,6 +463,10 @@ func _setup_client_game(): # Wait shorter time for host to be ready, then request full sync to correct positions/state await get_tree().create_timer(1.0).timeout rpc_id(1, "request_full_player_sync", my_id) + + # Only request grid if we remain connected + if multiplayer.has_multiplayer_peer() and multiplayer.multiplayer_peer.get_connection_status() == MultiplayerPeer.CONNECTION_CONNECTED: + rpc_id(1, "request_full_grid_sync") func _auto_start_from_lobby(): """Called when main.tscn is loaded from lobby - game is already connected.""" @@ -1032,6 +1036,32 @@ func randomize_game_grid(): # For now, let's assume server authority + sync on connect handles it, or add sync loop if critical. pass +@rpc("any_peer") +func request_full_grid_sync(): + if multiplayer.is_server(): + var sender_id = multiplayer.get_remote_sender_id() + print("[Main] Grid sync requested by %d" % sender_id) + var enhanced_gridmap = $EnhancedGridMap + if enhanced_gridmap: + var grid_data = enhanced_gridmap.get_floor_data(1) # Sync Floor 1 (Items) + print("[Main] Server: Prepared grid data. Size: %d. Sending to %d..." % [grid_data.size(), sender_id]) + + # Force send (Server is usually always connected) + rpc_id(sender_id, "sync_full_grid_data", grid_data) + print("[Main] Server: Sent rpc_id to %d" % sender_id) + +@rpc("authority", "call_local", "reliable") +func sync_full_grid_data(data: PackedInt32Array): + print("[Main] sync_full_grid_data received. Items: %d" % (data.size() / 3)) + var enhanced_gridmap = $EnhancedGridMap + if not enhanced_gridmap: + print("[Main] Error: EnhancedGridMap not found!") + return + + # Apply the synced data to Floor 1 + enhanced_gridmap.set_floor_data(1, data) + print("[Main] Grid sync complete.") + # ============================================================================= # Goals Cycle & Leaderboard UI