This commit is contained in:
Freddie
2020-05-28 20:46:34 +01:00
parent ff16ea5f96
commit 3a1952a478
8 changed files with 312 additions and 132 deletions

204
asphyxia-core.d.ts vendored
View File

@@ -62,7 +62,12 @@ declare type KAttrMap = { [key: string]: string };
/**
* Supported response encoding
*/
declare type KEncoding = 'shift_jis' | 'utf8' | 'euc-jp' | 'ascii' | 'iso-8859-1';
declare type KEncoding =
| 'shift_jis'
| 'utf8'
| 'euc-jp'
| 'ascii'
| 'iso-8859-1';
/**
* Information about requester
@@ -191,7 +196,11 @@ declare interface EamuseSend {
* pass null or undefined to render static xml
* @param options Response options. See: [[EamuseSendOption]]
*/
xmlFile: (file: string, data?: any, options?: EamuseSendOption) => Promise<void>;
xmlFile: (
file: string,
data?: any,
options?: EamuseSendOption
) => Promise<void>;
/**
* Render and send pug template from a file
@@ -201,13 +210,21 @@ declare interface EamuseSend {
* pass null or undefined to render static xml
* @param options Response options. See: [[EamuseSendOption]]
*/
pugFile: (file: string, data?: any, options?: EamuseSendOption) => Promise<void>;
pugFile: (
file: string,
data?: any,
options?: EamuseSendOption
) => Promise<void>;
}
/**
* Helper type for typing your custom route.
*/
declare type EamusePluginRoute = (req: EamuseInfo, data: any, send: EamuseSend) => Promise<any>;
declare type EamusePluginRoute = (
req: EamuseInfo,
data: any,
send: EamuseSend
) => Promise<any>;
/**
* Helper type for typing your custom route.
@@ -284,7 +301,10 @@ declare namespace R {
*
* Callback can be async function if you want to use await for your DB operations.
*/
function WebUIEvent(event: string, callback: (data: any) => void | Promise<void>): void;
function WebUIEvent(
event: string,
callback: (data: any) => void | Promise<void>
): void;
}
/**
@@ -685,8 +705,16 @@ declare namespace K {
function ITEM(type: 'bool', content: boolean, attr?: KAttrMap): any;
function ITEM(type: KNumberType, content: number, attr?: KAttrMap): any;
function ITEM(type: KBigIntType, content: bigint, attr?: KAttrMap): any;
function ITEM(type: KNumberGroupType, content: number[], attr?: KAttrMap): any;
function ITEM(type: KBigIntGroupType, content: bigint[], attr?: KAttrMap): any;
function ITEM(
type: KNumberGroupType,
content: number[],
attr?: KAttrMap
): any;
function ITEM(
type: KBigIntGroupType,
content: bigint[],
attr?: KAttrMap
): any;
/**
* Example:
@@ -728,7 +756,9 @@ declare namespace IO {
* Asynchronously read a directory.
* @param path A path to a directory.
*/
function ReadDir(path: string): Promise<{ name: string; type: 'file' | 'dir' | 'unsupported' }[]>;
function ReadDir(
path: string
): Promise<{ name: string; type: 'file' | 'dir' | 'unsupported' }[]>;
/**
* Asynchronously writes data to a file, replacing the file if it already exists.
@@ -744,7 +774,10 @@ declare namespace IO {
function WriteFile(
path: string,
data: any,
options: { encoding?: string | null; mode?: number | string; flag?: string } | string | null
options:
| { encoding?: string | null; mode?: number | string; flag?: string }
| string
| null
): Promise<void>;
/**
@@ -788,7 +821,11 @@ declare namespace IO {
*/
function ReadFile(
path: string,
options: { encoding?: string | null; flag?: string } | string | undefined | null
options:
| { encoding?: string | null; flag?: string }
| string
| undefined
| null
): Promise<string | Buffer>;
/**
@@ -827,6 +864,101 @@ declare namespace U {
function GetConfig(key: string): any;
}
/** @ignore */
type Doc<T> = { _id?: string } & T;
/** @ignore */
type Query<T> = {
[P in keyof T]?:
| T[P]
| (T[P] extends Array<infer E>
? { $elemMatch: Query<E[]> } | { $size: number }
: T[P] extends number | string
?
| { $lt: T[P] }
| { $lte: T[P] }
| { $gt: T[P] }
| { $gte: T[P] }
| { $in: T[P][] }
| { $ne: any }
| { $nin: any[] }
| { $exists: boolean }
| { $regex: RegExp }
: T[P] extends object
? Query<T[P]>
: T[P]);
} & {
$or?: Query<T>[];
$and?: Query<T>[];
$not?: Query<T>;
$where?: (this: T) => boolean;
_id?: string;
[path: string]: any;
};
/** @ignore */
type Operators =
| '$exists'
| '$lt'
| '$lte'
| '$gt'
| '$gte'
| '$in'
| '$ne'
| '$nin'
| '$regex';
/** @ignore */
type PickyOperator<T, C, F> = Pick<
{
[P in keyof T]?: T[P] extends C ? F : Omit<T[P], Operators>;
},
{
[P in keyof T]: T[P] extends C ? P : never;
}[keyof T]
>;
/** @ignore */
type ArrayPushOperator<T> = Pick<
{
[P in keyof T]?: T[P] extends Array<infer E>
? E | { $each?: E[]; $slice?: number }
: never;
},
{ [P in keyof T]: T[P] extends Array<any> ? P : never }[keyof T]
> & { [path: string]: any | { $each?: any[]; $slice?: number } };
/** @ignore */
type ArraySetOperator<T> = Pick<
{
[P in keyof T]?: T[P] extends Array<infer E> ? E | { $each: E[] } : never;
},
{ [P in keyof T]: T[P] extends Array<any> ? P : never }[keyof T]
> & { [path: string]: any | { $each: any[] } };
/** @ignore */
type ArrayInOperator<T> = Pick<
{
[P in keyof T]?: T[P] extends Array<infer E> ? E | { $in: E[] } : never;
},
{ [P in keyof T]: T[P] extends Array<any> ? P : never }[keyof T]
> & { [path: string]: any | { $in: any[] } };
/** @ignore */
type ArrayPopOperator<T> = Pick<
{
[P in keyof T]?: T[P] extends Array<any> ? -1 | 1 : never;
},
{ [P in keyof T]: T[P] extends Array<any> ? P : never }[keyof T]
> & { [path: string]: -1 | 1 };
/** @ignore */
type Update<T> = Partial<T> & {
$unset?: PickyOperator<T, number, true> & { [path: string]: true };
$set?: { [P in keyof T]?: Omit<T[P], Operators> } & { [path: string]: any };
$min?: PickyOperator<T, number, number> & { [path: string]: number };
$max?: PickyOperator<T, number, number> & { [path: string]: number };
$inc?: PickyOperator<T, number, number> & { [path: string]: number };
$push?: ArrayPushOperator<T>;
$addToSet?: ArraySetOperator<T>;
$pop?: ArrayPopOperator<T>;
$pull?: ArrayInOperator<T>;
} & {
[path: string]: any;
};
/**
* Database operation.
*
@@ -848,52 +980,52 @@ declare namespace U {
* There will be 16 profiles maximum which is small enough to manage.
*/
declare namespace DB {
function FindOne(refid: string, query: object): Promise<any>;
function FindOne(query: object): Promise<any>;
function FindOne<T>(refid: string, query: Query<T>): Promise<Doc<T>>;
function FindOne<T>(query: Query<T>): Promise<Doc<T>>;
function Find(refid: string | null, query: object): Promise<any>;
function Find(query: object): Promise<any>;
function Find<T>(refid: string | null, query: Query<T>): Promise<Doc<T>[]>;
function Find<T>(query: Query<T>): Promise<Doc<T>[]>;
function Insert(refid: string, doc: object): Promise<any>;
function Insert(doc: object): Promise<any>;
function Insert<T>(refid: string, doc: T): Promise<Doc<T>>;
function Insert<T>(doc: T): Promise<Doc<T>>;
function Remove(refid: string | null, query: object): Promise<number>;
function Remove(query: object): Promise<number>;
function Remove<T>(refid: string | null, query: Query<T>): Promise<number>;
function Remove<T>(query: Query<T>): Promise<number>;
function Update(
function Update<T>(
refid: string | null,
query: object,
update: object
query: Query<T>,
update: Update<T>
): Promise<{
updated: number;
docs: any[];
docs: Doc<T>[];
}>;
function Update(
query: object,
update: object
function Update<T>(
query: Query<T>,
update: Update<T>
): Promise<{
updated: number;
docs: any[];
docs: Doc<T>[];
}>;
function Upsert(
function Upsert<T>(
refid: string | null,
query: object,
update: object
query: Query<T>,
update: Update<T>
): Promise<{
updated: number;
docs: any[];
docs: Doc<T>[];
upsert: boolean;
}>;
function Upsert(
query: object,
update: object
function Upsert<T>(
query: Query<T>,
update: Update<T>
): Promise<{
updated: number;
docs: any[];
docs: Doc<T>[];
upsert: boolean;
}>;
function Count(refid: string | null, query: object): Promise<number>;
function Count(query: object): Promise<number>;
function Count<T>(refid: string | null, query: Query<T>): Promise<number>;
function Count<T>(query: Query<T>): Promise<number>;
}

View File

@@ -1,5 +1,9 @@
import { Profile } from '../models/profile';
import { VersionData } from '../models/version_data';
import { SDVX_AUTOMATION_SONGS } from '../data/vvw';
import { CourseRecord } from '../models/course_record';
import { Item } from '../models/item';
import { Param } from '../models/param';
export const loadScores: EPR = async (info, data, send) => {
const refid = $(data).str('refid');
@@ -8,6 +12,44 @@ export const loadScores: EPR = async (info, data, send) => {
send.pugFile('templates/load_m.pug', { records });
};
export const save: EPR = async (info, data, send) => {
const refid = $(data).str('refid');
await DB.Update<Profile>(
refid,
{ collection: 'profile' },
{
$set: {
appeal: $(data).number('appeal_id'),
musicID: $(data).number('music_id'),
musicType: $(data).number('music_type'),
sortType: $(data).number('sort_type'),
headphone: $(data).number('headphone'),
blasterCount: $(data).number('blaster_count'),
hiSpeed: $(data).number('hispeed'),
laneSpeed: $(data).number('lanespeed'),
gaugeOption: $(data).number('gauge_option'),
arsOption: $(data).number('ars_option'),
notesOption: $(data).number('notes_option'),
earlyLateDisp: $(data).number('early_late_disp'),
drawAdjust: $(data).number('draw_adjust'),
effCLeft: $(data).number('eff_c_left'),
effCRight: $(data).number('eff_c_right'),
narrowDown: $(data).number('narrow_down'),
},
$inc: {
packets: $(data).number('earned_gamecoin_packet'),
blocks: $(data).number('earned_gamecoin_block'),
blasterEnergy: $(data).number('earned_blaster_energy'),
},
}
);
send.success();
};
export const load: EPR = async (info, data, send) => {
const refid = $(data).str('refid');
@@ -21,8 +63,16 @@ export const load: EPR = async (info, data, send) => {
break;
}
const profile = await DB.FindOne(refid, { collection: 'profile' });
let versionData: VersionData = await DB.FindOne(refid, {
const profile = await DB.FindOne<Profile>(refid, {
collection: 'profile',
});
if (!profile) {
send.object({ result: K.ITEM('u8', 1) });
return;
}
let versionData = await DB.FindOne<VersionData>(refid, {
collection: 'version',
});
@@ -30,26 +80,22 @@ export const load: EPR = async (info, data, send) => {
versionData = {
collection: 'version',
version,
items: {},
params: {},
skill: {
base: 0,
level: 0,
name: 0,
},
skillBase: 0,
skillLevel: 0,
skillName: 0,
};
await DB.Insert(refid, versionData);
}
if (!profile) {
send.object({ result: K.ITEM('u8', 1) });
return;
}
const courses = await DB.Find(refid, { collection: 'course' });
const courses = await DB.Find<CourseRecord>(refid, { collection: 'course' });
const items = await DB.Find<Item>(refid, { collection: 'item' });
const params = await DB.Find<Param>(refid, { collection: 'param' });
send.pugFile('templates/load.pug', {
courses,
items,
params,
mixes: version == 5 ? SDVX_AUTOMATION_SONGS : [],
...profile,
...versionData,
});
@@ -66,30 +112,24 @@ export const create: EPR = async (info, data, send) => {
name,
appeal: 0,
akaname: 0,
currency: {
blocks: 0,
packets: 0,
},
settings: {
arsOption: 0,
drawAdjust: 0,
earlyLateDisp: 0,
effCLeft: 0,
effCRight: 1,
gaugeOption: 0,
hiSpeed: 0,
laneSpeed: 0,
narrowDown: 0,
notesOption: 0,
},
state: {
blasterCount: 0,
blasterEnergy: 0,
headphone: 0,
lastMusicID: 0,
lastMusicType: 0,
sortType: 0,
},
blocks: 0,
packets: 0,
arsOption: 0,
drawAdjust: 0,
earlyLateDisp: 0,
effCLeft: 0,
effCRight: 1,
gaugeOption: 0,
hiSpeed: 0,
laneSpeed: 0,
narrowDown: 0,
notesOption: 0,
blasterCount: 0,
blasterEnergy: 0,
headphone: 0,
musicID: 0,
musicType: 0,
sortType: 0,
};
await DB.Upsert(refid, { collection: 'profile' }, profile);

View File

@@ -1,5 +1,5 @@
import { common } from './handlers/common';
import { load, create, loadScores } from './handlers/profile';
import { load, create, loadScores, save } from './handlers/profile';
export function register() {
R.GameCode('KFC');
@@ -12,6 +12,8 @@ export function register() {
R.Route('game.sv4_new', create);
R.Route('game.sv4_frozen', true);
R.Route('game.sv4_load_r', true);
R.Route('game.sv4_save', save);
R.Route('game.sv4_save_m', true);
R.Route('game.sv5_common', common);
}

View File

@@ -0,0 +1,6 @@
export interface Item {
collection: 'item';
type: number;
id: number;
param: number;
}

View File

@@ -0,0 +1,6 @@
export interface Param {
collection: 'param';
type: number;
id: number;
param: number[];
}

View File

@@ -7,30 +7,24 @@ export interface Profile {
appeal: number;
akaname: number;
currency: {
packets: number;
blocks: number;
};
packets: number;
blocks: number;
state: {
lastMusicID: number;
lastMusicType: number;
sortType: number;
headphone: number;
blasterEnergy: number;
blasterCount: number;
};
musicID: number;
musicType: number;
sortType: number;
headphone: number;
blasterEnergy: number;
blasterCount: number;
settings: {
hiSpeed: number;
laneSpeed: number;
gaugeOption: number;
arsOption: number;
notesOption: number;
earlyLateDisp: number;
drawAdjust: number;
effCLeft: number;
effCRight: number;
narrowDown: number;
};
hiSpeed: number;
laneSpeed: number;
gaugeOption: number;
arsOption: number;
notesOption: number;
earlyLateDisp: number;
drawAdjust: number;
effCLeft: number;
effCRight: number;
narrowDown: number;
}

View File

@@ -3,15 +3,8 @@ export interface VersionData {
collection: 'version';
version: number;
skill: {
level: number;
base: number;
name: number;
};
items: {
[key: string]: number;
};
params: {
[key: string]: number[];
};
skillLevel: number;
skillBase: number;
skillName: number;
}

View File

@@ -3,32 +3,32 @@ game
name(__type="str") #{name}
code(__type="str") 1337-6666
sdvx_id(__type="str") 1337-6666
gamecoin_packet(__type="u32") #{currency.packets}
gamecoin_block(__type="u32") #{currency.blocks}
gamecoin_packet(__type="u32") #{packets}
gamecoin_block(__type="u32") #{blocks}
appeal_id(__type="u16") #{appeal}
last_music_id(__type="s32") #{state.lastMusicID}
last_music_type(__type="u8") #{state.lastMusicType}
sort_type(__type="u8") #{state.sortType}
headphone(__type="u8") #{state.headphone}
blaster_energy(__type="u32") #{state.blasterEnergy}
blaster_count(__type="u32") #{state.blasterCount}
last_music_id(__type="s32") #{musicID}
last_music_type(__type="u8") #{musicType}
sort_type(__type="u8") #{sortType}
headphone(__type="u8") #{headphone}
blaster_energy(__type="u32") #{blasterEnergy}
blaster_count(__type="u32") #{blasterCount}
hispeed(__type="s32") #{settings.hiSpeed}
lanespeed(__type="u32") #{settings.laneSpeed}
gauge_option(__type="u8") #{settings.gaugeOption}
ars_option(__type="u8") #{settings.arsOption}
notes_option(__type="u8") #{settings.notesOption}
early_late_disp(__type="u8") #{settings.earlyLateDisp}
draw_adjust(__type="s32") #{settings.drawAdjust}
eff_c_left(__type="u8") #{settings.effCLeft}
eff_c_right(__type="u8") #{settings.effCRight}
narrow_down(__type="u8") #{settings.narrowDown}
hispeed(__type="s32") #{hiSpeed}
lanespeed(__type="u32") #{laneSpeed}
gauge_option(__type="u8") #{gaugeOption}
ars_option(__type="u8") #{arsOption}
notes_option(__type="u8") #{notesOption}
early_late_disp(__type="u8") #{earlyLateDisp}
draw_adjust(__type="s32") #{drawAdjust}
eff_c_left(__type="u8") #{effCLeft}
eff_c_right(__type="u8") #{effCRight}
narrow_down(__type="u8") #{narrowDown}
kac_id(__type="str") #{name}
skill_level(__type="s16") #{skill.level}
skill_base_id(__type="s16") #{skill.base}
skill_name_id(__type="s16") #{skill.name}
skill_level(__type="s16") #{skillLevel}
skill_base_id(__type="s16") #{skillBase}
skill_name_id(__type="s16") #{skillName}
ea_shop
packet_booster(__type="s32") 1
@@ -59,6 +59,13 @@ game
id(__type="u32") #{item.id}
param(__type="u32") #{item.param}
//- Unlock automation songs
each song in mixes
info
type(__type="u8") 15
id(__type="u32") #{song}
param(__type="u32") 1
param
each param in params
info