make it possible to disable item tracking

This commit is contained in:
Martin Michelsen
2022-06-24 22:00:47 -07:00
parent c2b112db43
commit fc078a5d51
10 changed files with 168 additions and 85 deletions
+24 -21
View File
@@ -590,28 +590,31 @@ static void command_what(shared_ptr<ServerState>, shared_ptr<Lobby> l,
if (!l->episode || (l->episode > 3)) {
return;
}
float min_dist2 = 0.0f;
uint32_t nearest_item_id = 0xFFFFFFFF;
for (const auto& it : l->item_id_to_floor_item) {
if (it.second.area != c->area) {
continue;
}
float dx = it.second.x - c->x;
float dz = it.second.z - c->z;
float dist2 = (dx * dx) + (dz * dz);
if ((nearest_item_id == 0xFFFFFFFF) || (dist2 < min_dist2)) {
nearest_item_id = it.first;
min_dist2 = dist2;
}
}
if (nearest_item_id == 0xFFFFFFFF) {
send_text_message(c, u"No items are near you");
if (!(l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
send_text_message(c, u"$C4Item tracking is off");
} else {
const auto& item = l->item_id_to_floor_item.at(nearest_item_id);
string name = name_for_item(item.inv_item.data, true);
send_text_message(c, decode_sjis(name));
float min_dist2 = 0.0f;
uint32_t nearest_item_id = 0xFFFFFFFF;
for (const auto& it : l->item_id_to_floor_item) {
if (it.second.area != c->area) {
continue;
}
float dx = it.second.x - c->x;
float dz = it.second.z - c->z;
float dist2 = (dx * dx) + (dz * dz);
if ((nearest_item_id == 0xFFFFFFFF) || (dist2 < min_dist2)) {
nearest_item_id = it.first;
min_dist2 = dist2;
}
}
if (nearest_item_id == 0xFFFFFFFF) {
send_text_message(c, u"$C4No items are near you");
} else {
const auto& item = l->item_id_to_floor_item.at(nearest_item_id);
string name = name_for_item(item.inv_item.data, true);
send_text_message(c, decode_sjis(name));
}
}
}
+3 -2
View File
@@ -96,8 +96,9 @@ void Lobby::add_client(shared_ptr<Client> c) {
}
}
// If the lobby is a game, assign the inventory's item IDs
if (this->is_game()) {
// If the lobby is a game and item tracking is enabled, assign the inventory's
// item IDs
if (this->is_game() && (this->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
auto& inv = c->game_data.player()->inventory;
size_t count = min<uint8_t>(inv.num_items, 30);
for (size_t x = 0; x < count; x++) {
+13 -8
View File
@@ -18,14 +18,19 @@
struct Lobby {
enum Flag {
GAME = 0x01,
CHEATS_ENABLED = 0x02, // game only
PUBLIC = 0x04, // lobby only
EPISODE_3_ONLY = 0x08, // lobby & game
QUEST_IN_PROGRESS = 0x10, // game only
JOINABLE_QUEST_IN_PROGRESS = 0x20, // game only
DEFAULT = 0x40, // lobby only; not set for games and private lobbies
PERSISTENT = 0x80, // if not set, lobby is deleted when empty
GAME = 0x00000001,
EPISODE_3_ONLY = 0x00000002,
// Flags used only for games
CHEATS_ENABLED = 0x00000100,
QUEST_IN_PROGRESS = 0x00000200,
JOINABLE_QUEST_IN_PROGRESS = 0x00000400,
ITEM_TRACKING_ENABLED = 0x00000800,
// Flags used only for lobbies
PUBLIC = 0x00010000,
DEFAULT = 0x00020000,
PERSISTENT = 0x00040000,
};
uint32_t lobby_id;
+6
View File
@@ -128,6 +128,12 @@ void populate_state_from_config(shared_ptr<ServerState> s,
s->allow_unregistered_users = true;
}
try {
s->item_tracking_enabled = d.at("EnableItemTracking")->as_bool();
} catch (const out_of_range&) {
s->item_tracking_enabled = true;
}
for (const string& filename : list_directory("system/blueburst/keys")) {
if (!ends_with(filename, ".nsk")) {
continue;
+6 -1
View File
@@ -1767,6 +1767,8 @@ shared_ptr<Lobby> create_game_generic(shared_ptr<ServerState> s,
throw invalid_argument("level too low for difficulty");
}
bool item_tracking_enabled = (c->version == GameVersion::BB) | s->item_tracking_enabled;
shared_ptr<Lobby> game(new Lobby());
game->name = name;
game->password = password;
@@ -1787,7 +1789,10 @@ shared_ptr<Lobby> create_game_generic(shared_ptr<ServerState> s,
game->event = Lobby::game_event_for_lobby_event(current_lobby->event);
game->block = 0xFF;
game->max_clients = 4;
game->flags = (is_ep3 ? Lobby::Flag::EPISODE_3_ONLY : 0) | Lobby::Flag::GAME;
game->flags =
(is_ep3 ? Lobby::Flag::EPISODE_3_ONLY : 0) |
(item_tracking_enabled ? Lobby::Flag::ITEM_TRACKING_ENABLED : 0) |
Lobby::Flag::GAME;
game->min_level = min_level;
game->max_level = 0xFFFFFFFF;
+104 -53
View File
@@ -273,12 +273,14 @@ static void process_subcommand_player_drop_item(shared_ptr<ServerState>,
return;
}
l->add_item(c->game_data.player()->remove_item(cmd->item_id, 0),
cmd->area, cmd->x, cmd->z);
if (l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED) {
l->add_item(c->game_data.player()->remove_item(cmd->item_id, 0),
cmd->area, cmd->x, cmd->z);
log(INFO, "[Items/%08" PRIX32 "] Player %hhu dropped item %08" PRIX32 " at %hu:(%g, %g)",
l->lobby_id, cmd->client_id, cmd->item_id.load(), cmd->area.load(), cmd->x.load(), cmd->z.load());
c->game_data.player()->print_inventory(stderr);
log(INFO, "[Items/%08" PRIX32 "] Player %hhu dropped item %08" PRIX32 " at %hu:(%g, %g)",
l->lobby_id, cmd->client_id, cmd->item_id.load(), cmd->area.load(), cmd->x.load(), cmd->z.load());
c->game_data.player()->print_inventory(stderr);
}
forward_subcommand(l, c, command, flag, data);
}
@@ -297,16 +299,18 @@ static void process_subcommand_create_inventory_item(shared_ptr<ServerState>,
return;
}
PlayerInventoryItem item;
item.equip_flags = 0; // TODO: Use the right default flags here
item.tech_flag = 0;
item.game_flags = 0;
item.data = cmd->item;
c->game_data.player()->add_item(item);
if (l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED) {
PlayerInventoryItem item;
item.equip_flags = 0; // TODO: Use the right default flags here
item.tech_flag = 0;
item.game_flags = 0;
item.data = cmd->item;
c->game_data.player()->add_item(item);
log(INFO, "[Items/%08" PRIX32 "] Player %hhu created inventory item %08" PRIX32,
l->lobby_id, cmd->client_id, cmd->item.id.load());
c->game_data.player()->print_inventory(stderr);
log(INFO, "[Items/%08" PRIX32 "] Player %hhu created inventory item %08" PRIX32,
l->lobby_id, cmd->client_id, cmd->item.id.load());
c->game_data.player()->print_inventory(stderr);
}
forward_subcommand(l, c, command, flag, data);
}
@@ -324,18 +328,20 @@ static void process_subcommand_drop_partial_stack(shared_ptr<ServerState>,
return;
}
// TODO: Should we delete anything from the inventory here? Does the client
// send an appropriate 6x29 alongside this?
PlayerInventoryItem item;
item.equip_flags = 0; // TODO: Use the right default flags here
item.tech_flag = 0;
item.game_flags = 0;
item.data = cmd->data;
l->add_item(item, cmd->area, cmd->x, cmd->z);
if (l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED) {
// TODO: Should we delete anything from the inventory here? Does the client
// send an appropriate 6x29 alongside this?
PlayerInventoryItem item;
item.equip_flags = 0; // TODO: Use the right default flags here
item.tech_flag = 0;
item.game_flags = 0;
item.data = cmd->data;
l->add_item(item, cmd->area, cmd->x, cmd->z);
log(INFO, "[Items/%08" PRIX32 "] Player %hhu split stack to create ground item %08" PRIX32 " at %hu:(%g, %g)",
l->lobby_id, cmd->client_id, item.data.id.load(), cmd->area.load(), cmd->x.load(), cmd->z.load());
c->game_data.player()->print_inventory(stderr);
log(INFO, "[Items/%08" PRIX32 "] Player %hhu split stack to create ground item %08" PRIX32 " at %hu:(%g, %g)",
l->lobby_id, cmd->client_id, item.data.id.load(), cmd->area.load(), cmd->x.load(), cmd->z.load());
c->game_data.player()->print_inventory(stderr);
}
forward_subcommand(l, c, command, flag, data);
}
@@ -350,6 +356,10 @@ static void process_subcommand_drop_partial_stack_bb(shared_ptr<ServerState>,
return;
}
if (!(l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
throw logic_error("item tracking not enabled in BB game");
}
auto item = c->game_data.player()->remove_item(cmd->item_id, cmd->amount);
// if a stack was split, the original item still exists, so the dropped item
@@ -389,16 +399,18 @@ static void process_subcommand_buy_shop_item(shared_ptr<ServerState>,
return;
}
PlayerInventoryItem item;
item.equip_flags = 0; // TODO: Use the right default flags here
item.tech_flag = 0;
item.game_flags = 0;
item.data = cmd->item;
c->game_data.player()->add_item(item);
if (l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED) {
PlayerInventoryItem item;
item.equip_flags = 0; // TODO: Use the right default flags here
item.tech_flag = 0;
item.game_flags = 0;
item.data = cmd->item;
c->game_data.player()->add_item(item);
log(INFO, "[Items/%08" PRIX32 "] Player %hhu bought item %08" PRIX32 " from shop",
l->lobby_id, cmd->client_id, item.data.id.load());
c->game_data.player()->print_inventory(stderr);
log(INFO, "[Items/%08" PRIX32 "] Player %hhu bought item %08" PRIX32 " from shop",
l->lobby_id, cmd->client_id, item.data.id.load());
c->game_data.player()->print_inventory(stderr);
}
forward_subcommand(l, c, command, flag, data);
}
@@ -447,10 +459,12 @@ static void process_subcommand_pick_up_item(shared_ptr<ServerState>,
return;
}
effective_c->game_data.player()->add_item(l->remove_item(cmd->item_id));
log(INFO, "[Items/%08" PRIX32 "] Player %hu picked up %08" PRIX32,
l->lobby_id, cmd->client_id.load(), cmd->item_id.load());
effective_c->game_data.player()->print_inventory(stderr);
if (l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED) {
effective_c->game_data.player()->add_item(l->remove_item(cmd->item_id));
log(INFO, "[Items/%08" PRIX32 "] Player %hu picked up %08" PRIX32,
l->lobby_id, cmd->client_id.load(), cmd->item_id.load());
effective_c->game_data.player()->print_inventory(stderr);
}
forward_subcommand(l, c, command, flag, data);
}
@@ -466,6 +480,10 @@ static void process_subcommand_pick_up_item_request(shared_ptr<ServerState>,
return;
}
if (!(l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
throw logic_error("item tracking not enabled in BB game");
}
c->game_data.player()->add_item(l->remove_item(cmd->item_id));
log(INFO, "[Items/%08" PRIX32 "/BB] Player %hhu picked up %08" PRIX32,
@@ -482,7 +500,7 @@ static void process_subcommand_pick_up_item_request(shared_ptr<ServerState>,
static void process_subcommand_equip_unequip_item(shared_ptr<ServerState>,
shared_ptr<Lobby> l, shared_ptr<Client> c, uint8_t command, uint8_t flag,
const string& data) {
// We don't track equip state on non-BB versions
// TODO: We should track equip state on non-BB versions
if (l->version == GameVersion::BB) {
const auto* cmd = check_size_sc<G_ItemSubcommand>(data);
@@ -490,6 +508,10 @@ static void process_subcommand_equip_unequip_item(shared_ptr<ServerState>,
return;
}
if (!(l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
throw logic_error("item tracking not enabled in BB game");
}
size_t index = c->game_data.player()->inventory.find_item(cmd->item_id);
if (cmd->command == 0x25) {
c->game_data.player()->inventory.items[index].game_flags |= 0x00000008; // equip
@@ -511,12 +533,14 @@ static void process_subcommand_use_item(shared_ptr<ServerState>,
return;
}
size_t index = c->game_data.player()->inventory.find_item(cmd->item_id);
player_use_item(c, index);
if (l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED) {
size_t index = c->game_data.player()->inventory.find_item(cmd->item_id);
player_use_item(c, index);
log(INFO, "[Items/%08" PRIX32 "] Player used item %hhu:%08" PRIX32,
l->lobby_id, cmd->client_id, cmd->item_id.load());
c->game_data.player()->print_inventory(stderr);
log(INFO, "[Items/%08" PRIX32 "] Player used item %hhu:%08" PRIX32,
l->lobby_id, cmd->client_id, cmd->item_id.load());
c->game_data.player()->print_inventory(stderr);
}
forward_subcommand(l, c, command, flag, data);
}
@@ -572,6 +596,10 @@ static void process_subcommand_bank_action_bb(shared_ptr<ServerState>,
return;
}
if (!(l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
throw logic_error("item tracking not enabled in BB game");
}
if (cmd->action == 0) { // deposit
if (cmd->item_id == 0xFFFFFFFF) { // meseta
if (cmd->meseta_amount > c->game_data.player()->disp.meseta) {
@@ -615,6 +643,10 @@ static void process_subcommand_sort_inventory_bb(shared_ptr<ServerState>,
if (l->version == GameVersion::BB) {
const auto* cmd = check_size_sc<G_SortInventory_6xC4>(data);
if (!(l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
throw logic_error("item tracking not enabled in BB game");
}
PlayerInventory sorted;
for (size_t x = 0; x < 30; x++) {
@@ -647,6 +679,10 @@ static void process_subcommand_enemy_drop_item_request(shared_ptr<ServerState> s
return;
}
if (!(l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
throw logic_error("item tracking not enabled in BB game");
}
PlayerInventoryItem item;
// TODO: Deduplicate this code with the box drop item request handler
@@ -701,6 +737,10 @@ static void process_subcommand_box_drop_item_request(shared_ptr<ServerState> s,
return;
}
if (!(l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
throw logic_error("item tracking not enabled in BB game");
}
PlayerInventoryItem item;
bool is_rare = false;
@@ -891,11 +931,13 @@ static void process_subcommand_destroy_inventory_item(shared_ptr<ServerState>,
if (cmd->client_id != c->lobby_client_id) {
return;
}
c->game_data.player()->remove_item(cmd->item_id, cmd->amount);
log(INFO, "[Items/%08" PRIX32 "] Inventory item %hhu:%08" PRIX32 " destroyed (%" PRIX32 " of them)",
l->lobby_id, cmd->client_id, cmd->item_id.load(), cmd->amount.load());
c->game_data.player()->print_inventory(stderr);
forward_subcommand(l, c, command, flag, data);
if (l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED) {
c->game_data.player()->remove_item(cmd->item_id, cmd->amount);
log(INFO, "[Items/%08" PRIX32 "] Inventory item %hhu:%08" PRIX32 " destroyed (%" PRIX32 " of them)",
l->lobby_id, cmd->client_id, cmd->item_id.load(), cmd->amount.load());
c->game_data.player()->print_inventory(stderr);
forward_subcommand(l, c, command, flag, data);
}
}
static void process_subcommand_destroy_ground_item(shared_ptr<ServerState>,
@@ -905,10 +947,12 @@ static void process_subcommand_destroy_ground_item(shared_ptr<ServerState>,
if (!l->is_game()) {
return;
}
l->remove_item(cmd->item_id);
log(INFO, "[Items/%08" PRIX32 "] Ground item %08" PRIX32 " destroyed (%" PRIX32 " of them)",
l->lobby_id, cmd->item_id.load(), cmd->amount.load());
forward_subcommand(l, c, command, flag, data);
if (l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED) {
l->remove_item(cmd->item_id);
log(INFO, "[Items/%08" PRIX32 "] Ground item %08" PRIX32 " destroyed (%" PRIX32 " of them)",
l->lobby_id, cmd->item_id.load(), cmd->amount.load());
forward_subcommand(l, c, command, flag, data);
}
}
static void process_subcommand_identify_item_bb(shared_ptr<ServerState>,
@@ -920,6 +964,10 @@ static void process_subcommand_identify_item_bb(shared_ptr<ServerState>,
return;
}
if (!(l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
throw logic_error("item tracking not enabled in BB game");
}
size_t x = c->game_data.player()->inventory.find_item(cmd->item_id);
if (c->game_data.player()->inventory.items[x].data.data1[0] != 0) {
return; // only weapons can be identified
@@ -956,6 +1004,9 @@ static void process_subcommand_identify_item_bb(shared_ptr<ServerState>,
// if (cmd->client_id != c->lobby_client_id) {
// return;
// }
// if (!(l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED)) {
// throw logic_error("item tracking not enabled in BB game");
// }
//
// size_t x = c->game_data.player()->inventory.find_item(cmd->item_id);
// c->game_data.player()->inventory.items[x] = c->game_data.player()->identify_result;
+1
View File
@@ -18,6 +18,7 @@ ServerState::ServerState()
: dns_server_port(0),
ip_stack_debug(false),
allow_unregistered_users(false),
item_tracking_enabled(true),
run_shell_behavior(RunShellBehavior::DEFAULT), next_lobby_id(1),
pre_lobby_event(0),
ep3_menu_song(-1) {
+1
View File
@@ -46,6 +46,7 @@ struct ServerState {
std::vector<std::string> ip_stack_addresses;
bool ip_stack_debug;
bool allow_unregistered_users;
bool item_tracking_enabled;
RunShellBehavior run_shell_behavior;
std::vector<std::shared_ptr<const PSOBBEncryption::KeyFile>> bb_private_keys;
std::shared_ptr<const FunctionCodeIndex> function_code_index;
+2
View File
@@ -1468,6 +1468,8 @@ string name_for_item(const ItemData& item, bool include_color_codes) {
// For weapons, specials appear before the weapon name
if ((item.data1[0] == 0x00) && (item.data1[4] != 0x00)) {
// 0x80 is the unidentified flag, but we always return the identified name
// of the item here, so we ignore it
bool is_present = item.data1[4] & 0x40;
uint8_t special_id = item.data1[4] & 0x3F;
if (is_present) {
+8
View File
@@ -128,6 +128,14 @@
// BB users.
"WelcomeMessage": "",
// By default, the server keeps track of items in all games, even for versions
// other than Blue Burst. This enables use of the $what command, as well as
// protection against item duplication cheats (the cheater is disconnected
// instead of the other players). If item tracking causes any issues, it can
// be turned off here. This option has no effect on Blue Burst games - item
// tracking is always enabled for them.
"EnableItemTracking": true,
// Item drop rates for non-rare items in BB games. For each type (boxes or
// enemies), all the categories must add up to a number less than 0x100000000.
// Each number is a probability (out of 0x100000000) that the given item type