diff --git a/popn@asphyxia/README.md b/popn@asphyxia/README.md index 68c2547..6eb1f2b 100644 --- a/popn@asphyxia/README.md +++ b/popn@asphyxia/README.md @@ -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 newline at end of file +* No rival support for Tune Street +* Some stats are not implemented \ No newline at end of file diff --git a/popn@asphyxia/handler/eclale.ts b/popn@asphyxia/handler/eclale.ts index 7540fed..6213953 100644 --- a/popn@asphyxia/handler/eclale.ts +++ b/popn@asphyxia/handler/eclale.ts @@ -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 { 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), diff --git a/popn@asphyxia/handler/lapistoria.ts b/popn@asphyxia/handler/lapistoria.ts index 659a298..a90eb07 100644 --- a/popn@asphyxia/handler/lapistoria.ts +++ b/popn@asphyxia/handler/lapistoria.ts @@ -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 { 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), diff --git a/popn@asphyxia/handler/tunestreet.ts b/popn@asphyxia/handler/tunestreet.ts index f63c937..63c58b3 100644 --- a/popn@asphyxia/handler/tunestreet.ts +++ b/popn@asphyxia/handler/tunestreet.ts @@ -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 => { - 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 = 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 => { + 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(null, { collection: 'achievements', version: 'v19' }); + + if (friendId != undefined && friendId != null) { + // Check if friend exists + let friend = await DB.FindOne(null, { collection: 'profile', friendId }); + if(friend != undefined && friend != null) { + // Check if friend has tunestreet town mode data + const achievements = await DB.Find(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 = 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 = 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 => { - // 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; \ No newline at end of file +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 +} \ No newline at end of file diff --git a/popn@asphyxia/handler/usaneko.ts b/popn@asphyxia/handler/usaneko.ts index 95a5a4e..314fa94 100644 --- a/popn@asphyxia/handler/usaneko.ts +++ b/popn@asphyxia/handler/usaneko.ts @@ -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 { + 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 = { diff --git a/popn@asphyxia/handler/utils.ts b/popn@asphyxia/handler/utils.ts index 53c7654..d259907 100644 --- a/popn@asphyxia/handler/utils.ts +++ b/popn@asphyxia/handler/utils.ts @@ -57,11 +57,30 @@ export const getExtraData = (data: any, params: Params, extraData: ExtraData) => } export const readProfile = async (refid: string): Promise => { - const profile = await DB.FindOne(refid, { collection: 'profile' }); - if (profile !== undefined && profile !== null && profile.dataVersion !== CURRENT_DATA_VERSION) { - return await doConvert(profile); + let profile = await DB.FindOne(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 => { + let friendId; + let check = null; + do { + friendId = ""; + for (let i = 0; i < 12; i++) { + friendId += Math.floor(Math.random() * 10); + } + check = await DB.FindOne(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): Promise> // Update scores let scoresData: Scores = { collection: 'scores', version: 'v25', scores: {} }; - const oldScores = await DB.Find(null, { collection: 'scores' }); + const oldScores = await DB.Find(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): Promise> }[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; } \ No newline at end of file diff --git a/popn@asphyxia/index.ts b/popn@asphyxia/index.ts index cb63096..d5f5839 100644 --- a/popn@asphyxia/index.ts +++ b/popn@asphyxia/index.ts @@ -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(); diff --git a/popn@asphyxia/models/achievements.ts b/popn@asphyxia/models/achievements.ts index 5f508ec..768de45 100644 --- a/popn@asphyxia/models/achievements.ts +++ b/popn@asphyxia/models/achievements.ts @@ -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', diff --git a/popn@asphyxia/models/common.ts b/popn@asphyxia/models/common.ts index b6160f1..0d8ccf7 100644 --- a/popn@asphyxia/models/common.ts +++ b/popn@asphyxia/models/common.ts @@ -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, }; }; } \ No newline at end of file