Files
Sprout-Farm/Server/BugFix_VisitorMode_LastLoginTime.md

6.3 KiB
Raw Blame History

Bug修复访客模式下最后登录时间错误更新

问题描述

在原始代码中,当玩家处于访客模式访问其他玩家的农场时,被访问玩家的最后登录时间会被意外更新。这是一个严重的数据完整性问题,因为:

  1. 数据不准确:被访问玩家实际上没有登录,但最后登录时间被更新了
  2. 逻辑错误:只有玩家真正登录时,最后登录时间才应该被更新
  3. 影响统计:这会影响玩家活跃度统计和排行榜数据的准确性

问题根源

原始问题代码

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. 只更新在线玩家的作物生长状态

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. 优化访客模式的数据推送

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修复确保了

  • 数据完整性:只有真正登录的玩家才会更新最后登录时间
  • 性能优化:只处理在线玩家的数据,减少不必要的文件操作
  • 逻辑正确:访客模式下不会影响被访问玩家的数据
  • 可维护性:代码逻辑更清晰,易于理解和维护

通过这个修复,游戏的数据统计将更加准确,玩家的隐私和数据完整性得到更好的保护。