更新三个按钮 修了一堆bug

This commit is contained in:
2025-05-27 19:53:17 +08:00
parent 8215cfa3ee
commit 94f09b8dd9
47 changed files with 10303 additions and 3085 deletions

View File

@@ -0,0 +1,277 @@
# 铲除作物功能实现
## 功能概述
实现了玩家可以花费500金钱铲除地块上的作物将地块变成空地的功能。这个功能完全基于服务器端处理确保数据的一致性和安全性。
## 功能特点
- **费用固定**铲除任何作物都需要花费500金钱
- **服务器验证**:所有验证和处理都在服务器端完成
- **状态重置**:铲除后地块变成空地,可以重新种植
- **访客保护**:访客模式下无法进行铲除操作
- **实时更新**:操作完成后立即更新客户端显示
## 实现架构
### 1. 服务器端实现
#### 消息路由
```python
elif message_type == "remove_crop":
return self._handle_remove_crop(client_id, message)
```
#### 主处理方法
```python
def _handle_remove_crop(self, client_id, message):
"""处理铲除作物请求"""
# 检查用户是否已登录
logged_in, response = self._check_user_logged_in(client_id, "铲除作物", "remove_crop")
if not logged_in:
return self.send_data(client_id, response)
# 获取玩家数据
player_data, username, response = self._load_player_data_with_check(client_id, "remove_crop")
if not player_data:
return self.send_data(client_id, response)
lot_index = message.get("lot_index", -1)
# 验证地块索引
if lot_index < 0 or lot_index >= len(player_data.get("farm_lots", [])):
return self._send_action_error(client_id, "remove_crop", "无效的地块索引")
lot = player_data["farm_lots"][lot_index]
# 检查地块状态
if not lot.get("is_planted", False) or not lot.get("crop_type", ""):
return self._send_action_error(client_id, "remove_crop", "此地块没有种植作物")
# 处理铲除
return self._process_crop_removal(client_id, player_data, username, lot, lot_index)
```
#### 铲除处理逻辑
```python
def _process_crop_removal(self, client_id, player_data, username, lot, lot_index):
"""处理铲除作物逻辑"""
# 铲除费用
removal_cost = 500
# 检查玩家金钱是否足够
if player_data["money"] < removal_cost:
return self._send_action_error(client_id, "remove_crop", f"金钱不足,铲除作物需要 {removal_cost} 金钱")
# 获取作物名称用于日志
crop_type = lot.get("crop_type", "未知作物")
# 执行铲除操作
player_data["money"] -= removal_cost
lot["is_planted"] = False
lot["crop_type"] = ""
lot["grow_time"] = 0
lot["is_dead"] = False # 重置死亡状态
# 保存玩家数据
self.save_player_data(username, player_data)
# 发送作物更新
self._push_crop_update_to_player(username, player_data)
self.log('INFO', f"玩家 {username} 铲除了地块 {lot_index} 的作物 {crop_type},花费 {removal_cost} 金钱", 'SERVER')
return self.send_data(client_id, {
"type": "action_response",
"action_type": "remove_crop",
"success": True,
"message": f"成功铲除作物 {crop_type},花费 {removal_cost} 金钱",
"updated_data": {
"money": player_data["money"],
"farm_lots": player_data["farm_lots"]
}
})
```
### 2. 网络通信
#### 客户端发送请求
```gdscript
#发送铲除作物信息
func sendRemoveCrop(lot_index):
if not client.is_client_connected():
return false
client.send_data({
"type": "remove_crop",
"lot_index": lot_index,
"timestamp": Time.get_unix_time_from_system()
})
return true
```
### 3. 客户端UI实现
#### 按钮文本更新
```gdscript
# 更新按钮文本
func _update_button_texts():
dig_button.text = "开垦"+"\n花费:"+str(main_game.dig_money)
remove_button.text = "铲除"+"\n花费500"
```
#### 铲除操作处理
```gdscript
#铲除
func _on_remove_button_pressed():
# 检查是否处于访问模式
if main_game.is_visiting_mode:
Toast.show("访问模式下无法铲除作物", Color.ORANGE, 2.0, 1.0)
self.hide()
return
# 检查玩家金钱是否足够
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
# 发送铲除作物请求到服务器
if network_manager and network_manager.is_connected_to_server():
if network_manager.sendRemoveCrop(selected_lot_index):
Toast.show("正在铲除作物...", Color.YELLOW, 1.5, 1.0)
self.hide()
else:
Toast.show("发送铲除请求失败", Color.RED, 2.0, 1.0)
self.hide()
else:
Toast.show("网络未连接,无法铲除作物", Color.RED, 2.0, 1.0)
self.hide()
```
## 验证机制
### 服务器端验证
1. **用户登录验证**:确保用户已登录
2. **地块索引验证**:检查地块索引是否有效
3. **地块状态验证**:确保地块有作物可以铲除
4. **金钱验证**:检查玩家金钱是否足够支付铲除费用
### 客户端预验证
1. **访问模式检查**:访客模式下禁止操作
2. **金钱预检查**:提前检查金钱是否足够
3. **地块状态预检查**:确保地块有作物
4. **网络连接检查**:确保能够发送请求
## 操作流程
### 正常流程
1. 玩家点击地块,显示操作面板
2. 面板显示铲除按钮和费用信息
3. 玩家点击铲除按钮
4. 客户端进行预验证
5. 发送铲除请求到服务器
6. 服务器验证并处理请求
7. 服务器返回操作结果
8. 客户端更新UI显示
### 错误处理
- **金钱不足**:显示错误提示,不发送请求
- **无作物**:显示提示信息,不发送请求
- **访客模式**:显示权限提示,不发送请求
- **网络错误**:显示网络错误提示
- **服务器错误**:显示服务器返回的错误信息
## 数据更新
### 地块状态重置
```python
lot["is_planted"] = False # 取消种植状态
lot["crop_type"] = "" # 清空作物类型
lot["grow_time"] = 0 # 重置生长时间
lot["is_dead"] = False # 重置死亡状态
```
### 玩家数据更新
```python
player_data["money"] -= removal_cost # 扣除金钱
```
### 实时同步
- 服务器保存玩家数据到文件
- 推送作物更新到客户端
- 客户端接收并更新UI显示
## 使用场景
1. **清理死亡作物**:当作物死亡时,玩家可以花费金钱清理
2. **重新规划农场**:玩家想要种植不同作物时
3. **紧急处理**:当玩家需要快速清理地块时
4. **策略调整**:根据市场需求调整种植策略
## 安全考虑
1. **服务器权威**:所有验证和处理都在服务器端
2. **数据一致性**:确保客户端和服务器数据同步
3. **防作弊**:客户端无法直接修改游戏数据
4. **访问控制**:访客模式下无法进行破坏性操作
## 扩展性
该功能设计具有良好的扩展性:
1. **费用可配置**:可以根据作物类型设置不同的铲除费用
2. **条件扩展**:可以添加更多的铲除条件(如等级要求)
3. **奖励机制**:可以在铲除时给予部分资源回收
4. **工具系统**:可以引入铲子等工具来影响铲除效果
## 测试用例
### 测试用例1正常铲除
1. 玩家有足够金钱≥500
2. 地块有作物
3. 点击铲除按钮
4. 验证金钱减少500地块变成空地
### 测试用例2金钱不足
1. 玩家金钱不足(<500
2. 地块有作物
3. 点击铲除按钮
4. 验证:显示金钱不足提示,操作失败
### 测试用例3无作物地块
1. 玩家有足够金钱
2. 地块为空地
3. 点击铲除按钮
4. 验证:显示无作物提示,操作失败
### 测试用例4访客模式
1. 玩家处于访客模式
2. 点击铲除按钮
3. 验证:显示权限提示,操作失败
### 测试用例5网络断开
1. 网络连接断开
2. 点击铲除按钮
3. 验证:显示网络错误提示,操作失败
## 总结
铲除作物功能的实现遵循了以下设计原则:
-**服务器权威**:所有关键逻辑在服务器端处理
-**用户体验**:提供清晰的费用信息和操作反馈
-**数据安全**:多层验证确保数据完整性
-**错误处理**:完善的错误提示和处理机制
-**代码复用**:利用现有的验证和处理框架
-**可维护性**:清晰的代码结构和文档
这个功能为玩家提供了更灵活的农场管理选项,同时保持了游戏的平衡性和数据安全性。