mirror of
https://github.com/asphyxia-core/plugins.git
synced 2026-03-21 17:34:46 -05:00
commit
d9b3051839
|
|
@ -1,6 +1,6 @@
|
|||
# Pop'n Music
|
||||
|
||||
Plugin Version: **v2.1.0**
|
||||
Plugin Version: **v2.2.2**
|
||||
|
||||
## Supported Versions
|
||||
- pop'n music 19 Tune Street
|
||||
|
|
@ -15,6 +15,17 @@ Important : require minimum Asphyxia Core **v1.31**
|
|||
|
||||
## Changelog
|
||||
|
||||
### 2.2.2
|
||||
* Usaneko/Peace : Add Omnimix support (songs with id >= 3000).
|
||||
|
||||
### 2.2.1
|
||||
* Tune Street : User customization is now saved
|
||||
* Fix 1.x to 2.x conversion code when there are multiple profiles
|
||||
|
||||
### 2.2.0
|
||||
* Tune Street : Add Town Mode + enable Net Taisen (only CPU will works)
|
||||
* Some fixes
|
||||
|
||||
### 2.1.0
|
||||
* Add rivals support (except for Tune Street)
|
||||
* Some fixes
|
||||
|
|
@ -46,7 +57,5 @@ To import data, you have to :
|
|||
* Data is imported. Run the game, insert your card and your scores are available.
|
||||
|
||||
## Known limitations
|
||||
* Tune Street : It will not report your profile name in-game
|
||||
* Tune Street : No Town Mode
|
||||
* No rival support implemented
|
||||
* Some stats are not implemented (like daily stats, most played music)
|
||||
* No rival support for Tune Street
|
||||
* Some stats are not implemented
|
||||
|
|
@ -283,7 +283,7 @@ const getProfile = async (refid: string, name?: string) => {
|
|||
result: K.ITEM('s8', 0),
|
||||
account: {
|
||||
name: K.ITEM('str', profile.name),
|
||||
g_pm_id: K.ITEM('str', 'ASPHYXIAPLAY'),
|
||||
g_pm_id: K.ITEM('str', profile.friendId),
|
||||
staff: K.ITEM('s8', 0),
|
||||
item_type: K.ITEM('s16', 0),
|
||||
item_id: K.ITEM('s16', 0),
|
||||
|
|
@ -476,7 +476,7 @@ const friend = async (req: EamuseInfo, data: any, send: EamuseSend): Promise<any
|
|||
const friend = {
|
||||
friend: {
|
||||
no: K.ITEM('s16', no),
|
||||
g_pm_id: K.ITEM('str', 'ASPHYXIAPLAY'),
|
||||
g_pm_id: K.ITEM('str', profile.friendId),
|
||||
name: K.ITEM('str', profile.name),
|
||||
chara: K.ITEM('s16', params.params.chara || -1),
|
||||
is_open: K.ITEM('s8', 1),
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export const getInfo = async (req: EamuseInfo, data: any, send: EamuseSend): Pro
|
|||
game_phase: K.ITEM('s32', 2),
|
||||
ir_phase: K.ITEM('s32', 0),
|
||||
event_phase: K.ITEM('s32', 5),
|
||||
netvs_phase: K.ITEM('s32', 0),
|
||||
netvs_phase: K.ITEM('s32', 0), // 1 to enable
|
||||
card_phase: K.ITEM('s32', 6),
|
||||
illust_phase: K.ITEM('s32', 2),
|
||||
psp_phase: K.ITEM('s32', 5),
|
||||
|
|
@ -17,7 +17,7 @@ export const getInfo = async (req: EamuseInfo, data: any, send: EamuseSend): Pro
|
|||
jubeat_phase: K.ITEM('s32', 1),
|
||||
public_phase: K.ITEM('s32', 3),
|
||||
kac_phase: K.ITEM('s32', 2),
|
||||
local_matching: K.ITEM('s32', 1),
|
||||
local_matching: K.ITEM('s32', 0),
|
||||
n_matching_sec: K.ITEM('s32', 60),
|
||||
l_matching_sec: K.ITEM('s32', 60),
|
||||
is_check_cpu: K.ITEM('s32', 0),
|
||||
|
|
@ -84,7 +84,7 @@ export const getProfile = async (refid: string, name?: string) => {
|
|||
let player: any = {
|
||||
base: {
|
||||
name: K.ITEM('str', profile.name),
|
||||
g_pm_id: K.ITEM('str', '1234-5678'),
|
||||
g_pm_id: K.ITEM('str', profile.friendId),
|
||||
staff: K.ITEM('s8', 0),
|
||||
is_conv: K.ITEM('s8', -1),
|
||||
my_best: K.ARRAY('s16', myBest),
|
||||
|
|
@ -211,11 +211,11 @@ export const friend = async (req: EamuseInfo, data: any, send: EamuseSend): Prom
|
|||
const profile = await utils.readProfile(rival);
|
||||
const params = await utils.readParams(rival, version);
|
||||
|
||||
const scores = await getScores(refid);
|
||||
const scores = await getScores(rival);
|
||||
|
||||
result.friend.push({
|
||||
open: K.ITEM('s8', 1),
|
||||
g_pm_id: K.ITEM('str', 'ASPHYXIAPLAY'),
|
||||
g_pm_id: K.ITEM('str', profile.friendId),
|
||||
name: K.ITEM('str', profile.name),
|
||||
chara: K.ITEM('s16', params.params.chara || -1),
|
||||
clear_medal: K.ARRAY('u16', scores.clear_medal),
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ const getProfile = async (refid: string, name?: string) => {
|
|||
result: K.ITEM('s8', 0),
|
||||
account: {
|
||||
name: K.ITEM('str', profile.name),
|
||||
g_pm_id: K.ITEM('str', 'ASPHYXIAPLAY'),
|
||||
g_pm_id: K.ITEM('str', profile.friendId),
|
||||
staff: K.ITEM('s8', 0),
|
||||
is_conv: K.ITEM('s8', 0),
|
||||
item_type: K.ITEM('s16', 0),
|
||||
|
|
@ -435,7 +435,7 @@ const friend = async (req: EamuseInfo, data: any, send: EamuseSend): Promise<any
|
|||
const friend = {
|
||||
friend: {
|
||||
no: K.ITEM('s16', no),
|
||||
g_pm_id: K.ITEM('str', 'ASPHYXIAPLAY'),
|
||||
g_pm_id: K.ITEM('str', profile.friendId),
|
||||
name: K.ITEM('str', profile.name),
|
||||
chara: K.ITEM('s16', params.params.chara || -1),
|
||||
is_open: K.ITEM('s8', 1),
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export const getInfo = async (req: EamuseInfo, data: any, send: EamuseSend): Pro
|
|||
netvs_phase: K.ITEM('s32', 0),
|
||||
card_phase: K.ITEM('s32', 9),
|
||||
other_phase: K.ITEM('s32', 9),
|
||||
local_matching_enable: K.ITEM('s32', 1),
|
||||
local_matching_enable: K.ITEM('s32', 0),
|
||||
n_matching_sec: K.ITEM('s32', 60),
|
||||
l_matching_sec: K.ITEM('s32', 60),
|
||||
is_check_cpu: K.ITEM('s32', 0),
|
||||
|
|
@ -80,7 +80,7 @@ export const getProfile = async (refid: string, name?: string) => {
|
|||
let player: any = {
|
||||
base: {
|
||||
name: K.ITEM('str', profile.name),
|
||||
g_pm_id: K.ITEM('str', '1234-5678'),
|
||||
g_pm_id: K.ITEM('str', profile.friendId),
|
||||
staff: K.ITEM('s8', 0),
|
||||
is_conv: K.ITEM('s8', -1),
|
||||
collabo: K.ITEM('u8', 255),
|
||||
|
|
@ -250,7 +250,7 @@ export const friend = async (req: EamuseInfo, data: any, send: EamuseSend): Prom
|
|||
|
||||
result.friend.push({
|
||||
open: K.ITEM('s8', 1),
|
||||
g_pm_id: K.ITEM('str', 'ASPHYXIAPLAY'),
|
||||
g_pm_id: K.ITEM('str', profile.friendId),
|
||||
name: K.ITEM('str', profile.name),
|
||||
chara: K.ITEM('s16', params.params.chara || -1),
|
||||
hair: K.ITEM('u8', params.params.hair || 0),
|
||||
|
|
|
|||
|
|
@ -1,10 +1,24 @@
|
|||
import { AchievementsTuneStreet } from "../models/achievements";
|
||||
import { Params, Profile } from "../models/common";
|
||||
import * as utils from "./utils";
|
||||
|
||||
/**
|
||||
* Handler for getting the current state of the game (phase, good prices, etc...)
|
||||
*/
|
||||
export const getInfo = async (req: EamuseInfo, data: any, send: EamuseSend): Promise<any> => {
|
||||
const result = K.ATTR({ game_phase: "2", psp_phase: "2" });
|
||||
const result = K.ATTR({
|
||||
game_phase: "2",
|
||||
ir_phase: "14", // None at 0/7/14
|
||||
event_phase: "15", // Town Mode (max value 17 / Town Max = 15)
|
||||
netvs_phase: "18", // Max 18
|
||||
card_phase: "3",
|
||||
gfdm_phase: "2",
|
||||
jubeat_phase: "2",
|
||||
local_matching_enable: "0",
|
||||
matching_sec: "120",
|
||||
boss_diff: "100,100,100,100,100,100,100,100,100,100",
|
||||
boss_battle_point: "1",
|
||||
});
|
||||
|
||||
return send.object(result);
|
||||
};
|
||||
|
|
@ -38,6 +52,7 @@ export const read = async (req: EamuseInfo, data: any, send: EamuseSend): Promis
|
|||
*/
|
||||
export const getProfile = async (refid: string, name?: string) => {
|
||||
const profile = await utils.readProfile(refid);
|
||||
//const rivals = await utils.readRivals(refid);
|
||||
|
||||
if (name && name.length > 0) {
|
||||
profile.name = name;
|
||||
|
|
@ -46,7 +61,7 @@ export const getProfile = async (refid: string, name?: string) => {
|
|||
|
||||
const params = await utils.readParams(refid, version);
|
||||
|
||||
let binary_profile = Array(2200).fill(0);
|
||||
let binary_profile = Array(2892).fill(0);
|
||||
let name_binary = U.EncodeString(profile.name, 'shift_jis');
|
||||
for (let i = 0; i < name_binary.length || i < 12; i++) {
|
||||
binary_profile[i] = name_binary[i];
|
||||
|
|
@ -57,22 +72,73 @@ export const getProfile = async (refid: string, name?: string) => {
|
|||
1: 0,
|
||||
2: 1,
|
||||
3: 1,
|
||||
4: 4,
|
||||
4: 5,
|
||||
5: 2,
|
||||
}[_.get(params, `params.play_mode`, 0)]
|
||||
6: 4,
|
||||
7: 4,
|
||||
8: 4,
|
||||
9: 4,
|
||||
10: 1,
|
||||
11: 5,
|
||||
12: 4,
|
||||
13: 6,
|
||||
14: 6,
|
||||
15: 6,
|
||||
}[_.get(params, `params.play_mode`, 0)] & 0xFF; // mode_num
|
||||
binary_profile[14] = {
|
||||
0: 1,
|
||||
1: 0,
|
||||
2: 1,
|
||||
3: 0,
|
||||
4: -1,
|
||||
5: -1,
|
||||
6: -1,
|
||||
7: -1,
|
||||
8: -1,
|
||||
9: -1,
|
||||
10: 0,
|
||||
11: -1,
|
||||
12: -1,
|
||||
13: -1,
|
||||
14: -1,
|
||||
15: -1,
|
||||
}[_.get(params, `params.play_mode`, 0)] & 0xFF; //botton_num
|
||||
binary_profile[15] = _.get(params, `params.last_play_flag`, 0) & 0xFF;
|
||||
binary_profile[16] = _.get(params, `params.medal_and_friend`, 0) & 0xFF;
|
||||
|
||||
binary_profile[16] = _.get(params, `params.last_play_flag`, 0) & 0xFF
|
||||
binary_profile[44] = _.get(params, `params.option`, 0) & 0xFF
|
||||
binary_profile[45] = (_.get(params, `params.option`, 0) >> 8) & 0xFF
|
||||
binary_profile[46] = (_.get(params, `params.option`, 0) >> 16) & 0xFF
|
||||
binary_profile[47] = (_.get(params, `params.option`, 0) >> 24) & 0xFF
|
||||
binary_profile[60] = _.get(params, `params.chara`, 0) & 0xFF
|
||||
binary_profile[61] = (_.get(params, `params.chara`, 0) >> 8) & 0xFF
|
||||
binary_profile[62] = _.get(params, `params.music`, 0) & 0xFF
|
||||
binary_profile[63] = (_.get(params, `params.music`, 0) >> 8) & 0xFF
|
||||
binary_profile[64] = _.get(params, `params.sheet`, 0) & 0xFF
|
||||
binary_profile[65] = _.get(params, `params.category`, 0) & 0xFF
|
||||
binary_profile[67] = _.get(params, `params.medal_and_friend`, 0) & 0xFF
|
||||
let friendIdBinary = U.EncodeString(profile.friendId, 'shift_jis');
|
||||
for (let i = 0; i < friendIdBinary.length || i < 12; i++) {
|
||||
binary_profile[17 + i] = friendIdBinary[i];
|
||||
}
|
||||
|
||||
// binary_profile[30] = customize_available
|
||||
// binary_profile[31] = customize_level_min
|
||||
// binary_profile[32] = customize_level_max
|
||||
// binary_profile[33] = customize_medal_min
|
||||
// binary_profile[34] = customize_medal_max
|
||||
// binary_profile[35] = customize_friend_no
|
||||
// binary_profile[36] = customize_friend_winlose
|
||||
// binary_profile[37] = read_news_no_max
|
||||
binary_profile[38] = _.get(params, `params.skin_tex_note`, 0) & 0xFF;
|
||||
binary_profile[39] = _.get(params, `params.skin_tex_cmn`, 0) & 0xFF;
|
||||
binary_profile[40] = _.get(params, `params.skin_sd_bgm`, 0) & 0xFF;
|
||||
binary_profile[41] = _.get(params, `params.skin_sd_se`, 0) & 0xFF;
|
||||
binary_profile[44] = _.get(params, `params.option`, 0) & 0xFF;
|
||||
binary_profile[45] = (_.get(params, `params.option`, 0) >> 8) & 0xFF;
|
||||
binary_profile[46] = (_.get(params, `params.option`, 0) >> 16) & 0xFF;
|
||||
binary_profile[47] = (_.get(params, `params.option`, 0) >> 24) & 0xFF;
|
||||
// binary_profile[48] = jubeatcollabo
|
||||
// binary_profile[52] = color_3p_flag
|
||||
binary_profile[60] = _.get(params, `params.chara`, 0) & 0xFF;
|
||||
binary_profile[61] = (_.get(params, `params.chara`, 0) >> 8) & 0xFF;
|
||||
binary_profile[62] = _.get(params, `params.music`, 0) & 0xFF;
|
||||
binary_profile[63] = (_.get(params, `params.music`, 0) >> 8) & 0xFF;
|
||||
binary_profile[64] = _.get(params, `params.sheet`, 0) & 0xFF;
|
||||
binary_profile[65] = _.get(params, `params.category`, 0) & 0xFF;
|
||||
// binary_profile[66] = norma_point
|
||||
// binary_profile[67] = rivals.rivals.length; // TODO: implements rivals
|
||||
// binary_profile[2208 -> 2351] = ir
|
||||
// binary_profile[2352 -> 2892] = netvs
|
||||
|
||||
// Get Score
|
||||
let hiscore_array = Array(Math.floor((((GAME_MAX_MUSIC_ID * 7) * 17) + 7) / 8)).fill(0);
|
||||
|
|
@ -94,9 +160,9 @@ export const getProfile = async (refid: string, name?: string) => {
|
|||
|
||||
//flag
|
||||
const flags = __format_flags_for_score(sheet, score.clear_type);
|
||||
const flags_index = music * 2
|
||||
binary_profile[108 + flags_index] = binary_profile[108 + flags_index] | (flags & 0xFF)
|
||||
binary_profile[109 + flags_index] = binary_profile[109 + flags_index] | ((flags >> 8) & 0xFF)
|
||||
const flags_index = music * 2;
|
||||
binary_profile[108 + flags_index] = binary_profile[108 + flags_index] | (flags & 0xFF);
|
||||
binary_profile[109 + flags_index] = binary_profile[109 + flags_index] | ((flags >> 8) & 0xFF);
|
||||
|
||||
if (sheet == 7 || sheet == 8) {
|
||||
continue;
|
||||
|
|
@ -139,15 +205,187 @@ export const getProfile = async (refid: string, name?: string) => {
|
|||
profile_pos = profile_pos + 2
|
||||
}
|
||||
|
||||
const achievements = <AchievementsTuneStreet>await utils.readAchievements(refid, version, defaultAchievements);
|
||||
|
||||
// Town mode
|
||||
let town = Array(272).fill(0);
|
||||
const tp = _.get(params, `params.tp`, 100);
|
||||
town[0] = tp & 0xFF
|
||||
town[1] = (tp >> 8) & 0xFF
|
||||
town[2] = (tp >> 16) & 0xFF
|
||||
town[3] = (tp >> 24) & 0xFF
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const value = achievements.bought_flg[i] || 0;
|
||||
town[(i * 4) + 4] = value & 0xFF
|
||||
town[(i * 4) + 4 + 1] = (value >> 8) & 0xFF
|
||||
town[(i * 4) + 4 + 2] = (value >> 16) & 0xFF
|
||||
town[(i * 4) + 4 + 3] = (value >> 24) & 0xFF
|
||||
}
|
||||
for (let i = 0; i < 8; i++) {
|
||||
const value = achievements.build_flg[i] || 0;
|
||||
town[(i * 4) + 16] = value & 0xFF
|
||||
town[(i * 4) + 16 + 1] = (value >> 8) & 0xFF
|
||||
town[(i * 4) + 16 + 2] = (value >> 16) & 0xFF
|
||||
town[(i * 4) + 16 + 3] = (value >> 24) & 0xFF
|
||||
}
|
||||
for (let i = 0; i < 19; i++) {
|
||||
const value = achievements.chara_flg[i] || 0;
|
||||
town[(i * 4) + 48] = value & 0xFF
|
||||
town[(i * 4) + 48 + 1] = (value >> 8) & 0xFF
|
||||
town[(i * 4) + 48 + 2] = (value >> 16) & 0xFF
|
||||
town[(i * 4) + 48 + 3] = (value >> 24) & 0xFF
|
||||
}
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const value = achievements.event_flg[i] || 0;
|
||||
town[(i * 4) + 124] = value & 0xFF
|
||||
town[(i * 4) + 124 + 1] = (value >> 8) & 0xFF
|
||||
town[(i * 4) + 124 + 2] = (value >> 16) & 0xFF
|
||||
town[(i * 4) + 124 + 3] = (value >> 24) & 0xFF
|
||||
}
|
||||
town[140] = achievements.play_type & 0xFF
|
||||
|
||||
for (let applyIdx = 0; applyIdx < achievements.apply.length; applyIdx++) {
|
||||
let apply_name = U.EncodeString(achievements.apply[applyIdx], 'shift_jis');
|
||||
for (let i = 0; i < apply_name.length || i < 12; i++) {
|
||||
const index = applyIdx * 13 + i + 141;
|
||||
town[index] = apply_name[i];
|
||||
}
|
||||
}
|
||||
|
||||
const player = {
|
||||
b: K.ITEM('bin', Buffer.from(binary_profile)),
|
||||
hiscore: K.ITEM('bin', Buffer.from(hiscore_array)),
|
||||
town: K.ITEM('bin', Buffer.alloc(0)),
|
||||
town: K.ITEM('bin', Buffer.from(town)),
|
||||
}
|
||||
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for getting town mode maps data
|
||||
*/
|
||||
export const map = async (req: EamuseInfo, data: any, send: EamuseSend): Promise<any> => {
|
||||
let refid = $(data).attr()['ref_id'];
|
||||
if (!refid) return send.deny();
|
||||
|
||||
const friendId = $(data).attr()['gpm_id'];
|
||||
let isRandom = parseInt($(data).attr()['is_random'], 10);
|
||||
let friends = await DB.Find<AchievementsTuneStreet>(null, { collection: 'achievements', version: 'v19' });
|
||||
|
||||
if (friendId != undefined && friendId != null) {
|
||||
// Check if friend exists
|
||||
let friend = await DB.FindOne<Profile>(null, { collection: 'profile', friendId });
|
||||
if(friend != undefined && friend != null) {
|
||||
// Check if friend has tunestreet town mode data
|
||||
const achievements = await DB.Find<AchievementsTuneStreet>(null, { collection: 'achievements', version: 'v19' });
|
||||
if(achievements != undefined && achievements != null) {
|
||||
refid = friend.__refid;
|
||||
isRandom == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isRandom == 1) {
|
||||
// Pick a random refid from players having tunestreet data
|
||||
refid = friends[Math.floor(Math.random() * friends.length)].__refid
|
||||
}
|
||||
|
||||
const player = {
|
||||
residence: K.ATTR({ id: "0" }),
|
||||
map: []
|
||||
}
|
||||
|
||||
// player map
|
||||
player.map.push(K.ITEM("bin", Buffer.from(await formatMap(refid)), { residence: "0" }));
|
||||
|
||||
// Friends map (max 9)
|
||||
const usedFriends = [refid];
|
||||
let i = 1;
|
||||
while(i < 10 && i < friends.length) {
|
||||
const friendRefid = friends[Math.floor(Math.random() * friends.length)].__refid;
|
||||
if(usedFriends.indexOf(friendRefid) == -1) {
|
||||
usedFriends.push(friendRefid);
|
||||
player.map.push(K.ITEM("bin", Buffer.from(await formatMap(friendRefid)), { residence: `${i}` }));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
send.object(player);
|
||||
}
|
||||
|
||||
const formatMap = async (refid: string) => {
|
||||
const profile = await utils.readProfile(refid);
|
||||
const params = await utils.readParams(refid, version);
|
||||
const achievements = <AchievementsTuneStreet>await utils.readAchievements(refid, version, defaultAchievements);
|
||||
|
||||
let map = Array(180);
|
||||
map[0] = _.get(params, `params.chara`, 0) & 0xFF
|
||||
map[1] = (_.get(params, `params.chara`, 0) >> 8) & 0xFF
|
||||
|
||||
// Building data
|
||||
for (let i = 0; i <= 7; i++) {
|
||||
if (achievements.building[i]) {
|
||||
let idx = 0;
|
||||
for (let j = 0; j <= 7; j++) {
|
||||
map[(8 * i) + 42 + idx] = achievements.building[i][j] || 0;
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Friend ID
|
||||
for (let i = 0; i < profile.friendId.length || i < 12; i++) {
|
||||
map[106 + i] = profile.friendId[i];
|
||||
}
|
||||
|
||||
// Player Name
|
||||
let name_binary = U.EncodeString(profile.name, 'shift_jis');
|
||||
for (let i = 0; i < name_binary.length || i < 12; i++) {
|
||||
map[i + 119] = name_binary[i];
|
||||
}
|
||||
// map[132] = message
|
||||
|
||||
// Base state
|
||||
for (let i = 0; i < 4; i++) {
|
||||
map[i + 173] = achievements.base[i];
|
||||
}
|
||||
|
||||
// Player most played songs
|
||||
const scoresData = await utils.readScores(refid, version);
|
||||
const playCount = new Map();
|
||||
for (const key in scoresData.scores) {
|
||||
const keyData = key.split(':');
|
||||
const score = scoresData.scores[key];
|
||||
const music = parseInt(keyData[0], 10);
|
||||
const sheet = parseInt(keyData[1], 10);
|
||||
|
||||
if (music > GAME_MAX_MUSIC_ID || sheet == 0 || sheet == 7 || sheet == 8) {
|
||||
continue;
|
||||
}
|
||||
|
||||
playCount.set(music, (playCount.get(music) || 0) + score.cnt);
|
||||
}
|
||||
|
||||
let myBest = Array(20).fill(-1);
|
||||
const sortedPlayCount = new Map([...playCount.entries()].sort((a, b) => b[1] - a[1]));
|
||||
let i = 0;
|
||||
for (const value of sortedPlayCount.keys()) {
|
||||
if (i >= 20) {
|
||||
break;
|
||||
}
|
||||
myBest[i] = value;
|
||||
i++;
|
||||
}
|
||||
|
||||
let mybest_pos = 2
|
||||
for (let i = 0; i < myBest.length; i++) {
|
||||
map[mybest_pos] = myBest[i] & 0xFF
|
||||
map[mybest_pos + 1] = (myBest[i] >> 8) & 0xFF
|
||||
mybest_pos = mybest_pos + 2
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
const __format_flags_for_score = (sheet: number, clear_type: number) => {
|
||||
const playedflag = {
|
||||
9: 0x2000,
|
||||
|
|
@ -196,6 +434,7 @@ export const write = async (req: EamuseInfo, data: any, send: EamuseSend): Promi
|
|||
|
||||
const params = await utils.readParams(refid, version);
|
||||
|
||||
params.params['tp'] = parseInt($(data).attr()['tp']);
|
||||
params.params['play_mode'] = parseInt($(data).attr()['play_mode']);
|
||||
params.params['chara'] = parseInt($(data).attr()['chara_num']);
|
||||
params.params['option'] = parseInt($(data).attr()['option']);
|
||||
|
|
@ -204,6 +443,10 @@ export const write = async (req: EamuseInfo, data: any, send: EamuseSend): Promi
|
|||
params.params['music'] = parseInt($(data).attr()['music_num']);
|
||||
params.params['sheet'] = parseInt($(data).attr()['sheet_num']);
|
||||
params.params['category'] = parseInt($(data).attr()['category_num']);
|
||||
params.params['skin_sd_bgm'] = parseInt($(data).attr()['skin_sd_bgm']);
|
||||
params.params['skin_sd_se'] = parseInt($(data).attr()['skin_sd_se']);
|
||||
params.params['skin_tex_cmn'] = parseInt($(data).attr()['skin_tex_cmn']);
|
||||
params.params['skin_tex_note'] = parseInt($(data).attr()['skin_tex_note']);
|
||||
|
||||
await utils.writeParams(refid, version, params);
|
||||
|
||||
|
|
@ -283,6 +526,25 @@ export const write = async (req: EamuseInfo, data: any, send: EamuseSend): Promi
|
|||
|
||||
utils.writeScores(refid, version, scoresData);
|
||||
|
||||
// Town mode save
|
||||
const town = $(data).element('town');
|
||||
if (town != undefined && town != null) {
|
||||
const achievements = <AchievementsTuneStreet>await utils.readAchievements(refid, version, defaultAchievements);
|
||||
for (let i = 0; i <= 5; i++) {
|
||||
achievements.apply[i] = town.attr()[`apply_gpmid_${i}`];
|
||||
}
|
||||
for (let i = 0; i <= 7; i++) {
|
||||
achievements.building[i] = town.attr()[`building_${i}`].split(',').map(Number);
|
||||
}
|
||||
achievements.bought_flg = town.attr()[`bought_flg`].split(',').map(Number);
|
||||
achievements.build_flg = town.attr()[`build_flg`].split(',').map(Number);
|
||||
achievements.chara_flg = town.attr()[`chara_flg`].split(',').map(Number);
|
||||
achievements.event_flg = town.attr()[`event_flg`].split(',').map(Number);
|
||||
achievements.base = town.attr()[`base`].split(',').map(Number);
|
||||
achievements.play_type = parseInt(town.attr()['play_type'], 10);
|
||||
await utils.writeAchievements(refid, version, achievements);
|
||||
}
|
||||
|
||||
const profile = await utils.readProfile(refid);
|
||||
|
||||
const result = {
|
||||
|
|
@ -294,11 +556,33 @@ export const write = async (req: EamuseInfo, data: any, send: EamuseSend): Promi
|
|||
};
|
||||
|
||||
export const friend = async (req: EamuseInfo, data: any, send: EamuseSend): Promise<any> => {
|
||||
// No rivals support for Tune street :(
|
||||
// TODO: rival support (see e-amuemu C# code)
|
||||
send.deny();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const version: string = 'v19';
|
||||
const GAME_MAX_MUSIC_ID = 1045;
|
||||
const GAME_MAX_MUSIC_ID = 1047;
|
||||
|
||||
const defaultAchievements: AchievementsTuneStreet = {
|
||||
collection: 'achievements',
|
||||
version: 'v19',
|
||||
apply: Array(6),
|
||||
bought_flg: Array(3),
|
||||
build_flg: Array(8),
|
||||
chara_flg: Array(19),
|
||||
event_flg: Array(4),
|
||||
base: Array(4),
|
||||
building: {
|
||||
0: Array(8),
|
||||
1: Array(8),
|
||||
2: Array(8),
|
||||
3: Array(8),
|
||||
4: Array(8),
|
||||
5: Array(8),
|
||||
6: Array(8),
|
||||
7: Array(8),
|
||||
},
|
||||
play_type: 0
|
||||
}
|
||||
|
|
@ -166,6 +166,7 @@ const readScore = async (req: EamuseInfo, data: any, send: EamuseSend): Promise<
|
|||
const getScores = async (refid: string, version: string, forFriend: boolean = false) => {
|
||||
const scoresData = await utils.readScores(refid, version);
|
||||
const result = [];
|
||||
const maxMusicId = GAME_MAX_MUSIC_ID[isOmni ? 'omni' : version];
|
||||
|
||||
for (const key in scoresData.scores) {
|
||||
const keyData = key.split(':');
|
||||
|
|
@ -186,7 +187,7 @@ const getScores = async (refid: string, version: string, forFriend: boolean = fa
|
|||
1100: 11,
|
||||
}[score.clear_type];
|
||||
|
||||
if (music > GAME_MAX_MUSIC_ID[version]) {
|
||||
if (music > maxMusicId) {
|
||||
continue;
|
||||
}
|
||||
if ([0, 1, 2, 3].indexOf(sheet) == -1) {
|
||||
|
|
@ -324,7 +325,7 @@ const getProfile = async (refid: string, version: string, name?: string) => {
|
|||
result: K.ITEM('s8', 0),
|
||||
account: {
|
||||
name: K.ITEM('str', profile.name),
|
||||
g_pm_id: K.ITEM('str', 'ASPHYXIAPLAY'),
|
||||
g_pm_id: K.ITEM('str', profile.friendId),
|
||||
staff: K.ITEM('s8', 0),
|
||||
item_type: K.ITEM('s16', 0),
|
||||
item_id: K.ITEM('s16', 0),
|
||||
|
|
@ -654,7 +655,7 @@ const friend = async (req: EamuseInfo, data: any, send: EamuseSend): Promise<any
|
|||
const friend = {
|
||||
friend: {
|
||||
no: K.ITEM('s16', no),
|
||||
g_pm_id: K.ITEM('str', 'ASPHYXIAPLAY'),
|
||||
g_pm_id: K.ITEM('str', profile.friendId),
|
||||
name: K.ITEM('str', profile.name),
|
||||
chara: K.ITEM('s16', params.params.chara || -1),
|
||||
is_open: K.ITEM('s8', 1),
|
||||
|
|
@ -667,7 +668,13 @@ const friend = async (req: EamuseInfo, data: any, send: EamuseSend): Promise<any
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
let isOmni= false;
|
||||
|
||||
const getVersion = (req: EamuseInfo): string => {
|
||||
if(req.model.indexOf('J:A:X') >= 0) {
|
||||
isOmni = true;
|
||||
}
|
||||
|
||||
const date: number = parseInt(req.model.match(/:(\d*)$/)[1]);
|
||||
if (date >= 2018101700) {
|
||||
return 'v25';
|
||||
|
|
@ -678,7 +685,8 @@ const getVersion = (req: EamuseInfo): string => {
|
|||
|
||||
const GAME_MAX_MUSIC_ID = {
|
||||
v24: 1704,
|
||||
v25: 1877
|
||||
v25: 1877,
|
||||
omni: 3155
|
||||
}
|
||||
|
||||
const defaultAchievements: AchievementsUsaneko = {
|
||||
|
|
|
|||
|
|
@ -57,11 +57,30 @@ export const getExtraData = (data: any, params: Params, extraData: ExtraData) =>
|
|||
}
|
||||
|
||||
export const readProfile = async (refid: string): Promise<Profile> => {
|
||||
const profile = await DB.FindOne<Profile>(refid, { collection: 'profile' });
|
||||
if (profile !== undefined && profile !== null && profile.dataVersion !== CURRENT_DATA_VERSION) {
|
||||
return await doConvert(profile);
|
||||
let profile = await DB.FindOne<Profile>(refid, { collection: 'profile' });
|
||||
if (profile !== undefined && profile !== null) {
|
||||
if(profile.dataVersion !== CURRENT_DATA_VERSION) {
|
||||
profile = await doConvert(profile);
|
||||
}
|
||||
if(profile.friendId == undefined || profile.friendId == null) {
|
||||
profile.friendId = await generateFriendId();
|
||||
await writeProfile(refid, profile);
|
||||
}
|
||||
}
|
||||
return profile || { collection: 'profile', name: 'ゲスト', dataVersion: CURRENT_DATA_VERSION };
|
||||
return profile || { collection: 'profile', name: 'ゲスト', friendId: await generateFriendId(), dataVersion: CURRENT_DATA_VERSION };
|
||||
}
|
||||
|
||||
const generateFriendId = async (): Promise<string> => {
|
||||
let friendId;
|
||||
let check = null;
|
||||
do {
|
||||
friendId = "";
|
||||
for (let i = 0; i < 12; i++) {
|
||||
friendId += Math.floor(Math.random() * 10);
|
||||
}
|
||||
check = await DB.FindOne<Profile>(null, { collection: 'profile', friendId });
|
||||
} while(check != undefined && check != null);
|
||||
return friendId;
|
||||
}
|
||||
|
||||
export const writeProfile = async (refid: string, profile: Profile) => {
|
||||
|
|
@ -193,7 +212,7 @@ const doConvert = async (profile: ProfileDoc<any>): Promise<ProfileDoc<Profile>>
|
|||
|
||||
// Update scores
|
||||
let scoresData: Scores = { collection: 'scores', version: 'v25', scores: {} };
|
||||
const oldScores = await DB.Find<any>(null, { collection: 'scores' });
|
||||
const oldScores = await DB.Find<any>(profile.__refid, { collection: 'scores' });
|
||||
for (const oldScore of oldScores) {
|
||||
for (const key in oldScore.scores) {
|
||||
scoresData.scores[key] = {
|
||||
|
|
@ -215,9 +234,9 @@ const doConvert = async (profile: ProfileDoc<any>): Promise<ProfileDoc<Profile>>
|
|||
}[Math.max(oldScore.scores[key].clearmedal || 0, oldScore.scores[key].clear_type || 0)]
|
||||
};
|
||||
}
|
||||
await DB.Remove(oldScore.__refid, { collection: 'scores' });
|
||||
await DB.Insert(oldScore.__refid, scoresData);
|
||||
}
|
||||
await DB.Remove(profile.__refid, { collection: 'scores' });
|
||||
await DB.Insert(profile.__refid, scoresData);
|
||||
|
||||
return newProfile;
|
||||
}
|
||||
|
|
@ -65,6 +65,8 @@ export function register() {
|
|||
R.Route(`playerdata.get`, async (req, data, send) => getVersion(req).read(req, data, send));
|
||||
R.Route(`playerdata.set`, async (req, data, send) => getVersion(req).write(req, data, send));
|
||||
R.Route(`playerdata.friend`, async (req, data, send) => getVersion(req).friend(req, data, send));
|
||||
|
||||
R.Route(`playerdata.town`, async (req, data, send) => tunestreet.map(req, data, send));
|
||||
|
||||
// For Pnm >= 22, each game set his own route
|
||||
lapistoria.setRoutes();
|
||||
|
|
|
|||
|
|
@ -3,6 +3,21 @@ export interface Achievements {
|
|||
version: string,
|
||||
}
|
||||
|
||||
export interface AchievementsTuneStreet extends Achievements {
|
||||
version: 'v19',
|
||||
|
||||
apply: string[],
|
||||
bought_flg: number[],
|
||||
build_flg: number[],
|
||||
chara_flg: number[],
|
||||
event_flg: number[],
|
||||
base: number[],
|
||||
building: {
|
||||
[id: number]: number[]
|
||||
}
|
||||
play_type: number
|
||||
}
|
||||
|
||||
export interface AchievementsLapistoria extends Achievements {
|
||||
version: 'v22',
|
||||
|
||||
|
|
|
|||
|
|
@ -1,22 +1,23 @@
|
|||
export interface Phase {
|
||||
id: number;
|
||||
p: number;
|
||||
id: number,
|
||||
p: number,
|
||||
}
|
||||
|
||||
export interface ExtraData {
|
||||
[field: string]: {
|
||||
path: string;
|
||||
pathSrc?: string;
|
||||
type: string;
|
||||
default: any;
|
||||
isArray?: true;
|
||||
path: string,
|
||||
pathSrc?: string,
|
||||
type: string,
|
||||
default: any,
|
||||
isArray?: true,
|
||||
};
|
||||
};
|
||||
|
||||
export interface Profile {
|
||||
collection: 'profile',
|
||||
name: string;
|
||||
dataVersion: number;
|
||||
name: string,
|
||||
friendId: string,
|
||||
dataVersion: number
|
||||
}
|
||||
|
||||
export interface Params {
|
||||
|
|
@ -39,9 +40,9 @@ export interface Scores {
|
|||
|
||||
scores: {
|
||||
[key: string]: {
|
||||
clear_type?: number;
|
||||
score: number;
|
||||
cnt: number;
|
||||
clear_type?: number,
|
||||
score: number,
|
||||
cnt: number,
|
||||
};
|
||||
};
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user