Files
Sprout-Farm/Server/BugFix_VisitorMode_LastLoginTime.md

184 lines
6.3 KiB
Markdown
Raw 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.
# 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修复确保了
- ✅ 数据完整性:只有真正登录的玩家才会更新最后登录时间
- ✅ 性能优化:只处理在线玩家的数据,减少不必要的文件操作
- ✅ 逻辑正确:访客模式下不会影响被访问玩家的数据
- ✅ 可维护性:代码逻辑更清晰,易于理解和维护
通过这个修复,游戏的数据统计将更加准确,玩家的隐私和数据完整性得到更好的保护。