#!/usr/bin/env python # -*- coding: utf-8 -*- """ 特殊农场管理系统 作者: AI Assistant 功能: 管理特殊农场的自动种植和维护 """ import time import random import logging from datetime import datetime from SMYMongoDBAPI import SMYMongoDBAPI from bson import ObjectId #杂交农场666-种植杂交树1,杂交树2-每天0点种植 #花卉农场520-随机种植各种花卉-星期一,星期三,星期五,星期日零点种植 #瓜果农场333-随机种植各种瓜果-星期二,星期四,星期六零点种植 #小麦谷222-全屏种植小麦-每天0点种植 #稻香111-全屏种植稻谷-每天0点种植 #幸运农场888-随机种植1-80个幸运草和幸运花-星期一零点种植 class SpecialFarmManager: #初始化特殊农场管理器 def __init__(self, environment=None): """ 初始化特殊农场管理器 Args: environment: 环境类型,"test" 或 "production",如果为None则自动检测 """ # 如果没有指定环境,使用与TCPGameServer相同的环境检测逻辑 if environment is None: import os if os.path.exists('/.dockerenv') or os.environ.get('PRODUCTION', '').lower() == 'true': environment = "production" else: environment = "test" self.environment = environment self.mongo_api = SMYMongoDBAPI(environment) # 设置日志 logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler('special_farm.log', encoding='utf-8'), logging.StreamHandler() ] ) self.logger = logging.getLogger(__name__) # 特殊农场配置 self.special_farms = { "杂交农场": { "object_id": "689b4b9286cf953f2f4e56ee", "crops": ["杂交树1", "杂交树2"], "description": "专门种植杂交树的特殊农场" }, "花卉农场": { "object_id": "689bec6286cf953f2f4e56f1", "crops": ["郁金香", "牵牛花", "百合花", "栀子花", "玫瑰花", "向日葵", "藏红花", "幸运花"], "description": "盛产各种美丽花卉的特殊农场", "plant_type": "random_flowers" # 标记为随机花卉种植类型 }, "瓜果农场": { "object_id": "689bf73886cf953f2f4e56fa", "crops": ["西瓜", "南瓜", "哈密瓜", "葫芦", "黄瓜", "龙果", "菠萝", "芒果"], "description": "盛产各种瓜果的农场", "plant_type": "random_fruits" # 标记为随机瓜果种植类型 }, "小麦谷": { "object_id": "689bf9a886cf953f2f4e56fd", "crops": ["小麦"], "description": "盛产小麦的农场", "plant_type": "single_wheat" # 标记为单一小麦种植类型 }, "稻香": { "object_id": "689bf9ac86cf953f2f4e56fe", "crops": ["稻谷"], "description": "盛产稻谷的农场", "plant_type": "single_rice" # 标记为单一稻谷种植类型 }, "幸运农场": { "object_id": "689c027886cf953f2f4e56ff", "crops": ["幸运草", "幸运花"], "description": "盛产幸运草和幸运花的农场", "plant_type": "random_lucky" # 标记为随机幸运植物种植类型 } } self.logger.info(f"特殊农场管理器初始化完成 - 环境: {environment}") #获取作物系统数据 def get_crop_data(self): """ 获取作物配置数据 Returns: dict: 作物配置数据 """ try: crop_config = self.mongo_api.get_crop_data_config() if crop_config: # 移除MongoDB相关字段 if "_id" in crop_config: del crop_config["_id"] if "config_type" in crop_config: del crop_config["config_type"] if "updated_at" in crop_config: del crop_config["updated_at"] return crop_config else: self.logger.error("无法获取作物配置数据") return {} except Exception as e: self.logger.error(f"获取作物配置数据时出错: {str(e)}") return {} #通过文档ID获取农场数据 def get_player_data_by_object_id(self, object_id): """ 通过ObjectId获取玩家数据 Args: object_id: MongoDB文档ID Returns: dict: 玩家数据,如果未找到返回None """ try: collection = self.mongo_api.get_collection("playerdata") oid = ObjectId(object_id) player_data = collection.find_one({"_id": oid}) if player_data: self.logger.info(f"成功获取玩家数据: {player_data.get('玩家昵称', 'Unknown')}") return player_data else: self.logger.warning(f"未找到ObjectId为 {object_id} 的玩家数据") return None except Exception as e: self.logger.error(f"获取玩家数据时出错: {str(e)}") return None #通过文档ID保存农场数据 def save_player_data_by_object_id(self, object_id, player_data): """ 通过ObjectId保存玩家数据 Args: object_id: MongoDB文档ID player_data: 玩家数据 Returns: bool: 是否保存成功 """ try: collection = self.mongo_api.get_collection("playerdata") oid = ObjectId(object_id) # 更新最后登录时间 player_data["最后登录时间"] = datetime.now().strftime("%Y年%m月%d日%H时%M分%S秒") result = collection.replace_one({"_id": oid}, player_data) if result.acknowledged and result.matched_count > 0: self.logger.info(f"成功保存玩家数据: {player_data.get('玩家昵称', 'Unknown')}") return True else: self.logger.error(f"保存玩家数据失败: ObjectId {object_id}") return False except Exception as e: self.logger.error(f"保存玩家数据时出错: {str(e)}") return False #在指定农场种植作物 def plant_crops_in_farm(self, farm_name): """ 为指定特殊农场种植作物 Args: farm_name: 农场名称 Returns: bool: 是否种植成功 """ if farm_name not in self.special_farms: self.logger.error(f"未知的特殊农场: {farm_name}") return False farm_config = self.special_farms[farm_name] object_id = farm_config["object_id"] available_crops = farm_config["crops"] # 获取玩家数据 player_data = self.get_player_data_by_object_id(object_id) if not player_data: return False # 获取作物配置 crop_data = self.get_crop_data() if not crop_data: self.logger.error("无法获取作物配置,跳过种植") return False # 检查作物是否存在 for crop_name in available_crops: if crop_name not in crop_data: self.logger.error(f"作物 {crop_name} 不存在于作物配置中") return False # 获取农场土地 farm_lands = player_data.get("农场土地", []) if not farm_lands: self.logger.error(f"农场 {farm_name} 没有土地数据") return False planted_count = 0 plant_type = farm_config.get("plant_type", "normal") # 遍历所有土地,先开垦再种植作物 for i, land in enumerate(farm_lands): # 根据农场类型选择作物 if plant_type == "random_flowers": # 花卉农场:随机种植各种花卉,种满所有土地 crop_name = random.choice(available_crops) should_plant = True # 100%种植率,种满所有土地 elif plant_type == "random_fruits": # 瓜果农场:随机种植各种瓜果,种满所有土地 crop_name = random.choice(available_crops) should_plant = True # 100%种植率,种满所有土地 elif plant_type == "single_wheat": # 小麦谷:全屏种植小麦,种满所有土地 crop_name = "小麦" should_plant = True # 100%种植率,种满所有土地 elif plant_type == "single_rice": # 稻香:全屏种植稻谷,种满所有土地 crop_name = "稻谷" should_plant = True # 100%种植率,种满所有土地 elif plant_type == "random_lucky": # 幸运农场:随机种植1-80个幸运草和幸运花 crop_name = random.choice(available_crops) # 随机决定是否种植,确保总数在1-80之间 target_plants = random.randint(1, min(80, len(farm_lands))) should_plant = planted_count < target_plants else: # 普通农场:按原逻辑随机选择 crop_name = random.choice(available_crops) should_plant = True if should_plant: crop_info = crop_data[crop_name] # 更新土地数据(先开垦,再种植) land.update({ "is_diged": True, # 确保土地已开垦 "is_planted": True, "crop_type": crop_name, "grow_time": 0, # 立即成熟 "max_grow_time": crop_info.get("生长时间", 21600), "is_dead": False, "已浇水": True, "已施肥": True, "土地等级": 0 }) # 清除施肥时间戳 if "施肥时间" in land: del land["施肥时间"] planted_count += 1 else: # 留空的土地:只开垦不种植 land.update({ "is_diged": True, "is_planted": False, "crop_type": "", "grow_time": 0, "max_grow_time": 3, "is_dead": False, "已浇水": False, "已施肥": False, "土地等级": 0 }) # 清除施肥时间戳 if "施肥时间" in land: del land["施肥时间"] # 保存玩家数据 if self.save_player_data_by_object_id(object_id, player_data): self.logger.info(f"成功为 {farm_name} 种植了 {planted_count} 块土地的作物") return True else: self.logger.error(f"保存 {farm_name} 数据失败") return False #每日维护任务 def daily_maintenance(self): """ 每日维护任务 """ from datetime import datetime self.logger.info("开始执行特殊农场维护任务...") success_count = 0 total_farms = 0 current_time = datetime.now() current_weekday = current_time.weekday() # 0=Monday, 1=Tuesday, ..., 6=Sunday current_time_str = current_time.strftime("%Y-%m-%d %H:%M:%S") for farm_name in self.special_farms.keys(): # 检查农场是否需要在今天维护 should_maintain = True if farm_name == "瓜果农场": # 瓜果农场只在星期二(1)、四(3)、六(5)维护 if current_weekday not in [1, 3, 5]: should_maintain = False self.logger.info(f"瓜果农场今日({['周一','周二','周三','周四','周五','周六','周日'][current_weekday]})不需要维护") elif farm_name == "幸运农场": # 幸运农场只在星期一(0)维护 if current_weekday != 0: should_maintain = False self.logger.info(f"幸运农场今日({['周一','周二','周三','周四','周五','周六','周日'][current_weekday]})不需要维护") if should_maintain: total_farms += 1 try: if self.plant_crops_in_farm(farm_name): success_count += 1 self.logger.info(f"农场 {farm_name} 维护完成") # 更新维护时间记录 try: farm_config = self.special_farms[farm_name] object_id = farm_config["object_id"] player_data = self.get_player_data_by_object_id(object_id) if player_data: player_data["特殊农场最后维护时间"] = current_time_str self.save_player_data_by_object_id(object_id, player_data) except Exception as record_error: self.logger.error(f"更新 {farm_name} 维护时间记录失败: {str(record_error)}") else: self.logger.error(f"农场 {farm_name} 维护失败") except Exception as e: self.logger.error(f"维护农场 {farm_name} 时出错: {str(e)}") self.logger.info(f"维护任务完成: {success_count}/{total_farms} 个农场维护成功") #启动定时任务调度器(后台线程模式) def start_scheduler(self): """ 启动定时任务调度器(后台线程模式) """ import threading self.logger.info("特殊农场定时任务调度器已启动") self.logger.info("维护任务将在每天凌晨0点执行") # 检查是否需要立即执行维护任务 self._check_and_run_initial_maintenance() # 在后台线程中运行调度循环 def scheduler_loop(): last_maintenance_date = None while True: try: now = datetime.now() current_date = now.strftime("%Y-%m-%d") # 检查是否到了零点且今天还没有执行过维护 if (now.hour == 0 and now.minute == 0 and last_maintenance_date != current_date): self.logger.info("零点维护时间到,开始执行维护任务...") self.daily_maintenance() last_maintenance_date = current_date time.sleep(60) # 每分钟检查一次 except Exception as e: self.logger.error(f"调度器运行时出错: {str(e)}") time.sleep(60) # 启动后台线程 scheduler_thread = threading.Thread(target=scheduler_loop, daemon=True) scheduler_thread.start() self.logger.info("特殊农场调度器已在后台线程启动") #检查是否需要执行初始维护任务 def _check_and_run_initial_maintenance(self): """ 检查是否需要执行初始维护任务 避免服务器重启时重复执行 """ try: from datetime import datetime, timedelta # 检查今天是否已经执行过维护任务 current_time = datetime.now() today = current_time.strftime("%Y-%m-%d") current_weekday = current_time.weekday() # 0=Monday, 1=Tuesday, ..., 6=Sunday # 获取特殊农场数据,检查最后维护时间 for farm_name, farm_config in self.special_farms.items(): object_id = farm_config["object_id"] player_data = self.get_player_data_by_object_id(object_id) # 检查农场是否需要在今天维护 should_maintain = True if farm_name == "瓜果农场": # 瓜果农场只在星期二(1)、四(3)、六(5)维护 if current_weekday not in [1, 3, 5]: should_maintain = False self.logger.info(f"瓜果农场今日({['周一','周二','周三','周四','周五','周六','周日'][current_weekday]})不需要维护") elif farm_name == "幸运农场": # 幸运农场只在星期一(0)维护 if current_weekday != 0: should_maintain = False self.logger.info(f"幸运农场今日({['周一','周二','周三','周四','周五','周六','周日'][current_weekday]})不需要维护") if should_maintain and player_data: last_maintenance = player_data.get("特殊农场最后维护时间", "") # 如果今天还没有维护过,则执行维护 if not last_maintenance or not last_maintenance.startswith(today): self.logger.info(f"检测到 {farm_name} 今日尚未维护,执行维护任务...") if self.plant_crops_in_farm(farm_name): # 更新维护时间记录 player_data["特殊农场最后维护时间"] = current_time.strftime("%Y-%m-%d %H:%M:%S") self.save_player_data_by_object_id(object_id, player_data) else: self.logger.info(f"{farm_name} 今日已维护过,跳过初始维护") except Exception as e: self.logger.error(f"检查初始维护任务时出错: {str(e)}") # 如果检查失败,执行一次维护作为备用 self.logger.info("执行备用维护任务...") self.daily_maintenance() #停止定时任务调度器 def stop_scheduler(self): """ 停止定时任务调度器 """ try: # 设置停止标志(如果需要的话) self.logger.info("特殊农场定时任务调度器已停止") except Exception as e: self.logger.error(f"停止定时任务调度器时出错: {str(e)}") #手动执行维护任务 def manual_maintenance(self, farm_name=None): """ 手动执行维护任务 Args: farm_name: 指定农场名称,如果为None则维护所有农场 """ if farm_name: if farm_name in self.special_farms: self.logger.info(f"手动维护农场: {farm_name}") return self.plant_crops_in_farm(farm_name) else: self.logger.error(f"未知的农场名称: {farm_name}") return False else: self.logger.info("手动维护所有特殊农场") self.daily_maintenance() return True def main(): """ 主函数 """ import sys # 检查命令行参数 environment = "production" if len(sys.argv) > 1: if sys.argv[1] in ["test", "production"]: environment = sys.argv[1] else: print("使用方法: python SpecialFarm.py [test|production]") sys.exit(1) # 创建特殊农场管理器 manager = SpecialFarmManager(environment) # 检查是否为手动模式 if len(sys.argv) > 2 and sys.argv[2] == "manual": # 手动执行维护 farm_name = sys.argv[3] if len(sys.argv) > 3 else None manager.manual_maintenance(farm_name) else: # 启动定时任务 manager.start_scheduler() if __name__ == "__main__": main()