mirror of
https://github.com/asphyxia-core/plugins.git
synced 2026-04-04 16:25:14 -05:00
517 lines
19 KiB
TypeScript
517 lines
19 KiB
TypeScript
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");
|
|
if (!refId) return send.deny();
|
|
|
|
const version = getVersion(info);
|
|
if (version === 0) return send.deny();
|
|
|
|
const name = $(data).str("data.player.name");
|
|
|
|
let profile = await DB.FindOne<Profile>(refId, { collection: "profile" });
|
|
|
|
if (!profile) {
|
|
if (!name) return send.deny();
|
|
|
|
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;
|
|
}
|
|
|
|
return send.object({
|
|
data: {
|
|
...version === 5 && require("../templates/gameInfos/saucer.ts")(profile),
|
|
...version === 6 && require("../templates/gameInfos/fulfill.ts")(profile),
|
|
|
|
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)),
|
|
|
|
...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),
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
export const saveProfile: EPR = async (info, { data }, send) => {
|
|
console.log(U.toXML({
|
|
call: K.ATTR({ model: info.model }, {
|
|
[info.module]: K.ATTR({ method: info.method }, { data })
|
|
})
|
|
}));
|
|
|
|
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();
|
|
|
|
let lastMarker = 0;
|
|
let lastTheme = 0;
|
|
let lastTitle = 0;
|
|
let lastParts = 0;
|
|
let lastSort = 0;
|
|
let lastFilter = 0;
|
|
let lastCategory = 0;
|
|
let lastMselStat = 0;
|
|
|
|
const result = $(data).element("result");
|
|
|
|
if (result) {
|
|
const tunes = result.elements("tune");
|
|
const historys = {};
|
|
const historyNode = $(data).elements("player.history.tune");
|
|
|
|
if (historyNode) {
|
|
for (const history of historyNode) {
|
|
historys[history.attr().log_id] = {
|
|
timestamp: history.bigint("timestamp"),
|
|
isHard: history.bool("player.result.is_hard_mode")
|
|
};
|
|
}
|
|
}
|
|
|
|
for (const tune of tunes) {
|
|
const tuneId = tune.attr().id;
|
|
|
|
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") }
|
|
});
|
|
}
|
|
}
|
|
|
|
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) => {
|
|
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();
|
|
|
|
const version = getVersion(info);
|
|
if (version === 0) return send.deny();
|
|
|
|
const scores = await DB.Find<Score>(profile.__refid, { collection: "score" });
|
|
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]) {
|
|
scoreData[score.musicId] = {
|
|
playCnt: [0, 0, 0],
|
|
clearCnt: [0, 0, 0],
|
|
fcCnt: [0, 0, 0],
|
|
exCnt: [0, 0, 0],
|
|
clear: [0, 0, 0],
|
|
score: [0, 0, 0],
|
|
bar: [Array(30).fill(0), Array(30).fill(0), Array(30).fill(0)]
|
|
};
|
|
}
|
|
|
|
const data = scoreData[score.musicId];
|
|
data.playCnt[score.seq] = score.playCount;
|
|
data.clearCnt[score.seq] = score.clearCount;
|
|
data.fcCnt[score.seq] = score.fullcomboCount;
|
|
data.exCnt[score.seq] = score.excellentCount;
|
|
data.clear[score.seq] = score.clear;
|
|
data.score[score.seq] = score.score;
|
|
data.bar[score.seq] = score.bar;
|
|
}
|
|
|
|
return send.object({
|
|
data: {
|
|
player: {
|
|
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) }))
|
|
}))
|
|
})
|
|
}
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
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
|
|
}
|
|
});
|
|
|
|
return true;
|
|
} catch (e) {
|
|
console.error("Score saving failed: ", e.stack);
|
|
return false;
|
|
}
|
|
};
|
|
|
|
export const getCourse: EPR = async (info, data, send) => {
|
|
const version = getVersion(info);
|
|
if (version === 0) return send.deny();
|
|
|
|
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)
|
|
}
|
|
});
|
|
}
|
|
|
|
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" }),
|
|
},
|
|
reward: {
|
|
total: K.ITEM("s32", 0),
|
|
point: K.ITEM("s32", 0)
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
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),
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
};
|