Files
whale-town/scripts/WorldManager.gd
2025-12-05 19:00:14 +08:00

280 lines
7.8 KiB
GDScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
extends Node
class_name WorldManager
## 世界管理器
## 管理游戏世界中的所有角色和对象
# 角色管理
var characters: Dictionary = {} # character_id -> CharacterController
var player_character: CharacterController = null
# 场景引用
var character_container: Node2D = null
# 预加载的角色场景
var player_character_scene: PackedScene = null
var remote_character_scene: PackedScene = null
# 信号
signal character_spawned(character_id: String, character: CharacterController)
signal character_removed(character_id: String)
signal character_state_updated(character_id: String)
func _ready():
"""初始化世界管理器"""
print("WorldManager initialized")
## 设置角色容器
func set_character_container(container: Node2D):
"""
设置角色容器节点
@param container: 用于放置角色的 Node2D 容器
"""
character_container = container
## 生成角色
func spawn_character(character_data: Dictionary, is_player: bool = false) -> CharacterController:
"""
在世界中生成角色
@param character_data: 角色数据
@param is_player: 是否为玩家角色
@return: 生成的角色控制器
"""
if not character_container:
push_error("Character container not set")
return null
var character_id = character_data.get(CharacterData.FIELD_ID, "")
if character_id.is_empty():
push_error("Character data missing ID")
return null
# 检查是否已存在
if characters.has(character_id):
push_warning("Character already exists: ", character_id)
return characters[character_id]
# 创建角色实例
var character: CharacterController
if is_player:
# 玩家角色(将在任务 11 中使用场景)
character = CharacterController.new()
character.name = "PlayerCharacter_" + character_id
else:
# 远程角色
character = CharacterController.new()
character.name = "RemoteCharacter_" + character_id
# 初始化角色
character.initialize(character_data)
# 添加到容器
character_container.add_child(character)
# 记录到字典
characters[character_id] = character
# 如果是玩家角色,保存引用
if is_player:
player_character = character
# 发射信号
character_spawned.emit(character_id, character)
print("Character spawned: ", character_id, " (player: ", is_player, ")")
return character
## 移除角色
func remove_character(character_id: String) -> void:
"""
从世界中移除角色
@param character_id: 角色 ID
"""
if not characters.has(character_id):
push_warning("Character not found: ", character_id)
return
var character = characters[character_id]
# 如果是玩家角色,清除引用
if character == player_character:
player_character = null
# 从字典中移除
characters.erase(character_id)
# 从场景树中移除
character.queue_free()
# 发射信号
character_removed.emit(character_id)
print("Character removed: ", character_id)
## 更新角色状态
func update_character_state(character_id: String, state: Dictionary) -> void:
"""
更新角色状态
@param character_id: 角色 ID
@param state: 状态数据(包含位置、在线状态等)
"""
if not characters.has(character_id):
# 检查是否是离线状态更新,如果是则忽略(角色可能已被清理)
var is_online = state.get("isOnline", true)
if not is_online:
print("Ignoring offline state update for removed character: ", character_id)
return
# 如果是在线状态但角色不存在,可能需要重新创建
print("Character not found for state update, attempting to recreate: ", character_id)
# 尝试从状态数据重新创建角色
if state.has("name") and state.has("position"):
var character_data = {
CharacterData.FIELD_ID: character_id,
CharacterData.FIELD_NAME: state.get("name", "Unknown"),
CharacterData.FIELD_POSITION: state.get("position", {"x": 0, "y": 0}),
CharacterData.FIELD_IS_ONLINE: is_online
}
spawn_character(character_data, false)
return
else:
print("Insufficient data to recreate character: ", character_id)
return
var character = characters[character_id]
# 更新位置
if state.has("position"):
var pos_data = state["position"]
var new_pos = Vector2(pos_data.get("x", 0), pos_data.get("y", 0))
character.set_position_smooth(new_pos)
# 更新在线状态
if state.has("isOnline"):
var is_online = state["isOnline"]
character.set_online_status(is_online)
# 如果角色下线,考虑延迟清理(避免频繁上下线导致的问题)
if not is_online:
print("Character went offline: ", character_id)
# 可以在这里添加延迟清理逻辑比如5分钟后清理离线角色
# _schedule_character_cleanup(character_id)
# 发射信号
character_state_updated.emit(character_id)
## 获取附近角色
func get_nearby_characters(position: Vector2, radius: float) -> Array:
"""
获取指定位置附近的角色
@param position: 中心位置
@param radius: 搜索半径
@return: 附近角色的数组
"""
var nearby: Array = []
for character in characters.values():
if character is CharacterController:
var distance = position.distance_to(character.global_position)
if distance <= radius:
nearby.append(character)
return nearby
## 获取所有角色
func get_all_characters() -> Array:
"""
获取所有角色
@return: 所有角色的数组
"""
return characters.values()
## 获取角色
func get_character(character_id: String) -> CharacterController:
"""
根据 ID 获取角色
@param character_id: 角色 ID
@return: 角色控制器,如果不存在则返回 null
"""
return characters.get(character_id, null)
## 获取玩家角色
func get_player_character() -> CharacterController:
"""
获取玩家角色
@return: 玩家角色控制器
"""
return player_character
## 处理角色上线
func handle_character_online(character_id: String) -> void:
"""
处理角色上线事件
@param character_id: 角色 ID
"""
if characters.has(character_id):
# 角色已存在,更新在线状态
var character = characters[character_id]
character.set_online_status(true)
print("Character came online: ", character_id)
else:
# 角色不存在,需要从服务器获取数据后生成
print("Character online but not spawned yet: ", character_id)
## 处理角色下线
func handle_character_offline(character_id: String) -> void:
"""
处理角色下线事件
@param character_id: 角色 ID
"""
if characters.has(character_id):
# 更新为离线状态(但不移除角色)
var character = characters[character_id]
character.set_online_status(false)
print("Character went offline: ", character_id)
else:
push_warning("Character not found for offline event: ", character_id)
## 生成或更新角色
func spawn_or_update_character(character_data: Dictionary) -> CharacterController:
"""
生成新角色或更新已存在的角色
@param character_data: 角色数据
@return: 角色控制器
"""
var character_id = character_data.get(CharacterData.FIELD_ID, "")
if character_id.is_empty():
push_error("Character data missing ID")
return null
# 检查角色是否已存在
if characters.has(character_id):
# 更新已存在的角色
update_character_state(character_id, character_data)
return characters[character_id]
else:
# 生成新角色(远程角色)
return spawn_character(character_data, false)
## 更新角色位置
func update_character_position(character_id: String, new_position: Vector2) -> void:
"""
更新角色位置
@param character_id: 角色 ID
@param new_position: 新位置
"""
if not characters.has(character_id):
push_warning("Character not found for position update: ", character_id)
return
var character = characters[character_id]
character.set_position_smooth(new_position)
## 清除所有角色
func clear_all_characters() -> void:
"""清除世界中的所有角色"""
for character_id in characters.keys():
remove_character(character_id)
print("All characters cleared")