mirror of
https://github.com/asphyxia-core/plugins.git
synced 2026-08-12 20:55:51 -05:00
Merge branch 'stable' of https://github.com/cracrayol/plugins into stable
This commit is contained in:
18
ddr@asphyxia/README.md
Normal file
18
ddr@asphyxia/README.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Dance Dance Revolution
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
Supported version
|
||||
|
||||
- Dance Dance Revolution A20
|
||||
- Dance Dance Revolution A
|
||||
|
||||
---
|
||||
|
||||
Changelogs
|
||||
|
||||
**v1.0.0**
|
||||
|
||||
- Initial release
|
||||
18
ddr@asphyxia/handlers/common.ts
Normal file
18
ddr@asphyxia/handlers/common.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export const eventLog: EPR = (info, data, send) => {
|
||||
return send.object({
|
||||
gamesession: K.ITEM("s64", BigInt(1)),
|
||||
logsendflg: K.ITEM("s32", 0),
|
||||
logerrlevel: K.ITEM("s32", 0),
|
||||
evtidnosendflg: K.ITEM("s32", 0)
|
||||
});
|
||||
};
|
||||
|
||||
export const convcardnumber: EPR = (info, data, send) => {
|
||||
return send.object({
|
||||
result: K.ITEM("s32", 0),
|
||||
|
||||
data: {
|
||||
card_number: K.ITEM("str", $(data).str("data.card_id").split("|")[0])
|
||||
}
|
||||
});
|
||||
};
|
||||
275
ddr@asphyxia/handlers/usergamedata.ts
Normal file
275
ddr@asphyxia/handlers/usergamedata.ts
Normal file
@@ -0,0 +1,275 @@
|
||||
import { CommonOffset, LastOffset, OptionOffset, Profile } from "../models/profile";
|
||||
import { formatCode } from "../utils";
|
||||
import { Score } from "../models/score";
|
||||
import { Ghost } from "../models/ghost";
|
||||
|
||||
enum GameStyle {
|
||||
SINGLE,
|
||||
DOUBLE,
|
||||
VERSUS
|
||||
}
|
||||
|
||||
export const usergamedata: EPR = async (info, data, send) => {
|
||||
const mode = $(data).str("data.mode");
|
||||
const refId = $(data).str("data.refid");
|
||||
|
||||
switch (mode) {
|
||||
case "userload":
|
||||
return send.object(await userload(refId));
|
||||
case "usernew":
|
||||
return send.object(await usernew(refId, data));
|
||||
case "usersave":
|
||||
return send.object(await usersave(refId, data));
|
||||
case "rivalload":
|
||||
return send.object(await rivalload(refId, data));
|
||||
case "ghostload":
|
||||
return send.object(await ghostload(refId, data));
|
||||
case "inheritance":
|
||||
return send.object(inheritance(refId));
|
||||
default:
|
||||
return send.deny();
|
||||
}
|
||||
};
|
||||
|
||||
const userload = async (refId: string) => {
|
||||
let resObj = {
|
||||
result: K.ITEM("s32", 0),
|
||||
is_new: K.ITEM("bool", false),
|
||||
music: [],
|
||||
eventdata: []
|
||||
};
|
||||
|
||||
if (!refId.startsWith("X000")) {
|
||||
const profile = await DB.FindOne<Profile>(refId, { collection: "profile" });
|
||||
|
||||
if (!profile) resObj.is_new = K.ITEM("bool", true);
|
||||
|
||||
const scores = await DB.Find<Score>(refId, { collection: "score" });
|
||||
|
||||
for (const score of scores) {
|
||||
const note = [];
|
||||
|
||||
for (let i = 0; i < 9; i++) {
|
||||
if (score.difficulty !== i) {
|
||||
note.push({
|
||||
count: K.ITEM("u16", 0),
|
||||
rank: K.ITEM("u8", 0),
|
||||
clearkind: K.ITEM("u8", 0),
|
||||
score: K.ITEM("s32", 0),
|
||||
ghostid: K.ITEM("s32", 0)
|
||||
});
|
||||
} else {
|
||||
note.push({
|
||||
count: K.ITEM("u16", 1),
|
||||
rank: K.ITEM("u8", score.rank),
|
||||
clearkind: K.ITEM("u8", score.clearKind),
|
||||
score: K.ITEM("s32", score.score),
|
||||
ghostid: K.ITEM("s32", score.songId)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
resObj.music.push({
|
||||
mcode: K.ITEM("u32", score.songId),
|
||||
note
|
||||
});
|
||||
}
|
||||
|
||||
resObj["grade"] = {
|
||||
single_grade: K.ITEM("u32", profile.singleGrade || 0),
|
||||
dougle_grade: K.ITEM("u32", profile.doubleGrade || 0)
|
||||
};
|
||||
}
|
||||
|
||||
return resObj;
|
||||
};
|
||||
|
||||
const usernew = async (refId: string, data: any) => {
|
||||
const shopArea = $(data).str("data.shoparea", "");
|
||||
|
||||
let profile = await DB.FindOne<Profile>(refId, { collection: "profile" });
|
||||
|
||||
if (!profile) {
|
||||
profile = (await DB.Upsert<Profile>(refId, { collection: "profile" }, {
|
||||
collection: "profile",
|
||||
ddrCode: _.random(1, 99999999),
|
||||
shopArea
|
||||
})).docs[0];
|
||||
}
|
||||
|
||||
return {
|
||||
result: K.ITEM("s32", 0),
|
||||
seq: K.ITEM("str", formatCode(profile.ddrCode)),
|
||||
code: K.ITEM("s32", profile.ddrCode),
|
||||
shoparea: K.ITEM("str", profile.shopArea),
|
||||
};
|
||||
};
|
||||
|
||||
const usersave = async (refId: string, serverData: any) => {
|
||||
const profile = await DB.FindOne<Profile>(refId, { collection: "profile" });
|
||||
|
||||
if (profile) {
|
||||
const data = $(serverData).element("data");
|
||||
const notes = data.elements("note");
|
||||
const events = data.elements("event");
|
||||
|
||||
const common = profile.usergamedata.COMMON.strdata.split(",");
|
||||
const option = profile.usergamedata.OPTION.strdata.split(",");
|
||||
const last = profile.usergamedata.LAST.strdata.split(",");
|
||||
|
||||
if (data.bool("isgameover")) {
|
||||
const style = data.number("playstyle");
|
||||
|
||||
if (style === GameStyle.DOUBLE) {
|
||||
common[CommonOffset.DOUBLE_PLAYS] = (parseInt(common[CommonOffset.DOUBLE_PLAYS]) + 1) + "";
|
||||
} else {
|
||||
common[CommonOffset.SINGLE_PLAYS] = (parseInt(common[CommonOffset.SINGLE_PLAYS]) + 1) + "";
|
||||
}
|
||||
|
||||
common[CommonOffset.TOTAL_PLAYS] = (+common[CommonOffset.DOUBLE_PLAYS]) + (+common[CommonOffset.SINGLE_PLAYS]) + "";
|
||||
|
||||
const workoutEnabled = !!+common[CommonOffset.WEIGHT_DISPLAY];
|
||||
const workoutWeight = +common[CommonOffset.WEIGHT];
|
||||
|
||||
if (workoutEnabled && workoutWeight > 0) {
|
||||
let total = 0;
|
||||
|
||||
for (const note of notes) {
|
||||
total = total + note.number("calorie", 0);
|
||||
}
|
||||
|
||||
last[LastOffset.CALORIES] = total + "";
|
||||
}
|
||||
|
||||
for (const event of events) {
|
||||
const eventId = event.number("eventid", 0);
|
||||
const eventType = event.number("eventtype", 0);
|
||||
if (eventId === 0 || eventType === 0) continue;
|
||||
|
||||
const eventCompleted = event.number("comptime") !== 0;
|
||||
const eventProgress = event.number("savedata");
|
||||
|
||||
if (!profile.events) profile.events = {};
|
||||
profile.events[eventId] = {
|
||||
completed: eventCompleted,
|
||||
progress: eventProgress
|
||||
};
|
||||
}
|
||||
|
||||
const gradeNode = data.element("grade");
|
||||
|
||||
if (gradeNode) {
|
||||
const single = gradeNode.number("single_grade", 0);
|
||||
const double = gradeNode.number("double_grade", 0);
|
||||
|
||||
profile.singleGrade = single;
|
||||
profile.doubleGrade = double;
|
||||
}
|
||||
}
|
||||
|
||||
let scoreData: KDataReader | null;
|
||||
let stageNum = 0;
|
||||
|
||||
for (const note of notes) {
|
||||
if (note.number("stagenum") > stageNum) {
|
||||
scoreData = note;
|
||||
stageNum = note.number("stagenum");
|
||||
}
|
||||
}
|
||||
|
||||
if (scoreData) {
|
||||
const songId = scoreData.number("mcode");
|
||||
const difficulty = scoreData.number("notetype");
|
||||
const rank = scoreData.number("rank");
|
||||
const clearKind = scoreData.number("clearkind");
|
||||
const score = scoreData.number("score");
|
||||
const maxCombo = scoreData.number("maxcombo");
|
||||
const ghostSize = scoreData.number("ghostsize");
|
||||
const ghost = scoreData.str("ghost");
|
||||
|
||||
option[OptionOffset.SPEED] = scoreData.number("opt_speed").toString(16);
|
||||
option[OptionOffset.BOOST] = scoreData.number("opt_boost").toString(16);
|
||||
option[OptionOffset.APPEARANCE] = scoreData.number("opt_appearance").toString(16);
|
||||
option[OptionOffset.TURN] = scoreData.number("opt_turn").toString(16);
|
||||
option[OptionOffset.STEP_ZONE] = scoreData.number("opt_dark").toString(16);
|
||||
option[OptionOffset.SCROLL] = scoreData.number("opt_scroll").toString(16);
|
||||
option[OptionOffset.ARROW_COLOR] = scoreData.number("opt_arrowcolor").toString(16);
|
||||
option[OptionOffset.CUT] = scoreData.number("opt_cut").toString(16);
|
||||
option[OptionOffset.FREEZE] = scoreData.number("opt_freeze").toString(16);
|
||||
option[OptionOffset.JUMP] = scoreData.number("opt_jump").toString(16);
|
||||
option[OptionOffset.ARROW_SKIN] = scoreData.number("opt_arrowshape").toString(16);
|
||||
option[OptionOffset.FILTER] = scoreData.number("opt_filter").toString(16);
|
||||
option[OptionOffset.GUIDELINE] = scoreData.number("opt_guideline").toString(16);
|
||||
option[OptionOffset.GAUGE] = scoreData.number("opt_gauge").toString(16);
|
||||
option[OptionOffset.COMBO_POSITION] = scoreData.number("opt_judgepriority").toString(16);
|
||||
option[OptionOffset.FAST_SLOW] = scoreData.number("opt_timing").toString(16);
|
||||
|
||||
await DB.Upsert<Score>(refId, {
|
||||
collection: "score",
|
||||
songId,
|
||||
difficulty
|
||||
}, {
|
||||
$set: {
|
||||
rank,
|
||||
clearKind,
|
||||
score,
|
||||
maxCombo
|
||||
}
|
||||
});
|
||||
|
||||
await DB.Upsert<Ghost>(refId, {
|
||||
collection: "ghost",
|
||||
songId,
|
||||
difficulty
|
||||
}, {
|
||||
$set: {
|
||||
ghostSize,
|
||||
ghost
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
await DB.Update<Profile>(refId, { collection: "profile" }, {
|
||||
$set: {
|
||||
"usergamedata.COMMON.strdata": common.join(","),
|
||||
"usergamedata.OPTION.strdata": option.join(","),
|
||||
"usergamedata.LAST.strdata": last.join(","),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
result: K.ITEM("s32", 0)
|
||||
};
|
||||
};
|
||||
|
||||
const rivalload = (refId: string, data: any) => {
|
||||
const loadFlag = $(data).number("data.loadflag");
|
||||
|
||||
const record = [];
|
||||
|
||||
return {
|
||||
result: K.ITEM("s32", 0),
|
||||
|
||||
data: {
|
||||
recordtype: K.ITEM("s32", loadFlag),
|
||||
record
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const ghostload = (refId: string, data: any) => {
|
||||
const ghostdata = {};
|
||||
|
||||
return {
|
||||
result: K.ITEM("s32", 0),
|
||||
ghostdata
|
||||
};
|
||||
};
|
||||
|
||||
const inheritance = (refId: string) => {
|
||||
return {
|
||||
result: K.ITEM("s32", 0),
|
||||
InheritanceStatus: K.ITEM("s32", 1)
|
||||
};
|
||||
};
|
||||
45
ddr@asphyxia/handlers/usergamedata_recv.ts
Normal file
45
ddr@asphyxia/handlers/usergamedata_recv.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { Profile } from "../models/profile";
|
||||
|
||||
export const usergamedata_recv: EPR = async (info, data, send) => {
|
||||
const refId = $(data).str("data.refid");
|
||||
const profile = await DB.FindOne<Profile>(refId, { collection: "profile" });
|
||||
|
||||
let recordNum = 0;
|
||||
const record = [];
|
||||
|
||||
const d = [];
|
||||
const types = $(data).str("data.recv_csv").split(",").filter((_, i) => (i % 2 === 0));
|
||||
|
||||
for (const type of types) {
|
||||
let strdata = "<NODATA>";
|
||||
let bindata = "<NODATA>";
|
||||
|
||||
if (profile) {
|
||||
strdata = profile.usergamedata[type]["strdata"];
|
||||
bindata = profile.usergamedata[type]["bindata"];
|
||||
|
||||
if (type === "OPTION") {
|
||||
const split = strdata.split(",");
|
||||
|
||||
split[0] = U.GetConfig("save_option") ? "1" : "0";
|
||||
|
||||
strdata = split.join(",");
|
||||
}
|
||||
}
|
||||
|
||||
d.push({
|
||||
...K.ITEM("str", !profile ? strdata : Buffer.from(strdata).toString("base64")),
|
||||
...profile && { bin1: K.ITEM("str", Buffer.from(bindata).toString("base64")) }
|
||||
});
|
||||
recordNum++;
|
||||
}
|
||||
record.push({ d });
|
||||
|
||||
return send.object({
|
||||
result: K.ITEM("s32", 0),
|
||||
player: {
|
||||
record,
|
||||
record_num: K.ITEM("u32", recordNum)
|
||||
}
|
||||
});
|
||||
};
|
||||
31
ddr@asphyxia/handlers/usergamedata_send.ts
Normal file
31
ddr@asphyxia/handlers/usergamedata_send.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { Profile } from "../models/profile";
|
||||
|
||||
export const usergamedata_send: EPR = async (info, data, send) => {
|
||||
const refId = $(data).str("data.refid");
|
||||
|
||||
const profile = await DB.FindOne<Profile>(refId, { collection: "profile" });
|
||||
if (!profile) return send.deny();
|
||||
|
||||
for (const record of $(data).elements("data.record.d")) {
|
||||
const decodeStr = Buffer.from(record.str("", ""), "base64").toString("ascii");
|
||||
const decodeBin = Buffer.from(record.str("bin1", ""), "base64").toString("ascii");
|
||||
|
||||
const strdata = decodeStr.split(",");
|
||||
const type = Buffer.from(strdata[1]).toString("utf-8");
|
||||
|
||||
if (!profile.usergamedata) profile.usergamedata = {};
|
||||
if (!profile.usergamedata[type]) profile.usergamedata[type] = {};
|
||||
profile.usergamedata[type] = {
|
||||
strdata: strdata.slice(2, -1).join(","),
|
||||
bindata: decodeBin
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
await DB.Update<Profile>(refId, { collection: "profile" }, profile);
|
||||
|
||||
return send.object({ result: K.ITEM("s32", 0) });
|
||||
} catch {
|
||||
return send.deny();
|
||||
}
|
||||
};
|
||||
135
ddr@asphyxia/index.ts
Normal file
135
ddr@asphyxia/index.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
import { convcardnumber, eventLog } from "./handlers/common";
|
||||
import { usergamedata } from "./handlers/usergamedata";
|
||||
import { usergamedata_recv } from "./handlers/usergamedata_recv";
|
||||
import { usergamedata_send } from "./handlers/usergamedata_send";
|
||||
import { CommonOffset, OptionOffset, Profile } from "./models/profile";
|
||||
|
||||
export function register() {
|
||||
R.GameCode("MDX");
|
||||
|
||||
R.Config("save_option", {
|
||||
name: "Save option",
|
||||
desc: "Gets the previously set options as they are.",
|
||||
default: true,
|
||||
type: "boolean"
|
||||
});
|
||||
|
||||
R.Route("playerdata.usergamedata_advanced", usergamedata);
|
||||
R.Route("playerdata.usergamedata_recv", usergamedata_recv);
|
||||
R.Route("playerdata.usergamedata_send", usergamedata_send);
|
||||
|
||||
R.Route("system.convcardnumber", convcardnumber);
|
||||
R.Route("eventlog.write", eventLog);
|
||||
|
||||
R.WebUIEvent("updateName", async ({ refid, name }) => {
|
||||
let strdata: Profile | string[] = await DB.FindOne<Profile>(refid, { collection: "profile" });
|
||||
|
||||
if (strdata) {
|
||||
strdata = strdata.usergamedata.COMMON.strdata.split(",");
|
||||
strdata[CommonOffset.NAME] = name;
|
||||
await DB.Update<Profile>(refid, { collection: "profile" }, {
|
||||
$set: {
|
||||
"usergamedata.COMMON.strdata": strdata.join(",")
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
R.WebUIEvent("updateWeight", async ({ refid, weight }) => {
|
||||
let strdata: Profile | string[] = await DB.FindOne<Profile>(refid, { collection: "profile" });
|
||||
|
||||
if (strdata) {
|
||||
strdata = strdata.usergamedata.COMMON.strdata.split(",");
|
||||
strdata[CommonOffset.WEIGHT] = weight;
|
||||
await DB.Update<Profile>(refid, { collection: "profile" }, {
|
||||
$set: {
|
||||
"usergamedata.COMMON.strdata": strdata.join(",")
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
R.WebUIEvent("updateDisplayCalories", async ({ refid, selected }) => {
|
||||
let strdata: Profile | string[] = await DB.FindOne<Profile>(refid, { collection: "profile" });
|
||||
|
||||
if (strdata) {
|
||||
strdata = strdata.usergamedata.COMMON.strdata.split(",");
|
||||
strdata[CommonOffset.WEIGHT_DISPLAY] = selected;
|
||||
await DB.Update<Profile>(refid, { collection: "profile" }, {
|
||||
$set: {
|
||||
"usergamedata.COMMON.strdata": strdata.join(",")
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
R.WebUIEvent("updateArrowSkin", async ({ refid, selected }) => {
|
||||
let strdata: Profile | string[] = await DB.FindOne<Profile>(refid, { collection: "profile" });
|
||||
|
||||
if (strdata) {
|
||||
strdata = strdata.usergamedata.OPTION.strdata.split(",");
|
||||
strdata[OptionOffset.ARROW_SKIN] = selected;
|
||||
await DB.Update<Profile>(refid, { collection: "profile" }, {
|
||||
$set: {
|
||||
"usergamedata.OPTION.strdata": strdata.join(",")
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
R.WebUIEvent("updateGuideline", async ({ refid, selected }) => {
|
||||
let strdata: Profile | string[] = await DB.FindOne<Profile>(refid, { collection: "profile" });
|
||||
|
||||
if (strdata) {
|
||||
strdata = strdata.usergamedata.OPTION.strdata.split(",");
|
||||
strdata[OptionOffset.GUIDELINE] = selected;
|
||||
await DB.Update<Profile>(refid, { collection: "profile" }, {
|
||||
$set: {
|
||||
"usergamedata.OPTION.strdata": strdata.join(",")
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
R.WebUIEvent("updateFilter", async ({ refid, selected }) => {
|
||||
let strdata: Profile | string[] = await DB.FindOne<Profile>(refid, { collection: "profile" });
|
||||
|
||||
if (strdata) {
|
||||
strdata = strdata.usergamedata.OPTION.strdata.split(",");
|
||||
strdata[OptionOffset.FILTER] = selected;
|
||||
await DB.Update<Profile>(refid, { collection: "profile" }, {
|
||||
$set: {
|
||||
"usergamedata.OPTION.strdata": strdata.join(",")
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
R.WebUIEvent("updateJudgmentPriority", async ({ refid, selected }) => {
|
||||
let strdata: Profile | string[] = await DB.FindOne<Profile>(refid, { collection: "profile" });
|
||||
|
||||
if (strdata) {
|
||||
strdata = strdata.usergamedata.OPTION.strdata.split(",");
|
||||
strdata[OptionOffset.COMBO_POSITION] = selected;
|
||||
await DB.Update<Profile>(refid, { collection: "profile" }, {
|
||||
$set: {
|
||||
"usergamedata.OPTION.strdata": strdata.join(",")
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
R.WebUIEvent("updateDisplayTiming", async ({ refid, selected }) => {
|
||||
let strdata: Profile | string[] = await DB.FindOne<Profile>(refid, { collection: "profile" });
|
||||
|
||||
if (strdata) {
|
||||
strdata = strdata.usergamedata.OPTION.strdata.split(",");
|
||||
strdata[OptionOffset.FAST_SLOW] = selected;
|
||||
await DB.Update<Profile>(refid, { collection: "profile" }, {
|
||||
$set: {
|
||||
"usergamedata.OPTION.strdata": strdata.join(",")
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
8
ddr@asphyxia/models/ghost.ts
Normal file
8
ddr@asphyxia/models/ghost.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export interface Ghost {
|
||||
collection: "ghost";
|
||||
|
||||
songId: number;
|
||||
difficulty: number;
|
||||
ghostSize: number;
|
||||
ghost: string;
|
||||
}
|
||||
77
ddr@asphyxia/models/profile.ts
Normal file
77
ddr@asphyxia/models/profile.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
export enum CommonOffset {
|
||||
AREA = 1,
|
||||
SEQ_HEX = 1,
|
||||
WEIGHT_DISPLAY = 3,
|
||||
CHARACTER,
|
||||
EXTRA_CHARGE,
|
||||
TOTAL_PLAYS = 9,
|
||||
SINGLE_PLAYS = 11,
|
||||
DOUBLE_PLAYS,
|
||||
WEIGHT = 17,
|
||||
NAME = 25,
|
||||
SEQ
|
||||
}
|
||||
|
||||
export enum OptionOffset {
|
||||
SPEED = 1,
|
||||
BOOST,
|
||||
APPEARANCE,
|
||||
TURN,
|
||||
STEP_ZONE,
|
||||
SCROLL,
|
||||
ARROW_COLOR,
|
||||
CUT,
|
||||
FREEZE,
|
||||
JUMP,
|
||||
ARROW_SKIN,
|
||||
FILTER,
|
||||
GUIDELINE,
|
||||
GAUGE,
|
||||
COMBO_POSITION,
|
||||
FAST_SLOW
|
||||
}
|
||||
|
||||
export enum LastOffset {
|
||||
SONG = 3,
|
||||
CALORIES = 10
|
||||
}
|
||||
|
||||
export enum RivalOffset {
|
||||
RIVAL_1_ACTIVE = 1,
|
||||
RIVAL_2_ACTIVE,
|
||||
RIVAL_3_ACTIVE,
|
||||
RIVAL_1_DDRCODE = 9,
|
||||
RIVAL_2_DDRCODE,
|
||||
RIVAL_3_DDRCODE,
|
||||
}
|
||||
|
||||
export interface Profile {
|
||||
collection: "profile";
|
||||
|
||||
ddrCode: number;
|
||||
shopArea: string;
|
||||
|
||||
singleGrade?: number;
|
||||
doubleGrade?: number;
|
||||
|
||||
events?: {};
|
||||
|
||||
usergamedata?: {
|
||||
COMMON?: {
|
||||
strdata?: string;
|
||||
bindata?: string;
|
||||
};
|
||||
OPTION?: {
|
||||
strdata?: string;
|
||||
bindata?: string;
|
||||
};
|
||||
LAST?: {
|
||||
strdata?: string;
|
||||
bindata?: string;
|
||||
};
|
||||
RIVAL?: {
|
||||
strdata?: string;
|
||||
bindata?: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
49
ddr@asphyxia/models/score.ts
Normal file
49
ddr@asphyxia/models/score.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
export enum Difficulty {
|
||||
SINGLE_BEGINNER,
|
||||
SINGLE_BASIC,
|
||||
SINGLE_DIFFICULT,
|
||||
SINGLE_EXPERT,
|
||||
SINGLE_CHALLENGE,
|
||||
DOUBLE_BASIC,
|
||||
DOUBLE_DIFFICULT,
|
||||
DOUBLE_EXPERT,
|
||||
DOUBLE_CHALLENGE
|
||||
}
|
||||
|
||||
export enum Rank {
|
||||
AAA,
|
||||
AA_PLUS,
|
||||
AA,
|
||||
AA_MINUS,
|
||||
A_PLUS,
|
||||
A,
|
||||
A_MINUS,
|
||||
B_PLUS,
|
||||
B,
|
||||
B_MINUS,
|
||||
C_PLUS,
|
||||
C,
|
||||
C_MINUS,
|
||||
D_PLUS,
|
||||
D,
|
||||
E
|
||||
}
|
||||
|
||||
export enum ClearKind {
|
||||
NONE = 6,
|
||||
GOOD_COMBO,
|
||||
GREAT_COMBO,
|
||||
PERPECT_COMBO,
|
||||
MARVELOUS_COMBO
|
||||
}
|
||||
|
||||
export interface Score {
|
||||
collection: "score";
|
||||
|
||||
songId: number;
|
||||
difficulty: Difficulty;
|
||||
rank: Rank;
|
||||
clearKind: ClearKind;
|
||||
score: number;
|
||||
maxCombo: number;
|
||||
}
|
||||
13
ddr@asphyxia/utils.ts
Normal file
13
ddr@asphyxia/utils.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export function getVersion(info: EamuseInfo) {
|
||||
const dateCode = parseInt(info.model.split(":")[4]);
|
||||
|
||||
if (dateCode >= 2019022600 && dateCode <= 2020020300) return 10;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function formatCode(ddrCode: number) {
|
||||
const pad = (ddrCode + "").padStart(8, "0");
|
||||
|
||||
return pad.replace(/^([0-9]{4})([0-9]{4})$/, "$1-$2");
|
||||
}
|
||||
49
ddr@asphyxia/webui/js/profile_settings.js
Normal file
49
ddr@asphyxia/webui/js/profile_settings.js
Normal file
@@ -0,0 +1,49 @@
|
||||
$('#change-name').on('click', () => {
|
||||
const name = $('#dancer_name').val().toUpperCase();
|
||||
|
||||
emit('updateName', { refid, name }).then(() => location.reload());
|
||||
});
|
||||
|
||||
$('#change-weight').on('click', () => {
|
||||
const weight1 = $('#weight_1').val();
|
||||
const weight2 = $('#weight_2').val();
|
||||
const weight = weight1 + '.' + weight2;
|
||||
|
||||
emit('updateWeight', { refid, weight }).then(() => location.reload());
|
||||
});
|
||||
|
||||
$('#change-display-calories').on('click', () => {
|
||||
const selected = $('#display_calories option:selected').val();
|
||||
|
||||
emit('updateDisplayCalories', { refid, selected }).then(() => location.reload());
|
||||
});
|
||||
|
||||
$('#change-arrow-skin').on('click', () => {
|
||||
const selected = $('#arrow_skin option:selected').val();
|
||||
|
||||
emit('updateArrowSkin', { refid, selected }).then(() => location.reload());
|
||||
});
|
||||
|
||||
$('#change-guideline').on('click', () => {
|
||||
const selected = $('#guideline option:selected').val();
|
||||
|
||||
emit('updateGuideline', { refid, selected }).then(() => location.reload());
|
||||
});
|
||||
|
||||
$('#change-filter').on('click', () => {
|
||||
const selected = $('#filter option:selected').val();
|
||||
|
||||
emit('updateFilter', { refid, selected }).then(() => location.reload());
|
||||
});
|
||||
|
||||
$('#change-judgment-priority').on('click', () => {
|
||||
const selected = $('#judgment_priority option:selected').val();
|
||||
|
||||
emit('updateJudgmentPriority', { refid, selected }).then(() => location.reload());
|
||||
});
|
||||
|
||||
$('#change-display-timing').on('click', () => {
|
||||
const selected = $('#display_timing option:selected').val();
|
||||
|
||||
emit('updateDisplayTiming', { refid, selected }).then(() => location.reload());
|
||||
});
|
||||
147
ddr@asphyxia/webui/profile_settings.pug
Normal file
147
ddr@asphyxia/webui/profile_settings.pug
Normal file
@@ -0,0 +1,147 @@
|
||||
//DATA//
|
||||
profile: DB.FindOne(refid, { collection: "profile" })
|
||||
|
||||
-
|
||||
const onOff = [ "Off", "On" ];
|
||||
const characters = [ "All Character Random", "Man Random", "Female Random", "Yuni", "Rage", "Afro", "Jenny", "Emi", "Baby-Lon", "Gus", "Ruby", "Alice", "Julio", "Bonnie", "Zero", "Rinon" ];
|
||||
const arrowSkins = [ "Normal", "X", "Classic", "Cyber", "Medium", "Small", "Dot" ];
|
||||
const guidelines = [ "Off", "Border", "Center" ];
|
||||
const filters = [ "Off", "Dark", "Darker", "Darkest" ];
|
||||
const judgmentPrioritys = [ "Judgment priority", "Arrow priority" ];
|
||||
|
||||
if (profile.usergamedata)
|
||||
-
|
||||
const common = profile.usergamedata.COMMON.strdata.split(",");
|
||||
const option = profile.usergamedata.OPTION.strdata.split(",");
|
||||
|
||||
const name = common[25];
|
||||
const weight = common[17];
|
||||
const displayCalories = parseInt(common[3]);
|
||||
const character = parseInt(common[4]);
|
||||
const arrowSkin = parseInt(option[11]);
|
||||
const guideline = parseInt(option[13]);
|
||||
const filter = parseInt(option[12]);
|
||||
const judgmentPriority = parseInt(option[15]);
|
||||
const displayTiming = parseInt(option[16]);
|
||||
|
||||
div
|
||||
.card
|
||||
.card-header
|
||||
p.card-header-title
|
||||
span.icon
|
||||
i.mdi.mdi-cog
|
||||
| Profile Settings
|
||||
|
||||
.card-content
|
||||
.field.is-horizontal.has-addons
|
||||
.field-label.is-normal
|
||||
label.label Dancer Name
|
||||
.field-body
|
||||
p.control
|
||||
input.input(type="text", id="dancer_name", pattern="[A-Z]{8}", maxlength=8, value=name)
|
||||
p.control
|
||||
a.button.is-primary#change-name Change
|
||||
|
||||
.field.is-horizontal.has-addons
|
||||
.field-label.is-normal
|
||||
label.label Workout Weight
|
||||
.field-body
|
||||
p.control
|
||||
input.input(type="number", id="weight_1", value=weight.split(".")[0])
|
||||
p.control
|
||||
input.input(type="number", id="weight_2", value=weight.split(".")[1])
|
||||
p.control
|
||||
a.button.is-primary#change-weight Change
|
||||
|
||||
.field.is-horizontal.has-addons
|
||||
.field-label.is-normal
|
||||
label.label Workout Display Calories
|
||||
.field-body
|
||||
p.control
|
||||
.select
|
||||
select#display_calories
|
||||
if (displayCalories === 1)
|
||||
option(value=0) Off
|
||||
option(value=1, selected) On
|
||||
else
|
||||
option(value=0, selected) Off
|
||||
option(value=1) On
|
||||
p.control
|
||||
a.button.is-primary#change-display-calories Submit
|
||||
|
||||
.field.is-horizontal.has-addons
|
||||
.field-label.is-normal
|
||||
label.label Arrow Skin
|
||||
.field-body
|
||||
p.control
|
||||
.select
|
||||
select#arrow_skin
|
||||
each v, i in arrowSkins
|
||||
if (arrowSkin === i)
|
||||
option(value=i, selected) #{v}
|
||||
else
|
||||
option(value=i) #{v}
|
||||
p.control
|
||||
a.button.is-primary#change-arrow-skin Submit
|
||||
|
||||
.field.is-horizontal.has-addons
|
||||
.field-label.is-normal
|
||||
label.label Guideline
|
||||
.field-body
|
||||
p.control
|
||||
.select
|
||||
select#guideline
|
||||
each v, i in guidelines
|
||||
if (guideline === i)
|
||||
option(value=i, selected) #{v}
|
||||
else
|
||||
option(value=i) #{v}
|
||||
p.control
|
||||
a.button.is-primary#change-guideline Submit
|
||||
|
||||
.field.is-horizontal.has-addons
|
||||
.field-label.is-normal
|
||||
label.label Filter concentration
|
||||
.field-body
|
||||
p.control
|
||||
.select
|
||||
select#filter
|
||||
each v, i in filters
|
||||
if (filter === i)
|
||||
option(value=i, selected) #{v}
|
||||
else
|
||||
option(value=i) #{v}
|
||||
p.control
|
||||
a.button.is-primary#change-filter Submit
|
||||
|
||||
.field.is-horizontal.has-addons
|
||||
.field-label.is-normal
|
||||
label.label Judgment display priority
|
||||
.field-body
|
||||
p.control
|
||||
.select
|
||||
select#judgment_priority
|
||||
each v, i in judgmentPrioritys
|
||||
if (judgmentPriority === i)
|
||||
option(value=i, selected) #{v}
|
||||
else
|
||||
option(value=i) #{v}
|
||||
p.control
|
||||
a.button.is-primary#change-judgment-priority Submit
|
||||
|
||||
.field.is-horizontal.has-addons
|
||||
.field-label.is-normal
|
||||
label.label Display Timing judgment
|
||||
.field-body
|
||||
p.control
|
||||
.select
|
||||
select#display_timing
|
||||
each v, i in ["Off", "On"]
|
||||
if (displayTiming === i)
|
||||
option(value=i, selected) #{v}
|
||||
else
|
||||
option(value=i) #{v}
|
||||
p.control
|
||||
a.button.is-primary#change-display-timing Submit
|
||||
|
||||
script(src="static/js/profile_settings.js")
|
||||
@@ -1,15 +1,45 @@
|
||||
GITADORA Plugin for Asphyxia-Core
|
||||
=================================
|
||||
This plugin is converted from public-exported Asphyxia's Routes.
|
||||

|
||||
|
||||
This plugin is based on converted from public-exported Asphyxia's Routes.
|
||||
|
||||
Supported Versions
|
||||
==================
|
||||
- Matixx
|
||||
- Exchain
|
||||
- NEX+AGE
|
||||
|
||||
|
||||
When Plugin Doesn't work correctly / Startup Error on Plugin
|
||||
------------------------------------------------------------
|
||||
The folder structure between v1.0 and v1.1 is quite different. Do not overwrite plugin folder.
|
||||
<br>If encounter error, Please try these step:
|
||||
|
||||
1. Remove `gitadora@asphyxia` folder.
|
||||
2. C-C and C-V the newest version of `gitadora@asphyxia`
|
||||
3. (Custom MDB Users) Reupload MDB or move `data/custom_mdb.xml` to `data/mdb/custom.xml`
|
||||
|
||||
|
||||
Known Issues
|
||||
============
|
||||
* Information dialog keep showing as plugin doesn't store item data currently.
|
||||
* Special Premium Encore on Nextage
|
||||
- Bandage solution is implemented. Try it.
|
||||
|
||||
Release Notes
|
||||
=============
|
||||
v1.0.0 (Current)
|
||||
v1.1.1 (Current)
|
||||
----------------
|
||||
* fix: Error when create new profile on exchain.
|
||||
* fix: last song doesn't work correctly.
|
||||
* misc: Add logger for tracking problem.
|
||||
|
||||
v1.1.0
|
||||
------
|
||||
* NEX+AGE Support (Not full support.)
|
||||
* Restructure bit for maintaining.
|
||||
|
||||
v1.0.0
|
||||
------
|
||||
* Initial release for public
|
||||
5
gitadora@asphyxia/data/.gitignore
vendored
5
gitadora@asphyxia/data/.gitignore
vendored
@@ -1,5 +0,0 @@
|
||||
mdb_ex.xml
|
||||
mdb_mt.xml
|
||||
mdb_ex.b64
|
||||
mdb_mt.b64
|
||||
custom_mdb.xml
|
||||
@@ -1,58 +0,0 @@
|
||||
import { CommonMusicData, readJSONOrXML, readXML } from './helper';
|
||||
|
||||
export async function processData() {
|
||||
const { music } = await readJSONOrXML('data/mdb_ex.json', 'data/mdb_ex.xml', processRawData)
|
||||
return {
|
||||
music,
|
||||
};
|
||||
}
|
||||
|
||||
export async function processRawData(path: string): Promise<CommonMusicData> {
|
||||
const data = await readXML(path)
|
||||
const mdb = $(data).elements("mdb.mdb_data");
|
||||
const music: any[] = [];
|
||||
for (const m of mdb) {
|
||||
const d = m.numbers("xg_diff_list");
|
||||
const contain = m.numbers("contain_stat");
|
||||
const gf = contain[0];
|
||||
const dm = contain[1];
|
||||
|
||||
if (gf == 0 && dm == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let type = gf;
|
||||
if (gf == 0) {
|
||||
type = dm;
|
||||
}
|
||||
|
||||
music.push({
|
||||
id: K.ITEM('s32', m.number("music_id")),
|
||||
cont_gf: K.ITEM('bool', gf == 0 ? 0 : 1),
|
||||
cont_dm: K.ITEM('bool', dm == 0 ? 0 : 1),
|
||||
is_secret: K.ITEM('bool', 0),
|
||||
is_hot: K.ITEM('bool', type == 2 ? 0 : 1),
|
||||
data_ver: K.ITEM('s32', m.number("data_ver")),
|
||||
diff: K.ARRAY('u16', [
|
||||
d[0],
|
||||
d[1],
|
||||
d[2],
|
||||
d[3],
|
||||
d[4],
|
||||
d[10],
|
||||
d[11],
|
||||
d[12],
|
||||
d[13],
|
||||
d[14],
|
||||
d[5],
|
||||
d[6],
|
||||
d[7],
|
||||
d[8],
|
||||
d[9],
|
||||
]),
|
||||
});
|
||||
}
|
||||
return {
|
||||
music,
|
||||
};
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
import { CommonMusicData, readJSONOrXML, readXML } from './helper';
|
||||
|
||||
export async function processData() {
|
||||
const { music } = await readJSONOrXML('data/mdb_mt.json', 'data/mdb_mt.xml', processRawData)
|
||||
return {
|
||||
music,
|
||||
};
|
||||
}
|
||||
|
||||
export async function processRawData(path: string): Promise<CommonMusicData> {
|
||||
const data = await readXML(path)
|
||||
const mdb = $(data).elements("mdb.mdb_data");
|
||||
const music: any[] = [];
|
||||
for (const m of mdb) {
|
||||
const d = m.numbers("xg_diff_list");
|
||||
const contain = m.numbers("contain_stat");
|
||||
const gf = contain[0];
|
||||
const dm = contain[1];
|
||||
|
||||
if (gf == 0 && dm == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let type = gf;
|
||||
if (gf == 0) {
|
||||
type = dm;
|
||||
}
|
||||
|
||||
music.push({
|
||||
id: K.ITEM('s32', m.number("music_id")),
|
||||
cont_gf: K.ITEM('bool', gf == 0 ? 0 : 1),
|
||||
cont_dm: K.ITEM('bool', dm == 0 ? 0 : 1),
|
||||
is_secret: K.ITEM('bool', 0),
|
||||
is_hot: K.ITEM('bool', type == 2 ? 0 : 1),
|
||||
data_ver: K.ITEM('s32', m.number("data_ver")),
|
||||
diff: K.ARRAY('u16', [
|
||||
d[0],
|
||||
d[1],
|
||||
d[2],
|
||||
d[3],
|
||||
d[4],
|
||||
d[10],
|
||||
d[11],
|
||||
d[12],
|
||||
d[13],
|
||||
d[14],
|
||||
d[5],
|
||||
d[6],
|
||||
d[7],
|
||||
d[8],
|
||||
d[9],
|
||||
]),
|
||||
});
|
||||
}
|
||||
return {
|
||||
music,
|
||||
};
|
||||
}
|
||||
72
gitadora@asphyxia/data/extrastage.ts
Normal file
72
gitadora@asphyxia/data/extrastage.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { getVersion } from "../utils";
|
||||
|
||||
interface EncoreStageData {
|
||||
level: number
|
||||
musics: number[]
|
||||
unlock_challenge?: number[]
|
||||
}
|
||||
|
||||
export function getEncoreStageData(info: EamuseInfo): EncoreStageData {
|
||||
const fallback = { level: 10, musics: [0] }
|
||||
const level: number = U.GetConfig("encore_version")
|
||||
const ntDummyEncore = U.GetConfig("nextage_dummy_encore")
|
||||
switch (getVersion(info)) {
|
||||
case 'nextage':
|
||||
return {
|
||||
level,
|
||||
musics: !ntDummyEncore ? [
|
||||
2587, // 悪魔のハニープリン
|
||||
2531, // The ULTIMATES -reminiscence-
|
||||
2612, // ECLIPSE 2
|
||||
2622, // Slip Into My Royal Blood
|
||||
2686, // CYCLONICxSTORM
|
||||
// FIXME: Fix special encore.
|
||||
305, 602, 703, 802, 902, 1003, 1201, 1400, 1712, 1916, 2289, 2631, // DD13 and encores.
|
||||
1704, 1811, 2121, 2201, 2624, // Soranaki and encores.
|
||||
1907, 2020, 2282, 2341, 2666 // Stargazer and encores.
|
||||
] : [
|
||||
2622, 305, 1704, 1907, 2686 // Dummy.
|
||||
]
|
||||
}
|
||||
case 'exchain':
|
||||
return {
|
||||
level,
|
||||
musics: [
|
||||
2246, // 箱庭の世界
|
||||
2498, // Cinnamon
|
||||
2500, // キヤロラ衛星の軌跡
|
||||
2529, // グリーンリーフ症候群
|
||||
2548, // Let's Dance
|
||||
2587, // 悪魔のハニープリン
|
||||
5020, // Timepiece phase II (CLASSIC)
|
||||
5033, // MODEL FT2 Miracle Version (CLASSIC)
|
||||
2586, // 美麗的夏日風
|
||||
5060, // EXCELSIOR DIVE (CLASSIC)
|
||||
2530, // The ULTIMATES -CHRONICLE-
|
||||
2581, // 幸せの代償
|
||||
5046 // Rock to Infinity (CLASSIC)
|
||||
]
|
||||
}
|
||||
case 'matixx':
|
||||
return {
|
||||
level,
|
||||
musics: [
|
||||
2432, // Durian
|
||||
2445, // ヤオヨロズランズ
|
||||
2456, // Fate of the Furious
|
||||
2441, // PIRATES BANQUET
|
||||
2444, // Aion
|
||||
2381, // Duella Lyrica
|
||||
2471, // triangulum
|
||||
2476, // MODEL FT4
|
||||
2486, // 煉獄事変
|
||||
2496, // CAPTURING XANADU
|
||||
2497, // Physical Decay
|
||||
2499, // Cinnamon
|
||||
2498 // けもののおうじゃ★めうめう
|
||||
]
|
||||
}
|
||||
default:
|
||||
return fallback
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
export interface CommonMusicDataField {
|
||||
id: KITEM<"s32">;
|
||||
cont_gf: KITEM<"bool">;
|
||||
cont_dm: KITEM<"bool">;
|
||||
is_secret: KITEM<"bool">;
|
||||
is_hot: KITEM<"bool">;
|
||||
data_ver: KITEM<"s32">;
|
||||
diff: KARRAY<"u16">;
|
||||
}
|
||||
|
||||
export interface CommonMusicData {
|
||||
music: CommonMusicDataField[]
|
||||
}
|
||||
|
||||
export async function readXML(path: string) {
|
||||
const xml = await IO.ReadFile(path, 'utf-8');
|
||||
const json = U.parseXML(xml, false)
|
||||
return json
|
||||
}
|
||||
|
||||
export async function readJSON(path: string) {
|
||||
const str = await IO.ReadFile(path, 'utf-8');
|
||||
const json = JSON.parse(str)
|
||||
return json
|
||||
}
|
||||
|
||||
export async function readJSONOrXML(jsonPath: string, xmlPath: string, processHandler: (path: string) => Promise<CommonMusicData>): Promise<CommonMusicData> {
|
||||
if (!IO.Exists(jsonPath)) {
|
||||
const data = await processHandler(xmlPath)
|
||||
await IO.WriteFile(jsonPath, JSON.stringify(data))
|
||||
return data
|
||||
} else {
|
||||
const json = JSON.parse(await IO.ReadFile(jsonPath, 'utf-8'))
|
||||
return json
|
||||
}
|
||||
}
|
||||
9
gitadora@asphyxia/data/mdb/.gitignore
vendored
Normal file
9
gitadora@asphyxia/data/mdb/.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
ex.xml
|
||||
mt.xml
|
||||
nt.xml
|
||||
hv.xml
|
||||
ex.json
|
||||
mt.json
|
||||
nt.json
|
||||
hv.json
|
||||
custom.xml
|
||||
1
gitadora@asphyxia/data/mdb/ex.b64
Normal file
1
gitadora@asphyxia/data/mdb/ex.b64
Normal file
File diff suppressed because one or more lines are too long
126
gitadora@asphyxia/data/mdb/index.ts
Normal file
126
gitadora@asphyxia/data/mdb/index.ts
Normal file
@@ -0,0 +1,126 @@
|
||||
export interface CommonMusicDataField {
|
||||
id: KITEM<"s32">;
|
||||
cont_gf: KITEM<"bool">;
|
||||
cont_dm: KITEM<"bool">;
|
||||
is_secret: KITEM<"bool">;
|
||||
is_hot: KITEM<"bool">;
|
||||
data_ver: KITEM<"s32">;
|
||||
diff: KARRAY<"u16">;
|
||||
}
|
||||
|
||||
export interface CommonMusicData {
|
||||
music: CommonMusicDataField[]
|
||||
}
|
||||
|
||||
export enum DATAVersion {
|
||||
HIGHVOLTAGE = "hv",
|
||||
NEXTAGE = "nt",
|
||||
EXCHAIN = "ex",
|
||||
MATTIX = "mt"
|
||||
}
|
||||
|
||||
type processRawDataHandler = (path: string) => Promise<CommonMusicData>
|
||||
|
||||
export async function readXML(path: string) {
|
||||
const xml = await IO.ReadFile(path, 'utf-8');
|
||||
const json = U.parseXML(xml, false)
|
||||
return json
|
||||
}
|
||||
|
||||
export async function readJSON(path: string) {
|
||||
const str = await IO.ReadFile(path, 'utf-8');
|
||||
const json = JSON.parse(str)
|
||||
return json
|
||||
}
|
||||
|
||||
export async function readJSONOrXML(jsonPath: string, xmlPath: string, processHandler: processRawDataHandler): Promise<CommonMusicData> {
|
||||
if (!IO.Exists(jsonPath)) {
|
||||
const data = await processHandler(xmlPath)
|
||||
await IO.WriteFile(jsonPath, JSON.stringify(data))
|
||||
return data
|
||||
} else {
|
||||
const json = JSON.parse(await IO.ReadFile(jsonPath, 'utf-8'))
|
||||
return json
|
||||
}
|
||||
}
|
||||
|
||||
export async function readB64JSON(b64path: string) {
|
||||
const buff = await IO.ReadFile(b64path, 'utf-8');
|
||||
return JSON.parse(Buffer.from(buff, 'base64').toString('utf-8'));
|
||||
}
|
||||
|
||||
export function gameVerToDataVer(ver: string): DATAVersion {
|
||||
switch(ver) {
|
||||
case 'highvoltage':
|
||||
return DATAVersion.HIGHVOLTAGE
|
||||
case 'nextage':
|
||||
return DATAVersion.NEXTAGE
|
||||
case 'exchain':
|
||||
return DATAVersion.EXCHAIN
|
||||
case 'matixx':
|
||||
default:
|
||||
return DATAVersion.MATTIX
|
||||
}
|
||||
}
|
||||
|
||||
export async function processDataBuilder(gameVer: string, processHandler?: processRawDataHandler) {
|
||||
const ver = gameVerToDataVer(gameVer)
|
||||
const base = `data/mdb/${ver}`
|
||||
if (IO.Exists(`${base}.b64`)) {
|
||||
return await readB64JSON(`${base}.b64`);
|
||||
}
|
||||
const { music } = await readJSONOrXML(`${base}.json`, `${base}.xml`, processHandler ?? defaultProcessRawData)
|
||||
// await IO.WriteFile(`${base}.b64`, Buffer.from(JSON.stringify({music})).toString("base64"))
|
||||
return { music };
|
||||
}
|
||||
|
||||
|
||||
export async function defaultProcessRawData(path: string): Promise<CommonMusicData> {
|
||||
const data = await readXML(path)
|
||||
const mdb = $(data).elements("mdb.mdb_data");
|
||||
const music: any[] = [];
|
||||
for (const m of mdb) {
|
||||
const d = m.numbers("xg_diff_list");
|
||||
const contain = m.numbers("contain_stat");
|
||||
const gf = contain[0];
|
||||
const dm = contain[1];
|
||||
|
||||
if (gf == 0 && dm == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let type = gf;
|
||||
if (gf == 0) {
|
||||
type = dm;
|
||||
}
|
||||
|
||||
music.push({
|
||||
id: K.ITEM('s32', m.number("music_id")),
|
||||
cont_gf: K.ITEM('bool', gf == 0 ? 0 : 1),
|
||||
cont_dm: K.ITEM('bool', dm == 0 ? 0 : 1),
|
||||
is_secret: K.ITEM('bool', 0),
|
||||
is_hot: K.ITEM('bool', type == 2 ? 0 : 1),
|
||||
data_ver: K.ITEM('s32', m.number("data_ver", 115)),
|
||||
diff: K.ARRAY('u16', [
|
||||
d[0],
|
||||
d[1],
|
||||
d[2],
|
||||
d[3],
|
||||
d[4],
|
||||
d[10],
|
||||
d[11],
|
||||
d[12],
|
||||
d[13],
|
||||
d[14],
|
||||
d[5],
|
||||
d[6],
|
||||
d[7],
|
||||
d[8],
|
||||
d[9],
|
||||
]),
|
||||
});
|
||||
}
|
||||
return {
|
||||
music,
|
||||
};
|
||||
}
|
||||
1
gitadora@asphyxia/data/mdb/mt.b64
Normal file
1
gitadora@asphyxia/data/mdb/mt.b64
Normal file
File diff suppressed because one or more lines are too long
1
gitadora@asphyxia/data/mdb/nt.b64
Normal file
1
gitadora@asphyxia/data/mdb/nt.b64
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,70 +1,25 @@
|
||||
import { getVersion } from "../utils";
|
||||
import { processData as ExchainMusic } from "../data/Exchain"
|
||||
import { processData as MatixxMusic } from "../data/Matixx"
|
||||
import { CommonMusicDataField, readJSONOrXML, readXML } from "../data/helper";
|
||||
import { defaultProcessRawData, processDataBuilder } from "../data/mdb"
|
||||
import { CommonMusicDataField, readJSONOrXML, readXML } from "../data/mdb";
|
||||
import Logger from "../utils/logger"
|
||||
|
||||
const logger = new Logger("MusicList")
|
||||
|
||||
export const playableMusic: EPR = async (info, data, send) => {
|
||||
const version = getVersion(info);
|
||||
let music: CommonMusicDataField[] = [];
|
||||
try {
|
||||
if (U.GetConfig("enable_custom_mdb")) {
|
||||
const data = await readXML('data/custom_mdb.xml')
|
||||
const mdb = $(data).elements("mdb.mdb_data");
|
||||
|
||||
for (const m of mdb) {
|
||||
const d = m.numbers("xg_diff_list");
|
||||
const contain = m.numbers("contain_stat");
|
||||
const gf = contain[0];
|
||||
const dm = contain[1];
|
||||
|
||||
if (gf == 0 && dm == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let type = gf;
|
||||
if (gf == 0) {
|
||||
type = dm;
|
||||
}
|
||||
|
||||
music.push({
|
||||
id: K.ITEM('s32', m.number("music_id")),
|
||||
cont_gf: K.ITEM('bool', gf == 0 ? 0 : 1),
|
||||
cont_dm: K.ITEM('bool', dm == 0 ? 0 : 1),
|
||||
is_secret: K.ITEM('bool', 0),
|
||||
is_hot: K.ITEM('bool', type == 2 ? 0 : 1),
|
||||
data_ver: K.ITEM('s32', m.number("data_ver", 115)),
|
||||
diff: K.ARRAY('u16', [
|
||||
d[0],
|
||||
d[1],
|
||||
d[2],
|
||||
d[3],
|
||||
d[4],
|
||||
d[10],
|
||||
d[11],
|
||||
d[12],
|
||||
d[13],
|
||||
d[14],
|
||||
d[5],
|
||||
d[6],
|
||||
d[7],
|
||||
d[8],
|
||||
d[9],
|
||||
]),
|
||||
});
|
||||
}
|
||||
music = (await defaultProcessRawData('data/mdb/custom.xml')).music
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e.stack);
|
||||
console.error("Fallback: Using default MDB method.")
|
||||
logger.warn("Read Custom MDB failed. Using default MDB as a fallback.")
|
||||
logger.debugWarn(e.stack);
|
||||
music = [];
|
||||
}
|
||||
|
||||
if (music.length == 0) {
|
||||
if (version == 'exchain') {
|
||||
music = _.get(await ExchainMusic(), 'music', []);
|
||||
} else {
|
||||
music = _.get(await MatixxMusic(), 'music', []);
|
||||
}
|
||||
music = _.get(await processDataBuilder(version), 'music', []);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { getEncoreStageData } from "../data/extrastage";
|
||||
|
||||
export const shopInfoRegist: EPR = async (info, data, send) => {
|
||||
send.object({
|
||||
data: {
|
||||
@@ -19,6 +21,7 @@ export const gameInfoGet: EPR = async (info, data, send) => {
|
||||
bonus_musicid: K.ITEM('s32', 0),
|
||||
},
|
||||
bear_fes: {},
|
||||
nextadium: {},
|
||||
};
|
||||
const time = BigInt(31536000);
|
||||
for (let i = 1; i <= 20; ++i) {
|
||||
@@ -42,6 +45,18 @@ export const gameInfoGet: EPR = async (info, data, send) => {
|
||||
term: K.ITEM('u8', 0),
|
||||
sticker_list: {},
|
||||
};
|
||||
addition['thanksgiving'] = {
|
||||
...obj,
|
||||
box_term: {
|
||||
state: K.ITEM('u8', 0)
|
||||
}
|
||||
};
|
||||
addition['lotterybox'] = {
|
||||
...obj,
|
||||
box_term: {
|
||||
state: K.ITEM('u8', 0)
|
||||
}
|
||||
};
|
||||
} else {
|
||||
addition[`phrase_combo_challenge_${i}`] = obj;
|
||||
}
|
||||
@@ -59,16 +74,20 @@ export const gameInfoGet: EPR = async (info, data, send) => {
|
||||
}
|
||||
}
|
||||
|
||||
const extraData = getEncoreStageData(info)
|
||||
|
||||
await send.object({
|
||||
now_date: K.ITEM('u64', time),
|
||||
now_date: K.ITEM('u64', BigInt(Date.now())),
|
||||
extra: {
|
||||
extra_lv: K.ITEM('u8', 10),
|
||||
extra_lv: K.ITEM('u8', extraData.level),
|
||||
extramusic: {
|
||||
music: {
|
||||
musicid: K.ITEM('s32', 0),
|
||||
get_border: K.ITEM('u8', 0),
|
||||
},
|
||||
},
|
||||
music: extraData.musics.map(mid => {
|
||||
return {
|
||||
musicid: K.ITEM('s32', mid),
|
||||
get_border: K.ITEM('u8', 0),
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
infect_music: { term: K.ITEM('u8', 0) },
|
||||
unlock_challenge: { term: K.ITEM('u8', 0) },
|
||||
|
||||
@@ -45,6 +45,7 @@ export const check: EPR = async (info, data, send) => {
|
||||
|
||||
const playerInfo = await DB.FindOne<PlayerInfo>(refid, {
|
||||
collection: 'playerinfo',
|
||||
version
|
||||
})
|
||||
|
||||
if (playerInfo) {
|
||||
@@ -90,6 +91,7 @@ export const getPlayer: EPR = async (info, data, send) => {
|
||||
|
||||
const name = await DB.FindOne<PlayerInfo>(refid, {
|
||||
collection: 'playerinfo',
|
||||
version
|
||||
})
|
||||
const dmProfile = await getProfile(refid, version, 'dm')
|
||||
const gfProfile = await getProfile(refid, version, 'gf')
|
||||
@@ -388,12 +390,12 @@ export const getPlayer: EPR = async (info, data, send) => {
|
||||
send.object({
|
||||
player: K.ATTR({ 'no': `${no}` }, {
|
||||
now_date: K.ITEM('u64', time),
|
||||
secretmusic: {
|
||||
secretmusic: { // TODO: FIX THIS
|
||||
music: {
|
||||
musicid: K.ITEM('s32', 0),
|
||||
seq: K.ITEM('u16', 255),
|
||||
kind: K.ITEM('s32', 40),
|
||||
},
|
||||
}
|
||||
},
|
||||
chara_list: {},
|
||||
title_parts: {},
|
||||
@@ -512,6 +514,20 @@ export const getPlayer: EPR = async (info, data, send) => {
|
||||
unlock_status_6: K.ITEM('s32', 0),
|
||||
unlock_status_7: K.ITEM('s32', 0),
|
||||
},
|
||||
thanksgiving: {
|
||||
term: K.ITEM("u8", 0),
|
||||
score: {
|
||||
one_day_play_cnt: K.ITEM("s32", 0),
|
||||
one_day_lottery_cnt: K.ITEM("s32", 0),
|
||||
lucky_star: K.ITEM("s32", 0),
|
||||
bear_mark: K.ITEM("s32", 0),
|
||||
play_date_ms: K.ITEM("u64", BigInt(0))
|
||||
},
|
||||
lottery_result: {
|
||||
unlock_bit: K.ITEM("u64", BigInt(0))
|
||||
}
|
||||
},
|
||||
lotterybox: {},
|
||||
...addition,
|
||||
...playerData,
|
||||
finish: K.ITEM('bool', 1),
|
||||
@@ -910,7 +926,7 @@ export const savePlayer: EPR = async (info, data, send) => {
|
||||
scores[mid].update[1] = newSkill;
|
||||
}
|
||||
|
||||
scores[mid].diffs[seq] = {
|
||||
scores[mid].diffs[seq] = { //FIXME: Real server is bit complicated. this one is too buggy.
|
||||
perc: Math.max(_.get(scores[mid].diffs[seq], 'perc', 0), perc),
|
||||
rank: Math.max(_.get(scores[mid].diffs[seq], 'rank', 0), rank),
|
||||
meter: meter.toString(),
|
||||
|
||||
@@ -2,23 +2,42 @@ import { gameInfoGet, shopInfoRegist } from "./handlers/info";
|
||||
import { playableMusic } from "./handlers/MusicList"
|
||||
import { getPlayer, check, regist, savePlayer } from "./handlers/profiles";
|
||||
import { updatePlayerInfo } from "./handlers/webui";
|
||||
import { isRequiredVersion } from "./utils";
|
||||
import { isAsphyxiaDebugMode, isRequiredCoreVersion } from "./utils";
|
||||
import Logger from "./utils/logger";
|
||||
|
||||
const logger = new Logger("main")
|
||||
|
||||
export function register() {
|
||||
if(!isRequiredVersion(1, 20)) {
|
||||
if(!isRequiredCoreVersion(1, 20)) {
|
||||
console.error("You need newer version of Core. v1.20 or newer required.")
|
||||
}
|
||||
|
||||
R.GameCode('M32');
|
||||
|
||||
R.Config("encore_version", {
|
||||
name: "Encore Version",
|
||||
desc: "Set encore version",
|
||||
type: "integer",
|
||||
default: 13,
|
||||
})
|
||||
|
||||
R.Config("nextage_dummy_encore", {
|
||||
name: "Dummy Encore for SPE (Nextage Only)",
|
||||
desc: "Since Nextage's Special Premium Encore system is bit complicated, \n"
|
||||
+ "SPE System isn't fully implemented. \n"
|
||||
+ "This thing is bandage of these problem as limiting some Encores for SPE.",
|
||||
type: "boolean",
|
||||
default: false
|
||||
})
|
||||
|
||||
R.Config("enable_custom_mdb", {
|
||||
name: "Enable Custom MDB",
|
||||
desc: "For who uses own MDB",
|
||||
desc: "For who uses own MDB. eg) Omnimix.",
|
||||
type: "boolean",
|
||||
default: false,
|
||||
})
|
||||
|
||||
R.DataFile("data/custom_mdb.xml", {
|
||||
R.DataFile("data/mdb/custom.xml", {
|
||||
accept: ".xml",
|
||||
name: "Custom MDB",
|
||||
desc: "You need to enable Custom MDB option first."
|
||||
@@ -30,7 +49,7 @@ export function register() {
|
||||
// Helper for register multiple versions.
|
||||
R.Route(`exchain_${method}`, handler);
|
||||
R.Route(`matixx_${method}`, handler);
|
||||
// TODO: NEXTAGE
|
||||
R.Route(`nextage_${method}`, handler)
|
||||
// TODO: TB, TBRE and more older version?
|
||||
};
|
||||
|
||||
@@ -46,4 +65,13 @@ export function register() {
|
||||
MultiRoute('cardutil.check', check);
|
||||
MultiRoute('gametop.get', getPlayer);
|
||||
MultiRoute('gameend.regist', savePlayer);
|
||||
|
||||
// Misc
|
||||
R.Route('bemani_gakuen.get_music_info', true)
|
||||
|
||||
R.Unhandled(async (info, data, send) => {
|
||||
if (["eventlog"].includes(info.module)) return;
|
||||
logger.error(`Received Unhandled Request on Method "${info.method}" by ${info.model}/${info.module}`)
|
||||
logger.debugError(`Received Request: ${JSON.stringify(data, null, 4)}`)
|
||||
})
|
||||
}
|
||||
@@ -2,7 +2,7 @@ export interface Scores {
|
||||
collection: 'scores';
|
||||
|
||||
game: 'gf' | 'dm';
|
||||
version: string;
|
||||
version?: string;
|
||||
pluginVer: number
|
||||
|
||||
scores: {
|
||||
|
||||
@@ -11,9 +11,14 @@ export const getVersion = (info: EamuseInfo) => {
|
||||
return moduleName.match(/([^_]*)_(.*)/)[1];
|
||||
};
|
||||
|
||||
export function isRequiredVersion(major: number, minor: number) {
|
||||
export function isRequiredCoreVersion(major: number, minor: number) {
|
||||
// version value exposed since Core v1.19
|
||||
const core_major = typeof CORE_VERSION_MAJOR === "number" ? CORE_VERSION_MAJOR : 1
|
||||
const core_minor = typeof CORE_VERSION_MINOR === "number" ? CORE_VERSION_MINOR : 18
|
||||
return core_major >= major && core_minor >= minor
|
||||
return core_major > major || (core_major === major && core_minor >= minor)
|
||||
};
|
||||
|
||||
export function isAsphyxiaDebugMode() {
|
||||
const argv = process.argv
|
||||
return argv.includes("--dev") || argv.includes("--console")
|
||||
}
|
||||
62
gitadora@asphyxia/utils/logger.ts
Normal file
62
gitadora@asphyxia/utils/logger.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { isAsphyxiaDebugMode } from ".";
|
||||
|
||||
export default class Logger {
|
||||
public category: string | null;
|
||||
|
||||
public constructor(category?: string) {
|
||||
this.category = (category == null) ? null : `[${category}]`
|
||||
}
|
||||
|
||||
|
||||
public error(...args: any[]) {
|
||||
this.argsHandler(console.error, ...args)
|
||||
}
|
||||
|
||||
public debugError(...args: any[]) {
|
||||
if (isAsphyxiaDebugMode()) {
|
||||
this.argsHandler(console.error, ...args)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public warn(...args: any[]) {
|
||||
this.argsHandler(console.warn, ...args)
|
||||
}
|
||||
|
||||
public debugWarn(...args: any[]) {
|
||||
if (isAsphyxiaDebugMode()) {
|
||||
this.argsHandler(console.warn, ...args)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public info(...args: any[]) {
|
||||
this.argsHandler(console.info, ...args)
|
||||
}
|
||||
|
||||
public debugInfo(...args: any[]) {
|
||||
if (isAsphyxiaDebugMode()) {
|
||||
this.argsHandler(console.info, ...args)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public log(...args: any[]) {
|
||||
this.argsHandler(console.log, ...args)
|
||||
}
|
||||
|
||||
public debugLog(...args: any[]) {
|
||||
if (isAsphyxiaDebugMode()) {
|
||||
this.argsHandler(console.log, ...args)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private argsHandler(target: Function, ...args: any[]) {
|
||||
if (this.category == null) {
|
||||
target(...args)
|
||||
} else {
|
||||
target(this.category, ...args)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
# Jubeat
|
||||
|
||||
Plugin Version: **v1.0.0**
|
||||
Plugin Version: **v1.5.0**
|
||||
|
||||
### Supported Versions
|
||||
|
||||
@@ -8,11 +8,36 @@ Plugin Version: **v1.0.0**
|
||||
|
||||
- knit
|
||||
- knit APPEND
|
||||
- copious
|
||||
- copious APPEND
|
||||
- saucer
|
||||
- saucer fulfill
|
||||
|
||||
### Changelogs
|
||||
|
||||
***
|
||||
|
||||
#### 1.5.0
|
||||
|
||||
- saucer fulfill support
|
||||
|
||||
#### 1.4.1
|
||||
|
||||
- saucer support
|
||||
- Change profile structure
|
||||
|
||||
#### 1.3.0
|
||||
|
||||
- Matching Support (Experimental)
|
||||
|
||||
#### 1.2.0
|
||||
|
||||
- copious (APPEND) support
|
||||
|
||||
#### 1.1.0
|
||||
|
||||
- Fix profile structure
|
||||
|
||||
#### 1.0.0
|
||||
|
||||
- Initial Release
|
||||
|
||||
1624
jubeat@asphyxia/data/fulfill_courses.json
Normal file
1624
jubeat@asphyxia/data/fulfill_courses.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,31 +1,39 @@
|
||||
import {getVersion} from "../utils";
|
||||
import {getVersion, VersionRange} from "../utils";
|
||||
|
||||
export const shopinfo: EPR = (info, data, send) => {
|
||||
const locId = $(data.shop).content("locationid");
|
||||
export const gameInfo: EPR = (info, data, send) => {
|
||||
const locId = $(data).content("shop.locationid");
|
||||
const version = getVersion(info);
|
||||
if (version === 0) return send.deny();
|
||||
|
||||
if (version === 3) return send.object({
|
||||
return send.object({
|
||||
data: {
|
||||
cabid: K.ITEM('u32', 1),
|
||||
locationid: K.ITEM('str', locId),
|
||||
is_send: K.ITEM("u8", 1)
|
||||
}
|
||||
})
|
||||
...info.module === "shopinfo" && {
|
||||
cabid: K.ITEM("u32", _.random(1, 10)),
|
||||
locationid: K.ITEM("str", locId),
|
||||
...VersionRange(version, 3, 6) && { is_send: K.ITEM("u8", 1) },
|
||||
tax_phase: K.ITEM("u8", 0),
|
||||
facility: {
|
||||
exist: K.ITEM("u32", 1)
|
||||
}
|
||||
},
|
||||
|
||||
return send.deny();
|
||||
}
|
||||
...VersionRange(version, 5, 6) && {
|
||||
white_music_list: K.ARRAY("s32", Array(32).fill(-1))
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const demodata = {
|
||||
getNews: (_, __, send) => send.object({ data: { officialnews: K.ATTR({ count: "0" }) } }),
|
||||
getData: (_, data, send) => {
|
||||
const newsId = $(data).number('officialnews.newsid');
|
||||
const newsId = $(data).number("officialnews.newsid");
|
||||
return send.object({
|
||||
data: {
|
||||
officialnews: {
|
||||
data: {
|
||||
newsid: K.ITEM('s16', newsId),
|
||||
image: K.ITEM('u8', 0, { size: '0' })
|
||||
newsid: K.ITEM("s16", newsId),
|
||||
image: K.ITEM("u8", 0, { size: "0" })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,7 +42,7 @@ export const demodata = {
|
||||
getHitchart: (_, __, send) => send.object({
|
||||
data: {
|
||||
hitchart: {
|
||||
update: K.ITEM('str', ''),
|
||||
update: K.ITEM("str", ""),
|
||||
|
||||
hitchart_lic: K.ATTR({ count: "0" }),
|
||||
hitchart_org: K.ATTR({ count: "0" }),
|
||||
@@ -42,9 +50,3 @@ export const demodata = {
|
||||
}
|
||||
}),
|
||||
};
|
||||
|
||||
export const netlog: EPR = (info, data, send) => {
|
||||
const errMsg = $(data).str('msg');
|
||||
console.error(errMsg);
|
||||
return send.success();
|
||||
}
|
||||
|
||||
@@ -1,49 +1,147 @@
|
||||
export const check: EPR = (info, data, send) => {
|
||||
import {Room} from '../models/matching';
|
||||
|
||||
export const check: EPR = async (info, data, send) => {
|
||||
const enter = $(data).bool('data.enter');
|
||||
const time = $(data).number('data.time');
|
||||
|
||||
// enter
|
||||
// 0 - game is loading
|
||||
// 1 - music select screen
|
||||
|
||||
return send.object({
|
||||
data: {
|
||||
entrant_nr: K.ITEM('u32', 1, { time: String(time) }),
|
||||
interval: K.ITEM('s16', 1),
|
||||
entry_timeout: K.ITEM('s16', U.GetConfig("matching_entry_timeout")),
|
||||
waitlist: K.ATTR({ count: "0" })
|
||||
interval: K.ITEM('s16', 5),
|
||||
entry_timeout: K.ITEM('s16', 30),
|
||||
waitlist: K.ATTR({ count: '0' })
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const entry: EPR = (info, data, send) => {
|
||||
const localMatchingNode = $(data).element("data.local_matching");
|
||||
const connectNode = $(data).element("data.connect");
|
||||
export const entry: EPR = async (info, data, send) => {
|
||||
const localMatchingNode = $(data).element('data.local_matching');
|
||||
const connectNode = $(data).element('data.connect');
|
||||
const musicNode = $(data).element('data.music');
|
||||
|
||||
const roomId = _.random(1, 999999999999999);
|
||||
const localKey = localMatchingNode.numbers('key');
|
||||
const connectKey = connectNode.numbers('key');
|
||||
|
||||
// TODO Local matching support
|
||||
let matchRoom = await DB.FindOne<Room>({
|
||||
collection: 'matching_rooms',
|
||||
musicId: musicNode.number('id'),
|
||||
seqId: musicNode.number('seq'),
|
||||
isMatchEnd: false,
|
||||
isFull: false
|
||||
});
|
||||
|
||||
if (!matchRoom) {
|
||||
matchRoom = {
|
||||
collection: 'matching_rooms',
|
||||
|
||||
version: $(data).number('data.version'),
|
||||
roomId: _.random(1, 999999999),
|
||||
masterKey: connectKey,
|
||||
masterGlobal: connectNode.str('global'),
|
||||
masterPrivate: connectNode.str('private'),
|
||||
localKey,
|
||||
musicId: musicNode.number('id'),
|
||||
seqId: musicNode.number('seq'),
|
||||
members: [
|
||||
{
|
||||
cabid: $(data).number('data.cabid'),
|
||||
addr: connectNode.str('private')
|
||||
}
|
||||
],
|
||||
isFull: false,
|
||||
isMatchEnd: false
|
||||
};
|
||||
|
||||
await DB.Upsert<Room>({
|
||||
collection: 'matching_rooms', localKey,
|
||||
musicId: musicNode.number('id'),
|
||||
seqId: musicNode.number('seq'),
|
||||
isMatchEnd: false,
|
||||
isFull: false
|
||||
}, matchRoom);
|
||||
}
|
||||
|
||||
return send.object({
|
||||
data: {
|
||||
roomid: K.ITEM('s64', BigInt(roomId), { master: "1" }),
|
||||
refresh_intr: K.ITEM('s16', 3),
|
||||
roomid: K.ITEM('s64', BigInt(matchRoom.roomId), { master: matchRoom.masterKey === connectKey ? '1' : '0' }),
|
||||
...matchRoom.masterKey === connectKey && {
|
||||
refresh_intr: K.ITEM('s16', 10),
|
||||
},
|
||||
...matchRoom.masterKey !== connectKey && {
|
||||
connect: {
|
||||
key: K.ARRAY('u8', matchRoom.masterKey),
|
||||
global: K.ITEM('str', matchRoom.masterGlobal),
|
||||
private: K.ITEM('str', matchRoom.masterPrivate),
|
||||
}
|
||||
},
|
||||
music: {
|
||||
id: K.ITEM("u32", musicNode.number("id")),
|
||||
seq: K.ITEM("u8", musicNode.number("seq")),
|
||||
id: K.ITEM('u32', matchRoom.musicId),
|
||||
seq: K.ITEM('u8', matchRoom.seqId),
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const refresh: EPR = (info, data, send) => {
|
||||
export const refresh: EPR = async (info, data, send) => {
|
||||
const roomId = Number($(data).bigint('data.roomid'));
|
||||
const pcbinfos = $(data).elements('data.joined.pcbinfo');
|
||||
|
||||
const room = await DB.FindOne<Room>({ collection: 'matching_rooms', roomId });
|
||||
|
||||
if (room) {
|
||||
for (const i of pcbinfos) {
|
||||
const cabid = i.number('cabid');
|
||||
const addr = i.str('addr');
|
||||
|
||||
for (const i of room.members) {
|
||||
if (i.addr === addr) continue;
|
||||
|
||||
room.members.push({
|
||||
cabid,
|
||||
addr
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await DB.Update<Room>({ collection: 'matching_rooms', roomId: Number(roomId) }, {
|
||||
$set: {
|
||||
members: room.members
|
||||
}
|
||||
});
|
||||
|
||||
if (room.members.length >= 4) {
|
||||
await DB.Update<Room>({ collection: 'matching_rooms', roomId: Number(roomId) }, {
|
||||
$set: {
|
||||
isFull: true
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return send.object({
|
||||
data: {
|
||||
refresh_intr: K.ITEM('s16', 2),
|
||||
refresh_intr: K.ITEM('s16', 5),
|
||||
start: K.ITEM('bool', room.isFull)
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const report: EPR = (info, data, send) => {
|
||||
export const report: EPR = async (info, data, send) => {
|
||||
const roomId = $(data).bigint('data.roomid');
|
||||
|
||||
await DB.Update<Room>({ collection: 'matching_rooms', roomId: Number(roomId) }, {
|
||||
$set: {
|
||||
isMatchEnd: true
|
||||
}
|
||||
});
|
||||
|
||||
return send.object({
|
||||
data: {
|
||||
refresh_intr: K.ITEM('s16', 1),
|
||||
refresh_intr: K.ITEM('s16', 3),
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {getVersion} from "../utils";
|
||||
import Profile from '../models/profile';
|
||||
import {Score} from '../models/score';
|
||||
import {getVersion, getVersionName, VersionRange} from "../utils";
|
||||
import Profile from "../models/profile";
|
||||
import {Score} from "../models/score";
|
||||
import {CourseResult} from "../models/course";
|
||||
|
||||
export const profile: EPR = async (info, data, send) => {
|
||||
let refId = $(data).str("data.player.pass.refid");
|
||||
@@ -16,155 +17,298 @@ export const profile: EPR = async (info, data, send) => {
|
||||
if (!profile) {
|
||||
if (!name) return send.deny();
|
||||
|
||||
const newProfile = new Profile();
|
||||
newProfile.jubeatId = _.random(1, 99999999);
|
||||
newProfile.name = name;
|
||||
newProfile.previous_version = version;
|
||||
const newProfile: Profile = {
|
||||
collection: "profile",
|
||||
jubeatId: _.random(1, 99999999),
|
||||
name: name,
|
||||
|
||||
lastShopname: "NONE",
|
||||
lastAreaname: "NONE"
|
||||
};
|
||||
|
||||
await DB.Upsert<Profile>(refId, { collection: "profile" }, newProfile);
|
||||
|
||||
profile = newProfile;
|
||||
}
|
||||
|
||||
let migration = false;
|
||||
if (profile.previous_version < version) {
|
||||
migration = true;
|
||||
profile.name = "";
|
||||
await DB.Update<Profile>(refId, { collection: "profile" }, { $set: { name: "", previous_version: version } });
|
||||
}
|
||||
return send.object({
|
||||
data: {
|
||||
...version === 5 && require("../templates/gameInfos/saucer.ts")(profile),
|
||||
...version === 6 && require("../templates/gameInfos/fulfill.ts")(profile),
|
||||
|
||||
if (name) {
|
||||
profile.name = name;
|
||||
await DB.Update<Profile>(refId, { collection: "profile" }, { $set: { name } });
|
||||
}
|
||||
player: {
|
||||
name: K.ITEM("str", profile.name),
|
||||
jid: K.ITEM("s32", profile.jubeatId),
|
||||
refid: K.ITEM("str", profile.__refid),
|
||||
session_id: K.ITEM("s32", 1),
|
||||
event_flag: K.ITEM("u64", BigInt(0)),
|
||||
|
||||
if (version === 3) {
|
||||
if (U.GetConfig("unlock_all_songs")) {
|
||||
profile.knit.item = {
|
||||
secretList: [-1, -1],
|
||||
themeList: -1,
|
||||
markerList: [-1, -1],
|
||||
titleList: [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
||||
};
|
||||
profile.knit.item_new = {
|
||||
secretList: [0, 0],
|
||||
themeList: 0,
|
||||
markerList: [0, 0],
|
||||
titleList: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
};
|
||||
...version === 3 && require("../templates/profiles/knit.ts")(profile),
|
||||
...version === 4 && require("../templates/profiles/copious.ts")(profile),
|
||||
...version === 5 && require("../templates/profiles/saucer.ts")(profile),
|
||||
...version === 6 && require("../templates/profiles/fulfill.ts")(profile),
|
||||
}
|
||||
}
|
||||
return send.pugFile('templates/knit/profile.pug', { refId, migration, ...profile }, { compress: false });
|
||||
}
|
||||
|
||||
return send.deny();
|
||||
});
|
||||
};
|
||||
|
||||
export const saveProfile: EPR = async (info, { data }, send) => {
|
||||
console.log(U.toXML(data));
|
||||
const player = $(data).element("player");
|
||||
console.log(U.toXML({
|
||||
call: K.ATTR({ model: info.model }, {
|
||||
[info.module]: K.ATTR({ method: info.method }, { data })
|
||||
})
|
||||
}));
|
||||
|
||||
const refId = player.str("refid");
|
||||
const refId = $(data).str("player.refid");
|
||||
if (!refId) return send.deny();
|
||||
|
||||
const version = getVersion(info);
|
||||
if (version === 0) return send.deny();
|
||||
|
||||
const profile = await DB.FindOne<Profile>(refId, { collection: "profile" });
|
||||
if (!profile) return send.deny();
|
||||
|
||||
if (version === 3) {
|
||||
profile.name = player.str("name");
|
||||
let lastMarker = 0;
|
||||
let lastTheme = 0;
|
||||
let lastTitle = 0;
|
||||
let lastParts = 0;
|
||||
let lastSort = 0;
|
||||
let lastFilter = 0;
|
||||
let lastCategory = 0;
|
||||
let lastMselStat = 0;
|
||||
|
||||
profile.last.shopname = player.str("shopname", profile.last.shopname);
|
||||
profile.last.areaname = player.str("areaname", profile.last.areaname);
|
||||
const result = $(data).element("result");
|
||||
|
||||
profile.jubility = player.number("info.jubility", profile.jubility);
|
||||
profile.jubilityYday = player.number("info.jubility_yday", profile.jubilityYday);
|
||||
if (result) {
|
||||
const tunes = result.elements("tune");
|
||||
const historys = {};
|
||||
const historyNode = $(data).elements("player.history.tune");
|
||||
|
||||
profile.knit.acvProg = player.number("info.acv_prog", profile.knit.acvProg);
|
||||
profile.knit.acvWool = player.number("info.acv_wool", profile.knit.acvWool);
|
||||
profile.knit.acvRouteProg = player.numbers("info.acv_route_prog", profile.knit.acvRouteProg);
|
||||
profile.knit.acvPoint = player.number("info.acv_point", profile.knit.acvPoint);
|
||||
|
||||
profile.tuneCount = player.number("info.tune_cnt", profile.tuneCount);
|
||||
profile.saveCount = player.number("info.save_cnt", profile.saveCount);
|
||||
profile.savedCount = player.number("info.saved_cnt", profile.savedCount);
|
||||
profile.fullcomboCount = player.number("info.fc_cnt", profile.fullcomboCount);
|
||||
profile.fullcomboSeqCount = player.number("info.fc_seq_cnt", profile.fullcomboSeqCount);
|
||||
profile.excellentCount = player.number("info.exc_cnt", profile.excellentCount);
|
||||
profile.excellentSeqCount = player.number("info.exc_seq_cnt", profile.excellentSeqCount);
|
||||
profile.matchCount = player.number("info.match_cnt", profile.matchCount);
|
||||
profile.beatCount = player.number('info.beat_cnt', profile.beatCount);
|
||||
profile.conciergeSelectedCount = player.number('info.con_sel_cnt', profile.conciergeSelectedCount);
|
||||
profile.tagCount = player.number('info.tag_cnt', profile.tagCount);
|
||||
profile.mynewsCount = player.number('info.mynews_cnt', profile.mynewsCount);
|
||||
|
||||
if (!U.GetConfig("unlock_all_songs")) {
|
||||
profile.knit.item.secretList = player.numbers('item.secret_list', profile.knit.item.secretList);
|
||||
profile.knit.item.themeList = player.number('item.theme_list', profile.knit.item.themeList);
|
||||
profile.knit.item.markerList = player.numbers('item.marker_list', profile.knit.item.markerList);
|
||||
profile.knit.item.titleList = player.numbers('item.title_list', profile.knit.item.titleList);
|
||||
|
||||
profile.knit.item_new.secretList = player.numbers('item.secret_new', profile.knit.item_new.secretList);
|
||||
profile.knit.item_new.themeList = player.number('item.theme_new', profile.knit.item_new.themeList);
|
||||
profile.knit.item_new.markerList = player.numbers('item.marker_new', profile.knit.item_new.markerList);
|
||||
profile.knit.item_new.titleList = player.numbers('item.title_new', profile.knit.item_new.titleList);
|
||||
}
|
||||
|
||||
profile.last.conciergeSuggestId = player.number('info.con_suggest_id', profile.last.conciergeSuggestId);
|
||||
profile.last.playTime = BigInt(new Date().getMilliseconds());
|
||||
|
||||
// Append
|
||||
const collabo = player.element("collabo");
|
||||
if (collabo) {
|
||||
profile.knit.collabo.success = collabo.bool("success");
|
||||
profile.knit.collabo.completed = collabo.bool("completed");
|
||||
}
|
||||
|
||||
const result = $(data).element("result");
|
||||
|
||||
if (result) {
|
||||
const tunes = result.elements("tune");
|
||||
|
||||
for (const tune of tunes) {
|
||||
const musicId = tune.number("music", 0);
|
||||
profile.last.musicId = musicId;
|
||||
profile.last.seqId = parseInt(tune.attr("player.score").seq) || 0;
|
||||
profile.last.title = tune.number("title", profile.last.title);
|
||||
profile.last.theme = tune.number("theme", profile.last.theme);
|
||||
profile.last.marker = tune.number("marker", profile.last.marker);
|
||||
profile.last.sort = tune.number("sort", profile.last.sort);
|
||||
profile.last.filter = tune.number("filter", profile.last.filter);
|
||||
profile.last.showRank = tune.number("combo_disp", profile.last.showRank);
|
||||
profile.last.showCombo = tune.number("rank_sort", profile.last.showCombo);
|
||||
profile.last.mselStat = tune.number("msel_stat", profile.last.mselStat);
|
||||
|
||||
const score = tune.number('player.score');
|
||||
const seq = parseInt(tune.attr('player.score').seq);
|
||||
const clear = parseInt(tune.attr('player.score').clear);
|
||||
const combo = parseInt(tune.attr('player.score').combo);
|
||||
const bestScore = tune.number('player.best_score');
|
||||
const bestClear = tune.number('player.best_clear');
|
||||
const playCount = tune.number('player.play_cnt');
|
||||
const clearCount = tune.number('player.clear_cnt');
|
||||
const fullcomboCount = tune.number('player.fc_cnt');
|
||||
const excellentCount = tune.number('player.exc_cnt');
|
||||
const mbar = tune.numbers('player.mbar');
|
||||
|
||||
await updateScore(refId, musicId, seq, score, clear, mbar, {
|
||||
playCount,
|
||||
clearCount,
|
||||
fullcomboCount,
|
||||
excellentCount
|
||||
});
|
||||
if (historyNode) {
|
||||
for (const history of historyNode) {
|
||||
historys[history.attr().log_id] = {
|
||||
timestamp: history.bigint("timestamp"),
|
||||
isHard: history.bool("player.result.is_hard_mode")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
await DB.Update<Profile>(refId, { collection: "profile" }, profile);
|
||||
for (const tune of tunes) {
|
||||
const tuneId = tune.attr().id;
|
||||
|
||||
return send.object({ data: { player: { session_id: K.ITEM('s32', 1) } } });
|
||||
profile.musicId = tune.number("music");
|
||||
profile.seqId = parseInt(tune.attr("player.score").seq);
|
||||
lastMarker = tune.number("marker");
|
||||
lastTheme = tune.number("theme");
|
||||
lastTitle = tune.number("title");
|
||||
lastParts = tune.number("parts");
|
||||
lastSort = tune.number("sort");
|
||||
lastFilter = tune.number("filter");
|
||||
lastCategory = tune.number("category");
|
||||
lastMselStat = tune.number("msel_stat");
|
||||
profile.rankSort = tune.number("rank_sort");
|
||||
profile.comboDisp = tune.number("combo_disp");
|
||||
|
||||
await updateScore(refId, {
|
||||
musicId: tune.number("music"),
|
||||
seq: parseInt(tune.attr("player.score").seq),
|
||||
score: tune.number("player.score"),
|
||||
clear: parseInt(tune.attr("player.score").clear),
|
||||
isHard: historys[tuneId]?.isHard || false,
|
||||
bestScore: tune.number("player.best_score"),
|
||||
bestClear: tune.number("player.best_clear"),
|
||||
playCount: tune.number("player.play_cnt"),
|
||||
clearCount: tune.number("player.clear_cnt"),
|
||||
fullcomboCount: tune.number("player.fc_cnt"),
|
||||
excellentCount: tune.number("player.exc_cnt"),
|
||||
...tune.element("player.mbar") && { mbar: tune.numbers("player.mbar") }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return send.deny();
|
||||
profile.lastPlayTime = Number($(data).bigint("player.time_gameend"));
|
||||
profile.lastShopname = $(data).str("player.shopname");
|
||||
profile.lastAreaname = $(data).str("player.areaname");
|
||||
|
||||
if (version === 3) {
|
||||
if (!profile.knit) profile.knit = {};
|
||||
profile.knit.jubility = $(data).number("player.info.jubility");
|
||||
profile.knit.jubilityYday = $(data).number("player.info.jubility_yday");
|
||||
profile.knit.acvProg = $(data).number("player.info.acv_prog");
|
||||
profile.knit.acvPoint = $(data).number("player.info.acv_point");
|
||||
profile.knit.acvWool = $(data).number("player.info.acv_wool");
|
||||
profile.knit.acvRouteProg = $(data).numbers("player.info.acv_route_prog");
|
||||
profile.knit.tuneCount = $(data).number("player.info.tune_cnt");
|
||||
profile.knit.saveCount = $(data).number("player.info.save_cnt");
|
||||
profile.knit.savedCount = $(data).number("player.info.saved_cnt");
|
||||
profile.knit.fcCount = $(data).number("player.info.fc_cnt");
|
||||
profile.knit.fcSeqCount = $(data).number("player.info.fc_seq_cnt");
|
||||
profile.knit.exCount = $(data).number("player.info.exc_cnt");
|
||||
profile.knit.exSeqCount = $(data).number("player.info.exc_seq_cnt");
|
||||
profile.knit.matchCount = $(data).number("player.info.match_cnt");
|
||||
profile.knit.conSelCount = $(data).number("player.info.con_sel_cnt");
|
||||
|
||||
profile.knit.marker = lastMarker;
|
||||
profile.knit.theme = lastTheme;
|
||||
profile.knit.title = lastTitle;
|
||||
profile.knit.sort = lastSort;
|
||||
profile.knit.filter = lastFilter;
|
||||
profile.knit.mselStat = lastMselStat;
|
||||
profile.knit.conSuggestId = $(data).number("player.info.con_suggest_id");
|
||||
|
||||
profile.knit.secretList = $(data).numbers("player.item.secret_list");
|
||||
profile.knit.themeList = $(data).number("player.item.theme_list");
|
||||
profile.knit.markerList = $(data).numbers("player.item.marker_list");
|
||||
profile.knit.titleList = $(data).numbers("player.item.title_list");
|
||||
|
||||
profile.knit.secretListNew = $(data).numbers("player.item.secret_new");
|
||||
profile.knit.themeListNew = $(data).number("player.item.theme_new");
|
||||
profile.knit.markerListNew = $(data).numbers("player.item.marker_new");
|
||||
profile.knit.titleListNew = $(data).numbers("player.item.title_new");
|
||||
}
|
||||
|
||||
if (version === 4) {
|
||||
if (!profile.copious) profile.copious = {};
|
||||
profile.copious.jubility = $(data).number("player.info.jubility");
|
||||
profile.copious.jubilityYday = $(data).number("player.info.jubility_yday");
|
||||
profile.copious.acvState = $(data).number("player.info.acv_state");
|
||||
profile.copious.acvPoint = $(data).number("player.info.acv_point");
|
||||
profile.copious.acvOwn = $(data).number("player.info.acv_own");
|
||||
profile.copious.acvThrow = $(data).numbers("player.info.acv_throw");
|
||||
profile.copious.tuneCount = $(data).number("player.info.tune_cnt");
|
||||
profile.copious.saveCount = $(data).number("player.info.save_cnt");
|
||||
profile.copious.savedCount = $(data).number("player.info.saved_cnt");
|
||||
profile.copious.fcCount = $(data).number("player.info.fc_cnt");
|
||||
profile.copious.fcSeqCount = $(data).number("player.info.fc_seq_cnt");
|
||||
profile.copious.exCount = $(data).number("player.info.exc_cnt");
|
||||
profile.copious.exSeqCount = $(data).number("player.info.exc_seq_cnt");
|
||||
profile.copious.matchCount = $(data).number("player.info.match_cnt");
|
||||
profile.copious.totalBestScore = $(data).number("player.info.total_best_score");
|
||||
|
||||
profile.copious.marker = lastMarker;
|
||||
profile.copious.theme = lastTheme;
|
||||
profile.copious.title = lastTitle;
|
||||
profile.copious.parts = lastParts;
|
||||
profile.copious.sort = lastSort;
|
||||
profile.copious.category = lastCategory;
|
||||
profile.copious.mselStat = lastMselStat;
|
||||
|
||||
profile.copious.secretList = $(data).numbers("player.item.secret_list");
|
||||
profile.copious.themeList = $(data).number("player.item.theme_list");
|
||||
profile.copious.markerList = $(data).numbers("player.item.marker_list");
|
||||
profile.copious.titleList = $(data).numbers("player.item.title_list");
|
||||
profile.copious.partsList = $(data).numbers("player.item.parts_list");
|
||||
|
||||
profile.copious.secretListNew = $(data).numbers("player.item.secret_new");
|
||||
profile.copious.themeListNew = $(data).number("player.item.theme_new");
|
||||
profile.copious.markerListNew = $(data).numbers("player.item.marker_new");
|
||||
profile.copious.titleListNew = $(data).numbers("player.item.title_new");
|
||||
}
|
||||
|
||||
if (version === 5) {
|
||||
if (!profile.saucer) profile.saucer = {};
|
||||
profile.saucer.jubility = $(data).number("player.info.jubility");
|
||||
profile.saucer.jubilityYday = $(data).number("player.info.jubility_yday");
|
||||
profile.saucer.tuneCount = $(data).number("player.info.tune_cnt");
|
||||
profile.saucer.clearCount = $(data).number("player.info.clear_cnt");
|
||||
profile.saucer.saveCount = $(data).number("player.info.save_cnt");
|
||||
profile.saucer.savedCount = $(data).number("player.info.saved_cnt");
|
||||
profile.saucer.fcCount = $(data).number("player.info.fc_cnt");
|
||||
profile.saucer.exCount = $(data).number("player.info.exc_cnt");
|
||||
profile.saucer.matchCount = $(data).number("player.info.match_cnt");
|
||||
profile.saucer.totalBestScore = $(data).number("player.info.total_best_score");
|
||||
|
||||
profile.saucer.marker = lastMarker;
|
||||
profile.saucer.theme = lastTheme;
|
||||
profile.saucer.title = lastTitle;
|
||||
profile.saucer.parts = lastParts;
|
||||
profile.saucer.sort = lastSort;
|
||||
profile.saucer.category = lastCategory;
|
||||
|
||||
profile.saucer.secretList = $(data).numbers("player.item.secret_list");
|
||||
profile.saucer.themeList = $(data).number("player.item.theme_list");
|
||||
profile.saucer.markerList = $(data).numbers("player.item.marker_list");
|
||||
profile.saucer.titleList = $(data).numbers("player.item.title_list");
|
||||
profile.saucer.partsList = $(data).numbers("player.item.parts_list");
|
||||
|
||||
profile.saucer.secretListNew = $(data).numbers("player.item.secret_new");
|
||||
profile.saucer.themeListNew = $(data).number("player.item.theme_new");
|
||||
profile.saucer.markerListNew = $(data).numbers("player.item.marker_new");
|
||||
profile.saucer.titleListNew = $(data).numbers("player.item.title_new");
|
||||
|
||||
if (!profile.saucer.bistro) profile.saucer.bistro = {};
|
||||
profile.saucer.bistro.carry_over = $(data).number("player.bistro.carry_over");
|
||||
}
|
||||
|
||||
if (version === 6) {
|
||||
if (!profile.fulfill) profile.fulfill = {};
|
||||
profile.fulfill.jubility = $(data).number("player.info.jubility");
|
||||
profile.fulfill.jubilityYday = $(data).number("player.info.jubility_yday");
|
||||
profile.fulfill.tuneCount = $(data).number("player.info.tune_cnt");
|
||||
profile.fulfill.saveCount = $(data).number("player.info.save_cnt");
|
||||
profile.fulfill.savedCount = $(data).number("player.info.saved_cnt");
|
||||
profile.fulfill.fcCount = $(data).number("player.info.fc_cnt");
|
||||
profile.fulfill.exCount = $(data).number("player.info.exc_cnt");
|
||||
profile.fulfill.clearCount = $(data).number("player.info.clear_cnt");
|
||||
profile.fulfill.matchCount = $(data).number("player.info.match_cnt");
|
||||
profile.fulfill.expertOption = $(data).number("player.info.expert_option");
|
||||
profile.fulfill.matching = $(data).number("player.info.matching");
|
||||
profile.fulfill.hazard = $(data).number("player.info.hazard");
|
||||
profile.fulfill.hard = $(data).number("player.info.hard");
|
||||
profile.fulfill.extraPoint = $(data).number("player.info.extra_point");
|
||||
profile.fulfill.isExtraPlayed = $(data).bool("player.info.is_extra_played");
|
||||
profile.fulfill.totalBestScore = $(data).number("player.info.total_best_score");
|
||||
profile.fulfill.clearMaxLevel = $(data).number("player.info.clear_max_level");
|
||||
profile.fulfill.fcMaxLevel = $(data).number("player.info.fc_max_level");
|
||||
profile.fulfill.exMaxLevel = $(data).number("player.info.exc_max_level");
|
||||
|
||||
profile.fulfill.marker = lastMarker;
|
||||
profile.fulfill.theme = lastTheme;
|
||||
profile.fulfill.title = lastTitle;
|
||||
profile.fulfill.parts = lastParts;
|
||||
profile.fulfill.sort = lastSort;
|
||||
profile.fulfill.category = lastCategory;
|
||||
|
||||
profile.fulfill.secretList = $(data).numbers("player.item.secret_list");
|
||||
profile.fulfill.themeList = $(data).number("player.item.theme_list");
|
||||
profile.fulfill.markerList = $(data).numbers("player.item.marker_list");
|
||||
profile.fulfill.titleList = $(data).numbers("player.item.title_list");
|
||||
profile.fulfill.partsList = $(data).numbers("player.item.parts_list");
|
||||
profile.fulfill.secretListNew = $(data).numbers("player.item.secret_new");
|
||||
profile.fulfill.themeListNew = $(data).number("player.item.theme_new");
|
||||
profile.fulfill.markerListNew = $(data).numbers("player.item.marker_new");
|
||||
profile.fulfill.titleListNew = $(data).numbers("player.item.title_new");
|
||||
|
||||
const courseNode = $(data).element("course");
|
||||
if (courseNode) {
|
||||
profile.fulfill.lastCourseId = courseNode.number("course_id");
|
||||
|
||||
await DB.Upsert<CourseResult>(refId, {
|
||||
collection: "course_results",
|
||||
courseId: courseNode.number("course_id"),
|
||||
version: 6
|
||||
}, {
|
||||
$set: {
|
||||
rating: courseNode.number("rating"),
|
||||
scores: courseNode.elements("music").map(m => m.number("score"))
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await DB.Update<Profile>(refId, { collection: "profile" }, profile);
|
||||
|
||||
return send.object({
|
||||
data: {
|
||||
player: { session_id: K.ITEM("s32", 1) },
|
||||
...version === 4 && { collabo: { deller: K.ITEM("s32", 0) } }
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Profile save failed: ${e.message}`);
|
||||
return send.deny();
|
||||
}
|
||||
};
|
||||
|
||||
export const loadScore: EPR = async (info, data, send) => {
|
||||
@@ -178,7 +322,7 @@ export const loadScore: EPR = async (info, data, send) => {
|
||||
if (version === 0) return send.deny();
|
||||
|
||||
const scores = await DB.Find<Score>(profile.__refid, { collection: "score" });
|
||||
const scoreData: { [musicId: number]: any } = {};
|
||||
const scoreData: { [musicId: number]: { score: number[], clear: number[], playCnt: number[], clearCnt: number[], fcCnt: number[], exCnt: number[], bar: number[][] } } = {};
|
||||
|
||||
for (const score of scores) {
|
||||
if (!scoreData[score.musicId]) {
|
||||
@@ -198,95 +342,175 @@ export const loadScore: EPR = async (info, data, send) => {
|
||||
data.clearCnt[score.seq] = score.clearCount;
|
||||
data.fcCnt[score.seq] = score.fullcomboCount;
|
||||
data.exCnt[score.seq] = score.excellentCount;
|
||||
data.clear[score.seq] = score.clearType;
|
||||
data.clear[score.seq] = score.clear;
|
||||
data.score[score.seq] = score.score;
|
||||
data.bar[score.seq] = score.bar;
|
||||
}
|
||||
|
||||
if (version === 3) return send.object({
|
||||
return send.object({
|
||||
data: {
|
||||
player: {
|
||||
playdata: K.ATTR({ count: String(Object.keys(scoreData).length) }, {
|
||||
musicdata: (() => {
|
||||
const musicdata = [];
|
||||
Object.entries(scoreData).forEach(([k, v]) => {
|
||||
musicdata.push(K.ATTR({ music_id: String(k) }, {
|
||||
play_cnt: K.ARRAY('s32', v.playCnt),
|
||||
clear_cnt: K.ARRAY('s32', v.clearCnt),
|
||||
fc_cnt: K.ARRAY('s32', v.fcCnt),
|
||||
ex_cnt: K.ARRAY('s32', v.exCnt),
|
||||
clear: K.ARRAY('s8', v.clear),
|
||||
score: K.ARRAY('s32', v.score),
|
||||
bar: v.bar.map((v, i) => K.ARRAY('u8', v, { seq: String(i) }))
|
||||
}));
|
||||
});
|
||||
return musicdata;
|
||||
})()
|
||||
})
|
||||
jid: K.ITEM("s32", jubeatId),
|
||||
|
||||
...version >= 3 && {
|
||||
playdata: K.ATTR({ count: String(Object.keys(scoreData).length) }, {
|
||||
musicdata: Object.keys(scoreData).map(musicId => K.ATTR({ music_id: String(musicId) }, {
|
||||
score: K.ARRAY("s32", scoreData[musicId].score),
|
||||
clear: K.ARRAY("s8", scoreData[musicId].clear),
|
||||
play_cnt: K.ARRAY("s32", scoreData[musicId].playCnt),
|
||||
clear_cnt: K.ARRAY("s32", scoreData[musicId].clearCnt),
|
||||
fc_cnt: K.ARRAY("s32", scoreData[musicId].fcCnt),
|
||||
ex_cnt: K.ARRAY("s32", scoreData[musicId].exCnt),
|
||||
bar: scoreData[musicId].bar.map((bar, seq) => K.ARRAY("u8", bar, { seq: String(seq) }))
|
||||
}))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return send.deny();
|
||||
};
|
||||
|
||||
const updateScore = async (refId: string, musicId: number, seq: number, score: number, clear: number, mbar: number[], data: any) => {
|
||||
let raised;
|
||||
const updateScore = async (refId: string, data: any): Promise<boolean> => {
|
||||
try {
|
||||
await DB.Upsert<Score>(refId, {
|
||||
collection: "score",
|
||||
musicId: data.musicId,
|
||||
seq: data.seq,
|
||||
isHardMode: data.isHard
|
||||
}, {
|
||||
$set: {
|
||||
musicId: data.musicId,
|
||||
seq: data.seq,
|
||||
score: data.bestScore,
|
||||
clear: data.bestClear,
|
||||
musicRate: 0,
|
||||
...data.mbar && { bar: data.mbar, },
|
||||
playCount: data.playCount,
|
||||
clearCount: data.clearCount,
|
||||
fullcomboCount: data.fullcomboCount,
|
||||
excellentCount: data.excellentCount,
|
||||
isHardMode: data.isHard
|
||||
}
|
||||
});
|
||||
|
||||
const oldScore = await DB.FindOne<Score>(refId, { collection: "score", musicId, seq });
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error("Score saving failed: ", e.stack);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
let scoreData = oldScore;
|
||||
export const getCourse: EPR = async (info, data, send) => {
|
||||
const version = getVersion(info);
|
||||
if (version === 0) return send.deny();
|
||||
|
||||
if (!oldScore) {
|
||||
scoreData = new Score();
|
||||
scoreData.musicId = musicId;
|
||||
scoreData.seq = seq;
|
||||
raised = true;
|
||||
} else {
|
||||
raised = score > oldScore.score;
|
||||
score = Math.max(oldScore.score, score);
|
||||
const jubeatId = $(data).number("data.player.jid");
|
||||
if (!jubeatId) return send.deny();
|
||||
|
||||
const profile = await DB.FindOne<Profile>(null, { collection: "profile", jubeatId });
|
||||
if (!profile) return send.deny();
|
||||
|
||||
if (version === 6) {
|
||||
const results = await DB.Find<CourseResult>(profile.__refid, { collection: "course_results", version: 6 });
|
||||
|
||||
const { courses } = require("../data/fulfill_courses.json");
|
||||
|
||||
const validCourseIds: number[] = courses.map(course => course.course_id);
|
||||
|
||||
return send.object({
|
||||
data: {
|
||||
course_list: {
|
||||
course: courses.map(course => ({
|
||||
id: K.ITEM("s32", course.course_id),
|
||||
name: K.ITEM("str", course.course_name),
|
||||
level: K.ITEM("u8", course.course_level),
|
||||
|
||||
norma: {
|
||||
norma_id: K.ARRAY("s32", course.norma.norma_id),
|
||||
bronze_value: K.ARRAY("s32", course.norma.bronze),
|
||||
silver_value: K.ARRAY("s32", course.norma.silver),
|
||||
gold_value: K.ARRAY("s32", course.norma.gold)
|
||||
},
|
||||
|
||||
music_list: {
|
||||
music: course.music_list.map(music => (K.ATTR({ index: music.index }, {
|
||||
music_id: K.ITEM("s32", music.music_id),
|
||||
seq: K.ITEM("u8", music.seq_id)
|
||||
})))
|
||||
}
|
||||
}))
|
||||
},
|
||||
|
||||
player_list: {
|
||||
player: {
|
||||
jid: K.ITEM("s32", jubeatId),
|
||||
|
||||
result_list: {
|
||||
result: results.filter(e => validCourseIds.find(valid => valid === e.courseId)).map(result => ({
|
||||
id: K.ITEM("s32", result.courseId),
|
||||
rating: K.ITEM("u8", result.rating),
|
||||
score: K.ARRAY("s32", result.scores)
|
||||
}))
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
last_course_id: K.ITEM("s32", profile.fulfill?.lastCourseId || 0)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
scoreData.clearType = Math.max(scoreData.clearType, clear);
|
||||
scoreData.playCount = data.playCount;
|
||||
scoreData.clearCount = data.clearCount;
|
||||
scoreData.fullcomboCount = data.fullcomboCount;
|
||||
scoreData.excellentCount = data.excellentCount;
|
||||
scoreData.isHardmodeClear = false;
|
||||
|
||||
if (mbar && raised) {
|
||||
scoreData.score = score;
|
||||
scoreData.bar = mbar;
|
||||
}
|
||||
|
||||
await DB.Upsert(refId, { collection: "score", musicId, seq }, scoreData);
|
||||
return send.deny();
|
||||
};
|
||||
|
||||
export const meeting: EPR = (info, data, send) => {
|
||||
return send.object({
|
||||
data: {
|
||||
meeting: {
|
||||
single: K.ATTR({ count: '0' }),
|
||||
tag: K.ATTR({ count: '0' }),
|
||||
single: K.ATTR({ count: "0" }),
|
||||
tag: K.ATTR({ count: "0" }),
|
||||
},
|
||||
reward: {
|
||||
total: K.ITEM('s32', 0),
|
||||
point: K.ITEM('s32', 0)
|
||||
total: K.ITEM("s32", 0),
|
||||
point: K.ITEM("s32", 0)
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const getCollabo: EPR = (info, data, send) => send.object({
|
||||
data: {
|
||||
collabo: {
|
||||
played: {
|
||||
iidx: K.ITEM("s8", 1),
|
||||
popn: K.ITEM("s8", 1),
|
||||
ddr: K.ITEM("s8", 1),
|
||||
reflec: K.ITEM("s8", 1),
|
||||
gfdm: K.ITEM("s8", 1),
|
||||
export const getCollabo: EPR = (info, data, send) => {
|
||||
const version = getVersion(info);
|
||||
if (version === 0) return send.deny();
|
||||
|
||||
if (version === 3) {
|
||||
return send.object({
|
||||
data: {
|
||||
collabo: {
|
||||
played: {
|
||||
iidx: K.ITEM("s8", 1),
|
||||
popn: K.ITEM("s8", 1),
|
||||
ddr: K.ITEM("s8", 1),
|
||||
reflec: K.ITEM("s8", 1),
|
||||
gfdm: K.ITEM("s8", 1),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (version === 4) {
|
||||
return send.object({
|
||||
data: {
|
||||
player: {
|
||||
collabo: {
|
||||
reward: K.ITEM("s32", 0),
|
||||
dellar: K.ITEM("s32", 0),
|
||||
music_id: K.ITEM("s32", 0),
|
||||
wonder_state: K.ITEM("u32", 2),
|
||||
yellow_state: K.ITEM("u32", 2),
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {demodata, netlog, shopinfo} from "./handlers/common";
|
||||
import {demodata, gameInfo} from "./handlers/common";
|
||||
import {check, entry, refresh, report} from "./handlers/matching";
|
||||
import {getCollabo, loadScore, meeting, profile, saveProfile} from "./handlers/profile";
|
||||
import {getCollabo, getCourse, loadScore, meeting, profile, saveProfile} from "./handlers/profile";
|
||||
|
||||
export function register() {
|
||||
if (CORE_VERSION_MAJOR <= 1 && CORE_VERSION_MINOR < 31) {
|
||||
@@ -8,41 +8,22 @@ export function register() {
|
||||
return;
|
||||
}
|
||||
R.GameCode("J44");
|
||||
|
||||
R.Config("unlock_all_songs", {
|
||||
name: "Unlock All Songs",
|
||||
desc: "Tired of unlocking songs? Have this!",
|
||||
type: "boolean",
|
||||
default: false
|
||||
});
|
||||
|
||||
R.Config("quick_matching_end", {
|
||||
name: "Quick Matching End",
|
||||
desc: "Supported from clan to festo.",
|
||||
type: "boolean",
|
||||
default: false
|
||||
});
|
||||
|
||||
R.Config("matching_entry_timeout", {
|
||||
name: "Online Matching Timeout",
|
||||
desc: "If online matching songs are too boring, save time! (second)",
|
||||
type: "integer",
|
||||
default: 30,
|
||||
range: [15, 99],
|
||||
});
|
||||
R.GameCode("K44");
|
||||
R.GameCode("L44");
|
||||
|
||||
R.Route("gametop.regist", profile);
|
||||
R.Route("gametop.get_info", gameInfo);
|
||||
R.Route("gametop.get_pdata", profile);
|
||||
R.Route("gametop.get_mdata", loadScore);
|
||||
R.Route("gametop.get_course", getCourse);
|
||||
R.Route("gametop.get_meeting", meeting);
|
||||
R.Route("gametop.get_collabo", getCollabo);
|
||||
|
||||
R.Route('gameend.regist', saveProfile);
|
||||
R.Route('gameend.log', true);
|
||||
R.Route('gameend.set_collabo', true);
|
||||
R.Route("gameend.regist", saveProfile);
|
||||
R.Route("gameend.log", true);
|
||||
R.Route("gameend.set_collabo", true);
|
||||
|
||||
R.Route("shopinfo.regist", shopinfo);
|
||||
R.Route("netlog.send", netlog);
|
||||
R.Route("shopinfo.regist", gameInfo);
|
||||
R.Route("demodata.get_news", demodata.getNews);
|
||||
R.Route("demodata.get_data", demodata.getData);
|
||||
R.Route("demodata.get_hitchart", demodata.getHitchart);
|
||||
@@ -51,10 +32,6 @@ export function register() {
|
||||
R.Route("lobby.refresh", refresh);
|
||||
R.Route("lobby.report", report);
|
||||
|
||||
R.Unhandled((info, data, send) => {
|
||||
console.log(info.module, info.method);
|
||||
console.log(U.toXML(data));
|
||||
|
||||
return send.deny();
|
||||
});
|
||||
R.Route("netlog.send", true);
|
||||
R.Route("logger.report", true);
|
||||
}
|
||||
|
||||
9
jubeat@asphyxia/models/course.ts
Normal file
9
jubeat@asphyxia/models/course.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export interface CourseResult {
|
||||
collection: "course_results";
|
||||
|
||||
version: number;
|
||||
|
||||
courseId: number;
|
||||
rating: number;
|
||||
scores: number[];
|
||||
}
|
||||
18
jubeat@asphyxia/models/matching.ts
Normal file
18
jubeat@asphyxia/models/matching.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export interface Room {
|
||||
collection: 'matching_rooms';
|
||||
|
||||
version: number;
|
||||
roomId: number;
|
||||
masterKey: number[];
|
||||
masterGlobal: string;
|
||||
masterPrivate: string;
|
||||
localKey: number[];
|
||||
musicId: number;
|
||||
seqId: number;
|
||||
members: {
|
||||
cabid: number;
|
||||
addr: string;
|
||||
}[];
|
||||
isFull: boolean;
|
||||
isMatchEnd: boolean;
|
||||
}
|
||||
@@ -1,101 +1,167 @@
|
||||
export default class Profile {
|
||||
collection: "profile" = "profile";
|
||||
export default interface Profile {
|
||||
collection: "profile";
|
||||
|
||||
jubeatId: number = _.random(1, 99999999);
|
||||
name: string = "JUBEAT";
|
||||
jubeatId: number;
|
||||
name: string;
|
||||
|
||||
previous_version = 0;
|
||||
lastPlayTime?: number;
|
||||
lastShopname: string;
|
||||
lastAreaname: string;
|
||||
|
||||
jubility: number = 0;
|
||||
jubilityYday: number = 0;
|
||||
tuneCount: number = 0;
|
||||
saveCount: number = 0;
|
||||
savedCount: number = 0;
|
||||
fullcomboCount: number = 0;
|
||||
fullcomboSeqCount: number = 0;
|
||||
excellentCount: number = 0;
|
||||
excellentSeqCount: number = 0;
|
||||
matchCount: number = 0;
|
||||
beatCount: number = 0;
|
||||
tagCount: number = 0;
|
||||
mynewsCount: number = 0;
|
||||
conciergeSelectedCount: number = 0;
|
||||
musicId?: number;
|
||||
seqId?: number;
|
||||
rankSort?: number;
|
||||
comboDisp?: number;
|
||||
|
||||
last: {
|
||||
shopname: string;
|
||||
areaname: string;
|
||||
playTime: bigint;
|
||||
title: number;
|
||||
theme: number;
|
||||
marker: number;
|
||||
showRank: number;
|
||||
showCombo: number;
|
||||
musicId: number;
|
||||
seqId: number;
|
||||
seqEditId: string;
|
||||
sort: number;
|
||||
filter: number;
|
||||
mselStat: number;
|
||||
conciergeSuggestId: number;
|
||||
} = {
|
||||
shopname: "NONE",
|
||||
areaname: "NONE",
|
||||
playTime: BigInt(0),
|
||||
title: 0,
|
||||
theme: 0,
|
||||
marker: 0,
|
||||
showRank: 1,
|
||||
showCombo: 1,
|
||||
musicId: 0,
|
||||
seqId: 0,
|
||||
seqEditId: "",
|
||||
sort: 0,
|
||||
filter: 0,
|
||||
mselStat: 0,
|
||||
conciergeSuggestId: 0
|
||||
knit?: {
|
||||
jubility?: number;
|
||||
jubilityYday?: number;
|
||||
acvProg?: number;
|
||||
acvWool?: number;
|
||||
acvRouteProg?: number[];
|
||||
acvPoint?: number;
|
||||
tuneCount?: number;
|
||||
saveCount?: number;
|
||||
savedCount?: number;
|
||||
fcCount?: number;
|
||||
fcSeqCount?: number;
|
||||
exCount?: number;
|
||||
exSeqCount?: number;
|
||||
matchCount?: number;
|
||||
conSelCount?: number;
|
||||
|
||||
marker?: number;
|
||||
theme?: number;
|
||||
title?: number;
|
||||
sort?: number;
|
||||
filter?: number;
|
||||
mselStat?: number;
|
||||
conSuggestId?: number;
|
||||
|
||||
secretList?: number[];
|
||||
themeList?: number;
|
||||
markerList?: number[];
|
||||
titleList?: number[];
|
||||
|
||||
secretListNew?: number[];
|
||||
themeListNew?: number;
|
||||
markerListNew?: number[];
|
||||
titleListNew?: number[];
|
||||
};
|
||||
|
||||
knit: {
|
||||
acvProg: number;
|
||||
acvWool: number;
|
||||
acvRouteProg: number[];
|
||||
acvPoint: number;
|
||||
item: {
|
||||
secretList: number[],
|
||||
themeList: number,
|
||||
markerList: number[],
|
||||
titleList: number[]
|
||||
},
|
||||
item_new: {
|
||||
secretList: number[],
|
||||
themeList: number,
|
||||
markerList: number[],
|
||||
titleList: number[]
|
||||
},
|
||||
collabo: {
|
||||
success: boolean;
|
||||
completed: boolean;
|
||||
}
|
||||
} = {
|
||||
acvProg: 0,
|
||||
acvWool: 0,
|
||||
acvRouteProg: [0, 0, 0, 0],
|
||||
acvPoint: 0,
|
||||
item: {
|
||||
secretList: [0, 0],
|
||||
themeList: 0,
|
||||
markerList: [0, 0],
|
||||
titleList: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
},
|
||||
item_new: {
|
||||
secretList: [0, 0],
|
||||
themeList: 0,
|
||||
markerList: [0, 0],
|
||||
titleList: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
},
|
||||
collabo: {
|
||||
success: false,
|
||||
completed: false
|
||||
copious?: {
|
||||
jubility?: number;
|
||||
jubilityYday?: number;
|
||||
acvPoint?: number;
|
||||
acvState?: number;
|
||||
acvThrow?: number[];
|
||||
acvOwn?: number;
|
||||
tuneCount?: number;
|
||||
saveCount?: number;
|
||||
savedCount?: number;
|
||||
fcCount?: number;
|
||||
fcSeqCount?: number;
|
||||
exCount?: number;
|
||||
exSeqCount?: number;
|
||||
matchCount?: number;
|
||||
totalBestScore?: number;
|
||||
|
||||
marker?: number;
|
||||
theme?: number;
|
||||
title?: number;
|
||||
parts?: number;
|
||||
sort?: number;
|
||||
category?: number;
|
||||
mselStat?: number;
|
||||
|
||||
secretList?: number[];
|
||||
themeList?: number;
|
||||
markerList?: number[];
|
||||
titleList?: number[];
|
||||
partsList?: number[];
|
||||
|
||||
secretListNew?: number[];
|
||||
themeListNew?: number;
|
||||
markerListNew?: number[];
|
||||
titleListNew?: number[];
|
||||
};
|
||||
|
||||
saucer?: {
|
||||
jubility?: number;
|
||||
jubilityYday?: number;
|
||||
tuneCount?: number;
|
||||
clearCount?: number;
|
||||
saveCount?: number;
|
||||
savedCount?: number;
|
||||
fcCount?: number;
|
||||
exCount?: number;
|
||||
matchCount?: number;
|
||||
totalBestScore?: number;
|
||||
|
||||
marker?: number;
|
||||
theme?: number;
|
||||
title?: number;
|
||||
parts?: number;
|
||||
sort?: number;
|
||||
category?: number;
|
||||
|
||||
secretList?: number[];
|
||||
themeList?: number;
|
||||
markerList?: number[];
|
||||
titleList?: number[];
|
||||
partsList?: number[];
|
||||
|
||||
secretListNew?: number[];
|
||||
themeListNew?: number;
|
||||
markerListNew?: number[];
|
||||
titleListNew?: number[];
|
||||
|
||||
bistro?: {
|
||||
carry_over?: number;
|
||||
}
|
||||
};
|
||||
|
||||
fulfill?: {
|
||||
jubility?: number;
|
||||
jubilityYday?: number;
|
||||
tuneCount?: number;
|
||||
clearCount?: number;
|
||||
saveCount?: number;
|
||||
savedCount?: number;
|
||||
fcCount?: number;
|
||||
exCount?: number;
|
||||
matchCount?: number;
|
||||
extraPoint?: number;
|
||||
isExtraPlayed?: boolean;
|
||||
totalBestScore?: number;
|
||||
clearMaxLevel?: number;
|
||||
fcMaxLevel?: number;
|
||||
exMaxLevel?: number;
|
||||
|
||||
marker?: number;
|
||||
theme?: number;
|
||||
title?: number;
|
||||
parts?: number;
|
||||
sort?: number;
|
||||
category?: number;
|
||||
expertOption?: number;
|
||||
matching?: number;
|
||||
hazard?: number;
|
||||
hard?: number;
|
||||
|
||||
secretList?: number[];
|
||||
themeList?: number;
|
||||
markerList?: number[];
|
||||
titleList?: number[];
|
||||
partsList?: number[];
|
||||
|
||||
secretListNew?: number[];
|
||||
themeListNew?: number;
|
||||
markerListNew?: number[];
|
||||
titleListNew?: number[];
|
||||
|
||||
lastCourseId?: number;
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
export class Score {
|
||||
collection: "score" = "score";
|
||||
export interface Score {
|
||||
collection: "score";
|
||||
|
||||
musicId: number;
|
||||
seq: number;
|
||||
score: number = 0;
|
||||
clearType: number = 0;
|
||||
playCount: number = 0;
|
||||
clearCount: number = 0;
|
||||
fullcomboCount: number = 0;
|
||||
excellentCount: number = 0;
|
||||
isHardmodeClear: boolean;
|
||||
score: number;
|
||||
clear: number;
|
||||
musicRate: number;
|
||||
bar: number[];
|
||||
playCount: number;
|
||||
clearCount: number;
|
||||
fullcomboCount: number;
|
||||
excellentCount: number;
|
||||
isHardMode: boolean;
|
||||
}
|
||||
|
||||
28
jubeat@asphyxia/templates/gameInfos/fulfill.ts
Normal file
28
jubeat@asphyxia/templates/gameInfos/fulfill.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
module.exports = () => ({
|
||||
termver: K.ITEM("u8", 0),
|
||||
season_etime: K.ITEM("u32", 0),
|
||||
white_music_list: K.ARRAY("s32", Array(32).fill(-1)),
|
||||
open_music_list: K.ARRAY("s32", Array(32).fill(0)),
|
||||
|
||||
collabo_info: {
|
||||
collabo: [
|
||||
K.ATTR({ type: "1" }, { state: K.ITEM("u8", 0) }),
|
||||
K.ATTR({ type: "2" }, { state: K.ITEM("u8", 0) }),
|
||||
K.ATTR({ type: "3" }, { state: K.ITEM("u8", 0) }),
|
||||
K.ATTR({ type: "4" }, { state: K.ITEM("u8", 0) }),
|
||||
K.ATTR({ type: "5" }, { state: K.ITEM("u8", 0) }),
|
||||
K.ATTR({ type: "8" }, { state: K.ITEM("u8", 0) })
|
||||
],
|
||||
|
||||
policy_break: {
|
||||
is_report_end: K.ITEM("bool", true)
|
||||
}
|
||||
},
|
||||
|
||||
lab: {
|
||||
is_open: K.ITEM("bool", false)
|
||||
},
|
||||
|
||||
share_music: K.ATTR({ count: "0" }),
|
||||
bonus_music: K.ATTR({ count: "0" })
|
||||
});
|
||||
27
jubeat@asphyxia/templates/gameInfos/saucer.ts
Normal file
27
jubeat@asphyxia/templates/gameInfos/saucer.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
module.exports = () => ({
|
||||
termver: K.ITEM("u8", 0),
|
||||
season_etime: K.ITEM("u32", 0),
|
||||
bistro_last_music_id: K.ITEM("s32", 0),
|
||||
white_music_list: K.ARRAY("s32", Array(32).fill(-1)),
|
||||
old_music_list: K.ARRAY("s32", Array(32).fill(0)),
|
||||
open_music_list: K.ARRAY("s32", Array(32).fill(0)),
|
||||
|
||||
collabo_info: {
|
||||
collabo: [
|
||||
K.ATTR({ type: "1" }, { state: K.ITEM("u8", 0) }),
|
||||
K.ATTR({ type: "2" }, { state: K.ITEM("u8", 0) }),
|
||||
K.ATTR({ type: "3" }, { state: K.ITEM("u8", 0) }),
|
||||
K.ATTR({ type: "4" }, { state: K.ITEM("u8", 0) }),
|
||||
K.ATTR({ type: "5" }, { state: K.ITEM("u8", 0) }),
|
||||
K.ATTR({ type: "8" }, { state: K.ITEM("u8", 0) })
|
||||
],
|
||||
|
||||
run_run_marathon: {
|
||||
is_report_end: K.ITEM("bool", true)
|
||||
},
|
||||
|
||||
policy_break: {
|
||||
is_report_end: K.ITEM("bool", true)
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,89 +0,0 @@
|
||||
gametop
|
||||
data
|
||||
player
|
||||
name(__type="str") #{name}
|
||||
jid(__type="s32") #{jubeatId}
|
||||
refid(__type="str") #{refId}
|
||||
session_id(__type="s32") 1
|
||||
|
||||
info
|
||||
inherit(__type="bool") #{migration ? 1 : 0}
|
||||
jubility(__type="s16") #{jubility}
|
||||
jubility_yday(__type="s16") #{jubilityYday}
|
||||
acv_prog(__type="s8") #{knit.acvProg}
|
||||
acv_wool(__type="s8") #{knit.acvWool}
|
||||
acv_route_prog(__type="s8" __count="4") #{knit.acvRouteProg.join(" ")}
|
||||
acv_point(__type="s32") #{knit.acvPoint}
|
||||
tune_cnt(__type="s32") #{tuneCount}
|
||||
save_cnt(__type="s32") #{saveCount}
|
||||
saved_cnt(__type="s32") #{savedCount}
|
||||
fc_cnt(__type="s32") #{fullcomboCount}
|
||||
ex_cnt(__type="s32") #{excellentCount}
|
||||
match_cnt(__type="s32") #{matchCount}
|
||||
beat_cnt(__type="s32") #{beatCount}
|
||||
mynews_cnt(__type="s32") #{mynewsCount}
|
||||
con_sel_cnt(__type="s32") #{conciergeSelectedCount}
|
||||
tag_cnt(__type="s32") #{tagCount}
|
||||
mtg_entry_cnt(__type="s32") 0
|
||||
tag_entry_cnt(__type="s32") 0
|
||||
mtg_hold_cnt(__type="s32") 0
|
||||
tag_hold_cnt(__type="s32") 0
|
||||
mtg_result(__type="u8") 0
|
||||
|
||||
last
|
||||
play_time(__type="s64") #{last.playTime || 0}
|
||||
shopname(__type="str") #{last.shopname}
|
||||
areaname(__type="str") #{last.areaname}
|
||||
title(__type="s16") #{last.title}
|
||||
theme(__type="s8") #{last.theme}
|
||||
marker(__type="s8") #{last.marker}
|
||||
rank_sort(__type="s8") #{last.showRank}
|
||||
combo_disp(__type="s8") #{last.showCombo}
|
||||
music_id(__type="s32") #{last.musicId}
|
||||
seq_id(__type="s8") #{last.seqId}
|
||||
sort(__type="s8") #{last.sort}
|
||||
filter(__type="s32") #{last.filter}
|
||||
msel_stat(__type="s8") #{last.mselStat}
|
||||
con_suggest_id(__type="s8") #{last.conciergeSuggestId}
|
||||
|
||||
item
|
||||
secret_list(__type="s32" __count="2") #{knit.item.secretList.join(" ")}
|
||||
theme_list(__type="s16") #{knit.item.themeList}
|
||||
marker_list(__type="s32" __count="2") #{knit.item.markerList.join(" ")}
|
||||
title_list(__type="s32" __count="24") #{knit.item.titleList.join(" ")}
|
||||
|
||||
new
|
||||
secret_list(__type="s32" __count="2") #{knit.item_new.secretList.join(" ")}
|
||||
theme_list(__type="s16") #{knit.item_new.themeList}
|
||||
marker_list(__type="s32" __count="2") #{knit.item_new.markerList.join(" ")}
|
||||
title_list(__type="s32" __count="24") #{knit.item_new.titleList.join(" ")}
|
||||
|
||||
today_music
|
||||
music_id(__type="s32") 0
|
||||
|
||||
news
|
||||
checked(__type="s16") 0
|
||||
|
||||
friendlist(count="0")
|
||||
|
||||
lucky_music
|
||||
music_id(__type="s32") 0
|
||||
|
||||
mylist(count="0")
|
||||
|
||||
group
|
||||
group_id(__type="s32") 0
|
||||
|
||||
bingo
|
||||
reward
|
||||
total(__type="s32") 0
|
||||
point(__type="s32") 0
|
||||
|
||||
collabo
|
||||
success(__type="bool") #{knit.collabo.success ? 1 : 0}
|
||||
completed(__type="bool") #{knit.collabo.completed ? 1 : 0}
|
||||
|
||||
history
|
||||
play_hist(count="0")
|
||||
|
||||
match_hist(count="0")
|
||||
71
jubeat@asphyxia/templates/profiles/copious.ts
Normal file
71
jubeat@asphyxia/templates/profiles/copious.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import Profile from "../../models/profile";
|
||||
|
||||
module.exports = (data: Profile) => ({
|
||||
info: {
|
||||
jubility: K.ITEM("s16", data.copious?.jubility || 0),
|
||||
jubility_yday: K.ITEM("s16", data.copious?.jubilityYday || 0),
|
||||
acv_point: K.ITEM("s32", data.copious?.acvPoint || 0),
|
||||
acv_state: K.ITEM("s8", data.copious?.acvState || 0),
|
||||
acv_throw: K.ARRAY("s32", data.copious?.acvThrow || [0, 0, 0]),
|
||||
acv_own: K.ITEM("s32", data.copious?.acvOwn || 0),
|
||||
tune_cnt: K.ITEM("s32", data.copious?.tuneCount || 0),
|
||||
save_cnt: K.ITEM("s32", data.copious?.saveCount || 0),
|
||||
saved_cnt: K.ITEM("s32", data.copious?.savedCount || 0),
|
||||
fc_cnt: K.ITEM("s32", data.copious?.fcCount || 0),
|
||||
ex_cnt: K.ITEM("s32", data.copious?.exCount || 0),
|
||||
match_cnt: K.ITEM("s32", data.copious?.matchCount || 0),
|
||||
beat_cnt: K.ITEM("s32", 0),
|
||||
mynews_cnt: K.ITEM("s32", 0),
|
||||
mtg_entry_cnt: K.ITEM("s32", 0),
|
||||
mtg_hold_cnt: K.ITEM("s32", 0),
|
||||
mtg_result: K.ITEM("u8", 0)
|
||||
},
|
||||
|
||||
last: {
|
||||
play_time: K.ITEM("s64", BigInt(0)),
|
||||
shopname: K.ITEM("str", data.lastShopname),
|
||||
areaname: K.ITEM("str", data.lastAreaname),
|
||||
title: K.ITEM("s16", data.copious?.title || 0),
|
||||
parts: K.ITEM("s16", data.copious?.parts || 0),
|
||||
theme: K.ITEM("s8", data.copious?.theme || 0),
|
||||
marker: K.ITEM("s8", data.copious?.marker || 0),
|
||||
rank_sort: K.ITEM("s8", data.rankSort || 1),
|
||||
combo_disp: K.ITEM("s8", data.comboDisp || 1),
|
||||
music_id: K.ITEM("s32", data.musicId || 0),
|
||||
seq_id: K.ITEM("s8", data.seqId || 0),
|
||||
sort: K.ITEM("s8", data.copious?.sort || 0),
|
||||
category: K.ITEM("s8", data.copious?.category || 0),
|
||||
msel_stat: K.ITEM("s8", data.copious?.mselStat || 0)
|
||||
},
|
||||
|
||||
item: {
|
||||
secret_list: K.ARRAY("s32", data.copious?.secretList || Array(12).fill(0)),
|
||||
theme_list: K.ITEM("s16", data.copious?.themeList || 0),
|
||||
marker_list: K.ARRAY("s32", data.copious?.markerList || [0, 0]),
|
||||
title_list: K.ARRAY("s32", data.copious?.titleList || Array(32).fill(0)),
|
||||
parts_list: K.ARRAY("s32", data.copious?.partsList || Array(96).fill(0)),
|
||||
|
||||
new: {
|
||||
secret_list: K.ARRAY("s32", data.copious?.secretListNew || Array(12).fill(0)),
|
||||
theme_list: K.ITEM("s16", data.copious?.themeListNew || 0),
|
||||
marker_list: K.ARRAY("s32", data.copious?.markerListNew || [0, 0]),
|
||||
title_list: K.ARRAY("s32", data.copious?.titleListNew || Array(32).fill(0))
|
||||
}
|
||||
},
|
||||
|
||||
challenge: {
|
||||
today: {
|
||||
music_id: K.ITEM("s32", 0)
|
||||
},
|
||||
onlynow: {
|
||||
magic_no: K.ITEM("s32", 0),
|
||||
cycle: K.ITEM("s16", 0)
|
||||
}
|
||||
},
|
||||
|
||||
news: {
|
||||
checked: K.ITEM("s16", 0)
|
||||
},
|
||||
|
||||
rivallist: K.ATTR({ count: "0" })
|
||||
});
|
||||
117
jubeat@asphyxia/templates/profiles/fulfill.ts
Normal file
117
jubeat@asphyxia/templates/profiles/fulfill.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import Profile from "../../models/profile";
|
||||
|
||||
module.exports = (data: Profile) => ({
|
||||
info: {
|
||||
jubility: K.ITEM("s16", data.fulfill?.jubility || 0),
|
||||
jubility_yday: K.ITEM("s16", data.fulfill?.jubilityYday || 0),
|
||||
tune_cnt: K.ITEM("s32", data.fulfill?.tuneCount || 31),
|
||||
save_cnt: K.ITEM("s32", data.fulfill?.saveCount || 0),
|
||||
saved_cnt: K.ITEM("s32", data.fulfill?.savedCount || 0),
|
||||
fc_cnt: K.ITEM("s32", data.fulfill?.fcCount || 0),
|
||||
ex_cnt: K.ITEM("s32", data.fulfill?.exCount || 0),
|
||||
clear_cnt: K.ITEM("s32", data.fulfill?.clearCount || 0),
|
||||
pf_cnt: K.ITEM("s32", 0),
|
||||
match_cnt: K.ITEM("s32", data.fulfill?.matchCount || 0),
|
||||
beat_cnt: K.ITEM("s32", 0),
|
||||
mynews_cnt: K.ITEM("s32", 0),
|
||||
mtg_entry_cnt: K.ITEM("s32", 0),
|
||||
mtg_hold_cnt: K.ITEM("s32", 0),
|
||||
mtg_result: K.ITEM("u8", 0),
|
||||
extra_point: K.ITEM("s32", data.fulfill?.extraPoint || 0),
|
||||
is_extra_played: K.ITEM("bool", data.fulfill?.isExtraPlayed || false)
|
||||
},
|
||||
|
||||
last: {
|
||||
play_time: K.ITEM("s64", BigInt(0)),
|
||||
shopname: K.ITEM("str", data.lastShopname),
|
||||
areaname: K.ITEM("str", data.lastAreaname),
|
||||
title: K.ITEM("s16", data.fulfill?.title || 0),
|
||||
parts: K.ITEM("s16", data.fulfill?.parts || 0),
|
||||
theme: K.ITEM("s8", data.fulfill?.theme || 0),
|
||||
marker: K.ITEM("s8", data.fulfill?.marker || 0),
|
||||
rank_sort: K.ITEM("s8", data.rankSort || 1),
|
||||
combo_disp: K.ITEM("s8", data.comboDisp || 1),
|
||||
music_id: K.ITEM("s32", data.musicId || 0),
|
||||
seq_id: K.ITEM("s8", data.seqId || 0),
|
||||
sort: K.ITEM("s8", data.fulfill?.sort || 0),
|
||||
category: K.ITEM("s8", data.fulfill?.category || 0),
|
||||
expert_option: K.ITEM("s8", data.fulfill?.category || 0),
|
||||
matching: K.ITEM("s8", data.fulfill?.category || 1),
|
||||
hazard: K.ITEM("s8", data.fulfill?.category || 0),
|
||||
hard: K.ITEM("s8", data.fulfill?.category || 0)
|
||||
},
|
||||
|
||||
item: {
|
||||
secret_list: K.ARRAY("s32", Array(32).fill(-1)),
|
||||
theme_list: K.ITEM("s16", -1),
|
||||
marker_list: K.ARRAY("s32", Array(2).fill(-1)),
|
||||
title_list: K.ARRAY("s32", Array(96).fill(-1)),
|
||||
parts_list: K.ARRAY("s32", Array(96).fill(-1)),
|
||||
|
||||
new: {
|
||||
secret_list: K.ARRAY("s32", Array(32).fill(0)),
|
||||
theme_list: K.ITEM("s16", 0),
|
||||
marker_list: K.ARRAY("s32", Array(2).fill(0)),
|
||||
title_list: K.ARRAY("s32", Array(96).fill(0))
|
||||
}
|
||||
},
|
||||
|
||||
history: K.ATTR({ count: "0" }),
|
||||
|
||||
challenge: {
|
||||
today: {
|
||||
music_id: K.ITEM("s32", 0),
|
||||
state: K.ITEM("u8", 0)
|
||||
}
|
||||
},
|
||||
|
||||
news: {
|
||||
checked: K.ITEM("s16", 0)
|
||||
},
|
||||
|
||||
macchiato: {
|
||||
pack_id: K.ITEM("s32", 0),
|
||||
bean_num: K.ITEM("u16", 0),
|
||||
daily_milk_num: K.ITEM("s32", 1200),
|
||||
is_received_daily_milk: K.ITEM("bool", true),
|
||||
today_tune_cnt: K.ITEM("s32", 0),
|
||||
daily_milk_bonus: K.ARRAY("s32", [100, 100, 1000, 200, 200, 200, 200, 200, 1000]),
|
||||
daily_play_burst: K.ITEM("s32", 300),
|
||||
|
||||
sub_menu_is_completed: K.ITEM("bool", true),
|
||||
compensation_milk: K.ITEM("s32", 0),
|
||||
|
||||
macchiato_music_list: K.ATTR({ count: "0" }, {
|
||||
music: []
|
||||
}),
|
||||
|
||||
sub_pack_id: K.ITEM("s32", 0),
|
||||
|
||||
sub_macchiato_music_list: K.ATTR({ count: "0" }, {
|
||||
music: []
|
||||
}),
|
||||
|
||||
season_music_list: K.ATTR({ count: "0" }),
|
||||
|
||||
match_cnt: K.ITEM("s32", 0),
|
||||
|
||||
achievement_list: K.ATTR({ count: "0" }, {
|
||||
achievement: []
|
||||
}),
|
||||
|
||||
cow_list: K.ATTR({ count: "0" }),
|
||||
},
|
||||
|
||||
rivallist: K.ATTR({ count: "0" }),
|
||||
|
||||
only_now_music: K.ATTR({ count: "0" }),
|
||||
lab_edit_seq: K.ATTR({ count: "0" }),
|
||||
kac_music: K.ATTR({ count: "0" }),
|
||||
|
||||
memorial: {
|
||||
latest_event_id: K.ITEM("u8", 1),
|
||||
player_event_id: K.ITEM("u8", 1),
|
||||
flag: K.ITEM("u32", 0),
|
||||
params: K.ARRAY("u32", Array(15).fill(0))
|
||||
}
|
||||
});
|
||||
75
jubeat@asphyxia/templates/profiles/knit.ts
Normal file
75
jubeat@asphyxia/templates/profiles/knit.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import Profile from "../../models/profile";
|
||||
|
||||
module.exports = (data: Profile) => ({
|
||||
info: {
|
||||
jubility: K.ITEM("s16", data.knit?.jubility || 0),
|
||||
jubility_yday: K.ITEM("s16", data.knit?.jubilityYday || 0),
|
||||
acv_prog: K.ITEM("s8", data.knit?.acvProg || 0),
|
||||
acv_wool: K.ITEM("s8", data.knit?.acvWool || 0),
|
||||
acv_route_prog: K.ARRAY("s8", data.knit?.acvRouteProg || [0, 0, 0, 0]),
|
||||
acv_point: K.ITEM("s32", data.knit?.acvPoint || 0),
|
||||
tune_cnt: K.ITEM("s32", data.knit?.tuneCount || 0),
|
||||
save_cnt: K.ITEM("s32", data.knit?.saveCount || 0),
|
||||
saved_cnt: K.ITEM("s32", data.knit?.savedCount || 0),
|
||||
fc_cnt: K.ITEM("s32", data.knit?.fcCount || 0),
|
||||
ex_cnt: K.ITEM("s32", data.knit?.exCount || 0),
|
||||
match_cnt: K.ITEM("s32", data.knit?.matchCount || 0),
|
||||
beat_cnt: K.ITEM("s32", 0),
|
||||
mynews_cnt: K.ITEM("s32", 0),
|
||||
con_sel_cnt: K.ITEM("s32", data.knit?.conSelCount || 0),
|
||||
tag_cnt: K.ITEM("s32", 0),
|
||||
mtg_entry_cnt: K.ITEM("s32", 0),
|
||||
tag_entry_cnt: K.ITEM("s32", 0),
|
||||
mtg_hold_cnt: K.ITEM("s32", 0),
|
||||
tag_hold_cnt: K.ITEM("s32", 0),
|
||||
mtg_result: K.ITEM("u8", 0)
|
||||
},
|
||||
|
||||
last: {
|
||||
play_time: K.ITEM("s64", BigInt(0)),
|
||||
shopname: K.ITEM("str", data.lastShopname),
|
||||
areaname: K.ITEM("str", data.lastAreaname),
|
||||
title: K.ITEM("s16", data.knit?.title || 0),
|
||||
theme: K.ITEM("s8", data.knit?.theme || 0),
|
||||
marker: K.ITEM("s8", data.knit?.marker || 0),
|
||||
rank_sort: K.ITEM("s8", data.rankSort || 1),
|
||||
combo_disp: K.ITEM("s8", data.comboDisp || 1),
|
||||
music_id: K.ITEM("s32", data.musicId || 0),
|
||||
seq_id: K.ITEM("s8", data.seqId || 0),
|
||||
sort: K.ITEM("s8", data.knit?.sort || 0),
|
||||
filter: K.ITEM("s32", data.knit?.filter || 0),
|
||||
msel_stat: K.ITEM("s8", data.knit?.mselStat || 0),
|
||||
con_suggest_id: K.ITEM("s8", data.knit?.conSuggestId || 0)
|
||||
},
|
||||
|
||||
item: {
|
||||
secret_list: K.ARRAY("s32", data.knit?.secretList || [0, 0]),
|
||||
theme_list: K.ITEM("s16", data.knit?.themeList || 0),
|
||||
marker_list: K.ARRAY("s32", data.knit?.markerList || [0, 0]),
|
||||
title_list: K.ARRAY("s32", data.knit?.titleList || Array(24).fill(0)),
|
||||
|
||||
new: {
|
||||
secret_list: K.ARRAY("s32", data.knit?.secretListNew || [0, 0]),
|
||||
theme_list: K.ITEM("s16", data.knit?.themeListNew || 0),
|
||||
marker_list: K.ARRAY("s32", data.knit?.markerListNew || [0, 0]),
|
||||
title_list: K.ARRAY("s32", data.knit?.titleListNew || Array(24).fill(0))
|
||||
}
|
||||
},
|
||||
|
||||
today_music: {
|
||||
music_id: K.ITEM("s32", 0)
|
||||
},
|
||||
|
||||
news: {
|
||||
checked: K.ITEM("s16", 0)
|
||||
},
|
||||
|
||||
friendlist: K.ATTR({ count: "0" }),
|
||||
|
||||
mylist: K.ATTR({ count: "0" }),
|
||||
|
||||
collabo: {
|
||||
success: K.ITEM("bool", true),
|
||||
completed: K.ITEM("bool", true)
|
||||
}
|
||||
});
|
||||
101
jubeat@asphyxia/templates/profiles/saucer.ts
Normal file
101
jubeat@asphyxia/templates/profiles/saucer.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import Profile from "../../models/profile";
|
||||
|
||||
module.exports = (data: Profile) => ({
|
||||
info: {
|
||||
jubility: K.ITEM("s16", data.saucer?.jubility || 0),
|
||||
jubility_yday: K.ITEM("s16", data.saucer?.jubilityYday || 0),
|
||||
tune_cnt: K.ITEM("s32", data.saucer?.tuneCount || 0),
|
||||
save_cnt: K.ITEM("s32", data.saucer?.saveCount || 0),
|
||||
saved_cnt: K.ITEM("s32", data.saucer?.savedCount || 0),
|
||||
fc_cnt: K.ITEM("s32", data.saucer?.fcCount || 0),
|
||||
ex_cnt: K.ITEM("s32", data.saucer?.exCount || 0),
|
||||
clear_cnt: K.ITEM("s32", data.saucer?.clearCount || 0),
|
||||
pf_cnt: K.ITEM("s32", 0),
|
||||
match_cnt: K.ITEM("s32", data.saucer?.matchCount || 0),
|
||||
beat_cnt: K.ITEM("s32", 0),
|
||||
mynews_cnt: K.ITEM("s32", 0),
|
||||
mtg_entry_cnt: K.ITEM("s32", 0),
|
||||
mtg_hold_cnt: K.ITEM("s32", 0),
|
||||
mtg_result: K.ITEM("u8", 0)
|
||||
},
|
||||
|
||||
last: {
|
||||
play_time: K.ITEM("s64", BigInt(0)),
|
||||
shopname: K.ITEM("str", data.lastShopname),
|
||||
areaname: K.ITEM("str", data.lastAreaname),
|
||||
title: K.ITEM("s16", data.saucer?.title || 0),
|
||||
parts: K.ITEM("s16", data.saucer?.parts || 0),
|
||||
theme: K.ITEM("s8", data.saucer?.theme || 0),
|
||||
marker: K.ITEM("s8", data.saucer?.marker || 0),
|
||||
rank_sort: K.ITEM("s8", data.rankSort || 1),
|
||||
combo_disp: K.ITEM("s8", data.comboDisp || 1),
|
||||
music_id: K.ITEM("s32", data.musicId || 0),
|
||||
seq_id: K.ITEM("s8", data.seqId || 0),
|
||||
sort: K.ITEM("s8", data.saucer?.sort || 0),
|
||||
category: K.ITEM("s8", data.saucer?.category || 0)
|
||||
},
|
||||
|
||||
item: {
|
||||
secret_list: K.ARRAY("s32", Array(32).fill(-1)),
|
||||
theme_list: K.ITEM("s16", -1),
|
||||
marker_list: K.ARRAY("s32", Array(2).fill(-1)),
|
||||
title_list: K.ARRAY("s32", Array(96).fill(-1)),
|
||||
parts_list: K.ARRAY("s32", Array(96).fill(-1)),
|
||||
|
||||
new: {
|
||||
secret_list: K.ARRAY("s32", Array(32).fill(0)),
|
||||
theme_list: K.ITEM("s16", 0),
|
||||
marker_list: K.ARRAY("s32", Array(2).fill(0)),
|
||||
title_list: K.ARRAY("s32", Array(96).fill(0))
|
||||
}
|
||||
},
|
||||
|
||||
history: K.ATTR({ count: "0" }),
|
||||
|
||||
challenge: {
|
||||
today: {
|
||||
music_id: K.ITEM("s32", 0),
|
||||
state: K.ITEM("u8", 0)
|
||||
}
|
||||
},
|
||||
|
||||
news: {
|
||||
checked: K.ITEM("s16", 0)
|
||||
},
|
||||
|
||||
bistro: {
|
||||
info: {
|
||||
delicious_rate: K.ITEM("float", 1.0),
|
||||
favorite_rate: K.ITEM("float", 1.0)
|
||||
},
|
||||
|
||||
chef: {
|
||||
id: K.ITEM("s32", 0),
|
||||
ability: K.ITEM("u8", 0),
|
||||
remain: K.ITEM("u8", 0),
|
||||
rate: K.ARRAY("u8", [0, 0, 0, 0])
|
||||
},
|
||||
|
||||
carry_over: K.ITEM("s32", data.saucer?.bistro?.carry_over || 0),
|
||||
|
||||
route: Array(9).fill(0).map((v, i) => (K.ATTR({ no: String(i) }, {
|
||||
music: {
|
||||
id: K.ITEM("s32", 0),
|
||||
price_s32: K.ITEM("s32", 0)
|
||||
},
|
||||
|
||||
gourmates: {
|
||||
id: K.ITEM("s32", 0),
|
||||
favorite: K.ARRAY("u8", Array(30).fill(0)),
|
||||
satisfaction_s32: K.ITEM("s32", 0)
|
||||
}
|
||||
})))
|
||||
},
|
||||
|
||||
rivallist: K.ATTR({ count: "0" }),
|
||||
|
||||
only_now_music: K.ATTR({ count: "0" }),
|
||||
requested_music: K.ATTR({ count: "0" }),
|
||||
lab_edit_seq: K.ATTR({ count: "0" }),
|
||||
kac_music: K.ATTR({ count: "0" }),
|
||||
});
|
||||
@@ -1,6 +1,30 @@
|
||||
export function getVersion({ model }: EamuseInfo) {
|
||||
const dateCode = model.split(':')[4];
|
||||
const dateCode = parseInt(model.split(":")[4]);
|
||||
|
||||
if (model.startsWith("J44")) return 3;
|
||||
if (model.startsWith("K44")) return 4;
|
||||
if (model.startsWith("L44")) {
|
||||
if (dateCode >= 2012082400 && dateCode <= 2014022400) return 5;
|
||||
if (dateCode >= 2014030303 && dateCode <= 2014121802) return 6;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function getVersionName({ model }: EamuseInfo) {
|
||||
const dateCode = parseInt(model.split(":")[4]);
|
||||
|
||||
if (model.startsWith("J44")) return "knit";
|
||||
if (model.startsWith("K44")) return "copious";
|
||||
if (model.startsWith("L44")) {
|
||||
if (dateCode >= 2012082400 && dateCode <= 2014022400) return "saucer";
|
||||
if (dateCode >= 2014030303 && dateCode <= 2014121802) return "fulfill";
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function VersionRange(version: number, start: number, end: number = -1) {
|
||||
if (end === -1) return version >= start;
|
||||
return version >= start && version <= end;
|
||||
}
|
||||
|
||||
@@ -7,5 +7,5 @@ export function isRequiredVersion(major: number, minor: number) {
|
||||
// version value exposed since Core v1.19
|
||||
const core_major = typeof CORE_VERSION_MAJOR === "number" ? CORE_VERSION_MAJOR : 1
|
||||
const core_minor = typeof CORE_VERSION_MINOR === "number" ? CORE_VERSION_MINOR : 18
|
||||
return core_major >= major && core_minor >= minor
|
||||
return core_major > major || (core_major === major && core_minor >= minor)
|
||||
}
|
||||
Reference in New Issue
Block a user