mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-05-10 19:01:46 +00:00
Huge console and terminal rewrite
This commit is contained in:
parent
fb8fbd1136
commit
ca897a1ef2
37 changed files with 2913 additions and 430 deletions
2
Makefile
2
Makefile
|
|
@ -517,7 +517,7 @@ ifeq ($(DISCORD_SDK),1)
|
||||||
SRC_DIRS += src/pc/discord
|
SRC_DIRS += src/pc/discord
|
||||||
endif
|
endif
|
||||||
|
|
||||||
SRC_DIRS += src/pc/mumble
|
SRC_DIRS += src/pc/mumble src/pc/linenoise
|
||||||
|
|
||||||
ULTRA_SRC_DIRS := lib/src lib/src/math lib/asm lib/data
|
ULTRA_SRC_DIRS := lib/src lib/src/math lib/asm lib/data
|
||||||
ULTRA_BIN_DIRS := lib/bin
|
ULTRA_BIN_DIRS := lib/bin
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ in_files = [
|
||||||
"src/game/mario_step.h",
|
"src/game/mario_step.h",
|
||||||
"src/game/mario.h",
|
"src/game/mario.h",
|
||||||
"src/game/rumble_init.h",
|
"src/game/rumble_init.h",
|
||||||
|
"src/pc/commands.h",
|
||||||
"src/pc/djui/djui_popup.h",
|
"src/pc/djui/djui_popup.h",
|
||||||
"src/pc/network/network_utils.h",
|
"src/pc/network/network_utils.h",
|
||||||
"src/pc/djui/djui_console.h",
|
"src/pc/djui/djui_console.h",
|
||||||
|
|
@ -86,6 +87,7 @@ in_files = [
|
||||||
override_allowed_functions = {
|
override_allowed_functions = {
|
||||||
"src/audio/external.h": [ " play_", "fade", "current_background", "stop_", "sound_banks", "drop_queued_background_music", "set_sound_moving_speed", "background_music_default_volume", "get_sound_pan", "sound_get_level_intensity", "set_audio_muted" ],
|
"src/audio/external.h": [ " play_", "fade", "current_background", "stop_", "sound_banks", "drop_queued_background_music", "set_sound_moving_speed", "background_music_default_volume", "get_sound_pan", "sound_get_level_intensity", "set_audio_muted" ],
|
||||||
"src/game/rumble_init.h": [ "queue_rumble_", "reset_rumble_timers" ],
|
"src/game/rumble_init.h": [ "queue_rumble_", "reset_rumble_timers" ],
|
||||||
|
"src/pc/commands.h": [ "command_message_create" ],
|
||||||
"src/pc/djui/djui_popup.h": [ "create" ],
|
"src/pc/djui/djui_popup.h": [ "create" ],
|
||||||
"src/pc/djui/djui_language.h": [ "djui_language_get" ],
|
"src/pc/djui/djui_language.h": [ "djui_language_get" ],
|
||||||
"src/pc/djui/djui_panel_menu.h": [ "djui_menu_get_rainbow_string_color" ],
|
"src/pc/djui/djui_panel_menu.h": [ "djui_menu_get_rainbow_string_color" ],
|
||||||
|
|
|
||||||
|
|
@ -2751,6 +2751,9 @@ DIALOG_COUNT = 170 --- @type DialogId
|
||||||
--- | `DIALOG_169`
|
--- | `DIALOG_169`
|
||||||
--- | `DIALOG_COUNT`
|
--- | `DIALOG_COUNT`
|
||||||
|
|
||||||
|
--- @type integer
|
||||||
|
MAX_CONSOLE_INPUT_LENGTH = 500
|
||||||
|
|
||||||
CONSOLE_MESSAGE_INFO = 0 --- @type ConsoleMessageLevel
|
CONSOLE_MESSAGE_INFO = 0 --- @type ConsoleMessageLevel
|
||||||
CONSOLE_MESSAGE_WARNING = 1 --- @type ConsoleMessageLevel
|
CONSOLE_MESSAGE_WARNING = 1 --- @type ConsoleMessageLevel
|
||||||
CONSOLE_MESSAGE_ERROR = 2 --- @type ConsoleMessageLevel
|
CONSOLE_MESSAGE_ERROR = 2 --- @type ConsoleMessageLevel
|
||||||
|
|
|
||||||
|
|
@ -3789,6 +3789,12 @@ function update_character_anim_offset(m)
|
||||||
-- ...
|
-- ...
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- @param message string
|
||||||
|
--- @param level? ConsoleMessageLevel
|
||||||
|
function command_message_create(message, level)
|
||||||
|
-- ...
|
||||||
|
end
|
||||||
|
|
||||||
--- @param message string
|
--- @param message string
|
||||||
--- Creates a `message` in the game's chat box
|
--- Creates a `message` in the game's chat box
|
||||||
function djui_chat_message_create(message)
|
function djui_chat_message_create(message)
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ extern "C" {
|
||||||
#include "game/moving_texture.h"
|
#include "game/moving_texture.h"
|
||||||
#include "pc/djui/djui_console.h"
|
#include "pc/djui/djui_console.h"
|
||||||
#include "pc/fs/fmem.h"
|
#include "pc/fs/fmem.h"
|
||||||
|
#include "pc/debuglog.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FUNCTION_CODE (u32) 0x434E5546
|
#define FUNCTION_CODE (u32) 0x434E5546
|
||||||
|
|
@ -730,13 +731,13 @@ T *CopyBytes(const T *aPtr, u64 aSize) {
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void PrintNoNewLine(const char *aFmt, Args... aArgs) {
|
void PrintNoNewLine(const char *aFmt, Args... aArgs) {
|
||||||
printf(aFmt, aArgs...);
|
log_to_terminal(aFmt, aArgs...);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void Print(const char *aFmt, Args... aArgs) {
|
void Print(const char *aFmt, Args... aArgs) {
|
||||||
printf(aFmt, aArgs...);
|
log_to_terminal(aFmt, aArgs...);
|
||||||
printf("\r\n");
|
printf("\r\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
@ -750,7 +751,7 @@ void PrintConsole(enum ConsoleMessageLevel level, const char *aFmt, Args... aArg
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void PrintError(const char *aFmt, Args... aArgs) {
|
void PrintError(const char *aFmt, Args... aArgs) {
|
||||||
printf(aFmt, aArgs...);
|
log_to_terminal(aFmt, aArgs...);
|
||||||
printf("\r\n");
|
printf("\r\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
PrintConsole(CONSOLE_MESSAGE_ERROR, aFmt, aArgs...);
|
PrintConsole(CONSOLE_MESSAGE_ERROR, aFmt, aArgs...);
|
||||||
|
|
|
||||||
|
|
@ -1136,6 +1136,7 @@
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
## [djui_console.h](#djui_console.h)
|
## [djui_console.h](#djui_console.h)
|
||||||
|
- MAX_CONSOLE_INPUT_LENGTH
|
||||||
|
|
||||||
### [enum ConsoleMessageLevel](#ConsoleMessageLevel)
|
### [enum ConsoleMessageLevel](#ConsoleMessageLevel)
|
||||||
| Identifier | Value |
|
| Identifier | Value |
|
||||||
|
|
|
||||||
|
|
@ -2661,6 +2661,33 @@ Updates Mario's current animation offset. This adjusts Mario's position based on
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
# functions from commands.h
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
|
||||||
|
## [command_message_create](#command_message_create)
|
||||||
|
|
||||||
|
### Lua Example
|
||||||
|
`command_message_create(message, level)`
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
| Field | Type |
|
||||||
|
| ----- | ---- |
|
||||||
|
| message | `string` |
|
||||||
|
| level | [enum ConsoleMessageLevel](constants.md#enum-ConsoleMessageLevel) |
|
||||||
|
|
||||||
|
### Returns
|
||||||
|
- None
|
||||||
|
|
||||||
|
### C Prototype
|
||||||
|
`void command_message_create(const char* message, OPTIONAL enum ConsoleMessageLevel level);`
|
||||||
|
|
||||||
|
[:arrow_up_small:](#)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
---
|
---
|
||||||
# functions from djui_chat_message.h
|
# functions from djui_chat_message.h
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -740,6 +740,11 @@
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
|
- commands.h
|
||||||
|
- [command_message_create](functions-3.md#command_message_create)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
- djui_chat_message.h
|
- djui_chat_message.h
|
||||||
- [djui_chat_message_create](functions-3.md#djui_chat_message_create)
|
- [djui_chat_message_create](functions-3.md#djui_chat_message_create)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "pc/ini.h"
|
#include "pc/ini.h"
|
||||||
|
#include "pc/debuglog.h"
|
||||||
#include "pc/mods/mods.h"
|
#include "pc/mods/mods.h"
|
||||||
#include "pc/mods/mods_utils.h"
|
#include "pc/mods/mods_utils.h"
|
||||||
#include "player_palette.h"
|
#include "player_palette.h"
|
||||||
|
|
@ -118,7 +119,7 @@ void player_palettes_read(const char* palettesPath, bool appendPalettes) {
|
||||||
|
|
||||||
if (!player_palette_init(palettesPath, path, appendPalettes)) {
|
if (!player_palette_init(palettesPath, path, appendPalettes)) {
|
||||||
#ifdef DEVELOPMENT
|
#ifdef DEVELOPMENT
|
||||||
printf("Failed to load palette '%s.ini'\n", path);
|
LOG_ERROR("Failed to load palette '%s.ini'\n", path);
|
||||||
#endif
|
#endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -140,7 +141,7 @@ void player_palettes_read(const char* palettesPath, bool appendPalettes) {
|
||||||
gPresetPalettes[gPresetPaletteCount].palette = palette;
|
gPresetPalettes[gPresetPaletteCount].palette = palette;
|
||||||
gPresetPaletteCount++;
|
gPresetPaletteCount++;
|
||||||
#ifdef DEVELOPMENT
|
#ifdef DEVELOPMENT
|
||||||
printf("Loaded palette '%s.ini'\n", path);
|
LOG_INFO("Loaded palette '%s.ini'\n", path);
|
||||||
#endif
|
#endif
|
||||||
if (gPresetPaletteCount >= MAX_PRESET_PALETTES) { break; }
|
if (gPresetPaletteCount >= MAX_PRESET_PALETTES) { break; }
|
||||||
}
|
}
|
||||||
|
|
@ -160,7 +161,7 @@ void player_palette_export(char* name) {
|
||||||
snprintf(ppath, SYS_MAX_PATH, "%s/%s.ini", palettesPath, name);
|
snprintf(ppath, SYS_MAX_PATH, "%s/%s.ini", palettesPath, name);
|
||||||
fs_sys_mkdir(palettesPath);
|
fs_sys_mkdir(palettesPath);
|
||||||
|
|
||||||
printf("Saving palette as '%s.ini'\n", name);
|
LOG_INFO("Saving palette as '%s.ini'\n", name);
|
||||||
FILE* file = fopen(ppath, "w");
|
FILE* file = fopen(ppath, "w");
|
||||||
fprintf(file, "[PALETTE]\n\
|
fprintf(file, "[PALETTE]\n\
|
||||||
PANTS_R = %d\n\
|
PANTS_R = %d\n\
|
||||||
|
|
@ -224,7 +225,7 @@ bool player_palette_delete(const char* palettesPath, char* name, bool appendPale
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remove(ppath) == 0) {
|
if (remove(ppath) == 0) {
|
||||||
printf("Deleting palette '%s.ini'\n", name);
|
LOG_INFO("Deleting palette '%s.ini'\n", name);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -1,276 +0,0 @@
|
||||||
#include "pc/network/network.h"
|
|
||||||
#include "pc/network/socket/socket.h"
|
|
||||||
#include "pc/lua/smlua_hooks.h"
|
|
||||||
#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/debuglog.h"
|
|
||||||
#include "pc/lua/utils/smlua_level_utils.h"
|
|
||||||
#include "pc/mods/mods_utils.h"
|
|
||||||
#include "level_table.h"
|
|
||||||
#ifdef DEVELOPMENT
|
|
||||||
#include "pc/dev/chat.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static enum ChatConfirmCommand sConfirming = CCC_NONE;
|
|
||||||
static u8 sConfirmPlayerIndex = 0;
|
|
||||||
|
|
||||||
static struct NetworkPlayer* chat_get_network_player(const char* name) {
|
|
||||||
// check for id
|
|
||||||
for (s32 i = 0; i < MAX_PLAYERS; i++) {
|
|
||||||
if (!gNetworkPlayers[i].connected) { continue; }
|
|
||||||
char id[16] = { 0 };
|
|
||||||
if (snprintf(id, 16, "%d", i) < 0) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
if (strcmp(id, name) == 0) {
|
|
||||||
return &gNetworkPlayers[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for name
|
|
||||||
for (s32 i = 0; i < MAX_PLAYERS; i++) {
|
|
||||||
if (!gNetworkPlayers[i].connected) { continue; }
|
|
||||||
if (strcmp(gNetworkPlayers[i].name, name) == 0) {
|
|
||||||
return &gNetworkPlayers[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void chat_construct_player_message(struct NetworkPlayer* np, char* msg) {
|
|
||||||
char built[256] = { 0 };
|
|
||||||
snprintf(built, 256, "\\#fff982\\");
|
|
||||||
|
|
||||||
char player[128] = { 0 };
|
|
||||||
snprintf(player, 128, "%s%s\\#fff982\\", network_get_player_text_color_string(np->localIndex), np->name);
|
|
||||||
djui_language_replace(msg, &built[9], 256 - 9, '@', player);
|
|
||||||
djui_chat_message_create(built);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool exec_chat_command(char* command) {
|
|
||||||
struct NetworkPlayer* npl = &gNetworkPlayers[0];
|
|
||||||
enum ChatConfirmCommand ccc = sConfirming;
|
|
||||||
sConfirming = CCC_NONE;
|
|
||||||
|
|
||||||
if (ccc != CCC_NONE && strcmp("/confirm", command) == 0) {
|
|
||||||
struct NetworkPlayer* np = &gNetworkPlayers[sConfirmPlayerIndex];
|
|
||||||
if (!np->connected) return true;
|
|
||||||
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_player_disconnected(np->localIndex);
|
|
||||||
} else {
|
|
||||||
network_send_chat_command(np->globalIndex, CCC_KICK);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (gNetworkType == NT_SERVER || npl->moderator) {
|
|
||||||
if (ccc == CCC_BAN) {
|
|
||||||
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);
|
|
||||||
network_player_disconnected(np->localIndex);
|
|
||||||
} else {
|
|
||||||
network_send_chat_command(np->globalIndex, CCC_BAN);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
network_player_disconnected(np->localIndex);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (gNetworkType == NT_SERVER && ccc == CCC_MODERATOR) {
|
|
||||||
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);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp("/players", command) == 0) {
|
|
||||||
char line[128] = { 0 };
|
|
||||||
snprintf(line, 127, "\\#fff982\\%s:\n", DLANG(CHAT, PLAYERS));
|
|
||||||
djui_chat_message_create(line);
|
|
||||||
for (s32 i = 0; i < MAX_PLAYERS; i++) {
|
|
||||||
struct NetworkPlayer* np = &gNetworkPlayers[i];
|
|
||||||
if (!np->connected) { continue; }
|
|
||||||
if (gNetworkSystem == &gNetworkSystemSocket) {
|
|
||||||
snprintf(line, 127, "\\#82f9ff\\%u\\#fff982\\ - %s%s\n", np->globalIndex, network_get_player_text_color_string(np->localIndex), np->name);
|
|
||||||
} else {
|
|
||||||
snprintf(line, 127, "\\#82f9ff\\%u\\#fff982\\ - \\#82f9ff\\%s\\#fff982\\ - %s%s\n", np->globalIndex, gNetworkSystem->get_id_str(np->localIndex), network_get_player_text_color_string(np->localIndex), np->name);
|
|
||||||
}
|
|
||||||
djui_chat_message_create(line);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp("/kick", command) == 0) {
|
|
||||||
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));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NetworkPlayer* np = chat_get_network_player(&command[6]);
|
|
||||||
if (np == NULL) {
|
|
||||||
djui_chat_message_create(DLANG(CHAT, PLAYER_NOT_FOUND));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (np->localIndex == 0) {
|
|
||||||
djui_chat_message_create(DLANG(CHAT, SELF_KICK));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
chat_construct_player_message(np, DLANG(CHAT, KICK_CONFIRM));
|
|
||||||
sConfirming = CCC_KICK;
|
|
||||||
sConfirmPlayerIndex = np->localIndex;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp("/ban", command) == 0) {
|
|
||||||
djui_chat_message_create(DLANG(CHAT, PLAYER_NOT_FOUND));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str_starts_with(command, "/ban ")) {
|
|
||||||
if (gNetworkType != NT_SERVER && !npl->moderator) {
|
|
||||||
djui_chat_message_create(DLANG(CHAT, NO_PERMS));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NetworkPlayer* np = chat_get_network_player(&command[5]);
|
|
||||||
if (np == NULL) {
|
|
||||||
djui_chat_message_create(DLANG(CHAT, PLAYER_NOT_FOUND));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (np->localIndex == 0) {
|
|
||||||
djui_chat_message_create(DLANG(CHAT, SELF_BAN));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
chat_construct_player_message(np, DLANG(CHAT, BAN_CONFIRM));
|
|
||||||
sConfirming = CCC_BAN;
|
|
||||||
sConfirmPlayerIndex = np->localIndex;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp("/permban", command) == 0) {
|
|
||||||
djui_chat_message_create(DLANG(CHAT, PLAYER_NOT_FOUND));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str_starts_with(command, "/permban ")) {
|
|
||||||
if (gNetworkType != NT_SERVER && !npl->moderator) {
|
|
||||||
djui_chat_message_create(DLANG(CHAT, NO_PERMS));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NetworkPlayer* np = chat_get_network_player(&command[9]);
|
|
||||||
if (np == NULL) {
|
|
||||||
djui_chat_message_create(DLANG(CHAT, PLAYER_NOT_FOUND));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (np->localIndex == 0) {
|
|
||||||
djui_chat_message_create(DLANG(CHAT, SELF_BAN));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
chat_construct_player_message(np, DLANG(CHAT, PERM_BAN_CONFIRM));
|
|
||||||
sConfirming = CCC_PERMBAN;
|
|
||||||
sConfirmPlayerIndex = np->localIndex;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp("/moderator", command) == 0) {
|
|
||||||
djui_chat_message_create(DLANG(CHAT, PLAYER_NOT_FOUND));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str_starts_with(command, "/moderator ")) {
|
|
||||||
if (gNetworkType != NT_SERVER) {
|
|
||||||
djui_chat_message_create(DLANG(CHAT, SERVER_ONLY));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NetworkPlayer* np = chat_get_network_player(&command[11]);
|
|
||||||
if (np == NULL) {
|
|
||||||
djui_chat_message_create(DLANG(CHAT, PLAYER_NOT_FOUND));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (np->localIndex == 0) {
|
|
||||||
djui_chat_message_create(DLANG(CHAT, SELF_MOD));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
chat_construct_player_message(np, DLANG(CHAT, MOD_CONFIRM));
|
|
||||||
sConfirming = CCC_MODERATOR;
|
|
||||||
sConfirmPlayerIndex = np->localIndex;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gServerSettings.nametags) {
|
|
||||||
if (strcmp("/nametags", command) == 0) {
|
|
||||||
djui_chat_message_create(DLANG(CHAT, NAMETAGS_MISSING_PARAMETERS));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str_starts_with(command, "/nametags ")) {
|
|
||||||
char *option = &command[10];
|
|
||||||
if (strcmp("show-tag", option) == 0) {
|
|
||||||
gNametagsSettings.showSelfTag = !gNametagsSettings.showSelfTag;
|
|
||||||
} else if (strcmp("show-health", option) == 0) {
|
|
||||||
gNametagsSettings.showHealth = !gNametagsSettings.showHealth;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEVELOPMENT
|
|
||||||
if (exec_dev_chat_command(command)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return smlua_call_chat_command_hook(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
void display_chat_commands(void) {
|
|
||||||
djui_chat_message_create(DLANG(CHAT, PLAYERS_DESC));
|
|
||||||
if (gNetworkType == NT_SERVER || gNetworkPlayers[0].moderator) {
|
|
||||||
djui_chat_message_create(DLANG(CHAT, KICK_DESC));
|
|
||||||
djui_chat_message_create(DLANG(CHAT, BAN_DESC));
|
|
||||||
|
|
||||||
if (gNetworkType == NT_SERVER) {
|
|
||||||
djui_chat_message_create(DLANG(CHAT, PERM_BAN_DESC));
|
|
||||||
djui_chat_message_create(DLANG(CHAT, MOD_DESC));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (gServerSettings.nametags) {
|
|
||||||
djui_chat_message_create(DLANG(CHAT, NAMETAGS_DESC));
|
|
||||||
}
|
|
||||||
#ifdef DEVELOPMENT
|
|
||||||
dev_display_chat_commands();
|
|
||||||
#endif
|
|
||||||
if (sConfirming != CCC_NONE) { djui_chat_message_create("/confirm"); }
|
|
||||||
smlua_display_chat_commands();
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
#ifndef CHAT_COMMANDS_H
|
|
||||||
#define CHAT_COMMANDS_H
|
|
||||||
|
|
||||||
bool exec_chat_command(char* command);
|
|
||||||
void display_chat_commands(void);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include "pc_main.h"
|
#include "pc_main.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
|
#include "debuglog.h"
|
||||||
|
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -13,28 +14,28 @@
|
||||||
struct CLIOptions gCLIOpts;
|
struct CLIOptions gCLIOpts;
|
||||||
|
|
||||||
static void print_help(void) {
|
static void print_help(void) {
|
||||||
printf("sm64coopdx\n");
|
log_to_terminal("sm64coopdx\n");
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
printf("--console Enables the Windows console.\n");
|
log_to_terminal("--console Enables the Windows console.\n");
|
||||||
#endif
|
#endif
|
||||||
printf("--savepath SAVEPATH Overrides the default save/config path ('!' expands to executable path).\n");
|
log_to_terminal("--savepath SAVEPATH Overrides the default save/config path ('!' expands to executable path).\n");
|
||||||
printf("--configfile CONFIGNAME Saves the configuration file as CONFIGNAME.\n");
|
log_to_terminal("--configfile CONFIGNAME Saves the configuration file as CONFIGNAME.\n");
|
||||||
printf("--hide-loading-screen Hides the loading screen before the menu boots up.\n");
|
log_to_terminal("--hide-loading-screen Hides the loading screen before the menu boots up.\n");
|
||||||
printf("--fullscreen Starts the game in full screen mode.\n");
|
log_to_terminal("--fullscreen Starts the game in full screen mode.\n");
|
||||||
printf("--windowed Starts the game in windowed mode.\n");
|
log_to_terminal("--windowed Starts the game in windowed mode.\n");
|
||||||
printf("--width WIDTH Sets the window width.\n");
|
log_to_terminal("--width WIDTH Sets the window width.\n");
|
||||||
printf("--height HEIGHT Sets the window height.\n");
|
log_to_terminal("--height HEIGHT Sets the window height.\n");
|
||||||
printf("--skip-intro Skips the Peach and Lakitu intros when on a zero star save.\n");
|
log_to_terminal("--skip-intro Skips the Peach and Lakitu intros when on a zero star save.\n");
|
||||||
printf("--server PORT Starts the game and creates a new server on PORT.\n");
|
log_to_terminal("--server PORT Starts the game and creates a new server on PORT.\n");
|
||||||
printf("--client IP PORT Starts the game and joins an existing server.\n");
|
log_to_terminal("--client IP PORT Starts the game and joins an existing server.\n");
|
||||||
printf("--coopnet PASSWORD Starts the game and creates a new CoopNet server.\n");
|
log_to_terminal("--coopnet PASSWORD Starts the game and creates a new CoopNet server.\n");
|
||||||
printf("--playername PLAYERNAME Starts the game with a specific playername.\n");
|
log_to_terminal("--playername PLAYERNAME Starts the game with a specific playername.\n");
|
||||||
printf("--playercount PLAYERCOUNT Starts the game with a specific player count limit.\n");
|
log_to_terminal("--playercount PLAYERCOUNT Starts the game with a specific player count limit.\n");
|
||||||
printf("--skip-update-check Skips the update check when loading the game.\n");
|
log_to_terminal("--skip-update-check Skips the update check when loading the game.\n");
|
||||||
printf("--no-discord Disables discord integration.\n");
|
log_to_terminal("--no-discord Disables discord integration.\n");
|
||||||
printf("--disable-mods Disables all mods that are already enabled.\n");
|
log_to_terminal("--disable-mods Disables all mods that are already enabled.\n");
|
||||||
printf("--enable-mod MODNAME Enables a mod.\n");
|
log_to_terminal("--enable-mod MODNAME Enables a mod.\n");
|
||||||
printf("--headless Enable Headless mode.");
|
log_to_terminal("--headless Enable Headless mode.");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int arg_string(const char *name, const char *value, char *target, int maxLength) {
|
static inline int arg_string(const char *name, const char *value, char *target, int maxLength) {
|
||||||
|
|
|
||||||
483
src/pc/commands.c
Normal file
483
src/pc/commands.c
Normal file
|
|
@ -0,0 +1,483 @@
|
||||||
|
#include "pc/network/network.h"
|
||||||
|
#include "pc/network/socket/socket.h"
|
||||||
|
#include "pc/lua/smlua_hooks.h"
|
||||||
|
#include "pc/djui/djui_language.h"
|
||||||
|
#include "pc/djui/djui_chat_message.h"
|
||||||
|
#include "pc/djui/djui_console.h"
|
||||||
|
#include "commands.h"
|
||||||
|
#include "pc/network/ban_list.h"
|
||||||
|
#include "pc/network/moderator_list.h"
|
||||||
|
#include "pc/debuglog.h"
|
||||||
|
#include "pc/lua/utils/smlua_level_utils.h"
|
||||||
|
#include "pc/mods/mods_utils.h"
|
||||||
|
#include "pc/pc_main.h"
|
||||||
|
#include "level_table.h"
|
||||||
|
#ifdef DEVELOPMENT
|
||||||
|
#include "pc/dev/chat.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool command_help(UNUSED const char* message);
|
||||||
|
static bool command_players(UNUSED const char* message);
|
||||||
|
static bool command_kick(const char* message);
|
||||||
|
static bool command_ban(const char* message);
|
||||||
|
static bool command_permaban(const char* message);
|
||||||
|
static bool command_mod(const char* message);
|
||||||
|
static bool command_confirm(UNUSED const char* message);
|
||||||
|
static bool command_nametags(const char* message);
|
||||||
|
static bool command_clear(UNUSED const char* message);
|
||||||
|
static bool command_quit(UNUSED const char* message);
|
||||||
|
static bool command_host(UNUSED const char* message);
|
||||||
|
static bool command_rehost(UNUSED const char* message);
|
||||||
|
static bool command_stop_hosting(UNUSED const char* message);
|
||||||
|
static bool command_disconnect(UNUSED const char* message);
|
||||||
|
|
||||||
|
static struct Command sCommands[] = {
|
||||||
|
{
|
||||||
|
.command = "players",
|
||||||
|
.description = "PLAYERS_DESC",
|
||||||
|
.action = command_players,
|
||||||
|
.active = true,
|
||||||
|
.isChatCommand = true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.command = "kick",
|
||||||
|
.description = "KICK_DESC",
|
||||||
|
.action = command_kick,
|
||||||
|
.active = true,
|
||||||
|
.isChatCommand = true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.command = "ban",
|
||||||
|
.description = "BAN_DESC",
|
||||||
|
.action = command_ban,
|
||||||
|
.active = true,
|
||||||
|
.isChatCommand = true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.command = "permaban",
|
||||||
|
.description = "PERM_BAN_DESC",
|
||||||
|
.action = command_permaban,
|
||||||
|
.active = true,
|
||||||
|
.isChatCommand = true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.command = "moderator",
|
||||||
|
.description = "MOD_DESC",
|
||||||
|
.action = command_mod,
|
||||||
|
.active = true,
|
||||||
|
.isChatCommand = true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.command = "confirm",
|
||||||
|
.description = "",
|
||||||
|
.action = command_confirm,
|
||||||
|
.active = false,
|
||||||
|
.isChatCommand = true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.command = "nametags",
|
||||||
|
.description = "NAMETAGS_DESC",
|
||||||
|
.action = command_nametags,
|
||||||
|
.active = false,
|
||||||
|
.isChatCommand = true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.command = "clear",
|
||||||
|
.description = "/clear - Clears the current console's text",
|
||||||
|
.action = command_clear,
|
||||||
|
.active = true,
|
||||||
|
.isChatCommand = false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.command = "quit",
|
||||||
|
.description = "/quit - Quits the game",
|
||||||
|
.action = command_quit,
|
||||||
|
.active = true,
|
||||||
|
.isChatCommand = false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.command = "host",
|
||||||
|
.description = "/host - Hosts a new game using your saved server settings and mod list",
|
||||||
|
.action = command_host,
|
||||||
|
.active = true,
|
||||||
|
.isChatCommand = false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.command = "rehost",
|
||||||
|
.description = "/rehost - Rehosts a currently active game",
|
||||||
|
.action = command_rehost,
|
||||||
|
.active = false,
|
||||||
|
.isChatCommand = false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.command = "stop-hosting",
|
||||||
|
.description = "/stop-hosting - Stop hosting a currently active game",
|
||||||
|
.action = command_stop_hosting,
|
||||||
|
.active = false,
|
||||||
|
.isChatCommand = false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.command = "disconnect",
|
||||||
|
.description = "/disconnect - Disconnects from a currently active game",
|
||||||
|
.action = command_disconnect,
|
||||||
|
.active = false,
|
||||||
|
.isChatCommand = false
|
||||||
|
},
|
||||||
|
};
|
||||||
|
static unsigned int sCommandCount = sizeof(sCommands) / sizeof(struct Command);
|
||||||
|
static enum ChatConfirmCommand sConfirming = CCC_NONE;
|
||||||
|
static u8 sConfirmPlayerIndex = 0;
|
||||||
|
|
||||||
|
static struct NetworkPlayer* chat_get_network_player(const char* name) {
|
||||||
|
// check for id
|
||||||
|
for (s32 i = 0; i < MAX_PLAYERS; i++) {
|
||||||
|
if (!gNetworkPlayers[i].connected) { continue; }
|
||||||
|
char id[16] = { 0 };
|
||||||
|
if (snprintf(id, 16, "%d", i) < 0) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
if (strcmp(id, name) == 0) {
|
||||||
|
return &gNetworkPlayers[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for name
|
||||||
|
for (s32 i = 0; i < MAX_PLAYERS; i++) {
|
||||||
|
if (!gNetworkPlayers[i].connected) { continue; }
|
||||||
|
if (strcmp(gNetworkPlayers[i].name, name) == 0) {
|
||||||
|
return &gNetworkPlayers[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void chat_construct_player_message(struct NetworkPlayer* np, char* msg) {
|
||||||
|
char built[256] = { 0 };
|
||||||
|
snprintf(built, 256, "\\#fff982\\");
|
||||||
|
|
||||||
|
char player[128] = { 0 };
|
||||||
|
snprintf(player, 128, "%s%s\\#fff982\\", network_get_player_text_color_string(np->localIndex), np->name);
|
||||||
|
djui_language_replace(msg, &built[9], 256 - 9, '@', player);
|
||||||
|
command_message_create(built, CONSOLE_MESSAGE_INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool command_help(UNUSED const char* message) {
|
||||||
|
for (unsigned int i = 0; i < sCommandCount; i++) {
|
||||||
|
if (!sCommands[i].active) continue;
|
||||||
|
if (!sCommands[i].isChatCommand && gDjuiChatBoxFocus) continue;
|
||||||
|
command_message_create(djui_language_get("CHAT", sCommands[i].description), CONSOLE_MESSAGE_INFO);
|
||||||
|
}
|
||||||
|
#ifdef DEVELOPMENT
|
||||||
|
dev_display_chat_commands();
|
||||||
|
#endif
|
||||||
|
smlua_display_chat_commands(gDjuiConsoleFocus);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool command_players(UNUSED const char* message) {
|
||||||
|
char line[128] = { 0 };
|
||||||
|
snprintf(line, 127, "\\#fff982\\%s:\n", DLANG(CHAT, PLAYERS));
|
||||||
|
command_message_create(line, CONSOLE_MESSAGE_INFO);
|
||||||
|
for (s32 i = 0; i < MAX_PLAYERS; i++) {
|
||||||
|
struct NetworkPlayer* np = &gNetworkPlayers[i];
|
||||||
|
if (!np->connected) { continue; }
|
||||||
|
if (gNetworkSystem == &gNetworkSystemSocket) {
|
||||||
|
snprintf(line, 127, "\\#82f9ff\\%u\\#fff982\\ - %s%s\n", np->globalIndex, network_get_player_text_color_string(np->localIndex), np->name);
|
||||||
|
} else {
|
||||||
|
snprintf(line, 127, "\\#82f9ff\\%u\\#fff982\\ - \\#82f9ff\\%s\\#fff982\\ - %s%s\n", np->globalIndex, gNetworkSystem->get_id_str(np->localIndex), network_get_player_text_color_string(np->localIndex), np->name);
|
||||||
|
}
|
||||||
|
command_message_create(line, CONSOLE_MESSAGE_INFO);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool command_kick(const char* message) {
|
||||||
|
struct NetworkPlayer* npl = &gNetworkPlayers[0];
|
||||||
|
if (gNetworkType != NT_SERVER && !npl->moderator) {
|
||||||
|
command_message_create(DLANG(CHAT, NO_PERMS), CONSOLE_MESSAGE_ERROR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NetworkPlayer* np = chat_get_network_player(message);
|
||||||
|
if (np == NULL) {
|
||||||
|
command_message_create(DLANG(CHAT, PLAYER_NOT_FOUND), CONSOLE_MESSAGE_ERROR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (np->localIndex == 0) {
|
||||||
|
command_message_create(DLANG(CHAT, SELF_KICK), CONSOLE_MESSAGE_ERROR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
chat_construct_player_message(np, DLANG(CHAT, KICK_CONFIRM));
|
||||||
|
sConfirming = CCC_KICK;
|
||||||
|
sConfirmPlayerIndex = np->localIndex;
|
||||||
|
struct Command* confirmCommand = get_command("confirm");
|
||||||
|
if (confirmCommand) confirmCommand->active = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool command_ban(const char* message) {
|
||||||
|
struct NetworkPlayer* npl = &gNetworkPlayers[0];
|
||||||
|
if (gNetworkType != NT_SERVER && !npl->moderator) {
|
||||||
|
command_message_create(DLANG(CHAT, NO_PERMS), CONSOLE_MESSAGE_ERROR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NetworkPlayer* np = chat_get_network_player(message);
|
||||||
|
if (np == NULL) {
|
||||||
|
command_message_create(DLANG(CHAT, PLAYER_NOT_FOUND), CONSOLE_MESSAGE_ERROR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (np->localIndex == 0) {
|
||||||
|
command_message_create(DLANG(CHAT, SELF_BAN), CONSOLE_MESSAGE_ERROR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
chat_construct_player_message(np, DLANG(CHAT, BAN_CONFIRM));
|
||||||
|
sConfirming = CCC_BAN;
|
||||||
|
sConfirmPlayerIndex = np->localIndex;
|
||||||
|
struct Command* confirmCommand = get_command("confirm");
|
||||||
|
if (confirmCommand) confirmCommand->active = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool command_permaban(const char* message) {
|
||||||
|
struct NetworkPlayer* npl = &gNetworkPlayers[0];
|
||||||
|
if (gNetworkType != NT_SERVER && !npl->moderator) {
|
||||||
|
command_message_create(DLANG(CHAT, NO_PERMS), CONSOLE_MESSAGE_ERROR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NetworkPlayer* np = chat_get_network_player(message);
|
||||||
|
if (np == NULL) {
|
||||||
|
command_message_create(DLANG(CHAT, PLAYER_NOT_FOUND), CONSOLE_MESSAGE_ERROR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (np->localIndex == 0) {
|
||||||
|
command_message_create(DLANG(CHAT, SELF_BAN), CONSOLE_MESSAGE_ERROR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
chat_construct_player_message(np, DLANG(CHAT, PERM_BAN_CONFIRM));
|
||||||
|
sConfirming = CCC_PERMBAN;
|
||||||
|
sConfirmPlayerIndex = np->localIndex;
|
||||||
|
struct Command* confirmCommand = get_command("confirm");
|
||||||
|
if (confirmCommand) confirmCommand->active = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool command_mod(const char* message) {
|
||||||
|
if (gNetworkType != NT_SERVER) {
|
||||||
|
command_message_create(DLANG(CHAT, SERVER_ONLY), CONSOLE_MESSAGE_ERROR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NetworkPlayer* np = chat_get_network_player(message);
|
||||||
|
if (np == NULL) {
|
||||||
|
command_message_create(DLANG(CHAT, PLAYER_NOT_FOUND), CONSOLE_MESSAGE_ERROR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (np->localIndex == 0) {
|
||||||
|
command_message_create(DLANG(CHAT, SELF_MOD), CONSOLE_MESSAGE_ERROR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
chat_construct_player_message(np, DLANG(CHAT, MOD_CONFIRM));
|
||||||
|
sConfirming = CCC_MODERATOR;
|
||||||
|
sConfirmPlayerIndex = np->localIndex;
|
||||||
|
struct Command* confirmCommand = get_command("confirm");
|
||||||
|
if (confirmCommand) confirmCommand->active = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool command_confirm(UNUSED const char* message) {
|
||||||
|
// deactivate command
|
||||||
|
struct Command* confirmCommand = get_command("confirm");
|
||||||
|
if (confirmCommand) confirmCommand->active = false;
|
||||||
|
|
||||||
|
enum ChatConfirmCommand ccc = sConfirming;
|
||||||
|
sConfirming = CCC_NONE;
|
||||||
|
|
||||||
|
struct NetworkPlayer* npl = &gNetworkPlayers[0];
|
||||||
|
struct NetworkPlayer* np = &gNetworkPlayers[sConfirmPlayerIndex];
|
||||||
|
if (!np->connected) return true;
|
||||||
|
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_player_disconnected(np->localIndex);
|
||||||
|
} else {
|
||||||
|
network_send_chat_command(np->globalIndex, CCC_KICK);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (gNetworkType == NT_SERVER || npl->moderator) {
|
||||||
|
if (ccc == CCC_BAN) {
|
||||||
|
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);
|
||||||
|
network_player_disconnected(np->localIndex);
|
||||||
|
} else {
|
||||||
|
network_send_chat_command(np->globalIndex, CCC_BAN);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
network_player_disconnected(np->localIndex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (gNetworkType == NT_SERVER && ccc == CCC_MODERATOR) {
|
||||||
|
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);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool command_nametags(const char* message) {
|
||||||
|
if (strcmp("show-tag", message) == 0) {
|
||||||
|
gNametagsSettings.showSelfTag = !gNametagsSettings.showSelfTag;
|
||||||
|
} else if (strcmp("show-health", message) == 0) {
|
||||||
|
gNametagsSettings.showHealth = !gNametagsSettings.showHealth;
|
||||||
|
}
|
||||||
|
command_message_create(DLANG(CHAT, NAMETAGS_MISSING_PARAMETERS), CONSOLE_MESSAGE_ERROR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool command_clear(UNUSED const char* message) {
|
||||||
|
djui_console_clear();
|
||||||
|
terminal_clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool command_quit(UNUSED const char* message) {
|
||||||
|
game_exit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void djui_panel_do_host(bool reconnecting, bool playSound);
|
||||||
|
static bool command_host(UNUSED const char* message) {
|
||||||
|
djui_panel_do_host(false, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool command_rehost(UNUSED const char* message) {
|
||||||
|
network_rehost_begin();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool command_stop_hosting(UNUSED const char* message) {
|
||||||
|
network_reset_reconnect_and_rehost();
|
||||||
|
network_shutdown(true, false, false, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool command_disconnect(UNUSED const char* message) {
|
||||||
|
network_reset_reconnect_and_rehost();
|
||||||
|
network_shutdown(true, false, false, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_command_active(const char* name, bool active) {
|
||||||
|
struct Command* command = get_command(name);
|
||||||
|
if (command) command->active = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Command* get_command(const char* name) {
|
||||||
|
for (unsigned int i = 0; i < sCommandCount; i++) {
|
||||||
|
if (strcmp(sCommands[i].command, name) == 0) {
|
||||||
|
return &sCommands[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void command_message_create(const char* message, OPTIONAL enum ConsoleMessageLevel level) {
|
||||||
|
if (gDjuiChatBoxFocus) {
|
||||||
|
size_t newMsgLength = strlen(message) + 12;
|
||||||
|
char newMsg[newMsgLength];
|
||||||
|
switch (level) {
|
||||||
|
case CONSOLE_MESSAGE_INFO:
|
||||||
|
snprintf(newMsg, newMsgLength, "\\#dcdcdc\\%s", message);
|
||||||
|
break;
|
||||||
|
case CONSOLE_MESSAGE_WARNING:
|
||||||
|
snprintf(newMsg, newMsgLength, "\\#ffffa0\\%s", message);
|
||||||
|
break;
|
||||||
|
case CONSOLE_MESSAGE_ERROR:
|
||||||
|
snprintf(newMsg, newMsgLength, "\\#ffa0a0\\%s", message);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
snprintf(newMsg, newMsgLength, "\\#dcdcdc\\%s", message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
djui_chat_message_create(newMsg);
|
||||||
|
} else {
|
||||||
|
djui_console_message_create(message, level);
|
||||||
|
char* colorCode;
|
||||||
|
switch (level) {
|
||||||
|
case CONSOLE_MESSAGE_WARNING: colorCode = "\x1b[33m"; break;
|
||||||
|
case CONSOLE_MESSAGE_ERROR: colorCode = "\x1b[31m"; break;
|
||||||
|
default: colorCode = "\x1b[0m"; break;
|
||||||
|
}
|
||||||
|
log_to_terminal("%s%s\x1b[0m\n", colorCode, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_command(char* command) {
|
||||||
|
// directly set active state of certain commands
|
||||||
|
set_command_active("nametags", gServerSettings.nametags);
|
||||||
|
set_command_active("host", gDjuiInMainMenu);
|
||||||
|
set_command_active("rehost", gNetworkType == NT_SERVER && !gDjuiInMainMenu);
|
||||||
|
set_command_active("stop-hosting", gNetworkType == NT_SERVER && !gDjuiInMainMenu);
|
||||||
|
set_command_active("disconnect", gNetworkType == NT_CLIENT && !gDjuiInMainMenu);
|
||||||
|
|
||||||
|
// directly check help command
|
||||||
|
if (strcmp(command, "help") == 0 || strcmp(command, "?") == 0 || strcmp(command, "") == 0) {
|
||||||
|
command_help(NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// loop through builtin commands first
|
||||||
|
for (unsigned int i = 0; i < sCommandCount; i++) {
|
||||||
|
// sanity checks
|
||||||
|
if (sCommands[i].command[0] == '\0') continue;
|
||||||
|
if (!sCommands[i].action) continue;
|
||||||
|
if (!sCommands[i].active) continue;
|
||||||
|
if (!sCommands[i].isChatCommand && gDjuiChatBoxFocus) continue;
|
||||||
|
|
||||||
|
// compare strings
|
||||||
|
size_t commandLength = strlen(sCommands[i].command);
|
||||||
|
if (!str_starts_with(command, sCommands[i].command)) continue;
|
||||||
|
if (command[commandLength] != '\0' && command[commandLength] != ' ') continue;
|
||||||
|
|
||||||
|
// get args
|
||||||
|
char* arguments = command + commandLength;
|
||||||
|
if (*arguments != '\0') arguments++;
|
||||||
|
|
||||||
|
// run action
|
||||||
|
if (sCommands[i].action(arguments)) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEVELOPMENT
|
||||||
|
// check development commands
|
||||||
|
if (exec_dev_chat_command(command)) return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// check lua commands
|
||||||
|
if (smlua_call_chat_command_hook(command)) return;
|
||||||
|
|
||||||
|
// no command exists, alert the user
|
||||||
|
char extendedUnknownCommandMessage[MAX_CONSOLE_INPUT_LENGTH];
|
||||||
|
snprintf(extendedUnknownCommandMessage, sizeof(extendedUnknownCommandMessage), "%s (/help)", DLANG(CHAT, UNRECOGNIZED));
|
||||||
|
command_message_create(extendedUnknownCommandMessage, CONSOLE_MESSAGE_INFO);
|
||||||
|
}
|
||||||
17
src/pc/commands.h
Normal file
17
src/pc/commands.h
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define MAX_COMMAND_LEN 128
|
||||||
|
// only applies to builtin commands
|
||||||
|
#define MAX_COMMAND_DESC_LEN 512
|
||||||
|
|
||||||
|
struct Command {
|
||||||
|
char command[MAX_COMMAND_LEN];
|
||||||
|
char description[MAX_COMMAND_DESC_LEN];
|
||||||
|
bool (*action)(const char*);
|
||||||
|
bool active;
|
||||||
|
bool isChatCommand;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Command* get_command(const char* name);
|
||||||
|
void run_command(char* command);
|
||||||
|
void command_message_create(const char* message, OPTIONAL enum ConsoleMessageLevel level);
|
||||||
|
|
@ -877,7 +877,7 @@ void configfile_save(const char *filename) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Saving configuration to '%s'\n", filename);
|
LOG_INFO("Saving configuration to '%s'\n", filename);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < ARRAY_LEN(options); i++) {
|
for (unsigned int i = 0; i < ARRAY_LEN(options); i++) {
|
||||||
const struct ConfigOption *option = &options[i];
|
const struct ConfigOption *option = &options[i];
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,11 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "pc/network/network.h"
|
#include "pc/network/network.h"
|
||||||
#include "pc/djui/djui_console.h"
|
#include "pc/djui/djui_console.h"
|
||||||
|
#include "pc/terminal.h"
|
||||||
|
|
||||||
static void _debuglog_print_timestamp(void) {
|
#define MAX_LOG_SIZE 8192
|
||||||
|
|
||||||
|
static int _debuglog_print_timestamp(char* buffer, size_t bufferSize) {
|
||||||
time_t ltime = time(NULL);
|
time_t ltime = time(NULL);
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
char* str = asctime(localtime(<ime));
|
char* str = asctime(localtime(<ime));
|
||||||
|
|
@ -15,32 +18,60 @@ static void _debuglog_print_timestamp(void) {
|
||||||
localtime_r(<ime, <ime2);
|
localtime_r(<ime, <ime2);
|
||||||
char* str = asctime(<ime2);
|
char* str = asctime(<ime2);
|
||||||
#endif
|
#endif
|
||||||
printf("%.*s", (int)strlen(str) - 1, str);
|
return snprintf(buffer, bufferSize, "%.*s", (int)strlen(str) - 1, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _debuglog_print_network_type(void) {
|
static int _debuglog_print_network_type(char* buffer, size_t bufferSize) {
|
||||||
printf(" [%02d] ", (gNetworkPlayerLocal != NULL) ? gNetworkPlayerLocal->globalIndex : -1);
|
return snprintf(buffer, bufferSize, " [%02d] ", (gNetworkPlayerLocal != NULL) ? gNetworkPlayerLocal->globalIndex : -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _debuglog_print_log_type(const char* logType) {
|
static int _debuglog_print_log_type(const char* logType, char* buffer, size_t bufferSize) {
|
||||||
printf("[%s] ", logType);
|
return snprintf(buffer, bufferSize, "[%s] ", logType);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _debuglog_print_short_filename(const char* filename) {
|
static int _debuglog_print_short_filename(const char* filename, char* buffer, size_t bufferSize) {
|
||||||
const char* last = strrchr(filename, '/');
|
const char* last = strrchr(filename, '/');
|
||||||
if (last != NULL) {
|
if (last != NULL) {
|
||||||
printf("%s: ", last + 1);
|
return snprintf(buffer, bufferSize, "%s: ", last + 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("???: ");
|
return snprintf(buffer, bufferSize, "???: ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _debuglog_print_log(const char* logType, char* filename) {
|
static inline void _debuglog_print_log(const char* logType, const char* filename, const char* fmt, ...) {
|
||||||
_debuglog_print_timestamp();
|
char log[MAX_LOG_SIZE];
|
||||||
_debuglog_print_network_type();
|
size_t capacity = MAX_LOG_SIZE;
|
||||||
_debuglog_print_log_type(logType);
|
char* buffer = log;
|
||||||
_debuglog_print_short_filename(filename);
|
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = _debuglog_print_timestamp(buffer, capacity);
|
||||||
|
if (len < 0 || (size_t)len >= capacity) return;
|
||||||
|
buffer += len; capacity -= len;
|
||||||
|
|
||||||
|
len = _debuglog_print_network_type(buffer, capacity);
|
||||||
|
if (len < 0 || (size_t)len >= capacity) return;
|
||||||
|
buffer += len; capacity -= len;
|
||||||
|
|
||||||
|
len = _debuglog_print_log_type(logType, buffer, capacity);
|
||||||
|
if (len < 0 || (size_t)len >= capacity) return;
|
||||||
|
buffer += len; capacity -= len;
|
||||||
|
|
||||||
|
len = _debuglog_print_short_filename(filename, buffer, capacity);
|
||||||
|
if (len < 0 || (size_t)len >= capacity) return;
|
||||||
|
buffer += len; capacity -= len;
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
|
||||||
|
len = vsnprintf(buffer, capacity, fmt, args);
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
if (len < 0) return;
|
||||||
|
|
||||||
|
log_to_terminal("%s\n", log);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(DISABLE_MODULE_LOG)
|
#if defined(DISABLE_MODULE_LOG)
|
||||||
|
|
@ -48,9 +79,9 @@ static void _debuglog_print_log(const char* logType, char* filename) {
|
||||||
#define LOG_INFO(...)
|
#define LOG_INFO(...)
|
||||||
#define LOG_ERROR(...)
|
#define LOG_ERROR(...)
|
||||||
#else
|
#else
|
||||||
#define LOG_DEBUG(...) (configDebugPrint ? ( _debuglog_print_log("DEBUG", __FILE__), printf(__VA_ARGS__), printf("\n") ) : 0)
|
#define LOG_DEBUG(...) (configDebugPrint ? ( _debuglog_print_log("DEBUG", __FILE__, __VA_ARGS__) ) : 0)
|
||||||
#define LOG_INFO(...) ((configDebugInfo || gCLIOpts.headless) ? ( _debuglog_print_log("INFO", __FILE__), printf(__VA_ARGS__), printf("\n") ) : 0)
|
#define LOG_INFO(...) ((configDebugInfo || gCLIOpts.headless) ? ( _debuglog_print_log("INFO", __FILE__, __VA_ARGS__) ) : 0)
|
||||||
#define LOG_ERROR(...) (configDebugError ? ( _debuglog_print_log("ERROR", __FILE__), printf(__VA_ARGS__), printf("\n") ) : 0)
|
#define LOG_ERROR(...) (configDebugError ? ( _debuglog_print_log("ERROR", __FILE__, __VA_ARGS__) ) : 0)
|
||||||
#endif
|
#endif
|
||||||
#define LOG_CONSOLE(...) { snprintf(gDjuiConsoleTmpBuffer, CONSOLE_MAX_TMP_BUFFER, __VA_ARGS__), djui_console_message_create(gDjuiConsoleTmpBuffer, CONSOLE_MESSAGE_INFO); }
|
#define LOG_CONSOLE(...) { snprintf(gDjuiConsoleTmpBuffer, CONSOLE_MAX_TMP_BUFFER, __VA_ARGS__), djui_console_message_create(gDjuiConsoleTmpBuffer, CONSOLE_MESSAGE_INFO); }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
#include "pc/lua/smlua_hooks.h"
|
#include "pc/lua/smlua_hooks.h"
|
||||||
#include "pc/djui/djui_language.h"
|
#include "pc/djui/djui_language.h"
|
||||||
#include "pc/djui/djui_chat_message.h"
|
#include "pc/djui/djui_chat_message.h"
|
||||||
#include "pc/chat_commands.h"
|
#include "pc/commands.h"
|
||||||
#include "pc/network/ban_list.h"
|
#include "pc/network/ban_list.h"
|
||||||
#include "pc/network/moderator_list.h"
|
#include "pc/network/moderator_list.h"
|
||||||
#include "pc/debuglog.h"
|
#include "pc/debuglog.h"
|
||||||
|
|
@ -66,12 +66,12 @@ static s32 get_level_abbreviation_alt(const char *str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool exec_dev_chat_command(char* command) {
|
bool exec_dev_chat_command(char* command) {
|
||||||
if (strcmp("/warp", command) == 0) {
|
if (strcmp("warp", command) == 0) {
|
||||||
djui_chat_message_create("Missing parameters: [LEVEL] [AREA] [ACT]");
|
djui_chat_message_create("Missing parameters: [LEVEL] [AREA] [ACT]");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str_starts_with(command, "/warp ")) {
|
if (str_starts_with(command, "warp ")) {
|
||||||
static const struct { const char *name; s32 num; } sLevelNumByName[] = {
|
static const struct { const char *name; s32 num; } sLevelNumByName[] = {
|
||||||
#undef STUB_LEVEL
|
#undef STUB_LEVEL
|
||||||
#undef DEFINE_LEVEL
|
#undef DEFINE_LEVEL
|
||||||
|
|
@ -85,7 +85,7 @@ bool exec_dev_chat_command(char* command) {
|
||||||
s32 act = 0;
|
s32 act = 0;
|
||||||
|
|
||||||
// Params
|
// Params
|
||||||
char *paramLevel = command + 6;
|
char *paramLevel = command + 5;
|
||||||
if (*paramLevel == 0 || *paramLevel == ' ') {
|
if (*paramLevel == 0 || *paramLevel == ' ') {
|
||||||
djui_chat_message_create("Missing parameters: [LEVEL]");
|
djui_chat_message_create("Missing parameters: [LEVEL]");
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -161,23 +161,23 @@ bool exec_dev_chat_command(char* command) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp("/lua", command) == 0) {
|
if (strcmp("lua", command) == 0) {
|
||||||
djui_chat_message_create("Missing parameter: [LUA]");
|
djui_chat_message_create("Missing parameter: [LUA]");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str_starts_with(command, "/lua ")) {
|
if (str_starts_with(command, "lua ")) {
|
||||||
smlua_exec_str(&command[5]);
|
smlua_exec_str(&command[4]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp("/luaf", command) == 0) {
|
if (strcmp("luaf", command) == 0) {
|
||||||
djui_chat_message_create("Missing parameter: [FILENAME]");
|
djui_chat_message_create("Missing parameter: [FILENAME]");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str_starts_with(command, "/luaf ")) {
|
if (str_starts_with(command, "luaf ")) {
|
||||||
smlua_exec_file(&command[6]);
|
smlua_exec_file(&command[5]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -185,8 +185,8 @@ bool exec_dev_chat_command(char* command) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void dev_display_chat_commands(void) {
|
void dev_display_chat_commands(void) {
|
||||||
djui_chat_message_create("/warp [LEVEL] [AREA] [ACT] - Level can be either a numeric value or a shorthand name");
|
command_message_create("/warp [LEVEL] [AREA] [ACT] - Level can be either a numeric value or a shorthand name");
|
||||||
djui_chat_message_create("/lua [LUA] - Execute Lua code from a string");
|
command_message_create("/lua [LUA] - Execute Lua code from a string");
|
||||||
djui_chat_message_create("/luaf [FILENAME] - Execute Lua code from a file");
|
command_message_create("/luaf [FILENAME] - Execute Lua code from a file");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -46,7 +46,7 @@ void discord_fatal(int rc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_oauth2_token_callback(UNUSED void* data, enum EDiscordResult result, struct DiscordOAuth2Token* token) {
|
static void get_oauth2_token_callback(UNUSED void* data, enum EDiscordResult result, struct DiscordOAuth2Token* token) {
|
||||||
LOG_INFO("> get_oauth2_token_callback returned %d", result);
|
LOG_INFO("get_oauth2_token_callback returned %d", result);
|
||||||
if (result != DiscordResult_Ok) { return; }
|
if (result != DiscordResult_Ok) { return; }
|
||||||
LOG_INFO("OAuth2 token: %s", token->access_token);
|
LOG_INFO("OAuth2 token: %s", token->access_token);
|
||||||
}
|
}
|
||||||
|
|
@ -72,7 +72,7 @@ static void register_launch_command(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_current_user_update(UNUSED void* data) {
|
static void on_current_user_update(UNUSED void* data) {
|
||||||
LOG_INFO("> on_current_user_update");
|
LOG_INFO("on_current_user_update");
|
||||||
struct DiscordUser user = { 0 };
|
struct DiscordUser user = { 0 };
|
||||||
app.users->get_current_user(app.users, &user);
|
app.users->get_current_user(app.users, &user);
|
||||||
|
|
||||||
|
|
@ -95,7 +95,7 @@ static void on_current_user_update(UNUSED void* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IDiscordUserEvents* discord_user_initialize(void) {
|
struct IDiscordUserEvents* discord_user_initialize(void) {
|
||||||
LOG_INFO("> discord_user_intitialize");
|
LOG_INFO("discord_user_intitialize");
|
||||||
static struct IDiscordUserEvents events = { 0 };
|
static struct IDiscordUserEvents events = { 0 };
|
||||||
events.on_current_user_update = on_current_user_update;
|
events.on_current_user_update = on_current_user_update;
|
||||||
return &events;
|
return &events;
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,12 @@ static uint64_t sQueuedLobbyId = 0;
|
||||||
static char sQueuedLobbyPassword[64] = "";
|
static char sQueuedLobbyPassword[64] = "";
|
||||||
|
|
||||||
static void on_activity_update_callback(UNUSED void* data, enum EDiscordResult result) {
|
static void on_activity_update_callback(UNUSED void* data, enum EDiscordResult result) {
|
||||||
LOG_INFO("> on_activity_update_callback returned %d", result);
|
LOG_INFO("on_activity_update_callback returned %d", result);
|
||||||
DISCORD_REQUIRE(result);
|
DISCORD_REQUIRE(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_activity_join(UNUSED void* data, const char* secret) {
|
static void on_activity_join(UNUSED void* data, const char* secret) {
|
||||||
LOG_INFO("> on_activity_join, secret: %s", secret);
|
LOG_INFO("on_activity_join, secret: %s", secret);
|
||||||
char *token;
|
char *token;
|
||||||
|
|
||||||
// extract lobby type
|
// extract lobby type
|
||||||
|
|
@ -52,12 +52,12 @@ static void on_activity_join(UNUSED void* data, const char* secret) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_activity_join_request_callback(UNUSED void* data, enum EDiscordResult result) {
|
static void on_activity_join_request_callback(UNUSED void* data, enum EDiscordResult result) {
|
||||||
LOG_INFO("> on_activity_join_request_callback returned %d", (int)result);
|
LOG_INFO("on_activity_join_request_callback returned %d", (int)result);
|
||||||
DISCORD_REQUIRE(result);
|
DISCORD_REQUIRE(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_activity_join_request(UNUSED void* data, struct DiscordUser* user) {
|
static void on_activity_join_request(UNUSED void* data, struct DiscordUser* user) {
|
||||||
LOG_INFO("> on_activity_join_request from " DISCORD_ID_FORMAT, user->id);
|
LOG_INFO("on_activity_join_request from " DISCORD_ID_FORMAT, user->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void strncat_len(char* destination, char* source, size_t destinationLength, size_t sourceLength) {
|
static void strncat_len(char* destination, char* source, size_t destinationLength, size_t sourceLength) {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "pc/network/network.h"
|
#include "pc/network/network.h"
|
||||||
#include "pc/lua/smlua_hooks.h"
|
#include "pc/lua/smlua_hooks.h"
|
||||||
#include "pc/chat_commands.h"
|
#include "pc/commands.h"
|
||||||
#include "pc/configfile.h"
|
#include "pc/configfile.h"
|
||||||
#include "djui.h"
|
#include "djui.h"
|
||||||
#include "engine/math_util.h"
|
#include "engine/math_util.h"
|
||||||
|
|
@ -139,13 +139,7 @@ static void djui_chat_box_input_enter(struct DjuiInputbox* chatInput) {
|
||||||
if (strlen(chatInput->buffer) != 0) {
|
if (strlen(chatInput->buffer) != 0) {
|
||||||
sent_history_add_message(&sentHistory, chatInput->buffer);
|
sent_history_add_message(&sentHistory, chatInput->buffer);
|
||||||
if (chatInput->buffer[0] == '/') {
|
if (chatInput->buffer[0] == '/') {
|
||||||
if (strcmp(chatInput->buffer, "/help") == 0 || strcmp(chatInput->buffer, "/?") == 0 || strcmp(chatInput->buffer, "/") == 0) {
|
run_command(chatInput->buffer + 1);
|
||||||
display_chat_commands();
|
|
||||||
} else if (!exec_chat_command(chatInput->buffer)) {
|
|
||||||
char extendedUnknownCommandMessage[MAX_CHAT_MSG_LENGTH];
|
|
||||||
snprintf(extendedUnknownCommandMessage, sizeof(extendedUnknownCommandMessage), "%s (/help)", DLANG(CHAT, UNRECOGNIZED));
|
|
||||||
djui_chat_message_create(extendedUnknownCommandMessage);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
djui_chat_message_create_from(gNetworkPlayerLocal->globalIndex, chatInput->buffer);
|
djui_chat_message_create_from(gNetworkPlayerLocal->globalIndex, chatInput->buffer);
|
||||||
network_send_chat(chatInput->buffer, gNetworkPlayerLocal->globalIndex);
|
network_send_chat(chatInput->buffer, gNetworkPlayerLocal->globalIndex);
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include "djui.h"
|
#include "djui.h"
|
||||||
#include "djui_console.h"
|
#include "djui_console.h"
|
||||||
#include "pc/pc_main.h"
|
#include "pc/pc_main.h"
|
||||||
|
#include "pc/commands.h"
|
||||||
#include "engine/math_util.h"
|
#include "engine/math_util.h"
|
||||||
|
|
||||||
#define MAX_CONSOLE_MESSAGES 500
|
#define MAX_CONSOLE_MESSAGES 500
|
||||||
|
|
@ -12,6 +13,7 @@ bool gDjuiConsoleFocus = false;
|
||||||
char gDjuiConsoleTmpBuffer[CONSOLE_MAX_TMP_BUFFER] = "";
|
char gDjuiConsoleTmpBuffer[CONSOLE_MAX_TMP_BUFFER] = "";
|
||||||
u32 sDjuiConsoleMessages = 0;
|
u32 sDjuiConsoleMessages = 0;
|
||||||
bool sDjuiConsoleQueueMessages = true;
|
bool sDjuiConsoleQueueMessages = true;
|
||||||
|
bool sIgnoreNextTextInput = false;
|
||||||
|
|
||||||
struct ConsoleQueuedMessage {
|
struct ConsoleQueuedMessage {
|
||||||
char* message;
|
char* message;
|
||||||
|
|
@ -52,12 +54,13 @@ void djui_console_message_dequeue(void) {
|
||||||
|
|
||||||
bool djui_console_render(struct DjuiBase* base) {
|
bool djui_console_render(struct DjuiBase* base) {
|
||||||
struct DjuiConsole* console = (struct DjuiConsole*)base;
|
struct DjuiConsole* console = (struct DjuiConsole*)base;
|
||||||
djui_base_set_size(base, gDjuiRoot->base.width.value, gDjuiRoot->base.height.value * 0.5f);
|
djui_base_set_size(&console->base, gDjuiRoot->base.width.value, gDjuiRoot->base.height.value * 0.5f);
|
||||||
|
djui_base_set_size(&console->rectContainer->base, gDjuiRoot->base.width.value, gDjuiRoot->base.height.value * 0.5f - 32);
|
||||||
if (console->scrolling) {
|
if (console->scrolling) {
|
||||||
f32 yMax = console->base.comp.height - console->flow->base.height.value;
|
f32 yMax = console->base.comp.height - console->flow->base.height.value - 32;
|
||||||
f32 target = console->flow->base.y.value + (console->scrollY - console->flow->base.y.value) * (configSmoothScrolling ? 0.5f : 1.f);
|
f32 target = console->flow->base.y.value + (console->scrollY - console->flow->base.y.value) * (configSmoothScrolling ? 0.5f : 1.f);
|
||||||
|
|
||||||
console->flow->base.y.value = clamp(target, yMax, 0.f);
|
console->flow->base.y.value = clamp(target, yMax, 0.0f);
|
||||||
if (target < yMax || 0.f < target) {
|
if (target < yMax || 0.f < target) {
|
||||||
console->scrollY = clamp(target, yMax, 0.f);
|
console->scrollY = clamp(target, yMax, 0.f);
|
||||||
if (target > 0.f) { gDjuiConsole->scrolling = false; }
|
if (target > 0.f) { gDjuiConsole->scrolling = false; }
|
||||||
|
|
@ -75,12 +78,13 @@ static void djui_console_destroy(struct DjuiBase* base) {
|
||||||
|
|
||||||
void djui_console_toggle(void) {
|
void djui_console_toggle(void) {
|
||||||
if (gDjuiConsole == NULL) { return; }
|
if (gDjuiConsole == NULL) { return; }
|
||||||
|
sIgnoreNextTextInput = true;
|
||||||
gDjuiConsoleFocus = !gDjuiConsoleFocus;
|
gDjuiConsoleFocus = !gDjuiConsoleFocus;
|
||||||
djui_base_set_visible(&gDjuiConsole->base, gDjuiConsoleFocus);
|
djui_base_set_visible(&gDjuiConsole->base, gDjuiConsoleFocus);
|
||||||
|
|
||||||
if (gDjuiConsoleFocus) {
|
if (gDjuiConsoleFocus) {
|
||||||
if (gDjuiChatBoxFocus) { djui_chat_box_toggle(); }
|
if (gDjuiChatBoxFocus) { djui_chat_box_toggle(); }
|
||||||
djui_interactable_set_input_focus(&gDjuiConsole->base);
|
djui_interactable_set_input_focus(&gDjuiConsole->inputbox->base);
|
||||||
} else {
|
} else {
|
||||||
djui_interactable_set_input_focus(NULL);
|
djui_interactable_set_input_focus(NULL);
|
||||||
}
|
}
|
||||||
|
|
@ -102,12 +106,28 @@ static void djui_console_on_scroll(UNUSED struct DjuiBase *base, UNUSED float x,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool djui_console_on_key_down(UNUSED struct DjuiBase* base, int scancode) {
|
static void djui_console_enter() {
|
||||||
|
char* buffer = gDjuiConsole->inputbox->buffer;
|
||||||
|
if (strcmp(buffer, "") == 0) return;
|
||||||
|
if (buffer[0] == '/') buffer++;
|
||||||
|
run_command(buffer);
|
||||||
|
djui_inputbox_set_text(gDjuiConsole->inputbox, "");
|
||||||
|
djui_inputbox_select_all(gDjuiConsole->inputbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool djui_console_on_key_down(struct DjuiBase* base, int scancode) {
|
||||||
if (gDjuiConsole == NULL) { return false; }
|
if (gDjuiConsole == NULL) { return false; }
|
||||||
f32 yMax = gDjuiConsole->base.comp.height - gDjuiConsole->flow->base.height.value;
|
f32 yMax = gDjuiConsole->base.comp.height - gDjuiConsole->flow->base.height.value;
|
||||||
|
|
||||||
f32 pageAmount = gDjuiConsole->base.comp.height * 3.0f / 4.0f;
|
f32 pageAmount = gDjuiConsole->base.comp.height * 3.0f / 4.0f;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_BINDS; i++) {
|
||||||
|
if (scancode == (int)configKeyConsole[i]) {
|
||||||
|
djui_console_toggle();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (scancode) {
|
switch (scancode) {
|
||||||
case SCANCODE_UP:
|
case SCANCODE_UP:
|
||||||
gDjuiConsole->scrollY -= 15;
|
gDjuiConsole->scrollY -= 15;
|
||||||
|
|
@ -121,8 +141,14 @@ static bool djui_console_on_key_down(UNUSED struct DjuiBase* base, int scancode)
|
||||||
case SCANCODE_PAGE_DOWN:
|
case SCANCODE_PAGE_DOWN:
|
||||||
gDjuiConsole->scrollY += pageAmount;
|
gDjuiConsole->scrollY += pageAmount;
|
||||||
break;
|
break;
|
||||||
case SCANCODE_ESCAPE: djui_console_toggle(); break;
|
case SCANCODE_ENTER:
|
||||||
default: break;
|
djui_console_enter();
|
||||||
|
break;
|
||||||
|
case SCANCODE_ESCAPE:
|
||||||
|
djui_console_toggle();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return djui_inputbox_on_key_down(base, scancode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gDjuiConsole->scrolling) {
|
if (!gDjuiConsole->scrolling) {
|
||||||
|
|
@ -131,6 +157,27 @@ static bool djui_console_on_key_down(UNUSED struct DjuiBase* base, int scancode)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void djui_console_on_text_input(struct DjuiBase* base, char* text) {
|
||||||
|
if (sIgnoreNextTextInput) {
|
||||||
|
sIgnoreNextTextInput = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
djui_inputbox_on_text_input(base, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void djui_console_clear() {
|
||||||
|
if (gDjuiConsole == NULL) { return; }
|
||||||
|
|
||||||
|
struct DjuiBase* cfBase = &gDjuiConsole->flow->base;
|
||||||
|
djui_base_destroy_children(cfBase);
|
||||||
|
|
||||||
|
cfBase->height.value = 0;
|
||||||
|
cfBase->y.value = 0;
|
||||||
|
gDjuiConsole->scrollY = 0;
|
||||||
|
gDjuiConsole->scrolling = false;
|
||||||
|
sDjuiConsoleMessages = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void djui_console_message_create(const char* message, enum ConsoleMessageLevel level) {
|
void djui_console_message_create(const char* message, enum ConsoleMessageLevel level) {
|
||||||
if (sDjuiConsoleQueueMessages || !gDjuiConsole) {
|
if (sDjuiConsoleQueueMessages || !gDjuiConsole) {
|
||||||
djui_console_message_queue(message, level);
|
djui_console_message_queue(message, level);
|
||||||
|
|
@ -205,11 +252,13 @@ struct DjuiConsole* djui_console_create(void) {
|
||||||
djui_base_set_padding(base, 0, 8, 8, 8);
|
djui_base_set_padding(base, 0, 8, 8, 8);
|
||||||
djui_base_set_visible(base, false);
|
djui_base_set_visible(base, false);
|
||||||
|
|
||||||
djui_interactable_create(base, NULL);
|
struct DjuiRect* rectContainer = djui_rect_container_create(base, 0);
|
||||||
djui_interactable_hook_key(base, djui_console_on_key_down, NULL);
|
djui_base_set_alignment(&rectContainer->base, DJUI_HALIGN_LEFT, DJUI_VALIGN_TOP);
|
||||||
djui_interactable_hook_scroll(base, djui_console_on_scroll);
|
djui_base_set_size_type(&rectContainer->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||||
|
djui_base_set_size(&rectContainer->base, 1.0f, gDjuiRoot->base.height.value * 0.5f);
|
||||||
|
console->rectContainer = rectContainer;
|
||||||
|
|
||||||
struct DjuiFlowLayout* flow = djui_flow_layout_create(base);
|
struct DjuiFlowLayout* flow = djui_flow_layout_create(&rectContainer->base);
|
||||||
struct DjuiBase* cfBase = &flow->base;
|
struct DjuiBase* cfBase = &flow->base;
|
||||||
djui_base_set_alignment(cfBase, DJUI_HALIGN_LEFT, DJUI_VALIGN_BOTTOM);
|
djui_base_set_alignment(cfBase, DJUI_HALIGN_LEFT, DJUI_VALIGN_BOTTOM);
|
||||||
djui_base_set_location(cfBase, 0, 0);
|
djui_base_set_location(cfBase, 0, 0);
|
||||||
|
|
@ -223,6 +272,21 @@ struct DjuiConsole* djui_console_create(void) {
|
||||||
cfBase->abandonAfterChildRenderFail = true;
|
cfBase->abandonAfterChildRenderFail = true;
|
||||||
console->flow = flow;
|
console->flow = flow;
|
||||||
|
|
||||||
|
struct DjuiInputbox* inputbox = djui_inputbox_create(base, MAX_CONSOLE_INPUT_LENGTH);
|
||||||
|
inputbox->base.interactable->update_style = NULL;
|
||||||
|
djui_base_set_border_color(&inputbox->base, 0, 0, 0, 0);
|
||||||
|
djui_base_set_color(&inputbox->base, 0, 0, 0, 0);
|
||||||
|
djui_base_set_size_type(&inputbox->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||||
|
djui_base_set_size(&inputbox->base, 1.0f, 32);
|
||||||
|
djui_base_set_alignment(&inputbox->base, DJUI_HALIGN_CENTER, DJUI_VALIGN_BOTTOM);
|
||||||
|
djui_interactable_hook_key(&inputbox->base, djui_console_on_key_down, djui_inputbox_on_key_up);
|
||||||
|
djui_interactable_hook_text_input(&inputbox->base, djui_console_on_text_input);
|
||||||
|
djui_interactable_hook_text_editing(&inputbox->base, djui_inputbox_on_text_editing);
|
||||||
|
djui_interactable_hook_scroll(&inputbox->base, djui_console_on_scroll);
|
||||||
|
djui_inputbox_set_text_color(inputbox, 255, 255, 255, 255);
|
||||||
|
inputbox->yOffset = 6;
|
||||||
|
console->inputbox = inputbox;
|
||||||
|
|
||||||
gDjuiConsole = console;
|
gDjuiConsole = console;
|
||||||
|
|
||||||
return console;
|
return console;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "djui.h"
|
#include "djui.h"
|
||||||
|
|
||||||
|
#define MAX_CONSOLE_INPUT_LENGTH 500
|
||||||
|
|
||||||
enum ConsoleMessageLevel {
|
enum ConsoleMessageLevel {
|
||||||
CONSOLE_MESSAGE_INFO,
|
CONSOLE_MESSAGE_INFO,
|
||||||
CONSOLE_MESSAGE_WARNING,
|
CONSOLE_MESSAGE_WARNING,
|
||||||
|
|
@ -9,7 +11,9 @@ enum ConsoleMessageLevel {
|
||||||
|
|
||||||
struct DjuiConsole {
|
struct DjuiConsole {
|
||||||
struct DjuiBase base;
|
struct DjuiBase base;
|
||||||
|
struct DjuiRect* rectContainer;
|
||||||
struct DjuiFlowLayout* flow;
|
struct DjuiFlowLayout* flow;
|
||||||
|
struct DjuiInputbox* inputbox;
|
||||||
bool scrolling;
|
bool scrolling;
|
||||||
f32 scrollY;
|
f32 scrollY;
|
||||||
};
|
};
|
||||||
|
|
@ -20,6 +24,7 @@ extern bool gDjuiConsoleFocus;
|
||||||
extern char gDjuiConsoleTmpBuffer[];
|
extern char gDjuiConsoleTmpBuffer[];
|
||||||
|
|
||||||
void djui_console_message_dequeue(void);
|
void djui_console_message_dequeue(void);
|
||||||
|
void djui_console_clear();
|
||||||
void djui_console_message_create(const char* message, enum ConsoleMessageLevel level);
|
void djui_console_message_create(const char* message, enum ConsoleMessageLevel level);
|
||||||
/* |description|Toggles the visibility of the DJUI console|descriptionEnd| */
|
/* |description|Toggles the visibility of the DJUI console|descriptionEnd| */
|
||||||
void djui_console_toggle(void);
|
void djui_console_toggle(void);
|
||||||
|
|
|
||||||
|
|
@ -486,7 +486,7 @@ static void djui_inputbox_render_selection(struct DjuiInputbox* inputbox) {
|
||||||
if (sCursorBlink < DJUI_INPUTBOX_MID_BLINK && djui_interactable_is_input_focus(&inputbox->base)) {
|
if (sCursorBlink < DJUI_INPUTBOX_MID_BLINK && djui_interactable_is_input_focus(&inputbox->base)) {
|
||||||
create_dl_translation_matrix(DJUI_MTX_PUSH, renderX - DJUI_INPUTBOX_CURSOR_WIDTH / 2.0f, -0.1f, 0);
|
create_dl_translation_matrix(DJUI_MTX_PUSH, renderX - DJUI_INPUTBOX_CURSOR_WIDTH / 2.0f, -0.1f, 0);
|
||||||
create_dl_scale_matrix(DJUI_MTX_NOPUSH, DJUI_INPUTBOX_CURSOR_WIDTH, 0.8f, 1.0f);
|
create_dl_scale_matrix(DJUI_MTX_NOPUSH, DJUI_INPUTBOX_CURSOR_WIDTH, 0.8f, 1.0f);
|
||||||
gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, 255);
|
gDPSetEnvColor(gDisplayListHead++, inputbox->textColor.r, inputbox->textColor.g, inputbox->textColor.b, inputbox->textColor.a);
|
||||||
gSPDisplayList(gDisplayListHead++, dl_djui_simple_rect);
|
gSPDisplayList(gDisplayListHead++, dl_djui_simple_rect);
|
||||||
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
|
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
|
||||||
}
|
}
|
||||||
|
|
@ -559,7 +559,7 @@ static bool djui_inputbox_render(struct DjuiBase* base) {
|
||||||
|
|
||||||
// translate position
|
// translate position
|
||||||
f32 translatedX = comp->x + inputbox->viewX;
|
f32 translatedX = comp->x + inputbox->viewX;
|
||||||
f32 translatedY = comp->y + DJUI_INPUTBOX_YOFF;
|
f32 translatedY = comp->y + inputbox->yOffset;
|
||||||
djui_gfx_position_translate(&translatedX, &translatedY);
|
djui_gfx_position_translate(&translatedX, &translatedY);
|
||||||
create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, 0);
|
create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, 0);
|
||||||
|
|
||||||
|
|
@ -637,6 +637,7 @@ struct DjuiInputbox* djui_inputbox_create(struct DjuiBase* parent, u16 bufferSiz
|
||||||
struct DjuiBase* base = &inputbox->base;
|
struct DjuiBase* base = &inputbox->base;
|
||||||
inputbox->bufferSize = bufferSize;
|
inputbox->bufferSize = bufferSize;
|
||||||
inputbox->buffer = calloc(bufferSize, sizeof(char));
|
inputbox->buffer = calloc(bufferSize, sizeof(char));
|
||||||
|
inputbox->yOffset = DJUI_INPUTBOX_YOFF;
|
||||||
|
|
||||||
djui_base_init(parent, base, djui_inputbox_render, djui_inputbox_destroy);
|
djui_base_init(parent, base, djui_inputbox_render, djui_inputbox_destroy);
|
||||||
djui_base_set_size(base, 200, 32);
|
djui_base_set_size(base, 200, 32);
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ struct DjuiInputbox {
|
||||||
u16 bufferSize;
|
u16 bufferSize;
|
||||||
u16 selection[2];
|
u16 selection[2];
|
||||||
f32 viewX;
|
f32 viewX;
|
||||||
|
f32 yOffset;
|
||||||
struct DjuiColor textColor;
|
struct DjuiColor textColor;
|
||||||
void (*on_enter_press)(struct DjuiInputbox*);
|
void (*on_enter_press)(struct DjuiInputbox*);
|
||||||
void (*on_escape_press)(struct DjuiInputbox*);
|
void (*on_escape_press)(struct DjuiInputbox*);
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,7 @@ void djui_interactable_set_binding(struct DjuiBase* base) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void djui_interactable_set_input_focus(struct DjuiBase* base) {
|
void djui_interactable_set_input_focus(struct DjuiBase* base) {
|
||||||
if (gDjuiConsoleFocus && base != &gDjuiConsole->base) {
|
if (gDjuiConsoleFocus && base != &gDjuiConsole->inputbox->base) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -199,8 +199,8 @@ bool djui_interactable_on_key_down(int scancode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool keyFocused = (gInteractableFocus != NULL)
|
bool keyFocused = (gInteractableFocus != NULL)
|
||||||
&& (gInteractableFocus->interactable != NULL)
|
&& (gInteractableFocus->interactable != NULL)
|
||||||
&& (gInteractableFocus->interactable->on_key_down != NULL);
|
&& (gInteractableFocus->interactable->on_key_down != NULL);
|
||||||
|
|
||||||
if (keyFocused) {
|
if (keyFocused) {
|
||||||
bool consume = gInteractableFocus->interactable->on_key_down(gInteractableFocus, scancode);
|
bool consume = gInteractableFocus->interactable->on_key_down(gInteractableFocus, scancode);
|
||||||
|
|
@ -217,10 +217,22 @@ bool djui_interactable_on_key_down(int scancode) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!gDjuiChatBoxFocus) {
|
||||||
|
for (int i = 0; i < MAX_BINDS; i++) {
|
||||||
|
if (scancode == (int)configKeyConsole[i]) {
|
||||||
|
djui_console_toggle();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (gDjuiChatBox != NULL && !gDjuiChatBoxFocus) {
|
if (gDjuiChatBox != NULL && !gDjuiChatBoxFocus) {
|
||||||
bool pressChat = false;
|
bool pressChat = false;
|
||||||
for (int i = 0; i < MAX_BINDS; i++) {
|
for (int i = 0; i < MAX_BINDS; i++) {
|
||||||
if (scancode == (int)configKeyChat[i]) { pressChat = true; }
|
if (scancode == (int)configKeyChat[i]) {
|
||||||
|
pressChat = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pressChat && !gDjuiConsoleFocus) {
|
if (pressChat && !gDjuiConsoleFocus) {
|
||||||
|
|
@ -264,7 +276,7 @@ bool djui_interactable_on_key_down(int scancode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gDjuiChatBoxFocus || djui_panel_is_active()) {
|
if (gDjuiConsoleFocus || gDjuiChatBoxFocus || djui_panel_is_active()) {
|
||||||
switch (scancode) {
|
switch (scancode) {
|
||||||
case SCANCODE_UP: sKeyboardHoldDirection = PAD_HOLD_DIR_UP; return true;
|
case SCANCODE_UP: sKeyboardHoldDirection = PAD_HOLD_DIR_UP; return true;
|
||||||
case SCANCODE_DOWN: sKeyboardHoldDirection = PAD_HOLD_DIR_DOWN; return true;
|
case SCANCODE_DOWN: sKeyboardHoldDirection = PAD_HOLD_DIR_DOWN; return true;
|
||||||
|
|
@ -278,13 +290,6 @@ bool djui_interactable_on_key_down(int scancode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void djui_interactable_on_key_up(int scancode) {
|
void djui_interactable_on_key_up(int scancode) {
|
||||||
|
|
||||||
if (!gDjuiChatBoxFocus) {
|
|
||||||
for (int i = 0; i < MAX_BINDS; i++) {
|
|
||||||
if (scancode == (int)configKeyConsole[i]) { djui_console_toggle(); break; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gDjuiPlayerList != NULL || gDjuiModList != NULL) {
|
if (gDjuiPlayerList != NULL || gDjuiModList != NULL) {
|
||||||
for (int i = 0; i < MAX_BINDS; i++) {
|
for (int i = 0; i < MAX_BINDS; i++) {
|
||||||
if (scancode == (int)configKeyPlayerList[i]) {
|
if (scancode == (int)configKeyPlayerList[i]) {
|
||||||
|
|
@ -424,12 +429,12 @@ void djui_interactable_update(void) {
|
||||||
u16 mainButtons = PAD_BUTTON_A | PAD_BUTTON_B;
|
u16 mainButtons = PAD_BUTTON_A | PAD_BUTTON_B;
|
||||||
if ((mouseButtons & MOUSE_BUTTON_1) && !(sLastMouseButtons & MOUSE_BUTTON_1) && !djui_cursor_inside_base(gInteractableFocus)) {
|
if ((mouseButtons & MOUSE_BUTTON_1) && !(sLastMouseButtons & MOUSE_BUTTON_1) && !djui_cursor_inside_base(gInteractableFocus)) {
|
||||||
// clicked outside of focus
|
// clicked outside of focus
|
||||||
if (!gDjuiChatBoxFocus) {
|
if (!gDjuiChatBoxFocus && !gDjuiConsoleFocus) {
|
||||||
djui_interactable_set_input_focus(NULL);
|
djui_interactable_set_input_focus(NULL);
|
||||||
}
|
}
|
||||||
} else if ((padButtons & mainButtons) && !(sLastInteractablePad.button & mainButtons)) {
|
} else if ((padButtons & mainButtons) && !(sLastInteractablePad.button & mainButtons)) {
|
||||||
// pressed main face button
|
// pressed main face button
|
||||||
if (!gDjuiChatBoxFocus) {
|
if (!gDjuiChatBoxFocus && !gDjuiConsoleFocus) {
|
||||||
djui_interactable_set_input_focus(NULL);
|
djui_interactable_set_input_focus(NULL);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -287,6 +287,11 @@ static void djui_text_read_line(struct DjuiText* text, char** message, f32* line
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check for tab
|
||||||
|
if (*c == '\t') {
|
||||||
|
charWidth = 4 * text->font->char_width(" ");
|
||||||
|
}
|
||||||
|
|
||||||
// check to see if this character would exceed size
|
// check to see if this character would exceed size
|
||||||
if (*lineWidth + charWidth >= maxLineWidth) {
|
if (*lineWidth + charWidth >= maxLineWidth) {
|
||||||
break;
|
break;
|
||||||
|
|
@ -388,7 +393,9 @@ static void djui_text_render_line(struct DjuiText* text, char* c1, char* c2, f32
|
||||||
}
|
}
|
||||||
|
|
||||||
f32 charWidth = text->font->char_width(c);
|
f32 charWidth = text->font->char_width(c);
|
||||||
if (*c != '\n' && *c != ' ') {
|
if (*c == '\t') {
|
||||||
|
charWidth = 4 * text->font->char_width(" ");
|
||||||
|
} else if (*c != '\n' && *c != ' ') {
|
||||||
djui_text_render_char(text, c);
|
djui_text_render_char(text, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
1762
src/pc/linenoise/linenoise.c
Normal file
1762
src/pc/linenoise/linenoise.c
Normal file
File diff suppressed because it is too large
Load diff
114
src/pc/linenoise/linenoise.h
Normal file
114
src/pc/linenoise/linenoise.h
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
/* linenoise.h -- VERSION 1.0
|
||||||
|
*
|
||||||
|
* Guerrilla line editing library against the idea that a line editing lib
|
||||||
|
* needs to be 20,000 lines of C code.
|
||||||
|
*
|
||||||
|
* See linenoise.c for more information.
|
||||||
|
*
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2023, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||||
|
* Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LINENOISE_H
|
||||||
|
#define __LINENOISE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h> /* For size_t. */
|
||||||
|
|
||||||
|
extern char *linenoiseEditMore;
|
||||||
|
|
||||||
|
/* The linenoiseState structure represents the state during line editing.
|
||||||
|
* We pass this state to functions implementing specific editing
|
||||||
|
* functionalities. */
|
||||||
|
struct linenoiseState {
|
||||||
|
int in_completion; /* The user pressed TAB and we are now in completion
|
||||||
|
* mode, so input is handled by completeLine(). */
|
||||||
|
size_t completion_idx; /* Index of next completion to propose. */
|
||||||
|
int ifd; /* Terminal stdin file descriptor. */
|
||||||
|
int ofd; /* Terminal stdout file descriptor. */
|
||||||
|
char *buf; /* Edited line buffer. */
|
||||||
|
size_t buflen; /* Edited line buffer size. */
|
||||||
|
const char *prompt; /* Prompt to display. */
|
||||||
|
size_t plen; /* Prompt length. */
|
||||||
|
size_t pos; /* Current cursor position. */
|
||||||
|
size_t oldpos; /* Previous refresh cursor position. */
|
||||||
|
size_t len; /* Current edited line length. */
|
||||||
|
size_t cols; /* Number of columns in terminal. */
|
||||||
|
size_t oldrows; /* Rows used by last refrehsed line (multiline mode) */
|
||||||
|
int oldrpos; /* Cursor row from last refresh (for multiline clearing). */
|
||||||
|
int history_index; /* The history index we are currently editing. */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct linenoiseCompletions {
|
||||||
|
size_t len;
|
||||||
|
char **cvec;
|
||||||
|
} linenoiseCompletions;
|
||||||
|
|
||||||
|
/* Non blocking API. */
|
||||||
|
int linenoiseEditStart(struct linenoiseState *l, int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt);
|
||||||
|
char *linenoiseEditFeed(struct linenoiseState *l);
|
||||||
|
void linenoiseEditStop(struct linenoiseState *l);
|
||||||
|
void linenoiseHide(struct linenoiseState *l);
|
||||||
|
void linenoiseShow(struct linenoiseState *l);
|
||||||
|
|
||||||
|
/* Blocking API. */
|
||||||
|
char *linenoise(const char *prompt);
|
||||||
|
void linenoiseFree(void *ptr);
|
||||||
|
|
||||||
|
/* Completion API. */
|
||||||
|
typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *);
|
||||||
|
typedef char*(linenoiseHintsCallback)(const char *, int *color, int *bold);
|
||||||
|
typedef void(linenoiseFreeHintsCallback)(void *);
|
||||||
|
void linenoiseSetCompletionCallback(linenoiseCompletionCallback *);
|
||||||
|
void linenoiseSetHintsCallback(linenoiseHintsCallback *);
|
||||||
|
void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *);
|
||||||
|
void linenoiseAddCompletion(linenoiseCompletions *, const char *);
|
||||||
|
|
||||||
|
/* History API. */
|
||||||
|
int linenoiseHistoryAdd(const char *line);
|
||||||
|
int linenoiseHistorySetMaxLen(int len);
|
||||||
|
int linenoiseHistorySave(const char *filename);
|
||||||
|
int linenoiseHistoryLoad(const char *filename);
|
||||||
|
|
||||||
|
/* Other utilities. */
|
||||||
|
void linenoiseClearScreen(void);
|
||||||
|
void linenoiseSetMultiLine(int ml);
|
||||||
|
void linenoisePrintKeyCodes(void);
|
||||||
|
void linenoiseMaskModeEnable(void);
|
||||||
|
void linenoiseMaskModeDisable(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __LINENOISE_H */
|
||||||
|
|
@ -1485,6 +1485,7 @@ char gSmluaConstants[] = ""
|
||||||
"DIALOG_168=168\n"
|
"DIALOG_168=168\n"
|
||||||
"DIALOG_169=169\n"
|
"DIALOG_169=169\n"
|
||||||
"DIALOG_COUNT=170\n"
|
"DIALOG_COUNT=170\n"
|
||||||
|
"MAX_CONSOLE_INPUT_LENGTH=500\n"
|
||||||
"CONSOLE_MESSAGE_INFO=0\n"
|
"CONSOLE_MESSAGE_INFO=0\n"
|
||||||
"CONSOLE_MESSAGE_WARNING=1\n"
|
"CONSOLE_MESSAGE_WARNING=1\n"
|
||||||
"CONSOLE_MESSAGE_ERROR=2\n"
|
"CONSOLE_MESSAGE_ERROR=2\n"
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,52 @@ bool smlua_functions_valid_param_range(lua_State* L, int min, int max) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////
|
||||||
|
// print //
|
||||||
|
///////////
|
||||||
|
|
||||||
|
int smlua_func_print(lua_State *L) {
|
||||||
|
int top = lua_gettop(L);
|
||||||
|
|
||||||
|
// calculate total length first
|
||||||
|
size_t totalLen = 0;
|
||||||
|
for (int i = 1; i <= top; i++) {
|
||||||
|
size_t len;
|
||||||
|
luaL_tolstring(L, i, &len);
|
||||||
|
totalLen += len;
|
||||||
|
if (i > 1) totalLen += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate string
|
||||||
|
char* completeString = malloc(totalLen + 1);
|
||||||
|
if (!completeString) return 0;
|
||||||
|
|
||||||
|
size_t pos = 0;
|
||||||
|
|
||||||
|
// copy string
|
||||||
|
for (int i = 1; i <= top; i++) {
|
||||||
|
size_t len;
|
||||||
|
const char* str = luaL_tolstring(L, i, &len);
|
||||||
|
|
||||||
|
if (i > 1) {
|
||||||
|
completeString[pos] = '\t';
|
||||||
|
pos += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(completeString + pos, str, len);
|
||||||
|
pos += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
completeString[pos] = '\0';
|
||||||
|
|
||||||
|
// print to terminal and console
|
||||||
|
log_to_terminal("%s", completeString);
|
||||||
|
djui_console_message_create(completeString, CONSOLE_MESSAGE_INFO);
|
||||||
|
|
||||||
|
free(completeString);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
///////////
|
///////////
|
||||||
// table //
|
// table //
|
||||||
///////////
|
///////////
|
||||||
|
|
@ -806,6 +852,13 @@ int smlua_func_log_to_console(lua_State* L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
djui_console_message_create(message, level);
|
djui_console_message_create(message, level);
|
||||||
|
char* colorCode;
|
||||||
|
switch (level) {
|
||||||
|
case CONSOLE_MESSAGE_WARNING: colorCode = "\x1b[33m"; break;
|
||||||
|
case CONSOLE_MESSAGE_ERROR: colorCode = "\x1b[31m"; break;
|
||||||
|
default: colorCode = "\x1b[0m"; break;
|
||||||
|
}
|
||||||
|
log_to_terminal("%s%s\x1b[0m\n", colorCode, message);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -1013,6 +1066,7 @@ void smlua_bind_functions(void) {
|
||||||
lua_State* L = gLuaState;
|
lua_State* L = gLuaState;
|
||||||
|
|
||||||
// misc
|
// misc
|
||||||
|
smlua_bind_function(L, "print", smlua_func_print);
|
||||||
smlua_bind_function(L, "table_copy", smlua_func_table_copy);
|
smlua_bind_function(L, "table_copy", smlua_func_table_copy);
|
||||||
smlua_bind_function(L, "table_deepcopy", smlua_func_table_deepcopy);
|
smlua_bind_function(L, "table_deepcopy", smlua_func_table_deepcopy);
|
||||||
smlua_bind_function(L, "init_mario_after_warp", smlua_func_init_mario_after_warp);
|
smlua_bind_function(L, "init_mario_after_warp", smlua_func_init_mario_after_warp);
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
#include "src/game/mario_step.h"
|
#include "src/game/mario_step.h"
|
||||||
#include "src/game/mario.h"
|
#include "src/game/mario.h"
|
||||||
#include "src/game/rumble_init.h"
|
#include "src/game/rumble_init.h"
|
||||||
|
#include "src/pc/commands.h"
|
||||||
#include "src/pc/djui/djui_popup.h"
|
#include "src/pc/djui/djui_popup.h"
|
||||||
#include "src/pc/network/network_utils.h"
|
#include "src/pc/network/network_utils.h"
|
||||||
#include "src/pc/djui/djui_console.h"
|
#include "src/pc/djui/djui_console.h"
|
||||||
|
|
@ -12125,6 +12126,32 @@ int smlua_func_update_character_anim_offset(lua_State* L) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////
|
||||||
|
// commands.h //
|
||||||
|
////////////////
|
||||||
|
|
||||||
|
int smlua_func_command_message_create(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", "command_message_create", 1, 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, "command_message_create"); return 0; }
|
||||||
|
int level = (int) 0;
|
||||||
|
if (top >= 2) {
|
||||||
|
level = smlua_to_integer(L, 2);
|
||||||
|
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "command_message_create"); return 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
command_message_create(message, level);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////
|
/////////////////////////
|
||||||
// djui_chat_message.h //
|
// djui_chat_message.h //
|
||||||
/////////////////////////
|
/////////////////////////
|
||||||
|
|
@ -37478,6 +37505,9 @@ void smlua_bind_functions_autogen(void) {
|
||||||
smlua_bind_function(L, "get_character_anim", smlua_func_get_character_anim);
|
smlua_bind_function(L, "get_character_anim", smlua_func_get_character_anim);
|
||||||
smlua_bind_function(L, "update_character_anim_offset", smlua_func_update_character_anim_offset);
|
smlua_bind_function(L, "update_character_anim_offset", smlua_func_update_character_anim_offset);
|
||||||
|
|
||||||
|
// commands.h
|
||||||
|
smlua_bind_function(L, "command_message_create", smlua_func_command_message_create);
|
||||||
|
|
||||||
// djui_chat_message.h
|
// djui_chat_message.h
|
||||||
smlua_bind_function(L, "djui_chat_message_create", smlua_func_djui_chat_message_create);
|
smlua_bind_function(L, "djui_chat_message_create", smlua_func_djui_chat_message_create);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
#include "pc/network/network.h"
|
#include "pc/network/network.h"
|
||||||
#include "pc/network/network_player.h"
|
#include "pc/network/network_player.h"
|
||||||
#include "pc/network/socket/socket.h"
|
#include "pc/network/socket/socket.h"
|
||||||
#include "pc/chat_commands.h"
|
#include "pc/commands.h"
|
||||||
#include "pc/pc_main.h"
|
#include "pc/pc_main.h"
|
||||||
#include "pc/djui/djui_lua_profiler.h"
|
#include "pc/djui/djui_lua_profiler.h"
|
||||||
#include "pc/djui/djui_panel.h"
|
#include "pc/djui/djui_panel.h"
|
||||||
|
|
@ -1009,62 +1009,72 @@ bool smlua_call_behavior_hook(const BehaviorScript** behavior, struct Object* ob
|
||||||
// hooked chat command //
|
// hooked chat command //
|
||||||
/////////////////////////
|
/////////////////////////
|
||||||
|
|
||||||
struct LuaHookedChatCommand {
|
struct LuaHookedCommand {
|
||||||
char* command;
|
char* command;
|
||||||
char* description;
|
char* description;
|
||||||
int reference;
|
int reference;
|
||||||
struct Mod* mod;
|
struct Mod* mod;
|
||||||
struct ModFile* modFile;
|
struct ModFile* modFile;
|
||||||
|
bool isConsoleCommand;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_HOOKED_CHAT_COMMANDS 512
|
#define MAX_HOOKED_CHAT_COMMANDS 512
|
||||||
|
|
||||||
static struct LuaHookedChatCommand sHookedChatCommands[MAX_HOOKED_CHAT_COMMANDS] = { 0 };
|
static struct LuaHookedCommand sHookedChatCommands[MAX_HOOKED_CHAT_COMMANDS] = { 0 };
|
||||||
static int sHookedChatCommandsCount = 0;
|
static int sHookedChatCommandsCount = 0;
|
||||||
|
|
||||||
int smlua_hook_chat_command(lua_State* L) {
|
int smlua_hook_command_internal(lua_State* L, bool isConsoleCommand) {
|
||||||
if (L == NULL) { return 0; }
|
if (L == NULL) { return 0; }
|
||||||
if (!smlua_functions_valid_param_count(L, 3)) { return 0; }
|
if (!smlua_functions_valid_param_count(L, 3)) { return 0; }
|
||||||
|
|
||||||
if (gLuaLoadingMod == NULL) {
|
if (gLuaLoadingMod == NULL) {
|
||||||
LOG_LUA_LINE("hook_chat_command() can only be called on load.");
|
LOG_LUA_LINE("%s can only be called on load.", isConsoleCommand ? "hook_console_command()" : "hook_chat_command()");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sHookedChatCommandsCount >= MAX_HOOKED_CHAT_COMMANDS) {
|
if (sHookedChatCommandsCount >= MAX_HOOKED_CHAT_COMMANDS) {
|
||||||
LOG_LUA_LINE("Hooked chat command exceeded maximum references!");
|
LOG_LUA_LINE("Hooked command exceeded maximum references!");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* command = smlua_to_string(L, 1);
|
const char* command = smlua_to_string(L, 1);
|
||||||
if (command == NULL || strlen(command) == 0 || !gSmLuaConvertSuccess) {
|
if (command == NULL || strlen(command) == 0 || !gSmLuaConvertSuccess) {
|
||||||
LOG_LUA_LINE("Hook chat command: tried to hook invalid command");
|
LOG_LUA_LINE("Hook command: tried to hook invalid command");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* description = smlua_to_string(L, 2);
|
const char* description = smlua_to_string(L, 2);
|
||||||
if (description == NULL || strlen(description) == 0 || !gSmLuaConvertSuccess) {
|
if (description == NULL || strlen(description) == 0 || !gSmLuaConvertSuccess) {
|
||||||
LOG_LUA_LINE("Hook chat command: tried to hook invalid description");
|
LOG_LUA_LINE("Hook command: tried to hook invalid description");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
int ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||||
if (ref == -1) {
|
if (ref == -1) {
|
||||||
LOG_LUA_LINE("Hook chat command: tried to hook undefined function '%s'", command);
|
LOG_LUA_LINE("Hook command: tried to hook undefined function '%s'", command);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LuaHookedChatCommand* hooked = &sHookedChatCommands[sHookedChatCommandsCount];
|
struct LuaHookedCommand* hooked = &sHookedChatCommands[sHookedChatCommandsCount];
|
||||||
hooked->command = strdup(command);
|
hooked->command = strdup(command);
|
||||||
hooked->description = strdup(description);
|
hooked->description = strdup(description);
|
||||||
hooked->reference = ref;
|
hooked->reference = ref;
|
||||||
hooked->mod = gLuaActiveMod;
|
hooked->mod = gLuaActiveMod;
|
||||||
hooked->modFile = gLuaActiveModFile;
|
hooked->modFile = gLuaActiveModFile;
|
||||||
|
hooked->isConsoleCommand = isConsoleCommand;
|
||||||
|
|
||||||
sHookedChatCommandsCount++;
|
sHookedChatCommandsCount++;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int smlua_hook_chat_command(lua_State* L) {
|
||||||
|
return smlua_hook_command_internal(L, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int smlua_hook_console_command(lua_State* L) {
|
||||||
|
return smlua_hook_command_internal(L, true);
|
||||||
|
}
|
||||||
|
|
||||||
int smlua_update_chat_command_description(lua_State* L) {
|
int smlua_update_chat_command_description(lua_State* L) {
|
||||||
if (L == NULL) { return 0; }
|
if (L == NULL) { return 0; }
|
||||||
if (!smlua_functions_valid_param_count(L, 2)) { return 0; }
|
if (!smlua_functions_valid_param_count(L, 2)) { return 0; }
|
||||||
|
|
@ -1082,8 +1092,8 @@ int smlua_update_chat_command_description(lua_State* L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < sHookedChatCommandsCount; i++) {
|
for (int i = 0; i < sHookedChatCommandsCount; i++) {
|
||||||
struct LuaHookedChatCommand* hook = &sHookedChatCommands[i];
|
struct LuaHookedCommand* hook = &sHookedChatCommands[i];
|
||||||
if (!strcmp(hook->command, command)) {
|
if (!hook->isConsoleCommand && !strcmp(hook->command, command)) {
|
||||||
if (hook->description) {
|
if (hook->description) {
|
||||||
free(hook->description);
|
free(hook->description);
|
||||||
}
|
}
|
||||||
|
|
@ -1096,19 +1106,50 @@ int smlua_update_chat_command_description(lua_State* L) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int smlua_update_console_command_description(lua_State* L) {
|
||||||
|
if (L == NULL) { return 0; }
|
||||||
|
if (!smlua_functions_valid_param_count(L, 2)) { return 0; }
|
||||||
|
|
||||||
|
const char* command = smlua_to_string(L, 1);
|
||||||
|
if (command == NULL || strlen(command) == 0 || !gSmLuaConvertSuccess) {
|
||||||
|
LOG_LUA_LINE("Update console command: tried to update invalid command");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* description = smlua_to_string(L, 2);
|
||||||
|
if (description == NULL || strlen(description) == 0 || !gSmLuaConvertSuccess) {
|
||||||
|
LOG_LUA_LINE("Update console command: tried to update invalid description");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < sHookedChatCommandsCount; i++) {
|
||||||
|
struct LuaHookedCommand* hook = &sHookedChatCommands[i];
|
||||||
|
if (hook->isConsoleCommand && !strcmp(hook->command, command)) {
|
||||||
|
if (hook->description) {
|
||||||
|
free(hook->description);
|
||||||
|
}
|
||||||
|
hook->description = strdup(description);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_LUA_LINE("Update console command: could not find command to update");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool smlua_call_chat_command_hook(char* command) {
|
bool smlua_call_chat_command_hook(char* command) {
|
||||||
lua_State* L = gLuaState;
|
lua_State* L = gLuaState;
|
||||||
if (L == NULL) { return false; }
|
if (L == NULL) { return false; }
|
||||||
for (int i = 0; i < sHookedChatCommandsCount; i++) {
|
for (int i = 0; i < sHookedChatCommandsCount; i++) {
|
||||||
struct LuaHookedChatCommand* hook = &sHookedChatCommands[i];
|
struct LuaHookedCommand* hook = &sHookedChatCommands[i];
|
||||||
|
// compare strings
|
||||||
size_t commandLength = strlen(hook->command);
|
size_t commandLength = strlen(hook->command);
|
||||||
for (size_t j = 0; j < commandLength; j++) {
|
if (strncmp(hook->command, command, commandLength) != 0) goto NEXT_HOOK;
|
||||||
if (hook->command[j] != command[j + 1]) {
|
|
||||||
goto NEXT_HOOK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char* params = &command[commandLength + 1];
|
// make sure we aren't running a console command
|
||||||
|
if (hook->isConsoleCommand && !gDjuiConsoleFocus) goto NEXT_HOOK;
|
||||||
|
|
||||||
|
char* params = &command[commandLength];
|
||||||
if (*params != '\0' && *params != ' ') {
|
if (*params != '\0' && *params != ' ') {
|
||||||
goto NEXT_HOOK;
|
goto NEXT_HOOK;
|
||||||
}
|
}
|
||||||
|
|
@ -1145,12 +1186,13 @@ NEXT_HOOK:;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void smlua_display_chat_commands(void) {
|
void smlua_display_chat_commands(bool isConsole) {
|
||||||
for (int i = 0; i < sHookedChatCommandsCount; i++) {
|
for (int i = 0; i < sHookedChatCommandsCount; i++) {
|
||||||
struct LuaHookedChatCommand* hook = &sHookedChatCommands[i];
|
struct LuaHookedCommand* hook = &sHookedChatCommands[i];
|
||||||
|
if (!isConsole && hook->isConsoleCommand) continue;
|
||||||
char msg[256] = { 0 };
|
char msg[256] = { 0 };
|
||||||
snprintf(msg, 256, "/%s %s", hook->command, hook->description);
|
snprintf(msg, 256, "/%s %s", hook->command, hook->description);
|
||||||
djui_chat_message_create(msg);
|
command_message_create(msg, CONSOLE_MESSAGE_INFO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1207,6 +1249,7 @@ char** smlua_get_chat_player_list(void) {
|
||||||
return sortedPlayers;
|
return sortedPlayers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this needs a rewrite, actually all these funcs needs a rewrite, actually, the whole autocomplete system needs a rewrite
|
||||||
char** smlua_get_chat_maincommands_list(void) {
|
char** smlua_get_chat_maincommands_list(void) {
|
||||||
#if defined(DEVELOPMENT)
|
#if defined(DEVELOPMENT)
|
||||||
s32 defaultCmdsCount = 11;
|
s32 defaultCmdsCount = 11;
|
||||||
|
|
@ -1227,7 +1270,8 @@ char** smlua_get_chat_maincommands_list(void) {
|
||||||
}
|
}
|
||||||
char** commands = (char**) malloc((sHookedChatCommandsCount + defaultCmdsCountNew + 1) * sizeof(char*));
|
char** commands = (char**) malloc((sHookedChatCommandsCount + defaultCmdsCountNew + 1) * sizeof(char*));
|
||||||
for (s32 i = 0; i < sHookedChatCommandsCount; i++) {
|
for (s32 i = 0; i < sHookedChatCommandsCount; i++) {
|
||||||
struct LuaHookedChatCommand* hook = &sHookedChatCommands[i];
|
struct LuaHookedCommand* hook = &sHookedChatCommands[i];
|
||||||
|
if (hook->isConsoleCommand) continue;
|
||||||
commands[i] = strdup(hook->command);
|
commands[i] = strdup(hook->command);
|
||||||
}
|
}
|
||||||
for (s32 i = 0; i < defaultCmdsCount; i++) {
|
for (s32 i = 0; i < defaultCmdsCount; i++) {
|
||||||
|
|
@ -1251,7 +1295,7 @@ char** smlua_get_chat_subcommands_list(const char* maincommand) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (s32 i = 0; i < sHookedChatCommandsCount; i++) {
|
for (s32 i = 0; i < sHookedChatCommandsCount; i++) {
|
||||||
struct LuaHookedChatCommand* hook = &sHookedChatCommands[i];
|
struct LuaHookedCommand* hook = &sHookedChatCommands[i];
|
||||||
if (strcmp(hook->command, maincommand) == 0) {
|
if (strcmp(hook->command, maincommand) == 0) {
|
||||||
char* noColorsDesc = djui_text_get_uncolored_string(NULL, strlen(hook->description) + 1, hook->description);
|
char* noColorsDesc = djui_text_get_uncolored_string(NULL, strlen(hook->description) + 1, hook->description);
|
||||||
char* startSubcommands = strstr(noColorsDesc, "[");
|
char* startSubcommands = strstr(noColorsDesc, "[");
|
||||||
|
|
@ -1793,7 +1837,7 @@ void smlua_hook_replace_function_references(lua_State* L, int oldReference, int
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < sHookedChatCommandsCount; i++) {
|
for (int i = 0; i < sHookedChatCommandsCount; i++) {
|
||||||
struct LuaHookedChatCommand* hooked = &sHookedChatCommands[i];
|
struct LuaHookedCommand* hooked = &sHookedChatCommands[i];
|
||||||
smlua_hook_replace_function_reference(L, &hooked->reference, oldReference, newReference);
|
smlua_hook_replace_function_reference(L, &hooked->reference, oldReference, newReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1829,7 +1873,7 @@ void smlua_clear_hooks(void) {
|
||||||
sHookedMarioActionsCount = 0;
|
sHookedMarioActionsCount = 0;
|
||||||
|
|
||||||
for (int i = 0; i < sHookedChatCommandsCount; i++) {
|
for (int i = 0; i < sHookedChatCommandsCount; i++) {
|
||||||
struct LuaHookedChatCommand* hooked = &sHookedChatCommands[i];
|
struct LuaHookedCommand* hooked = &sHookedChatCommands[i];
|
||||||
if (hooked->command != NULL) { free(hooked->command); }
|
if (hooked->command != NULL) { free(hooked->command); }
|
||||||
hooked->command = NULL;
|
hooked->command = NULL;
|
||||||
|
|
||||||
|
|
@ -1896,6 +1940,7 @@ void smlua_bind_hooks(void) {
|
||||||
smlua_bind_function(L, "hook_event", smlua_hook_event);
|
smlua_bind_function(L, "hook_event", smlua_hook_event);
|
||||||
smlua_bind_function(L, "hook_mario_action", smlua_hook_mario_action);
|
smlua_bind_function(L, "hook_mario_action", smlua_hook_mario_action);
|
||||||
smlua_bind_function(L, "hook_chat_command", smlua_hook_chat_command);
|
smlua_bind_function(L, "hook_chat_command", smlua_hook_chat_command);
|
||||||
|
smlua_bind_function(L, "hook_console_command", smlua_hook_console_command);
|
||||||
smlua_bind_function(L, "hook_on_sync_table_change", smlua_hook_on_sync_table_change);
|
smlua_bind_function(L, "hook_on_sync_table_change", smlua_hook_on_sync_table_change);
|
||||||
smlua_bind_function(L, "hook_behavior", smlua_hook_behavior);
|
smlua_bind_function(L, "hook_behavior", smlua_hook_behavior);
|
||||||
smlua_bind_function(L, "hook_mod_menu_text", smlua_hook_mod_menu_text);
|
smlua_bind_function(L, "hook_mod_menu_text", smlua_hook_mod_menu_text);
|
||||||
|
|
@ -1904,6 +1949,7 @@ void smlua_bind_hooks(void) {
|
||||||
smlua_bind_function(L, "hook_mod_menu_slider", smlua_hook_mod_menu_slider);
|
smlua_bind_function(L, "hook_mod_menu_slider", smlua_hook_mod_menu_slider);
|
||||||
smlua_bind_function(L, "hook_mod_menu_inputbox", smlua_hook_mod_menu_inputbox);
|
smlua_bind_function(L, "hook_mod_menu_inputbox", smlua_hook_mod_menu_inputbox);
|
||||||
smlua_bind_function(L, "update_chat_command_description", smlua_update_chat_command_description);
|
smlua_bind_function(L, "update_chat_command_description", smlua_update_chat_command_description);
|
||||||
|
smlua_bind_function(L, "update_console_command_description", smlua_update_console_command_description);
|
||||||
smlua_bind_function(L, "update_mod_menu_element_name", smlua_update_mod_menu_element_name);
|
smlua_bind_function(L, "update_mod_menu_element_name", smlua_update_mod_menu_element_name);
|
||||||
smlua_bind_function(L, "update_mod_menu_element_checkbox", smlua_update_mod_menu_element_checkbox);
|
smlua_bind_function(L, "update_mod_menu_element_checkbox", smlua_update_mod_menu_element_checkbox);
|
||||||
smlua_bind_function(L, "update_mod_menu_element_slider", smlua_update_mod_menu_element_slider);
|
smlua_bind_function(L, "update_mod_menu_element_slider", smlua_update_mod_menu_element_slider);
|
||||||
|
|
|
||||||
|
|
@ -177,7 +177,7 @@ bool smlua_call_action_hook(enum LuaActionHookType hookType, struct MarioState*
|
||||||
u32 smlua_get_action_interaction_type(struct MarioState* m);
|
u32 smlua_get_action_interaction_type(struct MarioState* m);
|
||||||
|
|
||||||
bool smlua_call_chat_command_hook(char* command);
|
bool smlua_call_chat_command_hook(char* command);
|
||||||
void smlua_display_chat_commands(void);
|
void smlua_display_chat_commands(bool isConsole);
|
||||||
char** smlua_get_chat_player_list(void);
|
char** smlua_get_chat_player_list(void);
|
||||||
char** smlua_get_chat_maincommands_list(void);
|
char** smlua_get_chat_maincommands_list(void);
|
||||||
char** smlua_get_chat_subcommands_list(const char* maincommand);
|
char** smlua_get_chat_subcommands_list(const char* maincommand);
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,8 @@
|
||||||
#include "pc/discord/discord.h"
|
#include "pc/discord/discord.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "pc/terminal.h"
|
||||||
|
|
||||||
#include "pc/mumble/mumble.h"
|
#include "pc/mumble/mumble.h"
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
|
@ -529,7 +531,7 @@ int main(int argc, char *argv[]) {
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
printf("ERROR: could not find valid vanilla us sm64 rom in game's user folder\n");
|
LOG_ERROR("Could not find valid vanilla us sm64 rom in game's user folder\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -602,6 +604,10 @@ int main(int argc, char *argv[]) {
|
||||||
network_init(NT_NONE, false);
|
network_init(NT_NONE, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initialize terminal
|
||||||
|
terminal_init();
|
||||||
|
//init_thread_handle(&gTerminalThread, terminal_update, NULL, NULL, 0);
|
||||||
|
|
||||||
// main loop
|
// main loop
|
||||||
while (true) {
|
while (true) {
|
||||||
debug_context_reset();
|
debug_context_reset();
|
||||||
|
|
@ -611,6 +617,7 @@ int main(int argc, char *argv[]) {
|
||||||
discord_update();
|
discord_update();
|
||||||
#endif
|
#endif
|
||||||
mumble_update();
|
mumble_update();
|
||||||
|
terminal_update();
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
|
|
||||||
86
src/pc/terminal.c
Normal file
86
src/pc/terminal.c
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include "linenoise/linenoise.h"
|
||||||
|
#include "djui/djui_console.h"
|
||||||
|
#include "commands.h"
|
||||||
|
#include "pc_main.h"
|
||||||
|
#include "terminal.h"
|
||||||
|
|
||||||
|
#define TERMINAL_BUFFER_SIZE 1024
|
||||||
|
|
||||||
|
static struct linenoiseState sLinenoiseState;
|
||||||
|
static char sTerminalInput[TERMINAL_BUFFER_SIZE] = { 0 };
|
||||||
|
static bool sTerminalInitialized = false;
|
||||||
|
static bool sTerminalActive = false;
|
||||||
|
|
||||||
|
void log_to_terminal(const char* fmt, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
|
||||||
|
if (sTerminalActive) linenoiseHide(&sLinenoiseState);
|
||||||
|
|
||||||
|
vprintf(fmt, args);
|
||||||
|
|
||||||
|
if (sTerminalActive) linenoiseShow(&sLinenoiseState);
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void terminal_stop() {
|
||||||
|
if (!sTerminalInitialized) return;
|
||||||
|
linenoiseEditStop(&sLinenoiseState);
|
||||||
|
sTerminalActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void terminal_init() {
|
||||||
|
if (!isatty(STDIN_FILENO)) {
|
||||||
|
sTerminalActive = false;
|
||||||
|
sTerminalInitialized = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tcgetpgrp(STDIN_FILENO) != getpgrp()) {
|
||||||
|
sTerminalActive = false;
|
||||||
|
sTerminalInitialized = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
linenoiseEditStart(&sLinenoiseState, -1, -1, sTerminalInput, sizeof(sTerminalInput), "> ");
|
||||||
|
sTerminalInitialized = true;
|
||||||
|
sTerminalActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void terminal_update() {
|
||||||
|
if (!sTerminalInitialized) return;
|
||||||
|
struct timeval tv = {0L, 0L};
|
||||||
|
fd_set fds;
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(STDIN_FILENO, &fds);
|
||||||
|
|
||||||
|
if (select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv) <= 0) return;
|
||||||
|
|
||||||
|
char* input = linenoiseEditFeed(&sLinenoiseState);
|
||||||
|
|
||||||
|
if (input == NULL) {
|
||||||
|
linenoiseEditStop(&sLinenoiseState);
|
||||||
|
game_exit();
|
||||||
|
} else if (input != linenoiseEditMore) {
|
||||||
|
terminal_stop();
|
||||||
|
|
||||||
|
if (input[0] != '\0') {
|
||||||
|
run_command(input);
|
||||||
|
linenoiseHistoryAdd(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(input);
|
||||||
|
|
||||||
|
terminal_init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void terminal_clear() {
|
||||||
|
if (!sTerminalInitialized) return;
|
||||||
|
linenoiseClearScreen();
|
||||||
|
}
|
||||||
10
src/pc/terminal.h
Normal file
10
src/pc/terminal.h
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
#pragma once
|
||||||
|
#include "src/pc/thread.h"
|
||||||
|
|
||||||
|
extern struct ThreadHandle gTerminalThread;
|
||||||
|
|
||||||
|
void log_to_terminal(const char* fmt, ...);
|
||||||
|
//void* terminal_update(UNUSED void* dummy);
|
||||||
|
void terminal_init();
|
||||||
|
void terminal_update();
|
||||||
|
void terminal_clear();
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include "pc/djui/djui.h"
|
#include "pc/djui/djui.h"
|
||||||
#include "pc/network/version.h"
|
#include "pc/network/version.h"
|
||||||
#include "pc/loading.h"
|
#include "pc/loading.h"
|
||||||
|
#include "pc/debuglog.h"
|
||||||
|
|
||||||
#define URL "https://raw.githubusercontent.com/coop-deluxe/sm64coopdx/refs/heads/main/src/pc/network/version.h"
|
#define URL "https://raw.githubusercontent.com/coop-deluxe/sm64coopdx/refs/heads/main/src/pc/network/version.h"
|
||||||
#define VERSION_IDENTIFIER "#define SM64COOPDX_VERSION \""
|
#define VERSION_IDENTIFIER "#define SM64COOPDX_VERSION \""
|
||||||
|
|
@ -73,7 +74,7 @@ void get_version_remote(void) {
|
||||||
// initialize WinINet
|
// initialize WinINet
|
||||||
HINTERNET hInternet = InternetOpenA("sm64coopdx", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
|
HINTERNET hInternet = InternetOpenA("sm64coopdx", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
|
||||||
if (!hInternet) {
|
if (!hInternet) {
|
||||||
printf("Failed to check for updates!\n");
|
LOG_ERROR("Failed to check for updates!");
|
||||||
InternetCloseHandle(hInternet);
|
InternetCloseHandle(hInternet);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -81,7 +82,7 @@ void get_version_remote(void) {
|
||||||
// open the URL
|
// open the URL
|
||||||
HINTERNET hUrl = InternetOpenUrlA(hInternet, URL, NULL, 0, INTERNET_FLAG_RELOAD, 0);
|
HINTERNET hUrl = InternetOpenUrlA(hInternet, URL, NULL, 0, INTERNET_FLAG_RELOAD, 0);
|
||||||
if (!hUrl) {
|
if (!hUrl) {
|
||||||
printf("Failed to check for updates!\n");
|
LOG_ERROR("Failed to check for updates!");
|
||||||
InternetCloseHandle(hInternet);
|
InternetCloseHandle(hInternet);
|
||||||
InternetCloseHandle(hUrl);
|
InternetCloseHandle(hUrl);
|
||||||
return;
|
return;
|
||||||
|
|
@ -95,7 +96,7 @@ void get_version_remote(void) {
|
||||||
// read data from the URL, making room in the buffer for the null-terminator
|
// read data from the URL, making room in the buffer for the null-terminator
|
||||||
DWORD bytesRead;
|
DWORD bytesRead;
|
||||||
if (!InternetReadFile(hUrl, buffer, sizeof(buffer) - 1, &bytesRead)) {
|
if (!InternetReadFile(hUrl, buffer, sizeof(buffer) - 1, &bytesRead)) {
|
||||||
printf("Failed to check for updates!\n");
|
LOG_ERROR("Failed to check for updates!");
|
||||||
InternetCloseHandle(hInternet);
|
InternetCloseHandle(hInternet);
|
||||||
InternetCloseHandle(hUrl);
|
InternetCloseHandle(hUrl);
|
||||||
return;
|
return;
|
||||||
|
|
@ -112,7 +113,7 @@ void get_version_remote(void) {
|
||||||
// initialize libcurl
|
// initialize libcurl
|
||||||
CURL *curl = curl_easy_init();
|
CURL *curl = curl_easy_init();
|
||||||
if (!curl || curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
|
if (!curl || curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
|
||||||
printf("Failed to check for updates!\n");
|
LOG_ERROR("Failed to check for updates!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -126,7 +127,7 @@ void get_version_remote(void) {
|
||||||
// perform the request
|
// perform the request
|
||||||
CURLcode res = curl_easy_perform(curl);
|
CURLcode res = curl_easy_perform(curl);
|
||||||
if (res != CURLE_OK) {
|
if (res != CURLE_OK) {
|
||||||
printf("Failed to check for updates!\n");
|
LOG_ERROR("Failed to check for updates!");
|
||||||
curl_easy_cleanup(curl);
|
curl_easy_cleanup(curl);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue