From 11ee2f6e82760d0c1ab64bb511df9b35b92420e0 Mon Sep 17 00:00:00 2001 From: EmeraldLockdown <86802223+EmeraldLoc@users.noreply.github.com> Date: Fri, 6 Mar 2026 23:27:10 -0600 Subject: [PATCH] Begin work on a moderation rework - Adds a new ui for moderation - Redoes the entire backend system What still needs to be done: - Polish - Languages - Need to redo some of the code related to ui to make it cleaner and more concise - other stuff probably --- lang/English.ini | 5 ++++ src/pc/chat_commands.c | 17 ++++++++------ src/pc/djui/djui_base.c | 10 ++++---- src/pc/djui/djui_base.h | 2 ++ src/pc/djui/djui_panel_confirm.c | 2 +- src/pc/djui/djui_panel_host.c | 2 ++ src/pc/djui/djui_panel_pause.c | 5 ++++ src/pc/lua/utils/smlua_misc_utils.h | 3 +-- src/pc/network/packets/packet.c | 5 ++-- src/pc/network/packets/packet.h | 7 +++++- src/pc/network/packets/packet_command_mod.c | 23 ++++++++++++------- src/pc/network/packets/packet_join.c | 11 ++++++--- src/pc/network/packets/packet_kick.c | 8 +++++-- .../network/packets/packet_network_players.c | 7 +++--- src/pc/network/packets/packet_player.c | 2 +- src/pc/pc_main.c | 2 ++ 16 files changed, 77 insertions(+), 34 deletions(-) diff --git a/lang/English.ini b/lang/English.ini index 14ec1d462..60553fc5d 100644 --- a/lang/English.ini +++ b/lang/English.ini @@ -58,6 +58,7 @@ MOD_DESC = "/moderator [NAME|ID] - Make this player able to use commands like /k NAMETAGS_DESC = "/nametags [show-tag|show-health] - Change whether or not you see your own nametag and whether or not you see health" UNRECOGNIZED = "Unrecognized chat command." MOD_GRANTED = "\\#fff982\\You are now a Moderator." +MOD_REVOKED = "\\#FE7F7F\\You are no longer a Moderator." [MENU] BACK = "Back" @@ -338,6 +339,9 @@ CONSOLE = "CONSOLE" [MODLIST] MODS = "MODS" +[MODERATOR_MENU] +MODERATOR_MENU_TITLE = "MODERATOR MENU" + [OPTIONS] OPTIONS = "OPTIONS" PLAYER = "Player" @@ -359,6 +363,7 @@ DYNOS_PACKS = "DynOS Packs" OPTIONS = "Options" CHEATS = "Cheats" SERVER_SETTINGS = "Server Settings" +MODERATOR_MENU = "Moderator Menu" RESUME = "Resume" STOP_HOSTING = "Stop Hosting" DISCONNECT = "Disconnect" diff --git a/src/pc/chat_commands.c b/src/pc/chat_commands.c index adb2bec1e..099061cd2 100644 --- a/src/pc/chat_commands.c +++ b/src/pc/chat_commands.c @@ -4,8 +4,7 @@ #include "pc/djui/djui_language.h" #include "pc/djui/djui_chat_message.h" #include "chat_commands.h" -#include "pc/network/ban_list.h" -#include "pc/network/moderator_list.h" +#include "pc/network/moderation.h" #include "pc/debuglog.h" #include "pc/lua/utils/smlua_level_utils.h" #include "pc/mods/mods_utils.h" @@ -75,7 +74,9 @@ bool exec_chat_command(char* command) { chat_construct_player_message(np, DLANG(CHAT, BANNING)); if (gNetworkType == NT_SERVER) { network_send_kick(np->localIndex, EKT_BANNED); - ban_list_add(gNetworkSystem->get_id_str(np->localIndex), false); + + // TODO: Moderation: Allow you to insert a reason + moderation_list_add(MODERATION_LIST_TYPE_BAN, np->localIndex, "", false); network_player_disconnected(np->localIndex); } else { network_send_chat_command(np->globalIndex, CCC_BAN); @@ -86,7 +87,8 @@ bool exec_chat_command(char* command) { if (gNetworkType == NT_SERVER && ccc == CCC_PERMBAN) { chat_construct_player_message(np, DLANG(CHAT, PERM_BANNING)); network_send_kick(np->localIndex, EKT_BANNED); - ban_list_add(gNetworkSystem->get_id_str(np->localIndex), true); + // TODO: Moderation: Allow you to insert a reason + moderation_list_add(MODERATION_LIST_TYPE_BAN, np->localIndex, "", true); network_player_disconnected(np->localIndex); return true; } @@ -94,7 +96,8 @@ bool exec_chat_command(char* command) { chat_construct_player_message(np, DLANG(CHAT, ADD_MODERATOR)); np->moderator = true; network_send_moderator(np->localIndex); - moderator_list_add(gNetworkSystem->get_id_str(np->localIndex), true); + // TODO: Moderation: Allow you to insert a reason + moderation_list_add(MODERATION_LIST_TYPE_MODERATOR, np->localIndex, "", true); return true; } } @@ -120,7 +123,7 @@ bool exec_chat_command(char* command) { djui_chat_message_create(DLANG(CHAT, PLAYER_NOT_FOUND)); return true; } - + if (str_starts_with(command, "/kick ")) { if (gNetworkType != NT_SERVER && !npl->moderator) { djui_chat_message_create(DLANG(CHAT, NO_PERMS)); @@ -205,7 +208,7 @@ bool exec_chat_command(char* command) { return true; } - if (str_starts_with(command, "/moderator ")) { + if (str_starts_with(command, "/moderator ")) { if (gNetworkType != NT_SERVER) { djui_chat_message_create(DLANG(CHAT, SERVER_ONLY)); return true; diff --git a/src/pc/djui/djui_base.c b/src/pc/djui/djui_base.c index e4d85a506..7b60017e5 100644 --- a/src/pc/djui/djui_base.c +++ b/src/pc/djui/djui_base.c @@ -391,10 +391,12 @@ void djui_base_destroy(struct DjuiBase* base) { } // deallocate interactable - if (base->interactable != NULL) { - free(base->interactable); - base->interactable = NULL; - } + free(base->interactable); + base->interactable = NULL; + + // deallocate ctag + free(base->cTag); + base->cTag = NULL; // remove from interactable variable if (base == gDjuiHovered) { gDjuiHovered = NULL; } diff --git a/src/pc/djui/djui_base.h b/src/pc/djui/djui_base.h index 60174824e..2864c3875 100644 --- a/src/pc/djui/djui_base.h +++ b/src/pc/djui/djui_base.h @@ -43,7 +43,9 @@ struct DjuiBase { bool abandonAfterChildRenderFail; bool gradient; s64 tag; + u64 uTag; bool bTag; + char* cTag; void (*get_cursor_hover_location)(struct DjuiBase*, f32* x, f32* y); void (*on_child_render)(struct DjuiBase*, struct DjuiBase*); void (*on_render_pre)(struct DjuiBase*, bool*); diff --git a/src/pc/djui/djui_panel_confirm.c b/src/pc/djui/djui_panel_confirm.c index fc9dc948c..ea4fcfe9f 100644 --- a/src/pc/djui/djui_panel_confirm.c +++ b/src/pc/djui/djui_panel_confirm.c @@ -27,4 +27,4 @@ void djui_panel_confirm_create(struct DjuiBase* caller, char* title, char* messa } djui_panel_add(caller, panel, NULL); -} +} \ No newline at end of file diff --git a/src/pc/djui/djui_panel_host.c b/src/pc/djui/djui_panel_host.c index b1b069e4b..e9e3f682b 100644 --- a/src/pc/djui/djui_panel_host.c +++ b/src/pc/djui/djui_panel_host.c @@ -6,6 +6,7 @@ #include "djui_panel_host_settings.h" #include "djui_panel_host_save.h" #include "djui_panel_host_message.h" +#include "djui_panel_moderation_list.h" #include "djui_panel_rules.h" #include "game/save_file.h" #include "pc/network/network.h" @@ -181,6 +182,7 @@ void djui_panel_host_create(struct DjuiBase* caller) { djui_button_create(body, DLANG(HOST, SETTINGS), DJUI_BUTTON_STYLE_NORMAL, djui_panel_host_settings_create); djui_button_create(body, DLANG(HOST, MODS), DJUI_BUTTON_STYLE_NORMAL, djui_panel_host_mods_create); + djui_button_create(body, "Moderation Lists", DJUI_BUTTON_STYLE_NORMAL, djui_panel_moderation_list_create); struct DjuiRect* rect3 = djui_rect_container_create(body, 64); { diff --git a/src/pc/djui/djui_panel_pause.c b/src/pc/djui/djui_panel_pause.c index 9c993053d..4098305b8 100644 --- a/src/pc/djui/djui_panel_pause.c +++ b/src/pc/djui/djui_panel_pause.c @@ -5,6 +5,7 @@ #include "djui_panel_dynos.h" #include "djui_panel_options.h" #include "djui_panel_host.h" +#include "djui_panel_moderator_menu.h" #include "djui_panel_menu.h" #include "djui_panel_confirm.h" #include "djui_panel_mod_menu.h" @@ -72,6 +73,10 @@ void djui_panel_pause_create(struct DjuiBase* caller) { djui_button_create(body, DLANG(PAUSE, SERVER_SETTINGS), DJUI_BUTTON_STYLE_NORMAL, djui_panel_host_create); } + if (gNetworkType == NT_SERVER || network_is_moderator()) { + djui_button_create(body, DLANG(PAUSE, MODERATOR_MENU), DJUI_BUTTON_STYLE_NORMAL, djui_panel_moderator_menu_create); + } + struct Mod* addedMods[MAX_HOOKED_MOD_MENU_ELEMENTS] = { 0 }; int modCount = 0; for (int i = 0; i < gHookedModMenuElementsCount; i++) { diff --git a/src/pc/lua/utils/smlua_misc_utils.h b/src/pc/lua/utils/smlua_misc_utils.h index e4bb3c1eb..c9f07b98b 100644 --- a/src/pc/lua/utils/smlua_misc_utils.h +++ b/src/pc/lua/utils/smlua_misc_utils.h @@ -37,7 +37,7 @@ enum ActSelectHudPart { ACT_SELECT_HUD_ACT_NAME = 1 << 3, ACT_SELECT_HUD_STAR_NUM = 1 << 4, ACT_SELECT_HUD_PLAYERS_IN_LEVEL = 1 << 5, - + ACT_SELECT_HUD_NONE = 0, ACT_SELECT_HUD_ALL = ACT_SELECT_HUD_SCORE | ACT_SELECT_HUD_LEVEL_NAME | ACT_SELECT_HUD_COURSE_NUM | ACT_SELECT_HUD_ACT_NAME |ACT_SELECT_HUD_STAR_NUM | ACT_SELECT_HUD_PLAYERS_IN_LEVEL }; @@ -51,7 +51,6 @@ struct DateTime { s32 second; }; - /* |description|Gets the current area's networked timer|descriptionEnd| */ u32 get_network_area_timer(void); /* |description|Gets the area update counter incremented when objects are updated|descriptionEnd| */ diff --git a/src/pc/network/packets/packet.c b/src/pc/network/packets/packet.c index 199a88e5a..b2ccc9596 100644 --- a/src/pc/network/packets/packet.c +++ b/src/pc/network/packets/packet.c @@ -1,7 +1,7 @@ #include #include #include "../network.h" -#include "pc/network/ban_list.h" +#include "pc/network/moderation.h" #include "pc/debuglog.h" static u32 sCompBufferLen = 0; @@ -93,6 +93,7 @@ void packet_process(struct Packet* p) { case PACKET_KICK: network_receive_kick(p); break; case PACKET_COMMAND: network_receive_chat_command(p); break; case PACKET_MODERATOR: network_receive_moderator(p); break; + case PACKET_MODERATION_ACTION: network_receive_moderation_action(p); break; case PACKET_KEEP_ALIVE: network_receive_keep_alive(p); break; case PACKET_LEAVING: network_receive_leaving(p); break; case PACKET_SAVE_FILE: network_receive_save_file(p); break; @@ -153,7 +154,7 @@ void packet_receive(struct Packet* p) { // refuse packets from banned players if (gNetworkType == NT_SERVER) { - if (ban_list_contains(gNetworkSystem->get_id_str(p->localIndex))) { + if (moderation_list_contains(MODERATION_LIST_TYPE_BAN, gNetworkSystem->get_id_str(p->localIndex))) { LOG_INFO("kicking banned player"); network_send_kick(0, EKT_BANNED); return; diff --git a/src/pc/network/packets/packet.h b/src/pc/network/packets/packet.h index 5ab859760..9b2427fd7 100644 --- a/src/pc/network/packets/packet.h +++ b/src/pc/network/packets/packet.h @@ -74,9 +74,10 @@ enum PacketType { PACKET_LUA_CUSTOM, PACKET_LUA_CUSTOM_BYTESTRING, - + PACKET_COMMAND, PACKET_MODERATOR, + PACKET_MODERATION_ACTION, /// PACKET_CUSTOM = 255, @@ -248,6 +249,10 @@ void network_receive_chat_command(struct Packet* p); void network_send_moderator(u8 localIndex); void network_receive_moderator(struct Packet* p); +// packet_moderation.c +void network_send_moderation_action(u8 action, u8 localIndex, char* reason, bool permanent); +void network_receive_moderation_action(struct Packet* p); + // packet_keep_alive.c void network_send_keep_alive(u8 localIndex); void network_receive_keep_alive(struct Packet* p); diff --git a/src/pc/network/packets/packet_command_mod.c b/src/pc/network/packets/packet_command_mod.c index ce3fa0ba2..58cdba588 100644 --- a/src/pc/network/packets/packet_command_mod.c +++ b/src/pc/network/packets/packet_command_mod.c @@ -2,8 +2,7 @@ #include "../network.h" #include "pc/djui/djui_language.h" #include "pc/djui/djui_chat_message.h" -#include "pc/network/ban_list.h" -#include "pc/network/moderator_list.h" +#include "pc/network/moderation.h" #include "pc/debuglog.h" void network_send_chat_command(u8 globalIndex, enum ChatConfirmCommand ccc) { @@ -23,7 +22,7 @@ void network_receive_chat_command(struct Packet *p) { return; } - if (!moderator_list_contains(gNetworkSystem->get_id_str(p->localIndex))) { + if (!moderation_list_contains(MODERATION_LIST_TYPE_MODERATOR, gNetworkSystem->get_id_str(p->localIndex))) { LOG_ERROR("recieved moderator command from non moderator"); return; } @@ -48,21 +47,29 @@ void network_receive_chat_command(struct Packet *p) { } if (CCC == CCC_BAN) { network_send_kick(np->localIndex, EKT_BANNED); - ban_list_add(gNetworkSystem->get_id_str(np->localIndex), false); + // TODO: Moderation: Allow you to insert a reason + moderation_list_add(MODERATION_LIST_TYPE_BAN, np->localIndex, "", false); snprintf(message, 256, "\\#fff982\\Banned '%s%s\\#fff982\\'!", network_get_player_text_color_string(np->localIndex), np->name); } - network_player_disconnected(np->localIndex); + network_player_disconnected(np->globalIndex); djui_chat_message_create(message); } void network_send_moderator(u8 localIndex) { struct Packet p = { 0 }; packet_init(&p, PACKET_MODERATOR, false, PLMT_NONE); + packet_write(&p, &gNetworkPlayerLocal[localIndex].moderator, sizeof(bool)); network_send_to(localIndex, &p); } void network_receive_moderator(struct Packet *p) { - if (gNetworkPlayers[0].moderator || (network_player_any_connected() && gNetworkPlayers[p->localIndex].type != NPT_SERVER)) return; - gNetworkPlayers[0].moderator = true; - djui_chat_message_create(DLANG(CHAT, MOD_GRANTED)); + if (network_player_any_connected() && gNetworkPlayers[p->localIndex].type != NPT_SERVER) return; + bool moderator; + packet_read(p, &moderator, sizeof(bool)); + if (gNetworkPlayers[0].moderator == moderator) { + LOG_ERROR("Server moderator is telling me to be what I already am! Ignoring..."); + return; + } + gNetworkPlayers[0].moderator = moderator; + djui_chat_message_create(moderator ? DLANG(CHAT, MOD_GRANTED) : DLANG(CHAT, MOD_REVOKED)); } diff --git a/src/pc/network/packets/packet_join.c b/src/pc/network/packets/packet_join.c index 0f1602352..4d643452d 100644 --- a/src/pc/network/packets/packet_join.c +++ b/src/pc/network/packets/packet_join.c @@ -48,9 +48,12 @@ void network_send_join_request(void) { snprintf(version, MAX_VERSION_LENGTH, "%s", get_version()); packet_write(&p, &version, sizeof(u8) * MAX_VERSION_LENGTH); - packet_write(&p, &configPlayerModel, sizeof(u8)); - packet_write(&p, &configPlayerPalette, sizeof(struct PlayerPalette)); - packet_write(&p, &configPlayerName, sizeof(u8) * MAX_CONFIG_STRING); + packet_write(&p, &configPlayerModel, sizeof(u8)); + packet_write(&p, &configPlayerPalette, sizeof(struct PlayerPalette)); + packet_write(&p, &configPlayerName, sizeof(u8) * MAX_CONFIG_STRING); + char discordId[64]; + snprintf(discordId, 64, "%s", get_local_discord_id()); + packet_write(&p, &discordId, sizeof(u8) * 64); network_send_to((gNetworkPlayerServer != NULL) ? gNetworkPlayerServer->localIndex : 0, &p); LOG_INFO("sending join request"); @@ -66,10 +69,12 @@ void network_receive_join_request(struct Packet* p) { packet_read(p, &sJoinRequestPlayerModel, sizeof(u8)); packet_read(p, &sJoinRequestPlayerPalette, sizeof(struct PlayerPalette)); packet_read(p, &sJoinRequestPlayerName, sizeof(u8) * MAX_CONFIG_STRING); + packet_read(p, &sJoinRequestDiscordId, sizeof(u8) * 64); } else { sJoinRequestPlayerModel = 0; sJoinRequestPlayerPalette = DEFAULT_MARIO_PALETTE; snprintf(sJoinRequestPlayerName, MAX_CONFIG_STRING, "%s", "Player"); + snprintf(sJoinRequestDiscordId, 64, "%s", "0"); } network_send_join(p); diff --git a/src/pc/network/packets/packet_kick.c b/src/pc/network/packets/packet_kick.c index 9f2d006d2..b39bd591c 100644 --- a/src/pc/network/packets/packet_kick.c +++ b/src/pc/network/packets/packet_kick.c @@ -8,6 +8,10 @@ f32 sLastReconnectTime = -9999999; f32 sLastNotifyTime = -9999999; void network_send_kick(u8 localIndex, enum KickReasonType kickReason) { + if (localIndex == 0) { + LOG_ERROR("Trying to send kick to myself?"); + return; + } u8 kickReasonType = kickReason; struct Packet p = { 0 }; packet_init(&p, PACKET_KICK, true, PLMT_NONE); @@ -22,8 +26,8 @@ void network_receive_kick(struct Packet* p) { return; } - if (network_player_any_connected() && gNetworkPlayers[p->localIndex].type != NPT_SERVER) { - LOG_ERROR("Kick came from non-server... refuse!"); + if (network_player_any_connected() && gNetworkPlayers[p->localIndex].type != NPT_SERVER && !gNetworkPlayers[p->localIndex].moderator) { + LOG_ERROR("Kick came from non-server and non-moderator... refuse!"); return; } diff --git a/src/pc/network/packets/packet_network_players.c b/src/pc/network/packets/packet_network_players.c index c9e57e298..b8ac19e8f 100644 --- a/src/pc/network/packets/packet_network_players.c +++ b/src/pc/network/packets/packet_network_players.c @@ -5,7 +5,7 @@ #include "game/behavior_actions.h" #include "pc/debuglog.h" #include "pc/configfile.h" -#include "pc/network/moderator_list.h" +#include "pc/network/moderation.h" static void network_send_to_network_players(u8 sendToLocalIndex) { SOFT_ASSERT(gNetworkType == NT_SERVER); @@ -60,8 +60,9 @@ void network_receive_network_players_request(struct Packet* p) { } network_send_to_network_players(localIndex); - if (moderator_list_contains(gNetworkSystem->get_id_str(p->localIndex))) { - LOG_INFO("sending moderator packet to localIndex: %d", p->localIndex); + if (moderation_list_contains(MODERATION_LIST_TYPE_MODERATOR, gNetworkSystem->get_id_str(p->localIndex))) { + LOG_INFO("sending moderator packet to localIndex: %d", localIndex); + gNetworkPlayers[localIndex].moderator = true; network_send_moderator(p->localIndex); } } diff --git a/src/pc/network/packets/packet_player.c b/src/pc/network/packets/packet_player.c index 793def2db..3131136bb 100644 --- a/src/pc/network/packets/packet_player.c +++ b/src/pc/network/packets/packet_player.c @@ -253,7 +253,7 @@ void network_receive_player(struct Packet* p) { } #else network_send_kick(np->localIndex, EKT_KICKED); - network_player_disconnected(np->localIndex); + network_player_disconnected(np->globalIndex); return; #endif } diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c index 91f689b6d..9af6c0ec1 100644 --- a/src/pc/pc_main.c +++ b/src/pc/pc_main.c @@ -42,6 +42,7 @@ #include "pc/network/version.h" #include "pc/network/socket/socket.h" #include "pc/network/network_player.h" +#include "pc/network/moderation.h" #include "pc/update_checker.h" #include "pc/djui/djui.h" #include "pc/djui/djui_unicode.h" @@ -510,6 +511,7 @@ int main(int argc, char *argv[]) { #endif configfile_load(); + moderation_list_load(); legacy_folder_handler();