mirror of
https://github.com/asphyxia-core/plugins.git
synced 2026-04-26 02:02:29 -05:00
commit
ece1f7b7b8
27
museca@asphyxia/README.md
Normal file
27
museca@asphyxia/README.md
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
MUSECA
|
||||||
|
======
|
||||||
|
|
||||||
|
Plugin Version: **v1.0.0**
|
||||||
|
|
||||||
|
Supported Versions
|
||||||
|
------------------
|
||||||
|
- 1+1/2
|
||||||
|
- [MUSECA PLUS](https://museca.plus/) (2020-11-27)
|
||||||
|
|
||||||
|
|
||||||
|
For who plays MUSECA PLUS
|
||||||
|
-------------------------
|
||||||
|
If you have a version that not supported on plugin, try Custom MDB feature.
|
||||||
|
|
||||||
|
The mdb file is located on `museca-plus/museca/xml/music-info-b.xml`
|
||||||
|
|
||||||
|
Only Initial support for now.
|
||||||
|
-----------------------------
|
||||||
|
Course is not implemented yet.
|
||||||
|
Also, Score-Save is only proofed for working correctly. I didn't tested other features. sorry!
|
||||||
|
|
||||||
|
Changelog
|
||||||
|
=========
|
||||||
|
1.0.0 (Current)
|
||||||
|
---------------
|
||||||
|
Initial Support.
|
||||||
1
museca@asphyxia/data/.gitignore
vendored
Normal file
1
museca@asphyxia/data/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
*.xml
|
||||||
12
museca@asphyxia/data/CommunityPlusMDB.ts
Normal file
12
museca@asphyxia/data/CommunityPlusMDB.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { processMdbData,readJSONOrXML } from './helper';
|
||||||
|
|
||||||
|
export async function processData() {
|
||||||
|
const { music } = await readJSONOrXML("./data/mdb_community_plus.json", "./data/mdb_community_plus.xml")
|
||||||
|
return {
|
||||||
|
music
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function processRawData() {
|
||||||
|
return await processMdbData("./data/mdb_community_plus.xml")
|
||||||
|
}
|
||||||
12
museca@asphyxia/data/OnePlusHalfMDB.ts
Normal file
12
museca@asphyxia/data/OnePlusHalfMDB.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { processMdbData,readJSONOrXML } from './helper';
|
||||||
|
|
||||||
|
export async function processData() {
|
||||||
|
const { music } = await readJSONOrXML("./data/mdb_one_plus_half.json", "./data/mdb_one_plus_half.xml")
|
||||||
|
return {
|
||||||
|
music
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function processRawData() {
|
||||||
|
return await processMdbData("./data/mdb_one_plus_half.xml");
|
||||||
|
}
|
||||||
57
museca@asphyxia/data/helper.ts
Normal file
57
museca@asphyxia/data/helper.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
export interface CommonMusicDataField {
|
||||||
|
music_id: KITEM<"s32">;
|
||||||
|
music_type: KITEM<"u8">;
|
||||||
|
limited: KITEM<"u8">;
|
||||||
|
}
|
||||||
|
|
||||||
|
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): Promise<CommonMusicData> {
|
||||||
|
const str: string | null = await IO.ReadFile(jsonPath, 'utf-8');
|
||||||
|
if (str == null || str.length == 0) {
|
||||||
|
const data = await processMdbData(xmlPath)
|
||||||
|
await IO.WriteFile(jsonPath, JSON.stringify(data))
|
||||||
|
return data
|
||||||
|
} else {
|
||||||
|
const json = JSON.parse(str)
|
||||||
|
return json
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function processMdbData(path: string): Promise<CommonMusicData> {
|
||||||
|
const data = await readXML(path);
|
||||||
|
const mdb = $(data).elements("mdb.music");
|
||||||
|
const diff_list = ["novice", "advanced", "exhaust", "infinite"]
|
||||||
|
const music: CommonMusicDataField[] = [];
|
||||||
|
for (const m of mdb) {
|
||||||
|
for (const [i, d] of diff_list.entries()) {
|
||||||
|
const elem = m.element(`difficulty.${d}`)
|
||||||
|
if (elem.number("difnum", 0) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
music.push({
|
||||||
|
music_id: K.ITEM("s32", parseInt(m.attr().id)),
|
||||||
|
music_type: K.ITEM("u8", i),
|
||||||
|
limited: K.ITEM("u8", elem.number("limited"))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
music,
|
||||||
|
};
|
||||||
|
}
|
||||||
1
museca@asphyxia/data/mdb_community_plus.json
Normal file
1
museca@asphyxia/data/mdb_community_plus.json
Normal file
File diff suppressed because one or more lines are too long
1
museca@asphyxia/data/mdb_one_plus_half.json
Normal file
1
museca@asphyxia/data/mdb_one_plus_half.json
Normal file
File diff suppressed because one or more lines are too long
88
museca@asphyxia/handlers/common.ts
Normal file
88
museca@asphyxia/handlers/common.ts
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
import * as path from "path"
|
||||||
|
import { processMdbData } from "../data/helper"
|
||||||
|
import { processData as processCommunityPlusData } from "../data/CommunityPlusMDB"
|
||||||
|
import { processData as processOnePlusHalfData } from "../data/OnePlusHalfMDB"
|
||||||
|
|
||||||
|
|
||||||
|
export const shop: EPR = async (info, data, send) => {
|
||||||
|
// Ignore shop name setter.
|
||||||
|
send.object({
|
||||||
|
nxt_time: K.ITEM("u32", 1000 * 5 * 60)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const common: EPR = async (info, data, send) => {
|
||||||
|
let { music } = U.GetConfig("enable_custom_mdb")
|
||||||
|
? await processCustomData()
|
||||||
|
: (await processValidData(info))
|
||||||
|
|
||||||
|
if (music.length === 0) {
|
||||||
|
music = (await processValidData(info)).music
|
||||||
|
}
|
||||||
|
|
||||||
|
if (U.GetConfig("unlock_all_songs")) {
|
||||||
|
music.forEach(element => {
|
||||||
|
element.limited = K.ITEM("u8", 3)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flags
|
||||||
|
const event_list = [1, 83, 130, 194, 195, 98, 145, 146, 147, 148, 149, 56, 86, 105, 140, 211, 143]
|
||||||
|
const event = {
|
||||||
|
info: event_list.map((e) => {
|
||||||
|
return {
|
||||||
|
event_id: K.ITEM("u32", e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
send.object({
|
||||||
|
music_limited: {
|
||||||
|
info: music
|
||||||
|
},
|
||||||
|
event,
|
||||||
|
// TODO: Skill course, Extended option.
|
||||||
|
// skill_course,
|
||||||
|
// extend
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Implement this.
|
||||||
|
export const hiscore: EPR = async (info, data, send) => {
|
||||||
|
send.success()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const frozen: EPR = async (info, data, send) => {
|
||||||
|
send.object({
|
||||||
|
result: K.ITEM("u8", 0)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Implement this fully.
|
||||||
|
export const lounge: EPR = async (info, data, send) => {
|
||||||
|
send.object({
|
||||||
|
interval: K.ITEM("u32", 10),
|
||||||
|
// wait
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const exception: EPR = async (info, data, send) => {
|
||||||
|
send.success()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function processCustomData() {
|
||||||
|
return processMdbData("data/custom_mdb.xml")
|
||||||
|
}
|
||||||
|
|
||||||
|
async function processValidData(info: EamuseInfo) {
|
||||||
|
const version = parseInt(info.model.trim().substr(10), 10)
|
||||||
|
if (version >= 2020102200) {
|
||||||
|
// MUSECA PLUS
|
||||||
|
processCommunityPlusData();
|
||||||
|
} else /** if (version > 2016071300) */ {
|
||||||
|
return await processOnePlusHalfData()
|
||||||
|
} /** else {
|
||||||
|
// Museca 1
|
||||||
|
return await processOneData()
|
||||||
|
}**/
|
||||||
|
}
|
||||||
223
museca@asphyxia/handlers/player.ts
Normal file
223
museca@asphyxia/handlers/player.ts
Normal file
|
|
@ -0,0 +1,223 @@
|
||||||
|
import { Profile } from "../models/profile";
|
||||||
|
import { Scores } from "../models/scores";
|
||||||
|
import { IDToCode } from "../utils";
|
||||||
|
|
||||||
|
export const load: EPR = async (info, data, send) => {
|
||||||
|
const refid = $(data).str('refid');
|
||||||
|
if (!refid) return send.deny();
|
||||||
|
|
||||||
|
const profile = await DB.FindOne<Profile>(refid, { collection: "profile" })
|
||||||
|
if (profile == null) {
|
||||||
|
// Request New Profile from game side.
|
||||||
|
return send.object({
|
||||||
|
result: K.ITEM("u8", 1)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const item = _.map(profile.item, (v, k) => {
|
||||||
|
const id = k.replace("g", "")
|
||||||
|
return {
|
||||||
|
type: K.ITEM("u8", v.type),
|
||||||
|
id: K.ITEM("u32", parseInt(id)),
|
||||||
|
param: K.ITEM("u32", v.param)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
send.object({
|
||||||
|
hidden_param: K.ARRAY("s32", profile.hidden_param),
|
||||||
|
play_count: K.ITEM("u32", profile.play_count),
|
||||||
|
daily_count: K.ITEM("u32", profile.daily_count),
|
||||||
|
play_chain: K.ITEM("u32", profile.play_chain),
|
||||||
|
last: {
|
||||||
|
headphone: K.ITEM("u8", profile.last.headphone),
|
||||||
|
appeal_id: K.ITEM("u16", profile.last.appeal_id),
|
||||||
|
comment_id: K.ITEM("u16", profile.last.comment_id),
|
||||||
|
music_id: K.ITEM("s32", profile.last.music_id),
|
||||||
|
music_type: K.ITEM("u8", profile.last.music_type),
|
||||||
|
sort_type: K.ITEM("u8", profile.last.sort_type),
|
||||||
|
narrow_down: K.ITEM("u8", profile.last.narrow_down),
|
||||||
|
gauge_option: K.ITEM("u8", profile.last.gauge_option),
|
||||||
|
},
|
||||||
|
blaster_energy: K.ITEM("u32", profile.blaster_energy),
|
||||||
|
blaster_count: K.ITEM("u32", profile.blaster_count),
|
||||||
|
code: K.ITEM("str", IDToCode(profile.code)),
|
||||||
|
name: K.ITEM("str", profile.name),
|
||||||
|
creator_id: K.ITEM("u32", profile.creator_id),
|
||||||
|
skill_level: K.ITEM("s16", profile.skill_level),
|
||||||
|
skill_name_id: K.ITEM("s16", profile.skill_name_id),
|
||||||
|
gamecoin_packet: K.ITEM("u32", profile.gamecoin_packet),
|
||||||
|
gamecoin_block: K.ITEM("u32", profile.gamecoin_block),
|
||||||
|
item: {
|
||||||
|
info: item
|
||||||
|
},
|
||||||
|
param: {},
|
||||||
|
result: K.ITEM("u8", 0),
|
||||||
|
ea_shop: {
|
||||||
|
packet_booster: K.ITEM("s32", 0),
|
||||||
|
block_booster: K.ITEM("s32", 0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const load_m: EPR = async (info, data, send) => {
|
||||||
|
const refid = $(data).str('dataid');
|
||||||
|
if (!refid) return send.deny();
|
||||||
|
|
||||||
|
const scores = (await DB.FindOne<Scores>(refid, { collection: 'scores'})).scores
|
||||||
|
|
||||||
|
const music: any[] = [];
|
||||||
|
for (const mid in scores) {
|
||||||
|
for (const type in scores[mid]) {
|
||||||
|
let score = scores[mid][type]
|
||||||
|
music.push({
|
||||||
|
music_id: K.ITEM("u32", parseInt(mid)),
|
||||||
|
music_type: K.ITEM("u32", parseInt(type)),
|
||||||
|
score: K.ITEM("u32", score.score),
|
||||||
|
cnt: K.ITEM("u32", score.count),
|
||||||
|
clear_type: K.ITEM("u32", score.clear_type),
|
||||||
|
score_grade: K.ITEM("u32", score.score_grade),
|
||||||
|
btn_rate: K.ITEM("u32", score.btn_rate),
|
||||||
|
long_rate: K.ITEM("u32", score.long_rate),
|
||||||
|
vol_rate: K.ITEM("u32", score.vol_rate)
|
||||||
|
})
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
send.object({
|
||||||
|
new: {
|
||||||
|
music
|
||||||
|
},
|
||||||
|
// This field seems used on Museca 1, Ignore this.
|
||||||
|
old: {}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const save: EPR = async (info, data, send) => {
|
||||||
|
const refid = $(data).str('refid');
|
||||||
|
if (!refid) return send.deny();
|
||||||
|
|
||||||
|
const dbItem = (await DB.FindOne<Profile>(refid, { collection: "profile" })).item
|
||||||
|
for(const item of $(data).elements("item.info")) {
|
||||||
|
const id = item.number("id");
|
||||||
|
const type = item.number("type")
|
||||||
|
// Grafica and Mission shares same ID. Why?????
|
||||||
|
dbItem[type == 16 ? `g${id}` : id] = {
|
||||||
|
type,
|
||||||
|
param : item.number("param")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
await DB.Upsert<Profile>(refid, { collection: "profile" }, {
|
||||||
|
$set: {
|
||||||
|
last: {
|
||||||
|
headphone: $(data).number("headphone"),
|
||||||
|
appeal_id: $(data).number("appeal_id"),
|
||||||
|
comment_id: $(data).number("comment_id"),
|
||||||
|
music_id: $(data).number("music_id"),
|
||||||
|
music_type: $(data).number("music_type"),
|
||||||
|
sort_type: $(data).number("sort_type"),
|
||||||
|
narrow_down: $(data).number("narrow_down"),
|
||||||
|
gauge_option: $(data).number("gauge_option"),
|
||||||
|
},
|
||||||
|
hidden_param: $(data).numbers("hidden_param"),
|
||||||
|
blaster_count: $(data).number("blaster_count"),
|
||||||
|
item: dbItem,
|
||||||
|
},
|
||||||
|
$inc: {
|
||||||
|
blaster_energy: $(data).number("earned_blaster_energy"),
|
||||||
|
gamecoin_block: $(data).number("earned_gamecoin_block"),
|
||||||
|
gamecoin_packet: $(data).number("earned_gamecoin_packet")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
send.success()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const save_m: EPR = async (info, data, send) => {
|
||||||
|
const refid = $(data).str('refid');
|
||||||
|
if (!refid) return send.deny();
|
||||||
|
|
||||||
|
const scores = (await DB.FindOne<Scores>(refid, { collection: "scores" })).scores
|
||||||
|
const mid = $(data).number("music_id")
|
||||||
|
const type = $(data).number("music_type")
|
||||||
|
|
||||||
|
if (!scores[mid]) {
|
||||||
|
scores[mid] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
scores[mid][type] = {
|
||||||
|
score: Math.max(_.get(scores[mid][type], 'score', 0), $(data).number("score")),
|
||||||
|
clear_type: Math.max(_.get(scores[mid][type], 'clear_type', 0), $(data).number("clear_type")),
|
||||||
|
score_grade: Math.max(_.get(scores[mid][type], 'score_grade', 0), $(data).number("score_grade")),
|
||||||
|
count: _.get(scores[mid][type], 'count', 0) + 1,
|
||||||
|
btn_rate: Math.max(_.get(scores[mid][type], 'btn_rate', 0), $(data).number("btn_rate")),
|
||||||
|
long_rate: Math.max(_.get(scores[mid][type], 'long_rate', 0), $(data).number("long_rate")),
|
||||||
|
vol_rate: Math.max(_.get(scores[mid][type], 'vol_rate', 0), $(data).number("vol_rate")),
|
||||||
|
};
|
||||||
|
|
||||||
|
const store: Scores = {
|
||||||
|
collection: "scores",
|
||||||
|
scores
|
||||||
|
}
|
||||||
|
|
||||||
|
await DB.Upsert<Scores>(refid, { collection: "scores" }, store)
|
||||||
|
|
||||||
|
send.success()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const newProfile: EPR = async (info, data, send) => {
|
||||||
|
const refid = $(data).str('refid');
|
||||||
|
if (!refid) return send.deny();
|
||||||
|
|
||||||
|
const name = $(data).str('name', 'NONAME');
|
||||||
|
let code = _.random(0, 99999999);
|
||||||
|
while (await DB.FindOne<Profile>(null, { collecttion: 'profile', code })) {
|
||||||
|
code = _.random(0, 99999999);
|
||||||
|
}
|
||||||
|
|
||||||
|
let defItem = {};
|
||||||
|
for(let i = 1; i < 801; i++) {
|
||||||
|
defItem[i] = {
|
||||||
|
type: 4,
|
||||||
|
param : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const profile: Profile = {
|
||||||
|
collection: "profile",
|
||||||
|
code,
|
||||||
|
name,
|
||||||
|
|
||||||
|
hidden_param: Array(20).fill(0),
|
||||||
|
play_count: 0,
|
||||||
|
daily_count: 0,
|
||||||
|
play_chain: 0,
|
||||||
|
last: {
|
||||||
|
headphone: 0,
|
||||||
|
appeal_id: 0,
|
||||||
|
comment_id: 0,
|
||||||
|
music_id: 0,
|
||||||
|
music_type: 0,
|
||||||
|
sort_type: 0,
|
||||||
|
narrow_down: 0,
|
||||||
|
gauge_option: 0,
|
||||||
|
},
|
||||||
|
blaster_energy: 0,
|
||||||
|
blaster_count: 0,
|
||||||
|
creator_id: 0,
|
||||||
|
skill_level: 0,
|
||||||
|
skill_name_id: 0,
|
||||||
|
gamecoin_packet: 0,
|
||||||
|
gamecoin_block: 0,
|
||||||
|
|
||||||
|
item: defItem,
|
||||||
|
|
||||||
|
packet_booster: 0,
|
||||||
|
block_booster: 0,
|
||||||
|
}
|
||||||
|
await DB.Upsert<Profile>(refid, { collection: "profile"}, profile)
|
||||||
|
await DB.Upsert<Scores>(refid, { collection: "scores" }, { collection: "scores", scores: {}})
|
||||||
|
send.success()
|
||||||
|
}
|
||||||
59
museca@asphyxia/index.ts
Normal file
59
museca@asphyxia/index.ts
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
import { common, exception, lounge, shop, hiscore, frozen } from "./handlers/common";
|
||||||
|
import { load, load_m, newProfile, save, save_m } from "./handlers/player";
|
||||||
|
import { isRequiredVersion } from "./utils";
|
||||||
|
|
||||||
|
export function register() {
|
||||||
|
if(!isRequiredVersion(1, 19)) {
|
||||||
|
console.error("You need newer version of Core. v1.19 or newer required.")
|
||||||
|
}
|
||||||
|
|
||||||
|
R.GameCode('PIX');
|
||||||
|
|
||||||
|
R.Config("unlock_all_songs", {
|
||||||
|
name: "Force unlock all songs",
|
||||||
|
type: "boolean",
|
||||||
|
default: false
|
||||||
|
})
|
||||||
|
|
||||||
|
R.Config("enable_custom_mdb", {
|
||||||
|
name: "Enable Custom MDB",
|
||||||
|
desc: "For who uses own MDB",
|
||||||
|
type: "boolean",
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
R.DataFile("data/custom_mdb.xml", {
|
||||||
|
accept: ".xml",
|
||||||
|
name: "Custom MDB",
|
||||||
|
desc: "You need to enable Custom MDB option first."
|
||||||
|
})
|
||||||
|
|
||||||
|
const Route = (method: string, handler: EPR | boolean) => {
|
||||||
|
// Helper for register multiple versions.
|
||||||
|
// Use this when plugin supports first version.
|
||||||
|
R.Route(`game_3.${method}`, handler);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Common
|
||||||
|
Route("common", common)
|
||||||
|
Route("shop", shop)
|
||||||
|
Route("exception", exception)
|
||||||
|
Route("hiscore", hiscore),
|
||||||
|
Route("lounge", lounge),
|
||||||
|
Route("frozen", frozen)
|
||||||
|
Route("play_e", true)
|
||||||
|
|
||||||
|
// Player
|
||||||
|
Route("new", newProfile)
|
||||||
|
Route("save", save)
|
||||||
|
Route("save_m", save_m)
|
||||||
|
//Route("save_c", save_c)
|
||||||
|
Route("load", load)
|
||||||
|
Route("load_m", load_m)
|
||||||
|
|
||||||
|
R.Unhandled(async (info, data, send) => {
|
||||||
|
if (["eventlog"].includes(info.module)) return;
|
||||||
|
console.error(`Received Unhandled Response on ${info.method} by ${info.model}/${info.module}`)
|
||||||
|
console.error(`Received Request: ${JSON.stringify(data, null, 4)}`)
|
||||||
|
})
|
||||||
|
}
|
||||||
38
museca@asphyxia/models/profile.ts
Normal file
38
museca@asphyxia/models/profile.ts
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
export interface Profile {
|
||||||
|
collection: 'profile';
|
||||||
|
|
||||||
|
code: number;
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
hidden_param: number[];
|
||||||
|
play_count: number;
|
||||||
|
daily_count: number;
|
||||||
|
play_chain: number;
|
||||||
|
last: {
|
||||||
|
headphone: number;
|
||||||
|
appeal_id: number;
|
||||||
|
comment_id: number;
|
||||||
|
music_id: number;
|
||||||
|
music_type: number;
|
||||||
|
sort_type: number;
|
||||||
|
narrow_down: number;
|
||||||
|
gauge_option: number;
|
||||||
|
},
|
||||||
|
blaster_energy: number;
|
||||||
|
blaster_count: number;
|
||||||
|
creator_id: number;
|
||||||
|
skill_level: number;
|
||||||
|
skill_name_id: number;
|
||||||
|
gamecoin_packet: number;
|
||||||
|
gamecoin_block: number;
|
||||||
|
|
||||||
|
item: {
|
||||||
|
[id: number]: {
|
||||||
|
type: number,
|
||||||
|
param: number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
packet_booster: number;
|
||||||
|
block_booster: number;
|
||||||
|
}
|
||||||
17
museca@asphyxia/models/scores.ts
Normal file
17
museca@asphyxia/models/scores.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
export interface Scores {
|
||||||
|
collection: 'scores',
|
||||||
|
|
||||||
|
scores: {
|
||||||
|
[mid: string]: {
|
||||||
|
[type: string]: {
|
||||||
|
score: number;
|
||||||
|
count: number;
|
||||||
|
clear_type: number;
|
||||||
|
score_grade: number;
|
||||||
|
btn_rate: number;
|
||||||
|
long_rate: number;
|
||||||
|
vol_rate: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
11
museca@asphyxia/utils.ts
Normal file
11
museca@asphyxia/utils.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
export function IDToCode(id: number) {
|
||||||
|
const padded = _.padStart(id.toString(), 8);
|
||||||
|
return `${padded.slice(0, 4)}-${padded.slice(4)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user