'Small' update

- Add Course Mode
- Add support for downloading additional files
- Add support for `skill_fatalis` (Hikari booms your world.)

- Delete my hair X<

> WHERE IS MY TAIRITSU ?!
> Some other things are not supported now, such as... the feature which is one line above.
This commit is contained in:
Lost-MSth
2022-07-09 01:15:03 +08:00
parent af3e91b3e8
commit 9f41ef0a70
23 changed files with 1276 additions and 214 deletions

View File

@@ -9,6 +9,7 @@ from . import purchase
from . import present
from . import others
from . import multiplayer
from . import course
bp = Blueprint('server', __name__, url_prefix=Config.GAME_API_PREFIX)
bp.register_blueprint(user.bp)
@@ -20,3 +21,4 @@ bp.register_blueprint(purchase.bp)
bp.register_blueprint(present.bp)
bp.register_blueprint(others.bp)
bp.register_blueprint(multiplayer.bp)
bp.register_blueprint(course.bp)

View File

@@ -0,0 +1,33 @@
from core.constant import Constant
from core.course import UserCourseList
from core.error import ArcError
from core.item import ItemCore
from core.sql import Connect
from core.user import UserOnline
from flask import Blueprint, request
from .auth import auth_required
from .func import error_return, success_return
bp = Blueprint('course', __name__, url_prefix='/course')
@bp.route('/me', methods=['GET'])
@auth_required(request)
def course_me(user_id):
with Connect() as c:
try:
user = UserOnline(c, user_id)
core = ItemCore(c)
core.item_id = 'core_course_skip_purchase'
core.select(user)
x = UserCourseList(c, user)
x.select_all()
return success_return({
'courses': x.to_dict_list(),
"stamina_cost": Constant.COURSE_STAMINA_COST,
"course_skip_purchase_ticket": core.amount
})
except ArcError as e:
return error_return(e)
return error_return()

View File

@@ -12,7 +12,7 @@ from werkzeug.datastructures import ImmutableMultiDict
from .auth import auth_required
from .func import error_return, success_return
from .present import present_info
from .purchase import bundle_pack
from .purchase import bundle_pack, bundle_bundle
from .score import song_score_friend
from .user import user_me
from .world import world_all
@@ -44,13 +44,20 @@ def download_song(user_id):
return error_return()
@bp.route('/finale/progress', methods=['GET'])
def finale_progress():
return success_return({'percentage': 100000})
map_dict = {'/user/me': user_me,
'/purchase/bundle/pack': bundle_pack,
'/serve/download/me/song': download_song,
'/game/info': game_info,
'/present/me': present_info,
'/world/map/me': world_all,
'/score/song/friend': song_score_friend}
'/score/song/friend': song_score_friend,
'/purchase/bundle/bundle': bundle_bundle,
'/finale/progress': finale_progress}
@bp.route('/compose/aggregate', methods=['GET']) # 集成式请求

View File

@@ -1,7 +1,7 @@
from time import time
from core.error import ArcError, ItemUnavailable
from core.item import ItemFactory
from core.item import ItemFactory, Stamina6
from core.purchase import Purchase, PurchaseList
from core.redeem import UserRedeem
from core.sql import Connect
@@ -40,6 +40,35 @@ def get_single(user_id):
return error_return()
@bp.route('/bundle/bundle', methods=['GET']) # 捆绑包
def bundle_bundle():
return success_return([])
# return success_return([{
# "name": "chronicles",
# "items": [{
# "type": "bundle",
# "id": "core"
# }, {
# "type": "bundle",
# "id": "prelude"
# }, {
# "type": "bundle",
# "id": "rei"
# }, {
# "type": "bundle",
# "id": "yugamu"
# }, {
# "type": "bundle",
# "id": "vs"
# }],
# "orig_price": 2000,
# "price": 2000,
# "discount_from": 1657152000000,
# "discount_to": 1758447999000,
# "discount_reason": "chronicle"
# }])
@bp.route('/me/pack', methods=['POST']) # 曲包和单曲购买
@auth_required(request)
def buy_pack_or_single(user_id):
@@ -89,7 +118,7 @@ def buy_special(user_id):
if item_id == 'stamina6':
r['stamina'] = x.user.stamina.stamina
r['max_stamina_ts'] = x.user.stamina.max_stamina_ts
r['world_mode_locked_end_ts'] = -1
return success_return(r)
except ArcError as e:
return error_return(e)
@@ -105,21 +134,21 @@ def purchase_stamina(user_id, buy_stamina_type):
return error_return()
user = UserOnline(c, user_id)
user.select_user_about_fragstam()
user.select_user_one_column('next_fragstam_ts', -1)
now = int(time()*1000)
if user.next_fragstam_ts > now:
return ItemUnavailable('Buying stamina by fragment is not available yet.', 905)
user.update_user_about_fragstam(now + 24 * 3600 * 1000)
user.select_user_about_stamina()
user.stamina.stamina += 6
user.stamina.update()
user.update_user_one_column(
'next_fragstam_ts', now + 24 * 3600 * 1000)
s = Stamina6(c)
s.user_claim_item(user)
return success_return({
"user_id": user.user_id,
"stamina": user.stamina.stamina,
"max_stamina_ts": user.stamina.max_stamina_ts,
"next_fragstam_ts": user.next_fragstam_ts
"next_fragstam_ts": user.next_fragstam_ts,
'world_mode_locked_end_ts': -1
})
except ArcError as e:
return error_return(e)

View File

@@ -1,4 +1,5 @@
from time import time
from core.course import CoursePlay
from core.error import ArcError, InputError
from core.rank import RankList
@@ -18,7 +19,7 @@ def score_token():
return success_return({'token': '1145141919810'})
@bp.route('/token/world', methods=['GET']) # 世界模式成绩上传所需的token,无验证
@bp.route('/token/world', methods=['GET']) # 世界模式成绩上传所需的token
@auth_required(request)
def score_token_world(user_id):
@@ -33,12 +34,12 @@ def score_token_world(user_id):
x = UserPlay(c, UserOnline(c, user_id))
x.song.set_chart(request.args['song_id'], int(
request.args['difficulty']))
x.set_play_state(stamina_multiply,
fragment_multiply, prog_boost_multiply)
x.set_play_state_for_world(stamina_multiply,
fragment_multiply, prog_boost_multiply)
return success_return({
"stamina": x.user.stamina.stamina,
"max_stamina_ts": x.user.stamina.max_stamina_ts,
"token": "13145201919810"
"token": x.song_token
}
)
except ArcError as e:
@@ -46,6 +47,47 @@ def score_token_world(user_id):
return error_return()
@bp.route('/token/course', methods=['GET']) # 课题模式成绩上传所需的token
@auth_required(request)
def score_token_course(user_id):
with Connect() as c:
try:
use_course_skip_purchase = request.args.get(
'use_course_skip_purchase', 'false') == 'true'
user = UserOnline(c, user_id)
user_play = UserPlay(c, user)
user_play.song_token = request.args.get('previous_token', None)
user_play.get_play_state()
status = 'created'
if user_play.course_play_state == -1:
# 没有token课题模式刚开始
course_play = CoursePlay(c, user, user_play)
course_play.course_id = request.args['course_id']
user_play.course_play = course_play
user_play.set_play_state_for_course(
use_course_skip_purchase)
elif 0 <= user_play.course_play_state <= 3:
# 验证token
user_play.update_token_for_course()
else:
# 课题模式已经结束
user_play.clear_play_state()
user.select_user_about_stamina()
status = 'cleared' if user_play.course_play_state == 4 else 'failed'
return success_return({
"stamina": user.stamina.stamina,
"max_stamina_ts": user.stamina.max_stamina_ts,
"token": user_play.song_token,
'status': status
})
except ArcError as e:
return error_return(e)
return error_return()
@bp.route('/song', methods=['POST']) # 成绩上传
@auth_required(request)
def song_score_post(user_id):

View File

@@ -177,10 +177,8 @@ def sys_set(user_id, set_arg):
user.change_favorite_character(int(value))
else:
value = 'true' == value
if 'is_hide_rating' == set_arg:
user.change_is_hide_rating(value)
elif 'max_stamina_notification_enabled' == set_arg:
user.change_max_stamina_notification_enabled(value)
if 'is_hide_rating' == set_arg or 'max_stamina_notification_enabled' == set_arg:
user.update_user_one_column(set_arg, value)
return success_return(user.to_dict())
except ArcError as e:
return error_return(e)