From f0e41e32585caedc344b639c5f32df9b88d3f58b Mon Sep 17 00:00:00 2001 From: Naruse <71993948+DevilProMT@users.noreply.github.com> Date: Wed, 16 Apr 2025 16:25:31 +0800 Subject: [PATCH] Refactor battle & fix name for avatar_manager --- .gitignore | 1 + database/avatar/avatar_data.py | 6 +- game_server/game/battle/battle_manager.py | 80 +++++++++++++++++++ game_server/game/chat/command/giveall.py | 4 +- game_server/game/player/player_manager.py | 19 +++-- game_server/game/scene/scene_manager.py | 2 - game_server/handlers/DressAvatarCsReq.py | 4 +- game_server/handlers/DressRelicAvatarCsReq.py | 4 +- game_server/handlers/GetAvatarDataCsReq.py | 2 +- game_server/handlers/PVEBattleResultCsReq.py | 36 +++++---- game_server/handlers/SceneCastSkillCsReq.py | 51 +----------- 11 files changed, 127 insertions(+), 82 deletions(-) create mode 100644 game_server/game/battle/battle_manager.py diff --git a/.gitignore b/.gitignore index 1101c87..5f9b142 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ __pycache__/ /proto .idea/ /logs +Config.json diff --git a/database/avatar/avatar_data.py b/database/avatar/avatar_data.py index f83d262..f64c5e6 100644 --- a/database/avatar/avatar_data.py +++ b/database/avatar/avatar_data.py @@ -72,10 +72,10 @@ class AvatarData(BaseDatabaseData): has_taken_promotion_reward_list=[1,2,3,4,5,6], ) - def ToBattleProto(self,index,session): + def ToBattleProto(self,index,player): get_equipment = None if self.lightcone_id > 0: - get_equipment = session.player.inventory_manager.get(self.lightcone_id) + get_equipment = player.inventory_manager.get(self.lightcone_id) return BattleAvatar( id=self.avatar_id, @@ -105,7 +105,7 @@ class AvatarData(BaseDatabaseData): ) ], relic_list = [ - session.player.inventory_manager.get(relic_id).RelicBattleProto() + player.inventory_manager.get(relic_id).RelicBattleProto() for type, relic_id in self.relic_ids.items() if relic_id > 0 ] diff --git a/game_server/game/battle/battle_manager.py b/game_server/game/battle/battle_manager.py new file mode 100644 index 0000000..c100045 --- /dev/null +++ b/game_server/game/battle/battle_manager.py @@ -0,0 +1,80 @@ +import numpy as np +from game_server.resource.configdb.stage_config import StageConfig +from game_server.resource import ResourceManager +from rail_proto.lib import ( + BattleEndStatus, + PVEBattleResultCsReq, + SceneCastSkillCsReq, + SceneCastSkillScRsp, + SceneBattleInfo, + SceneMonsterWave, + SceneMonster, + SceneEntityInfo +) + +class BattleManager: + def __init__(self, player): + self.player = player + self.player.next_battle_id += 1 + self.battle_id: int = self.player.next_battle_id + self.round_limit: int = 0 + self.stage_id: int = 0 + self.battle_end_status: BattleEndStatus = BattleEndStatus.BATTLE_END_NONE + + # list & dict + self.stages: list[StageConfig] = [] + self.entity_monster: list[SceneEntityInfo] = [] + #self.buffs: list[MazeBuff] = [] + self.battle_result: PVEBattleResultCsReq | None = None + + + def GetBattleLineup(self): + return [ + self.player.avatar_manager.get(avatar_id).ToBattleProto(index,self.player) + for index, avatar_id in enumerate(self.player.lineup_manager.get(self.player.data.cur_lineup, None).avatar_list) + ] + + def GetBattleMonster(self): + return [ + SceneMonsterWave( + battle_stage_id=monster_list.StageID, + battle_wave_id=index, + monster_list=[ + SceneMonster( + monster_id=id + ) + for monster_dict in monster_list.MonsterList + for monster, id in monster_dict.items() + if id > 0 + ] + ) + for index, monster_list in enumerate(self.stages) + ] + + def EnterBattle(self, msg: SceneCastSkillCsReq, targets: list[int]) -> SceneCastSkillScRsp: + self.stages: list[StageConfig] = [] + for entity_id in targets: + entity_data = self.player.scene_manager.entities.get(entity_id) + if entity_data: + stage = ResourceManager.instance().find_by_index(StageConfig, entity_data.npc_monster.event_id * 10) + if not stage: + stage = ResourceManager.instance().find_by_index(StageConfig, entity_data.npc_monster.event_id) + if stage: + self.stages.append(stage) + self.entity_monster.append(entity_data) + if self.stages: + self.stage_id = self.stages[0].StageID + return SceneCastSkillScRsp( + retcode=0, + cast_entity_id=msg.cast_entity_id, + battle_info=SceneBattleInfo( + rounds_limit=self.round_limit, + world_level=self.player.data.world_level, + logic_random_seed=np.random.randint(1, np.iinfo(np.int32).max, dtype=np.int32), + stage_id=self.stage_id, + battle_id=self.battle_id, + battle_avatar_list=self.GetBattleLineup(), + monster_wave_list=self.GetBattleMonster() + ) + ) + return SceneCastSkillScRsp() \ No newline at end of file diff --git a/game_server/game/chat/command/giveall.py b/game_server/game/chat/command/giveall.py index 121f9eb..a63ad0e 100644 --- a/game_server/game/chat/command/giveall.py +++ b/game_server/game/chat/command/giveall.py @@ -17,11 +17,11 @@ async def execute(session:PlayerSession, text): for avatar in avatars: if avatar.AvatarID == 1224 or avatar.AvatarID >= 7000: continue - if session.player.avatar_mananger.get(avatar.AvatarID): + if session.player.avatar_manager.get(avatar.AvatarID): continue data = session.player.add_avatar(avatar.AvatarID) if data: - session.player.avatar_mananger[data.avatar_id] = data + session.player.avatar_manager[data.avatar_id] = data sync = True if text == "lightcones": diff --git a/game_server/game/player/player_manager.py b/game_server/game/player/player_manager.py index 7f77c4e..9fc1468 100644 --- a/game_server/game/player/player_manager.py +++ b/game_server/game/player/player_manager.py @@ -3,6 +3,7 @@ from database.player.player_data import PlayerData,players_collection from database.avatar.avatar_data import AvatarData,get_all_avatars_by_uid,avatars_collection from database.lineup.lineup_data import LineupData,get_all_lineup_by_uid,lineups_collection from database.inventory.inventory_data import InventoryData,get_all_items_by_uid,items_collection +from game_server.game.battle.battle_manager import BattleManager from game_server.game.scene.scene_manager import SceneManager from typing import Optional from rail_proto.lib import ( @@ -14,11 +15,17 @@ from utils.logger import Error class PlayerManager(BaseModel): + class Config: + arbitrary_types_allowed = True + data : PlayerData = PlayerData() - avatar_mananger: dict[int,AvatarData] = {} + avatar_manager: dict[int,AvatarData] = {} lineup_manager: dict[int,LineupData] = {} inventory_manager: dict[int,InventoryData] = {} scene_manager: SceneManager = None + battle_manager: BattleManager = None + + next_battle_id: int = 0 def init_default(self): self.add_all_avatars() @@ -41,10 +48,10 @@ class PlayerManager(BaseModel): uid=self.data.uid, avatar_id=self.data.cur_basic_type ).add_avatar() - self.avatar_mananger[self.data.cur_basic_type] = avatar + self.avatar_manager[self.data.cur_basic_type] = avatar for avatar in avatars: - self.avatar_mananger[avatar.avatar_id] = avatar + self.avatar_manager[avatar.avatar_id] = avatar def add_all_lineups(self): lineups = get_all_lineup_by_uid(uid=self.data.uid) @@ -65,7 +72,7 @@ class PlayerManager(BaseModel): self.inventory_manager[item.unique_id] = item def add_avatar(self,avatar_id:int) -> Optional[AvatarData]: - avatar = self.avatar_mananger.get(avatar_id) + avatar = self.avatar_manager.get(avatar_id) if avatar: return None @@ -106,7 +113,7 @@ class PlayerManager(BaseModel): def PlayerSyncProto(self) -> PlayerSyncScNotify: avatars = [] - for avatar_id,avatar in self.avatar_mananger.items(): + for avatar_id,avatar in self.avatar_manager.items(): avatars.append(avatar.ToProto()) lightcones = [] @@ -139,7 +146,7 @@ class PlayerManager(BaseModel): def save_all_avatars_bulk(self): operations = [] - for avatar in self.avatar_mananger.values(): + for avatar in self.avatar_manager.values(): avatar_data = avatar.model_dump() avatar_data["uid"] = avatar.uid query = {"uid": avatar.uid, "avatar_id": avatar.avatar_id} diff --git a/game_server/game/scene/scene_manager.py b/game_server/game/scene/scene_manager.py index c5f52b1..b3a3808 100644 --- a/game_server/game/scene/scene_manager.py +++ b/game_server/game/scene/scene_manager.py @@ -5,7 +5,6 @@ from game_server.resource.configdb.maze_plane import MazePlaneData from game_server.resource.configdb.map_entrance import MapEntranceData from game_server.game.motion.motion_info import Motion from rail_proto.lib import ( - SceneEntityGroupInfo, SceneInfo, SceneEntityInfo, SceneEntityGroupInfo, @@ -25,7 +24,6 @@ class SceneManager(BaseModel): teleport_id: int = 0 entity_group_list: list[SceneEntityGroupInfo] = [] entities: dict[int,SceneEntityInfo] = {} - battle_monster: list[SceneEntityInfo] = [] def ToProto(self,session) -> SceneInfo: prop_entity_id = 10 diff --git a/game_server/handlers/DressAvatarCsReq.py b/game_server/handlers/DressAvatarCsReq.py index 999b269..0981540 100644 --- a/game_server/handlers/DressAvatarCsReq.py +++ b/game_server/handlers/DressAvatarCsReq.py @@ -7,12 +7,12 @@ from rail_proto.lib import ( async def handle(session: PlayerSession, msg: DressAvatarCsReq) -> betterproto.Message: equipment = session.player.inventory_manager.get(msg.equipment_unique_id) - target_avatar = session.player.avatar_mananger.get(msg.avatar_id) + target_avatar = session.player.avatar_manager.get(msg.avatar_id) if not equipment or not target_avatar: return DressAvatarScRsp() - previous_avatar = session.player.avatar_mananger.get(equipment.equip_avatar) + previous_avatar = session.player.avatar_manager.get(equipment.equip_avatar) if previous_avatar: if previous_avatar.lightcone_id > 0 and target_avatar.lightcone_id > 0: target_equipment = session.player.inventory_manager.get(target_avatar.lightcone_id) diff --git a/game_server/handlers/DressRelicAvatarCsReq.py b/game_server/handlers/DressRelicAvatarCsReq.py index 11658d8..faf8bcb 100644 --- a/game_server/handlers/DressRelicAvatarCsReq.py +++ b/game_server/handlers/DressRelicAvatarCsReq.py @@ -6,7 +6,7 @@ from rail_proto.lib import ( ) async def handle(session: PlayerSession, msg: DressRelicAvatarCsReq) -> betterproto.Message: - target_avatar = session.player.avatar_mananger.get(msg.avatar_id) + target_avatar = session.player.avatar_manager.get(msg.avatar_id) if not target_avatar: return DressRelicAvatarScRsp() @@ -17,7 +17,7 @@ async def handle(session: PlayerSession, msg: DressRelicAvatarCsReq) -> betterpr relic_sub_type = str(relic.sub_type) current_relic_id = target_avatar.relic_ids.get(relic_sub_type, 0) - previous_avatar = session.player.avatar_mananger.get(relic.equip_avatar) + previous_avatar = session.player.avatar_manager.get(relic.equip_avatar) if previous_avatar: previous_relic_id = previous_avatar.relic_ids.get(relic_sub_type, 0) diff --git a/game_server/handlers/GetAvatarDataCsReq.py b/game_server/handlers/GetAvatarDataCsReq.py index 069fc04..caf3e99 100644 --- a/game_server/handlers/GetAvatarDataCsReq.py +++ b/game_server/handlers/GetAvatarDataCsReq.py @@ -8,7 +8,7 @@ from rail_proto.lib import ( async def handle(session: PlayerSession, msg: GetAvatarDataCsReq) -> betterproto.Message: avatars: list[Avatar] = [] - for avatar_id,avatar in session.player.avatar_mananger.items(): + for avatar_id,avatar in session.player.avatar_manager.items(): avatars.append(avatar.ToProto()) return GetAvatarDataScRsp( retcode=0, diff --git a/game_server/handlers/PVEBattleResultCsReq.py b/game_server/handlers/PVEBattleResultCsReq.py index 974dee8..0d3c24b 100644 --- a/game_server/handlers/PVEBattleResultCsReq.py +++ b/game_server/handlers/PVEBattleResultCsReq.py @@ -12,24 +12,26 @@ from rail_proto.lib import ( async def handle(session: PlayerSession, msg: PVEBattleResultCsReq) -> betterproto.Message: if msg.end_status == BattleEndStatus.BATTLE_END_WIN.value: - await session.notify( - SceneGroupRefreshScNotify( - group_refresh_list=[ - GroupRefreshInfo( - refresh_type=SceneGroupRefreshType.SCENE_GROUP_REFRESH_TYPE_LOADED.value, - refresh_entity=[ - SceneEntityRefreshInfo( - delete_entity=monster.entity_id - ) - ], - group_id=monster.group_id - ) for monster in session.player.scene_manager.battle_monster - ], - floor_id=session.player.data.floor_id + if session.player.battle_manager: + await session.notify( + SceneGroupRefreshScNotify( + group_refresh_list=[ + GroupRefreshInfo( + refresh_type=SceneGroupRefreshType.SCENE_GROUP_REFRESH_TYPE_LOADED.value, + refresh_entity=[ + SceneEntityRefreshInfo( + delete_entity=monster.entity_id + ) + ], + group_id=monster.group_id + ) for monster in session.player.battle_manager.entity_monster + ], + floor_id=session.player.data.floor_id + ) ) - ) - for monster in session.player.scene_manager.battle_monster: - session.player.scene_manager.entities.pop(monster.entity_id, None) + for monster in session.player.battle_manager.entity_monster: + session.player.scene_manager.entities.pop(monster.entity_id, None) + session.player.battle_manager = None return PVEBattleResultScRsp( retcode=0, end_status=msg.end_status, diff --git a/game_server/handlers/SceneCastSkillCsReq.py b/game_server/handlers/SceneCastSkillCsReq.py index f7efbb7..91fdd1b 100644 --- a/game_server/handlers/SceneCastSkillCsReq.py +++ b/game_server/handlers/SceneCastSkillCsReq.py @@ -1,15 +1,11 @@ import betterproto from game_server.net.session import PlayerSession -from game_server.resource import ResourceManager -from game_server.resource.configdb.stage_config import StageConfig +from game_server.game.battle.battle_manager import BattleManager from rail_proto.lib import ( SceneCastSkillCsReq, SceneCastSkillScRsp, - SceneBattleInfo, - SceneMonsterWave, - SceneMonster ) -import numpy as np + async def handle(session: PlayerSession, msg: SceneCastSkillCsReq) -> betterproto.Message: targets = [id for id in msg.assist_monster_entity_id_list if id > 20000 or id < 10] @@ -18,46 +14,7 @@ async def handle(session: PlayerSession, msg: SceneCastSkillCsReq) -> betterprot id for id in monster.entity_id_list if id not in targets and (id > 20000 or id < 10) ) + session.player.battle_manager = BattleManager(session.player) if msg.skill_index == 0 and targets: - monster_data: list[StageConfig] = [] - for entity_id in targets: - entity_data = session.player.scene_manager.entities.get(entity_id) - if entity_data: - stage = ResourceManager.instance().find_by_index(StageConfig,entity_data.npc_monster.event_id*10) - if not stage: - stage = ResourceManager.instance().find_by_index(StageConfig,entity_data.npc_monster.event_id) - if stage: - monster_data.append(stage) - session.player.scene_manager.battle_monster.append(entity_data) - if monster_data: - return SceneCastSkillScRsp( - retcode=0, - cast_entity_id=msg.cast_entity_id, - battle_info=SceneBattleInfo( - rounds_limit=0, - world_level=session.player.data.world_level, - logic_random_seed=np.random.randint(1, np.iinfo(np.int32).max, dtype=np.int32), - stage_id=monster_data[0].StageID, - battle_id=1, - battle_avatar_list=[ - session.player.avatar_mananger.get(avatar_id).ToBattleProto(index,session) - for index, avatar_id in enumerate(session.player.lineup_manager.get(session.player.data.cur_lineup, None).avatar_list) - ], - monster_wave_list=[ - SceneMonsterWave( - battle_stage_id=monster_list.StageID, - battle_wave_id=index, - monster_list=[ - SceneMonster( - monster_id=id - ) - for monster_dict in monster_list.MonsterList - for monster, id in monster_dict.items() - if id > 0 - ] - ) - for index,monster_list in enumerate(monster_data) - ] - ) - ) + return session.player.battle_manager.EnterBattle(msg,targets) return SceneCastSkillScRsp(retcode=0) \ No newline at end of file