feat: Add initial gridmap mesh library, main game script, and Nakama manager.
This commit is contained in:
@@ -128,56 +128,56 @@ item/6/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0,
|
|||||||
item/6/navigation_layers = 1
|
item/6/navigation_layers = 1
|
||||||
item/7/name = "tile_heart"
|
item/7/name = "tile_heart"
|
||||||
item/7/mesh = SubResource("ArrayMesh_pgnbl")
|
item/7/mesh = SubResource("ArrayMesh_pgnbl")
|
||||||
item/7/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
item/7/mesh_transform = Transform3D(0.9, 0, 0, 0, 0.9, 0, 0, 0, 0.9, 0, 0.05, 0)
|
||||||
item/7/mesh_cast_shadow = 1
|
item/7/mesh_cast_shadow = 1
|
||||||
item/7/shapes = []
|
item/7/shapes = []
|
||||||
item/7/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
item/7/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
||||||
item/7/navigation_layers = 1
|
item/7/navigation_layers = 1
|
||||||
item/8/name = "tile_diamond"
|
item/8/name = "tile_diamond"
|
||||||
item/8/mesh = SubResource("ArrayMesh_r32il")
|
item/8/mesh = SubResource("ArrayMesh_r32il")
|
||||||
item/8/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
item/8/mesh_transform = Transform3D(0.9, 0, 0, 0, 0.9, 0, 0, 0, 0.9, 0, 0.05, 0)
|
||||||
item/8/mesh_cast_shadow = 1
|
item/8/mesh_cast_shadow = 1
|
||||||
item/8/shapes = []
|
item/8/shapes = []
|
||||||
item/8/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
item/8/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
||||||
item/8/navigation_layers = 1
|
item/8/navigation_layers = 1
|
||||||
item/9/name = "tile_star"
|
item/9/name = "tile_star"
|
||||||
item/9/mesh = ExtResource("7_p5epg")
|
item/9/mesh = ExtResource("7_p5epg")
|
||||||
item/9/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
item/9/mesh_transform = Transform3D(0.9, 0, 0, 0, 0.9, 0, 0, 0, 0.9, 0, 0.05, 0)
|
||||||
item/9/mesh_cast_shadow = 1
|
item/9/mesh_cast_shadow = 1
|
||||||
item/9/shapes = []
|
item/9/shapes = []
|
||||||
item/9/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
item/9/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
||||||
item/9/navigation_layers = 1
|
item/9/navigation_layers = 1
|
||||||
item/10/name = "tile_coin"
|
item/10/name = "tile_coin"
|
||||||
item/10/mesh = ExtResource("4_76xkl")
|
item/10/mesh = ExtResource("4_76xkl")
|
||||||
item/10/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
item/10/mesh_transform = Transform3D(0.9, 0, 0, 0, 0.9, 0, 0, 0, 0.9, 0, 0.05, 0)
|
||||||
item/10/mesh_cast_shadow = 1
|
item/10/mesh_cast_shadow = 1
|
||||||
item/10/shapes = []
|
item/10/shapes = []
|
||||||
item/10/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
item/10/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
||||||
item/10/navigation_layers = 1
|
item/10/navigation_layers = 1
|
||||||
item/11/name = "tile_speed"
|
item/11/name = "tile_speed"
|
||||||
item/11/mesh = ExtResource("7_sx8rm")
|
item/11/mesh = ExtResource("7_sx8rm")
|
||||||
item/11/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
item/11/mesh_transform = Transform3D(1.1, 0, 0, 0, 1.1, 0, 0, 0, 1.1, 0, 0, 0)
|
||||||
item/11/mesh_cast_shadow = 1
|
item/11/mesh_cast_shadow = 1
|
||||||
item/11/shapes = []
|
item/11/shapes = []
|
||||||
item/11/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
item/11/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
||||||
item/11/navigation_layers = 1
|
item/11/navigation_layers = 1
|
||||||
item/12/name = "tile_area_freeze"
|
item/12/name = "tile_area_freeze"
|
||||||
item/12/mesh = ExtResource("5_sx8rm")
|
item/12/mesh = ExtResource("5_sx8rm")
|
||||||
item/12/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
item/12/mesh_transform = Transform3D(1.1, 0, 0, 0, 1.1, 0, 0, 0, 1.1, 0, 0, 0)
|
||||||
item/12/mesh_cast_shadow = 1
|
item/12/mesh_cast_shadow = 1
|
||||||
item/12/shapes = []
|
item/12/shapes = []
|
||||||
item/12/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
item/12/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
||||||
item/12/navigation_layers = 1
|
item/12/navigation_layers = 1
|
||||||
item/13/name = "tile_wall"
|
item/13/name = "tile_wall"
|
||||||
item/13/mesh = ExtResource("4_8v5xv")
|
item/13/mesh = ExtResource("4_8v5xv")
|
||||||
item/13/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
item/13/mesh_transform = Transform3D(1.1, 0, 0, 0, 1.1, 0, 0, 0, 1.1, 0, 0, 0)
|
||||||
item/13/mesh_cast_shadow = 1
|
item/13/mesh_cast_shadow = 1
|
||||||
item/13/shapes = []
|
item/13/shapes = []
|
||||||
item/13/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
item/13/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
||||||
item/13/navigation_layers = 1
|
item/13/navigation_layers = 1
|
||||||
item/14/name = "tile_ghost"
|
item/14/name = "tile_ghost"
|
||||||
item/14/mesh = ExtResource("6_r32il")
|
item/14/mesh = ExtResource("6_r32il")
|
||||||
item/14/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
item/14/mesh_transform = Transform3D(1.1, 0, 0, 0, 1.1, 0, 0, 0, 1.1, 0, 0, 0)
|
||||||
item/14/mesh_cast_shadow = 1
|
item/14/mesh_cast_shadow = 1
|
||||||
item/14/shapes = []
|
item/14/shapes = []
|
||||||
item/14/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
item/14/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ var touch_controls
|
|||||||
|
|
||||||
# Minimal local state
|
# Minimal local state
|
||||||
var _connection_check_timer: float = 0.0
|
var _connection_check_timer: float = 0.0
|
||||||
var tile_respawn_timers = {} # Tracks removed tiles: {Vector2i(x,z): respawn_time_msec}
|
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
# Initialize scene managers
|
# Initialize scene managers
|
||||||
@@ -49,15 +48,6 @@ func _ready():
|
|||||||
# Ensure grid is randomized with Scarcity if server
|
# Ensure grid is randomized with Scarcity if server
|
||||||
if multiplayer.is_server():
|
if multiplayer.is_server():
|
||||||
randomize_game_grid()
|
randomize_game_grid()
|
||||||
_setup_tile_respawn_timer()
|
|
||||||
|
|
||||||
# Targeted 5s Respawn Timer for empty spots
|
|
||||||
var respawn_check_timer = Timer.new()
|
|
||||||
respawn_check_timer.name = "RespawnCheckTimer"
|
|
||||||
respawn_check_timer.wait_time = 0.5
|
|
||||||
respawn_check_timer.autostart = true
|
|
||||||
respawn_check_timer.timeout.connect(_check_respawns)
|
|
||||||
add_child(respawn_check_timer)
|
|
||||||
|
|
||||||
# Force gridmap cell size to match player logic (1, 0.05, 1) - >0.001 to avoid errors
|
# Force gridmap cell size to match player logic (1, 0.05, 1) - >0.001 to avoid errors
|
||||||
var em = $EnhancedGridMap
|
var em = $EnhancedGridMap
|
||||||
@@ -69,56 +59,6 @@ func _on_goal_count_updated(peer_id: int, count: int):
|
|||||||
if peer_id == multiplayer.get_unique_id():
|
if peer_id == multiplayer.get_unique_id():
|
||||||
ui_manager.update_goal_count_label(count)
|
ui_manager.update_goal_count_label(count)
|
||||||
|
|
||||||
func _setup_tile_respawn_timer():
|
|
||||||
# Configure respawn rate based on Scarcity Mode from Lobby
|
|
||||||
var mode = LobbyManager.get_scarcity_mode()
|
|
||||||
var interval = 0.0
|
|
||||||
|
|
||||||
match mode:
|
|
||||||
"Aggressive": interval = 5.0
|
|
||||||
"Chaos": interval = 1.0 # Very fast!
|
|
||||||
"Normal": interval = 0.0 # No periodic respawn (only refill when empty)
|
|
||||||
_: interval = 0.0
|
|
||||||
|
|
||||||
if interval > 0:
|
|
||||||
var timer = Timer.new()
|
|
||||||
timer.name = "TileRespawnTimer"
|
|
||||||
timer.wait_time = interval
|
|
||||||
timer.autostart = true
|
|
||||||
timer.one_shot = false
|
|
||||||
timer.timeout.connect(_on_tile_respawn_timeout)
|
|
||||||
add_child(timer)
|
|
||||||
print("[Main] TileRespawnTimer started with interval: %.1f (Mode: %s)" % [interval, mode])
|
|
||||||
|
|
||||||
func _on_tile_respawn_timeout():
|
|
||||||
if not multiplayer.is_server(): return
|
|
||||||
|
|
||||||
var enhanced_gridmap = $EnhancedGridMap
|
|
||||||
if not enhanced_gridmap: return
|
|
||||||
|
|
||||||
# Try to find an empty spot (max 10 retries)
|
|
||||||
for i in range(10):
|
|
||||||
var x = randi() % enhanced_gridmap.columns
|
|
||||||
var z = randi() % enhanced_gridmap.rows
|
|
||||||
var cell = Vector3i(x, 1, z)
|
|
||||||
|
|
||||||
if enhanced_gridmap.get_cell_item(cell) == -1:
|
|
||||||
# Check floor 0
|
|
||||||
if enhanced_gridmap.get_cell_item(Vector3i(x, 0, z)) != -1:
|
|
||||||
# Check player occupancy
|
|
||||||
var occupied = false
|
|
||||||
for player in get_tree().get_nodes_in_group("Players"):
|
|
||||||
if Vector2i(player.current_position.x, player.current_position.y) == Vector2i(x, z):
|
|
||||||
occupied = true
|
|
||||||
break
|
|
||||||
|
|
||||||
if not occupied:
|
|
||||||
# Spawn!
|
|
||||||
var new_item = ScarcityController.get_random_tile_id()
|
|
||||||
sync_grid_item(x, 1, z, new_item)
|
|
||||||
rpc("sync_grid_item", x, 1, z, new_item)
|
|
||||||
return # Spawned one, done for this tick
|
|
||||||
|
|
||||||
func _init_managers():
|
func _init_managers():
|
||||||
# Create and attach scene managers
|
# Create and attach scene managers
|
||||||
ui_manager = load("res://scripts/managers/ui_manager.gd").new()
|
ui_manager = load("res://scripts/managers/ui_manager.gd").new()
|
||||||
@@ -1144,42 +1084,12 @@ func request_randomize_item(grid_position: Vector2i):
|
|||||||
if multiplayer.is_server():
|
if multiplayer.is_server():
|
||||||
randomize_item_at_position(grid_position)
|
randomize_item_at_position(grid_position)
|
||||||
|
|
||||||
func _check_respawns():
|
|
||||||
"""Check tile respawn timers and spawn items if ready."""
|
|
||||||
if not multiplayer.is_server():
|
|
||||||
return
|
|
||||||
|
|
||||||
var current_time = Time.get_ticks_msec()
|
|
||||||
var tiles_to_respawn = []
|
|
||||||
|
|
||||||
for pos in tile_respawn_timers.keys():
|
|
||||||
if current_time >= tile_respawn_timers[pos]:
|
|
||||||
tiles_to_respawn.append(pos)
|
|
||||||
|
|
||||||
for pos in tiles_to_respawn:
|
|
||||||
print("[Main] Respawning tile at ", pos)
|
|
||||||
randomize_item_at_position(pos)
|
|
||||||
tile_respawn_timers.erase(pos)
|
|
||||||
|
|
||||||
@rpc("any_peer", "call_local", "reliable")
|
@rpc("any_peer", "call_local", "reliable")
|
||||||
func sync_grid_item(x: int, y: int, z: int, item: int):
|
func sync_grid_item(x: int, y: int, z: int, item: int):
|
||||||
var enhanced_gridmap = $EnhancedGridMap
|
var enhanced_gridmap = $EnhancedGridMap
|
||||||
if enhanced_gridmap:
|
if enhanced_gridmap:
|
||||||
enhanced_gridmap.set_cell_item(Vector3i(x, y, z), item)
|
enhanced_gridmap.set_cell_item(Vector3i(x, y, z), item)
|
||||||
|
|
||||||
# Server logic for respawns
|
|
||||||
if multiplayer.is_server() and y == 1:
|
|
||||||
var pos = Vector2i(x, z)
|
|
||||||
if item == -1:
|
|
||||||
# Item removed - schedule respawn 5s later
|
|
||||||
tile_respawn_timers[pos] = Time.get_ticks_msec() + 10000
|
|
||||||
print("[Main] Scheduled respawn for tile at %s in 10s" % pos)
|
|
||||||
else:
|
|
||||||
# Item placed - cancel pending respawn
|
|
||||||
if tile_respawn_timers.has(pos):
|
|
||||||
tile_respawn_timers.erase(pos)
|
|
||||||
print("[Main] Cancelled respawn for tile at %s (occupied)" % pos)
|
|
||||||
|
|
||||||
# Sync grid update (no need to sync whole grid if we do it at start, but if we do it late we might need to sync)
|
# Sync grid update (no need to sync whole grid if we do it at start, but if we do it late we might need to sync)
|
||||||
# For simplicity, we trust the grid syncs via normal mechanisms or initial state.
|
# For simplicity, we trust the grid syncs via normal mechanisms or initial state.
|
||||||
|
|
||||||
|
|||||||
@@ -102,6 +102,14 @@ func join_game(match_id: String):
|
|||||||
if not bridge:
|
if not bridge:
|
||||||
printerr("Cannot join: Bridge not initialized")
|
printerr("Cannot join: Bridge not initialized")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# If already connected, leave current match first
|
||||||
|
if bridge.multiplayer_peer.get_connection_status() == MultiplayerPeer.CONNECTION_CONNECTED:
|
||||||
|
print("Already connected to a match. Leaving current match before joining...")
|
||||||
|
bridge.leave()
|
||||||
|
# Wait a bit for cleanup
|
||||||
|
await get_tree().create_timer(0.2).timeout
|
||||||
|
|
||||||
print("Joining match: ", match_id)
|
print("Joining match: ", match_id)
|
||||||
var result = await bridge.join_match(match_id)
|
var result = await bridge.join_match(match_id)
|
||||||
if result and result.is_exception():
|
if result and result.is_exception():
|
||||||
|
|||||||
Reference in New Issue
Block a user