(client) feat:支持定义实体的碰撞体大小和偏移;建筑支持定义实体建筑和瓦片建筑,建筑支持指定按钮回调;添加存档管理器;Dev支持设置是否暂停;实体允许定义事件组;添加基地界面 (#57)

Co-authored-by: m0_75251201 <m0_75251201@noreply.gitcode.com>
Reviewed-on: http://47.107.252.169:3000/Roguelite-Game-Developing-Team/Gen_Hack-and-Slash-Roguelite/pulls/57
This commit is contained in:
2025-09-28 15:02:57 +08:00
parent 87a8abe86c
commit aff747be17
232 changed files with 39203 additions and 4161 deletions

View File

@@ -2,22 +2,41 @@ using Map;
using System;
using System.Collections.Generic;
using System.Linq;
using Base;
using Data;
using Managers;
using UnityEngine;
using Utils;
/// <summary>
/// Program 类作为单例模式的核心管理器,负责维护和管理游戏或应用中的维度(Dimension)实例和焦点状态。
/// 它提供了维度注册、注销、获取以及焦点维度设置的功能。
/// </summary>
public class Program : Singleton<Program>
{
// 当前角色定义
public CharacterDef CurrentCharacter { get;private set; }
// 指示是否需要加载数据的标志,例如在游戏启动或场景切换时。
private bool _needLoad = true;
/// <summary>
/// 指示是否需要加载数据的标志,例如在游戏启动或场景切换时。
/// </summary>
public bool needLoad = true;
public bool NeedLoad
{
get => _needLoad;
set
{
if (value)
{
CurrentCharacter = null;
}
_needLoad = value;
}
}
public bool OnPlay => CurrentCharacter != null;
/// <summary>
/// 当前聚焦的实体对象。
@@ -35,7 +54,6 @@ public class Program : Singleton<Program>
/// 当前活跃焦点的维度唯一标识符,可能为空。
/// 变更为属性并私有化setter确保通过 SetFocusedDimension 方法集中管理其更新。
/// </summary>
// 逻辑修改1修正属性名 'focuseDimensionId' 为 'focusedDimensionId'
public string FocusedDimensionId { get; private set; } = null;
/// <summary>
@@ -59,9 +77,25 @@ public class Program : Singleton<Program>
/// </summary>
public event Action<Dimension> OnFocusedDimensionChanged;
/// <summary>
/// 获取已注册维度的数量。
/// </summary>
public int DimensionCount => _registeredDimensions.Count;
/// <summary>
/// 获取所有已注册维度的ID数组。
/// </summary>
public string[] Dimensions => _registeredDimensions.Keys.ToArray();
public bool CanOpenRightMenu => Setting.Instance.CurrentSettings.developerMode && !OnPlay;
public bool CanMoveCamera => CanOpenRightMenu;
/// <summary>
/// 注册一个维度实例到 Program。
/// </summary>
@@ -70,28 +104,23 @@ public class Program : Singleton<Program>
{
if (dimension == null)
{
Debug.LogError("[Program] Attempted to register a null Dimension.");
Debug.LogError("[Program] 尝试注册一个空的维度。");
return;
}
var id = dimension.DimensionId;
if (string.IsNullOrEmpty(id))
{
Debug.LogError($"[Program] Attempted to register a Dimension with an empty or null ID: {dimension.name}");
Debug.LogError($"[Program] 尝试注册一个ID为空的维度: {dimension.name}");
return;
}
if (_registeredDimensions.ContainsKey(id))
if (!_registeredDimensions.TryAdd(id, dimension))
{
Debug.LogWarning($"[Program] Dimension with ID '{id}' is already registered. Skipping duplicate registration for {dimension.name}.");
Debug.LogWarning($"[Program] ID '{id}' 的维度已注册。跳过重复注册 {dimension.name}");
return;
}
_registeredDimensions.Add(id, dimension);
// 逻辑修改此处不需要if语句包裹_registeredDimensions.Add因为前置的ContainsKey已确保不会抛异常
// 确保任何对焦点的潜在更新都通过 SetFocusedDimension 进行,
// 从而集中管理焦点状态的同步和事件的触发。
// 如果注册的维度恰好是当前 focusedDimensionId SetFocusedDimension(id) 将负责更新 FocusedDimension 并触发事件。
// 如果注册的维度恰好是当前 focusedDimensionIdSetFocusedDimension(id) 将负责更新 FocusedDimension 并触发事件
// 并且由于SetFocusedDimension会清空FocusedEntity这也符合新维度的行为。
// 逻辑修改1修正属性名 'focuseDimensionId' 为 'focusedDimensionId'
if (FocusedDimensionId == id)
{
SetFocusedDimension(id);
@@ -106,16 +135,13 @@ public class Program : Singleton<Program>
{
if (dimension == null)
{
Debug.LogWarning("[Program] Attempted to unregister a null Dimension. Skipping.");
Debug.LogWarning("[Program] 尝试注销一个空的维度。");
return;
}
var id = dimension.DimensionId;
if (_registeredDimensions.Remove(id))
{
// 确保任何对焦点的潜在更新都通过 SetFocusedDimension 进行,
// 从而集中管理焦点状态的同步和事件的触发。
// 如果注销的维度是当前焦点维度,则调用 SetFocusedDimension(null) 清除焦点并触发事件。
// 逻辑修改1修正属性名 'focuseDimensionId' 为 'focusedDimensionId'
if (FocusedDimensionId == id)
{
SetFocusedDimension(null); // 清除焦点
@@ -123,7 +149,7 @@ public class Program : Singleton<Program>
}
else
{
Debug.LogWarning($"[Program] Attempted to unregister Dimension '{id}' which was not found in the registered list.");
Debug.LogWarning($"[Program] 尝试注销ID为 '{id}' 的维度,但未在已注册列表中找到。");
}
}
@@ -134,6 +160,8 @@ public class Program : Singleton<Program>
/// <returns>对应的Dimension实例如果未找到则返回null。</returns>
public Dimension GetDimension(string dimensionId)
{
if (dimensionId == null)
return null;
_registeredDimensions.TryGetValue(dimensionId, out var dimension);
return dimension;
}
@@ -145,33 +173,29 @@ public class Program : Singleton<Program>
/// <param name="dimensionId">要设置为焦点的维度的唯一标识符。如果传入null或空字符串将清除当前焦点维度。</param>
public void SetFocusedDimension(string dimensionId)
{
// 1. 确定新的焦点维度及其ID
// 确定新的焦点维度及其ID
Dimension newFocusedDimension = null; // 默认为清除焦点
string newFocusedDimensionId = null; // 逻辑修改1修正属性名 'newFocuseDimensionId' 为 'newFocusedDimensionId'
string newFocusedDimensionId = null;
if (!string.IsNullOrEmpty(dimensionId))
{
if (_registeredDimensions.TryGetValue(dimensionId, out var foundDimension))
{
newFocusedDimensionId = dimensionId; // 逻辑修改1修正属性名
newFocusedDimensionId = dimensionId;
newFocusedDimension = foundDimension;
}
else
{
// 如果尝试设置未注册的维度,警告并直接返回,不改变当前焦点状态。
Debug.LogWarning($"[Program] Attempted to set focus to unregistered dimension ID: '{dimensionId}'. Focus not changed.");
Debug.LogWarning($"[Program] 尝试设置焦点到未注册的维度ID: '{dimensionId}'。焦点未改变。");
return;
}
}
// 如果 dimensionId 为 null 或空, newFocusedDimension 和 newFocusedDimensionId 将保持为 null表示清除焦点。
// 2. 优化:检查是否实际发生变化,避免不必要的更新和事件触发
// 只有当新的ID或新的维度对象引用与当前的不一致时才执行更新。
// 逻辑修改1修正属性名 'focuseDimensionId' 为 'focusedDimensionId'
// 逻辑修改1修正局部变量名 'newFocuseDimensionId' 为 'newFocusedDimensionId'
// 检查是否实际发生变化
if (FocusedDimensionId == newFocusedDimensionId && FocusedDimension == newFocusedDimension)
{
// Debug.Log($"[Program] SetFocusedDimension: ID '{dimensionId}' already current. No change needed.");
return;
}
@@ -179,15 +203,14 @@ public class Program : Singleton<Program>
{
FocusedEntity.PlayerControlled = false;
}
// 3. 更新内部状态
FocusedDimensionId = newFocusedDimensionId; // 逻辑修改1修正属性名
// 更新内部状态
FocusedDimensionId = newFocusedDimensionId;
FocusedDimension = newFocusedDimension;
// 逻辑修改2功能缺失修复 - 切换维度时,焦点实体应该置为空
// 确保功能一致性:当维度焦点改变(或被清除)时,任何实体焦点也应被清除。
SetFocusedEntity(null);
// 4. 触发事件
// 触发事件
OnFocusedDimensionChanged?.Invoke(FocusedDimension);
}
@@ -198,14 +221,25 @@ public class Program : Singleton<Program>
/// <param name="entity">要设置为焦点的实体实例。如果传入null将清除当前焦点实体。</param>
public void SetFocusedEntity(Entity.Entity entity)
{
// 优化:检查是否实际发生变化,避免不必要的更新和事件触发。
// 如果新的实体与当前焦点实体相同(按引用比较),则不执行任何操作。
if (FocusedEntity == entity||!FocusedDimension)
// 检查是否实际发生变化
if (FocusedEntity == entity || !FocusedDimension)
{
return;
}
FocusedDimension.focusEntity=entity;
FocusedDimension.focusEntity = entity;
// 触发事件,将新的焦点实体(或 null作为参数传递。
OnFocusedEntityChanged?.Invoke(FocusedEntity);
}
public void PlayGame(CharacterDef character)
{
CurrentCharacter = character;
if (character == null)
return;
var pos = CameraControl.CameraControl.Instance.Position;
var player = EntityManager.Instance.GenerateEntity(FocusedDimensionId, character, new Vector3(pos.x, pos.y));
if(!player)
return;
player.entity.PlayerControlled = true;
}
}