add get_player_card
This commit is contained in:
+55
-30
@@ -243,6 +243,31 @@ static void server_command_get_self_card(shared_ptr<ServerState>, shared_ptr<Lob
|
||||
send_guild_card(c, c);
|
||||
}
|
||||
|
||||
static void proxy_command_get_player_card(shared_ptr<ServerState>,
|
||||
ProxyServer::LinkedSession& session, const std::u16string& u16args) {
|
||||
string args = encode_sjis(u16args);
|
||||
|
||||
bool any_card_sent = false;
|
||||
for (const auto& p : session.lobby_players) {
|
||||
if (!p.name.empty() && args == p.name) {
|
||||
send_guild_card(session.client_channel, p.guild_card_number, decode_sjis(p.name), u"", u"", p.section_id, p.char_class);
|
||||
any_card_sent = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!any_card_sent) {
|
||||
try {
|
||||
size_t index = stoull(args, nullptr, 0);
|
||||
const auto& p = session.lobby_players.at(index);
|
||||
if (!p.name.empty()) {
|
||||
send_guild_card(session.client_channel, p.guild_card_number, decode_sjis(p.name), u"", u"", p.section_id, p.char_class);
|
||||
}
|
||||
} catch (const exception& e) {
|
||||
send_text_message_printf(session.client_channel, "Error: %s", e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Lobby commands
|
||||
|
||||
@@ -924,39 +949,39 @@ struct ChatCommandDefinition {
|
||||
|
||||
static const unordered_map<u16string, ChatCommandDefinition> chat_commands({
|
||||
// TODO: implement command_help and actually use the usage strings here
|
||||
{u"$allevent", {server_command_lobby_event_all, nullptr, u"Usage:\nallevent <name/ID>"}},
|
||||
{u"$ann", {server_command_announce, nullptr, u"Usage:\nann <message>"}},
|
||||
{u"$arrow", {server_command_arrow, proxy_command_arrow, u"Usage:\narrow <color>"}},
|
||||
{u"$ax", {server_command_ax, nullptr, u"Usage:\nax <message>"}},
|
||||
{u"$ban", {server_command_ban, nullptr, u"Usage:\nban <name-or-number>"}},
|
||||
{u"$allevent", {server_command_lobby_event_all, nullptr, u"Usage:\nallevent <name/ID>"}},
|
||||
{u"$ann", {server_command_announce, nullptr, u"Usage:\nann <message>"}},
|
||||
{u"$arrow", {server_command_arrow, proxy_command_arrow, u"Usage:\narrow <color>"}},
|
||||
{u"$ax", {server_command_ax, nullptr, u"Usage:\nax <message>"}},
|
||||
{u"$ban", {server_command_ban, nullptr, u"Usage:\nban <name-or-number>"}},
|
||||
// TODO: implement this on proxy server
|
||||
{u"$bbchar", {server_command_convert_char_to_bb, nullptr, u"Usage:\nbbchar <user> <pass> <1-4>"}},
|
||||
{u"$cheat", {server_command_cheat, nullptr, u"Usage:\ncheat"}},
|
||||
{u"$dbgid", {server_command_dbgid, nullptr, u"Usage:\ndbgid"}},
|
||||
{u"$edit", {server_command_edit, nullptr , u"Usage:\nedit <stat> <value>"}},
|
||||
{u"$event", {server_command_lobby_event, proxy_command_lobby_event, u"Usage:\nevent <name>"}},
|
||||
{u"$gc", {server_command_get_self_card, nullptr, u"Usage:\ngc"}},
|
||||
{u"$infhp", {server_command_infinite_hp, proxy_command_infinite_hp, u"Usage:\ninfhp"}},
|
||||
{u"$inftp", {server_command_infinite_tp, proxy_command_infinite_tp, u"Usage:\ninftp"}},
|
||||
{u"$item", {server_command_item, proxy_command_item, u"Usage:\nitem <item-code>"}},
|
||||
{u"$kick", {server_command_kick, nullptr, u"Usage:\nkick <name-or-number>"}},
|
||||
{u"$li", {server_command_lobby_info, proxy_command_lobby_info, u"Usage:\nli"}},
|
||||
{u"$maxlevel", {server_command_max_level, nullptr, u"Usage:\nmax_level <level>"}},
|
||||
{u"$minlevel", {server_command_min_level, nullptr, u"Usage:\nmin_level <level>"}},
|
||||
{u"$bbchar", {server_command_convert_char_to_bb, nullptr, u"Usage:\nbbchar <user> <pass> <1-4>"}},
|
||||
{u"$cheat", {server_command_cheat, nullptr, u"Usage:\ncheat"}},
|
||||
{u"$dbgid", {server_command_dbgid, nullptr, u"Usage:\ndbgid"}},
|
||||
{u"$edit", {server_command_edit, nullptr , u"Usage:\nedit <stat> <value>"}},
|
||||
{u"$event", {server_command_lobby_event, proxy_command_lobby_event, u"Usage:\nevent <name>"}},
|
||||
{u"$gc", {server_command_get_self_card, proxy_command_get_player_card, u"Usage:\ngc"}},
|
||||
{u"$infhp", {server_command_infinite_hp, proxy_command_infinite_hp, u"Usage:\ninfhp"}},
|
||||
{u"$inftp", {server_command_infinite_tp, proxy_command_infinite_tp, u"Usage:\ninftp"}},
|
||||
{u"$item", {server_command_item, proxy_command_item, u"Usage:\nitem <item-code>"}},
|
||||
{u"$kick", {server_command_kick, nullptr, u"Usage:\nkick <name-or-number>"}},
|
||||
{u"$li", {server_command_lobby_info, proxy_command_lobby_info, u"Usage:\nli"}},
|
||||
{u"$maxlevel", {server_command_max_level, nullptr, u"Usage:\nmax_level <level>"}},
|
||||
{u"$minlevel", {server_command_min_level, nullptr, u"Usage:\nmin_level <level>"}},
|
||||
// TODO: implement this on proxy server
|
||||
{u"$next", {server_command_next, nullptr, u"Usage:\nnext"}},
|
||||
{u"$password", {server_command_password, nullptr, u"Usage:\nlock [password]\nomit password to\nunlock game"}},
|
||||
{u"$persist", {server_command_persist, nullptr, u"Usage:\npersist"}},
|
||||
{u"$proxygc", {server_command_proxygc, proxy_command_proxygc, u"Usage:\nproxygc <gc#>"}},
|
||||
{u"$rand", {server_command_rand, proxy_command_rand, u"Usage:\nrand [hex seed]\nomit seed to revert\nto default"}},
|
||||
{u"$secid", {server_command_secid, proxy_command_secid, u"Usage:\nsecid [section ID]\nomit section ID to\nrevert to normal"}},
|
||||
{u"$silence", {server_command_silence, nullptr, u"Usage:\nsilence <name-or-number>"}},
|
||||
{u"$next", {server_command_next, nullptr, u"Usage:\nnext"}},
|
||||
{u"$password", {server_command_password, nullptr, u"Usage:\nlock [password]\nomit password to\nunlock game"}},
|
||||
{u"$persist", {server_command_persist, nullptr, u"Usage:\npersist"}},
|
||||
{u"$proxygc", {server_command_proxygc, proxy_command_proxygc, u"Usage:\nproxygc <gc#>"}},
|
||||
{u"$rand", {server_command_rand, proxy_command_rand, u"Usage:\nrand [hex seed]\nomit seed to revert\nto default"}},
|
||||
{u"$secid", {server_command_secid, proxy_command_secid, u"Usage:\nsecid [section ID]\nomit section ID to\nrevert to normal"}},
|
||||
{u"$silence", {server_command_silence, nullptr, u"Usage:\nsilence <name-or-number>"}},
|
||||
// TODO: implement this on proxy server
|
||||
{u"$song", {server_command_song, nullptr, u"Usage:\nsong <song-number>"}},
|
||||
{u"$swa", {server_command_switch_assist, proxy_command_switch_assist, u"Usage:\nswa"}},
|
||||
{u"$type", {server_command_lobby_type, nullptr, u"Usage:\ntype <name>"}},
|
||||
{u"$warp", {server_command_warp, proxy_command_warp, u"Usage:\nwarp <area-number>"}},
|
||||
{u"$what", {server_command_what, nullptr, u"Usage:\nwhat"}},
|
||||
{u"$song", {server_command_song, nullptr, u"Usage:\nsong <song-number>"}},
|
||||
{u"$swa", {server_command_switch_assist, proxy_command_switch_assist, u"Usage:\nswa"}},
|
||||
{u"$type", {server_command_lobby_type, nullptr, u"Usage:\ntype <name>"}},
|
||||
{u"$warp", {server_command_warp, proxy_command_warp, u"Usage:\nwarp <area-number>"}},
|
||||
{u"$what", {server_command_what, nullptr, u"Usage:\nwhat"}},
|
||||
});
|
||||
|
||||
struct SplitCommand {
|
||||
|
||||
+19
-14
@@ -1002,13 +1002,14 @@ static HandlerResult S_65_67_68(shared_ptr<ServerState>,
|
||||
num_replacements++;
|
||||
modified = true;
|
||||
}
|
||||
session.lobby_players[index].guild_card_number = cmd.entries[x].lobby_data.guild_card;
|
||||
auto& p = session.lobby_players[index];
|
||||
p.guild_card_number = cmd.entries[x].lobby_data.guild_card;
|
||||
ptext<char, 0x10> name = cmd.entries[x].disp.name;
|
||||
session.lobby_players[index].name = name;
|
||||
p.name = name;
|
||||
p.section_id = cmd.entries[x].disp.section_id;
|
||||
p.char_class = cmd.entries[x].disp.char_class;
|
||||
session.log.info("Added lobby player: (%zu) %" PRIu32 " %s",
|
||||
index,
|
||||
session.lobby_players[index].guild_card_number,
|
||||
session.lobby_players[index].name.c_str());
|
||||
index, p.guild_card_number, p.name.c_str());
|
||||
}
|
||||
}
|
||||
if (num_replacements > 1) {
|
||||
@@ -1057,17 +1058,18 @@ static HandlerResult S_64(shared_ptr<ServerState>,
|
||||
cmd->lobby_data[x].guild_card = session.license->serial_number;
|
||||
modified = true;
|
||||
}
|
||||
session.lobby_players[x].guild_card_number = cmd->lobby_data[x].guild_card;
|
||||
auto& p = session.lobby_players[x];
|
||||
p.guild_card_number = cmd->lobby_data[x].guild_card;
|
||||
if (cmd_ep3) {
|
||||
ptext<char, 0x10> name = cmd_ep3->players_ep3[x].disp.name;
|
||||
session.lobby_players[x].name = name;
|
||||
p.name = name;
|
||||
p.section_id = cmd_ep3->players_ep3[x].disp.section_id;
|
||||
p.char_class = cmd_ep3->players_ep3[x].disp.char_class;
|
||||
} else {
|
||||
session.lobby_players[x].name.clear();
|
||||
p.name.clear();
|
||||
}
|
||||
session.log.info("Added lobby player: (%zu) %" PRIu32 " %s",
|
||||
x,
|
||||
session.lobby_players[x].guild_card_number,
|
||||
session.lobby_players[x].name.c_str());
|
||||
x, p.guild_card_number, p.name.c_str());
|
||||
}
|
||||
|
||||
if (session.override_section_id >= 0) {
|
||||
@@ -1098,8 +1100,9 @@ static HandlerResult S_66_69(shared_ptr<ServerState>,
|
||||
if (index >= session.lobby_players.size()) {
|
||||
session.log.warning("Lobby leave command references missing position");
|
||||
} else {
|
||||
session.lobby_players[index].guild_card_number = 0;
|
||||
session.lobby_players[index].name.clear();
|
||||
auto& p = session.lobby_players[index];
|
||||
p.guild_card_number = 0;
|
||||
p.name.clear();
|
||||
session.log.info("Removed lobby player (%zu)", index);
|
||||
}
|
||||
update_leader_id(session, cmd.leader_id);
|
||||
@@ -1197,7 +1200,9 @@ template <typename SendGuildCardCmdT>
|
||||
static HandlerResult C_6x(shared_ptr<ServerState> s,
|
||||
ProxyServer::LinkedSession& session, uint16_t command, uint32_t flag, string& data) {
|
||||
if (session.license && !data.empty()) {
|
||||
if (data[0] == 0x06) {
|
||||
// On BB, the 6x06 command is blank - the server generates the actual Guild
|
||||
// Card contents and sends it to the target client.
|
||||
if (data[0] == 0x06 && session.version != GameVersion::BB) {
|
||||
auto& cmd = check_size_t<SendGuildCardCmdT>(data);
|
||||
if (cmd.guild_card_number == session.license->serial_number) {
|
||||
cmd.guild_card_number = session.remote_guild_card_number;
|
||||
|
||||
+3
-1
@@ -78,7 +78,9 @@ public:
|
||||
struct LobbyPlayer {
|
||||
uint32_t guild_card_number;
|
||||
std::string name;
|
||||
LobbyPlayer() : guild_card_number(0) { }
|
||||
uint8_t section_id;
|
||||
uint8_t char_class;
|
||||
LobbyPlayer() : guild_card_number(0), section_id(0), char_class(0) { }
|
||||
};
|
||||
std::vector<LobbyPlayer> lobby_players;
|
||||
size_t lobby_client_id;
|
||||
|
||||
+64
-25
@@ -770,54 +770,93 @@ void send_card_search_result(
|
||||
|
||||
|
||||
template <typename CmdT>
|
||||
void send_guild_card_dc_pc_v3_t(shared_ptr<Client> c, shared_ptr<Client> source) {
|
||||
void send_guild_card_dc_pc_v3_t(
|
||||
Channel& ch,
|
||||
uint32_t guild_card_number,
|
||||
const u16string& name,
|
||||
const u16string& description,
|
||||
uint8_t section_id,
|
||||
uint8_t char_class) {
|
||||
CmdT cmd;
|
||||
cmd.subcommand = 0x06;
|
||||
cmd.size = sizeof(CmdT) / 4;
|
||||
cmd.unused = 0x0000;
|
||||
cmd.player_tag = 0x00010000;
|
||||
cmd.guild_card_number = source->license->serial_number;
|
||||
cmd.name = source->game_data.player()->disp.name;
|
||||
cmd.guild_card_number = guild_card_number;
|
||||
cmd.name = name;
|
||||
remove_language_marker_inplace(cmd.name);
|
||||
cmd.description = source->game_data.player()->guild_card_description;
|
||||
cmd.description = description;
|
||||
cmd.present = 1;
|
||||
cmd.present2 = 1;
|
||||
cmd.section_id = source->game_data.player()->disp.section_id;
|
||||
cmd.char_class = source->game_data.player()->disp.char_class;
|
||||
send_command_t(c, 0x62, c->lobby_client_id, cmd);
|
||||
cmd.section_id = section_id;
|
||||
cmd.char_class = char_class;
|
||||
ch.send(0x60, 0x00, &cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
void send_guild_card_bb(shared_ptr<Client> c, shared_ptr<Client> source) {
|
||||
static void send_guild_card_bb(
|
||||
Channel& ch,
|
||||
uint32_t guild_card_number,
|
||||
const u16string& name,
|
||||
const u16string& team_name,
|
||||
const u16string& description,
|
||||
uint8_t section_id,
|
||||
uint8_t char_class) {
|
||||
G_SendGuildCard_BB_6x06 cmd;
|
||||
cmd.subcommand = 0x06;
|
||||
cmd.size = sizeof(cmd) / 4;
|
||||
cmd.unused = 0x0000;
|
||||
cmd.guild_card_number = source->license->serial_number;
|
||||
cmd.name = remove_language_marker(source->game_data.player()->disp.name);
|
||||
cmd.team_name = remove_language_marker(source->game_data.account()->team_name);
|
||||
cmd.description = source->game_data.player()->guild_card_description;
|
||||
cmd.guild_card_number = guild_card_number;
|
||||
cmd.name = remove_language_marker(name);
|
||||
cmd.team_name = remove_language_marker(team_name);
|
||||
cmd.description = description;
|
||||
cmd.present = 1;
|
||||
cmd.present2 = 1;
|
||||
cmd.section_id = source->game_data.player()->disp.section_id;
|
||||
cmd.char_class = source->game_data.player()->disp.char_class;
|
||||
send_command_t(c, 0x62, c->lobby_client_id, cmd);
|
||||
cmd.section_id = section_id;
|
||||
cmd.char_class = char_class;
|
||||
ch.send(0x60, 0x00, &cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
void send_guild_card(shared_ptr<Client> c, shared_ptr<Client> source) {
|
||||
if (c->version() == GameVersion::DC) {
|
||||
send_guild_card_dc_pc_v3_t<G_SendGuildCard_DC_6x06>(c, source);
|
||||
} else if (c->version() == GameVersion::PC) {
|
||||
send_guild_card_dc_pc_v3_t<G_SendGuildCard_PC_6x06>(c, source);
|
||||
} else if ((c->version() == GameVersion::GC) ||
|
||||
(c->version() == GameVersion::XB)) {
|
||||
send_guild_card_dc_pc_v3_t<G_SendGuildCard_V3_6x06>(c, source);
|
||||
} else if (c->version() == GameVersion::BB) {
|
||||
send_guild_card_bb(c, source);
|
||||
void send_guild_card(
|
||||
Channel& ch,
|
||||
uint32_t guild_card_number,
|
||||
const u16string& name,
|
||||
const u16string& team_name,
|
||||
const u16string& description,
|
||||
uint8_t section_id,
|
||||
uint8_t char_class) {
|
||||
if (ch.version == GameVersion::DC) {
|
||||
send_guild_card_dc_pc_v3_t<G_SendGuildCard_DC_6x06>(
|
||||
ch, guild_card_number, name, description, section_id, char_class);
|
||||
} else if (ch.version == GameVersion::PC) {
|
||||
send_guild_card_dc_pc_v3_t<G_SendGuildCard_PC_6x06>(
|
||||
ch, guild_card_number, name, description, section_id, char_class);
|
||||
} else if ((ch.version == GameVersion::GC) ||
|
||||
(ch.version == GameVersion::XB)) {
|
||||
send_guild_card_dc_pc_v3_t<G_SendGuildCard_V3_6x06>(
|
||||
ch, guild_card_number, name, description, section_id, char_class);
|
||||
} else if (ch.version == GameVersion::BB) {
|
||||
send_guild_card_bb(
|
||||
ch, guild_card_number, name, team_name, description, section_id, char_class);
|
||||
} else {
|
||||
throw logic_error("unimplemented versioned command");
|
||||
}
|
||||
}
|
||||
|
||||
void send_guild_card(shared_ptr<Client> c, shared_ptr<Client> source) {
|
||||
if (!source->license) {
|
||||
throw runtime_error("source player does not have a license");
|
||||
}
|
||||
|
||||
uint32_t guild_card_number = source->license->serial_number;
|
||||
u16string name = source->game_data.player()->disp.name;
|
||||
u16string description = source->game_data.player()->guild_card_description;
|
||||
uint8_t section_id = source->game_data.player()->disp.section_id;
|
||||
uint8_t char_class = source->game_data.player()->disp.char_class;
|
||||
|
||||
send_guild_card(
|
||||
c->channel, guild_card_number, name, u"", description, section_id, char_class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -182,6 +182,14 @@ void send_card_search_result(
|
||||
std::shared_ptr<Client> result,
|
||||
std::shared_ptr<Lobby> result_lobby);
|
||||
|
||||
void send_guild_card(
|
||||
Channel& ch,
|
||||
uint32_t guild_card_number,
|
||||
const u16string& name,
|
||||
const u16string& team_name,
|
||||
const u16string& description,
|
||||
uint8_t section_id,
|
||||
uint8_t char_class);
|
||||
void send_guild_card(std::shared_ptr<Client> c, std::shared_ptr<Client> source);
|
||||
void send_menu(std::shared_ptr<Client> c, const std::u16string& menu_name,
|
||||
uint32_t menu_id, const std::vector<MenuItem>& items, bool is_info_menu = false);
|
||||
|
||||
Reference in New Issue
Block a user