184 lines
6.3 KiB
Markdown
184 lines
6.3 KiB
Markdown
# Bug修复:访客模式下最后登录时间错误更新
|
||
|
||
## 问题描述
|
||
|
||
在原始代码中,当玩家处于访客模式访问其他玩家的农场时,被访问玩家的最后登录时间会被意外更新。这是一个严重的数据完整性问题,因为:
|
||
|
||
1. **数据不准确**:被访问玩家实际上没有登录,但最后登录时间被更新了
|
||
2. **逻辑错误**:只有玩家真正登录时,最后登录时间才应该被更新
|
||
3. **影响统计**:这会影响玩家活跃度统计和排行榜数据的准确性
|
||
|
||
## 问题根源
|
||
|
||
### 原始问题代码
|
||
|
||
```python
|
||
def update_crops_growth(self):
|
||
"""更新所有玩家的作物生长状态"""
|
||
# 获取所有玩家存档文件
|
||
save_files = glob.glob(os.path.join("game_saves", "*.json"))
|
||
|
||
for save_file in save_files:
|
||
try:
|
||
# 从文件名提取账号ID
|
||
account_id = os.path.basename(save_file).split('.')[0]
|
||
|
||
# 加载玩家数据
|
||
player_data = self.load_player_data(account_id)
|
||
# ... 更新作物生长状态 ...
|
||
|
||
# 如果有作物更新,保存玩家数据
|
||
if growth_updated:
|
||
self.save_player_data(account_id, player_data) # 问题在这里!
|
||
```
|
||
|
||
**问题分析:**
|
||
- 系统遍历所有玩家存档文件,包括离线玩家
|
||
- 当保存玩家数据时,可能会触发其他逻辑更新最后登录时间
|
||
- 访客模式下,被访问玩家的数据被加载和保存,导致时间戳更新
|
||
|
||
## 修复方案
|
||
|
||
### 1. 只更新在线玩家的作物生长状态
|
||
|
||
```python
|
||
def update_crops_growth(self):
|
||
"""更新所有玩家的作物生长状态"""
|
||
# 只更新在线玩家的作物生长状态,避免影响离线玩家的数据
|
||
for client_id, user_info in self.user_data.items():
|
||
if not user_info.get("logged_in", False):
|
||
continue
|
||
|
||
username = user_info.get("username")
|
||
if not username:
|
||
continue
|
||
|
||
try:
|
||
# 加载玩家数据
|
||
player_data = self.load_player_data(username)
|
||
# ... 更新作物生长状态 ...
|
||
|
||
# 如果有作物更新,保存玩家数据
|
||
if growth_updated:
|
||
self.save_player_data(username, player_data)
|
||
```
|
||
|
||
**修复要点:**
|
||
- ✅ 只遍历在线玩家(`self.user_data`)
|
||
- ✅ 检查玩家登录状态(`logged_in: True`)
|
||
- ✅ 避免处理离线玩家的数据
|
||
|
||
### 2. 优化访客模式的数据推送
|
||
|
||
```python
|
||
def _push_crop_update_to_player(self, account_id, player_data):
|
||
# ... 现有代码 ...
|
||
|
||
if visiting_mode and visiting_target:
|
||
# 如果处于访问模式,发送被访问玩家的更新数据
|
||
# 注意:这里只读取数据,不修改被访问玩家的数据
|
||
target_player_data = self.load_player_data(visiting_target)
|
||
if target_player_data:
|
||
# 检查被访问玩家是否也在线
|
||
target_client_id = None
|
||
for cid, user_info in self.user_data.items():
|
||
if user_info.get("username") == visiting_target and user_info.get("logged_in", False):
|
||
target_client_id = cid
|
||
break
|
||
|
||
update_message = {
|
||
"type": "crop_update",
|
||
"farm_lots": target_player_data.get("farm_lots", []),
|
||
"timestamp": time.time(),
|
||
"is_visiting": True,
|
||
"visited_player": visiting_target,
|
||
"target_online": target_client_id is not None # 新增:标记被访问玩家是否在线
|
||
}
|
||
```
|
||
|
||
**优化要点:**
|
||
- ✅ 明确标注只读取数据,不修改
|
||
- ✅ 检查被访问玩家是否在线
|
||
- ✅ 提供在线状态信息给客户端
|
||
|
||
## 修复效果
|
||
|
||
### 修复前的问题
|
||
1. **错误场景**:
|
||
- 玩家A访问玩家B的农场
|
||
- 系统更新所有玩家的作物生长状态
|
||
- 玩家B的数据被加载、修改、保存
|
||
- 玩家B的最后登录时间被意外更新
|
||
|
||
2. **数据污染**:
|
||
```
|
||
玩家B实际最后登录:2024-01-01 10:00:00
|
||
被访问后错误更新为:2024-01-02 15:30:00 ❌ 错误!
|
||
```
|
||
|
||
### 修复后的正确行为
|
||
1. **正确场景**:
|
||
- 玩家A访问玩家B的农场
|
||
- 系统只更新在线玩家(玩家A)的作物生长状态
|
||
- 玩家B的数据只被读取,不被修改
|
||
- 玩家B的最后登录时间保持不变
|
||
|
||
2. **数据准确**:
|
||
```
|
||
玩家B实际最后登录:2024-01-01 10:00:00
|
||
访问后仍然保持:2024-01-01 10:00:00 ✅ 正确!
|
||
```
|
||
|
||
## 测试验证
|
||
|
||
### 测试用例1:访客模式数据完整性
|
||
1. 玩家A登录游戏
|
||
2. 玩家A访问离线玩家B的农场
|
||
3. 等待作物生长更新周期
|
||
4. 检查玩家B的最后登录时间是否保持不变
|
||
|
||
**预期结果**:玩家B的最后登录时间不应该改变
|
||
|
||
### 测试用例2:在线玩家正常更新
|
||
1. 玩家A和玩家B都在线
|
||
2. 玩家A访问玩家B的农场
|
||
3. 等待作物生长更新周期
|
||
4. 检查两个玩家的作物是否正常生长
|
||
|
||
**预期结果**:两个玩家的作物都应该正常生长
|
||
|
||
### 测试用例3:离线玩家数据保护
|
||
1. 确保有离线玩家的存档文件
|
||
2. 在线玩家进行游戏操作
|
||
3. 检查离线玩家的数据是否被意外修改
|
||
|
||
**预期结果**:离线玩家的数据应该保持不变
|
||
|
||
## 代码审查要点
|
||
|
||
在未来的开发中,需要注意以下几点:
|
||
|
||
1. **数据修改原则**:
|
||
- 只修改当前在线玩家的数据
|
||
- 访问其他玩家数据时,优先使用只读操作
|
||
- 避免在定时任务中修改离线玩家数据
|
||
|
||
2. **时间戳更新**:
|
||
- 最后登录时间只在真正登录时更新
|
||
- 避免在数据保存时自动更新时间戳
|
||
- 区分数据修改和时间戳更新的逻辑
|
||
|
||
3. **访客模式处理**:
|
||
- 明确区分访客模式和正常模式
|
||
- 访客模式下只读取数据,不修改
|
||
- 提供足够的状态信息给客户端
|
||
|
||
## 总结
|
||
|
||
这个bug修复确保了:
|
||
- ✅ 数据完整性:只有真正登录的玩家才会更新最后登录时间
|
||
- ✅ 性能优化:只处理在线玩家的数据,减少不必要的文件操作
|
||
- ✅ 逻辑正确:访客模式下不会影响被访问玩家的数据
|
||
- ✅ 可维护性:代码逻辑更清晰,易于理解和维护
|
||
|
||
通过这个修复,游戏的数据统计将更加准确,玩家的隐私和数据完整性得到更好的保护。 |