Merge pull request #10 from DitFranXX/nostalgia

Nostalgia(First version) support
This commit is contained in:
Freddie Wang 2020-12-26 15:13:38 +08:00 committed by GitHub
commit 8f4282e711
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 151 additions and 44 deletions

View File

@ -1,25 +1,28 @@
# Nostalgia
Plugin Version: **v1.1.0**
Plugin Version: **v1.2.0**
Supported Versions
-------------------
- Forte (Experiment)
- ノスタルジア/ First Version (Experiment-Old)
- Forte (Experiment-Old)
- Op.2
About Experiment-Old Support
----------------------------
A version that marked as **Experiment-Old** is _Not_ Primary supported experiment version.
Since This plugin is mainly focused on Op.2, other versions may not work correctly.
About Forte Support
-------------------
Forte support is live. But since it has much difference compared to Op.2, Forte is not-primary-supported version.
It may works unexpectedly. Forte was tested very lightly. So this feature is tagged as **Experiment**.
Also, Technically, This *may* support First version of Nostalgia too.
But It's highly not recommend to run First version with it.
If you have a problem that move from old version to new version, There's webui for mitigate the issue.
Changelog
=========
1.1.0 (Current)
1.2.0 (Current)
---------------
- Nostalgia First version support.
1.1.0
-----
- Fix saving issue with brooch, island, and kentei.
- Moved to Base64 encoded data base.
- Forte support.

View File

@ -0,0 +1,11 @@
import { CommonMusicData, readJSONOrXML } from "./ForteMusic";
import { readB64JSON } from "./helper";
export async function processData(): Promise<CommonMusicData> {
if (IO.Exists("data/first_mdb.json.b64")) {
return await readB64JSON("data/first_mdb.json.b64");
}
const data = await readJSONOrXML("data/first_mdb.json", "data/first_mdb.xml")
// await IO.WriteFile("data/first_mdb.json.b64", Buffer.from(JSON.stringify(data)).toString("base64"))
return data;
}

View File

@ -1,12 +1,11 @@
import { CommonMusicDataField, readB64JSON, readXML } from "./helper";
export async function processData() {
export async function processData(): Promise<CommonMusicData> {
if (IO.Exists("data/forte_mdb.json.b64")) {
return await readB64JSON("data/forte_mdb.json.b64");
}
const data = await readJSONOrXML("data/forte_mdb.json", "data/forte_mdb.xml")
// await IO.WriteFile("data/forte_mdb.json.b64", Buffer.from(JSON.stringify(data)).toString("base64"))
return data
return data;
}
export async function processMdbData(path: string): Promise<CommonMusicData> {
@ -62,7 +61,7 @@ export async function readJSONOrXML(jsonPath: string, xmlPath: string): Promise<
}
}
interface CommonMusicData {
export interface CommonMusicData {
"@attr": {
revision: string,
release_code: string

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,8 @@
import * as path from "path";
import { processData } from "../data/ForteMusic";
import { processData as firstData } from "../data/FirstMusic";
import { processData as forteData } from "../data/ForteMusic";
import { readB64JSON } from "../data/helper";
import { NosVersionHelper } from "../utils";
export const permitted_list = {
flag: [
@ -80,7 +82,7 @@ export const get_common_info = async (info, data, send) => {
};
export const get_music_info: EPR = async (info, data, send) => {
const isForte = !info.module.includes("op")
const version = new NosVersionHelper(info)
const music_spec: any = [];
for (let i = 1; i < 400; ++i) {
@ -99,10 +101,12 @@ export const get_music_info: EPR = async (info, data, send) => {
}));
}
const versionObject = isForte
const music_list = async () => version.version === 'Forte' ? await forteData() : await firstData()
const versionObject = version.isFirstOrForte()
? {
permitted_list: forte_permitted_list,
music_list: await processData()
music_list: await music_list()
}
: {
permitted_list,

View File

@ -1,11 +1,7 @@
// import { EAHandler } from '../../util/EAHandler';
// import { get, _.isArray } from 'lodash';
// import { Logger } from '../../util/Logger';
import { Profile } from '../models/profile';
import { Scores } from '../models/scores';
import { NosVersionHelper } from '../utils';
import { permitted_list, forte_permitted_list } from './common';
// import { getValue, getArray, getAttr, getStr, getBigInt } from '../../util/Helper';
// export const event_list = {
// event: {
@ -18,9 +14,9 @@ import { permitted_list, forte_permitted_list } from './common';
// },
// };
const getEventInfo = (isForte: boolean) => {
const getEventInfo = (version: NosVersionHelper) => {
const event: any[] = [];
const event_num = isForte ? 10 : 17
const event_num = version.getEventMaxIndex()
for (let i = 1; i <= event_num; ++i) {
event.push({
type: K.ITEM('s32', 4),
@ -37,7 +33,7 @@ const getEventInfo = (isForte: boolean) => {
const getPlayerData = async (refid: string, info: EamuseInfo, name?: string) => {
const p = await readProfile(refid);
const isForte = !info.module.includes("op")
const version = new NosVersionHelper(info)
if (name && name.length > 0) {
p.name = name;
@ -55,7 +51,7 @@ const getPlayerData = async (refid: string, info: EamuseInfo, name?: string) =>
const brooch: any[] = [];
for (const b in p.brooches) {
if (isForte && parseInt(b, 10) > 147) continue; // Forte Brooch is ~147.
if (parseInt(b, 10) > version.getBroochMaxIndex()) continue;
const bData = p.brooches[b];
brooch.push(K.ATTR({ index: b }, {
watch_count: K.ITEM('s32', bData.watch),
@ -67,6 +63,7 @@ const getPlayerData = async (refid: string, info: EamuseInfo, name?: string) =>
// Unlock brooches
for (let i = 101; i <= 124; ++i) {
if (i > version.getBroochMaxIndex()) continue;
brooch.push(K.ATTR({ index: `${i}` }, {
'watch_count': K.ITEM('s32', 0),
'level': K.ITEM('s8', 1),
@ -137,7 +134,7 @@ const getPlayerData = async (refid: string, info: EamuseInfo, name?: string) =>
}));
}
const correct_permitted_list = !isForte ? permitted_list : forte_permitted_list
const correct_permitted_list = !version.isFirstOrForte() ? permitted_list : forte_permitted_list
const music_list = [
K.ARRAY('s32', p.musicList.type_0, { sheet_type: '0' }),
K.ARRAY('s32', p.musicList.type_1, { sheet_type: '1' }),
@ -151,7 +148,7 @@ const getPlayerData = async (refid: string, info: EamuseInfo, name?: string) =>
K.ARRAY('s32', p.musicList2.type_3, { sheet_type: '3' }),
];
if(isForte) {
if(version.isFirstOrForte()) {
music_list.pop();
music_list2.pop();
}
@ -161,8 +158,8 @@ const getPlayerData = async (refid: string, info: EamuseInfo, name?: string) =>
play_count: K.ITEM('s32', p.playCount),
today_play_count: K.ITEM('s32', p.todayPlayCount),
permitted_list: correct_permitted_list,
event_info_list: { event: getEventInfo(isForte) }, // Op2
event_control_list: { event: getEventInfo(isForte) }, // Forte
event_info_list: { event: getEventInfo(version) }, // Op2
event_control_list: { event: getEventInfo(version) }, // Forte
music_list: {
flag: music_list,
},
@ -170,17 +167,17 @@ const getPlayerData = async (refid: string, info: EamuseInfo, name?: string) =>
flag: music_list2,
},
last: {
music_index: K.ITEM('s32', forteNumericHandler(isForte, p.music, 195, 0)),
sheet_type: K.ITEM('s8', forteNumericHandler(isForte, p.sheet, 3, 0)),
brooch_index: K.ITEM('s32', forteNumericHandler(isForte, p.brooch, 147, 0)),
music_index: K.ITEM('s32', version.numericHandler('music_index', p.music, 0)),
sheet_type: K.ITEM('s8', version.numericHandler('sheet_type', p.sheet, 0)),
brooch_index: K.ITEM('s32', version.numericHandler('brooch_index', p.brooch, 0)),
hi_speed_level: K.ITEM('s32', p.hispeed),
beat_guide: K.ITEM('s8', p.beatGuide),
headphone_volume: K.ITEM('s8', p.headphone),
judge_bar_pos: K.ITEM('s32', p.judgeBar),
music_group: K.ITEM('s32', p.group),
hands_mode: isForte ? K.ITEM('s32', p.mode) : K.ITEM('s8', p.mode),
hands_mode: version.isFirstOrForte() ? K.ITEM('s32', p.mode) : K.ITEM('s8', p.mode),
near_setting: K.ITEM('s8', p.near),
judge_delay_offset: isForte ? K.ITEM('s32', p.offset) : K.ITEM('s8', p.offset),
judge_delay_offset: version.isFirstOrForte() ? K.ITEM('s32', p.offset) : K.ITEM('s8', p.offset),
bingo_index: K.ITEM('s32', p.bingo),
total_skill_value: K.ITEM('u64', BigInt(p.skill)),
key_beam_level: K.ITEM('s8', p.keyBeam),
@ -250,7 +247,7 @@ export const set_total_result: EPR = async (info, data, send) => {
const refid = $(data).str('refid');
if (!refid) return send.deny();
const isForte = !info.module.includes("op")
const isForte = new NosVersionHelper(info).isFirstOrForte()
const p = await readProfile(refid);
p.playCount = $(data).number('play_count', p.playCount);
@ -471,7 +468,7 @@ export const get_musicdata: EPR = async (info, data, send) => {
const refid = $(data).str('refid');
if (!refid) return send.deny();
const isForte = !info.module.includes("op")
const version = new NosVersionHelper(info)
const scoreData = await readScores(refid);
const recital_record: any[] = [];
@ -499,7 +496,7 @@ export const get_musicdata: EPR = async (info, data, send) => {
const mdata = m.split(':');
const musi = scoreData.scores[m];
if (isForte && parseInt(mdata[0], 10) > 195) continue;
if (parseInt(mdata[0], 10) > version.getMusicMaxIndex()) continue;
music.push(K.ATTR({
music_index: mdata[0],
@ -523,10 +520,6 @@ export const get_musicdata: EPR = async (info, data, send) => {
});
};
function forteNumericHandler(isForte: boolean, input: number, max: number, def: number = 0) {
return isForte ? input > max ? def : input : input;
}
async function readProfile(refid: string): Promise<Profile> {
const profile = await DB.FindOne<Profile>(refid, { collection: 'profile' })
return profile || defaultProfile

View File

@ -0,0 +1,20 @@
import { Profile } from "../models/profile";
export const fixIndexBug = async (data: {
refid: string;
confirm: string;
}) => {
if (data.confirm == "on") {
console.warn(`refid "${data.refid}" performs index reset!`)
await DB.Update<Profile>(
data.refid,
{ collection: 'profile' },
{ $set: {
music: 0,
sheet: 0,
brooch: 0
}
}
);
}
};

View File

@ -1,9 +1,12 @@
import { get_common_info, get_music_info } from "./handler/common";
import { get_musicdata, get_playdata, regist_playdata, set_total_result } from "./handler/player"
import { fixIndexBug } from "./handler/webui";
export function register() {
R.GameCode('PAN');
R.WebUIEvent("nosFixIndexBug", fixIndexBug)
const MultiRoute = (method: string, handler: EPR | boolean) => {
// Helper for register multiple versions.
R.Route(method, handler); // First version and Forte.

View File

@ -0,0 +1,47 @@
type NostalgiaVersions = 'First' | 'Forte' | 'Op2' | 'Op3'
type NostalgiaNumericTypes = 'music_index' | 'sheet_type' | 'brooch_index' | 'event_index'
export class NosVersionHelper {
public version: NostalgiaVersions
private table = { // FIXME: All of Op3 values are placeholder
music_index: { First: 87, Forte: 195, Op2: 315, Op3: 500 },
brooch_index: { First: 120, Forte: 147, Op2: 148, Op3: 200 },
sheet_type: { First: 2, Forte: 2, Op2: 3, Op3: 3 },
event_index: { First: 10, Forte: 10, Op2: 17, Op3: 20 }
}
constructor (info: EamuseInfo) {
const version = parseInt(info.model.trim().substr(10), 10)
if (version >= 2020000000) {
this.version = 'Op3'
} else if (version >= 2019000000) {
this.version = 'Op2'
} else if (version >= 2018000000) {
this.version = 'Forte'
} else {
this.version = 'First'
}
}
getMusicMaxIndex() {
return this.table['music_index'][this.version]
}
getBroochMaxIndex() {
return this.table['brooch_index'][this.version]
}
getEventMaxIndex() {
return this.table['event_index'][this.version]
}
numericHandler(type: NostalgiaNumericTypes, input: number, def: number = 0) {
return input > this.table[type][this.version] ? def : input;
}
isFirstOrForte() {
return this.version === 'First' || this.version === 'Forte'
}
}

View File

@ -0,0 +1,26 @@
div
.card
.card-header
p.card-header-title
span.icon
i.mdi.mdi-account-edit
| Fix Error with Login
.card-content
p If you unable to login after travels of between versions, This may helpful.
p Normally, login issue caused you played deleted song last time in previous version that not deleted time.
p This page is about reset of last indexes that causing login problem.
form(method="post" action="/emit/nosFixIndexBug")
.field
label.label ID
.control
input.input(type="text" name="refid", value=refid readonly)
.field
label.label Are you sure to reset indexes?
.control
input(type="checkbox" name="confirm")
| This is not recoverable. Do this if you have a problem.
.field
button.button.is-primary(type="submit")
span.icon
i.mdi.mdi-check
span Submit