mirror of https://github.com/hykilpikonna/AquaDX
Merge branch 'v1-dev' into broker
commit
8efb3d7554
|
@ -6,6 +6,8 @@ on:
|
|||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 0 * * 0' # Runs at midnight UTC every Sunday
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
|
|
|
@ -9,19 +9,17 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
java-version: '21'
|
||||
distribution: 'temurin'
|
||||
server-id: github
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/gradle-build-action@v2
|
||||
|
||||
- name: Build with Gradle
|
||||
run: |
|
||||
mkdir data
|
||||
bash ./src/main/resources/meta/update.sh
|
||||
chmod +x gradlew
|
||||
./gradlew build
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
VITE_AQUA_HOST=https://aquadx.net/aqua
|
||||
VITE_DATA_HOST=https://aquadx.net
|
||||
|
||||
VITE_AQUA_CONNECTION=aquadx.hydev.org
|
||||
|
||||
VITE_TURNSTILE_SITE_KEY=0x4AAAAAAASGA2KQEIelo9P9
|
||||
VITE_DISCORD_INVITE=https://discord.gg/FNgveqFF7s
|
||||
VITE_TELEGRAM_INVITE=https://t.me/+zBL4RZdyfvUzZGU1
|
||||
VITE_QQ_INVITE=https://qm.qq.com/q/wvNXbXbHbO
|
|
@ -32,4 +32,7 @@ dist-ssr
|
|||
!.yarn/sdks
|
||||
!.yarn/versions
|
||||
|
||||
public/chu3
|
||||
public/chu3
|
||||
|
||||
# local env file
|
||||
*.local
|
|
@ -34,7 +34,7 @@
|
|||
// Available (unlocked) options for each kind of item
|
||||
// In allItems: 'namePlate', 'frame', 'trophy', 'mapIcon', 'systemVoice', 'avatarAccessory'
|
||||
let allItems: Record<string, Record<string, { name: string }>> = {}
|
||||
let iKinds = { namePlate: 1, frame: 2, trophy: 3, mapIcon: 8, systemVoice: 9, avatarAccessory: 11 }
|
||||
let iKinds = { namePlate: 1, frame: 2, trophy: 3, trophySub1: 4, trophySub2: 5, mapIcon: 8, systemVoice: 9, avatarAccessory: 11 }
|
||||
// In userbox: 'nameplateId', 'frameId', 'trophyId', 'mapIconId', 'voiceId', 'avatar{Wear/Head/Face/Skin/Item/Front/Back}'
|
||||
let userbox: UserBox
|
||||
let avatarKinds = ['Wear', 'Head', 'Face', 'Skin', 'Item', 'Front', 'Back'] as const
|
||||
|
@ -66,6 +66,10 @@
|
|||
userItems = Object.entries(iKinds).flatMap(([iKey, iKind]) => {
|
||||
if (iKey != 'avatarAccessory') {
|
||||
let ubKey = `${iKey}Id`
|
||||
if (iKey.slice('trophy'.length, 'trophy'.length + 3) == "Sub") {
|
||||
ubKey = `trophyIdSub${iKey.slice('trophySub'.length, 'trophySub'.length + 1)}`;
|
||||
iKey = `trophy`;
|
||||
}
|
||||
if (ubKey == 'namePlateId') ubKey = 'nameplateId'
|
||||
if (ubKey == 'systemVoiceId') ubKey = 'voiceId'
|
||||
return [{ iKey, ubKey: ubKey as keyof UserBox,
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import type { ChusanMatchingOption } from "./generalTypes"
|
||||
|
||||
export const AQUA_HOST = 'https://aquadx.net/aqua'
|
||||
export const DATA_HOST = 'https://aquadx.net'
|
||||
export const AQUA_HOST = import.meta.env.VITE_AQUA_HOST
|
||||
export const DATA_HOST = import.meta.env.VITE_DATA_HOST
|
||||
|
||||
// This will be displayed for users to connect from the client
|
||||
export const AQUA_CONNECTION = 'aquadx.hydev.org'
|
||||
export const AQUA_CONNECTION = import.meta.env.VITE_AQUA_CONNECTION
|
||||
|
||||
export const TURNSTILE_SITE_KEY = '0x4AAAAAAASGA2KQEIelo9P9'
|
||||
export const DISCORD_INVITE = 'https://discord.gg/FNgveqFF7s'
|
||||
export const TELEGRAM_INVITE = 'https://t.me/+zBL4RZdyfvUzZGU1'
|
||||
export const QQ_INVITE = 'https://qm.qq.com/q/wvNXbXbHbO'
|
||||
export const TURNSTILE_SITE_KEY = import.meta.env.VITE_TURNSTILE_SITE_KEY
|
||||
export const DISCORD_INVITE = import.meta.env.VITE_DISCORD_INVITE
|
||||
export const TELEGRAM_INVITE = import.meta.env.VITE_TELEGRAM_INVITE
|
||||
export const QQ_INVITE = import.meta.env.VITE_QQ_INVITE
|
||||
|
||||
// UI
|
||||
export const FADE_OUT = { duration: 200 }
|
||||
|
|
|
@ -142,6 +142,8 @@ export interface UserBox {
|
|||
frameId: number,
|
||||
characterId: number,
|
||||
trophyId: number,
|
||||
trophyIdSub1: number,
|
||||
trophyIdSub2: number,
|
||||
mapIconId: number,
|
||||
voiceId: number,
|
||||
avatarWear: number,
|
||||
|
|
|
@ -191,6 +191,8 @@ export const EN_REF_USERBOX = {
|
|||
'userbox.nameplateId': 'Nameplate',
|
||||
'userbox.frameId': 'Frame',
|
||||
'userbox.trophyId': 'Trophy (Title)',
|
||||
'userbox.trophyIdSub1': 'Trophy Sub #1 (Title)',
|
||||
'userbox.trophyIdSub2': 'Trophy Sub #2 (Title)',
|
||||
'userbox.mapIconId': 'Map Icon',
|
||||
'userbox.voiceId': 'System Voice',
|
||||
'userbox.avatarWear': 'Avatar Wear',
|
||||
|
|
|
@ -318,7 +318,13 @@
|
|||
<RatingComposition title="B15" comp={d.user.ratingComposition.best15} {allMusics} game={game != "auto" ? game : "mai2"}/>
|
||||
<!-- <RatingComposition title="Hot 10" comp={d.user.ratingComposition.hot10} {allMusics} {game}/> -->
|
||||
<!-- <RatingComposition title="N10" comp={d.user.ratingComposition.next10} {allMusics} {game}/> -->
|
||||
<RatingComposition title="Recent 10" comp={d.user.ratingComposition.recent10} {allMusics} game={game != "auto" ? game : "mai2"} top={10}/>
|
||||
<!-- Chuni -->
|
||||
{#if d.user.ratingComposition.new}
|
||||
<RatingComposition title="New 20" comp={d.user.ratingComposition.new} {allMusics} game="chu3"/>
|
||||
{:else}
|
||||
<RatingComposition title="Recent 10" comp={d.user.ratingComposition.recent10} {allMusics} game={game != "auto" ? game : "mai2"} top={10}/>
|
||||
{/if}
|
||||
|
||||
|
||||
<div class="recent">
|
||||
<h2>{t('UserHome.RecentScores')}</h2>
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
return submitting = false
|
||||
}
|
||||
|
||||
if (turnstile === "") {
|
||||
if (TURNSTILE_SITE_KEY && turnstile === "") {
|
||||
// Sleep for 100ms to allow Turnstile to finish
|
||||
error = t("welcome.waiting-turnstile")
|
||||
return setTimeout(submit, 100)
|
||||
|
@ -137,11 +137,13 @@
|
|||
{isSignup ? t('welcome.btn-signup') : t('welcome.btn-login')}
|
||||
{/if}
|
||||
</button>
|
||||
{#if TURNSTILE_SITE_KEY}
|
||||
<Turnstile siteKey={TURNSTILE_SITE_KEY} bind:reset={turnstileReset}
|
||||
on:turnstile-callback={e => console.log(turnstile = e.detail.token)}
|
||||
on:turnstile-error={_ => console.log(error = t("welcome.turnstile-error"))}
|
||||
on:turnstile-expired={_ => window.location.reload()}
|
||||
on:turnstile-timeout={_ => console.log(error = t('welcome.turnstile-timeout'))} />
|
||||
{/if}
|
||||
</div>
|
||||
{:else if state === "verify"}
|
||||
<div class="login-form" transition:slide>
|
||||
|
|
|
@ -33,7 +33,7 @@ Below is a list of games supported by this server.
|
|||
|
||||
| Game | Ver | Codename | Thanks to |
|
||||
|------------------------|------|---------------------|--------------------------------------------|
|
||||
| SDHD: CHUNITHM | 2.30 | VERSE¹ | [@rinsama](https://github.com/mxihan) |
|
||||
| SDHD: CHUNITHM | 2.30 | VERSE | [@rinsama](https://github.com/mxihan) |
|
||||
| SDEZ: MaiMai DX | 1.50 | PRiSM | [@肥宅虾哥](https://github.com/FeiZhaixiage) |
|
||||
| SDGA: MaiMai DX (Intl) | 1.50 | PRiSM | [@Clansty](https://github.com/clansty) |
|
||||
| SDED: Card Maker | 1.39 | | [@Becods](https://github.com/Becods) |
|
||||
|
@ -41,8 +41,6 @@ Below is a list of games supported by this server.
|
|||
| SBZV: Project DIVA | 7.10 | Future Tone | |
|
||||
| SDFE: Wacca (*ALPHA) | 3.07 | Reverse | |
|
||||
|
||||
* ¹: For VERSE, normal gameplay works, but events and new features might be missing. Luminous+ and older are fully supported.
|
||||
|
||||
Check out these docs for more information.
|
||||
* [Game specific notes](docs/game_specific_notes.md)
|
||||
* [Frequently asked questions](docs/frequently_asked_questions.md)
|
||||
|
|
|
@ -30,7 +30,7 @@ allnet.server.redirect=https://aquadx.net
|
|||
## Http Server Port
|
||||
## Only change this if you have a reverse proxy running.
|
||||
## The game rely on 80 port for boot up command
|
||||
server.port=8080
|
||||
server.port=80
|
||||
|
||||
## Static file server
|
||||
## This is used to server static files in /web/ directory, which is Aquaviewer
|
||||
|
|
|
@ -45,6 +45,13 @@ netsh advfirewall firewall add rule name="Chunithm National Matching Outbound" d
|
|||
|
||||
## Troubleshooting
|
||||
|
||||
**Q: Me and my friend are queuing but we can't join the same room**
|
||||
|
||||
Make sure you both have the same ROM and options (e.g. it would not work if you have luminuous and they have verse, or if you have A121 while they don't).
|
||||
|
||||
> [!NOTE]
|
||||
> If you just updated your options, your matching will be disabled because of data version mismatch. You need to play for a session, save, and then restart your game for the server-side data version to update.
|
||||
|
||||
**Q: Matching server BAD on network check**
|
||||
|
||||
Make sure you have selected "Yukiotoko" as your matching server.
|
||||
|
|
|
@ -29,6 +29,8 @@ class Chusan(
|
|||
"nameplateId" to { u, v -> u.nameplateId = v.int },
|
||||
"frameId" to { u, v -> u.frameId = v.int },
|
||||
"trophyId" to { u, v -> u.trophyId = v.int },
|
||||
"trophyIdSub1" to { u, v -> u.trophyIdSub1 = v.int },
|
||||
"trophyIdSub2" to { u, v -> u.trophyIdSub2 = v.int },
|
||||
"mapIconId" to { u, v -> u.mapIconId = v.int },
|
||||
"voiceId" to { u, v -> u.voiceId = v.int },
|
||||
"avatarWear" to { u, v -> u.avatarWear = v.int },
|
||||
|
@ -52,6 +54,7 @@ class Chusan(
|
|||
"best30" to (extra["rating_base_list"] ?: ""),
|
||||
"hot10" to (extra["rating_hot_list"] ?: ""),
|
||||
"next10" to (extra["rating_next_list"] ?: ""),
|
||||
"new" to (extra["rating_new_list"] ?: ""),
|
||||
)
|
||||
|
||||
genericUserSummary(card, ratingComposition)
|
||||
|
|
|
@ -96,7 +96,7 @@ class AllNet(
|
|||
|
||||
@PostMapping("/sys/servlet/PowerOn", produces = ["text/plain"])
|
||||
fun powerOn(dataStream: InputStream, req: HttpServletRequest): String {
|
||||
val localAddr = req.localAddr
|
||||
val here = req.getHeader("AllNet-Forwarded-From") ?: props.host.ifBlank { req.localAddr }
|
||||
val localPort = req.localPort.toString()
|
||||
|
||||
// game_id SDEZ, ver 1.35, serial A0000001234, ip, firm_ver 50000, boot_ver 0000,
|
||||
|
@ -138,8 +138,8 @@ class AllNet(
|
|||
|
||||
val formatVer = reqMap["format_ver"] ?: ""
|
||||
val resp = props.map.mut + mapOf(
|
||||
"uri" to switchUri(localAddr, localPort, gameId, ver, session),
|
||||
"host" to props.host.ifBlank { localAddr },
|
||||
"uri" to switchUri(here, localPort, gameId, ver, session),
|
||||
"host" to props.host.ifBlank { here },
|
||||
)
|
||||
|
||||
// Different responses for different versions
|
||||
|
@ -171,9 +171,8 @@ class AllNet(
|
|||
return resp.toUrl() + "\n"
|
||||
}
|
||||
|
||||
private fun switchUri(localAddr: Str, localPort: Str, gameId: Str, ver: Str, session: Str?): Str {
|
||||
val addr = props.host.ifBlank { localAddr } +
|
||||
if (props.hidePort) "" else ":${props.port ?: localPort}"
|
||||
private fun switchUri(hereAddr: Str, localPort: Str, gameId: Str, ver: Str, session: Str?): Str {
|
||||
val addr = hereAddr + (if (props.hidePort) "" else ":${props.port ?: localPort}")
|
||||
|
||||
// If keychip authentication is enabled, the game URLs will be set to /gs/{token}/{game}/...
|
||||
val base = if (session != null) "gs/$session" else "g"
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package icu.samnyan.aqua.sega.cardmaker.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.allnet.KeychipSession;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.cardmaker.model.response.data.GameConnect;
|
||||
import icu.samnyan.aqua.sega.util.jackson.BasicMapper;
|
||||
import icu.samnyan.aqua.sega.allnet.TokenChecker;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -32,7 +34,7 @@ public class GetGameConnectHandler implements BaseHandler {
|
|||
|
||||
@Autowired
|
||||
public GetGameConnectHandler(BasicMapper mapper, @Value("${allnet.server.host:}") String ALLNET_HOST,
|
||||
@Value("${allnet.server.port:}") String ALLNET_PORT, @Value("${server.port:}") String SERVER_PORT) {
|
||||
@Value("${allnet.server.port:}") String ALLNET_PORT, @Value("${server.port:}") String SERVER_PORT) {
|
||||
this.mapper = mapper;
|
||||
this.ALLNET_HOST = ALLNET_HOST;
|
||||
this.ALLNET_PORT = ALLNET_PORT;
|
||||
|
@ -43,7 +45,8 @@ public class GetGameConnectHandler implements BaseHandler {
|
|||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
int type = ((Number) request.get("type")).intValue(); // Allnet enabled or not
|
||||
long version = ((Number) request.get("version")).longValue(); // Rom version
|
||||
|
||||
KeychipSession session = TokenChecker.Companion.getCurrentSession();
|
||||
|
||||
// Unless ip and port is explicitly overridden, use the guessed ip and port as same as AllNet Controller does.
|
||||
String localAddr;
|
||||
try {
|
||||
|
@ -56,10 +59,11 @@ public class GetGameConnectHandler implements BaseHandler {
|
|||
String addr = ALLNET_HOST.equals("") ? localAddr : ALLNET_HOST;
|
||||
String port = ALLNET_PORT.equals("") ? SERVER_PORT : ALLNET_PORT;
|
||||
|
||||
String base = session == null ? "/g" : "/gs/" + session.getToken();
|
||||
List<GameConnect> gameConnectList = new ArrayList<>();
|
||||
GameConnect chuni = new GameConnect(0, 1, "http://" + addr + ":" + port + "/g/chu3/" + version + "/");
|
||||
GameConnect mai = new GameConnect(1, 1, "http://" + addr + ":" + port + "/g/mai2/");
|
||||
GameConnect ongeki = new GameConnect(2, 1, "http://" + addr + ":" + port + "/g/ongeki/");
|
||||
GameConnect chuni = new GameConnect(0, 1, "http://" + addr + ":" + port + base + "/chu3/" + version + "/");
|
||||
GameConnect mai = new GameConnect(1, 1, "http://" + addr + ":" + port + base + "/mai2/");
|
||||
GameConnect ongeki = new GameConnect(2, 1, "http://" + addr + ":" + port + base + "/ongeki/");
|
||||
gameConnectList.add(chuni);
|
||||
gameConnectList.add(mai);
|
||||
gameConnectList.add(ongeki);
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
ALTER TABLE chusan_user_data ADD COLUMN trophy_id_sub1 INT NOT NULL DEFAULT 0;
|
||||
ALTER TABLE chusan_user_data ADD COLUMN trophy_id_sub2 INT NOT NULL DEFAULT 0;
|
||||
|
||||
CREATE TABLE chusan_user_challenge
|
||||
(
|
||||
id BIGINT AUTO_INCREMENT NOT NULL PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
unlock_challenge_id INT NOT NULL,
|
||||
status INT NOT NULL,
|
||||
clear_course_id INT NOT NULL,
|
||||
condition_type INT NOT NULL,
|
||||
score INT NOT NULL,
|
||||
life INT NOT NULL,
|
||||
clear_date VARCHAR(20) NULL,
|
||||
CONSTRAINT fku_chusan_user_challenge FOREIGN KEY (user_id) REFERENCES chusan_user_data (id) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT unique_user_challenge UNIQUE (user_id, unlock_challenge_id)
|
||||
);
|
Loading…
Reference in New Issue