This commit is contained in:
WangXiang
2025-12-22 18:57:51 +08:00
commit 6119faf53e
159 changed files with 19162 additions and 0 deletions

159
Scripts/World.gd Normal file
View File

@@ -0,0 +1,159 @@
extends Node2D
@onready var players_container = $PlayersContainer
@onready var tile_map = $Ground
var player_nodes := {} # id -> Node
func _ready():
$Ground.scale = Vector2(1, 1)
if has_node("Water"):
$Water.scale = Vector2(1, 1)
# Clean setup: trust the scene file
var entrance = get_node_or_null("NeighborhoodEntrance")
if entrance:
entrance.monitorable = true
entrance.monitoring = true
# Ensure it detects Player (Layer 2) OR Layer 1 just in case
entrance.collision_mask = 3 # Layers 1 and 2
if not entrance.body_entered.is_connected(_on_neighborhood_entrance_body_entered):
entrance.body_entered.connect(_on_neighborhood_entrance_body_entered)
if not entrance.body_exited.is_connected(_on_neighborhood_entrance_body_exited):
entrance.body_exited.connect(_on_neighborhood_entrance_body_exited)
NetworkManager.login_ok.connect(_on_login_ok)
NetworkManager.player_joined.connect(_on_player_joined)
NetworkManager.player_left.connect(_on_player_left)
NetworkManager.player_moved.connect(_on_player_moved)
NetworkManager.disconnected.connect(_on_disconnected)
# Explicitly spawn local player if logged in
if NetworkManager.my_id != -1:
_spawn_player(NetworkManager.my_id, NetworkManager.player_info["name"], 0, 0, NetworkManager.player_info["skin_id"])
for id in NetworkManager.players:
var p = NetworkManager.players[id]
_spawn_player(id, p["name"], p["x"], p["y"], p.get("skin_id", 0))
var chat = preload("res://Scenes/UI/ChatHUD.tscn").instantiate()
add_child(chat)
var player_in_entrance := false
func _on_neighborhood_entrance_body_entered(body):
print("Body ENTERED Trigger: ", body.name, " (My ID: ", NetworkManager.my_id, ")")
# Check if it's the local player
if body.name == str(NetworkManager.my_id):
player_in_entrance = true
print("Player ENTERED entrance area")
func _on_neighborhood_entrance_body_exited(body):
if body.name == str(NetworkManager.my_id):
player_in_entrance = false
print("Player EXITED entrance area")
func _physics_process(_delta):
if player_in_entrance:
# Check for Up input while inside the entrance
if Input.is_action_pressed("ui_up") or Input.is_key_pressed(KEY_W):
_do_room_transition()
func _do_room_transition():
var entrance = get_node_or_null("NeighborhoodEntrance")
if not entrance:
return
var local_player = player_nodes.get(NetworkManager.my_id)
if not local_player:
return
player_in_entrance = false # Prevent re-trigger
NetworkManager.next_spawn_position = local_player.position + Vector2(0, 32)
NetworkManager.send_change_scene("room_" + str(NetworkManager.my_id), Vector2(0, 0))
get_tree().change_scene_to_file("res://Scenes/Room.tscn")
func _fill_background():
# Fill base stone floor (standard blue brick at 0,0)
# Procedural generation for background
# Procedural generation for background
for x in range(-50, 150):
for y in range(-50, 100):
var tile_pos = Vector2i(x, y)
# Plaza in the center (0 to 15)
if x >= 0 and x < 15 and y >= 0 and y < 15:
# Use light gray stone coordinates confirmed in TownTileset.tres
var rand_var = randi() % 3
tile_map.set_cell(tile_pos, 5, Vector2i(4 + rand_var, 0)) # (4,0), (5,0), (6,0)
else:
# Regular floor (blue-ish / darker)
if (x + y) % 2 == 0:
tile_map.set_cell(tile_pos, 5, Vector2i(1, 0))
else:
tile_map.set_cell(tile_pos, 5, Vector2i(2, 0))
func _on_login_ok(_my_id, _players):
pass
func _on_player_joined(id, p_name, x, y, skin_id):
_spawn_player(id, p_name, x, y, skin_id)
func _on_player_left(id):
if player_nodes.has(id):
player_nodes[id].queue_free()
player_nodes.erase(id)
func _on_player_moved(id, x, y, flip_h, frame):
if player_nodes.has(id):
player_nodes[id].set_remote_state(Vector2(x, y), flip_h, frame)
func _on_disconnected():
get_tree().change_scene_to_file("res://Scenes/StartMenu.tscn")
func _spawn_player(id, _p_name, x, y, _skin_id):
# Anti-Ghosting: Check if this player already exists in the tree
if players_container.has_node(str(id)):
var old_node = players_container.get_node(str(id))
old_node.name = "Ghost_" + str(id) # Rename to avoid duplicate name error during queue_free
old_node.queue_free()
# Also clean dictionary
if player_nodes.has(id):
player_nodes.erase(id)
var p = preload("res://Scenes/Player.tscn").instantiate()
p.name = str(id)
# Override position if returning from another scene
var spawn_pos = Vector2(x, y)
if id == NetworkManager.my_id and NetworkManager.next_spawn_position != Vector2.ZERO:
spawn_pos = NetworkManager.next_spawn_position
# Reset after use
NetworkManager.next_spawn_position = Vector2.ZERO
p.position = spawn_pos
p.player_id = id
p.is_local = (id == NetworkManager.my_id)
print("Spawning Player ID: ", id, " Name: ", _p_name, " Is Local: ", p.is_local, " (My ID: ", NetworkManager.my_id, ")")
if p.is_local:
p.interaction_request.connect(_on_interaction_request)
players_container.add_child(p)
player_nodes[id] = p
func _on_interaction_request(target_id, target_name):
print("World received interaction request for: ", target_name)
var chat = get_node_or_null("ChatHUD")
if chat:
if chat.has_method("set_private_target"):
chat.set_private_target(target_id, target_name)
else:
print("ChatHUD missing set_private_target method")