from pydantic import BaseModel from game_server.game.enums.scene.game_mode_type import GameModeTypeEnum from game_server.resource import ResourceManager from game_server.resource.configdb.maze_plane import MazePlaneData from game_server.resource.configdb.map_entrance import MapEntranceData from game_server.resource.configdb.summon_unit_data import SummonUnitData from game_server.game.motion.motion_info import Motion from rail_proto.lib import ( SceneInfo, SceneEntityInfo, SceneEntityGroupInfo, ScenePropInfo, SceneNpcInfo, SceneNpcMonsterInfo, SceneActorInfo, AvatarType, SceneCastSkillCsReq, SceneGroupRefreshScNotify, GroupRefreshInfo, SceneGroupRefreshType, SceneEntityRefreshInfo, SceneSummonUnitInfo ) from utils.time import cur_timestamp_ms class SceneManager(BaseModel): entry_id: int plane_id: int = 0 floor_id: int = 0 game_mode_type: int = 0 world_id: int = 0 teleport_id: int = 0 entity_group_list: list[SceneEntityGroupInfo] = [] entities: dict[int,SceneEntityInfo] = {} @staticmethod def Actor(avatar_id,player_pos): return SceneEntityInfo( entity_id=avatar_id << 20, motion=player_pos, actor=SceneActorInfo( base_avatar_id=avatar_id, avatar_type=AvatarType.AVATAR_FORMAL_TYPE ) ) def ToProto(self,session) -> SceneInfo: prop_entity_id = 10 npc_entity_id = 10_000 monster_entity_id = 20_000 entrance = ResourceManager.instance().find_by_index(MapEntranceData, self.entry_id) maze_plane = ResourceManager.instance().find_by_index(MazePlaneData, entrance.PlaneID) floor_infos = entrance.floor_infos.get(self.entry_id) proto = SceneInfo( entry_id=self.entry_id, plane_id=entrance.PlaneID, floor_id=entrance.FloorID, ) proto.game_mode_type = GameModeTypeEnum[maze_plane.PlaneType].value if maze_plane.WorldID == 100: maze_plane.WorldID = 401 proto.world_id = maze_plane.WorldID loaded_npc = [13199,13321,1313,13227,13190,13191,13192,13141,13246,13407 ,13223,13152] for group_id,group in floor_infos.groups.items(): if group.LoadSide == "Client": continue if group.GroupName: if "TrainVisitor" in group.GroupName or "DeployPuzzle_Repeat_Area" in group.GroupName or "TrainVisiter" in group.GroupName: continue group_info = SceneEntityGroupInfo( group_id=group_id ) for prop in group.PropList: prop_entity_id += 1 prop_entity_info = SceneEntityInfo( inst_id=prop.ID, group_id=group_id, motion=Motion( x=prop.PosX, y=prop.PosY, z=prop.PosZ, rotY=prop.RotY ).ToProto(), prop=ScenePropInfo( prop_id=prop.PropID, prop_state=8 if prop.MappingInfoID > 0 else (1 if prop.State == 0 else prop.State) ), entity_id=prop_entity_id ) group_info.entity_list.append(prop_entity_info) if self.teleport_id > 0 and self.teleport_id == prop.MappingInfoID: for anchor in group.AnchorList: if group.id == prop.AnchorGroupID and anchor.ID == prop.AnchorID: session.player.data.pos.x = int(anchor.PosX) session.player.data.pos.y = int(anchor.PosY) session.player.data.pos.z = int(anchor.PosZ) session.player.data.rot.y = int(anchor.RotY) for npc in group.NPCList: if npc.NPCID in loaded_npc: continue loaded_npc.append(npc.NPCID) npc_entity_id += 1 npc_entity_info = SceneEntityInfo( inst_id=npc.ID, group_id=group_id, entity_id=npc_entity_id, motion=Motion( x=npc.PosX, y=npc.PosY, z=npc.PosZ, rotY=npc.RotY ).ToProto(), npc=SceneNpcInfo( npc_id=npc.NPCID ) ) group_info.entity_list.append(npc_entity_info) for monster in group.MonsterList: monster_entity_id += 1 monster_entity_info = SceneEntityInfo( inst_id=monster.ID, group_id=group_id, entity_id=monster_entity_id, motion=Motion( x=monster.PosX, y=monster.PosY, z=monster.PosZ, rotY=monster.RotY ).ToProto(), npc_monster=SceneNpcMonsterInfo( monster_id=monster.NPCMonsterID, event_id=monster.EventID, world_level=6 ) ) group_info.entity_list.append(monster_entity_info) session.player.scene_manager.entities[monster_entity_id] = monster_entity_info proto.entity_group_list.append(group_info) player_pos = Motion( x=session.player.data.pos.x, y=session.player.data.pos.y, z=session.player.data.pos.z, rotY=session.player.data.rot.y ).ToProto() player_group = SceneEntityGroupInfo(state=0,group_id=0) for avatar_id in session.player.lineup_manager.get(session.player.data.cur_lineup).avatar_list: player_group.entity_list.append(self.Actor(avatar_id,player_pos)) proto.entity_group_list.append(player_group) session.player.data.entry_id = self.entry_id session.player.data.plane_id = entrance.PlaneID session.player.data.floor_id = entrance.FloorID self.plane_id = entrance.PlaneID self.floor_id = entrance.FloorID return proto def SummonUnit(self,msg: SceneCastSkillCsReq,summon_id) -> SceneEntityInfo: return SceneEntityInfo( entity_id=msg.cast_entity_id, motion=Motion( x=msg.target_motion.pos.x, y=msg.target_motion.pos.y, z=msg.target_motion.pos.z, rotY=msg.target_motion.rot.y ).ToProto(), summon_unit=SceneSummonUnitInfo( attach_entity_id=msg.attacked_by_entity_id, caster_entity_id=msg.attacked_by_entity_id, summon_unit_id=summon_id, life_time_ms=20000, create_time_ms=cur_timestamp_ms() ) ) async def GetSummonUnit(self,session, msg: SceneCastSkillCsReq): summon_id = str(msg.attacked_by_entity_id >> 20) + "1" summon = ResourceManager.instance().find_all_by_index(SummonUnitData, summon_id) if summon: summon_unit = SceneGroupRefreshScNotify( floor_id=self.floor_id, group_refresh_list=[ GroupRefreshInfo( refresh_type=SceneGroupRefreshType.SCENE_GROUP_REFRESH_TYPE_LOADED.value, refresh_entity=[ SceneEntityRefreshInfo( add_entity=self.SummonUnit(msg,data.ID) ) for data in summon ] ) ] ) await session.notify(summon_unit)