From 13aaaca1b2cbd8e1d26b039a1aff4fb1e7a0ebf3 Mon Sep 17 00:00:00 2001 From: DitFranXX Date: Fri, 27 Nov 2020 04:12:29 +0900 Subject: [PATCH] Add support for `Hello! Pop'n Music`. --- popn-hello@asphyxia/README.md | 7 + popn-hello@asphyxia/handler/player.ts | 161 +++++++++++++++++++ popn-hello@asphyxia/handler/webui.ts | 15 ++ popn-hello@asphyxia/index.ts | 39 +++++ popn-hello@asphyxia/models/profile.ts | 12 ++ popn-hello@asphyxia/models/scores.ts | 14 ++ popn-hello@asphyxia/webui/profile_unlock.pug | 26 +++ 7 files changed, 274 insertions(+) create mode 100644 popn-hello@asphyxia/README.md create mode 100644 popn-hello@asphyxia/handler/player.ts create mode 100644 popn-hello@asphyxia/handler/webui.ts create mode 100644 popn-hello@asphyxia/index.ts create mode 100644 popn-hello@asphyxia/models/profile.ts create mode 100644 popn-hello@asphyxia/models/scores.ts create mode 100644 popn-hello@asphyxia/webui/profile_unlock.pug diff --git a/popn-hello@asphyxia/README.md b/popn-hello@asphyxia/README.md new file mode 100644 index 0000000..7584516 --- /dev/null +++ b/popn-hello@asphyxia/README.md @@ -0,0 +1,7 @@ +Hello! Pop'n Music +================== + +This plugin supports _Hello! Pop'n Music_. + +# ! IMPORTANT ! +You may need proper data to connect a network. Otherwise, it won't work! \ No newline at end of file diff --git a/popn-hello@asphyxia/handler/player.ts b/popn-hello@asphyxia/handler/player.ts new file mode 100644 index 0000000..cd9959e --- /dev/null +++ b/popn-hello@asphyxia/handler/player.ts @@ -0,0 +1,161 @@ +import { Profile } from '../models/profile'; +import { Scores } from '../models/scores'; + +export const newProfile: EPR = async (req, data, send) => { + const refid = $(data).attr().refid; + if (!refid) return send.deny(); + + await writeProfile(refid, await readProfile(refid)); + send.success(); +}; + +export const load: EPR = async (req, data, send) => { + try{ + const refid = $(data).attr().refid; + if (!refid) return send.deny(); + + const profile = await readProfile(refid); + const chara: any[] = []; + + if (profile.unlockAll) { + for (let i = 0; i < 11; ++i) { + chara.push(K.ATTR({ id: `${i}`, love: '5' })); + } + } else { + for (const i in profile.charas) { + chara.push(K.ATTR({ id: `${i}`, love: `${profile.charas[i]}` })); + } + } + + send.object({ + last: K.ATTR({ + chara: `${profile.history.chara}`, + level: `${profile.history.level}`, + music_id: `${profile.history.mid}`, + style: `${profile.history.style}`, + }), + chara, + // threshold: { + // '@attr': { id: 0, point: 100 }, + // }, + }) + } catch (e) { console.log(e.stack || e.stacktrace )} +}; + +export const load_m: EPR = async (req, data, send) => { + const refid = $(data).attr().refid; + if (!refid) return send.deny(); + + const scores = (await readScores(refid)).scores; + + const music: any[] = []; + for (const mid in scores) { + const style: any[] = []; + for (const sid in scores[mid]) { + const level: any[] = []; + for (const lid in scores[mid][sid]) { + level.push(K.ATTR({ + id: lid, + score: `${scores[mid][sid][lid].score}`, + clear_type: `${scores[mid][sid][lid].clear}`, + }), + ); + } + style.push(K.ATTR({ id: sid }, { level })); + } + music.push(K.ATTR({ music_id: mid }, { style })); + } + + send.object({ + music, + }); +}; + +export const save_m: EPR = async (req, data, send) => { + const refid = $(data).attr().refid; + if (!refid) return send.deny(); + + const scores = (await readScores(refid)).scores; + + const clear = parseInt($(data).attr().clear_type || '-1'); + const level = parseInt($(data).attr().level || '-1'); + const mid = parseInt($(data).attr().music_id || '-1'); + const score = parseInt($(data).attr().score || '-1'); + const style = parseInt($(data).attr().style || '-1'); + + if (clear < 0 || level < 0 || mid < 0 || score < 0 || style < 0) { + return send.success(); + } + + if (!scores[mid]) { + scores[mid] = {}; + } + + if (!scores[mid][style]) { + scores[mid][style] = {}; + } + + scores[mid][style][level] = { + score: Math.max(_.get(scores[mid][style][level], 'score', 0), score), + clear: Math.max(_.get(scores[mid][style][level], 'clear', 0), clear), + }; + + writeScores(refid, { collection: 'scores', scores }); + + send.success(); +}; + +export const save: EPR = async (req, data, send) => { + const refid = $(data).attr().refid; + if (!refid) return send.deny(); + + const profile = await readProfile(refid); + + const chara = parseInt($(data).attr('last').chara || '-1'); + const level = parseInt($(data).attr('last').level || '-1'); + const love = parseInt($(data).attr('last').love || '-1'); + const mid = parseInt($(data).attr('last').music_id || '-1'); + const style = parseInt($(data).attr('last').style || '-1'); + + if (chara < 0 || level < 0 || mid < 0 || love < 0 || style < 0) { + return send.success(); + } + + if (!profile.unlockAll) { + profile.charas[chara] = _.get(profile.charas, chara, 0) + love; + } + + profile.history = { + chara, + mid, + level, + style, + }; + + await writeProfile(refid, profile); + + send.success(); +}; + +async function readProfile(refid: string): Promise { + const profile = await DB.FindOne(refid, { collection: 'profile'} ) + return profile || { + collection: 'profile', + unlockAll: false, + history: { chara: 0, level: 0, mid: 0, style: 0 }, + charas: {}, + } + } + + async function writeProfile(refid: string, profile: Profile) { + await DB.Upsert(refid, { collection: 'profile'}, profile) + } + + async function readScores(refid: string): Promise { + const score = await DB.FindOne(refid, { collection: 'scores'} ) + return score || { collection: 'scores', scores: {}} + } + + async function writeScores(refid: string, scores: Scores) { + await DB.Upsert(refid, { collection: 'scores'}, scores) + } \ No newline at end of file diff --git a/popn-hello@asphyxia/handler/webui.ts b/popn-hello@asphyxia/handler/webui.ts new file mode 100644 index 0000000..d052265 --- /dev/null +++ b/popn-hello@asphyxia/handler/webui.ts @@ -0,0 +1,15 @@ +import { Profile } from "../models/profile"; + +export const setUnlockState = async (data: { + refid: string; + unlock_all: string; +}) => { + await DB.Update( + data.refid, + { collection: 'profile' }, + { $set: { + unlockAll: data.unlock_all == "on" + } + } + ); +}; \ No newline at end of file diff --git a/popn-hello@asphyxia/index.ts b/popn-hello@asphyxia/index.ts new file mode 100644 index 0000000..3993438 --- /dev/null +++ b/popn-hello@asphyxia/index.ts @@ -0,0 +1,39 @@ +import { load, load_m, newProfile, save, save_m } from "./handler/player"; +import { setUnlockState } from "./handler/webui"; + +const common: EPR = async (req, data, send) => { + send.object( + { + flag: K.ATTR({ id: '1', s1: '1', s2: '1', t: '1' }), + cnt_music: K.ITEM('u32', 36), + }, + { encoding: 'euc-jp' } + ); +}; + +const shop: EPR = async (req, data, send) => { + send.success() +} + +export function register() { + R.GameCode("JMP") + + R.WebUIEvent("setUnlockState", setUnlockState) + + // const Route = (method: string, handler: EPR) => + // R.Route(`game.${method}`, handler) + + // Common + R.Route("game.common", common) + R.Route("game.shop", shop) + + // Player + R.Route("game.new", newProfile) + R.Route("game.load", load) + R.Route("game.load_m", load_m) + R.Route("game.save", save) + R.Route("game.save_m", save_m) + + + R.Unhandled() +} \ No newline at end of file diff --git a/popn-hello@asphyxia/models/profile.ts b/popn-hello@asphyxia/models/profile.ts new file mode 100644 index 0000000..9ce7236 --- /dev/null +++ b/popn-hello@asphyxia/models/profile.ts @@ -0,0 +1,12 @@ +export interface Profile { + collection: 'profile', + + unlockAll: boolean; + history: { + chara: number; + level: number; + mid: number; + style: number; + }; + charas: { [id: string]: number }; +} \ No newline at end of file diff --git a/popn-hello@asphyxia/models/scores.ts b/popn-hello@asphyxia/models/scores.ts new file mode 100644 index 0000000..c53c723 --- /dev/null +++ b/popn-hello@asphyxia/models/scores.ts @@ -0,0 +1,14 @@ +export interface Scores { + collection: 'scores', + + scores: { + [mid: string]: { + [style: string]: { + [level: string]: { + score: number; + clear: number; + }; + }; + } + }; +} \ No newline at end of file diff --git a/popn-hello@asphyxia/webui/profile_unlock.pug b/popn-hello@asphyxia/webui/profile_unlock.pug new file mode 100644 index 0000000..d7072a9 --- /dev/null +++ b/popn-hello@asphyxia/webui/profile_unlock.pug @@ -0,0 +1,26 @@ +//DATA// + profile: DB.FindOne(refid, { collection: 'profile' }) + +div + .card + .card-header + p.card-header-title + span.icon + i.mdi.mdi-account-edit + | Detail Change + .card-content + form(method="post" action="/emit/setUnlockState") + .field + label.label ID + .control + input.input(type="text" name="refid", value=refid readonly) + .field + label.label Unlock All + .control + input(type="checkbox" name="unlock_all", checked=profile.unlockAll) + | Turn this on to max out all characters and unlock 11 hidden songs. + .field + button.button.is-primary(type="submit") + span.icon + i.mdi.mdi-check + span Submit