implement ep3 jukebox
This commit is contained in:
+18
-1
@@ -362,6 +362,14 @@ static void check_is_game(shared_ptr<Lobby> l, bool is_game) {
|
||||
}
|
||||
}
|
||||
|
||||
static void check_is_ep3(shared_ptr<Client> c, bool is_ep3) {
|
||||
if (!!(c->flags & ClientFlag::Episode3Games) != is_ep3) {
|
||||
throw precondition_failed(is_ep3 ?
|
||||
u"$C6This command can only\nbe used in Episode 3." :
|
||||
u"$C6This command cannot\nbe used in Episode 3.");
|
||||
}
|
||||
}
|
||||
|
||||
static void check_cheats_enabled(shared_ptr<Lobby> l) {
|
||||
if (!(l->flags & LobbyFlag::CheatsEnabled)) {
|
||||
throw precondition_failed(u"$C6This command can\nonly be used in\ncheat mode.");
|
||||
@@ -817,6 +825,14 @@ static void command_warp(shared_ptr<ServerState>, shared_ptr<Lobby> l,
|
||||
send_warp(c, area);
|
||||
}
|
||||
|
||||
static void command_song(shared_ptr<ServerState>, shared_ptr<Lobby>,
|
||||
shared_ptr<Client> c, const char16_t* args) {
|
||||
check_is_ep3(c, true);
|
||||
|
||||
uint32_t song = stoul(encode_sjis(args), nullptr, 0);
|
||||
send_ep3_change_music(c, song);
|
||||
}
|
||||
|
||||
static void command_infinite_hp(shared_ptr<ServerState>, shared_ptr<Lobby> l,
|
||||
shared_ptr<Client> c, const char16_t*) {
|
||||
check_is_game(l, true);
|
||||
@@ -890,10 +906,11 @@ static const unordered_map<u16string, ChatCommandDefinition> chat_commands({
|
||||
{u"item" , {command_item , u"Usage:\nitem <item-code>"}},
|
||||
{u"kick" , {command_kick , u"Usage:\nkick <name-or-number>"}},
|
||||
{u"li" , {command_lobby_info , u"Usage:\nli"}},
|
||||
{u"password" , {command_password , u"Usage:\nlock [password]\nomit password to\nunlock game"}},
|
||||
{u"maxlevel" , {command_max_level , u"Usage:\nmax_level <level>"}},
|
||||
{u"minlevel" , {command_min_level , u"Usage:\nmin_level <level>"}},
|
||||
{u"password" , {command_password , u"Usage:\nlock [password]\nomit password to\nunlock game"}},
|
||||
{u"silence" , {command_silence , u"Usage:\nsilence <name-or-number>"}},
|
||||
{u"song" , {command_song , u"Usage:\nsong <song-number>"}},
|
||||
{u"type" , {command_lobby_type , u"Usage:\ntype <name>"}},
|
||||
{u"warp" , {command_warp , u"Usage:\nwarp <area-number>"}},
|
||||
});
|
||||
|
||||
+14
-5
@@ -463,18 +463,27 @@ void process_server_time_request(shared_ptr<ServerState>, shared_ptr<Client> c,
|
||||
|
||||
void process_ep3_jukebox(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
uint16_t command, uint32_t, uint16_t size, const void* data) {
|
||||
struct Cmd {
|
||||
uint32_t unknown[3]; // should be FFFFFFFF 00000000
|
||||
struct InputCmd {
|
||||
uint32_t transaction_num;
|
||||
uint32_t value;
|
||||
uint32_t unknown_token;
|
||||
};
|
||||
check_size(size, sizeof(Cmd));
|
||||
const auto* cmd = reinterpret_cast<const Cmd*>(data);
|
||||
struct OutputCmd {
|
||||
uint32_t remaining_meseta;
|
||||
uint32_t unknown;
|
||||
uint32_t unknown_token;
|
||||
};
|
||||
check_size(size, sizeof(InputCmd));
|
||||
const auto* in_cmd = reinterpret_cast<const InputCmd*>(data);
|
||||
|
||||
OutputCmd out_cmd = {1000000, 0x80E8, in_cmd->unknown_token};
|
||||
|
||||
auto l = s->find_lobby(c->lobby_id);
|
||||
if (!l || !(l->flags & LobbyFlag::Episode3)) {
|
||||
return;
|
||||
}
|
||||
|
||||
send_command(l, command, 0x03, cmd);
|
||||
send_command(c, command, 0x03, &out_cmd, sizeof(out_cmd));
|
||||
}
|
||||
|
||||
void process_ep3_menu_challenge(shared_ptr<ServerState>, shared_ptr<Client> c,
|
||||
|
||||
@@ -869,6 +869,15 @@ static void process_subcommand_forward_check_size_game(shared_ptr<ServerState>,
|
||||
forward_subcommand(l, c, command, flag, p, count);
|
||||
}
|
||||
|
||||
static void process_subcommand_forward_check_size_ep3_lobby(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
|
||||
const PSOSubcommand* p, size_t count) {
|
||||
if (!(l->flags & LobbyFlag::Episode3) || l->is_game() || (p->byte[1] != count)) {
|
||||
return;
|
||||
}
|
||||
forward_subcommand(l, c, command, flag, p, count);
|
||||
}
|
||||
|
||||
static void process_subcommand_invalid(shared_ptr<ServerState>,
|
||||
shared_ptr<Lobby>, shared_ptr<Client>, uint8_t command, uint8_t flag,
|
||||
const PSOSubcommand* p, size_t count) {
|
||||
@@ -951,7 +960,7 @@ subcommand_handler_t subcommand_handlers[0x100] = {
|
||||
process_subcommand_drop_item,
|
||||
process_subcommand_unimplemented,
|
||||
process_subcommand_forward_check_size,
|
||||
process_subcommand_forward_check_size_game,
|
||||
process_subcommand_forward_check_size,
|
||||
process_subcommand_unimplemented,
|
||||
process_subcommand_hit_by_monster,
|
||||
// 30
|
||||
@@ -1106,7 +1115,7 @@ subcommand_handler_t subcommand_handlers[0x100] = {
|
||||
process_subcommand_unimplemented,
|
||||
process_subcommand_bank_action,
|
||||
process_subcommand_unimplemented,
|
||||
process_subcommand_unimplemented,
|
||||
process_subcommand_forward_check_size_ep3_lobby,
|
||||
// C0
|
||||
process_subcommand_unimplemented,
|
||||
process_subcommand_unimplemented,
|
||||
|
||||
+29
-1
@@ -1847,7 +1847,6 @@ void send_player_stats_change(shared_ptr<Lobby> l, shared_ptr<Client> c,
|
||||
send_command(l, 0x60, 0x00, subs);
|
||||
}
|
||||
|
||||
// sends a player to the given area.
|
||||
void send_warp(shared_ptr<Client> c, uint32_t area) {
|
||||
PSOSubcommand cmds[2];
|
||||
cmds[0].byte[0] = 0x94;
|
||||
@@ -1858,6 +1857,35 @@ void send_warp(shared_ptr<Client> c, uint32_t area) {
|
||||
send_command(c, 0x62, c->lobby_client_id, cmds, 8);
|
||||
}
|
||||
|
||||
void send_ep3_change_music(shared_ptr<Client> c, uint32_t song) {
|
||||
PSOSubcommand cmds[2];
|
||||
cmds[0].byte[0] = 0xBF;
|
||||
cmds[0].byte[1] = 0x02;
|
||||
cmds[0].byte[2] = c->lobby_client_id;
|
||||
cmds[0].byte[3] = 0x00;
|
||||
cmds[1].dword = song;
|
||||
send_command(c, 0x60, 0x00, cmds, 8);
|
||||
}
|
||||
|
||||
void send_set_player_visibility(shared_ptr<Lobby> l, shared_ptr<Client> c,
|
||||
bool visible) {
|
||||
PSOSubcommand cmd;
|
||||
cmd.byte[0] = visible ? 0x23 : 0x22;
|
||||
cmd.byte[1] = 0x01;
|
||||
cmd.byte[2] = c->lobby_client_id;
|
||||
cmd.byte[3] = 0x00;
|
||||
send_command(l, 0x60, 0x00, &cmd, 4);
|
||||
}
|
||||
|
||||
void send_revive_player(shared_ptr<Lobby> l, shared_ptr<Client> c) {
|
||||
PSOSubcommand cmd;
|
||||
cmd.byte[0] = 0x31;
|
||||
cmd.byte[1] = 0x01;
|
||||
cmd.byte[2] = c->lobby_client_id;
|
||||
cmd.byte[3] = 0x00;
|
||||
send_command(l, 0x60, 0x00, &cmd, 4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -158,6 +158,11 @@ void send_player_stats_change(std::shared_ptr<Lobby> l, std::shared_ptr<Client>
|
||||
PlayerStatsChange which, uint32_t amount);
|
||||
void send_warp(std::shared_ptr<Client> c, uint32_t area);
|
||||
|
||||
void send_ep3_change_music(std::shared_ptr<Client> c, uint32_t song);
|
||||
void send_set_player_visibility(std::shared_ptr<Lobby> l,
|
||||
std::shared_ptr<Client> c, bool visible);
|
||||
void send_revive_player(std::shared_ptr<Lobby> l, std::shared_ptr<Client> c);
|
||||
|
||||
void send_drop_item(std::shared_ptr<Lobby> l, const ItemData& item,
|
||||
bool from_enemy, uint8_t area, float x, float y, uint16_t request_id);
|
||||
void send_drop_stacked_item(std::shared_ptr<Lobby> l, const ItemData& item,
|
||||
|
||||
Reference in New Issue
Block a user