init
This commit is contained in:
79
game_server/resource/__init__.py
Normal file
79
game_server/resource/__init__.py
Normal file
@@ -0,0 +1,79 @@
|
||||
import json
|
||||
import traceback
|
||||
from typing import Dict, Type, TypeVar, Optional, Any, List
|
||||
|
||||
from utils.logger import Error, Info
|
||||
from game_server.resource.base_resource import BaseResource
|
||||
from game_server.resource.decorators import resource_registry
|
||||
import game_server.resource.configdb # noqa: F401
|
||||
|
||||
T = TypeVar("T", bound=BaseResource)
|
||||
|
||||
|
||||
def filter_data(cls: Type, data):
|
||||
valid_fields = cls.__annotations__.keys()
|
||||
return {field: data.get(field, None) for field in valid_fields}
|
||||
|
||||
|
||||
class ResourceManager:
|
||||
def __init__(self):
|
||||
self.data: Dict[Type[T], Dict[Any, T]] = {}
|
||||
self.check_floor: bool = False
|
||||
|
||||
def load_resources(self) -> None:
|
||||
Info("[BOOT] [ResourceManager] Loading Resourcses...")
|
||||
sorted_load_priority = dict(
|
||||
sorted(resource_registry.items(), key=lambda item: item[1]["load_priority"])
|
||||
).items()
|
||||
for cls, metadata in sorted_load_priority:
|
||||
path = metadata["path"]
|
||||
try:
|
||||
with open(path, "r", encoding="utf-8") as file:
|
||||
raw_data = json.load(file)
|
||||
except Exception:
|
||||
Error(f"Error when loading resource {path}")
|
||||
traceback.print_exc()
|
||||
continue
|
||||
|
||||
self.data[cls] = {}
|
||||
i = 0
|
||||
for data in raw_data:
|
||||
data = filter_data(cls, data)
|
||||
item: T = cls(**data)
|
||||
if "MapEntrance" in path:
|
||||
if not self.check_floor:
|
||||
Info("[BOOT] Loading floor infos... this may take a while.")
|
||||
self.check_floor = True
|
||||
if not item.check_floor_dir():
|
||||
break
|
||||
if not item.on_load():
|
||||
continue
|
||||
i += 1
|
||||
index_value = item.get_index()
|
||||
|
||||
if index_value not in self.data[cls]:
|
||||
self.data[cls][index_value] = []
|
||||
self.data[cls][index_value].append(item)
|
||||
Info(f"[BOOT] [ResourceManager] Loaded {i} config(s) for {cls.__name__}")
|
||||
if "MapEntrance" in path:
|
||||
Info(f"[BOOT] Loaded floor infos.")
|
||||
|
||||
def find_by_index(self, cls: Type[T], value: Any) -> Optional[T]:
|
||||
items = self.data.get(cls, {}).get(str(value), [])
|
||||
return items[0] if items else None
|
||||
|
||||
def find_all_by_index(self, cls: Type[T], value: Any) -> List[T]:
|
||||
return self.data.get(cls, {}).get(str(value), [])
|
||||
|
||||
def has_index(self, cls: Type[T], value: Any) -> bool:
|
||||
return str(value) in self.data.get(cls, {})
|
||||
|
||||
def values(self, cls: Type[T]) -> List[T]:
|
||||
return [item for sublist in self.data.get(cls, {}).values() for item in sublist]
|
||||
|
||||
@staticmethod
|
||||
def instance():
|
||||
return resource_manager
|
||||
|
||||
|
||||
resource_manager = ResourceManager()
|
||||
19
game_server/resource/base_resource.py
Normal file
19
game_server/resource/base_resource.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass
|
||||
from typing import TypeVar
|
||||
|
||||
T = TypeVar("T", bound="BaseResource")
|
||||
|
||||
@dataclass
|
||||
class BaseResource(ABC):
|
||||
def on_load(self: T) -> bool:
|
||||
"""returns True by default if item loaded, otherwise will be skipped"""
|
||||
return True
|
||||
|
||||
def check_floor_dir(self: T) -> bool:
|
||||
"""returns True by default if floor dir exist, otherwise will be skipped"""
|
||||
return True
|
||||
|
||||
@abstractmethod
|
||||
def get_index(self) -> str:
|
||||
pass
|
||||
15
game_server/resource/configdb/__init__.py
Normal file
15
game_server/resource/configdb/__init__.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import importlib
|
||||
import os
|
||||
import sys
|
||||
|
||||
folder = "game_server/resource/configdb"
|
||||
sys.path.append(os.path.dirname(folder))
|
||||
|
||||
for filename in os.listdir(folder):
|
||||
if filename.endswith(".py") and filename != "__init__.py":
|
||||
module_name = filename[:-3]
|
||||
module_path = f"game_server.resource.configdb.{module_name}"
|
||||
try:
|
||||
importlib.import_module(module_path)
|
||||
except Exception as e:
|
||||
print(f"Error importing module '{module_path}': {e}")
|
||||
32
game_server/resource/configdb/avatar_config.py
Normal file
32
game_server/resource/configdb/avatar_config.py
Normal file
@@ -0,0 +1,32 @@
|
||||
from dataclasses import dataclass, field
|
||||
from game_server.resource.base_resource import BaseResource, T
|
||||
from game_server.resource.decorators import GameResource
|
||||
from game_server.resource.configdb.avatar_skill_tree_config import AvatarSkillTreeConfig
|
||||
|
||||
@dataclass
|
||||
@GameResource("resources/ExcelOutput/AvatarConfig.json")
|
||||
class AvatarConfig(BaseResource):
|
||||
AvatarID: int
|
||||
AvatarSkills: dict[int, int]
|
||||
|
||||
def on_load(self: T) -> bool:
|
||||
from game_server.resource import ResourceManager
|
||||
|
||||
self.AvatarSkills = {}
|
||||
|
||||
skill_tree_config = ResourceManager.instance().find_all_by_index(
|
||||
AvatarSkillTreeConfig, self.AvatarID
|
||||
)
|
||||
|
||||
for skill in skill_tree_config:
|
||||
skill_id = skill.PointID
|
||||
skill_level = skill.MaxLevel
|
||||
|
||||
skill = self.AvatarSkills.get(skill_id)
|
||||
if not skill:
|
||||
self.AvatarSkills[skill_id] = skill_level
|
||||
return True
|
||||
|
||||
|
||||
def get_index(self) -> str:
|
||||
return str(self.AvatarID)
|
||||
13
game_server/resource/configdb/avatar_skill_tree_config.py
Normal file
13
game_server/resource/configdb/avatar_skill_tree_config.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from dataclasses import dataclass
|
||||
from game_server.resource.base_resource import BaseResource
|
||||
from game_server.resource.decorators import GameResource, LoadPriority
|
||||
|
||||
@dataclass
|
||||
@GameResource("resources/ExcelOutput/AvatarSkillTreeConfig.json", load_priority=LoadPriority.HIGH)
|
||||
class AvatarSkillTreeConfig(BaseResource):
|
||||
AvatarID: int
|
||||
MaxLevel: int
|
||||
PointID: int
|
||||
|
||||
def get_index(self) -> str:
|
||||
return str(self.AvatarID)
|
||||
22
game_server/resource/configdb/challenge_maze_config.py
Normal file
22
game_server/resource/configdb/challenge_maze_config.py
Normal file
@@ -0,0 +1,22 @@
|
||||
from dataclasses import dataclass
|
||||
from game_server.resource.base_resource import BaseResource
|
||||
from game_server.resource.decorators import GameResource
|
||||
|
||||
@dataclass
|
||||
@GameResource("resources/ExcelOutput/ChallengeMazeConfig.json")
|
||||
class ChallengeMazeConfig(BaseResource):
|
||||
ID: int
|
||||
MazeBuffID: int
|
||||
ChallengeCountDown: int
|
||||
MapEntranceID: int
|
||||
MapEntranceID2: int
|
||||
MazeGroupID1: int
|
||||
MazeGroupID2: int
|
||||
GroupID: int
|
||||
EventIDList1: list
|
||||
EventIDList2: list
|
||||
NpcMonsterIDList1: list
|
||||
NpcMonsterIDList2: list
|
||||
|
||||
def get_index(self) -> str:
|
||||
return str(self.ID)
|
||||
12
game_server/resource/configdb/equipment_config.py
Normal file
12
game_server/resource/configdb/equipment_config.py
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
from dataclasses import dataclass
|
||||
from game_server.resource.base_resource import BaseResource
|
||||
from game_server.resource.decorators import GameResource
|
||||
|
||||
@dataclass
|
||||
@GameResource("resources/ExcelOutput/EquipmentConfig.json")
|
||||
class EquipmentConfig(BaseResource):
|
||||
EquipmentID: int
|
||||
|
||||
def get_index(self) -> str:
|
||||
return str(self.EquipmentID)
|
||||
13
game_server/resource/configdb/item_config.py
Normal file
13
game_server/resource/configdb/item_config.py
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
from dataclasses import dataclass
|
||||
from game_server.resource.base_resource import BaseResource
|
||||
from game_server.resource.decorators import GameResource
|
||||
|
||||
@dataclass
|
||||
@GameResource("resources/ExcelOutput/ItemConfig.json")
|
||||
class ItemConfig(BaseResource):
|
||||
ID: int
|
||||
ItemSubType: str
|
||||
|
||||
def get_index(self) -> str:
|
||||
return str(self.ID)
|
||||
11
game_server/resource/configdb/main_mission.py
Normal file
11
game_server/resource/configdb/main_mission.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from dataclasses import dataclass
|
||||
from game_server.resource.base_resource import BaseResource
|
||||
from game_server.resource.decorators import GameResource
|
||||
|
||||
@dataclass
|
||||
@GameResource("resources/ExcelOutput/MainMission.json")
|
||||
class MainMissionData(BaseResource):
|
||||
MainMissionID: int
|
||||
|
||||
def get_index(self) -> str:
|
||||
return str(self.MainMissionID)
|
||||
12
game_server/resource/configdb/map_default_entrance.py
Normal file
12
game_server/resource/configdb/map_default_entrance.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from dataclasses import dataclass
|
||||
from game_server.resource.base_resource import BaseResource
|
||||
from game_server.resource.decorators import GameResource
|
||||
|
||||
@dataclass
|
||||
@GameResource("resources/ExcelOutput/MapDefaultEntrance.json")
|
||||
class MapDefaultEntranceData(BaseResource):
|
||||
EntranceID: int
|
||||
FloorID: int
|
||||
|
||||
def get_index(self) -> str:
|
||||
return str(self.FloorID)
|
||||
85
game_server/resource/configdb/map_entrance.py
Normal file
85
game_server/resource/configdb/map_entrance.py
Normal file
@@ -0,0 +1,85 @@
|
||||
import os
|
||||
import json
|
||||
import dataclasses
|
||||
from utils.logger import Warn
|
||||
from game_server.resource.base_resource import BaseResource
|
||||
from game_server.resource.decorators import GameResource,LoadPriority
|
||||
from game_server.resource.configdb.sub_type.floor_info import FloorInfo,parse_floor_info
|
||||
from game_server.resource.configdb.sub_type.group_info import parse_group_info
|
||||
|
||||
floor_dir = './resources/Config/LevelOutput/RuntimeFloor/'
|
||||
|
||||
@dataclasses.dataclass
|
||||
@GameResource("resources/ExcelOutput/MapEntrance.json", load_priority=LoadPriority.LOW)
|
||||
class MapEntranceData(BaseResource):
|
||||
ID: int
|
||||
PlaneID: int
|
||||
FloorID: int
|
||||
StartAnchorID: int
|
||||
StartGroupID: int
|
||||
EntranceType: str
|
||||
|
||||
floor_infos: dict[int, FloorInfo] = dataclasses.field(default_factory=dict)
|
||||
|
||||
def on_load(self) -> bool:
|
||||
name = f"P{self.PlaneID}_F{self.FloorID}"
|
||||
file_path = os.path.join(floor_dir, f"{name}.json")
|
||||
if not os.path.exists(file_path):
|
||||
Warn(f"Missing floor info: {name}")
|
||||
return False
|
||||
|
||||
with open(file_path, 'r', encoding='utf-8') as file:
|
||||
raw_data = json.load(file)
|
||||
|
||||
self.floor_infos = {}
|
||||
|
||||
floor_data = parse_floor_info(raw_data)
|
||||
self.floor_infos[self.ID] = floor_data
|
||||
|
||||
floor = self.floor_infos[self.ID]
|
||||
|
||||
for simpleGroup in floor.GroupInstanceList:
|
||||
if simpleGroup.IsDelete:
|
||||
continue
|
||||
|
||||
group_file_path = os.path.join('./resources/', simpleGroup.GroupPath)
|
||||
|
||||
if not os.path.exists(group_file_path):
|
||||
Warn(f"Missing GroupPath info: {simpleGroup.GroupPath}")
|
||||
continue
|
||||
|
||||
try:
|
||||
with open(group_file_path, 'r', encoding='utf-8') as group_file:
|
||||
content = group_file.read().strip()
|
||||
if not content:
|
||||
Warn(f"File is empty: {group_file_path}")
|
||||
continue
|
||||
|
||||
group_raw_data = json.loads(content)
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
Warn(f"Error decoding JSON in file {group_file_path}: {e}")
|
||||
continue
|
||||
|
||||
except Exception as e:
|
||||
Warn(f"Unexpected error occurred while processing file {group_file_path}: {e}")
|
||||
continue
|
||||
|
||||
group_info = parse_group_info(group_raw_data)
|
||||
group_info.id = simpleGroup.ID
|
||||
|
||||
if group_info.OwnerMainMissionID and group_info.OwnerMainMissionID > 0:
|
||||
continue
|
||||
|
||||
floor.groups[simpleGroup.ID] = group_info
|
||||
|
||||
return True
|
||||
|
||||
def check_floor_dir(self) -> bool:
|
||||
if not os.path.exists(floor_dir):
|
||||
Warn(f"Floor infos are missing, please check your resources folder: {floor_dir}. Teleports and natural world spawns may not work!")
|
||||
return
|
||||
return True
|
||||
|
||||
def get_index(self) -> str:
|
||||
return str(self.ID)
|
||||
15
game_server/resource/configdb/maze_plane.py
Normal file
15
game_server/resource/configdb/maze_plane.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from dataclasses import dataclass
|
||||
from game_server.resource.base_resource import BaseResource
|
||||
from game_server.resource.decorators import GameResource
|
||||
from game_server.game.enums.scene.game_mode_type import GameModeTypeEnum
|
||||
|
||||
@dataclass
|
||||
@GameResource("resources/ExcelOutput/MazePlane.json")
|
||||
class MazePlaneData(BaseResource):
|
||||
PlaneID: int
|
||||
PlaneType: GameModeTypeEnum
|
||||
WorldID: int
|
||||
StartFloorID: int
|
||||
|
||||
def get_index(self) -> str:
|
||||
return str(self.PlaneID)
|
||||
13
game_server/resource/configdb/player_icon_config.py
Normal file
13
game_server/resource/configdb/player_icon_config.py
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
from dataclasses import dataclass
|
||||
from game_server.resource.base_resource import BaseResource
|
||||
from game_server.resource.decorators import GameResource
|
||||
|
||||
@dataclass
|
||||
@GameResource("resources/ExcelOutput/PlayerIconConfig.json")
|
||||
class PlayerIconConfig(BaseResource):
|
||||
ID: int
|
||||
IsVisible: bool
|
||||
|
||||
def get_index(self) -> str:
|
||||
return str(self.ID)
|
||||
18
game_server/resource/configdb/relic_config.py
Normal file
18
game_server/resource/configdb/relic_config.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from dataclasses import dataclass
|
||||
from game_server.resource.base_resource import BaseResource
|
||||
from game_server.resource.decorators import GameResource
|
||||
|
||||
@dataclass
|
||||
@GameResource("resources/ExcelOutput/RelicConfig.json")
|
||||
class RelicConfigData(BaseResource):
|
||||
ID: int
|
||||
Type: str
|
||||
MaxLevel: int
|
||||
MainAffixGroup: int
|
||||
SubAffixGroup: int
|
||||
|
||||
def on_load(self) -> bool:
|
||||
return self.MaxLevel == 15
|
||||
|
||||
def get_index(self) -> str:
|
||||
return str(self.ID)
|
||||
15
game_server/resource/configdb/relic_main_affix_config.py
Normal file
15
game_server/resource/configdb/relic_main_affix_config.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from dataclasses import dataclass
|
||||
from game_server.resource.base_resource import BaseResource
|
||||
from game_server.resource.decorators import GameResource
|
||||
|
||||
@dataclass
|
||||
@GameResource("resources/ExcelOutput/RelicMainAffixConfig.json")
|
||||
class RelicMainAffixConfigData(BaseResource):
|
||||
GroupID: int
|
||||
AffixID: int
|
||||
Property: str
|
||||
|
||||
def get_index(self) -> str:
|
||||
return str(self.GroupID)
|
||||
|
||||
|
||||
16
game_server/resource/configdb/relic_sub_affix_config.py
Normal file
16
game_server/resource/configdb/relic_sub_affix_config.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from dataclasses import dataclass
|
||||
from game_server.resource.base_resource import BaseResource
|
||||
from game_server.resource.decorators import GameResource
|
||||
|
||||
@dataclass
|
||||
@GameResource("resources/ExcelOutput/RelicSubAffixConfig.json")
|
||||
class RelicSubAffixConfigData(BaseResource):
|
||||
GroupID: int
|
||||
AffixID: int
|
||||
StepNum: int
|
||||
Property: str
|
||||
|
||||
def get_index(self) -> str:
|
||||
return str(self.GroupID)
|
||||
|
||||
|
||||
15
game_server/resource/configdb/stage_config.py
Normal file
15
game_server/resource/configdb/stage_config.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from dataclasses import dataclass
|
||||
from game_server.resource.base_resource import BaseResource
|
||||
from game_server.resource.decorators import GameResource
|
||||
|
||||
@dataclass
|
||||
@GameResource("resources/ExcelOutput/StageConfig.json")
|
||||
class StageConfig(BaseResource):
|
||||
StageID: int
|
||||
StageType: str
|
||||
MonsterList: list
|
||||
|
||||
def get_index(self) -> str:
|
||||
return str(self.StageID)
|
||||
|
||||
|
||||
12
game_server/resource/configdb/sub_type/anchor_info.py
Normal file
12
game_server/resource/configdb/sub_type/anchor_info.py
Normal file
@@ -0,0 +1,12 @@
|
||||
import dataclasses
|
||||
|
||||
@dataclasses.dataclass
|
||||
class AnchorInfo:
|
||||
ID: int
|
||||
Name : str
|
||||
PosX : float
|
||||
PosY : float
|
||||
PosZ : float
|
||||
RotX : float
|
||||
RotY : float
|
||||
RotZ : float
|
||||
35
game_server/resource/configdb/sub_type/floor_info.py
Normal file
35
game_server/resource/configdb/sub_type/floor_info.py
Normal file
@@ -0,0 +1,35 @@
|
||||
import dataclasses
|
||||
from typing import List, Optional, Dict
|
||||
from game_server.resource.configdb.sub_type.group_info import GroupInfo
|
||||
|
||||
@dataclasses.dataclass
|
||||
class GroupInstance:
|
||||
GroupPath: str
|
||||
ID: int
|
||||
IsDelete: Optional[bool] = False
|
||||
|
||||
@dataclasses.dataclass
|
||||
class FloorInfo:
|
||||
FloorID: int
|
||||
StartGroupIndex: int
|
||||
StartAnchorID: int
|
||||
GroupInstanceList: List[GroupInstance]
|
||||
groups: Dict[int, GroupInfo] = dataclasses.field(default_factory=dict)
|
||||
|
||||
|
||||
def parse_floor_info(raw_data: dict) -> FloorInfo:
|
||||
group_instances = [
|
||||
GroupInstance(
|
||||
GroupPath=group.get("GroupPath", ""),
|
||||
ID=group.get("ID", 0),
|
||||
IsDelete=group.get("IsDelete", False),
|
||||
)
|
||||
for group in raw_data.get("GroupInstanceList", [])
|
||||
]
|
||||
return FloorInfo(
|
||||
FloorID=raw_data.get("FloorID", 0),
|
||||
StartGroupIndex=raw_data.get("StartGroupIndex", 0),
|
||||
StartAnchorID=raw_data.get("StartAnchorID", 0),
|
||||
GroupInstanceList=group_instances,
|
||||
groups={},
|
||||
)
|
||||
89
game_server/resource/configdb/sub_type/group_info.py
Normal file
89
game_server/resource/configdb/sub_type/group_info.py
Normal file
@@ -0,0 +1,89 @@
|
||||
import dataclasses
|
||||
from typing import List, Optional,Type, TypeVar
|
||||
from enum import Enum
|
||||
from game_server.resource.configdb.sub_type.npc_info import NpcInfo
|
||||
from game_server.resource.configdb.sub_type.anchor_info import AnchorInfo
|
||||
from game_server.resource.configdb.sub_type.monster_info import MonsterInfo
|
||||
from game_server.resource.configdb.sub_type.prop_info import PropInfo,PropState
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
class GroupLoadSide(Enum):
|
||||
CLIENT = "Client"
|
||||
SERVER = "Server"
|
||||
|
||||
@classmethod
|
||||
def from_value(cls, value):
|
||||
if value in ("Server"):
|
||||
return cls.SERVER
|
||||
elif value in ("Client"):
|
||||
return cls.CLIENT
|
||||
raise ValueError(f"{value!r} is not a valid GroupLoadSide")
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class GroupInfo:
|
||||
NPCList: List[NpcInfo] = dataclasses.field(default_factory=list)
|
||||
id: Optional[int] = dataclasses.field(default_factory=int)
|
||||
OwnerMainMissionID: Optional[int] = dataclasses.field(default_factory=int)
|
||||
LoadOnInitial: Optional[bool] = dataclasses.field(default_factory=bool)
|
||||
AnchorList: Optional[List[AnchorInfo]] = dataclasses.field(default_factory=list)
|
||||
MonsterList: Optional[List[MonsterInfo]] = dataclasses.field(default_factory=list)
|
||||
PropList: Optional[List[PropInfo]] = dataclasses.field(default_factory=list)
|
||||
LoadSide: Optional[str] = None
|
||||
|
||||
|
||||
def parse_dataclass(cls: Type[T], raw_data: dict) -> T:
|
||||
"""
|
||||
Parse a dictionary into a dataclass, filtering out unknown fields
|
||||
and filling in missing fields with default values.
|
||||
:param cls: The dataclass type to instantiate.
|
||||
:param raw_data: The raw dictionary data.
|
||||
:return: An instance of the dataclass.
|
||||
"""
|
||||
cls_fields = {f.name: f for f in dataclasses.fields(cls)}
|
||||
filtered_data = {}
|
||||
|
||||
for field_name, field_def in cls_fields.items():
|
||||
if field_name in raw_data:
|
||||
filtered_data[field_name] = raw_data[field_name]
|
||||
elif field_def.default is not dataclasses.MISSING:
|
||||
filtered_data[field_name] = field_def.default
|
||||
elif field_def.default_factory is not dataclasses.MISSING:
|
||||
filtered_data[field_name] = field_def.default_factory()
|
||||
else:
|
||||
if field_def.type == float:
|
||||
filtered_data[field_name] = 0.0
|
||||
elif field_def.type == int:
|
||||
filtered_data[field_name] = 0
|
||||
elif field_def.type == str:
|
||||
filtered_data[field_name] = ""
|
||||
elif field_def.type == list:
|
||||
filtered_data[field_name] = []
|
||||
elif field_def.type == dict:
|
||||
filtered_data[field_name] = {}
|
||||
else:
|
||||
filtered_data[field_name] = None
|
||||
|
||||
return cls(**filtered_data)
|
||||
|
||||
def parse_group_info(raw_data: dict) -> GroupInfo:
|
||||
def parse_state(state):
|
||||
return PropState[state].value
|
||||
|
||||
return GroupInfo(
|
||||
id=raw_data.get("id"),
|
||||
OwnerMainMissionID=raw_data.get("OwnerMainMissionID"),
|
||||
LoadOnInitial=raw_data.get("LoadOnInitial", False),
|
||||
NPCList=[parse_dataclass(NpcInfo, npc) for npc in (raw_data.get("NPCList") or [])],
|
||||
AnchorList=[parse_dataclass(AnchorInfo, anchor) for anchor in (raw_data.get("AnchorList") or [])],
|
||||
MonsterList=[parse_dataclass(MonsterInfo, monster) for monster in (raw_data.get("MonsterList") or [])],
|
||||
PropList=[
|
||||
parse_dataclass(
|
||||
PropInfo,
|
||||
{k: (parse_state(v) if k == "State" else v) for k, v in prop.items()}
|
||||
)
|
||||
for prop in (raw_data.get("PropList") or [])
|
||||
],
|
||||
LoadSide=raw_data.get("LoadSide") if raw_data.get("LoadSide") else None,
|
||||
)
|
||||
15
game_server/resource/configdb/sub_type/monster_info.py
Normal file
15
game_server/resource/configdb/sub_type/monster_info.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import dataclasses
|
||||
|
||||
@dataclasses.dataclass
|
||||
class MonsterInfo:
|
||||
ID : int
|
||||
NPCMonsterID : int
|
||||
EventID : int
|
||||
FarmElementID : int
|
||||
IsClientOnly : bool
|
||||
PosX : float
|
||||
PosY : float
|
||||
PosZ : float
|
||||
RotX : float
|
||||
RotY : float
|
||||
RotZ : float
|
||||
13
game_server/resource/configdb/sub_type/npc_info.py
Normal file
13
game_server/resource/configdb/sub_type/npc_info.py
Normal file
@@ -0,0 +1,13 @@
|
||||
import dataclasses
|
||||
|
||||
@dataclasses.dataclass
|
||||
class NpcInfo:
|
||||
ID : int
|
||||
NPCID : int
|
||||
IsClientOnly: bool
|
||||
PosX : float
|
||||
PosY : float
|
||||
PosZ : float
|
||||
RotX : float
|
||||
RotY : float
|
||||
RotZ : float
|
||||
65
game_server/resource/configdb/sub_type/prop_info.py
Normal file
65
game_server/resource/configdb/sub_type/prop_info.py
Normal file
@@ -0,0 +1,65 @@
|
||||
from typing import List, Optional
|
||||
import dataclasses
|
||||
from enum import Enum
|
||||
|
||||
class PropState(Enum):
|
||||
Closed = 0
|
||||
Open = 1
|
||||
Locked = 2
|
||||
BridgeState1 = 3
|
||||
BridgeState2 = 4
|
||||
BridgeState3 = 5
|
||||
BridgeState4 = 6
|
||||
CheckPointDisable = 7
|
||||
CheckPointEnable = 8
|
||||
TriggerDisable = 9
|
||||
TriggerEnable = 10
|
||||
ChestLocked = 11
|
||||
ChestClosed = 12
|
||||
ChestUsed = 13
|
||||
Elevator1 = 14
|
||||
Elevator2 = 15
|
||||
Elevator3 = 16
|
||||
WaitActive = 17
|
||||
EventClose = 18
|
||||
EventOpen = 19
|
||||
Hidden = 20
|
||||
TeleportGate0 = 21
|
||||
TeleportGate1 = 22
|
||||
TeleportGate2 = 23
|
||||
TeleportGate3 = 24
|
||||
Destructed = 25
|
||||
CustomState01 = 101
|
||||
CustomState02 = 102
|
||||
CustomState03 = 103
|
||||
CustomState04 = 104
|
||||
CustomState05 = 105
|
||||
CustomState06 = 106
|
||||
CustomState07 = 107
|
||||
CustomState08 = 108
|
||||
CustomState09 = 109
|
||||
|
||||
@dataclasses.dataclass
|
||||
class ValueSource:
|
||||
Values: Optional[List] = dataclasses.field(default_factory=list)
|
||||
|
||||
@dataclasses.dataclass
|
||||
class PropInfo:
|
||||
ID : int
|
||||
MappingInfoID : int
|
||||
AnchorGroupID : int
|
||||
AnchorID : int
|
||||
PropID : int
|
||||
EventID : int
|
||||
CocoonID : int
|
||||
FarmElementID : int
|
||||
IsClientOnly : int
|
||||
State: PropState
|
||||
PosX : float
|
||||
PosY : float
|
||||
PosZ : float
|
||||
RotX : float
|
||||
RotY : float
|
||||
RotZ : float
|
||||
IsDelete: bool
|
||||
Name : str
|
||||
17
game_server/resource/decorators.py
Normal file
17
game_server/resource/decorators.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from typing import Type, Dict
|
||||
|
||||
resource_registry: Dict[Type, Dict[str, any]] = {}
|
||||
|
||||
|
||||
class LoadPriority:
|
||||
HIGH = 1
|
||||
NORMAL = 2
|
||||
LOW = 3
|
||||
|
||||
|
||||
def GameResource(path: str, load_priority=LoadPriority.NORMAL):
|
||||
def decorator(cls):
|
||||
resource_registry[cls] = {"path": path, "load_priority": load_priority}
|
||||
return cls
|
||||
|
||||
return decorator
|
||||
Reference in New Issue
Block a user