From 5515c841a13ff1c1b3a7510d6a9cac643f266811 Mon Sep 17 00:00:00 2001 From: Quentin Date: Fri, 13 Oct 2023 00:11:37 +0200 Subject: [PATCH] feat(lua): Allow lua scripts to flag modders with a custom reason if needed. (#2248) --- docs/lua/doc_gen.py | 134 +++++++++++++++--- docs/lua/infraction.md | 23 +++ docs/lua/tables/network.md | 21 ++- src/core/data/infractions.hpp | 26 +--- src/lua/bindings/network.cpp | 66 +++++++-- .../player_database/persistent_player.cpp | 63 ++++++++ .../player_database/persistent_player.hpp | 18 +-- src/util/session.hpp | 14 +- src/views/network/view_player_database.cpp | 2 +- src/views/players/view_players.cpp | 2 +- 10 files changed, 301 insertions(+), 68 deletions(-) create mode 100644 docs/lua/infraction.md create mode 100644 src/services/player_database/persistent_player.cpp diff --git a/docs/lua/doc_gen.py b/docs/lua/doc_gen.py index 1c163065..c2639c78 100644 --- a/docs/lua/doc_gen.py +++ b/docs/lua/doc_gen.py @@ -18,6 +18,7 @@ class DocKind(Enum): Constructor = "constructor" Function = "function" Tabs = "tabs" + Infraction = "infraction" class Table: @@ -324,7 +325,10 @@ def parse_lua_api_doc(folder_path): .lower() ) - if doc_kind is not DocKind.Tabs: + if ( + doc_kind is not DocKind.Tabs + and doc_kind is not DocKind.Infraction + ): continue if doc_kind is not None and "//" in line: @@ -367,7 +371,10 @@ def parse_lua_api_doc(folder_path): line, line_lower, ) - case DocKind.Tabs: parse_tabs_doc(file) + case DocKind.Tabs: + parse_tabs_doc(file) + case DocKind.Infraction: + parse_infraction_doc(file) case _: # print("unsupported doc kind: " + str(doc_kind)) pass @@ -386,6 +393,7 @@ def parse_table_doc(cur_table, line, line_lower): return cur_table + def parse_class_doc(cur_class, line, line_lower): if is_lua_doc_comment_startswith(line_lower, "name"): class_name = line.split(lua_api_comment_separator, 1)[1].strip() @@ -402,28 +410,43 @@ def parse_class_doc(cur_class, line, line_lower): def parse_function_doc(cur_function, cur_table, cur_class, line, line_lower): - if is_lua_doc_comment_startswith(line_lower, "table") and lua_api_comment_separator in line_lower: + if ( + is_lua_doc_comment_startswith(line_lower, "table") + and lua_api_comment_separator in line_lower + ): table_name = line.split(lua_api_comment_separator, 1)[1].strip() cur_table = make_table(table_name) cur_function = Function("Didnt get name yet", cur_table, [], None, "", "") cur_table.functions.append(cur_function) - elif is_lua_doc_comment_startswith(line_lower, "class") and lua_api_comment_separator in line_lower: + elif ( + is_lua_doc_comment_startswith(line_lower, "class") + and lua_api_comment_separator in line_lower + ): class_name = line.split(lua_api_comment_separator, 1)[1].strip() cur_class = make_class(class_name) cur_function = Function("Didnt get name yet", cur_class, [], None, "", "") cur_class.functions.append(cur_function) - elif is_lua_doc_comment_startswith(line_lower, "name") and lua_api_comment_separator in line_lower: + elif ( + is_lua_doc_comment_startswith(line_lower, "name") + and lua_api_comment_separator in line_lower + ): function_name = line.split(lua_api_comment_separator, 1)[1].strip() cur_function.name = function_name if function_name not in functions: functions[function_name] = cur_function - elif is_lua_doc_comment_startswith(line_lower, "param") and lua_api_comment_separator in line_lower: + elif ( + is_lua_doc_comment_startswith(line_lower, "param") + and lua_api_comment_separator in line_lower + ): parameter = make_parameter_from_doc_line(line) cur_function.parameters.append(parameter) - elif is_lua_doc_comment_startswith(line_lower, "return") and lua_api_comment_separator in line_lower: + elif ( + is_lua_doc_comment_startswith(line_lower, "return") + and lua_api_comment_separator in line_lower + ): return_info = line.split(lua_api_comment_separator, 2) try: cur_function.return_type = return_info[1].strip() @@ -439,19 +462,28 @@ def parse_function_doc(cur_function, cur_table, cur_class, line, line_lower): def parse_field_doc(cur_field, cur_table, cur_class, line, line_lower): - if is_lua_doc_comment_startswith(line_lower, "table") and lua_api_comment_separator in line_lower: + if ( + is_lua_doc_comment_startswith(line_lower, "table") + and lua_api_comment_separator in line_lower + ): table_name = line.split(lua_api_comment_separator, 1)[1].strip() cur_table = make_table(table_name) cur_field = Field("Didnt get name yet", "", "") cur_table.fields.append(cur_field) - elif is_lua_doc_comment_startswith(line_lower, "class") and lua_api_comment_separator in line_lower: + elif ( + is_lua_doc_comment_startswith(line_lower, "class") + and lua_api_comment_separator in line_lower + ): class_name = line.split(lua_api_comment_separator, 1)[1].strip() cur_class = make_class(class_name) cur_field = Field("Didnt get name yet", "", "") cur_class.fields.append(cur_field) - elif is_lua_doc_comment_startswith(line_lower, "field") and lua_api_comment_separator in line_lower: + elif ( + is_lua_doc_comment_startswith(line_lower, "field") + and lua_api_comment_separator in line_lower + ): field_info = line.split(lua_api_comment_separator, 2) cur_field.name = field_info[1].strip() cur_field.type_ = field_info[2].strip() @@ -467,13 +499,19 @@ def parse_field_doc(cur_field, cur_table, cur_class, line, line_lower): def parse_constructor_doc(cur_constructor, cur_class, line, line_lower): - if is_lua_doc_comment_startswith(line_lower, "class") and lua_api_comment_separator in line_lower: + if ( + is_lua_doc_comment_startswith(line_lower, "class") + and lua_api_comment_separator in line_lower + ): class_name = line.split(lua_api_comment_separator, 1)[1].strip() cur_class = make_class(class_name) cur_constructor = Constructor(cur_class, [], "") cur_class.constructors.append(cur_constructor) - elif is_lua_doc_comment_startswith(line_lower, "param") and lua_api_comment_separator in line_lower: + elif ( + is_lua_doc_comment_startswith(line_lower, "param") + and lua_api_comment_separator in line_lower + ): parameter = make_parameter_from_doc_line(line) cur_constructor.parameters.append(parameter) else: @@ -485,6 +523,8 @@ def parse_constructor_doc(cur_constructor, cur_class, line, line_lower): tabs_enum = [] + + def parse_tabs_doc(file): start_parsing = False for line in file: @@ -503,7 +543,29 @@ def parse_tabs_doc(file): continue else: tabs_enum.append(line.replace(",", "").strip()) - + + +infraction_enum = [] + + +def parse_infraction_doc(file): + start_parsing = False + for line in file: + if "enum class" in line.lower(): + start_parsing = True + continue + + if start_parsing: + if "};" in line.lower(): + return + if "{" == line.lower().strip(): + continue + if "//" in line.lower(): + continue + if "" == line.lower().strip(): + continue + else: + infraction_enum.append(line.replace(",", "").strip()) def make_parameter_from_doc_line(line): @@ -519,13 +581,15 @@ def make_parameter_from_doc_line(line): return Parameter(param_name, param_type, param_desc) + def sanitize_description(line): - if line.startswith("// ") and line[3] != ' ': + if line.startswith("// ") and line[3] != " ": line = line[3:] if line.startswith("//"): line = line[2:] return line.rstrip() + def is_lua_doc_comment_startswith(line_lower, starts_with_text): return line_lower.replace("//", "").strip().startswith(starts_with_text) @@ -550,7 +614,8 @@ if os.path.exists(tabs_file_name): os.remove(tabs_file_name) f = open(tabs_file_name, "a") -f.write("""# Tabs +f.write( + """# Tabs All the tabs from the menu are listed below, used as parameter for adding gui elements to them. @@ -565,16 +630,42 @@ end) For a complete list of available gui functions, please refer to the tab class documentation and the gui table documentation. -""") +""" +) f.write(f"## Tab Count: {len(tabs_enum)}\n\n") # Minus the first, because it's the `NONE` tab, minus the last one because it's for runtime defined tabs. -for i in range(1, len(tabs_enum) - 1 ): +for i in range(1, len(tabs_enum) - 1): f.write("### `GUI_TAB_" + tabs_enum[i] + "`\n") f.close() +infraction_file_name = f"../lua/infraction.md" +if os.path.exists(infraction_file_name): + os.remove(infraction_file_name) +f = open(infraction_file_name, "a") + +f.write( + """# Infraction + +All the infraction from the menu are listed below, used as parameter for adding an infraction to a given player, for flagging them as modder. + +**Example Usage:** +```lua +network.flag_player_as_modder(player_index, infraction.CUSTOM_REASON, "My custom reason on why the player is flagged as a modder") +``` + +""" +) + +f.write(f"## Infraction Count: {len(infraction_enum)}\n\n") + +for i in range(0, len(infraction_enum)): + f.write("### `" + infraction_enum[i] + "`\n") + +f.close() + try: os.makedirs("./classes/") except: @@ -589,13 +680,13 @@ for class_name, class_ in classes.items(): f.close() - commands_file_name = f"./commands.md" if os.path.exists(commands_file_name): os.remove(commands_file_name) f = open(commands_file_name, "a") -f.write("""# Commands +f.write( + """# Commands All the current commands from the menu are listed below. @@ -608,7 +699,8 @@ command.call_player(somePlayerIndex, "spawn", {joaat("adder")}) For a complete list of available command functions, please refer to the command table documentation. -""") +""" +) commands = [] @@ -629,4 +721,4 @@ for cmd in commands: f.write(f"Arg Count: {arg_count}\n") f.write("\n") -f.close() \ No newline at end of file +f.close() diff --git a/docs/lua/infraction.md b/docs/lua/infraction.md new file mode 100644 index 00000000..597a3db5 --- /dev/null +++ b/docs/lua/infraction.md @@ -0,0 +1,23 @@ +# Infraction + +All the infraction from the menu are listed below, used as parameter for adding an infraction to a given player, for flagging them as modder. + +**Example Usage:** +```lua +network.flag_player_as_modder(player_index, infraction.CUSTOM_REASON, "My custom reason on why the player is flagged as a modder") +``` + +## Infraction Count: 12 + +### `TRIGGERED_ANTICHEAT` +### `TRIED_CRASH_PLAYER` +### `TRIED_KICK_PLAYER` +### `ATTACKING_WITH_GODMODE` +### `ATTACKING_WITH_INVISIBILITY` +### `ATTACKING_WHEN_HIDDEN_FROM_PLAYER_LIST` +### `SPOOFED_DATA` +### `SPOOFED_HOST_TOKEN` +### `INVALID_PLAYER_MODEL` +### `SUPER_JUMP` +### `UNDEAD_OTR` +### `CUSTOM_REASON` diff --git a/docs/lua/tables/network.md b/docs/lua/tables/network.md index 49f69065..d9e5ad96 100644 --- a/docs/lua/tables/network.md +++ b/docs/lua/tables/network.md @@ -2,7 +2,7 @@ Table containing helper functions for network related features. -## Functions (10) +## Functions (11) ### `trigger_script_event(bitset, _args)` @@ -79,16 +79,18 @@ integer = network.get_selected_player() integer = network.get_selected_database_player_rockstar_id() ``` -### `flag_player_as_modder(player_idx)` +### `flag_player_as_modder(player_idx, reason, custom_reason)` Flags the given player as a modder in our local database. - **Parameters:** - `player_idx` (integer): Index of the player. + - `reason` (Infraction): Reason why the player is flagged as a modder, if the infraction is CUSTOM_REASON, then the custom_reason string is added in the local database. For a full list of the possible infraction reasons to use, please check the infraction page. + - `custom_reason` (string): Optional, required only when the infraction is CUSTOM_REASON. The custom reason why the player is flagged as a modder. **Example Usage:** ```lua -network.flag_player_as_modder(player_idx) +network.flag_player_as_modder(player_idx, reason, custom_reason) ``` ### `is_player_flagged_as_modder(player_idx)` @@ -104,6 +106,19 @@ network.flag_player_as_modder(player_idx) boolean = network.is_player_flagged_as_modder(player_idx) ``` +### `get_flagged_modder_reason(player_idx)` + +- **Parameters:** + - `player_idx` (integer): Index of the player. + +- **Returns:** + - `string`: Returns a string which contains the reason(s) why the player is flagged as a modder. + +**Example Usage:** +```lua +string = network.get_flagged_modder_reason(player_idx) +``` + ### `force_script_host(script_name)` Try to force ourself to be host for the given GTA Script. diff --git a/src/core/data/infractions.hpp b/src/core/data/infractions.hpp index 238d81bd..f46d46ed 100644 --- a/src/core/data/infractions.hpp +++ b/src/core/data/infractions.hpp @@ -1,11 +1,12 @@ #pragma once -#include "gta/joaat.hpp" namespace big { - // Add new values to the bottom + // Lua API: Infraction enum class Infraction { + // Add new values to the bottom (for serialization) + DESYNC_PROTECTION, // do not use BREAKUP_KICK_DETECTED, // do not use LOST_CONNECTION_KICK_DETECTED, // do not use @@ -22,24 +23,7 @@ namespace big INVALID_PLAYER_MODEL, SUPER_JUMP, UNDEAD_OTR, - }; - - inline std::unordered_map infraction_desc = { - {Infraction::DESYNC_PROTECTION, "Used desync protections"}, - {Infraction::BREAKUP_KICK_DETECTED, "Kicked someone using breakup kick"}, - {Infraction::LOST_CONNECTION_KICK_DETECTED, "Tried to kick someone using lost connection kick"}, - {Infraction::SPOOFED_ROCKSTAR_ID, "Had spoofed RID"}, - {Infraction::TRIGGERED_ANTICHEAT, "Triggered Rockstar's anticheat"}, - {Infraction::TRIED_CRASH_PLAYER, "Tried to crash you"}, - {Infraction::TRIED_KICK_PLAYER, "Tried to kick you"}, - {Infraction::BLAME_EXPLOSION_DETECTED, "Tried to blame someone for their explosion"}, - {Infraction::ATTACKING_WITH_GODMODE, "Attacked someone while using godmode"}, - {Infraction::ATTACKING_WITH_INVISIBILITY, "Attacked someone while being invisible"}, - {Infraction::ATTACKING_WHEN_HIDDEN_FROM_PLAYER_LIST, "Attacked someone while being hidden from the player list"}, - {Infraction::SPOOFED_DATA, "Had spoofed data"}, - {Infraction::SPOOFED_HOST_TOKEN, "Had spoofed their host token"}, - {Infraction::INVALID_PLAYER_MODEL, "Had used an invalid player model"}, - {Infraction::SUPER_JUMP, "Had used super jump"}, - {Infraction::UNDEAD_OTR, "Had used undead OTR"}, + // So that lua scripts can add a custom runtime reason. + CUSTOM_REASON, }; } \ No newline at end of file diff --git a/src/lua/bindings/network.cpp b/src/lua/bindings/network.cpp index d3d3c5cc..4eeeb3ed 100644 --- a/src/lua/bindings/network.cpp +++ b/src/lua/bindings/network.cpp @@ -6,6 +6,7 @@ #include "services/player_database/player_database_service.hpp" #include "util/notify.hpp" #include "util/scripts.hpp" +#include "util/session.hpp" #include "util/system.hpp" #include "util/teleport.hpp" @@ -100,19 +101,26 @@ namespace lua::network return -1; } + static void flag_player_as_modder(int player_idx, big::Infraction reason) + { + if (auto player = big::g_player_service->get_by_id(player_idx)) + { + big::session::add_infraction(player, reason); + } + } + // Lua API: Function // Table: network // Name: flag_player_as_modder // Param: player_idx: integer: Index of the player. + // Param: reason: Infraction: Reason why the player is flagged as a modder, if the infraction is CUSTOM_REASON, then the custom_reason string is added in the local database. For a full list of the possible infraction reasons to use, please check the infraction page. + // Param: custom_reason: string: Optional, required only when the infraction is CUSTOM_REASON. The custom reason why the player is flagged as a modder. // Flags the given player as a modder in our local database. - static void flag_player_as_modder(int player_idx) + static void flag_player_as_modder_custom_reason(int player_idx, big::Infraction reason, const std::string& custom_reason) { if (auto player = big::g_player_service->get_by_id(player_idx)) { - auto pers = big::g_player_database_service->get_or_create_player(player); - pers->is_modder = true; - big::g_player_database_service->save(); - player->is_modder = true; + big::session::add_infraction(player, reason, custom_reason); } } @@ -129,6 +137,21 @@ namespace lua::network return false; } + // Lua API: Function + // Table: network + // Name: get_flagged_modder_reason + // Param: player_idx: integer: Index of the player. + // Returns: string: Returns a string which contains the reason(s) why the player is flagged as a modder. + static std::string get_flagged_modder_reason(int player_idx) + { + if (auto player = big::g_player_service->get_by_id(player_idx)) + { + return big::g_player_database_service->get_or_create_player(player)->get_all_infraction_descriptions(); + } + + return ""; + } + // Lua API: Function // Table: network // Name: force_script_host @@ -158,16 +181,39 @@ namespace lua::network void bind(sol::state& state) { - auto ns = state["network"].get_or_create(); + state.new_enum("infraction", + { + {"ATTACKING_WHEN_HIDDEN_FROM_PLAYER_LIST", big::Infraction::ATTACKING_WHEN_HIDDEN_FROM_PLAYER_LIST}, + {"ATTACKING_WITH_GODMODE", big::Infraction::ATTACKING_WITH_GODMODE}, + {"ATTACKING_WITH_INVISIBILITY", big::Infraction::ATTACKING_WITH_INVISIBILITY}, + {"BLAME_EXPLOSION_DETECTED", big::Infraction::BLAME_EXPLOSION_DETECTED}, + {"BREAKUP_KICK_DETECTED", big::Infraction::BREAKUP_KICK_DETECTED}, + {"CUSTOM_REASON", big::Infraction::CUSTOM_REASON}, + {"DESYNC_PROTECTION", big::Infraction::DESYNC_PROTECTION}, + {"INVALID_PLAYER_MODEL", big::Infraction::INVALID_PLAYER_MODEL}, + {"LOST_CONNECTION_KICK_DETECTED", big::Infraction::LOST_CONNECTION_KICK_DETECTED}, + {"SPOOFED_DATA", big::Infraction::SPOOFED_DATA}, + {"SPOOFED_HOST_TOKEN", big::Infraction::SPOOFED_HOST_TOKEN}, + {"SPOOFED_ROCKSTAR_ID", big::Infraction::SPOOFED_ROCKSTAR_ID}, + {"SUPER_JUMP", big::Infraction::SUPER_JUMP}, + {"TRIED_CRASH_PLAYER", big::Infraction::TRIED_CRASH_PLAYER}, + {"TRIED_KICK_PLAYER", big::Infraction::TRIED_KICK_PLAYER}, + {"TRIGGERED_ANTICHEAT", big::Infraction::TRIGGERED_ANTICHEAT}, + {"UNDEAD_OTR", big::Infraction::UNDEAD_OTR}, + }); + + auto ns = state["network"].get_or_create(); + ns["trigger_script_event"] = trigger_script_event; ns["give_pickup_rewards"] = give_pickup_rewards; ns["set_player_coords"] = set_player_coords; ns["set_all_player_coords"] = set_all_player_coords; ns["get_selected_player"] = get_selected_player; ns["get_selected_database_player_rockstar_id"] = get_selected_database_player_rockstar_id; - ns["flag_player_as_modder"] = flag_player_as_modder; - ns["is_player_flagged_as_modder"] = is_player_flagged_as_modder; - ns["force_script_host"] = force_script_host; - ns["send_chat_message"] = send_chat_message; + ns["flag_player_as_modder"] = sol::overload(flag_player_as_modder, flag_player_as_modder_custom_reason); + ns["is_player_flagged_as_modder"] = is_player_flagged_as_modder; + ns["get_flagged_modder_reason"] = get_flagged_modder_reason; + ns["force_script_host"] = force_script_host; + ns["send_chat_message"] = send_chat_message; } } \ No newline at end of file diff --git a/src/services/player_database/persistent_player.cpp b/src/services/player_database/persistent_player.cpp new file mode 100644 index 00000000..377644d4 --- /dev/null +++ b/src/services/player_database/persistent_player.cpp @@ -0,0 +1,63 @@ +#pragma once +#include "persistent_player.hpp" + +#include "core/data/infractions.hpp" + +namespace big +{ + static std::unordered_map infraction_desc = { + {Infraction::DESYNC_PROTECTION, "Used desync protections"}, + {Infraction::BREAKUP_KICK_DETECTED, "Kicked someone using breakup kick"}, + {Infraction::LOST_CONNECTION_KICK_DETECTED, "Tried to kick someone using lost connection kick"}, + {Infraction::SPOOFED_ROCKSTAR_ID, "Had spoofed RID"}, + {Infraction::TRIGGERED_ANTICHEAT, "Triggered Rockstar's anticheat"}, + {Infraction::TRIED_CRASH_PLAYER, "Tried to crash you"}, + {Infraction::TRIED_KICK_PLAYER, "Tried to kick you"}, + {Infraction::BLAME_EXPLOSION_DETECTED, "Tried to blame someone for their explosion"}, + {Infraction::ATTACKING_WITH_GODMODE, "Attacked someone while using godmode"}, + {Infraction::ATTACKING_WITH_INVISIBILITY, "Attacked someone while being invisible"}, + {Infraction::ATTACKING_WHEN_HIDDEN_FROM_PLAYER_LIST, "Attacked someone while being hidden from the player list"}, + {Infraction::SPOOFED_DATA, "Had spoofed data"}, + {Infraction::SPOOFED_HOST_TOKEN, "Had spoofed their host token"}, + {Infraction::INVALID_PLAYER_MODEL, "Had used an invalid player model"}, + {Infraction::SUPER_JUMP, "Had used super jump"}, + {Infraction::UNDEAD_OTR, "Had used undead OTR"}, + }; + + const char* persistent_player::get_infraction_description(int infraction) + { + if (static_cast(infraction) == Infraction::CUSTOM_REASON) + { + return custom_infraction_reason.c_str(); + } + + return infraction_desc[static_cast(infraction)]; + } + + std::string persistent_player::get_all_infraction_descriptions() + { + if (!infractions.size()) + { + return ""; + } + + constexpr auto separator = ", "; + constexpr size_t separator_length = (std::string(separator)).size(); + + std::string s; + + for (const auto infr : infractions) + { + s += get_infraction_description(infr); + s += separator; + } + + // Remove last useless separator + for (size_t i = 0; i < separator_length; i++) + { + s.pop_back(); + } + + return s; + } +} diff --git a/src/services/player_database/persistent_player.hpp b/src/services/player_database/persistent_player.hpp index 472df783..853d0e02 100644 --- a/src/services/player_database/persistent_player.hpp +++ b/src/services/player_database/persistent_player.hpp @@ -1,5 +1,4 @@ #pragma once -#include "core/data/infractions.hpp" #include "json_util.hpp" #include @@ -43,12 +42,13 @@ namespace big struct persistent_player { std::string name; - uint64_t rockstar_id = 0; - bool block_join = false; - int block_join_reason = 1; - bool is_modder = false; - bool notify_online = false; + uint64_t rockstar_id = 0; + bool block_join = false; + int block_join_reason = 1; + bool is_modder = false; + bool notify_online = false; std::unordered_set infractions; + std::string custom_infraction_reason = ""; std::string notes = ""; std::optional command_access_level = std::nullopt; bool join_redirect = false; @@ -66,7 +66,9 @@ namespace big std::string game_mode_id = ""; rage::rlSessionInfo redirect_info{}; - NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(persistent_player, name, rockstar_id, block_join, block_join_reason, is_modder, notify_online, infractions, notes, command_access_level, join_redirect, join_redirect_preference) - }; + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(persistent_player, name, rockstar_id, block_join, block_join_reason, is_modder, notify_online, infractions, custom_infraction_reason, notes, command_access_level, join_redirect, join_redirect_preference) + const char* get_infraction_description(int infraction); + std::string get_all_infraction_descriptions(); + }; }; diff --git a/src/util/session.hpp b/src/util/session.hpp index 06bf4686..53f8718f 100644 --- a/src/util/session.hpp +++ b/src/util/session.hpp @@ -1,4 +1,5 @@ #pragma once +#include "core/data/infractions.hpp" #include "core/data/session_types.hpp" #include "fiber_pool.hpp" #include "gta/joaat.hpp" @@ -48,7 +49,7 @@ namespace big::session else { *scr_globals::session.at(2).as() = 0; - *scr_globals::session2.as() = (int)session; + *scr_globals::session2.as() = (int)session; } *scr_globals::session.as() = 1; @@ -63,7 +64,7 @@ namespace big::session } scr_functions::reset_session_data({true, true}); - *scr_globals::session3.as() = 0; + *scr_globals::session3.as() = 0; *scr_globals::session4.as() = 1; *scr_globals::session5.as() = 32; @@ -158,7 +159,7 @@ namespace big::session }); } - inline void add_infraction(player_ptr player, Infraction infraction) + inline void add_infraction(player_ptr player, Infraction infraction, const std::string& custom_reason = "") { if (g.debug.fuzzer.enabled) return; @@ -168,8 +169,15 @@ namespace big::session { plyr->is_modder = true; player->is_modder = true; + plyr->infractions.insert((int)infraction); + if (infraction == Infraction::CUSTOM_REASON) + { + plyr->custom_infraction_reason += plyr->custom_infraction_reason.size() ? (std::string(", ") + custom_reason) : custom_reason; + } + g_player_database_service->save(); + g.reactions.modder_detection.process(player); } } diff --git a/src/views/network/view_player_database.cpp b/src/views/network/view_player_database.cpp index 6e732b83..ad7ecfc7 100644 --- a/src/views/network/view_player_database.cpp +++ b/src/views/network/view_player_database.cpp @@ -182,7 +182,7 @@ namespace big for (auto& infraction : current_player->infractions) { - ImGui::BulletText(infraction_desc[(Infraction)infraction]); + ImGui::BulletText(current_player->get_infraction_description(infraction)); } } diff --git a/src/views/players/view_players.cpp b/src/views/players/view_players.cpp index 92ed74b9..8de77fc1 100644 --- a/src/views/players/view_players.cpp +++ b/src/views/players/view_players.cpp @@ -71,7 +71,7 @@ namespace big { ImGui::BeginTooltip(); for (auto infraction : sorted_player->infractions) - ImGui::BulletText(infraction_desc[(Infraction)infraction]); + ImGui::BulletText(sorted_player->get_infraction_description(infraction)); ImGui::EndTooltip(); } }