working save data

This commit is contained in:
GEEKiDoS
2024-04-09 16:14:04 +08:00
parent 1fa7d578fe
commit 83e63acc94
7 changed files with 315 additions and 191 deletions
+44 -63
View File
@@ -1,72 +1,53 @@
import { Binary } from "mongodb";
export interface PlayerInfo {
_id: string;
rivals: string[];
pointCount: number;
customize: {
2: string;
3: string;
4: string;
5: string;
6: string;
7: string;
8: string;
11: string;
10: string;
},
otherCustomize: {
1: string;
2: string;
3: string;
4: string;
5: string;
}
}
import { Binary, ObjectId } from "mongodb";
export interface PlayerPlayData {
_id: string;
// konami binary xml
pdata: Binary;
checksum: string;
// sha256 to ^
check_sum: string;
}
export interface PlayerMusicData {
player: string;
musicId: string;
clearFlag: {
spb: number;
spn: number;
sph: number;
spa: number;
spl: number;
dpb: number;
dpn: number;
dph: number;
dpa: number;
dpl: number;
};
score: {
spb: number;
spn: number;
sph: number;
spa: number;
spl: number;
dpb: number;
dpn: number;
dph: number;
dpa: number;
dpl: number;
};
missCount: {
spb: number;
spn: number;
sph: number;
spa: number;
spl: number;
dpb: number;
dpn: number;
dph: number;
dpa: number;
dpl: number;
};
music_id: number;
play_style: number;
// 1 = B, 5 = L, etc
score: number[];
clear_flag: number[];
miss_count: number[];
play_num: number[];
clear_num: number[];
}
export interface PlayerPlayLog {
_id: ObjectId,
player: string;
clock: number,
music_id: number,
note_id: number,
score: number,
pgreat_count: number,
great_count: number,
miss_count: number,
clear_flag: number,
stage: number,
groove_gauge: number,
mode_id: number,
mode_sub_id: number,
fail_detail: number,
ghost_check_sum: string,
update_my_best_score: boolean,
is_limit_score: boolean,
rival_infinitas_id: string,
is_compe: boolean,
compe_id: number,
compe_music_index: number
valid_best_option: boolean,
arrange_0: number,
arrange_1: number,
assist: number,
flip: number,
ghost: Buffer,
};
+3 -2
View File
@@ -109,11 +109,12 @@ async function main(): Promise<void> {
}
logger.info(
'%s.%s [%s]: request = %s',
'%s %s.%s [%s]: request = %o',
ctx.url,
ctx.service.name,
ctx.service.method,
ctx.token,
JSON.stringify(ctx.body),
ctx.body,
);
let method = ctx.service.method;
+20 -7
View File
@@ -6,10 +6,15 @@ import { XMLParser } from 'fast-xml-parser';
const parser = new XMLParser({
ignoreAttributes: false,
parseAttributeValue: true,
parseAttributeValue: false,
attributeNamePrefix: '$',
removeNSPrefix: true,
allowBooleanAttributes: true,
numberParseOptions: {
hex: false,
leadingZeros: false,
eNotation: false,
skipLike: /.*/,
},
});
function parseValue(node: { $__type: string; $__count?: unknown }): any {
@@ -25,15 +30,21 @@ function parseValue(node: { $__type: string; $__count?: unknown }): any {
'u32',
's64',
'u64',
'float',
'double',
].includes(node.$__type)
) {
if (isArray) {
return node['#text'].split(' ').map((v) => new Number(v));
return node['#text'].split(' ').map((v) => parseInt(v));
}
return new Number(node['#text']);
return parseInt(node['#text']);
}
if (['float', 'double'].includes(node.$__type)) {
if (isArray) {
return node['#text'].split(' ').map((v) => parseFloat(v));
}
return parseFloat(node['#text']);
}
if (['b', 'bool'].includes(node.$__type)) {
@@ -106,7 +117,9 @@ export async function eacnet(ctx: Context, next: Next): Promise<any> {
'base64'
);
const decoded = LZ77.decompress(buffer);
const xmlResult = kxmlToObject(parser.parse(to_xml(decoded).data));
const xml = to_xml(decoded).data;
const parsedXml = parser.parse(xml);
const xmlResult = kxmlToObject(parsedXml);
const game = Object.keys(xmlResult)[0];
+82 -80
View File
@@ -88,10 +88,8 @@
3013,
3018,
4000,
4001,
4003,
4004,
4005,
4006,
4007,
4008,
@@ -114,7 +112,6 @@
5009,
5011,
5012,
5014,
5015,
5016,
5017,
@@ -164,7 +161,6 @@
7026,
7032,
7036,
7038,
7039,
8001,
8003,
@@ -180,7 +176,6 @@
8020,
8022,
8023,
8024,
8025,
8026,
8028,
@@ -214,14 +209,12 @@
9030,
9033,
9037,
9038,
9042,
9043,
9044,
9045,
9046,
9048,
9051,
9052,
9054,
9057,
@@ -265,7 +258,6 @@
11009,
11010,
11011,
11012,
11013,
11014,
11015,
@@ -273,7 +265,6 @@
11026,
11027,
11028,
11032,
11035,
11036,
11037,
@@ -285,7 +276,6 @@
11052,
12000,
12001,
12002,
12003,
12004,
12005,
@@ -293,13 +283,11 @@
12007,
12008,
12009,
12010,
12011,
12012,
12013,
12014,
12015,
12016,
12018,
12019,
12020,
@@ -321,7 +309,6 @@
12050,
12052,
12053,
12054,
13000,
13001,
13002,
@@ -330,7 +317,6 @@
13006,
13008,
13009,
13010,
13011,
13012,
13013,
@@ -351,7 +337,6 @@
13035,
13036,
13037,
13038,
13039,
13040,
13041,
@@ -368,12 +353,10 @@
14000,
14001,
14003,
14004,
14005,
14006,
14007,
14008,
14009,
14011,
14012,
14014,
@@ -384,7 +367,6 @@
14019,
14020,
14021,
14022,
14023,
14024,
14025,
@@ -398,32 +380,23 @@
14034,
14038,
14045,
14046,
14047,
14048,
14049,
14050,
14051,
14052,
14053,
14055,
14056,
15000,
15001,
15002,
15003,
15004,
15005,
15006,
15007,
15008,
15009,
15010,
15011,
15012,
15013,
15014,
15015,
15016,
15017,
15018,
@@ -431,10 +404,7 @@
15020,
15021,
15022,
15023,
15024,
15025,
15026,
15028,
15031,
15032,
@@ -445,21 +415,16 @@
15039,
15040,
15044,
15045,
15047,
15048,
15049,
15050,
15051,
15052,
15054,
15056,
15057,
15058,
15059,
15061,
16000,
16001,
16003,
16004,
16005,
@@ -467,24 +432,18 @@
16008,
16009,
16010,
16011,
16012,
16013,
16014,
16015,
16016,
16017,
16018,
16019,
16020,
16021,
16022,
16023,
16024,
16025,
16026,
16029,
16031,
16032,
16035,
16036,
@@ -492,12 +451,8 @@
16039,
16040,
16041,
16042,
16043,
16044,
16045,
16047,
16050,
16051,
16052,
16053,
@@ -529,7 +484,6 @@
17025,
17026,
17027,
17028,
17030,
17031,
17032,
@@ -552,7 +506,6 @@
17056,
17058,
17059,
17060,
17062,
17064,
17065,
@@ -566,7 +519,6 @@
18008,
18009,
18010,
18011,
18012,
18013,
18014,
@@ -579,7 +531,6 @@
18022,
18023,
18024,
18025,
18026,
18027,
18028,
@@ -671,7 +622,6 @@
19060,
19061,
19062,
19063,
19064,
19065,
19067,
@@ -681,7 +631,6 @@
19071,
19072,
19073,
19074,
19075,
20000,
20001,
@@ -702,12 +651,10 @@
20016,
20017,
20018,
20019,
20020,
20021,
20022,
20023,
20024,
20025,
20027,
20028,
@@ -721,7 +668,6 @@
20036,
20037,
20038,
20039,
20040,
20041,
20042,
@@ -747,7 +693,6 @@
20065,
20066,
20067,
20068,
20069,
20070,
20071,
@@ -772,7 +717,6 @@
20097,
20098,
20099,
20100,
20101,
20102,
21001,
@@ -786,7 +730,6 @@
21009,
21010,
21011,
21012,
21014,
21015,
21016,
@@ -801,7 +744,6 @@
21026,
21027,
21028,
21029,
21030,
21032,
21033,
@@ -815,17 +757,13 @@
21045,
21046,
21047,
21048,
21049,
21050,
21051,
21052,
21053,
21054,
21056,
21057,
21058,
21059,
21060,
21061,
21062,
@@ -835,10 +773,8 @@
21066,
21067,
21068,
21069,
21070,
21071,
21073,
21074,
21075,
21076,
@@ -853,21 +789,17 @@
21086,
21087,
21088,
21089,
21090,
22001,
22002,
22003,
22004,
22005,
22006,
22007,
22008,
22009,
22010,
22011,
22012,
22013,
22014,
22015,
22016,
@@ -876,13 +808,10 @@
22019,
22020,
22023,
22024,
22025,
22026,
22027,
22028,
22029,
22031,
22032,
22033,
22034,
@@ -928,7 +857,6 @@
22082,
22087,
22088,
22089,
22090,
22091,
22092,
@@ -968,7 +896,6 @@
23028,
23029,
23030,
23031,
23032,
23034,
23035,
@@ -989,7 +916,6 @@
23051,
23052,
23053,
23054,
23055,
23056,
23057,
@@ -1003,7 +929,6 @@
23067,
23068,
23069,
23070,
23074,
23075,
23076,
@@ -1020,7 +945,6 @@
23092,
23093,
23094,
23095,
24000,
24001,
24002,
@@ -1032,7 +956,6 @@
24008,
24009,
24010,
24011,
24012,
24013,
24014,
@@ -1061,7 +984,6 @@
24038,
24039,
24040,
24041,
24042,
24043,
24044,
@@ -1069,7 +991,6 @@
24046,
24047,
24048,
24050,
24051,
24053,
24054,
@@ -1364,7 +1285,6 @@
27112,
27113,
27114,
27116,
27117,
28002,
28005,
@@ -1537,5 +1457,87 @@
80049,
80050,
80051
],
"lmusics": [
4001,
4005,
5014,
7038,
8024,
9038,
9051,
11012,
11032,
12002,
12010,
12016,
12054,
13010,
13038,
14004,
14009,
14022,
14046,
14053,
15000,
15004,
15005,
15007,
15008,
15014,
15015,
15023,
15025,
15026,
15045,
15054,
15061,
16000,
16001,
16011,
16015,
16018,
16022,
16025,
16031,
16042,
16045,
16047,
16050,
17028,
17060,
18011,
18025,
19063,
19074,
20019,
20024,
20039,
20068,
20100,
21012,
21029,
21048,
21050,
21052,
21059,
21069,
21073,
21089,
22006,
22008,
22013,
22024,
22027,
22031,
22089,
23031,
23054,
23070,
23095,
24011,
24041,
24050,
27116
]
}
+15 -7
View File
@@ -16,7 +16,7 @@ function Combine(...modules: ({ new(): any })[]) {
modules.forEach(v => {
const descriptors = Object.getOwnPropertyDescriptors(v.prototype);
for(const name in descriptors) {
for (const name in descriptors) {
if (name === 'constructor')
continue;
@@ -40,9 +40,17 @@ export default class extends Combine(Service, User, Game) {
}
export const ITEM_LIST = data.items;
export const MUSIC_LIST = data.musics.map(id => ({
music_id: v.s32(id),
kind: v.s32(1),
note_bit: v.s32(0),
music_pack_item_id: v.str('')
}));
export const MUSIC_LIST = [
...data.musics.map(id => ({
music_id: v.s32(id),
kind: v.s32(1),
note_bit: v.s32(0),
music_pack_item_id: v.str('')
})),
...data.lmusics.map(id => ({
music_id: v.s32(id),
kind: v.s32(2),
note_bit: v.s32(1),
music_pack_item_id: v.str('')
})),
];
+142 -32
View File
@@ -3,7 +3,8 @@ import { eacnet } from "../../decorators/eacnet.js";
import { Context } from "../../types.js";
import { v } from "../../utils/kxml-value.js";
import { ITEM_LIST, MUSIC_LIST } from "./index.js";
import { PlayerMusicData, PlayerPlayData } from "../../database/index.js";
import { PlayerMusicData, PlayerPlayData, PlayerPlayLog } from "../../database/index.js";
import { fromToken } from "../../utils/laochan-id.js";
export class User {
db: Db;
@@ -12,10 +13,14 @@ export class User {
return this.db.collection<PlayerPlayData>('player_play_data');
}
get playMusicCol() {
get musicDataCol() {
return this.db.collection<PlayerMusicData>('player_music_data');
}
get playLogCol() {
return this.db.collection<PlayerPlayLog>('player_play_log');
}
@eacnet('p2d')
async getCustomizeSetting() {
return {
@@ -58,7 +63,11 @@ export class User {
status: v.s32(0),
error: v.s32(0),
result: {
point_count: v.s32(114514),
point_count: v.s32(1),
point: [{
point_id: v.str('P0100000'),
point_num: v.u32(114514),
}]
}
}
}
@@ -85,16 +94,79 @@ export class User {
}
}
@eacnet('p2d')
async reportMusicResult(ctx: Context) {
const result = ctx.body as PlayerPlayLog;
result.player = ctx.token;
let updateTask = Promise.resolve();
const play_style = Math.floor(result.note_id / 5);
const diff = result.note_id % 5;
updateTask = (async () => {
const musicData = (await this.musicDataCol.findOne({
player: result.player,
music_id: result.music_id,
play_style: play_style
})) ?? {
player: result.player,
music_id: result.music_id,
play_style: play_style,
score: [0, 0, 0, 0, 0],
clear_flag: [0, 0, 0, 0, 0],
miss_count: [0, 0, 0, 0, 0],
play_num: [0, 0, 0, 0, 0],
clear_num: [0, 0, 0, 0, 0],
};
if (result.clear_flag > musicData.clear_flag[diff])
musicData.clear_flag[diff] = result.clear_flag;
if (result.miss_count < musicData.miss_count[diff])
musicData.miss_count[diff] = result.miss_count;
if (result.score > musicData.score[diff])
musicData.score[diff] = result.score;
if (result.clear_flag >= 2)
musicData.clear_num[diff]++;
musicData.play_num[diff]++;
await this.musicDataCol.updateOne({
player: result.player,
music_id: result.music_id,
play_style: play_style
}, {
$set: musicData
}, {
upsert: true
});
})();
await Promise.all([
this.playLogCol.insertOne(result),
updateTask,
])
return {
status: v.s32(0),
error: v.s32(0),
};
}
@eacnet('p2d')
async savePlayData(ctx: Context) {
const uid = ctx.token;
const { pdata, checksum } = ctx.body as { pdata: Buffer, checksum: string };
const { pdata, check_sum } = ctx.body as { pdata: Buffer, check_sum: string };
await this.playDataCol
.updateOne({ _id: uid }, {
$set: {
pdata: new Binary(pdata),
checksum: checksum,
check_sum,
}
});
@@ -122,6 +194,9 @@ export class User {
status: v.s32(0),
error: v.s32(0),
result: {
size: v.s32(result.pdata.length()),
rest_size: v.s32(0),
check_sum: v.str(result.check_sum),
pdata: v.bin(result.pdata.buffer),
}
}
@@ -130,12 +205,10 @@ export class User {
@eacnet('p2d')
async registPlayer(ctx: Context) {
const uid = ctx.token;
const { pdata, checksum } = ctx.body as { pdata: Buffer, checksum: string };
const { pdata, check_sum } = ctx.body as { pdata: Buffer, check_sum: string };
await this.playDataCol
.insertOne({ _id: uid, pdata: new Binary(pdata), checksum });
// this.userDataSaveTemp.set(uid, { pdata, checksum });
.insertOne({ _id: uid, pdata: new Binary(pdata), check_sum });
return {
status: v.s32(0),
@@ -143,6 +216,53 @@ export class User {
}
}
@eacnet('p2d')
async checkPlayData(ctx: Context) {
const { check_sum } = ctx.body as { check_sum: string };
const data = await this.playDataCol.findOne({ _id: ctx.token }, {
projection: {
check_sum: 1,
}
});
const id = fromToken(ctx.token);
if (!data) {
return {
status: v.s32(0),
error: v.s32(0),
result: {
infinitas_id: v.str(id),
valid: v.bool(false),
is_exist: v.bool(false),
}
};
}
if (data.check_sum !== check_sum) {
return {
status: v.s32(0),
error: v.s32(0),
result: {
infinitas_id: v.str(id),
valid: v.bool(false),
is_exist: v.bool(true),
}
};
}
return {
status: v.s32(0),
error: v.s32(0),
result: {
infinitas_id: v.str(id),
valid: v.bool(true),
is_exist: v.bool(true),
}
};
}
@eacnet('p2d')
async getRivalInfo() {
return {
@@ -163,7 +283,7 @@ export class User {
error: v.s32(0),
result: {
status: v.s32(0),
check_sum: v.str('f57959c468c9c59c47a4cead973f59fbec72eaa53a790c5b792222148e69c19d'),
check_sum: v.str('adb004981ab29df534ef1d8b5e6216b447042f798010c2c1f233eebc058e1b67'),
music_list: {
music_num: v.s32(MUSIC_LIST.length),
music: MUSIC_LIST,
@@ -185,38 +305,28 @@ export class User {
async getMusicData(ctx: Context) {
const { play_style } = ctx.body as { play_style: number };
const musicDatas = await this.musicDataCol.find({
player: ctx.token,
play_style,
}).toArray();
return {
status: v.s32(0),
error: v.s32(0),
play_style: v.s32(play_style),
result: {
music: MUSIC_LIST.map(music => ({
music_id: music.music_id,
score: v.s32([9999, 9999, 9999, 9999]),
clear_flag: v.s32([7, 7, 7, 7]),
miss_count: v.s32([0, 0, 0, 0]),
play_num: v.s32([1, 1, 1 ,1]),
clear_num: v.s32([1, 1, 1 ,1]),
music: musicDatas.map(data => ({
music_id: v.s32(data.music_id),
score: v.s32(data.score),
clear_flag: v.s32(data.clear_flag),
miss_count: v.s32(data.miss_count),
play_num: v.s32(data.play_num),
clear_num: v.s32(data.clear_num),
}))
},
}
}
@eacnet('p2d')
async checkPlayData(ctx: Context) {
const count = await this.playDataCol.countDocuments({ _id: ctx.token });
return {
status: v.s32(0),
error: v.s32(0),
result: {
infinitas_id: v.str(ctx.token),
valid: v.bool(count),
is_exist: v.bool(count),
}
};
}
@eacnet('p2d')
async getItemList() {
return {
+9
View File
@@ -0,0 +1,9 @@
import { createHash } from 'crypto';
export function fromToken(token: string) {
const key = createHash('md5')
.update(token, 'utf-8')
.digest('hex');
return ('LCHAN' + key).slice(0, 13);
}