mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-05-10 10:51:39 +00:00
Push up changes, language stuff, add mod moderation commands, yipee
This commit is contained in:
parent
537eabc3bd
commit
88a552f601
30 changed files with 306 additions and 48 deletions
|
|
@ -8237,6 +8237,15 @@ HOOK_MAX = 60 --- @type LuaHookedEventType
|
|||
--- @type integer
|
||||
MAX_HOOKED_BEHAVIORS = 1024
|
||||
|
||||
DC_LEAVE = 0 --- @type DisconnectType
|
||||
DC_KICK = 1 --- @type DisconnectType
|
||||
DC_BAN = 2 --- @type DisconnectType
|
||||
|
||||
--- @alias DisconnectType
|
||||
--- | `DC_LEAVE`
|
||||
--- | `DC_KICK`
|
||||
--- | `DC_BAN`
|
||||
|
||||
HUD_DISPLAY_LIVES = 0 --- @type HudDisplayValue
|
||||
HUD_DISPLAY_COINS = 1 --- @type HudDisplayValue
|
||||
HUD_DISPLAY_STARS = 2 --- @type HudDisplayValue
|
||||
|
|
|
|||
|
|
@ -4149,6 +4149,13 @@ function djui_menu_get_rainbow_string_color(color)
|
|||
-- ...
|
||||
end
|
||||
|
||||
--- @param message string
|
||||
--- @param paddingLines integer
|
||||
--- Creates an auto-scaling popup that says `message` which will always show the entire message with padding lines of 'paddingLines'
|
||||
function djui_popup_create_auto_scaling(message, paddingLines)
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- @param message string
|
||||
--- @param lines integer
|
||||
--- Creates a popup that says `message` and has `lines`
|
||||
|
|
@ -11554,6 +11561,13 @@ function get_coopnet_id(localIndex)
|
|||
-- ...
|
||||
end
|
||||
|
||||
--- @param dcType DisconnectType
|
||||
--- @param reason? string
|
||||
--- Disconnects the local player with DisconnectType `dcType` (default is DC_LEAVE) because of `reason` (optional).
|
||||
function network_disconnect(dcType, reason)
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- @return number
|
||||
--- Gets the master volume level
|
||||
function get_volume_master()
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@
|
|||
- [enum LuaActionHookType](#enum-LuaActionHookType)
|
||||
- [enum LuaModMenuElementType](#enum-LuaModMenuElementType)
|
||||
- [smlua_misc_utils.h](#smlua_misc_utilsh)
|
||||
- [enum DisconnectType](#enum-DisconnectType)
|
||||
- [enum HudDisplayValue](#enum-HudDisplayValue)
|
||||
- [enum HudDisplayFlags](#enum-HudDisplayFlags)
|
||||
- [enum ActSelectHudPart](#enum-ActSelectHudPart)
|
||||
|
|
@ -3533,6 +3534,13 @@
|
|||
|
||||
## [smlua_misc_utils.h](#smlua_misc_utils.h)
|
||||
|
||||
### [enum DisconnectType](#DisconnectType)
|
||||
| Identifier | Value |
|
||||
| :--------- | :---- |
|
||||
| DC_LEAVE | 0 |
|
||||
| DC_KICK | 1 |
|
||||
| DC_BAN | 2 |
|
||||
|
||||
### [enum HudDisplayValue](#HudDisplayValue)
|
||||
| Identifier | Value |
|
||||
| :--------- | :---- |
|
||||
|
|
|
|||
|
|
@ -3823,6 +3823,30 @@ Gets the header hex color code from a `DJUI_RAINBOW_COLOR_*` constant
|
|||
<br />
|
||||
|
||||
|
||||
## [djui_popup_create_auto_scaling](#djui_popup_create_auto_scaling)
|
||||
|
||||
### Description
|
||||
Creates an auto-scaling popup that says `message` which will always show the entire message with padding lines of 'paddingLines'
|
||||
|
||||
### Lua Example
|
||||
`djui_popup_create_auto_scaling(message, paddingLines)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| message | `string` |
|
||||
| paddingLines | `integer` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void djui_popup_create_auto_scaling(const char* message, int paddingLines);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [djui_popup_create](#djui_popup_create)
|
||||
|
||||
### Description
|
||||
|
|
|
|||
|
|
@ -1840,6 +1840,30 @@ Gets the CoopNet ID of a player with `localIndex` if CoopNet is being used and t
|
|||
|
||||
<br />
|
||||
|
||||
## [network_disconnect](#network_disconnect)
|
||||
|
||||
### Description
|
||||
Disconnects the local player with DisconnectType `dcType` (default is DC_LEAVE) because of `reason` (optional).
|
||||
|
||||
### Lua Example
|
||||
`network_disconnect(dcType, reason)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| dcType | [enum DisconnectType](constants.md#enum-DisconnectType) |
|
||||
| reason | `string` |
|
||||
|
||||
### Returns
|
||||
- None
|
||||
|
||||
### C Prototype
|
||||
`void network_disconnect(enum DisconnectType dcType, OPTIONAL const char* reason);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [get_volume_master](#get_volume_master)
|
||||
|
||||
### Description
|
||||
|
|
|
|||
|
|
@ -809,6 +809,7 @@
|
|||
<br />
|
||||
|
||||
- djui_popup.h
|
||||
- [djui_popup_create_auto_scaling](functions-3.md#djui_popup_create_auto_scaling)
|
||||
- [djui_popup_create](functions-3.md#djui_popup_create)
|
||||
|
||||
<br />
|
||||
|
|
@ -2057,6 +2058,7 @@
|
|||
- [get_time_stop_flags](functions-7.md#get_time_stop_flags)
|
||||
- [get_local_discord_id](functions-7.md#get_local_discord_id)
|
||||
- [get_coopnet_id](functions-7.md#get_coopnet_id)
|
||||
- [network_disconnect](functions-7.md#network_disconnect)
|
||||
- [get_volume_master](functions-7.md#get_volume_master)
|
||||
- [get_volume_level](functions-7.md#get_volume_level)
|
||||
- [get_volume_sfx](functions-7.md#get_volume_sfx)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@ DISCORD_ERROR = "Discord threw an error.\nTo fix, try: \n1. Close the game.\n2.
|
|||
DISCORD_DETECT = "\\#ffa0a0\\Error:\\#dcdcdc\\ Could not detect Discord.\n\\#a0a0a0\\Try closing the game, restarting Discord, and opening the game again."
|
||||
DISCONNECT_FULL = "\\#ffa0a0\\Disconnected:\\#dcdcdc\\ The server is full."
|
||||
DISCONNECT_KICK = "\\#ffa0a0\\Disconnected:\\#dcdcdc\\ You have been kicked."
|
||||
DISCONNECT_KICK_REASON = "\\#ffa0a0\\Disconnected:\\#dcdcdc\\ You have been kicked. Reason: @"
|
||||
DISCONNECT_BAN = "\\#ffa0a0\\Disconnected:\\#dcdcdc\\ You have been banned."
|
||||
DISCONNECT_BAN_REASON = "\\#ffa0a0\\Disconnected:\\#dcdcdc\\ You have been banned. Reason: @"
|
||||
DISCONNECT_REJOIN = "\\#ffa0a0\\Disconnected:\\#dcdcdc\\ Rejoining..."
|
||||
DISCONNECT_CLOSED = "\\#ffa0a0\\Disconnected:\\#dcdcdc\\ Host closed the connection."
|
||||
DISCONNECT_BIG_MOD = "Server had too large of a mod.\nQuitting."
|
||||
|
|
|
|||
|
|
@ -54,14 +54,18 @@ bool exec_chat_command(char* command) {
|
|||
enum ChatConfirmCommand ccc = sConfirming;
|
||||
sConfirming = CCC_NONE;
|
||||
|
||||
if (ccc != CCC_NONE && strcmp("/confirm", command) == 0) {
|
||||
if (ccc != CCC_NONE && (strcmp("/confirm", command) == 0 || str_starts_with(command, "/confirm "))) {
|
||||
struct NetworkPlayer* np = &gNetworkPlayers[sConfirmPlayerIndex];
|
||||
if (!np->connected) return true;
|
||||
char* reason = NULL;
|
||||
if (str_starts_with(command, "/confirm ")) {
|
||||
reason = &command[9];
|
||||
}
|
||||
if (gNetworkType == NT_SERVER || npl->moderator) {
|
||||
if (ccc == CCC_KICK) {
|
||||
chat_construct_player_message(np, DLANG(CHAT, KICKING));
|
||||
if (gNetworkType == NT_SERVER) {
|
||||
network_send_kick(np->localIndex, EKT_KICKED);
|
||||
network_send_kick(np->localIndex, EKT_KICKED, reason);
|
||||
network_player_disconnected(np->localIndex);
|
||||
} else {
|
||||
network_send_chat_command(np->globalIndex, CCC_KICK);
|
||||
|
|
@ -73,10 +77,10 @@ bool exec_chat_command(char* command) {
|
|||
if (ccc == CCC_BAN) {
|
||||
chat_construct_player_message(np, DLANG(CHAT, BANNING));
|
||||
if (gNetworkType == NT_SERVER) {
|
||||
network_send_kick(np->localIndex, EKT_BANNED);
|
||||
network_send_kick(np->localIndex, EKT_BANNED, reason);
|
||||
|
||||
// TODO: Moderation: Allow you to insert a reason
|
||||
moderation_list_add(MODERATION_LIST_TYPE_BAN, np->localIndex, "", false);
|
||||
moderation_list_add(MODERATION_LIST_TYPE_BAN, np->localIndex, reason, false);
|
||||
network_player_disconnected(np->localIndex);
|
||||
} else {
|
||||
network_send_chat_command(np->globalIndex, CCC_BAN);
|
||||
|
|
@ -86,9 +90,9 @@ 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);
|
||||
network_send_kick(np->localIndex, EKT_BANNED, reason);
|
||||
// TODO: Moderation: Allow you to insert a reason
|
||||
moderation_list_add(MODERATION_LIST_TYPE_BAN, np->localIndex, "", true);
|
||||
moderation_list_add(MODERATION_LIST_TYPE_BAN, np->localIndex, reason, true);
|
||||
network_player_disconnected(np->localIndex);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -97,7 +101,7 @@ bool exec_chat_command(char* command) {
|
|||
np->moderator = true;
|
||||
network_send_moderator(np->localIndex);
|
||||
// TODO: Moderation: Allow you to insert a reason
|
||||
moderation_list_add(MODERATION_LIST_TYPE_MODERATOR, np->localIndex, "", true);
|
||||
moderation_list_add(MODERATION_LIST_TYPE_MODERATOR, np->localIndex, reason, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ void djui_language_replace(char* src, char* dst, int size, char key, char* value
|
|||
char* o = dst;
|
||||
while (*c != '\0') {
|
||||
if (*c == key) {
|
||||
snprintf(o, size - (o - dst), "%s", value);
|
||||
snprintf(o, size - (o - dst), "%s", value == NULL ? "" : value);
|
||||
} else {
|
||||
djui_unicode_get_char(c, tmpChar);
|
||||
snprintf(o, size - (o - dst), "%s", tmpChar);
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ static void djui_panel_moderation_confirm_destroy(struct DjuiBase* base) {
|
|||
free(sReason);
|
||||
sReason = NULL;
|
||||
sPermanent = false;
|
||||
sOnYesClick = NULL;
|
||||
}
|
||||
|
||||
void djui_panel_moderation_confirm_create_body(struct DjuiBase* caller, char* title, char* message, u8 localIndex, u8 action, bool permanent, char* address, void (*on_yes_click)(struct DjuiBase*)) {
|
||||
|
|
@ -95,7 +96,7 @@ void djui_panel_moderation_confirm_create_body(struct DjuiBase* caller, char* ti
|
|||
struct DjuiText* text = djui_text_create(body, message);
|
||||
djui_base_set_size_type(&text->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
|
||||
if (action == MODERATION_ACTION_BAN || action == MODERATION_ACTION_MOD) {
|
||||
if (action == MODERATION_ACTION_KICK || action == MODERATION_ACTION_BAN || action == MODERATION_ACTION_MOD) {
|
||||
struct DjuiRect* rect1 = djui_rect_container_create(body, 32);
|
||||
{
|
||||
struct DjuiText* text1 = djui_text_create(&rect1->base, DLANG(MODERATION, REASON));
|
||||
|
|
@ -112,7 +113,7 @@ void djui_panel_moderation_confirm_create_body(struct DjuiBase* caller, char* ti
|
|||
djui_interactable_hook_value_change(&inputbox1->base, djui_panel_moderation_confirm_reason_text_change);
|
||||
}
|
||||
|
||||
djui_checkbox_create(body, DLANG(MODERATION, PERMANENT), &sPermanent, NULL);
|
||||
if (action != MODERATION_ACTION_KICK) djui_checkbox_create(body, DLANG(MODERATION, PERMANENT), &sPermanent, NULL);
|
||||
}
|
||||
|
||||
djui_base_set_size(&text->base, 1.0f, 64);
|
||||
|
|
|
|||
|
|
@ -71,9 +71,10 @@ void djui_panel_moderation_list_inspect_create(struct DjuiBase* caller) {
|
|||
djui_text_set_drop_shadow(discordIdText, 64, 64, 64, 100);
|
||||
}
|
||||
|
||||
if (entry->reason && strcmp(entry->reason, "") != 0) {
|
||||
char reasonStr[512];
|
||||
djui_language_replace(DLANG(MODERATION, REASON_INFO), reasonStr, 512, '@', entry->reason);
|
||||
if (entry->reason[0] != '\0') {
|
||||
int reasonStrLen = MAX_REASON_LENGTH + strlen(DLANG(MODERATION, REASON_INFO)) + 1;
|
||||
char reasonStr[reasonStrLen];
|
||||
djui_language_replace(DLANG(MODERATION, REASON_INFO), reasonStr, reasonStrLen, '@', entry->reason);
|
||||
struct DjuiText* reasonText = djui_text_create(body, reasonStr);
|
||||
djui_base_set_color(&reasonText->base, 220, 220, 220, 255);
|
||||
djui_base_set_size_type(&reasonText->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "djui_panel.h"
|
||||
#include "djui_panel_menu.h"
|
||||
#include "djui_panel_moderator_menu.h"
|
||||
#include "djui_panel_moderator_menu_inspect.h"
|
||||
#include "djui_panel_moderation_list.h"
|
||||
#include "djui_panel_moderation_confirm_action.h"
|
||||
#include "pc/network/network.h"
|
||||
|
|
@ -12,8 +13,10 @@
|
|||
struct DjuiButton* sModButton = NULL;
|
||||
static u8 sSelectedIndex = 0;
|
||||
|
||||
static void djui_panel_moderator_inspector_validate_and_reload();
|
||||
|
||||
static void djui_panel_moderator_menu_action_button_click(struct DjuiBase* caller) {
|
||||
djui_panel_moderation_confirm_create(caller, caller->uTag, caller->tag, caller->bTag, djui_panel_moderator_menu_reload);
|
||||
djui_panel_moderation_confirm_create(caller, caller->uTag, caller->tag, caller->bTag, djui_panel_moderator_inspector_validate_and_reload);
|
||||
}
|
||||
|
||||
static void djui_panel_moderator_menu_inspector_destroy(struct DjuiBase* base) {
|
||||
|
|
@ -22,6 +25,14 @@ static void djui_panel_moderator_menu_inspector_destroy(struct DjuiBase* base) {
|
|||
sModButton = NULL;
|
||||
}
|
||||
|
||||
static void djui_panel_moderator_inspector_validate_and_reload() {
|
||||
djui_panel_moderator_menu_reload();
|
||||
if (sSelectedIndex >= MAX_PLAYERS) djui_panel_back_by(2);
|
||||
struct NetworkPlayer* np = &gNetworkPlayers[sSelectedIndex];
|
||||
if (!np->connected) djui_panel_back_by(2);
|
||||
djui_panel_moderator_inspector_reload();
|
||||
}
|
||||
|
||||
void djui_panel_moderator_inspector_reload() {
|
||||
if (!sModButton) return;
|
||||
if (sSelectedIndex >= MAX_PLAYERS) return;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@
|
|||
#include "pc/utils/misc.h"
|
||||
#include "pc/configfile.h"
|
||||
#include "pc/lua/utils/smlua_misc_utils.h"
|
||||
#include "djui_hud_utils.h"
|
||||
|
||||
#define DJUI_POPUP_WIDTH 400.0f
|
||||
#define DJUI_POPUP_LIFETIME 6.0f
|
||||
|
||||
struct DjuiPopupList {
|
||||
|
|
@ -35,25 +37,27 @@ static void djui_popup_destroy(struct DjuiBase* base) {
|
|||
free(popup);
|
||||
}
|
||||
|
||||
void djui_popup_create(const char* message, int lines) {
|
||||
static void djui_popup_create_interal(const char* message, int lines, int paddingLines) {
|
||||
if (djui_is_popup_disabled()) { return; }
|
||||
if (paddingLines < 0) paddingLines = 0;
|
||||
struct DjuiPopup* popup = calloc(1, sizeof(struct DjuiPopup));
|
||||
struct DjuiBase* base = &popup->base;
|
||||
|
||||
f32 height = lines * 32 + 32;
|
||||
f32 height = (lines + paddingLines) * 32 + 32;
|
||||
djui_base_init(&gDjuiRoot->base, base, djui_popup_render, djui_popup_destroy);
|
||||
djui_base_set_alignment(base, DJUI_HALIGN_RIGHT, DJUI_VALIGN_TOP);
|
||||
djui_base_set_location(base, 8, -height);
|
||||
djui_base_set_size(base, 400, height);
|
||||
djui_base_set_size(base, DJUI_POPUP_WIDTH, height);
|
||||
djui_base_set_border_width(base, 4);
|
||||
djui_base_set_color(base, 0, 0, 0, 220);
|
||||
djui_base_set_border_color(base, 0, 0, 0, 180);
|
||||
|
||||
struct DjuiText* text = djui_text_create(base, message);
|
||||
djui_base_set_size_type(&text->base, DJUI_SVT_RELATIVE, DJUI_SVT_RELATIVE);
|
||||
djui_base_set_size(&text->base, 1.0f, 1.0f);
|
||||
djui_base_set_alignment(&text->base, DJUI_HALIGN_CENTER, DJUI_VALIGN_CENTER);
|
||||
djui_base_set_size_type(&text->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(&text->base, 1.0f, lines * 32.0f);
|
||||
djui_base_set_color(&text->base, 220, 220, 220, 255);
|
||||
djui_text_set_alignment(text, DJUI_HALIGN_CENTER, DJUI_VALIGN_CENTER);
|
||||
djui_text_set_alignment(text, DJUI_HALIGN_CENTER, DJUI_VALIGN_TOP);
|
||||
djui_text_set_drop_shadow(text, 0, 0, 0, 64);
|
||||
popup->text = text;
|
||||
|
||||
|
|
@ -62,6 +66,19 @@ void djui_popup_create(const char* message, int lines) {
|
|||
play_sound(SOUND_MENU_PINCH_MARIO_FACE, gGlobalSoundSource);
|
||||
}
|
||||
|
||||
void djui_popup_create(const char* message, int lines) {
|
||||
int linesReq = (int)ceilf(djui_hud_measure_text(message) / DJUI_POPUP_WIDTH);
|
||||
if (linesReq < 1) linesReq = 1;
|
||||
if (linesReq > lines) linesReq = lines;
|
||||
djui_popup_create_interal(message, linesReq, lines - linesReq);
|
||||
}
|
||||
|
||||
void djui_popup_create_auto_scaling(const char* message, int paddingLines) {
|
||||
int linesReq = (int)ceilf(djui_hud_measure_text(message) / DJUI_POPUP_WIDTH);
|
||||
if (linesReq < 1) linesReq = 1;
|
||||
djui_popup_create_interal(message, linesReq, paddingLines);
|
||||
}
|
||||
|
||||
void djui_popup_update(void) {
|
||||
struct DjuiPopupList* node = sPopupListHead;
|
||||
struct DjuiPopupList* last = NULL;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ struct DjuiPopup {
|
|||
struct DjuiText* text;
|
||||
};
|
||||
|
||||
/* |description|Creates an auto-scaling popup that says `message` which will always show the entire message with padding lines of 'paddingLines'|descriptionEnd| */
|
||||
void djui_popup_create_auto_scaling(const char* message, int paddingLines);
|
||||
/* |description|Creates a popup that says `message` and has `lines`|descriptionEnd| */
|
||||
void djui_popup_create(const char* message, int lines);
|
||||
|
||||
void djui_popup_update(void);
|
||||
|
|
|
|||
|
|
@ -3536,6 +3536,9 @@ char gSmluaConstants[] = ""
|
|||
"HOOK_ON_PACKET_BYTESTRING_RECEIVE=59\n"
|
||||
"HOOK_MAX=60\n"
|
||||
"MAX_HOOKED_BEHAVIORS=1024\n"
|
||||
"DC_LEAVE=0\n"
|
||||
"DC_KICK=1\n"
|
||||
"DC_BAN=2\n"
|
||||
"HUD_DISPLAY_LIVES=0\n"
|
||||
"HUD_DISPLAY_COINS=1\n"
|
||||
"HUD_DISPLAY_STARS=2\n"
|
||||
|
|
|
|||
|
|
@ -13067,6 +13067,25 @@ int smlua_func_djui_menu_get_rainbow_string_color(lua_State* L) {
|
|||
// djui_popup.h //
|
||||
//////////////////
|
||||
|
||||
int smlua_func_djui_popup_create_auto_scaling(lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
int top = lua_gettop(L);
|
||||
if (top != 2) {
|
||||
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "djui_popup_create_auto_scaling", 2, top);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* message = smlua_to_string(L, 1);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "djui_popup_create_auto_scaling"); return 0; }
|
||||
int paddingLines = smlua_to_integer(L, 2);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "djui_popup_create_auto_scaling"); return 0; }
|
||||
|
||||
djui_popup_create_auto_scaling(message, paddingLines);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_djui_popup_create(lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
|
|
@ -34051,6 +34070,28 @@ int smlua_func_get_coopnet_id(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_network_disconnect(lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
int top = lua_gettop(L);
|
||||
if (top < 1 || top > 2) {
|
||||
LOG_LUA_LINE("Improper param count for '%s': Expected between %u and %u, Received %u", "network_disconnect", 1, 2, top);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dcType = smlua_to_integer(L, 1);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "network_disconnect"); return 0; }
|
||||
const char* reason = (const char*) NULL;
|
||||
if (top >= 2) {
|
||||
reason = smlua_to_string(L, 2);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "network_disconnect"); return 0; }
|
||||
}
|
||||
|
||||
network_disconnect(dcType, reason);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_get_volume_master(UNUSED lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
|
|
@ -37446,6 +37487,7 @@ void smlua_bind_functions_autogen(void) {
|
|||
smlua_bind_function(L, "djui_menu_get_rainbow_string_color", smlua_func_djui_menu_get_rainbow_string_color);
|
||||
|
||||
// djui_popup.h
|
||||
smlua_bind_function(L, "djui_popup_create_auto_scaling", smlua_func_djui_popup_create_auto_scaling);
|
||||
smlua_bind_function(L, "djui_popup_create", smlua_func_djui_popup_create);
|
||||
|
||||
// external.h
|
||||
|
|
@ -38617,6 +38659,7 @@ void smlua_bind_functions_autogen(void) {
|
|||
smlua_bind_function(L, "get_time_stop_flags", smlua_func_get_time_stop_flags);
|
||||
smlua_bind_function(L, "get_local_discord_id", smlua_func_get_local_discord_id);
|
||||
smlua_bind_function(L, "get_coopnet_id", smlua_func_get_coopnet_id);
|
||||
smlua_bind_function(L, "network_disconnect", smlua_func_network_disconnect);
|
||||
smlua_bind_function(L, "get_volume_master", smlua_func_get_volume_master);
|
||||
smlua_bind_function(L, "get_volume_level", smlua_func_get_volume_level);
|
||||
smlua_bind_function(L, "get_volume_sfx", smlua_func_get_volume_sfx);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "game/rumble_init.h"
|
||||
#include "game/sound_init.h"
|
||||
#include "pc/lua/utils/smlua_audio_utils.h"
|
||||
#include "pc/network/moderation.h"
|
||||
|
||||
#ifdef DISCORD_SDK
|
||||
#include "pc/discord/discord.h"
|
||||
|
|
@ -524,6 +525,30 @@ const char* get_coopnet_id(UNUSED s8 localIndex) {
|
|||
|
||||
///
|
||||
|
||||
void network_disconnect(enum DisconnectType dcType, OPTIONAL const char* reason) {
|
||||
switch (dcType) {
|
||||
case DC_KICK:
|
||||
if (gNetworkType == NT_SERVER) {
|
||||
LOG_LUA("network_disconnect: Cannot kick the server!");
|
||||
return;
|
||||
}
|
||||
network_send_moderation_action(MODERATION_ACTION_KICK, 0, (char*)reason, false);
|
||||
break;
|
||||
case DC_BAN:
|
||||
if (gNetworkType == NT_SERVER) {
|
||||
LOG_LUA("network_disconnect: Cannot ban the server!");
|
||||
return;
|
||||
}
|
||||
network_send_moderation_action(MODERATION_ACTION_BAN, 0, (char*)reason, false);
|
||||
break;
|
||||
default:
|
||||
gQueuedDisconnect = dcType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
f32 get_volume_master(void) {
|
||||
return gLuaVolumeMaster;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,12 @@
|
|||
#include "game/camera.h"
|
||||
#include "pc/lua/smlua_utils.h"
|
||||
|
||||
enum DisconnectType {
|
||||
DC_LEAVE,
|
||||
DC_KICK,
|
||||
DC_BAN
|
||||
};
|
||||
|
||||
enum HudDisplayValue {
|
||||
HUD_DISPLAY_LIVES,
|
||||
HUD_DISPLAY_COINS,
|
||||
|
|
@ -219,6 +225,9 @@ const char* get_local_discord_id(void);
|
|||
/* |description|Gets the CoopNet ID of a player with `localIndex` if CoopNet is being used and the player is connected, otherwise "-1" is returned|descriptionEnd| */
|
||||
const char* get_coopnet_id(s8 localIndex);
|
||||
|
||||
/* |description|Disconnects the local player with DisconnectType `dcType` (default is DC_LEAVE) because of `reason` (optional).|descriptionEnd| */
|
||||
void network_disconnect(enum DisconnectType dcType, OPTIONAL const char* reason);
|
||||
|
||||
/* |description|Gets the master volume level|descriptionEnd| */
|
||||
f32 get_volume_master(void);
|
||||
/* |description|Gets the volume level of music|descriptionEnd| */
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
#include "pc/debuglog.h"
|
||||
#include "pc/ini.h"
|
||||
|
||||
u8 gQueuedDisconnect = QUEUED_DISCONNECT_NONE;
|
||||
|
||||
void djui_reload_moderation_panels() {
|
||||
djui_panel_moderator_menu_reload();
|
||||
djui_panel_moderation_list_reload();
|
||||
|
|
@ -28,7 +30,7 @@ void network_kick_player(u8 localIndex, char* reason) {
|
|||
LOG_ERROR("Tried to perform moderation on disconnected player!");
|
||||
return;
|
||||
}
|
||||
network_send_kick(np->localIndex, EKT_KICKED);
|
||||
network_send_kick(np->localIndex, EKT_KICKED, reason);
|
||||
network_player_disconnected(np->globalIndex);
|
||||
}
|
||||
|
||||
|
|
@ -47,7 +49,7 @@ void network_ban_player(u8 localIndex, char* reason, bool permanent) {
|
|||
return;
|
||||
}
|
||||
moderation_list_add(MODERATION_LIST_TYPE_BAN, localIndex, reason, permanent);
|
||||
network_send_kick(np->localIndex, EKT_BANNED);
|
||||
network_send_kick(np->localIndex, EKT_BANNED, reason);
|
||||
network_player_disconnected(np->globalIndex);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
#include <stdbool.h>
|
||||
|
||||
#define QUEUED_DISCONNECT_NONE 255
|
||||
|
||||
enum ModerationActions {
|
||||
MODERATION_ACTION_KICK,
|
||||
MODERATION_ACTION_BAN,
|
||||
|
|
@ -10,6 +12,8 @@ enum ModerationActions {
|
|||
MODERATION_ACTION_COUNT,
|
||||
};
|
||||
|
||||
extern u8 gQueuedDisconnect;
|
||||
|
||||
void djui_reload_moderation_panels();
|
||||
void network_kick_player(u8 localIndex, char* reason);
|
||||
void network_ban_player(u8 localIndex, char* reason, bool permanent);
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ void moderation_list_load() {
|
|||
entry->playerColor[2] = strtol(safe_ini_get(iniFile, entrySection, "playerColorB"), NULL, 0);
|
||||
entry->address = strdup(safe_ini_get(iniFile, entrySection, "address"));
|
||||
entry->discordId = strdup(safe_ini_get(iniFile, entrySection, "discordId"));
|
||||
entry->reason = strdup(safe_ini_get(iniFile, entrySection, "reason"));
|
||||
snprintf(entry->reason, MAX_REASON_LENGTH, "%s", safe_ini_get(iniFile, entrySection, "reason"));
|
||||
|
||||
list->list[list->count++] = entry;
|
||||
}
|
||||
|
|
@ -114,7 +114,7 @@ void moderation_list_add(enum ModerationListType type, u8 localIndex, char* reas
|
|||
memcpy(entry->playerColor, network_get_player_text_color(np->localIndex), 3);
|
||||
entry->address = strdup(gNetworkSystem->get_id_str(localIndex));
|
||||
entry->discordId = strdup(network_discord_id_from_local_index(localIndex));
|
||||
entry->reason = strdup(reason ? reason : "");
|
||||
snprintf(entry->reason, MAX_REASON_LENGTH, "%s", reason ? reason : "");
|
||||
entry->permanent = permanent;
|
||||
time(&entry->time);
|
||||
|
||||
|
|
@ -131,7 +131,6 @@ void moderation_list_remove(enum ModerationListType type, char* address) {
|
|||
free(list->list[i]->playerName);
|
||||
free(list->list[i]->address);
|
||||
free(list->list[i]->discordId);
|
||||
free(list->list[i]->reason);
|
||||
free(list->list[i]);
|
||||
|
||||
for (u16 j = i; j < list->count - 1; j++) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#define MODERATION_LIST_FILEPATH "moderation_list.ini"
|
||||
#define MAX_MODERATION_LIST_ENTRIES 1024
|
||||
#define MAX_REASON_LENGTH 256
|
||||
|
||||
enum ModerationListType {
|
||||
MODERATION_LIST_TYPE_BAN,
|
||||
|
|
@ -18,7 +19,7 @@ struct ModerationEntry {
|
|||
u8 playerColor[3];
|
||||
char* address;
|
||||
char* discordId;
|
||||
char* reason;
|
||||
char reason[MAX_REASON_LENGTH];
|
||||
bool permanent;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "game/level_update.h"
|
||||
#include "object_constants.h"
|
||||
#include "behavior_table.h"
|
||||
#include "moderation.h"
|
||||
#include "pc/configfile.h"
|
||||
#include "pc/djui/djui.h"
|
||||
#include "pc/djui/djui_panel.h"
|
||||
|
|
@ -498,7 +499,7 @@ void network_rehost_begin(void) {
|
|||
struct NetworkPlayer* np = &gNetworkPlayers[i];
|
||||
if (!np->connected) { continue; }
|
||||
|
||||
network_send_kick(i, EKT_REJOIN);
|
||||
network_send_kick(i, EKT_REJOIN, NULL);
|
||||
network_player_disconnected(i);
|
||||
}
|
||||
|
||||
|
|
@ -635,6 +636,13 @@ void network_update(void) {
|
|||
network_reset_reconnect_and_rehost();
|
||||
network_shutdown(true, false, false, false);
|
||||
}
|
||||
|
||||
if (gNetworkType != NT_NONE && !gDjuiInMainMenu && gQueuedDisconnect != QUEUED_DISCONNECT_NONE) {
|
||||
network_reset_reconnect_and_rehost();
|
||||
network_shutdown(true, false, false, false);
|
||||
} else {
|
||||
gQueuedDisconnect = QUEUED_DISCONNECT_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void color_set(Color color, u8 r, u8 g, u8 b) {
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ void packet_receive(struct Packet* p) {
|
|||
if (gNetworkType == NT_SERVER) {
|
||||
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);
|
||||
network_send_kick(0, EKT_BANNED, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -179,7 +179,7 @@ void packet_receive(struct Packet* p) {
|
|||
}
|
||||
if (packetType != PACKET_PLAYER) {
|
||||
LOG_INFO("closing connection for packetType: %d", packetType);
|
||||
network_send_kick(0, EKT_CLOSE_CONNECTION);
|
||||
network_send_kick(0, EKT_CLOSE_CONNECTION, NULL);
|
||||
}
|
||||
LOG_INFO("refusing packet from unknown player, packetType: %d", packetType);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -238,7 +238,8 @@ void network_send_chat(char* message, u8 globalIndex);
|
|||
void network_receive_chat(struct Packet* p);
|
||||
|
||||
// packet_kick.c
|
||||
void network_send_kick(u8 localIndex, enum KickReasonType kickReason);
|
||||
void network_create_kick_popup(enum KickReasonType kickReason, char* reason);
|
||||
void network_send_kick(u8 localIndex, enum KickReasonType kickReason, char* reason);
|
||||
void network_receive_kick(struct Packet* p);
|
||||
|
||||
// packet_command_mod.c
|
||||
|
|
|
|||
|
|
@ -42,11 +42,11 @@ void network_receive_chat_command(struct Packet *p) {
|
|||
}
|
||||
char message[256] = { 0 };
|
||||
if (CCC == CCC_KICK) {
|
||||
network_send_kick(np->localIndex, EKT_KICKED);
|
||||
network_send_kick(np->localIndex, EKT_KICKED, NULL);
|
||||
snprintf(message, 256, "\\#fff982\\Kicked '%s%s\\#fff982\\'!", network_get_player_text_color_string(np->localIndex), np->name);
|
||||
}
|
||||
if (CCC == CCC_BAN) {
|
||||
network_send_kick(np->localIndex, EKT_BANNED);
|
||||
network_send_kick(np->localIndex, EKT_BANNED, NULL);
|
||||
// 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);
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ void network_send_join(struct Packet* joinRequestPacket) {
|
|||
}
|
||||
}
|
||||
if (globalIndex == UNKNOWN_LOCAL_INDEX || connectedCount >= gServerSettings.maxPlayers) {
|
||||
network_send_kick(0, EKT_FULL_PARTY);
|
||||
network_send_kick(0, EKT_FULL_PARTY, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include <stdio.h>
|
||||
#include "../network.h"
|
||||
#include "../moderation.h"
|
||||
#include "pc/debuglog.h"
|
||||
#include "pc/djui/djui.h"
|
||||
#include "pc/utils/misc.h"
|
||||
|
|
@ -7,7 +8,38 @@
|
|||
f32 sLastReconnectTime = -9999999;
|
||||
f32 sLastNotifyTime = -9999999;
|
||||
|
||||
void network_send_kick(u8 localIndex, enum KickReasonType kickReason) {
|
||||
void network_create_kick_popup(enum KickReasonType kickReason, char* reason) {
|
||||
char* text = NULL;
|
||||
|
||||
switch (kickReason) {
|
||||
case EKT_FULL_PARTY:
|
||||
text = DLANG(NOTIF, DISCONNECT_FULL);
|
||||
break;
|
||||
case EKT_KICKED:
|
||||
if (reason && reason[0] != '\0') {
|
||||
text = DLANG(NOTIF, DISCONNECT_KICK_REASON);
|
||||
} else {
|
||||
text = DLANG(NOTIF, DISCONNECT_KICK);
|
||||
}
|
||||
break;
|
||||
case EKT_BANNED:
|
||||
if (reason && reason[0] != '\0') {
|
||||
text = DLANG(NOTIF, DISCONNECT_BAN_REASON);
|
||||
} else {
|
||||
text = DLANG(NOTIF, DISCONNECT_BAN);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
text = DLANG(NOTIF, DISCONNECT_CLOSED);
|
||||
break;
|
||||
}
|
||||
|
||||
char popupText[512] = { 0 };
|
||||
djui_language_replace(text, popupText, 512, '@', reason);
|
||||
djui_popup_create_auto_scaling(popupText, 1);
|
||||
}
|
||||
|
||||
void network_send_kick(u8 localIndex, enum KickReasonType kickReason, char* reason) {
|
||||
if (localIndex == 0) {
|
||||
LOG_ERROR("Trying to send kick to myself?");
|
||||
return;
|
||||
|
|
@ -17,6 +49,15 @@ void network_send_kick(u8 localIndex, enum KickReasonType kickReason) {
|
|||
packet_init(&p, PACKET_KICK, true, PLMT_NONE);
|
||||
p.keepSendingAfterDisconnect = (kickReason == EKT_REJOIN);
|
||||
packet_write(&p, &kickReasonType, sizeof(u8));
|
||||
if (reason) {
|
||||
u16 reasonLength = strlen(reason);
|
||||
if (reasonLength >= MAX_REASON_LENGTH) reasonLength = MAX_REASON_LENGTH - 1;
|
||||
packet_write(&p, &reasonLength, sizeof(u16));
|
||||
packet_write(&p, reason, sizeof(u8) * reasonLength);
|
||||
} else {
|
||||
u16 reasonLength = 0;
|
||||
packet_write(&p, &reasonLength, sizeof(u16));
|
||||
}
|
||||
network_send_to(localIndex, &p);
|
||||
}
|
||||
|
||||
|
|
@ -32,18 +73,18 @@ void network_receive_kick(struct Packet* p) {
|
|||
}
|
||||
|
||||
u8 kickReasonType;
|
||||
u16 reasonLength = 0;
|
||||
char reason[MAX_REASON_LENGTH] = { 0 };
|
||||
packet_read(p, &kickReasonType, sizeof(u8));
|
||||
enum KickReasonType kickReason = kickReasonType;
|
||||
packet_read(p, &reasonLength, sizeof(u16));
|
||||
if (reasonLength >= MAX_REASON_LENGTH) reasonLength = MAX_REASON_LENGTH - 1;
|
||||
if (reasonLength > 0) packet_read(p, reason, sizeof(u8) * reasonLength);
|
||||
|
||||
f32 now = clock_elapsed();
|
||||
if ((now - sLastNotifyTime) > 3) {
|
||||
sLastNotifyTime = now;
|
||||
switch (kickReason) {
|
||||
case EKT_FULL_PARTY: djui_popup_create(DLANG(NOTIF, DISCONNECT_FULL), 1); break;
|
||||
case EKT_KICKED: djui_popup_create(DLANG(NOTIF, DISCONNECT_KICK), 1); break;
|
||||
case EKT_BANNED: djui_popup_create(DLANG(NOTIF, DISCONNECT_BAN), 1); break;
|
||||
default: djui_popup_create(DLANG(NOTIF, DISCONNECT_CLOSED), 1); break;
|
||||
}
|
||||
network_create_kick_popup(kickReasonType, reason);
|
||||
}
|
||||
|
||||
if (kickReason == EKT_REJOIN) {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ bool sValidActions[MODERATION_ACTION_COUNT] = {
|
|||
|
||||
void network_send_moderation_action(u8 action, u8 localIndex, char* reason, bool permanent) {
|
||||
SOFT_ASSERT(gNetworkType != NT_SERVER);
|
||||
if (!gNetworkPlayerLocal->moderator) {
|
||||
if (!gNetworkPlayerLocal->moderator && localIndex != 0) {
|
||||
LOG_ERROR("Tried to send moderation action as a non-moderator!");
|
||||
return;
|
||||
}
|
||||
|
|
@ -18,7 +18,7 @@ void network_send_moderation_action(u8 action, u8 localIndex, char* reason, bool
|
|||
if (!np->connected) {
|
||||
LOG_ERROR("Moderator tried to perform moderation on a disconnected player!");
|
||||
}
|
||||
if (np->moderator) {
|
||||
if (np->moderator && localIndex != 0) {
|
||||
LOG_ERROR("Moderator tried to perform moderation on another moderator!");
|
||||
return;
|
||||
}
|
||||
|
|
@ -32,16 +32,17 @@ void network_send_moderation_action(u8 action, u8 localIndex, char* reason, bool
|
|||
packet_init(&p, PACKET_MODERATION_ACTION, false, PLMT_NONE);
|
||||
packet_write(&p, &action, sizeof(u8));
|
||||
packet_write(&p, &np->globalIndex, sizeof(u8));
|
||||
u16 reasonLength = 0;
|
||||
if (reason) {
|
||||
u16 reasonLength = strlen(reason);
|
||||
packet_write(&p, &reasonLength, sizeof(u16));
|
||||
packet_write(&p, &reason, sizeof(u8) * reasonLength);
|
||||
packet_write(&p, reason, sizeof(u8) * reasonLength);
|
||||
} else {
|
||||
packet_write(&p, 0, sizeof(u16));
|
||||
packet_write(&p, &reasonLength, sizeof(u16));
|
||||
}
|
||||
packet_write(&p, &permanent, sizeof(bool));
|
||||
|
||||
network_send_to(gNetworkPlayerServer->globalIndex, &p);
|
||||
network_send_to(gNetworkPlayerServer->localIndex, &p);
|
||||
}
|
||||
|
||||
void network_receive_moderation_action(struct Packet* p) {
|
||||
|
|
@ -50,7 +51,7 @@ void network_receive_moderation_action(struct Packet* p) {
|
|||
enum ModerationActions action = MODERATION_ACTION_COUNT;
|
||||
u8 globalIndex = 0;
|
||||
u16 reasonLength = 0;
|
||||
char* reason = NULL;
|
||||
char reason[MAX_REASON_LENGTH] = { 0 };
|
||||
bool permanent = false;
|
||||
|
||||
packet_read(p, &action, sizeof(u8));
|
||||
|
|
@ -71,7 +72,8 @@ void network_receive_moderation_action(struct Packet* p) {
|
|||
}
|
||||
|
||||
packet_read(p, &reasonLength, sizeof(u16));
|
||||
packet_read(p, &reason, sizeof(u8) * reasonLength);
|
||||
if (reasonLength >= MAX_REASON_LENGTH) reasonLength = MAX_REASON_LENGTH - 1;
|
||||
packet_read(p, reason, sizeof(u8) * reasonLength);
|
||||
packet_read(p, &permanent, sizeof(bool));
|
||||
|
||||
switch (action) {
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ void network_receive_player(struct Packet* p) {
|
|||
construct_player_popup(np, DLANG(NOTIF, DEBUG_FLY), NULL);
|
||||
}
|
||||
#else
|
||||
network_send_kick(np->localIndex, EKT_KICKED);
|
||||
network_send_kick(np->localIndex, EKT_KICKED, NULL);
|
||||
network_player_disconnected(np->globalIndex);
|
||||
return;
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue