mirror of
https://github.com/qwerfd2/Groove_Coaster_2_Server.git
synced 2025-12-22 03:30:18 +00:00
Bug fixing and ready for Extra Challenge
This commit is contained in:
@@ -48,9 +48,9 @@ If you'd like to upload it somewhere else and contribute the link, please contac
|
||||
|
||||
Download `common.zip` and a platform of your choosing. Unzip the folders within to the private server root directory. If in doubt, check the `File Structure` section at the end.
|
||||
|
||||
### GC4MAX Expansion
|
||||
### GC4MAX Expansion and Extra Challenge Expansion
|
||||
|
||||
To install the `GC4MAX` expansion, which ports arcade exclusive tracks, avatars, and skins to 2OS, download the `4max expansion` folder's `common.zip` and a platform of your choosing. Unzip the folders within to the privates server root directory. Overwrite existing files. Note that the included installation `apk` or `ipa` must be used for correct avatar rendering.
|
||||
To install the `GC4MAX Expansion` (which includes the `Extra Challenge Expansion`), which ports arcade exclusive tracks, avatars, and skins to 2OS, download the `4max expansion` folder's `common.zip` and a platform of your choosing. Unzip the folders within to the privates server root directory. Overwrite existing files. Note that the included installation `apk` or `ipa` must be used for correct avatar rendering.
|
||||
|
||||
Edit `config.py`'s `MODEL`, `TUNEFILE`, and `SKIN` value to match the `pak`'s timestamp. `paks` can be found at `/files/gc2/`.
|
||||
|
||||
@@ -313,9 +313,9 @@ Note that this data is for analytics only, and the functionality to embed this d
|
||||
|
||||
下载 `common.zip` 和您设备的平台。将里面的所有文件夹解压到服务器根目录。如有疑惑,请参照文末`文件结构`章节。
|
||||
|
||||
## GC4MAX扩展包
|
||||
## GC4MAX扩展包和Extra Challenge扩展包
|
||||
|
||||
如想下载`GC4MAX`扩展包(包含了街机独占曲目,皮肤,和角色),下载`4max expansion`里的`common.zip`和和您设备的平台。将里面的所有文件夹解压到服务器根目录。如有重复,覆盖所有文件。请注意,必须使用包含的`apk`或`ipa`安装包来正确渲染角色。
|
||||
如想下载`GC4MAX扩展包`(内含`Extra Challenge扩展包`)(包含了街机独占曲目,皮肤,和角色),下载`4max expansion`里的`common.zip`和和您设备的平台。将里面的所有文件夹解压到服务器根目录。如有重复,覆盖所有文件。请注意,必须使用包含的`apk`或`ipa`安装包来正确渲染角色。
|
||||
|
||||
修改`config.py`的`MODEL`, `TUNEFILE`, and `SKIN` 值至现有`pak`文件的时间戳. `paks`文件的位置在`/files/gc2/`.
|
||||
|
||||
|
||||
@@ -36,12 +36,12 @@ def get_4max_version_string():
|
||||
|
||||
def parse_res(res):
|
||||
parsed_data = []
|
||||
if isinstance(res, int):
|
||||
if isinstance(res, int) or res == None:
|
||||
return "Failed to fetch version info: Error " + str(res)
|
||||
|
||||
for item in res:
|
||||
if item.get("isOpen"):
|
||||
version = item.get("version", "Unknown Version")
|
||||
version = item.get("version", 0)
|
||||
changelog = "<br>".join(item.get("changeLog", {}).get("en", []))
|
||||
parsed_data.append(f"<strong>Version: {version}</strong><p><strong>Changelog:</strong><br>{changelog}</p>")
|
||||
return "".join(parsed_data)
|
||||
|
||||
@@ -8,7 +8,7 @@ import xml.etree.ElementTree as ET
|
||||
|
||||
from config import ROOT_FOLDER, START_COIN, COIN_REWARD, AUTHORIZATION_NEEDED
|
||||
|
||||
from api.database import database, user, daily_reward, result, result, check_blacklist, check_whitelist
|
||||
from api.database import database, user, daily_reward, result, check_blacklist, check_whitelist
|
||||
from api.crypt import decrypt_fields
|
||||
from api.templates import START_STAGES, EXP_UNLOCKED_SONGS
|
||||
|
||||
|
||||
@@ -248,7 +248,10 @@ async def ranking_detail(request: Request):
|
||||
play_record = None
|
||||
|
||||
if user_id:
|
||||
play_record = next((record for record in play_results if int(record[3]) == user_id), None)
|
||||
play_record = play_record = next(
|
||||
(record for record in play_results if record[3] not in (None, '') and int(record[3]) == user_id),
|
||||
None
|
||||
)
|
||||
|
||||
if not play_record:
|
||||
play_record = next((record for record in play_results if record[1] == device_id and record[3] is None), None)
|
||||
@@ -257,10 +260,10 @@ async def ranking_detail(request: Request):
|
||||
avatar_index = str(play_record[7]) if play_record else "1"
|
||||
user_score = play_record[8] if play_record else 0
|
||||
for rank, result_obj in enumerate(play_results, start=1):
|
||||
if user_result and int(result_obj[3]) == user_id:
|
||||
if user_result and result_obj[3] not in (None, '') and int(result_obj[3]) == user_id:
|
||||
player_rank = rank
|
||||
break
|
||||
elif result_obj[1] == device_id and result_obj[3] is None:
|
||||
elif result_obj[1] == device_id and result_obj[3] in (None, ''):
|
||||
player_rank = rank
|
||||
break
|
||||
|
||||
|
||||
76
api/shop.py
76
api/shop.py
@@ -7,7 +7,7 @@ import math
|
||||
from sqlalchemy import select, update
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from config import START_COIN, AUTHORIZATION_NEEDED, STAGE_PRICE, START_COIN, AVATAR_PRICE, ITEM_PRICE
|
||||
from config import START_COIN, AUTHORIZATION_NEEDED, STAGE_PRICE, START_COIN, AVATAR_PRICE, ITEM_PRICE, FMAX_PRICE, EX_PRICE
|
||||
|
||||
from api.crypt import decrypt_fields
|
||||
from api.misc import inform_page, parse_res, FMAX_VER, FMAX_RES
|
||||
@@ -46,7 +46,7 @@ async def web_shop(request: Request):
|
||||
|
||||
if cnt_type == "1":
|
||||
low_range = 100
|
||||
up_range = 616
|
||||
up_range = 615
|
||||
|
||||
if page < 0 or page > math.ceil(up_range - low_range) / 80:
|
||||
return HTMLResponse("""<html><body><h1>Invalid page number</h1></body></html>""", status_code=400)
|
||||
@@ -59,17 +59,31 @@ async def web_shop(request: Request):
|
||||
low_range = low_range + page * 80
|
||||
up_range = min(up_range, low_range + 80)
|
||||
|
||||
if 700 not in my_stage and os.path.isfile('./files/dlc_4max.html'):
|
||||
if 700 not in my_stage and os.path.isfile('./files/dlc_4max.html') and not spawn_prev_page:
|
||||
buttons_html += """
|
||||
<a href="wwic://web_shop_detail?&cnt_type=1&cnt_id=-1">
|
||||
<img src="/files/web/dlc_4max.jpg" style="width: 84%; margin-bottom: 20px; margin-top: -100px;" />
|
||||
<img src="/files/web/dlc_4max.jpg" style="width: 84%; margin-bottom: 110px; margin-top: -100px;" />
|
||||
</a><br>
|
||||
"""
|
||||
fmax_inc = 1
|
||||
elif 700 in my_stage and os.path.isfile('./files/dlc_4max.html'):
|
||||
elif 700 in my_stage and os.path.isfile('./files/dlc_4max.html') and not spawn_prev_page:
|
||||
buttons_html += """
|
||||
<a href="wwic://web_shop_detail?&cnt_type=1&cnt_id=-3">
|
||||
<img src="/files/web/dlc_4max.jpg" style="width: 84%; margin-bottom: 110px; margin-top: -100px;" />
|
||||
</a><br>
|
||||
"""
|
||||
|
||||
if 980 not in my_stage and os.path.isfile('./files/dlc_extra.html') and not spawn_prev_page:
|
||||
buttons_html += """
|
||||
<a href="wwic://web_shop_detail?&cnt_type=1&cnt_id=-2">
|
||||
<img src="/files/web/dlc_4max.jpg" style="width: 84%; margin-bottom: 20px; margin-top: -100px;" />
|
||||
<img src="/files/web/dlc_extra.jpg" style="width: 84%; margin-bottom: 20px; margin-top: -100px;" />
|
||||
</a><br>
|
||||
"""
|
||||
fmax_inc = 1
|
||||
elif 980 in my_stage and os.path.isfile('./files/dlc_4max.html') and not spawn_prev_page:
|
||||
buttons_html += """
|
||||
<a href="wwic://web_shop_detail?&cnt_type=1&cnt_id=-4">
|
||||
<img src="/files/web/dlc_extra.jpg" style="width: 84%; margin-bottom: 20px; margin-top: -100px;" />
|
||||
</a><br>
|
||||
"""
|
||||
|
||||
@@ -204,7 +218,7 @@ async def web_shop_detail(request: Request):
|
||||
<span style="color: #FFFFFF; font-size: 44px; font-family: Hiragino Kaku Gothic ProN, sans-serif;">{song_stage_price}</span>
|
||||
</div>
|
||||
"""
|
||||
elif cnt_id == -2:
|
||||
elif cnt_id == -3:
|
||||
log = parse_res(FMAX_RES)
|
||||
html = f"""
|
||||
<div class="text-content">
|
||||
@@ -218,6 +232,36 @@ async def web_shop_detail(request: Request):
|
||||
<p>{log}<p><br>
|
||||
</div>
|
||||
"""
|
||||
elif cnt_id == -4:
|
||||
html = f"""
|
||||
<div class="text-content">
|
||||
<p>You have unlocked the EXTRA Challenge!</p>
|
||||
<p>Please report bugs/missing tracks to Discord: #AnTcfgss, or QQ 3421587952.</p>
|
||||
<button class="quit-button-extra" onclick="window.location.href='wwic://web_shop?&cnt_type=1'">
|
||||
Go Back
|
||||
</button>
|
||||
</div>
|
||||
"""
|
||||
elif cnt_id == -2:
|
||||
html = f"""
|
||||
<div class="text-content">
|
||||
<p>Brace the Ultimate - Extra - Challenge.</p>
|
||||
<p>170+ Arcade Extra difficulty charts await you.</p>
|
||||
<p>You have been warned.</p>
|
||||
</div>
|
||||
|
||||
<button class="buy-button-extra" onclick="window.location.href='wwic://web_purchase_coin?&cnt_type=1&cnt_id=-2&num=1'">
|
||||
Buy
|
||||
<div class="coin-container">
|
||||
<img src="/files/web/coin_icon.png" alt="Coin Icon" class="coin-icon">
|
||||
<span style="font-size: 22px; font-weight: bold;"> {EX_PRICE}</span>
|
||||
</div>
|
||||
</button>
|
||||
<br><br>
|
||||
<button class="quit-button-extra" onclick="window.location.href='wwic://web_shop?&cnt_type=1'">
|
||||
Go Back
|
||||
</button>
|
||||
"""
|
||||
elif cnt_id == -1:
|
||||
html = f"""
|
||||
<div class="text-content">
|
||||
@@ -230,7 +274,7 @@ async def web_shop_detail(request: Request):
|
||||
Buy
|
||||
<div class="coin-container">
|
||||
<img src="/files/web/coin_icon.png" alt="Coin Icon" class="coin-icon">
|
||||
<span style="font-size: 22px; font-weight: bold;"> 300</span>
|
||||
<span style="font-size: 22px; font-weight: bold;"> {FMAX_PRICE}</span>
|
||||
</div>
|
||||
</button>
|
||||
<br><br>
|
||||
@@ -279,8 +323,10 @@ async def web_shop_detail(request: Request):
|
||||
else:
|
||||
html = "<p>Item not found.</p>"
|
||||
|
||||
if cnt_type == "1" and cnt_id < 0:
|
||||
if cnt_type == "1" and (cnt_id == -1 or cnt_id == -3):
|
||||
source_html = f"files/dlc_4max.html"
|
||||
elif cnt_type == "1" and (cnt_id == -2 or cnt_id == -4):
|
||||
source_html = f"files/dlc_extra.html"
|
||||
else:
|
||||
source_html = f"files/web_shop_detail.html"
|
||||
html += f"""
|
||||
@@ -331,11 +377,19 @@ async def buy_by_coin(request: Request):
|
||||
|
||||
if cnt_type == "1":
|
||||
if cnt_id == -1:
|
||||
song_stage_price = 300
|
||||
song_stage_price = FMAX_PRICE
|
||||
if coin < song_stage_price:
|
||||
return Response(fail_url, media_type="application/xml")
|
||||
|
||||
for i in range(616, 950):
|
||||
for i in range(615, 926):
|
||||
my_stage.add(i)
|
||||
coin -= song_stage_price
|
||||
elif cnt_id == -2:
|
||||
song_stage_price = EX_PRICE
|
||||
if coin < song_stage_price:
|
||||
return Response(fail_url, media_type="application/xml")
|
||||
|
||||
for i in range(926, 985):
|
||||
my_stage.add(i)
|
||||
coin -= song_stage_price
|
||||
else:
|
||||
|
||||
@@ -11,7 +11,7 @@ START_STAGES = [7,23,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,55,56,57
|
||||
|
||||
START_AVATARS = []
|
||||
|
||||
EXCLUDE_STAGE_EXP = [121,134,166,167,168,169,170,213,214,215,225,277,397] # 134 and 170 unoccupied dummy tracks (filled with Departure -Remix-),
|
||||
EXCLUDE_STAGE_EXP = [121,134,166,167,168,169,170,213,214,215,225,277,396] # 134 and 170 unoccupied dummy tracks (filled with Departure -Remix-),
|
||||
#121 (and 93-96 lady gaga songs) removed (can be enabled by patching stageParam:isAvailable, or change the last byte before next song's name - 1 from 01 to 03 in stage_param.dat.
|
||||
# Rest are exp unlocked songs.
|
||||
EXCLUDE_AVATAR_EXP = [28,29]
|
||||
|
||||
@@ -606,7 +606,7 @@ async def bonus(request: Request):
|
||||
await database.execute(update_query)
|
||||
|
||||
elif cnt_type == 2:
|
||||
avatars = set(json.loads(my_avatar)) if my_avatar else set()
|
||||
avatars = set(my_avatar) if my_avatar else set()
|
||||
if cnt_id not in avatars:
|
||||
avatars.add(cnt_id)
|
||||
my_avatar = json.dumps(list(avatars))
|
||||
|
||||
@@ -13,11 +13,26 @@
|
||||
margin: 0px auto;
|
||||
padding: 20px;
|
||||
}
|
||||
.dlc_container_extra {
|
||||
max-width: 800px;
|
||||
height: 70vh;
|
||||
margin: 0px auto;
|
||||
padding: 20px;
|
||||
}
|
||||
.dlc_logo {
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.dlc_extra_body {
|
||||
background: url('/files/web/extra_bg.jpg') no-repeat center center fixed;
|
||||
background-size: cover;
|
||||
color: red;
|
||||
font-family: Arial, sans-serif;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.text-content {
|
||||
font-size: 18px;
|
||||
line-height: 1.6;
|
||||
@@ -50,6 +65,33 @@
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
.buy-button-extra {
|
||||
display: inline-block;
|
||||
width: 160px;
|
||||
height: 110px;
|
||||
background: url('/files/web/frame_buy_extra.png') no-repeat center center;
|
||||
background-size: contain;
|
||||
border: none;
|
||||
color: white;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
padding: 15px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
.quit-button-extra {
|
||||
display: inline-block;
|
||||
width: 150px;
|
||||
height: 30px;
|
||||
background: url('/files/web/quit_button_extra.png') no-repeat center center;
|
||||
background-size: contain;
|
||||
border: none;
|
||||
color: white;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
.coin-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
Reference in New Issue
Block a user