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
This commit is contained in:
EmeraldLockdown 2026-03-06 23:27:10 -06:00
parent dd838ad979
commit 11ee2f6e82
16 changed files with 77 additions and 34 deletions

View file

@ -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"

View file

@ -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;

View file

@ -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; }

View file

@ -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*);

View file

@ -27,4 +27,4 @@ void djui_panel_confirm_create(struct DjuiBase* caller, char* title, char* messa
}
djui_panel_add(caller, panel, NULL);
}
}

View file

@ -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);
{

View file

@ -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++) {

View file

@ -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| */

View file

@ -1,7 +1,7 @@
#include <stdio.h>
#include <zlib.h>
#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;

View file

@ -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);

View file

@ -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));
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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
}

View file

@ -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();