mirror of
https://github.com/Lost-MSth/Arcaea-server.git
synced 2026-02-12 19:17:26 +08:00
[Enhance] World map sub folder
- Make the world maps' folder can have sub folders.
This commit is contained in:
@@ -82,11 +82,15 @@ class BundleParser:
|
|||||||
version_tuple_bundles: 'dict[tuple[str, str], ContentBundle]' = {}
|
version_tuple_bundles: 'dict[tuple[str, str], ContentBundle]' = {}
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.parse()
|
if not self.bundles:
|
||||||
|
self.parse()
|
||||||
|
|
||||||
def re_init(self) -> None:
|
def re_init(self) -> None:
|
||||||
self.bundles.clear()
|
self.bundles.clear()
|
||||||
self.max_bundle_version.clear()
|
self.max_bundle_version.clear()
|
||||||
|
self.next_versions.clear()
|
||||||
|
self.version_tuple_bundles.clear()
|
||||||
|
self.get_bundles.cache_clear()
|
||||||
self.parse()
|
self.parse()
|
||||||
|
|
||||||
def parse(self) -> None:
|
def parse(self) -> None:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from .config_manager import Config
|
from .config_manager import Config
|
||||||
|
|
||||||
ARCAEA_SERVER_VERSION = 'v2.11.3.13'
|
ARCAEA_SERVER_VERSION = 'v2.11.3.14'
|
||||||
ARCAEA_DATABASE_VERSION = 'v2.11.3.13'
|
ARCAEA_DATABASE_VERSION = 'v2.11.3.13'
|
||||||
ARCAEA_LOG_DATBASE_VERSION = 'v1.1'
|
ARCAEA_LOG_DATBASE_VERSION = 'v1.1'
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ from core.sql import (Connect, DatabaseMigrator, LogDatabaseMigrator,
|
|||||||
MemoryDatabase)
|
MemoryDatabase)
|
||||||
from core.user import UserRegister
|
from core.user import UserRegister
|
||||||
from core.util import try_rename
|
from core.util import try_rename
|
||||||
|
from core.world import MapParser
|
||||||
|
|
||||||
|
|
||||||
class DatabaseInit:
|
class DatabaseInit:
|
||||||
@@ -326,12 +327,11 @@ class FileChecker:
|
|||||||
def check_song_file(self) -> bool:
|
def check_song_file(self) -> bool:
|
||||||
'''检查song有关文件并初始化缓存'''
|
'''检查song有关文件并初始化缓存'''
|
||||||
f = self.check_folder(Config.SONG_FILE_FOLDER_PATH)
|
f = self.check_folder(Config.SONG_FILE_FOLDER_PATH)
|
||||||
self.logger.info("Start to initialize song data...")
|
self.logger.info("Initialize song data...")
|
||||||
try:
|
try:
|
||||||
DownloadList.initialize_cache()
|
DownloadList.initialize_cache()
|
||||||
if not Config.SONG_FILE_HASH_PRE_CALCULATE:
|
if not Config.SONG_FILE_HASH_PRE_CALCULATE:
|
||||||
self.logger.info('Song file hash pre-calculate is disabled.')
|
self.logger.info('Song file hash pre-calculate is disabled.')
|
||||||
self.logger.info('Song data initialization is complete!')
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(format_exc())
|
self.logger.error(format_exc())
|
||||||
self.logger.warning('Song data initialization error!')
|
self.logger.warning('Song data initialization error!')
|
||||||
@@ -341,17 +341,28 @@ class FileChecker:
|
|||||||
def check_content_bundle(self) -> bool:
|
def check_content_bundle(self) -> bool:
|
||||||
'''检查 content bundle 有关文件并初始化缓存'''
|
'''检查 content bundle 有关文件并初始化缓存'''
|
||||||
f = self.check_folder(Config.CONTENT_BUNDLE_FOLDER_PATH)
|
f = self.check_folder(Config.CONTENT_BUNDLE_FOLDER_PATH)
|
||||||
self.logger.info("Start to initialize content bundle data...")
|
self.logger.info("Initialize content bundle data...")
|
||||||
try:
|
try:
|
||||||
BundleParser()
|
BundleParser()
|
||||||
self.logger.info('Content bundle data initialization is complete!')
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(format_exc())
|
self.logger.error(format_exc())
|
||||||
self.logger.warning('Content bundle data initialization error!')
|
self.logger.warning('Content bundle data initialization error!')
|
||||||
f = False
|
f = False
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
def check_world_map(self) -> bool:
|
||||||
|
'''检查 world map 有关文件并初始化缓存'''
|
||||||
|
f = self.check_folder(Config.WORLD_MAP_FOLDER_PATH)
|
||||||
|
self.logger.info("Initialize world map data...")
|
||||||
|
try:
|
||||||
|
MapParser()
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(format_exc())
|
||||||
|
self.logger.warning('World map data initialization error!')
|
||||||
|
f = False
|
||||||
|
return f
|
||||||
|
|
||||||
def check_before_run(self) -> bool:
|
def check_before_run(self) -> bool:
|
||||||
'''运行前检查,返回布尔值'''
|
'''运行前检查,返回布尔值'''
|
||||||
MemoryDatabase() # 初始化内存数据库
|
MemoryDatabase() # 初始化内存数据库
|
||||||
return self.check_song_file() and self.check_content_bundle() and self.check_update_database()
|
return self.check_song_file() and self.check_content_bundle() and self.check_update_database() and self.check_world_map()
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from .save import SaveData
|
|||||||
from .score import Score
|
from .score import Score
|
||||||
from .sql import Connect, Sql
|
from .sql import Connect, Sql
|
||||||
from .user import User
|
from .user import User
|
||||||
|
from .world import MapParser
|
||||||
|
|
||||||
|
|
||||||
class BaseOperation:
|
class BaseOperation:
|
||||||
@@ -88,6 +89,16 @@ class RefreshBundleCache(BaseOperation):
|
|||||||
BundleParser().re_init()
|
BundleParser().re_init()
|
||||||
|
|
||||||
|
|
||||||
|
class RefreshWorldMapCache(BaseOperation):
|
||||||
|
'''
|
||||||
|
刷新 map 缓存
|
||||||
|
'''
|
||||||
|
_name = 'refresh_world_map_cache'
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
MapParser().re_init()
|
||||||
|
|
||||||
|
|
||||||
class SaveUpdateScore(BaseOperation):
|
class SaveUpdateScore(BaseOperation):
|
||||||
'''
|
'''
|
||||||
云存档更新成绩,是覆盖式更新
|
云存档更新成绩,是覆盖式更新
|
||||||
|
|||||||
@@ -437,7 +437,7 @@ class DatabaseMigrator:
|
|||||||
def _version_2_11_3_11(self):
|
def _version_2_11_3_11(self):
|
||||||
'''
|
'''
|
||||||
2.11.3.11 版本特殊更新,调整 recent30 表结构
|
2.11.3.11 版本特殊更新,调整 recent30 表结构
|
||||||
recent30 表从 (user_id: int PK, song_id<index>: text, rating<index>: real, ...) \
|
recent30 表从 (user_id: int PK, rating<index>: real, song_id<index>: text, ...) \
|
||||||
更改为 (user_id: int PK, r_index: int PK, time_played: int, song_id: text, difficulty: int, score: int, sp, p, n, m, hp, mod, clear_type, rating: real)
|
更改为 (user_id: int PK, r_index: int PK, time_played: int, song_id: text, difficulty: int, score: int, sp, p, n, m, hp, mod, clear_type, rating: real)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|||||||
@@ -10,34 +10,46 @@ from .error import InputError, MapLocked, NoData
|
|||||||
from .item import ItemFactory
|
from .item import ItemFactory
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=128)
|
class MapParser:
|
||||||
def get_world_name(file_dir: str = Constant.WORLD_MAP_FOLDER_PATH) -> list:
|
|
||||||
'''获取所有地图名称,返回列表'''
|
|
||||||
file_list = []
|
|
||||||
for root, dirs, files in os.walk(file_dir):
|
|
||||||
for file in files:
|
|
||||||
if os.path.splitext(file)[1] == '.json':
|
|
||||||
file_list.append(os.path.splitext(file)[0])
|
|
||||||
return file_list
|
|
||||||
|
|
||||||
|
map_id_path: 'dict[str, str]' = {}
|
||||||
|
|
||||||
@lru_cache(maxsize=128)
|
def __init__(self) -> None:
|
||||||
def get_world_info(map_id: str) -> dict:
|
if not self.map_id_path:
|
||||||
'''读取json文件内容,返回字典'''
|
self.parse()
|
||||||
world_info = {}
|
|
||||||
with open(os.path.join(Constant.WORLD_MAP_FOLDER_PATH, f'{map_id}.json'), 'rb') as f:
|
|
||||||
world_info = load(f)
|
|
||||||
|
|
||||||
return world_info
|
def parse(self) -> None:
|
||||||
|
for root, dirs, files in os.walk(Constant.WORLD_MAP_FOLDER_PATH):
|
||||||
|
for file in files:
|
||||||
|
if not file.endswith('.json'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
path = os.path.join(root, file)
|
||||||
|
self.map_id_path[file[:-5]] = path
|
||||||
|
|
||||||
def get_world_all(c, user) -> list:
|
def re_init(self) -> None:
|
||||||
'''
|
self.map_id_path.clear()
|
||||||
读取所有地图信息,返回列表
|
self.get_world_info.cache_clear()
|
||||||
parameter: `user` - `User`类或子类的实例
|
self.parse()
|
||||||
'''
|
|
||||||
worlds = get_world_name()
|
@staticmethod
|
||||||
return [UserMap(c, map_id, user) for map_id in worlds]
|
@lru_cache(maxsize=128)
|
||||||
|
def get_world_info(map_id: str) -> dict:
|
||||||
|
'''读取json文件内容,返回字典'''
|
||||||
|
world_info = {}
|
||||||
|
with open(MapParser.map_id_path[map_id], 'rb') as f:
|
||||||
|
world_info = load(f)
|
||||||
|
|
||||||
|
return world_info
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_world_all(c, user) -> list:
|
||||||
|
'''
|
||||||
|
读取所有地图信息,返回列表
|
||||||
|
parameter: `user` - `User` 类或子类的实例
|
||||||
|
`c` - 数据库连接
|
||||||
|
'''
|
||||||
|
return [UserMap(c, map_id, user) for map_id in MapParser.map_id_path.keys()]
|
||||||
|
|
||||||
|
|
||||||
class Step:
|
class Step:
|
||||||
@@ -208,7 +220,7 @@ class Map:
|
|||||||
|
|
||||||
def select_map_info(self):
|
def select_map_info(self):
|
||||||
'''获取地图信息'''
|
'''获取地图信息'''
|
||||||
self.from_dict(get_world_info(self.map_id))
|
self.from_dict(MapParser.get_world_info(self.map_id))
|
||||||
|
|
||||||
|
|
||||||
class UserMap(Map):
|
class UserMap(Map):
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from flask import Blueprint, request
|
|||||||
|
|
||||||
from core.sql import Connect
|
from core.sql import Connect
|
||||||
from core.user import UserOnline
|
from core.user import UserOnline
|
||||||
from core.world import UserMap, get_world_all
|
from core.world import MapParser, UserMap
|
||||||
|
|
||||||
from .auth import auth_required
|
from .auth import auth_required
|
||||||
from .func import arc_try, success_return
|
from .func import arc_try, success_return
|
||||||
@@ -20,7 +20,7 @@ def world_all(user_id):
|
|||||||
return success_return({
|
return success_return({
|
||||||
"current_map": user.current_map.map_id,
|
"current_map": user.current_map.map_id,
|
||||||
"user_id": user_id,
|
"user_id": user_id,
|
||||||
"maps": [x.to_dict(has_map_info=True, has_rewards=True) for x in get_world_all(c, user)]
|
"maps": [x.to_dict(has_map_info=True, has_rewards=True) for x in MapParser.get_world_all(c, user)]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user