241 lines
7.3 KiB
Markdown
241 lines
7.3 KiB
Markdown
# Bug修复:开垦和铲除操作UI更新缺失
|
||
|
||
## 问题描述
|
||
|
||
在开垦土地和铲除作物操作完成后,客户端的UI没有正确更新,具体表现为:
|
||
|
||
1. **金钱数量不更新**:操作完成后,显示的金钱数量仍然是操作前的数值
|
||
2. **等级和经验不更新**:如果操作导致等级或经验变化,UI没有反映
|
||
3. **地块状态不同步**:虽然服务器数据已更新,但客户端显示可能不一致
|
||
|
||
## 问题根源
|
||
|
||
### 原始问题分析
|
||
|
||
客户端的 `_handle_action_response()` 方法只处理了以下操作类型:
|
||
- `harvest_crop` - 收获作物 ✅
|
||
- `plant_crop` - 种植作物 ✅
|
||
- `buy_seed` - 购买种子 ✅
|
||
- `dig_ground` - 开垦土地 ✅
|
||
|
||
但是缺少了:
|
||
- `remove_crop` - 铲除作物 ❌
|
||
|
||
### 代码问题位置
|
||
|
||
```gdscript
|
||
# MainGame.gd 中的 _handle_action_response 方法
|
||
func _handle_action_response(response_data):
|
||
var action_type = response_data.get("action_type", "")
|
||
var success = response_data.get("success", false)
|
||
var message = response_data.get("message", "")
|
||
var updated_data = response_data.get("updated_data", {})
|
||
|
||
match action_type:
|
||
"harvest_crop":
|
||
# 处理收获响应 ✅
|
||
"plant_crop":
|
||
# 处理种植响应 ✅
|
||
"buy_seed":
|
||
# 处理购买响应 ✅
|
||
"dig_ground":
|
||
# 处理开垦响应 ✅
|
||
# 缺少 "remove_crop" 的处理 ❌
|
||
```
|
||
|
||
## 修复方案
|
||
|
||
### 1. 添加铲除作物响应处理
|
||
|
||
在 `MainGame.gd` 的 `_handle_action_response()` 方法中添加对 `remove_crop` 操作的处理:
|
||
|
||
```gdscript
|
||
"remove_crop":
|
||
if success:
|
||
# 更新玩家数据
|
||
if updated_data.has("money"):
|
||
money = updated_data["money"]
|
||
if updated_data.has("farm_lots"):
|
||
farm_lots = updated_data["farm_lots"]
|
||
|
||
# 更新UI
|
||
_update_ui()
|
||
_update_farm_lots_state()
|
||
Toast.show(message, Color.GREEN)
|
||
else:
|
||
Toast.show(message, Color.RED)
|
||
```
|
||
|
||
### 2. 优化客户端预验证
|
||
|
||
为了提供更好的用户体验,在 `land_panel.gd` 中添加了更完善的预验证:
|
||
|
||
#### 开垦操作预验证
|
||
```gdscript
|
||
# 检查玩家金钱是否足够
|
||
var dig_cost = main_game.dig_money
|
||
if main_game.money < dig_cost:
|
||
Toast.show("金钱不足,开垦土地需要 " + str(dig_cost) + " 金钱", Color.RED, 2.0, 1.0)
|
||
self.hide()
|
||
return
|
||
|
||
# 检查地块是否已经开垦
|
||
var lot = main_game.farm_lots[selected_lot_index]
|
||
if lot.get("is_diged", false):
|
||
Toast.show("此地块已经开垦过了", Color.ORANGE, 2.0, 1.0)
|
||
self.hide()
|
||
return
|
||
```
|
||
|
||
#### 铲除操作预验证
|
||
```gdscript
|
||
# 检查玩家金钱是否足够
|
||
var removal_cost = 500
|
||
if main_game.money < removal_cost:
|
||
Toast.show("金钱不足,铲除作物需要 " + str(removal_cost) + " 金钱", Color.RED, 2.0, 1.0)
|
||
self.hide()
|
||
return
|
||
|
||
# 检查地块是否有作物
|
||
var lot = main_game.farm_lots[selected_lot_index]
|
||
if not lot.get("is_planted", false) or lot.get("crop_type", "") == "":
|
||
Toast.show("此地块没有种植作物", Color.ORANGE, 2.0, 1.0)
|
||
self.hide()
|
||
return
|
||
```
|
||
|
||
### 3. 移除不必要的UI更新调用
|
||
|
||
移除了 `land_panel.gd` 中不必要的 `main_game._update_ui()` 调用,因为服务器响应会统一处理UI更新。
|
||
|
||
## 修复效果
|
||
|
||
### 修复前的问题
|
||
1. **开垦土地后**:
|
||
- 金钱显示:1000元 → 1000元 ❌ (实际应该减少)
|
||
- 地块状态:可能不同步
|
||
- 用户体验:困惑,不知道操作是否成功
|
||
|
||
2. **铲除作物后**:
|
||
- 金钱显示:1000元 → 1000元 ❌ (实际应该减少500)
|
||
- 地块状态:可能显示仍有作物
|
||
- 用户体验:需要刷新页面才能看到变化
|
||
|
||
### 修复后的正确行为
|
||
1. **开垦土地后**:
|
||
- 金钱显示:1000元 → 0元 ✅ (正确扣除1000)
|
||
- 地块状态:立即显示为已开垦 ✅
|
||
- 用户体验:即时反馈,操作流畅
|
||
|
||
2. **铲除作物后**:
|
||
- 金钱显示:1000元 → 500元 ✅ (正确扣除500)
|
||
- 地块状态:立即显示为空地 ✅
|
||
- 用户体验:即时反馈,操作流畅
|
||
|
||
## 数据流程
|
||
|
||
### 完整的操作流程
|
||
1. **客户端预验证** → 检查金钱、地块状态等
|
||
2. **发送请求** → 向服务器发送操作请求
|
||
3. **服务器处理** → 验证并执行操作,更新数据
|
||
4. **服务器响应** → 返回操作结果和更新后的数据
|
||
5. **客户端处理响应** → 更新本地数据和UI显示
|
||
6. **UI更新** → 刷新金钱、经验、地块状态等显示
|
||
|
||
### 数据同步机制
|
||
```gdscript
|
||
# 服务器响应处理
|
||
if success:
|
||
# 1. 更新本地数据
|
||
if updated_data.has("money"):
|
||
money = updated_data["money"]
|
||
if updated_data.has("farm_lots"):
|
||
farm_lots = updated_data["farm_lots"]
|
||
|
||
# 2. 刷新UI显示
|
||
_update_ui() # 更新金钱、经验、等级显示
|
||
_update_farm_lots_state() # 更新地块状态显示
|
||
|
||
# 3. 显示成功提示
|
||
Toast.show(message, Color.GREEN)
|
||
```
|
||
|
||
## 测试验证
|
||
|
||
### 测试用例1:开垦土地UI更新
|
||
1. 玩家有1000金钱
|
||
2. 点击未开垦地块,选择开垦
|
||
3. 操作成功后检查:
|
||
- 金钱显示是否减少1000 ✅
|
||
- 地块是否显示为已开垦 ✅
|
||
- 是否显示成功提示 ✅
|
||
|
||
### 测试用例2:铲除作物UI更新
|
||
1. 玩家有1000金钱,地块有作物
|
||
2. 点击地块,选择铲除
|
||
3. 操作成功后检查:
|
||
- 金钱显示是否减少500 ✅
|
||
- 地块是否显示为空地 ✅
|
||
- 是否显示成功提示 ✅
|
||
|
||
### 测试用例3:操作失败时的UI状态
|
||
1. 玩家金钱不足
|
||
2. 尝试进行开垦或铲除操作
|
||
3. 检查:
|
||
- UI数据不应该改变 ✅
|
||
- 显示错误提示 ✅
|
||
- 操作被正确阻止 ✅
|
||
|
||
### 测试用例4:网络异常时的处理
|
||
1. 断开网络连接
|
||
2. 尝试进行操作
|
||
3. 检查:
|
||
- 显示网络错误提示 ✅
|
||
- UI状态保持不变 ✅
|
||
- 不发送无效请求 ✅
|
||
|
||
## 代码改进点
|
||
|
||
### 1. 统一的响应处理
|
||
所有游戏操作现在都有统一的响应处理机制:
|
||
- 成功时更新数据和UI
|
||
- 失败时显示错误信息
|
||
- 保持数据一致性
|
||
|
||
### 2. 改进的用户体验
|
||
- 添加了操作进行中的提示("正在开垦土地...")
|
||
- 提供了详细的错误信息
|
||
- 即时的UI反馈
|
||
|
||
### 3. 更好的错误处理
|
||
- 客户端预验证减少无效请求
|
||
- 网络错误的友好提示
|
||
- 服务器错误的正确显示
|
||
|
||
## 防止类似问题的建议
|
||
|
||
### 1. 代码审查检查点
|
||
- 新增操作类型时,确保在 `_handle_action_response` 中添加对应处理
|
||
- 检查所有UI更新是否通过统一的响应处理机制
|
||
- 验证客户端和服务器的数据同步
|
||
|
||
### 2. 测试覆盖
|
||
- 为每个新操作添加UI更新测试用例
|
||
- 测试成功和失败场景的UI表现
|
||
- 验证网络异常情况下的行为
|
||
|
||
### 3. 开发规范
|
||
- 所有游戏操作都应该通过服务器处理
|
||
- 客户端只做预验证和UI更新
|
||
- 保持数据流的一致性
|
||
|
||
## 总结
|
||
|
||
这个bug修复确保了:
|
||
- ✅ **数据一致性**:客户端UI与服务器数据保持同步
|
||
- ✅ **用户体验**:操作后立即看到结果反馈
|
||
- ✅ **错误处理**:完善的错误提示和状态管理
|
||
- ✅ **代码质量**:统一的响应处理机制
|
||
- ✅ **可维护性**:清晰的数据流和处理逻辑
|
||
|
||
通过这个修复,玩家在进行开垦和铲除操作时将获得与收获作物操作一致的流畅体验。 |