mirror of
https://github.com/asphyxia-core/plugins.git
synced 2026-04-25 16:21:44 -05:00
Merge pull request #1 from thomeval/bug/39_twoPlayerSave
Bug/39 two player save
This commit is contained in:
commit
b7377a3d0d
1
gitadora@asphyxia/.gitignore
vendored
Normal file
1
gitadora@asphyxia/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
apisamples/
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
GITADORA Plugin for Asphyxia-Core
|
GITADORA Plugin for Asphyxia-Core
|
||||||
=================================
|
=================================
|
||||||

|

|
||||||
|
|
||||||
This plugin is based on converted from public-exported Asphyxia's Routes.
|
This plugin is based on converted from public-exported Asphyxia's Routes.
|
||||||
|
|
||||||
|
|
@ -14,10 +14,10 @@ Supported Versions
|
||||||
When Plugin Doesn't work correctly / Startup Error on Plugin
|
When Plugin Doesn't work correctly / Startup Error on Plugin
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
The folder structure between v1.0 and v1.1 is quite different. Do not overwrite plugin folder.
|
The folder structure between v1.0 and v1.1 is quite different. Do not overwrite plugin folder.
|
||||||
<br>If encounter error, Please try these step:
|
<br>If you encounter errors, Please try these steps:
|
||||||
|
|
||||||
1. Remove `gitadora@asphyxia` folder.
|
1. Remove `gitadora@asphyxia` folder.
|
||||||
2. C-C and C-V the newest version of `gitadora@asphyxia`
|
2. Ctrl-C and Ctrl-V the newest version of `gitadora@asphyxia`
|
||||||
3. (Custom MDB Users) Reupload MDB or move `data/custom_mdb.xml` to `data/mdb/custom.xml`
|
3. (Custom MDB Users) Reupload MDB or move `data/custom_mdb.xml` to `data/mdb/custom.xml`
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -29,7 +29,20 @@ Known Issues
|
||||||
|
|
||||||
Release Notes
|
Release Notes
|
||||||
=============
|
=============
|
||||||
v1.1.1 (Current)
|
|
||||||
|
v1.2.0
|
||||||
|
----------------
|
||||||
|
* Fixed server error when saving profiles for two Guitar Freaks players at the end of a session. Fixes Github issue #39.
|
||||||
|
* Fixed another server error when two players are present, but only one player is using a profile.
|
||||||
|
* Added support for the "ranking" field. Gitadora will now correctly display your server ranking (based on Skill) on the post-game screen.
|
||||||
|
* "Recommended to friends" songs are now saved and loaded correctly. Since you don't have any friends, this won't be terribly useful, but it does at least provide an extra five slots for saving your favourite songs.
|
||||||
|
* Fixed "Recommended to friends" song list being incorrectly initialized to "I think about you".
|
||||||
|
* misc: Added logging for profile loading/saving when Asphyxia is running in dev mode.
|
||||||
|
* misc: Added more logging to mdb (song database) loading.
|
||||||
|
* misc: Removed some unneeded duplicate code.
|
||||||
|
* misc: Latest getPlayer() and savePlayers() API requests and responses are now saved to file when Asphyxia is in dev mode. Useful for debugging.
|
||||||
|
|
||||||
|
v1.1.1
|
||||||
----------------
|
----------------
|
||||||
* fix: Error when create new profile on exchain.
|
* fix: Error when create new profile on exchain.
|
||||||
* fix: last song doesn't work correctly.
|
* fix: last song doesn't work correctly.
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import Logger from "../../utils/logger";
|
||||||
|
|
||||||
export interface CommonMusicDataField {
|
export interface CommonMusicDataField {
|
||||||
id: KITEM<"s32">;
|
id: KITEM<"s32">;
|
||||||
cont_gf: KITEM<"bool">;
|
cont_gf: KITEM<"bool">;
|
||||||
|
|
@ -21,13 +23,17 @@ export enum DATAVersion {
|
||||||
|
|
||||||
type processRawDataHandler = (path: string) => Promise<CommonMusicData>
|
type processRawDataHandler = (path: string) => Promise<CommonMusicData>
|
||||||
|
|
||||||
|
const logger = new Logger("mdb")
|
||||||
|
|
||||||
export async function readXML(path: string) {
|
export async function readXML(path: string) {
|
||||||
|
logger.debugInfo(`Loading MDB data from ${path}.`)
|
||||||
const xml = await IO.ReadFile(path, 'utf-8');
|
const xml = await IO.ReadFile(path, 'utf-8');
|
||||||
const json = U.parseXML(xml, false)
|
const json = U.parseXML(xml, false)
|
||||||
return json
|
return json
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function readJSON(path: string) {
|
export async function readJSON(path: string) {
|
||||||
|
logger.debugInfo(`Loading MDB data from ${path}.`)
|
||||||
const str = await IO.ReadFile(path, 'utf-8');
|
const str = await IO.ReadFile(path, 'utf-8');
|
||||||
const json = JSON.parse(str)
|
const json = JSON.parse(str)
|
||||||
return json
|
return json
|
||||||
|
|
@ -35,16 +41,19 @@ export async function readJSON(path: string) {
|
||||||
|
|
||||||
export async function readJSONOrXML(jsonPath: string, xmlPath: string, processHandler: processRawDataHandler): Promise<CommonMusicData> {
|
export async function readJSONOrXML(jsonPath: string, xmlPath: string, processHandler: processRawDataHandler): Promise<CommonMusicData> {
|
||||||
if (!IO.Exists(jsonPath)) {
|
if (!IO.Exists(jsonPath)) {
|
||||||
|
logger.debugInfo(`Loading MDB data from ${xmlPath}.`)
|
||||||
const data = await processHandler(xmlPath)
|
const data = await processHandler(xmlPath)
|
||||||
await IO.WriteFile(jsonPath, JSON.stringify(data))
|
await IO.WriteFile(jsonPath, JSON.stringify(data))
|
||||||
return data
|
return data
|
||||||
} else {
|
} else {
|
||||||
|
logger.debugInfo(`Loading MDB data from ${jsonPath}.`)
|
||||||
const json = JSON.parse(await IO.ReadFile(jsonPath, 'utf-8'))
|
const json = JSON.parse(await IO.ReadFile(jsonPath, 'utf-8'))
|
||||||
return json
|
return json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function readB64JSON(b64path: string) {
|
export async function readB64JSON(b64path: string) {
|
||||||
|
logger.debugInfo(`Loading MDB data from ${b64path}.`)
|
||||||
const buff = await IO.ReadFile(b64path, 'utf-8');
|
const buff = await IO.ReadFile(b64path, 'utf-8');
|
||||||
return JSON.parse(Buffer.from(buff, 'base64').toString('utf-8'));
|
return JSON.parse(Buffer.from(buff, 'base64').toString('utf-8'));
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +75,7 @@ export function gameVerToDataVer(ver: string): DATAVersion {
|
||||||
export async function processDataBuilder(gameVer: string, processHandler?: processRawDataHandler) {
|
export async function processDataBuilder(gameVer: string, processHandler?: processRawDataHandler) {
|
||||||
const ver = gameVerToDataVer(gameVer)
|
const ver = gameVerToDataVer(gameVer)
|
||||||
const base = `data/mdb/${ver}`
|
const base = `data/mdb/${ver}`
|
||||||
if (IO.Exists(`${base}.b64`)) {
|
if (IO.Exists(`${base}.b64`)) {
|
||||||
return await readB64JSON(`${base}.b64`);
|
return await readB64JSON(`${base}.b64`);
|
||||||
}
|
}
|
||||||
const { music } = await readJSONOrXML(`${base}.json`, `${base}.xml`, processHandler ?? defaultProcessRawData)
|
const { music } = await readJSONOrXML(`${base}.json`, `${base}.xml`, processHandler ?? defaultProcessRawData)
|
||||||
|
|
@ -74,7 +83,6 @@ export async function processDataBuilder(gameVer: string, processHandler?: proce
|
||||||
return { music };
|
return { music };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function defaultProcessRawData(path: string): Promise<CommonMusicData> {
|
export async function defaultProcessRawData(path: string): Promise<CommonMusicData> {
|
||||||
const data = await readXML(path)
|
const data = await readXML(path)
|
||||||
const mdb = $(data).elements("mdb.mdb_data");
|
const mdb = $(data).elements("mdb.mdb_data");
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ export const playableMusic: EPR = async (info, data, send) => {
|
||||||
music = _.get(await processDataBuilder(version), 'music', []);
|
music = _.get(await processDataBuilder(version), 'music', []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
await send.object({
|
await send.object({
|
||||||
hot: {
|
hot: {
|
||||||
major: K.ITEM('s32', 1),
|
major: K.ITEM('s32', 1),
|
||||||
|
|
|
||||||
|
|
@ -1,94 +1,78 @@
|
||||||
import { PlayerInfo } from "../models/playerinfo";
|
import { PlayerInfo } from "../models/playerinfo";
|
||||||
|
import { PlayerRanking } from "../models/playerranking";
|
||||||
import { Profile } from "../models/profile";
|
import { Profile } from "../models/profile";
|
||||||
import { Record } from "../models/record";
|
import { Record } from "../models/record";
|
||||||
import { Extra } from "../models/extra";
|
import { Extra } from "../models/extra";
|
||||||
import { getVersion, isDM } from "../utils";
|
import { getVersion, isDM } from "../utils";
|
||||||
import { Scores } from "../models/scores";
|
import { Scores } from "../models/scores";
|
||||||
import { PLUGIN_VER } from "../const";
|
import { PLUGIN_VER } from "../const";
|
||||||
|
import Logger from "../utils/logger"
|
||||||
|
import { isAsphyxiaDebugMode } from "../Utils/index";
|
||||||
|
|
||||||
|
const logger = new Logger("profiles")
|
||||||
|
|
||||||
export const regist: EPR = async (info, data, send) => {
|
export const regist: EPR = async (info, data, send) => {
|
||||||
|
|
||||||
const refid = $(data).str('player.refid');
|
const refid = $(data).str('player.refid');
|
||||||
if (!refid) return send.deny();
|
if (!refid) {
|
||||||
|
logger.error("Request data is missing required parameter: player.refid")
|
||||||
|
return send.deny();
|
||||||
|
}
|
||||||
|
|
||||||
const no = getPlayerNo(data);
|
const no = getPlayerNo(data);
|
||||||
const version = getVersion(info);
|
const version = getVersion(info);
|
||||||
|
const playerInfo = await getOrRegisterPlayerInfo(refid, version, no);
|
||||||
|
|
||||||
const playerInfo = await DB.FindOne<PlayerInfo>(refid, {
|
await send.object({
|
||||||
collection: 'playerinfo',
|
player: K.ATTR({ no: `${no}` }, {
|
||||||
version
|
is_succession: K.ITEM("bool", 0), //FIX THIS with upsert result.
|
||||||
|
did: K.ITEM("s32", playerInfo.id)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
if (playerInfo) {
|
|
||||||
send.object({
|
|
||||||
player: K.ATTR({ no: `${no}` }, {
|
|
||||||
is_succession: K.ITEM("bool", 0), //FIX THIS with upsert result.
|
|
||||||
did: K.ITEM("s32", playerInfo.id)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
let info = await registerUser(refid, version)
|
|
||||||
send.object({
|
|
||||||
player: K.ATTR({ no: `${no}` }, {
|
|
||||||
is_succession: K.ITEM("bool", 0), //FIX THIS with upsert result.
|
|
||||||
did: K.ITEM("s32", info.id)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const check: EPR = async (info, data, send) => {
|
export const check: EPR = async (info, data, send) => {
|
||||||
|
|
||||||
const refid = $(data).str('player.refid');
|
const refid = $(data).str('player.refid');
|
||||||
if (!refid) return send.deny();
|
if (!refid) {
|
||||||
|
logger.error("Request data is missing required parameter: player.refid")
|
||||||
|
return send.deny();
|
||||||
|
}
|
||||||
|
|
||||||
const no = getPlayerNo(data);
|
const no = getPlayerNo(data);
|
||||||
const version = getVersion(info)
|
const version = getVersion(info)
|
||||||
|
const playerInfo = await getOrRegisterPlayerInfo(refid, version, no)
|
||||||
|
|
||||||
const playerInfo = await DB.FindOne<PlayerInfo>(refid, {
|
await send.object({
|
||||||
collection: 'playerinfo',
|
player: K.ATTR({ no: `${no}`, state: '2' }, {
|
||||||
version
|
name: K.ITEM('str', playerInfo.name),
|
||||||
|
charaid: K.ITEM('s32', 0),
|
||||||
|
did: K.ITEM('s32', playerInfo.id),
|
||||||
|
skilldata: {
|
||||||
|
skill: K.ITEM('s32', 0),
|
||||||
|
all_skill: K.ITEM('s32', 0),
|
||||||
|
old_skill: K.ITEM('s32', 0),
|
||||||
|
old_all_skill: K.ITEM('s32', 0),
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
if (playerInfo) {
|
|
||||||
send.object({
|
|
||||||
player: K.ATTR({ no: `${no}`, state: '2' }, {
|
|
||||||
name: K.ITEM('str', playerInfo.name),
|
|
||||||
charaid: K.ITEM('s32', 0),
|
|
||||||
did: K.ITEM('s32', playerInfo.id),
|
|
||||||
skilldata: {
|
|
||||||
skill: K.ITEM('s32', 0),
|
|
||||||
all_skill: K.ITEM('s32', 0),
|
|
||||||
old_skill: K.ITEM('s32', 0),
|
|
||||||
old_all_skill: K.ITEM('s32', 0),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
let info = await registerUser(refid, version)
|
|
||||||
send.object({
|
|
||||||
player: K.ATTR({ no: `${no}`, state: '2' }, {
|
|
||||||
name: K.ITEM('str', info.name),
|
|
||||||
charaid: K.ITEM('s32', 0),
|
|
||||||
did: K.ITEM('s32', info.id),
|
|
||||||
skilldata: {
|
|
||||||
skill: K.ITEM('s32', 0),
|
|
||||||
all_skill: K.ITEM('s32', 0),
|
|
||||||
old_skill: K.ITEM('s32', 0),
|
|
||||||
old_all_skill: K.ITEM('s32', 0),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getPlayer: EPR = async (info, data, send) => {
|
export const getPlayer: EPR = async (info, data, send) => {
|
||||||
const refid = $(data).str('player.refid');
|
const refid = $(data).str('player.refid');
|
||||||
if (!refid) return send.deny();
|
if (!refid) {
|
||||||
|
logger.error("Request data is missing required parameter: player.refid")
|
||||||
|
return send.deny();
|
||||||
|
}
|
||||||
|
|
||||||
const no = getPlayerNo(data);
|
const no = getPlayerNo(data);
|
||||||
const version = getVersion(info);
|
const version = getVersion(info);
|
||||||
const time = BigInt(31536000);
|
const time = BigInt(31536000);
|
||||||
const dm = isDM(info);
|
const dm = isDM(info);
|
||||||
|
const game = dm ? 'dm' : 'gf';
|
||||||
|
|
||||||
|
logger.debugInfo(`Loading ${game} profile for player ${no} with refid: ${refid}`)
|
||||||
const name = await DB.FindOne<PlayerInfo>(refid, {
|
const name = await DB.FindOne<PlayerInfo>(refid, {
|
||||||
collection: 'playerinfo',
|
collection: 'playerinfo',
|
||||||
version
|
version
|
||||||
|
|
@ -343,6 +327,7 @@ export const getPlayer: EPR = async (info, data, send) => {
|
||||||
list_2: K.ARRAY('s32', extra.list_2),
|
list_2: K.ARRAY('s32', extra.list_2),
|
||||||
list_3: K.ARRAY('s32', extra.list_3),
|
list_3: K.ARRAY('s32', extra.list_3),
|
||||||
},
|
},
|
||||||
|
recommend_musicid_list: K.ARRAY('s32', extra.recommend_musicid_list ?? Array(5).fill(-1)),
|
||||||
record,
|
record,
|
||||||
groove: {
|
groove: {
|
||||||
extra_gauge: K.ITEM('s32', profile.extra_gauge),
|
extra_gauge: K.ITEM('s32', profile.extra_gauge),
|
||||||
|
|
@ -354,6 +339,8 @@ export const getPlayer: EPR = async (info, data, send) => {
|
||||||
musiclist: { '@attr': { nr: musicdata.length }, musicdata },
|
musiclist: { '@attr': { nr: musicdata.length }, musicdata },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const playerRanking = await getPlayerRanking(refid, version, game)
|
||||||
|
|
||||||
const addition: any = {
|
const addition: any = {
|
||||||
monstar_subjugation: {},
|
monstar_subjugation: {},
|
||||||
bear_fes: {},
|
bear_fes: {},
|
||||||
|
|
@ -387,7 +374,7 @@ export const getPlayer: EPR = async (info, data, send) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
send.object({
|
const response = {
|
||||||
player: K.ATTR({ 'no': `${no}` }, {
|
player: K.ATTR({ 'no': `${no}` }, {
|
||||||
now_date: K.ITEM('u64', time),
|
now_date: K.ITEM('u64', time),
|
||||||
secretmusic: { // TODO: FIX THIS
|
secretmusic: { // TODO: FIX THIS
|
||||||
|
|
@ -404,7 +391,7 @@ export const getPlayer: EPR = async (info, data, send) => {
|
||||||
},
|
},
|
||||||
reward: {
|
reward: {
|
||||||
status: K.ARRAY('u32', Array(50).fill(0)),
|
status: K.ARRAY('u32', Array(50).fill(0)),
|
||||||
},
|
},
|
||||||
rivaldata: {},
|
rivaldata: {},
|
||||||
frienddata: {},
|
frienddata: {},
|
||||||
thanks_medal: {
|
thanks_medal: {
|
||||||
|
|
@ -412,7 +399,7 @@ export const getPlayer: EPR = async (info, data, send) => {
|
||||||
grant_medal: K.ITEM('s32', 0),
|
grant_medal: K.ITEM('s32', 0),
|
||||||
grant_total_medal: K.ITEM('s32', 0),
|
grant_total_medal: K.ITEM('s32', 0),
|
||||||
},
|
},
|
||||||
recommend_musicid_list: K.ARRAY('s32', [0, 0, 0, 0, 0]),
|
recommend_musicid_list: K.ARRAY('s32', extra.recommend_musicid_list ?? Array(5).fill(-1)),
|
||||||
skindata: {
|
skindata: {
|
||||||
skin: K.ARRAY('u32', Array(100).fill(-1)),
|
skin: K.ARRAY('u32', Array(100).fill(-1)),
|
||||||
},
|
},
|
||||||
|
|
@ -454,8 +441,8 @@ export const getPlayer: EPR = async (info, data, send) => {
|
||||||
},
|
},
|
||||||
is_free_ok: K.ITEM('bool', 0),
|
is_free_ok: K.ITEM('bool', 0),
|
||||||
ranking: {
|
ranking: {
|
||||||
skill: { rank: K.ITEM('s32', 1), total_nr: K.ITEM('s32', 1) },
|
skill: { rank: K.ITEM('s32', playerRanking.skill), total_nr: K.ITEM('s32', playerRanking.totalPlayers) },
|
||||||
all_skill: { rank: K.ITEM('s32', 1), total_nr: K.ITEM('s32', 1) },
|
all_skill: { rank: K.ITEM('s32', playerRanking.all_skill), total_nr: K.ITEM('s32', playerRanking.totalPlayers) },
|
||||||
},
|
},
|
||||||
stage_result: {},
|
stage_result: {},
|
||||||
monthly_skill: {},
|
monthly_skill: {},
|
||||||
|
|
@ -532,7 +519,26 @@ export const getPlayer: EPR = async (info, data, send) => {
|
||||||
...playerData,
|
...playerData,
|
||||||
finish: K.ITEM('bool', 1),
|
finish: K.ITEM('bool', 1),
|
||||||
}),
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAsphyxiaDebugMode()) {
|
||||||
|
await IO.WriteFile(`apisamples/lastGetPlayerRequest.json`, JSON.stringify(data, null, 4))
|
||||||
|
await IO.WriteFile(`apisamples/lastGetPlayerResponse.json`, JSON.stringify(response, null, 4))
|
||||||
|
}
|
||||||
|
send.object(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getOrRegisterPlayerInfo(refid: string, version: string, no: number) {
|
||||||
|
let playerInfo = await DB.FindOne<PlayerInfo>(refid, {
|
||||||
|
collection: 'playerinfo',
|
||||||
|
version
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!playerInfo) {
|
||||||
|
logger.debugInfo(`Registering new profile for player ${no} with refid: ${refid}`);
|
||||||
|
playerInfo = await registerUser(refid, version);
|
||||||
|
}
|
||||||
|
return playerInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPlayerNo(data: any): number {
|
function getPlayerNo(data: any): number {
|
||||||
|
|
@ -725,7 +731,8 @@ async function registerUser(refid: string, version: string, id = _.random(0, 999
|
||||||
list_1: Array(100).fill(-1),
|
list_1: Array(100).fill(-1),
|
||||||
list_2: Array(100).fill(-1),
|
list_2: Array(100).fill(-1),
|
||||||
list_3: Array(100).fill(-1),
|
list_3: Array(100).fill(-1),
|
||||||
|
recommend_musicid_list: Array(5).fill(-1),
|
||||||
|
reward_status: Array(50).fill(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -755,20 +762,61 @@ async function registerUser(refid: string, version: string, id = _.random(0, 999
|
||||||
return defaultInfo
|
return defaultInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
export const savePlayer: EPR = async (info, data, send) => {
|
export const savePlayers: EPR = async (info, data, send) => {
|
||||||
const refid = $(data).str('player.refid');
|
|
||||||
if (!refid) return send.deny();
|
|
||||||
|
|
||||||
const no = getPlayerNo(data);
|
|
||||||
const version = getVersion(info);
|
const version = getVersion(info);
|
||||||
const dm = isDM(info);
|
const dm = isDM(info);
|
||||||
|
|
||||||
const game = dm ? 'dm' : 'gf';
|
const game = dm ? 'dm' : 'gf';
|
||||||
|
|
||||||
|
let players = $(data).elements("player")
|
||||||
|
|
||||||
|
let response = {
|
||||||
|
player: [],
|
||||||
|
gamemode: _.get(data, 'gamemode'),
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (let player of players) {
|
||||||
|
|
||||||
|
const no = parseInt(player.attr().no || '1', 10)
|
||||||
|
// Only save players that are using a profile. Don't try to save guest players.
|
||||||
|
const hasCard = player.attr().card === 'use'
|
||||||
|
if (!hasCard) {
|
||||||
|
logger.debugInfo(`Skipping save for guest ${game} player ${no}.`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const refid = player.str('refid')
|
||||||
|
if (!refid) {
|
||||||
|
throw "Request data is missing required parameter: player.refid"
|
||||||
|
}
|
||||||
|
|
||||||
|
await saveSinglePlayer(player, refid, no, version, game);
|
||||||
|
|
||||||
|
let ranking = await getPlayerRanking(refid, version, game)
|
||||||
|
let responsePart = getSaveProfileResponse(no, ranking)
|
||||||
|
response.player.push(responsePart)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAsphyxiaDebugMode()) {
|
||||||
|
await IO.WriteFile(`apisamples/lastSavePlayersRequest.json`, JSON.stringify(data, null, 4))
|
||||||
|
await IO.WriteFile(`apisamples/lastSavePlayersResponse.json`, JSON.stringify(response, null, 4))
|
||||||
|
}
|
||||||
|
await send.object(response);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
logger.error(e)
|
||||||
|
return send.deny();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async function saveSinglePlayer(dataplayer: KDataReader, refid: string, no: number, version: string, game: 'gf' | 'dm')
|
||||||
|
{
|
||||||
|
logger.debugInfo(`Saving ${game} profile for player ${no} with refid: ${refid}`)
|
||||||
const profile = await getProfile(refid, version, game) as any;
|
const profile = await getProfile(refid, version, game) as any;
|
||||||
const extra = await getExtra(refid, version, game) as any;
|
const extra = await getExtra(refid, version, game) as any;
|
||||||
const rec = await getRecord(refid, version, game) as any;
|
const rec = await getRecord(refid, version, game) as any;
|
||||||
const dataplayer = $(data).element("player")
|
|
||||||
|
|
||||||
const autoSet = (field: keyof Profile, path: string, array = false): void => {
|
const autoSet = (field: keyof Profile, path: string, array = false): void => {
|
||||||
if (array) {
|
if (array) {
|
||||||
|
|
@ -781,7 +829,7 @@ export const savePlayer: EPR = async (info, data, send) => {
|
||||||
const autoExtra = (field: keyof Extra, path: string, array = false): void => {
|
const autoExtra = (field: keyof Extra, path: string, array = false): void => {
|
||||||
if (array) {
|
if (array) {
|
||||||
extra[field] = dataplayer.numbers(path, extra[field])
|
extra[field] = dataplayer.numbers(path, extra[field])
|
||||||
} else {
|
} else {
|
||||||
extra[field] = dataplayer.number(path, extra[field])
|
extra[field] = dataplayer.number(path, extra[field])
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -887,6 +935,7 @@ export const savePlayer: EPR = async (info, data, send) => {
|
||||||
autoExtra('list_1', 'favoritemusic.music_list_1', true);
|
autoExtra('list_1', 'favoritemusic.music_list_1', true);
|
||||||
autoExtra('list_2', 'favoritemusic.music_list_2', true);
|
autoExtra('list_2', 'favoritemusic.music_list_2', true);
|
||||||
autoExtra('list_3', 'favoritemusic.music_list_3', true);
|
autoExtra('list_3', 'favoritemusic.music_list_3', true);
|
||||||
|
autoExtra('recommend_musicid_list', 'recommend_musicid_list', true);
|
||||||
|
|
||||||
autoExtra('playstyle', 'customdata.playstyle', true);
|
autoExtra('playstyle', 'customdata.playstyle', true);
|
||||||
autoExtra('custom', 'customdata.custom', true);
|
autoExtra('custom', 'customdata.custom', true);
|
||||||
|
|
@ -895,7 +944,7 @@ export const savePlayer: EPR = async (info, data, send) => {
|
||||||
await DB.Upsert(refid, { collection: 'record', game, version }, rec)
|
await DB.Upsert(refid, { collection: 'record', game, version }, rec)
|
||||||
await DB.Upsert(refid, { collection: 'extra', game, version }, extra)
|
await DB.Upsert(refid, { collection: 'extra', game, version }, extra)
|
||||||
|
|
||||||
const stages = $(data).elements('player.stage');
|
const stages = dataplayer.elements('stage');
|
||||||
const scores = (await getScore(refid, version, game)).scores;
|
const scores = (await getScore(refid, version, game)).scores;
|
||||||
for (const stage of stages) {
|
for (const stage of stages) {
|
||||||
const mid = stage.number('musicid', -1);
|
const mid = stage.number('musicid', -1);
|
||||||
|
|
@ -937,25 +986,55 @@ export const savePlayer: EPR = async (info, data, send) => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
await saveScore(refid, version, game, scores);
|
await saveScore(refid, version, game, scores);
|
||||||
|
}
|
||||||
|
async function getPlayerRanking(refid: string, version: string, game: 'gf' | 'dm') : Promise<PlayerRanking> {
|
||||||
|
let profiles = await getAllProfiles(version, game)
|
||||||
|
let playerCount = profiles.length
|
||||||
|
let sortedProfilesA = profiles.sort((a,b) => b.skill - a.skill)
|
||||||
|
let sortedProfilesB = profiles.sort((a,b) => b.all_skill - a.all_skill)
|
||||||
|
|
||||||
await send.object({
|
let idxA = _.findIndex(sortedProfilesA, (e) => e.__refid === refid)
|
||||||
player: K.ATTR({ no: `${no}` }, {
|
idxA = idxA > -1 ? idxA + 1 : playerCount // Default to last place if not found in the DB.
|
||||||
skill: { rank: K.ITEM('s32', 1), total_nr: K.ITEM('s32', 1) },
|
let idxB = _.findIndex(sortedProfilesB, (e) => e.__refid === refid)
|
||||||
all_skill: { rank: K.ITEM('s32', 1), total_nr: K.ITEM('s32', 1) },
|
idxB = idxB > -1 ? idxB + 1 : playerCount // Default to last place if not found in the DB.
|
||||||
kac2018: {
|
|
||||||
data: {
|
return {
|
||||||
term: K.ITEM('s32', 0),
|
refid,
|
||||||
total_score: K.ITEM('s32', 0),
|
skill: idxA,
|
||||||
score: K.ARRAY('s32', [0, 0, 0, 0, 0, 0]),
|
all_skill: idxB,
|
||||||
music_type: K.ARRAY('s32', [0, 0, 0, 0, 0, 0]),
|
totalPlayers: playerCount
|
||||||
play_count: K.ARRAY('s32', [0, 0, 0, 0, 0, 0]),
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
|
function getSaveProfileResponse(playerNo: number, ranking : PlayerRanking)
|
||||||
|
{
|
||||||
|
|
||||||
|
const result = K.ATTR({ no: `${playerNo}` }, {
|
||||||
|
skill: { rank: K.ITEM('s32', ranking.skill), total_nr: K.ITEM('s32', ranking.totalPlayers) },
|
||||||
|
all_skill: { rank: K.ITEM('s32', ranking.all_skill), total_nr: K.ITEM('s32', ranking.totalPlayers) },
|
||||||
|
kac2018: {
|
||||||
|
data: {
|
||||||
|
term: K.ITEM('s32', 0),
|
||||||
|
total_score: K.ITEM('s32', 0),
|
||||||
|
score: K.ARRAY('s32', [0, 0, 0, 0, 0, 0]),
|
||||||
|
music_type: K.ARRAY('s32', [0, 0, 0, 0, 0, 0]),
|
||||||
|
play_count: K.ARRAY('s32', [0, 0, 0, 0, 0, 0]),
|
||||||
},
|
},
|
||||||
}),
|
},
|
||||||
gamemode: _.get(data, 'gamemode'),
|
})
|
||||||
});
|
|
||||||
};
|
return result
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getAllProfiles( version: string, game: 'gf' | 'dm') {
|
||||||
|
return await DB.Find<Profile>(null, {
|
||||||
|
collection: 'profile',
|
||||||
|
version: version,
|
||||||
|
game: game
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
async function getProfile(refid: string, version: string, game: 'gf' | 'dm') {
|
async function getProfile(refid: string, version: string, game: 'gf' | 'dm') {
|
||||||
return await DB.FindOne<Profile>(refid, {
|
return await DB.FindOne<Profile>(refid, {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { gameInfoGet, shopInfoRegist } from "./handlers/info";
|
import { gameInfoGet, shopInfoRegist } from "./handlers/info";
|
||||||
import { playableMusic } from "./handlers/MusicList"
|
import { playableMusic } from "./handlers/MusicList"
|
||||||
import { getPlayer, check, regist, savePlayer } from "./handlers/profiles";
|
import { getPlayer, check, regist, savePlayers } from "./handlers/profiles";
|
||||||
import { updatePlayerInfo } from "./handlers/webui";
|
import { updatePlayerInfo } from "./handlers/webui";
|
||||||
import { isAsphyxiaDebugMode, isRequiredCoreVersion } from "./utils";
|
import { isAsphyxiaDebugMode, isRequiredCoreVersion } from "./utils";
|
||||||
import Logger from "./utils/logger";
|
import Logger from "./utils/logger";
|
||||||
|
|
@ -64,7 +64,7 @@ export function register() {
|
||||||
MultiRoute('cardutil.regist', regist);
|
MultiRoute('cardutil.regist', regist);
|
||||||
MultiRoute('cardutil.check', check);
|
MultiRoute('cardutil.check', check);
|
||||||
MultiRoute('gametop.get', getPlayer);
|
MultiRoute('gametop.get', getPlayer);
|
||||||
MultiRoute('gameend.regist', savePlayer);
|
MultiRoute('gameend.regist', savePlayers);
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
R.Route('bemani_gakuen.get_music_info', true)
|
R.Route('bemani_gakuen.get_music_info', true)
|
||||||
|
|
|
||||||
|
|
@ -11,4 +11,6 @@ export interface Extra {
|
||||||
list_1: number[];
|
list_1: number[];
|
||||||
list_2: number[];
|
list_2: number[];
|
||||||
list_3: number[];
|
list_3: number[];
|
||||||
|
recommend_musicid_list: number[];
|
||||||
|
reward_status: number[];
|
||||||
}
|
}
|
||||||
7
gitadora@asphyxia/models/playerranking.ts
Normal file
7
gitadora@asphyxia/models/playerranking.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
export interface PlayerRanking
|
||||||
|
{
|
||||||
|
refid: string;
|
||||||
|
skill: number;
|
||||||
|
all_skill: number;
|
||||||
|
totalPlayers: number;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user