mirror of
https://github.com/Lost-MSth/Arcaea-server.git
synced 2025-12-14 08:06:23 +08:00
Update to v2.8.6 without release
- Code refactoring - Update the song database - Fix a bug of the friend system which arose in the last version - Fix a bug of duplicate calculating finishing states when players finish playing the chart in Link Play.
This commit is contained in:
@@ -1,54 +1,72 @@
|
||||
from setting import Config
|
||||
from .error import ArcError, NoData
|
||||
from .error import ArcError, InputError, NoData, ItemNotEnough
|
||||
from .constant import Constant
|
||||
from .item import Item
|
||||
from .item import Item, ItemCore
|
||||
|
||||
|
||||
class Level:
|
||||
max_level = None
|
||||
mid_level = 20
|
||||
min_level = 1
|
||||
level = None
|
||||
exp = None
|
||||
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
self.max_level = None
|
||||
self.level = None
|
||||
self.exp = None
|
||||
|
||||
@property
|
||||
def level_exp(self):
|
||||
return Constant.LEVEL_STEPS[self.level]
|
||||
|
||||
def add_exp(self, exp_addition: float):
|
||||
# 添加经验计算
|
||||
|
||||
exp = self.exp + exp_addition
|
||||
|
||||
if exp >= Constant.LEVEL_STEPS[self.max_level]:
|
||||
self.exp = Constant.LEVEL_STEPS[self.max_level]
|
||||
self.level = self.max_level
|
||||
|
||||
a = []
|
||||
b = []
|
||||
for i in Constant.LEVEL_STEPS:
|
||||
a.append(i)
|
||||
b.append(Constant.LEVEL_STEPS[i])
|
||||
|
||||
if exp < b[0]: # 向下溢出,是异常状态,不该被try捕获,不然数据库无法回滚
|
||||
raise ValueError('EXP value error.')
|
||||
|
||||
i = len(a) - 1
|
||||
while exp < b[i]:
|
||||
i -= 1
|
||||
|
||||
self.exp = exp
|
||||
self.level = a[i]
|
||||
|
||||
|
||||
class Skill:
|
||||
skill_id = None
|
||||
skill_id_uncap = None
|
||||
skill_unlock_level = None
|
||||
skill_requires_uncap = None
|
||||
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
self.skill_id = None
|
||||
self.skill_id_uncap = None
|
||||
self.skill_unlock_level = None
|
||||
self.skill_requires_uncap = None
|
||||
|
||||
|
||||
class Core(Item):
|
||||
item_type = 'core'
|
||||
amount = None
|
||||
|
||||
def __init__(self, core_type: str = '', amount: int = 0) -> None:
|
||||
super().__init__()
|
||||
self.item_id = core_type
|
||||
self.amount = amount
|
||||
self.is_available = True
|
||||
|
||||
def to_dict(self):
|
||||
return {'core_type': self.item_id, 'amount': self.amount}
|
||||
|
||||
|
||||
class CharacterValue:
|
||||
start = None
|
||||
mid = None
|
||||
end = None
|
||||
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
def __init__(self, start: float = 0, mid: float = 0, end: float = 0) -> None:
|
||||
self.set_parameter(start, mid, end)
|
||||
|
||||
@staticmethod
|
||||
def _calc_char_value_20(level, stata, statb, lva=1, lvb=20):
|
||||
@@ -82,20 +100,19 @@ class CharacterValue:
|
||||
|
||||
|
||||
class Character:
|
||||
character_id = None
|
||||
name = None
|
||||
char_type = None
|
||||
is_uncapped = None
|
||||
is_uncapped_override = None
|
||||
skill = Skill()
|
||||
level = Level()
|
||||
frag = CharacterValue()
|
||||
prog = CharacterValue()
|
||||
overdrive = CharacterValue()
|
||||
uncap_cores = None
|
||||
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
self.character_id = None
|
||||
self.name = None
|
||||
self.char_type = None
|
||||
self.is_uncapped = None
|
||||
self.is_uncapped_override = None
|
||||
self.skill = Skill()
|
||||
self.level = Level()
|
||||
self.frag = CharacterValue()
|
||||
self.prog = CharacterValue()
|
||||
self.overdrive = CharacterValue()
|
||||
self.uncap_cores = []
|
||||
self.voice = None
|
||||
|
||||
@property
|
||||
def uncap_cores_to_dict(self):
|
||||
@@ -103,6 +120,7 @@ class Character:
|
||||
|
||||
|
||||
class UserCharacter(Character):
|
||||
database_table_name = 'user_char_full' if Config.CHARACTER_FULL_UNLOCK else 'user_char'
|
||||
|
||||
def __init__(self, c, character_id=None) -> None:
|
||||
super().__init__()
|
||||
@@ -122,12 +140,10 @@ class UserCharacter(Character):
|
||||
def select_character_uncap_condition(self, user):
|
||||
# parameter: user - User类或子类的实例
|
||||
# 获取此角色的觉醒信息
|
||||
if Config.CHARACTER_FULL_UNLOCK:
|
||||
self.c.execute('''select is_uncapped, is_uncapped_override from user_char_full where user_id = :a and character_id = :b''',
|
||||
{'a': user.user_id, 'b': self.character_id})
|
||||
else:
|
||||
self.c.execute('''select is_uncapped, is_uncapped_override from user_char where user_id = :a and character_id = :b''',
|
||||
{'a': user.user_id, 'b': self.character_id})
|
||||
|
||||
self.c.execute('''select is_uncapped, is_uncapped_override from %s where user_id = :a and character_id = :b''' % self.database_table_name,
|
||||
{'a': user.user_id, 'b': self.character_id})
|
||||
|
||||
x = self.c.fetchone()
|
||||
if not x:
|
||||
raise NoData('The character of the user does not exist.')
|
||||
@@ -138,12 +154,10 @@ class UserCharacter(Character):
|
||||
def select_character_info(self, user):
|
||||
# parameter: user - User类或子类的实例
|
||||
# 获取所给用户此角色信息
|
||||
if not Config.CHARACTER_FULL_UNLOCK:
|
||||
self.c.execute('''select * from user_char a,character b where a.user_id=? and a.character_id=b.character_id and a.character_id=?''',
|
||||
(user.user_id, self.character_id))
|
||||
else:
|
||||
self.c.execute('''select * from user_char_full a,character b where a.user_id=? and a.character_id=b.character_id and a.character_id=?''',
|
||||
(user.user_id, self.character_id))
|
||||
|
||||
self.c.execute('''select * from %s a,character b where a.user_id=? and a.character_id=b.character_id and a.character_id=?''' % self.database_table_name,
|
||||
(user.user_id, self.character_id))
|
||||
|
||||
y = self.c.fetchone()
|
||||
if y is None:
|
||||
raise NoData('The character of the user does not exist.')
|
||||
@@ -162,37 +176,40 @@ class UserCharacter(Character):
|
||||
self.skill.skill_id_uncap = y[21]
|
||||
self.skill.skill_unlock_level = y[19]
|
||||
self.skill.skill_requires_uncap = y[20] == 1
|
||||
|
||||
if self.character_id == 21 or self.character_id == 46:
|
||||
self.voice = [0, 1, 2, 3, 100, 1000, 1001]
|
||||
|
||||
self.select_character_core()
|
||||
|
||||
@property
|
||||
def to_dict(self):
|
||||
return {"is_uncapped_override": self.is_uncapped_override,
|
||||
"is_uncapped": self.is_uncapped,
|
||||
"uncap_cores": self.uncap_cores_to_dict,
|
||||
"char_type": self.char_type,
|
||||
"skill_id_uncap": self.skill.skill_id_uncap,
|
||||
"skill_requires_uncap": self.skill.skill_requires_uncap,
|
||||
"skill_unlock_level": self.skill.skill_unlock_level,
|
||||
"skill_id": self.skill.skill_id,
|
||||
"overdrive": self.overdrive.get_value(self.level),
|
||||
"prog": self.overdrive.get_value(self.level),
|
||||
"frag": self.overdrive.get_value(self.level),
|
||||
"level_exp": self.level.level_exp,
|
||||
"exp": self.level.exp,
|
||||
"level": self.level.level,
|
||||
"name": self.name,
|
||||
"character_id": self.character_id
|
||||
}
|
||||
r = {"is_uncapped_override": self.is_uncapped_override,
|
||||
"is_uncapped": self.is_uncapped,
|
||||
"uncap_cores": self.uncap_cores_to_dict,
|
||||
"char_type": self.char_type,
|
||||
"skill_id_uncap": self.skill.skill_id_uncap,
|
||||
"skill_requires_uncap": self.skill.skill_requires_uncap,
|
||||
"skill_unlock_level": self.skill.skill_unlock_level,
|
||||
"skill_id": self.skill.skill_id,
|
||||
"overdrive": self.overdrive.get_value(self.level),
|
||||
"prog": self.overdrive.get_value(self.level),
|
||||
"frag": self.overdrive.get_value(self.level),
|
||||
"level_exp": self.level.level_exp,
|
||||
"exp": self.level.exp,
|
||||
"level": self.level.level,
|
||||
"name": self.name,
|
||||
"character_id": self.character_id
|
||||
}
|
||||
if self.voice:
|
||||
r['voice'] = self.voice
|
||||
return r
|
||||
|
||||
def change_uncap_override(self, user):
|
||||
# parameter: user - User类或子类的实例
|
||||
# 切换觉醒状态
|
||||
if not Config.CHARACTER_FULL_UNLOCK:
|
||||
self.c.execute('''select is_uncapped, is_uncapped_override from user_char where user_id = :a and character_id = :b''',
|
||||
{'a': user.user_id, 'b': self.character_id})
|
||||
else:
|
||||
self.c.execute('''select is_uncapped, is_uncapped_override from user_char_full where user_id = :a and character_id = :b''',
|
||||
{'a': user.user_id, 'b': self.character_id})
|
||||
self.c.execute('''select is_uncapped, is_uncapped_override from %s where user_id = :a and character_id = :b''' % self.database_table_name,
|
||||
{'a': user.user_id, 'b': self.character_id})
|
||||
|
||||
x = self.c.fetchone()
|
||||
if x is None or x[0] == 0:
|
||||
@@ -201,13 +218,80 @@ class UserCharacter(Character):
|
||||
self.c.execute('''update user set is_char_uncapped_override = :a where user_id = :b''', {
|
||||
'a': 1 if x[1] == 0 else 0, 'b': user.user_id})
|
||||
|
||||
if not Config.CHARACTER_FULL_UNLOCK:
|
||||
self.c.execute('''update user_char set is_uncapped_override = :a where user_id = :b and character_id = :c''', {
|
||||
'a': 1 if x[1] == 0 else 0, 'b': user.user_id, 'c': self.character_id})
|
||||
else:
|
||||
self.c.execute('''update user_char_full set is_uncapped_override = :a where user_id = :b and character_id = :c''', {
|
||||
'a': 1 if x[1] == 0 else 0, 'b': user.user_id, 'c': self.character_id})
|
||||
self.c.execute('''update %s set is_uncapped_override = :a where user_id = :b and character_id = :c''' % self.database_table_name, {
|
||||
'a': 1 if x[1] == 0 else 0, 'b': user.user_id, 'c': self.character_id})
|
||||
|
||||
def character_uncap(self):
|
||||
self.is_uncapped_override = x[1] == 0
|
||||
|
||||
def character_uncap(self, user):
|
||||
# parameter: user - User类或子类的实例
|
||||
# 觉醒角色
|
||||
pass
|
||||
if Config.CHARACTER_FULL_UNLOCK:
|
||||
# 全解锁了你觉醒个鬼啊
|
||||
raise ArcError('All characters are available.')
|
||||
|
||||
if not self.uncap_cores:
|
||||
self.select_character_core()
|
||||
|
||||
if self.is_uncapped is None:
|
||||
self.c.execute(
|
||||
'''select is_uncapped from user_char where user_id=? and character_id=?''', (user.user_id, self.character_id))
|
||||
x = self.c.fetchone()
|
||||
if x and x[0] == 1:
|
||||
raise ArcError('The character has been uncapped.')
|
||||
elif self.is_uncapped:
|
||||
raise ArcError('The character has been uncapped.')
|
||||
|
||||
for i in self.uncap_cores:
|
||||
self.c.execute(
|
||||
'''select amount from user_item where user_id=? and item_id=? and type="core"''', (user.user_id, i.item_id))
|
||||
y = self.c.fetchone()
|
||||
if not y or i.amount > y[0]:
|
||||
raise ItemNotEnough('The cores are not enough.')
|
||||
|
||||
for i in self.uncap_cores:
|
||||
ItemCore(self.c, i, reverse=True).user_claim_item(user)
|
||||
|
||||
self.c.execute('''update user_char set is_uncapped=1, is_uncapped_override=0 where user_id=? and character_id=?''',
|
||||
(user.user_id, self.character_id))
|
||||
|
||||
self.is_uncapped = True
|
||||
self.is_uncapped_override = False
|
||||
|
||||
def upgrade(self, user, exp_addition: float):
|
||||
# parameter: user - User类或子类的实例
|
||||
# 升级角色
|
||||
if Config.CHARACTER_FULL_UNLOCK:
|
||||
# 全解锁了你升级个鬼啊
|
||||
raise ArcError('All characters are available.')
|
||||
|
||||
if self.level.exp is None:
|
||||
self.select_character_info(user)
|
||||
|
||||
if self.is_uncapped is None:
|
||||
self.c.execute(
|
||||
'''select is_uncapped from user_char where user_id=? and character_id=?''', (user.user_id, self.character_id))
|
||||
x = self.c.fetchone()
|
||||
if x:
|
||||
self.is_uncapped = x[0] == 1
|
||||
|
||||
self.level.max_level = 30 if self.is_uncapped else 20
|
||||
self.level.add_exp(exp_addition)
|
||||
|
||||
self.c.execute('''update user_char set level=?, exp=? where user_id=? and character_id=?''',
|
||||
(self.level.level, self.level.exp, user.user_id, self.character_id))
|
||||
|
||||
def upgrade_by_core(self, user, core):
|
||||
# parameter: user - User类或子类的实例
|
||||
# core - ItemCore类或子类的实例
|
||||
# 以太之滴升级,注意这里core.amount应该是负数
|
||||
|
||||
if core.item_id != 'core_generic':
|
||||
raise ArcError('Core type error.')
|
||||
|
||||
if core.amount >= 0:
|
||||
raise InputError(
|
||||
'The amount of `core_generic` should be negative.')
|
||||
|
||||
core.user_claim_item(user)
|
||||
self.upgrade(user, - core.amount * Constant.CORE_EXP)
|
||||
|
||||
@@ -1,17 +1,9 @@
|
||||
class ArcError(Exception):
|
||||
api_error_code = -999
|
||||
error_code = 108
|
||||
message = None
|
||||
extra_data = None
|
||||
|
||||
def __init__(self, message=None, error_code=None, api_error_code=None, extra_data=None) -> None:
|
||||
def __init__(self, message=None, error_code=108, api_error_code=-999, extra_data=None) -> None:
|
||||
self.message = message
|
||||
if error_code:
|
||||
self.error_code = error_code
|
||||
if api_error_code:
|
||||
self.api_error_code = api_error_code
|
||||
if extra_data:
|
||||
self.extra_data = extra_data
|
||||
self.error_code = error_code
|
||||
self.api_error_code = api_error_code
|
||||
self.extra_data = extra_data
|
||||
|
||||
def __str__(self) -> str:
|
||||
return repr(self.message)
|
||||
@@ -19,7 +11,7 @@ class ArcError(Exception):
|
||||
|
||||
class InputError(ArcError):
|
||||
# 输入类型错误
|
||||
def __init__(self, message=None, error_code=None, api_error_code=-100, extra_data=None) -> None:
|
||||
def __init__(self, message=None, error_code=108, api_error_code=-100, extra_data=None) -> None:
|
||||
super().__init__(message, error_code, api_error_code, extra_data)
|
||||
|
||||
|
||||
@@ -46,6 +38,24 @@ class UserBan(ArcError):
|
||||
super().__init__(message, error_code, api_error_code, extra_data)
|
||||
|
||||
|
||||
class ItemNotEnough(ArcError):
|
||||
# 物品数量不足
|
||||
def __init__(self, message=None, error_code=-6, api_error_code=-999, extra_data=None) -> None:
|
||||
super().__init__(message, error_code, api_error_code, extra_data)
|
||||
|
||||
|
||||
class ItemUnavailable(ArcError):
|
||||
# 物品不可用
|
||||
def __init__(self, message=None, error_code=-6, api_error_code=-999, extra_data=None) -> None:
|
||||
super().__init__(message, error_code, api_error_code, extra_data)
|
||||
|
||||
|
||||
class FriendError(ArcError):
|
||||
# 好友系统出错
|
||||
def __init__(self, message=None, error_code=108, api_error_code=-999, extra_data=None) -> None:
|
||||
super().__init__(message, error_code, api_error_code, extra_data)
|
||||
|
||||
|
||||
class NoAccess(ArcError):
|
||||
# 无权限
|
||||
pass
|
||||
|
||||
@@ -1,7 +1,185 @@
|
||||
from sympy import Nor
|
||||
from .error import NoData, ItemUnavailable, ItemNotEnough, InputError
|
||||
|
||||
|
||||
class Item:
|
||||
item_id = None
|
||||
item_type = None
|
||||
is_available = None
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.item_id = None
|
||||
self.__amount = None
|
||||
self.is_available = None
|
||||
|
||||
@property
|
||||
def amount(self):
|
||||
return self.__amount
|
||||
|
||||
@amount.setter
|
||||
def amount(self, value: int):
|
||||
self.__amount = int(value)
|
||||
|
||||
def user_claim_item(self, user):
|
||||
# parameter: user - User类或子类的实例
|
||||
pass
|
||||
|
||||
|
||||
class NormalItem(Item):
|
||||
def __init__(self, c) -> None:
|
||||
super().__init__()
|
||||
self.c = c
|
||||
|
||||
def user_claim_item(self, user):
|
||||
if not self.is_available:
|
||||
self.c.execute(
|
||||
'''select is_available from item where item_id=? and type=?''', (self.item_id, self.item_type))
|
||||
x = self.c.fetchone()
|
||||
if x:
|
||||
if x[0] == 0:
|
||||
self.is_available = False
|
||||
raise ItemUnavailable('The item is unavailable.')
|
||||
else:
|
||||
self.is_available = True
|
||||
else:
|
||||
raise NoData('No item data.')
|
||||
|
||||
self.c.execute('''select exists(select * from user_item where user_id=? and item_id=? and type=?)''',
|
||||
(user.user_id, self.item_id, self.item_type))
|
||||
if self.c.fetchone() == (0,):
|
||||
self.c.execute('''insert into user_item values(:a,:b,:c,1)''',
|
||||
{'a': user.user_id, 'b': self.item_id, 'c': self.item_type})
|
||||
|
||||
|
||||
class PositiveItem(Item):
|
||||
def __init__(self, c) -> None:
|
||||
super().__init__()
|
||||
self.c = c
|
||||
|
||||
def user_claim_item(self, user):
|
||||
self.c.execute('''select amount from user_item where user_id=? and item_id=? and type=?''',
|
||||
(user.user_id, self.item_id, self.item_type))
|
||||
x = self.c.fetchone()
|
||||
if x:
|
||||
if x[0] + self.amount < 0: # 数量不足
|
||||
raise ItemNotEnough(
|
||||
'The user does not have enough `%s`.' % self.item_id)
|
||||
self.c.execute('''update user_item set amount=? where user_id=? and item_id=? and type=?''',
|
||||
(x[0]+self.amount, user.user_id, self.item_id, self.item_type))
|
||||
else:
|
||||
if self.amount < 0: # 添加数量错误
|
||||
raise InputError(
|
||||
'The amount of `%s` is wrong.' % self.item_id)
|
||||
self.c.execute('''insert into user_item values(?,?,?,?)''',
|
||||
(user.user_id, self.item_id, self.item_type, self.amount))
|
||||
|
||||
|
||||
class ItemCore(PositiveItem):
|
||||
item_type = 'core'
|
||||
|
||||
def __init__(self, c, core=None, reverse=False) -> None:
|
||||
super().__init__(c)
|
||||
self.is_available = True
|
||||
if core:
|
||||
self.item_id = core.item_id
|
||||
self.amount = - core.amount if reverse else core.amount
|
||||
|
||||
|
||||
class ItemCharacter(Item):
|
||||
item_type = 'character'
|
||||
|
||||
def __init__(self, c) -> None:
|
||||
super().__init__()
|
||||
self.c = c
|
||||
self.is_available = True
|
||||
|
||||
def set_id(self, character_id):
|
||||
# 将name: str转为character_id: int存到item_id里
|
||||
if character_id.isdigit():
|
||||
self.item_id = int(character_id)
|
||||
else:
|
||||
self.c.execute(
|
||||
'''select character_id from character where name=?''', (character_id,))
|
||||
x = self.c.fetchone()
|
||||
if x:
|
||||
self.item_id = x[0]
|
||||
else:
|
||||
raise NoData('No character `%s`.' % character_id)
|
||||
|
||||
def user_claim_item(self, user):
|
||||
self.c.execute(
|
||||
'''select exists(select * from user_char where user_id=? and character_id=?)''', (user.user_id, self.item_id))
|
||||
if self.c.fetchone() == (0,):
|
||||
self.c.execute(
|
||||
'''insert into user_char values(?,?,1,0,0,0)''', (user.user_id, self.item_id))
|
||||
|
||||
|
||||
class Memory(Item):
|
||||
item_type = 'memory'
|
||||
|
||||
def __init__(self, c) -> None:
|
||||
super().__init__()
|
||||
self.c = c
|
||||
self.is_available = True
|
||||
|
||||
def user_claim_item(self, user):
|
||||
self.c.execute(
|
||||
'''select ticket from user where user_id=?''', (user.user_id,))
|
||||
x = self.c.fetchone()
|
||||
if x is not None:
|
||||
self.c.execute('''update user set ticket=? where user_id=?''',
|
||||
(x[0]+self.amount, user.user_id))
|
||||
else:
|
||||
raise NoData('The ticket of the user is null.')
|
||||
|
||||
|
||||
class Anni5tix(PositiveItem):
|
||||
item_type = 'anni5tix'
|
||||
|
||||
def __init__(self, c) -> None:
|
||||
super().__init__(c)
|
||||
self.is_available = True
|
||||
|
||||
|
||||
class WorldSong(NormalItem):
|
||||
item_type = 'world_song'
|
||||
|
||||
def __init__(self, c) -> None:
|
||||
super().__init__(c)
|
||||
|
||||
|
||||
class WorldUnlock(NormalItem):
|
||||
item_type = 'world_unlock'
|
||||
|
||||
def __init__(self, c) -> None:
|
||||
super().__init__(c)
|
||||
|
||||
|
||||
class Single(NormalItem):
|
||||
item_type = 'single'
|
||||
|
||||
def __init__(self, c) -> None:
|
||||
super().__init__(c)
|
||||
|
||||
|
||||
class Pack(NormalItem):
|
||||
item_type = 'pack'
|
||||
|
||||
def __init__(self, c) -> None:
|
||||
super().__init__(c)
|
||||
|
||||
|
||||
def get_user_cores(c, user) -> list:
|
||||
# parameter: user - User类或子类的实例
|
||||
# 得到用户的cores,返回字典列表
|
||||
r = []
|
||||
c.execute(
|
||||
'''select item_id, amount from user_item where user_id = ? and type="core"''', (user.user_id,))
|
||||
x = c.fetchall()
|
||||
if x:
|
||||
for i in x:
|
||||
if i[1]:
|
||||
amount = i[1]
|
||||
else:
|
||||
amount = 0
|
||||
r.append({'core_type': i[0], 'amount': amount})
|
||||
|
||||
return r
|
||||
|
||||
73
latest version/core/score.py
Normal file
73
latest version/core/score.py
Normal file
@@ -0,0 +1,73 @@
|
||||
from .song import Chart
|
||||
|
||||
|
||||
class Score:
|
||||
def __init__(self) -> None:
|
||||
self.song = Chart()
|
||||
self.score = None
|
||||
self.shiny_perfect_count = None
|
||||
self.perfect_count = None
|
||||
self.near_count = None
|
||||
self.miss_count = None
|
||||
self.health = None
|
||||
self.modifier = None
|
||||
self.time_played = None
|
||||
self.best_clear_type = None
|
||||
self.clear_type = None
|
||||
self.rating = None
|
||||
|
||||
def set_score(self, score: int, shiny_perfect_count: int, perfect_count: int, near_count: int, miss_count: int, health: int, modifier: int, time_played: int, clear_type: int):
|
||||
self.score = score
|
||||
self.shiny_perfect_count = shiny_perfect_count
|
||||
self.perfect_count = perfect_count
|
||||
self.near_count = near_count
|
||||
self.miss_count = miss_count
|
||||
self.health = health
|
||||
self.modifier = modifier
|
||||
self.time_played = time_played
|
||||
self.clear_type = clear_type
|
||||
|
||||
@property
|
||||
def is_valid(self) -> bool:
|
||||
# 分数有效性检查
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def calculate_rating(defnum: int, score: int) -> float:
|
||||
# 计算rating,-1视作Unrank
|
||||
if not defnum or defnum <= 0:
|
||||
# 谱面没定数或者定数小于等于0被视作Unrank
|
||||
return -1
|
||||
|
||||
if score >= 10000000:
|
||||
ptt = defnum + 2
|
||||
elif score < 9800000:
|
||||
ptt = defnum + (score-9500000) / 300000
|
||||
if ptt < 0:
|
||||
ptt = 0
|
||||
else:
|
||||
ptt = defnum + 1 + (score-9800000) / 200000
|
||||
|
||||
return ptt
|
||||
|
||||
def get_rating_by_calc(self) -> float:
|
||||
# 通过计算得到本成绩的rating
|
||||
self.rating = self.calculate_rating(self.song.defnum, self.score)
|
||||
return self.rating
|
||||
|
||||
@property
|
||||
def to_dict(self) -> dict:
|
||||
return {
|
||||
"rating": self.rating,
|
||||
"modifier": self.modifier,
|
||||
"time_played": self.time_played,
|
||||
"health": self.health,
|
||||
"clear_type": self.clear_type,
|
||||
"miss_count": self.miss_count,
|
||||
"near_count": self.near_count,
|
||||
"perfect_count": self.perfect_count,
|
||||
"shiny_perfect_count": self.shiny_perfect_count,
|
||||
"score": self.score,
|
||||
"difficulty": self.song.difficulty,
|
||||
"song_id": self.song.song_id
|
||||
}
|
||||
7
latest version/core/song.py
Normal file
7
latest version/core/song.py
Normal file
@@ -0,0 +1,7 @@
|
||||
class Chart:
|
||||
# defnum: chart const * 10
|
||||
|
||||
def __init__(self, song_id: str = None, difficulty: int = None, defnum: int = None) -> None:
|
||||
self.song_id = song_id
|
||||
self.difficulty = difficulty
|
||||
self.defnum = defnum
|
||||
@@ -20,14 +20,17 @@ class Connect():
|
||||
return self.c
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
if exc_type is not None:
|
||||
if self.conn:
|
||||
self.conn.rollback()
|
||||
|
||||
current_app.logger.error(
|
||||
traceback.format_exception(exc_type, exc_val, exc_tb))
|
||||
|
||||
if self.conn:
|
||||
self.conn.commit()
|
||||
self.conn.close()
|
||||
|
||||
if exc_type is not None:
|
||||
current_app.logger.error(
|
||||
traceback.format_exception(exc_type, exc_val, exc_tb))
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from .error import ArcError, InputError, DataExist, NoAccess, NoData, UserBan
|
||||
from .error import ArcError, InputError, DataExist, NoAccess, NoData, UserBan, FriendError
|
||||
from .constant import Constant
|
||||
from .character import UserCharacter
|
||||
from .score import Score
|
||||
from .world import Map
|
||||
from .item import get_user_cores
|
||||
from setting import Config
|
||||
import hashlib
|
||||
import base64
|
||||
@@ -8,23 +11,42 @@ import time
|
||||
from os import urandom
|
||||
|
||||
|
||||
class User:
|
||||
name = None
|
||||
email = None
|
||||
password = None
|
||||
user_id = None
|
||||
user_code = None
|
||||
def code_get_id(c, user_code: str) -> int:
|
||||
# 用user_code获取user_id
|
||||
|
||||
c.execute('''select user_id from user where user_code = :a''',
|
||||
{'a': user_code})
|
||||
x = c.fetchone()
|
||||
|
||||
if x is not None:
|
||||
user_id = int(x[0])
|
||||
else:
|
||||
raise NoData('No user.', 401, -3)
|
||||
|
||||
return user_id
|
||||
|
||||
|
||||
class User:
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
self.name = None
|
||||
self.email = None
|
||||
self.password = None
|
||||
self.user_id = None
|
||||
self.user_code = None
|
||||
|
||||
self.join_date = None
|
||||
self.rating_ptt = None
|
||||
|
||||
self.ticket = None
|
||||
self.world_rank_score = None
|
||||
self.ban_flag = None
|
||||
|
||||
|
||||
class UserRegister(User):
|
||||
hash_pwd = None
|
||||
|
||||
def __init__(self, c) -> None:
|
||||
super().__init__()
|
||||
self.c = c
|
||||
self.hash_pwd = None
|
||||
|
||||
def set_name(self, name: str):
|
||||
if 3 <= len(name) <= 16:
|
||||
@@ -115,15 +137,14 @@ class UserRegister(User):
|
||||
|
||||
class UserLogin(User):
|
||||
# 密码和token的加密方式为 SHA-256
|
||||
device_id = None
|
||||
ip = None
|
||||
hash_pwd = None
|
||||
token = None
|
||||
now = 0
|
||||
|
||||
def __init__(self, c) -> None:
|
||||
super().__init__()
|
||||
self.c = c
|
||||
self.device_id = None
|
||||
self.ip = None
|
||||
self.hash_pwd = None
|
||||
self.token = None
|
||||
self.now = 0
|
||||
|
||||
def set_name(self, name: str):
|
||||
self.name = name
|
||||
@@ -230,11 +251,10 @@ class UserLogin(User):
|
||||
|
||||
|
||||
class UserAuth(User):
|
||||
token = None
|
||||
|
||||
def __init__(self, c) -> None:
|
||||
super().__init__()
|
||||
self.c = c
|
||||
self.token = None
|
||||
|
||||
def token_get_id(self):
|
||||
# 用token获取id,没有考虑不同用户token相同情况,说不定会有bug
|
||||
@@ -248,33 +268,155 @@ class UserAuth(User):
|
||||
|
||||
return self.user_id
|
||||
|
||||
def code_get_id(self):
|
||||
# 用user_code获取id
|
||||
|
||||
self.c.execute('''select user_id from user where user_code = :a''',
|
||||
{'a': self.user_code})
|
||||
x = self.c.fetchone()
|
||||
|
||||
if x is not None:
|
||||
self.user_id = x[0]
|
||||
else:
|
||||
raise NoData('No user.', 401, -3)
|
||||
|
||||
return self.user_id
|
||||
|
||||
|
||||
class UserOnline(User):
|
||||
character = None
|
||||
|
||||
def __init__(self, c, user_id=None) -> None:
|
||||
super().__init__()
|
||||
self.c = c
|
||||
self.user_id = user_id
|
||||
self.character = None
|
||||
self.is_skill_sealed = False
|
||||
self.is_hide_rating = False
|
||||
self.recent_score = Score()
|
||||
self.favorite_character = -1
|
||||
self.max_stamina_notification_enabled = False
|
||||
self.prog_boost = 0
|
||||
|
||||
self.__cores = None
|
||||
self.__friends = None
|
||||
|
||||
@property
|
||||
def cores(self) -> list:
|
||||
if self.__cores is None:
|
||||
self.__cores = get_user_cores(self.c, self)
|
||||
|
||||
return self.__cores
|
||||
|
||||
@property
|
||||
def friends(self) -> list:
|
||||
# 得到用户的朋友列表
|
||||
if self.__friends is None:
|
||||
self.c.execute('''select user_id_other from friend where user_id_me = :user_id''', {
|
||||
'user_id': self.user_id})
|
||||
x = self.c.fetchall()
|
||||
s = []
|
||||
if x != [] and x[0][0] is not None:
|
||||
for i in x:
|
||||
self.c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''',
|
||||
{'x': i[0], 'y': self.user_id})
|
||||
|
||||
is_mutual = True if self.c.fetchone() == (1,) else False
|
||||
|
||||
you = UserOnline(self.c, i[0])
|
||||
you.select_user()
|
||||
character = you.character if you.favorite_character is None else you.favorite_character
|
||||
character.select_character_uncap_condition(you)
|
||||
|
||||
rating = you.rating_ptt if not you.is_hide_rating else -1
|
||||
|
||||
s.append({
|
||||
"is_mutual": is_mutual,
|
||||
"is_char_uncapped_override": character.is_uncapped_override,
|
||||
"is_char_uncapped": character.is_uncapped,
|
||||
"is_skill_sealed": you.is_skill_sealed,
|
||||
"rating": rating,
|
||||
"join_date": you.join_date,
|
||||
"character": character.character_id,
|
||||
"recent_score": you.recent_score_list,
|
||||
"name": you.name,
|
||||
"user_id": you.user_id
|
||||
})
|
||||
s.sort(key=lambda item: item["recent_score"][0]["time_played"] if len(
|
||||
item["recent_score"]) > 0 else 0, reverse=True)
|
||||
self.__friends = s
|
||||
|
||||
return self.__friends
|
||||
|
||||
@property
|
||||
def recent_score_list(self) -> list:
|
||||
# 用户最近一次成绩,是列表
|
||||
if self.name is None:
|
||||
self.select_user()
|
||||
|
||||
if self.recent_score.song.song_id is None:
|
||||
return []
|
||||
|
||||
self.c.execute('''select best_clear_type from best_score where user_id=:u and song_id=:s and difficulty=:d''', {
|
||||
'u': self.user_id, 's': self.recent_score.song.song_id, 'd': self.recent_score.song.difficulty})
|
||||
y = self.c.fetchone()
|
||||
best_clear_type = y[0] if y is not None else self.recent_score.clear_type
|
||||
|
||||
r = self.recent_score.to_dict
|
||||
r["best_clear_type"] = best_clear_type
|
||||
return [r]
|
||||
|
||||
def change_character(self, character_id: int, skill_sealed: bool = False):
|
||||
# 用户角色改变,包括技能封印的改变
|
||||
self.character = UserCharacter(self.c, character_id)
|
||||
self.character.select_character_uncap_condition(self)
|
||||
self.is_skill_sealed = skill_sealed
|
||||
|
||||
self.c.execute('''update user set is_skill_sealed = :a, character_id = :b, is_char_uncapped = :c, is_char_uncapped_override = :d where user_id = :e''', {
|
||||
'a': 1 if skill_sealed else 0, 'b': self.character.character_id, 'c': self.character.is_uncapped, 'd': self.character.is_uncapped_override, 'e': self.user_id})
|
||||
'a': 1 if self.is_skill_sealed else 0, 'b': self.character.character_id, 'c': self.character.is_uncapped, 'd': self.character.is_uncapped_override, 'e': self.user_id})
|
||||
|
||||
def select_user(self):
|
||||
# 查user表所有信息
|
||||
self.c.execute(
|
||||
'''select * from user where user_id = :x''', {'x': self.user_id})
|
||||
x = self.c.fetchone()
|
||||
if not x:
|
||||
raise NoData('No user.', 108, -3)
|
||||
|
||||
self.name = x[1]
|
||||
self.join_date = int(x[3])
|
||||
self.user_code = x[4]
|
||||
self.rating_ptt = x[5]
|
||||
self.character = UserCharacter(self.c, x[6])
|
||||
self.is_skill_sealed = x[7] == 1
|
||||
self.character.is_uncapped = x[8] == 1
|
||||
self.character.is_uncapped_override = x[9] == 1
|
||||
self.is_hide_rating = x[10] == 1
|
||||
|
||||
self.recent_score.song.song_id = x[11]
|
||||
self.recent_score.song.difficulty = x[12]
|
||||
self.recent_score.set_score(
|
||||
x[13], x[14], x[15], x[16], x[17], x[18], x[19], x[20], x[21])
|
||||
self.recent_score.rating = x[22]
|
||||
|
||||
self.favorite_character = None if x[23] == - \
|
||||
1 else UserCharacter(self.c, x[23])
|
||||
self.max_stamina_notification_enabled = x[24] == 1
|
||||
self.current_map = Map(x[25])
|
||||
self.ticket = x[26]
|
||||
self.prog_boost = x[27]
|
||||
self.email = x[28]
|
||||
self.world_rank_score = x[29]
|
||||
self.ban_flag = x[30]
|
||||
|
||||
self.next_fragstam_ts = x[31]
|
||||
self.max_stamina_ts = x[32]
|
||||
self.stamina = x[33]
|
||||
|
||||
def add_friend(self, friend_id: int):
|
||||
# 加好友
|
||||
if self.user_id == friend_id:
|
||||
raise FriendError('Add yourself as a friend.', 604)
|
||||
|
||||
self.c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''',
|
||||
{'x': self.user_id, 'y': friend_id})
|
||||
if self.c.fetchone() == (0,):
|
||||
self.c.execute('''insert into friend values(:a, :b)''', {
|
||||
'a': self.user_id, 'b': friend_id})
|
||||
else:
|
||||
raise FriendError('The user has been your friend.', 602)
|
||||
|
||||
def delete_friend(self, friend_id: int):
|
||||
# 删好友
|
||||
|
||||
self.c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''',
|
||||
{'x': self.user_id, 'y': friend_id})
|
||||
if self.c.fetchone() == (1,):
|
||||
self.c.execute('''delete from friend where user_id_me = :x and user_id_other = :y''',
|
||||
{'x': self.user_id, 'y': friend_id})
|
||||
else:
|
||||
raise FriendError('No user or the user is not your friend.', 401)
|
||||
|
||||
3
latest version/core/world.py
Normal file
3
latest version/core/world.py
Normal file
@@ -0,0 +1,3 @@
|
||||
class Map:
|
||||
def __init__(self, map_id: str = None) -> None:
|
||||
self.map_id = map_id
|
||||
Binary file not shown.
@@ -4,7 +4,7 @@ import json
|
||||
|
||||
# 数据库初始化文件,删掉arcaea_database.db文件后运行即可,谨慎使用
|
||||
|
||||
ARCAEA_SERVER_VERSION = 'v2.8.5'
|
||||
ARCAEA_SERVER_VERSION = 'v2.8.6'
|
||||
|
||||
|
||||
def main(path='./'):
|
||||
@@ -387,7 +387,7 @@ def main(path='./'):
|
||||
c.execute('''insert into item values(?,"core",1,'')''', (i,))
|
||||
|
||||
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"]
|
||||
"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"]
|
||||
for i in world_songs:
|
||||
c.execute('''insert into item values(?,"world_song",1,'')''', (i,))
|
||||
|
||||
|
||||
@@ -1180,5 +1180,23 @@
|
||||
],
|
||||
"orig_price": 100,
|
||||
"price": 100
|
||||
},
|
||||
{
|
||||
"name": "mu",
|
||||
"items": [
|
||||
{
|
||||
"type": "single",
|
||||
"id": "mu",
|
||||
"is_available": true
|
||||
},
|
||||
{
|
||||
"type": "core",
|
||||
"amount": 1,
|
||||
"id": "core_generic",
|
||||
"is_available": true
|
||||
}
|
||||
],
|
||||
"orig_price": 100,
|
||||
"price": 100
|
||||
}
|
||||
]
|
||||
@@ -226,85 +226,6 @@ def user_me(user_id):
|
||||
return error_return(108)
|
||||
|
||||
|
||||
# 角色觉醒
|
||||
@app.route(add_url_prefix('/<path:path>/uncap', True), methods=['POST'])
|
||||
@server.auth.auth_required(request)
|
||||
def character_first_uncap(user_id, path):
|
||||
character_id = int(path[path.find('character')+10:])
|
||||
r = server.character.char_uncap(user_id, character_id)
|
||||
if r is not None:
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"value": r
|
||||
})
|
||||
else:
|
||||
return error_return(108)
|
||||
|
||||
|
||||
# 角色使用以太之滴
|
||||
@app.route(add_url_prefix('/<path:path>/exp', True), methods=['POST'])
|
||||
@server.auth.auth_required(request)
|
||||
def character_exp(user_id, path):
|
||||
character_id = int(path[path.find('character')+10:])
|
||||
amount = int(request.form['amount'])
|
||||
r = server.character.char_use_core(user_id, character_id, amount)
|
||||
if r is not None:
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"value": r
|
||||
})
|
||||
else:
|
||||
return error_return(108)
|
||||
|
||||
|
||||
@app.route(add_url_prefix('/friend/me/add'), methods=['POST']) # 加好友
|
||||
@server.auth.auth_required(request)
|
||||
def add_friend(user_id):
|
||||
friend_code = request.form['friend_code']
|
||||
friend_id = server.auth.code_get_id(friend_code)
|
||||
if friend_id is not None:
|
||||
r = server.setme.arc_add_friend(user_id, friend_id)
|
||||
if r is not None and r != 602 and r != 604:
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"value": {
|
||||
"user_id": user_id,
|
||||
"updatedAt": "2020-09-07T07:32:12.740Z",
|
||||
"createdAt": "2020-09-06T10:05:18.471Z",
|
||||
"friends": r
|
||||
}
|
||||
})
|
||||
else:
|
||||
if r is not None:
|
||||
return error_return(r)
|
||||
else:
|
||||
return error_return(108)
|
||||
else:
|
||||
return error_return(401)
|
||||
|
||||
|
||||
@app.route(add_url_prefix('/friend/me/delete'), methods=['POST']) # 删好友
|
||||
@server.auth.auth_required(request)
|
||||
def delete_friend(user_id):
|
||||
friend_id = int(request.form['friend_id'])
|
||||
if friend_id is not None:
|
||||
r = server.setme.arc_delete_friend(user_id, friend_id)
|
||||
if r is not None:
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"value": {
|
||||
"user_id": user_id,
|
||||
"updatedAt": "2020-09-07T07:32:12.740Z",
|
||||
"createdAt": "2020-09-06T10:05:18.471Z",
|
||||
"friends": r
|
||||
}
|
||||
})
|
||||
else:
|
||||
return error_return(108)
|
||||
else:
|
||||
return error_return(401)
|
||||
|
||||
|
||||
# 好友排名,默认最多50
|
||||
@app.route(add_url_prefix('/score/song/friend'), methods=['GET'])
|
||||
@server.auth.auth_required(request)
|
||||
@@ -701,10 +622,10 @@ def multiplayer_update(user_id):
|
||||
return error_return(error_code), 400
|
||||
|
||||
|
||||
@app.route(add_url_prefix('/user/me/request_delete'), methods=['POST']) # 删除账号
|
||||
@server.auth.auth_required(request)
|
||||
def user_delete(user_id):
|
||||
return error_return(151), 404
|
||||
# @app.route(add_url_prefix('/user/me/request_delete'), methods=['POST']) # 删除账号
|
||||
# @server.auth.auth_required(request)
|
||||
# def user_delete(user_id):
|
||||
# return error_return(151), 404
|
||||
|
||||
|
||||
# 三个设置,写在最后降低优先级
|
||||
|
||||
@@ -2,7 +2,9 @@ from flask import Blueprint
|
||||
from setting import Config
|
||||
from . import user
|
||||
from . import auth
|
||||
from . import friend
|
||||
|
||||
bp = Blueprint('server', __name__, url_prefix=Config.GAME_API_PREFIX)
|
||||
bp.register_blueprint(user.bp)
|
||||
bp.register_blueprint(auth.bp)
|
||||
bp.register_blueprint(auth.bp)
|
||||
bp.register_blueprint(friend.bp)
|
||||
|
||||
@@ -1149,4 +1149,10 @@ class Constant:
|
||||
}, {
|
||||
"unlock_key": "cyberneciacatharsis|2|0",
|
||||
"complete": 1
|
||||
}, {
|
||||
"unlock_key": "sanskia|1|0",
|
||||
"complete": 1
|
||||
}, {
|
||||
"unlock_key": "sanskia|2|0",
|
||||
"complete": 1
|
||||
}]
|
||||
|
||||
49
latest version/server/friend.py
Normal file
49
latest version/server/friend.py
Normal file
@@ -0,0 +1,49 @@
|
||||
from flask import Blueprint, request
|
||||
from core.sql import Connect
|
||||
from core.error import ArcError
|
||||
from core.user import UserOnline, code_get_id
|
||||
from .func import error_return, success_return
|
||||
from .auth import auth_required
|
||||
|
||||
bp = Blueprint('friend', __name__, url_prefix='/friend')
|
||||
|
||||
|
||||
@bp.route('/me/add', methods=['POST']) # 加好友
|
||||
@auth_required(request)
|
||||
def add_friend(user_id):
|
||||
with Connect() as c:
|
||||
try:
|
||||
friend_code = request.form['friend_code']
|
||||
friend_id = code_get_id(c, friend_code)
|
||||
user = UserOnline(c, user_id)
|
||||
user.add_friend(friend_id)
|
||||
|
||||
return success_return({
|
||||
"user_id": user.user_id,
|
||||
"updatedAt": "2020-09-07T07:32:12.740Z",
|
||||
"createdAt": "2020-09-06T10:05:18.471Z",
|
||||
"friends": user.friends
|
||||
})
|
||||
except ArcError as e:
|
||||
return error_return(e)
|
||||
return error_return()
|
||||
|
||||
|
||||
@bp.route('/me/delete', methods=['POST']) # 删好友
|
||||
@auth_required(request)
|
||||
def delete_friend(user_id):
|
||||
with Connect() as c:
|
||||
try:
|
||||
friend_id = int(request.form['friend_id'])
|
||||
user = UserOnline(c, user_id)
|
||||
user.delete_friend(friend_id)
|
||||
|
||||
return success_return({
|
||||
"user_id": user.user_id,
|
||||
"updatedAt": "2020-09-07T07:32:12.740Z",
|
||||
"createdAt": "2020-09-06T10:05:18.471Z",
|
||||
"friends": user.friends
|
||||
})
|
||||
except ArcError as e:
|
||||
return error_return(e)
|
||||
return error_return()
|
||||
@@ -3,6 +3,7 @@ from core.error import ArcError, NoAccess
|
||||
from core.sql import Connect
|
||||
from core.user import UserRegister, UserLogin, User, UserOnline
|
||||
from core.character import UserCharacter
|
||||
from core.item import ItemCore
|
||||
from .func import error_return, success_return
|
||||
from .auth import auth_required
|
||||
from setting import Config
|
||||
@@ -63,11 +64,49 @@ def toggle_uncap(user_id, character_id):
|
||||
try:
|
||||
user = User()
|
||||
user.user_id = user_id
|
||||
character = UserCharacter(c)
|
||||
character.character_id = character_id
|
||||
character = UserCharacter(c, character_id)
|
||||
character.change_uncap_override(user)
|
||||
character.select_character_info(user)
|
||||
return success_return({'user_id': user.user_id, 'character': [character.to_dict]})
|
||||
except ArcError as e:
|
||||
return error_return(e)
|
||||
return error_return()
|
||||
|
||||
|
||||
@bp.route('/me/character/<int:character_id>/uncap', methods=['POST']) # 角色觉醒
|
||||
@auth_required(request)
|
||||
def character_first_uncap(user_id, character_id):
|
||||
with Connect() as c:
|
||||
try:
|
||||
user = UserOnline(c, user_id)
|
||||
character = UserCharacter(c, character_id)
|
||||
character.select_character_info(user)
|
||||
character.character_uncap(user)
|
||||
return success_return({'user_id': user.user_id, 'character': [character.to_dict], 'cores': user.cores})
|
||||
except ArcError as e:
|
||||
return error_return(e)
|
||||
return error_return()
|
||||
|
||||
|
||||
@bp.route('/me/character/<int:character_id>/exp', methods=['POST']) # 角色使用以太之滴
|
||||
@auth_required(request)
|
||||
def character_exp(user_id, character_id):
|
||||
with Connect() as c:
|
||||
try:
|
||||
user = UserOnline(c, user_id)
|
||||
character = UserCharacter(c, character_id)
|
||||
character.select_character_info(user)
|
||||
core = ItemCore(c)
|
||||
core.amount = - int(request.form['amount'])
|
||||
core.item_id = 'core_generic'
|
||||
character.upgrade_by_core(user, core)
|
||||
return success_return({'user_id': user.user_id, 'character': [character.to_dict], 'cores': user.cores})
|
||||
except ArcError as e:
|
||||
return error_return(e)
|
||||
return error_return()
|
||||
|
||||
|
||||
@bp.route('/me/request_delete', methods=['POST']) # 删除账号
|
||||
@auth_required(request)
|
||||
def user_delete(user_id):
|
||||
return error_return(ArcError('Cannot delete the account.', 151)), 404
|
||||
|
||||
@@ -30,7 +30,7 @@ class Config():
|
||||
Allowed game versions
|
||||
If it is blank, all are allowed.
|
||||
'''
|
||||
ALLOW_APPVERSION = ['3.12.6', '3.12.6c', '3.12.8', '3.12.8c']
|
||||
ALLOW_APPVERSION = ['3.12.6', '3.12.6c', '3.12.10', '3.12.10c']
|
||||
'''
|
||||
--------------------
|
||||
'''
|
||||
|
||||
@@ -140,6 +140,9 @@ class Room:
|
||||
|
||||
def is_finish(self):
|
||||
# 是否全部进入结算
|
||||
if self.state == 8:
|
||||
return False
|
||||
|
||||
for i in self.players:
|
||||
if i.player_id != 0 and (i.finish_flag == 0 or i.online == 0):
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user