[Enhance][Bug Fix]

- For Arcaea 5.10.4
- Add support for the Link Play notification setting.
- Fix a bug that public rooms cannot be matched possibly if some players leave the room.
- Continue to fix the bug that the player cannot complete one course twice.
- Continue to fix the bug that users cannot change online settings.
This commit is contained in:
Lost-MSth
2024-09-27 00:28:56 +08:00
parent c52fda6f47
commit dc1ca344e5
10 changed files with 49 additions and 33 deletions

View File

@@ -12,7 +12,7 @@ class Config:
SONG_FILE_HASH_PRE_CALCULATE = True
GAME_API_PREFIX = '/pastatabetai/32' # str | list[str]
GAME_API_PREFIX = '/autumnequinox/33' # str | list[str]
OLD_GAME_API_PREFIX = [] # str | list[str]
ALLOW_APPVERSION = [] # list[str]

View File

@@ -1,7 +1,7 @@
from .config_manager import Config
ARCAEA_SERVER_VERSION = 'v2.11.3.18'
ARCAEA_DATABASE_VERSION = 'v2.11.3.18'
ARCAEA_SERVER_VERSION = 'v2.11.3.19'
ARCAEA_DATABASE_VERSION = 'v2.11.3.19'
ARCAEA_LOG_DATBASE_VERSION = 'v1.1'

View File

@@ -1,6 +1,5 @@
from .error import NoData
from .item import ItemFactory
from .score import Score
from .song import Chart
@@ -40,7 +39,7 @@ class Course:
self.requirements: list = []
self.charts: list = [None, None, None, None]
self.items: list = None
self.items: list = []
def to_dict(self) -> dict:
if self.course_name is None:
@@ -282,15 +281,14 @@ class CoursePlay(UserCourse):
self.user_play.course_play_state += 1
from .score import Score
if Score.get_song_state(self.clear_type) > Score.get_song_state(self.user_play.clear_type):
self.clear_type = self.user_play.clear_type
self.user_play.update_play_state_for_course()
if self.user_play.course_play_state == 4:
self.user.select_user_about_stamina()
self.items = []
if not self.is_completed:
self.user.select_user_about_stamina()
self.select_course_item()
for i in self.items:
i.user_claim_item(self.user)

View File

@@ -320,12 +320,17 @@ class MatchStore:
# 加入已有房间
for i in MatchStore.room_cache:
f = True
num = 0
for j in i['players']:
if j['player_id'] != 0 and abs(user.rating_ptt - j['rating_ptt']) >= ptt_abs:
if j['player_id'] != 0:
num += 1
if abs(user.rating_ptt - j['rating_ptt']) >= ptt_abs:
f = False
break
if f and user.calc_available_chart_num(b64decode(i['song_unlock'])) >= unlock_min and ((time() + 2) * 1000000 < i['next_state_timestamp'] or i['next_state_timestamp'] <= 0):
# 有玩家非正常退房时next_state_timestamp 不为 0有概率新玩家进不来所以使用 num 统计玩家数量
if f and user.calc_available_chart_num(b64decode(i['song_unlock'])) >= unlock_min and ((time() + 2) * 1000000 < i['next_state_timestamp'] or i['next_state_timestamp'] <= 0 or num == 1):
room = Room()
room.room_code = i['room_code']
user.c = self.c

View File

@@ -26,6 +26,10 @@ class BaseNotification:
raise NotImplementedError()
def insert(self):
self.receiver.select_user_one_column('mp_notification_enabled', True, bool)
if not self.receiver.mp_notification_enabled:
return
self.c_m.execute(
'''select max(id) from notification where user_id = ?''', (self.receiver.user_id,))
x = self.c_m.fetchone()

View File

