add in-game debug messages

This commit is contained in:
Martin Michelsen
2023-03-03 22:57:28 -08:00
parent aea43781ea
commit d5ececfa87
7 changed files with 92 additions and 22 deletions
+1 -1
View File
@@ -228,7 +228,7 @@ Some commands only work on the game server and not on the proxy server. The chat
* `$what` (game server only): Shows the type, name, and stats of the nearest item on the ground.
* Debugging commands
* `$dbgid` (game server only): Enable or disable high ID preference. When enabled, you'll be placed into the highest available slot in lobbies and games instead of the lowest. This is useful for finding commands for which newserv doesn't handle client IDs properly.
* `$debug` (game server only): Enable or disable debugging. When enabled, you'll see purple debug messages from the server when you take certain actions. You'll also be placed into the highest available slot in lobbies and games instead of the lowest, which is useful for finding commands for which newserv doesn't handle client IDs properly.
* `$gc` (game server only): Send your own Guild Card to yourself.
* `$persist` (game server only): Enable or disable persistence for the current lobby or game. This determines whether the lobby/game is deleted when the last player leaves. You need the DEBUG permission in your user license to use this command because there are no game state checks when you do this. For example, if you make a game persistent, start a quest, then leave the game, the game can't be joined by anyone but also can't be deleted.
* `$sc <data>`: Send a command to yourself.
+5 -5
View File
@@ -234,11 +234,11 @@ static void proxy_command_arrow(shared_ptr<ServerState>,
session.server_channel.send(0x89, stoull(encode_sjis(args), nullptr, 0));
}
static void server_command_dbgid(shared_ptr<ServerState>, shared_ptr<Lobby>,
static void server_command_debug(shared_ptr<ServerState>, shared_ptr<Lobby>,
shared_ptr<Client> c, const std::u16string&) {
c->options.prefer_high_lobby_client_id = !c->options.prefer_high_lobby_client_id;
send_text_message_printf(c, "ID preference set\nto $C6%s",
c->options.prefer_high_lobby_client_id ? "high" : "low");
c->options.debug = !c->options.debug;
send_text_message_printf(c, "Debug %s",
c->options.debug ? "enabled" : "disabled");
}
static void server_command_auction(shared_ptr<ServerState>, shared_ptr<Lobby> l,
@@ -1186,7 +1186,7 @@ static const unordered_map<u16string, ChatCommandDefinition> chat_commands({
// 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"$debug", {server_command_debug, nullptr, u"Usage:\ndebug"}},
{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"$exit", {server_command_exit, proxy_command_exit, u"Usage:\nexit"}},
+1 -1
View File
@@ -29,7 +29,7 @@ ClientOptions::ClientOptions()
: switch_assist(false),
infinite_hp(false),
infinite_tp(false),
prefer_high_lobby_client_id(false),
debug(false),
override_section_id(-1),
override_lobby_event(-1),
override_lobby_number(-1),
+1 -1
View File
@@ -29,7 +29,7 @@ struct ClientOptions {
bool switch_assist;
bool infinite_hp;
bool infinite_tp;
bool prefer_high_lobby_client_id;
bool debug;
int16_t override_section_id;
int16_t override_lobby_event;
int16_t override_lobby_number;
+1 -1
View File
@@ -81,7 +81,7 @@ void Lobby::add_client(shared_ptr<Client> c, ssize_t required_client_id) {
this->clients[required_client_id] = c;
index = required_client_id;
} else if (c->options.prefer_high_lobby_client_id) {
} else if (c->options.debug) {
for (index = max_clients - 1; index >= min_client_id; index--) {
if (!this->clients[index].get()) {
this->clients[index] = c;
+80 -11
View File
@@ -156,6 +156,9 @@ static void on_unimplemented(shared_ptr<ServerState>,
} else {
c->log.warning("Unknown subcommand: %02hhX (public)", cmd.subcommand);
}
if (c->options.debug) {
send_text_message_printf(c, "$C5Sub 6x%02hhX missing", cmd.subcommand);
}
}
@@ -438,6 +441,9 @@ static void on_switch_state_changed(shared_ptr<ServerState>,
if ((l->flags & Lobby::Flag::CHEATS_ENABLED) && c->options.switch_assist &&
(c->last_switch_enabled_command.header.subcommand == 0x05)) {
c->log.info("[Switch assist] Replaying previous enable command");
if (c->options.debug) {
send_text_message(c, u"$C5Switch assist");
}
forward_subcommand(l, c, command, flag, &c->last_switch_enabled_command,
sizeof(c->last_switch_enabled_command));
send_command_t(c, command, flag, c->last_switch_enabled_command);
@@ -484,6 +490,11 @@ static void on_player_drop_item(shared_ptr<ServerState>,
l->log.info("Player %hu dropped item %08" PRIX32 " (%s) at %hu:(%g, %g)",
cmd.header.client_id.load(), cmd.item_id.load(), name.c_str(),
cmd.area.load(), cmd.x.load(), cmd.z.load());
if (c->options.debug) {
string name = name_for_item(item.data, true);
send_text_message_printf(c, "$C5Items: drop %08" PRIX32 "\n%s",
cmd.item_id.load(), name.c_str());
}
c->game_data.player()->print_inventory(stderr);
}
@@ -515,6 +526,11 @@ static void on_create_inventory_item(shared_ptr<ServerState>,
auto name = name_for_item(item.data, false);
l->log.info("Player %hu created inventory item %08" PRIX32 " (%s)",
cmd.header.client_id.load(), cmd.item.id.load(), name.c_str());
if (c->options.debug) {
string name = name_for_item(item.data, true);
send_text_message_printf(c, "$C5Items: create %08" PRIX32 "\n%s",
cmd.item.id.load(), name.c_str());
}
c->game_data.player()->print_inventory(stderr);
}
@@ -548,6 +564,11 @@ static void on_drop_partial_stack(shared_ptr<ServerState>,
l->log.info("Player %hu split stack to create ground item %08" PRIX32 " (%s) at %hu:(%g, %g)",
cmd.header.client_id.load(), item.data.id.load(), name.c_str(),
cmd.area.load(), cmd.x.load(), cmd.z.load());
if (c->options.debug) {
string name = name_for_item(item.data, true);
send_text_message_printf(c, "$C5Items: split %08" PRIX32 "\n%s",
item.data.id.load(), name.c_str());
}
c->game_data.player()->print_inventory(stderr);
}
@@ -588,6 +609,11 @@ static void on_drop_partial_stack_bb(shared_ptr<ServerState>,
l->log.info("Player %hu split stack %08" PRIX32 " (removed: %s) at %hu:(%g, %g)",
cmd.header.client_id.load(), cmd.item_id.load(), name.c_str(),
cmd.area.load(), cmd.x.load(), cmd.z.load());
if (c->options.debug) {
string name = name_for_item(item.data, true);
send_text_message_printf(c, "$C5Items: split/BB %08" PRIX32 "\n%s",
cmd.item_id.load(), name.c_str());
}
c->game_data.player()->print_inventory(stderr);
send_drop_stacked_item(l, item.data, cmd.area, cmd.x, cmd.z);
@@ -619,6 +645,11 @@ static void on_buy_shop_item(shared_ptr<ServerState>,
auto name = name_for_item(item.data, false);
l->log.info("Player %hu bought item %08" PRIX32 " (%s) from shop",
cmd.header.client_id.load(), item.data.id.load(), name.c_str());
if (c->options.debug) {
string name = name_for_item(item.data, true);
send_text_message_printf(c, "$C5Items: buy %08" PRIX32 "\n%s",
item.data.id.load(), name.c_str());
}
c->game_data.player()->print_inventory(stderr);
}
@@ -648,6 +679,11 @@ static void on_box_or_enemy_item_drop(shared_ptr<ServerState>,
auto name = name_for_item(item.data, false);
l->log.info("Leader created ground item %08" PRIX32 " (%s) at %hhu:(%g, %g)",
item.data.id.load(), name.c_str(), cmd.area, cmd.x.load(), cmd.z.load());
if (c->options.debug) {
string name = name_for_item(item.data, true);
send_text_message_printf(c, "$C5Items: drop %08" PRIX32 "\n%s",
item.data.id.load(), name.c_str());
}
}
forward_subcommand(l, c, command, flag, data);
@@ -679,6 +715,11 @@ static void on_pick_up_item(shared_ptr<ServerState>,
auto name = name_for_item(item.data, false);
l->log.info("Player %hu picked up %08" PRIX32 " (%s)",
cmd.header.client_id.load(), cmd.item_id.load(), name.c_str());
if (c->options.debug) {
string name = name_for_item(item.data, true);
send_text_message_printf(c, "$C5Items: pick %08" PRIX32 "\n%s",
cmd.item_id.load(), name.c_str());
}
effective_c->game_data.player()->print_inventory(stderr);
}
@@ -706,6 +747,11 @@ static void on_pick_up_item_request(shared_ptr<ServerState>,
auto name = name_for_item(item.data, false);
l->log.info("Player %hu picked up %08" PRIX32 " (%s)",
cmd.header.client_id.load(), cmd.item_id.load(), name.c_str());
if (c->options.debug) {
string name = name_for_item(item.data, true);
send_text_message_printf(c, "$C5Items: pick/BB %08" PRIX32 "\n%s",
cmd.item_id.load(), name.c_str());
}
c->game_data.player()->print_inventory(stderr);
send_pick_up_item(l, c, cmd.item_id, cmd.area);
@@ -751,11 +797,22 @@ static void on_use_item(shared_ptr<ServerState>,
if (l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED) {
size_t index = c->game_data.player()->inventory.find_item(cmd.item_id);
auto name = name_for_item(c->game_data.player()->inventory.items[index].data, false);
string name, colored_name;
{
// Note: We do this weird scoping thing because player_use_item will
// likely delete the item, which will break the reference here.
const auto& item = c->game_data.player()->inventory.items[index].data;
name = name_for_item(item, false);
colored_name = name_for_item(item, true);
}
player_use_item(c, index);
l->log.info("Player used item %hu:%08" PRIX32 " (%s)",
cmd.header.client_id.load(), cmd.item_id.load(), name.c_str());
if (c->options.debug) {
send_text_message_printf(c, "$C5Items: use %08" PRIX32 "\n%s",
cmd.item_id.load(), colored_name.c_str());
}
c->game_data.player()->print_inventory(stderr);
}
@@ -1077,20 +1134,28 @@ static void on_enemy_killed(shared_ptr<ServerState> s,
send_text_message(c, u"$C6Missing enemy killed");
return;
}
string e_str = l->enemies[cmd.enemy_id].str();
auto& e = l->enemies[cmd.enemy_id];
string e_str = e.str();
c->log.info("Enemy killed: entry %hu => %s", cmd.enemy_id.load(), e_str.c_str());
if (l->enemies[cmd.enemy_id].hit_flags & 0x80) {
if (e.hit_flags & 0x80) {
if (c->options.debug) {
send_text_message_printf(c, "$C5E-%hX (already dead)", cmd.enemy_id.load());
}
return; // Enemy is already dead
}
if (l->enemies[cmd.enemy_id].experience == 0xFFFFFFFF) {
send_text_message(c, u"$C6Unknown enemy type killed");
if (e.experience == 0xFFFFFFFF) {
if (c->options.debug) {
send_text_message_printf(c, "$C5E-%hX (missing definition)", cmd.enemy_id.load());
} else {
send_text_message(c, u"$C6Unknown enemy type killed");
}
return;
}
auto& enemy = l->enemies[cmd.enemy_id];
enemy.hit_flags |= 0x80;
e.hit_flags |= 0x80;
for (size_t x = 0; x < l->max_clients; x++) {
if (!((enemy.hit_flags >> x) & 1)) {
if (!((e.hit_flags >> x) & 1)) {
continue; // Player did not hit this enemy
}
@@ -1104,14 +1169,18 @@ static void on_enemy_killed(shared_ptr<ServerState> s,
// Killer gets full experience, others get 77%
uint32_t exp;
if (enemy.last_hit == other_c->lobby_client_id) {
exp = enemy.experience;
if (e.last_hit == other_c->lobby_client_id) {
exp = e.experience;
} else {
exp = ((enemy.experience * 77) / 100);
exp = ((e.experience * 77) / 100);
}
other_c->game_data.player()->disp.experience += exp;
send_give_experience(l, other_c, exp);
if (other_c->options.debug) {
send_text_message_printf(other_c, "$C5+%" PRIu32 " E-%hX (%s)",
exp, cmd.enemy_id.load(), e.type_name);
}
bool leveled_up = false;
do {
+3 -2
View File
@@ -1465,7 +1465,8 @@ uint8_t technique_for_name(const u16string& name) {
string name_for_item(const ItemData& item, bool include_color_codes) {
if (item.data1[0] == 0x04) {
return string_printf("%" PRIu32 " Meseta", item.data2d.load());
return string_printf("%s%" PRIu32 " Meseta",
include_color_codes ? "$C7" : "", item.data2d.load());
}
vector<string> ret_tokens;
@@ -1705,7 +1706,7 @@ string name_for_item(const ItemData& item, bool include_color_codes) {
} else if (name_info.is_rare) {
return "$C6" + ret;
} else {
return ret;
return "$C7" + ret;
}
} else {
return ret;