@@ -305,7 +305,7 @@ class UserInfo(User):
self.recent_score = Score()
self.favorite_character = None
self.max_stamina_notification_enabled = False
self.mp_notification_enabled = False
self.mp_notification_enabled = True
self.prog_boost: int = 0
self.beyond_boost_gauge: float = 0
self.kanae_stored_prog: float = 0
@@ -497,7 +497,7 @@ class UserInfo(User):
"favorite_character": favorite_character_id,
"is_hide_rating": self.is_hide_rating,
"max_stamina_notification_enabled": self.max_stamina_notification_enabled,
"mp_notification_enabled": self.mp_notification_enabled
"mp_notification_enabled": self.mp_notification_enabled,
},
"user_id": self.user_id,
"name": self.name,
@@ -562,7 +562,6 @@ class UserInfo(User):
self.favorite_character = None if x[23] == - \
1 else UserCharacter(self.c, x[23])
self.max_stamina_notification_enabled = x[24] == 1
self.mp_notification_enabled = x[37] == 1
self.current_map = Map(x[25]) if x[25] is not None else Map('')
self.ticket = x[26]
self.prog_boost = x[27] if x[27] is not None else 0
@@ -578,6 +577,8 @@ class UserInfo(User):
self.beyond_boost_gauge = x[35] if x[35] else 0
self.kanae_stored_prog = x[36] if x[36] else 0
self.mp_notification_enabled = x[37] == 1
return self
def select_user(self) -> None:
@@ -664,20 +665,6 @@ class UserInfo(User):
self.rating_ptt = x[1]
self.is_hide_rating = x[2] == 1
def select_user_about_settings(self) -> None:
'''
查询 user 表有关设置的信息
'''
self.c.execute(
'''select is_hide_rating, max_stamina_notification_enabled, mp_notification_enabled from user where user_id=?''', (self.user_id,)
x = self.c.fetchone()
if not x:
raise NoData('No user.', 108, -3)
self.is_hide_rating = x[0] == 1
self.max_stamina_notification_enabled = x[1] == 1
self.mp_notification_enabled = x[2] == 1
@property
def global_rank(self) -> int:
'''用户世界排名如果超过设定最大值返回0'''
@@ -720,7 +707,7 @@ class UserInfo(User):
'''update user set world_rank_score = ? where user_id = ?''', (x[0], self.user_id))
self.world_rank_score = x[0]
def select_user_one_column(self, column_name: str, default_value=None) -> None:
def select_user_one_column(self, column_name: str, default_value=None, data_type=None) -> None:
'''
查询user表的某个属性
请注意必须是一个普通属性,不能是一个类的实例
@@ -733,7 +720,12 @@ class UserInfo(User):
if not x:
raise NoData('No user.', 108, -3)
self.__dict__[column_name] = x[0] if x[0] else default_value
data = x[0] if x[0] is not None else default_value
if data_type is not None:
data = data_type(data)
self.__dict__[column_name] = data
def update_user_one_column(self, column_name: str, value=None) -> None:
'''

View File

@@ -71,7 +71,7 @@ class InitData:
'core_ambivalent', 'core_scarlet', 'core_groove', 'core_generic', 'core_binary', 'core_colorful', 'core_course_skip_purchase', 'core_umbral', 'core_wacca', 'core_sunset', 'core_tanoc', 'core_serene']
world_songs = ["babaroque", "shadesoflight", "kanagawa", "lucifer", "anokumene", "ignotus", "rabbitintheblackroom", "qualia", "redandblue", "bookmaker", "darakunosono", "espebranch", "blacklotus", "givemeanightmare", "vividtheory", "onefr", "gekka", "vexaria3", "infinityheaven3", "fairytale3", "goodtek3", "suomi", "rugie", "faintlight", "harutopia", "goodtek", "dreaminattraction", "syro", "diode", "freefall", "grimheart", "blaster",
"cyberneciacatharsis", "monochromeprincess", "revixy", "vector", "supernova", "nhelv", "purgatorium3", "dement3", "crossover", "guardina", "axiumcrisis", "worldvanquisher", "sheriruth", "pragmatism", "gloryroad", "etherstrike", "corpssansorganes", "lostdesire", "blrink", "essenceoftwilight", "lapis", "solitarydream", "lumia3", "purpleverse", "moonheart3", "glow", "enchantedlove", "take", "lifeispiano", "vandalism", "nexttoyou3", "lostcivilization3", "turbocharger", "bookmaker3", "laqryma3", "kyogenkigo", "hivemind", "seclusion", "quonwacca3", "bluecomet", "energysynergymatrix", "gengaozo", "lastendconductor3", "antithese3", "qualia3", "kanagawa3", "heavensdoor3", "pragmatism3", "nulctrl", "avril", "ddd", "merlin3", "omakeno3", "nekonote", "sanskia", 'altair', 'mukishitsu', 'trapcrow', 'redandblue3', 'ignotus3', 'singularity3', 'dropdead3', 'arcahv', 'freefall3', 'partyvinyl3', 'tsukinimurakumo', 'mantis', 'worldfragments', 'astrawalkthrough', 'chronicle', 'trappola3', 'letsrock', 'shadesoflight3', 'teriqma3', 'impact3', 'lostemotion', 'gimmick', 'lawlesspoint', 'hybris', 'ultimatetaste', 'rgb', 'matenrou', 'dynitikos', 'amekagura', 'fantasy', 'aloneandlorn', 'felys', 'onandon', 'hotarubinoyuki', 'oblivia3', 'libertas3', 'einherjar3', 'purpleverse3', 'viciousheroism3', 'inkarusi3', 'cyberneciacatharsis3', 'alephzero', 'hellohell', 'ichirin', 'awakeninruins', 'morningloom', 'lethalvoltage', 'leaveallbehind', 'desive', 'oldschoolsalvage', 'distortionhuman', 'epitaxy']
"cyberneciacatharsis", "monochromeprincess", "revixy", "vector", "supernova", "nhelv", "purgatorium3", "dement3", "crossover", "guardina", "axiumcrisis", "worldvanquisher", "sheriruth", "pragmatism", "gloryroad", "etherstrike", "corpssansorganes", "lostdesire", "blrink", "essenceoftwilight", "lapis", "solitarydream", "lumia3", "purpleverse", "moonheart3", "glow", "enchantedlove", "take", "lifeispiano", "vandalism", "nexttoyou3", "lostcivilization3", "turbocharger", "bookmaker3", "laqryma3", "kyogenkigo", "hivemind", "seclusion", "quonwacca3", "bluecomet", "energysynergymatrix", "gengaozo", "lastendconductor3", "antithese3", "qualia3", "kanagawa3", "heavensdoor3", "pragmatism3", "nulctrl", "avril", "ddd", "merlin3", "omakeno3", "nekonote", "sanskia", 'altair', 'mukishitsu', 'trapcrow', 'redandblue3', 'ignotus3', 'singularity3', 'dropdead3', 'arcahv', 'freefall3', 'partyvinyl3', 'tsukinimurakumo', 'mantis', 'worldfragments', 'astrawalkthrough', 'chronicle', 'trappola3', 'letsrock', 'shadesoflight3', 'teriqma3', 'impact3', 'lostemotion', 'gimmick', 'lawlesspoint', 'hybris', 'ultimatetaste', 'rgb', 'matenrou', 'dynitikos', 'amekagura', 'fantasy', 'aloneandlorn', 'felys', 'onandon', 'hotarubinoyuki', 'oblivia3', 'libertas3', 'einherjar3', 'purpleverse3', 'viciousheroism3', 'inkarusi3', 'cyberneciacatharsis3', 'alephzero', 'hellohell', 'ichirin', 'awakeninruins', 'morningloom', 'lethalvoltage', 'leaveallbehind', 'desive', 'oldschoolsalvage', 'distortionhuman', 'epitaxy', 'hailstone', 'furetemitai']
world_unlocks = ["scenery_chap1", "scenery_chap2",
"scenery_chap3", "scenery_chap4", "scenery_chap5", "scenery_chap6", "scenery_chap7", "scenery_beyond"]

View File

@@ -1900,5 +1900,23 @@
],
"orig_price": 100,
"price": 100
},
{
"name": "gensounosatellite",
"items": [
{
"type": "single",
"id": "gensounosatellite",
"is_available": true
},
{
"type": "core",
"amount": 1,
"id": "core_generic",
"is_available": true
}
],
"orig_price": 100,
"price": 100
}
]

View File

@@ -36,7 +36,7 @@ stamina int,
world_mode_locked_end_ts int,
beyond_boost_gauge real default 0,
kanae_stored_prog real default 0,
mp_notification_enabled int
mp_notification_enabled int default 1
);
create table if not exists login(access_token text,
user_id int,

View File

@@ -158,7 +158,6 @@ def sys_set(user_id, set_arg):
else:
value = 'true' == value
if set_arg in ('is_hide_rating', 'max_stamina_notification_enabled', 'mp_notification_enabled'):
user.select_user_about_settings()
user.update_user_one_column(set_arg, value)
return success_return(user.to_dict())