From bed036bcfb0610bcc25bc25a328b43c3a893c8a9 Mon Sep 17 00:00:00 2001 From: MysterD Date: Sun, 6 Sep 2020 10:31:41 -0700 Subject: [PATCH] Added coop settings to saved config file Saves and loads last join IP/port attempt Made host's port configurable in config file Made host's save slot configurable in config file Made host's player interaction setting configurable in config file Indicated when the client was trying to connect on the join menu. Fixed join menu display error where the port would disappear --- src/game/interaction.c | 6 +-- src/menu/file_select.c | 53 +++++++++++++++++++------ src/pc/cliopts.c | 4 +- src/pc/cliopts.h | 2 +- src/pc/configfile.c | 25 +++++++++++- src/pc/configfile.h | 8 ++++ src/pc/controller/controller_keyboard.c | 10 ++--- src/pc/controller/controller_keyboard.h | 2 +- src/pc/network/network.c | 18 ++++++--- src/pc/network/network.h | 3 +- 10 files changed, 97 insertions(+), 34 deletions(-) diff --git a/src/game/interaction.c b/src/game/interaction.c index a16f6d59b..2404a48a0 100644 --- a/src/game/interaction.c +++ b/src/game/interaction.c @@ -635,7 +635,7 @@ u32 determine_knockback_action(struct MarioState *m, UNUSED s32 arg) { m->forwardVel = mag; if (sign > 0 && terrainIndex == 1) { mag *= -1.0f; } m->vel[0] = mag * sins(angleToObject); - m->vel[1] = abs(mag); + m->vel[1] = (mag < 0) ? -mag : mag; m->vel[2] = mag * coss(angleToObject); } @@ -1150,14 +1150,14 @@ static u8 resolve_player_collision(struct MarioState* m, struct MarioState* m2) f32 marioRelY = localTorso[1] - remoteTorso[1]; if (marioRelY < 0) { marioRelY = -marioRelY; } - if (marioRelY >= extentY) { return; } + if (marioRelY >= extentY) { return FALSE; } f32 marioRelX = localTorso[0] - remoteTorso[0]; f32 marioRelZ = localTorso[2] - remoteTorso[2]; f32 marioDist = sqrtf(sqr(marioRelX) + sqr(marioRelZ)); - if (marioDist >= radius) { return; } + if (marioDist >= radius) { return FALSE; } // bounce u32 interaction = determine_interaction(m, m2->marioObj); diff --git a/src/menu/file_select.c b/src/menu/file_select.c index 234b20025..3c947331a 100644 --- a/src/menu/file_select.c +++ b/src/menu/file_select.c @@ -22,8 +22,6 @@ #include "text_strings.h" #include "game/ingame_menu.h" -#include "pc/controller/controller_keyboard.h" -#include "pc/network/network.h" #include "eu_translation.h" #ifdef VERSION_EU @@ -31,6 +29,11 @@ #define LANGUAGE_FUNCTION sLanguageMode #endif +#include +#include "pc/configfile.h" +#include "pc/controller/controller_keyboard.h" +#include "pc/network/network.h" + /** * @file file_select.c * This file implements how the file select and it's menus render and function. @@ -404,8 +407,12 @@ void join_server_as_client(void) { char delims[] = { ' ' }; + // copy input + char buffer[MAX_TEXT_INPUT] = { 0 }; + strncpy(buffer, gTextInput, MAX_TEXT_INPUT); + char* text = buffer; + // trim whitespace - char* text = textInput; while (*text == ' ') { text++; } // grab IP @@ -414,16 +421,23 @@ void join_server_as_client(void) { exit_join_to_network_menu(); return; } + strncpy(configJoinIp, ip, MAX_CONFIG_STRING); // grab port char* port = strtok(NULL, delims); - if (port != NULL && atoi(port) == 0) { - exit_join_to_network_menu(); - return; + if (port != NULL) { + unsigned int intPort = atoi(port); + if (intPort == 0) { + exit_join_to_network_menu(); + return; + } + configJoinPort = intPort; + } else { + configJoinPort = DEFAULT_PORT; } keyboard_stop_text_input(); - network_init(NT_CLIENT, textInput, port); + network_init(NT_CLIENT, configJoinIp, configJoinPort); } void joined_server_as_client(s16 fileIndex) { @@ -467,7 +481,16 @@ void check_network_mode_menu_clicked_buttons(struct Object* networkModeButton) { play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs); sMainMenuButtons[buttonID]->oMenuButtonState = MENU_BUTTON_STATE_GROWING; sSelectedButtonID = buttonID; + + // start input keyboard_start_text_input(TIM_IP, keyboard_exit_join_to_network_menu, join_server_as_client); + + // fill in config ip/port + static u8 openedJoinMenu = FALSE; + if (!openedJoinMenu && strlen(configJoinIp) > 0) { + if (configJoinPort == 0) { configJoinPort = DEFAULT_PORT; } + sprintf(gTextInput, "%s %d", configJoinIp, configJoinPort); + } } sCurrentMenuLevel = MENU_LAYER_SUBMENU; @@ -494,8 +517,8 @@ void print_network_mode_menu_strings(void) { gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); -#define TEXT_HOST 0x11,0x18,0x1C,0x1D,0xFF -#define TEXT_JOIN 0x13,0x18,0x12,0x17,0xFF + #define TEXT_HOST 0x11,0x18,0x1C,0x1D,0xFF + #define TEXT_JOIN 0x13,0x18,0x12,0x17,0xFF static unsigned char textNetworkModes[][5] = { { TEXT_HOST }, { TEXT_JOIN } }; // Print network mode names @@ -535,9 +558,12 @@ void print_join_mode_menu_strings(void) { // Print level name print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (12 * 0), "Type or paste the host's IP."); - print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (12 * 2), textInput); + print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (12 * 2), gTextInput); - if (strlen(textInput) > 0) { + // Print status + if (networkType == NT_CLIENT) { + print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (12 * 14), "Connecting..."); + } else if (strlen(gTextInput) > 0) { print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (12 * 14), "Press (ENTER) to join."); } @@ -1304,7 +1330,8 @@ void check_sound_mode_menu_clicked_buttons(struct Object *soundModeButton) { void load_main_menu_save_file(struct Object *fileButton, s32 fileNum) { if (fileButton->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN) { sSelectedFileNum = fileNum; - network_init(NT_SERVER, "", NETWORK_DEFAULT_PORT); + configHostSaveSlot = fileNum; + network_init(NT_SERVER, "", configHostPort); } } @@ -3092,7 +3119,7 @@ s32 lvl_init_menu_values_and_cursor_pos(UNUSED s32 arg, UNUSED s32 unused) { // immediately jump in if (networkType == NT_SERVER) { - sSelectedFileNum = 1; + sSelectedFileNum = configHostSaveSlot; } //! no return value diff --git a/src/pc/cliopts.c b/src/pc/cliopts.c index c3c7e3c55..3f20f911a 100644 --- a/src/pc/cliopts.c +++ b/src/pc/cliopts.c @@ -57,12 +57,12 @@ void parse_cli_opts(int argc, char* argv[]) { else if (strcmp(argv[i], "--server") == 0 && (i + 1) < argc) { // Host server gCLIOpts.Network = NT_SERVER; - arg_string("--server ", argv[++i], gCLIOpts.NetworkPort, PORT_MAX_LEN); + arg_uint("--server ", argv[++i], &gCLIOpts.NetworkPort); } else if (strcmp(argv[i], "--client") == 0 && (i + 2) < argc) { // Join server gCLIOpts.Network = NT_CLIENT; arg_string("--client ", argv[++i], gCLIOpts.JoinIp, IP_MAX_LEN); - arg_string("--client ", argv[++i], gCLIOpts.NetworkPort, PORT_MAX_LEN); + arg_uint("--client ", argv[++i], &gCLIOpts.NetworkPort); } else if (strcmp(argv[i], "--cheats") == 0) // Enable cheats menu Cheats.EnableCheats = true; diff --git a/src/pc/cliopts.h b/src/pc/cliopts.h index d0d300557..916e19b12 100644 --- a/src/pc/cliopts.h +++ b/src/pc/cliopts.h @@ -17,7 +17,7 @@ struct PCCLIOptions { unsigned int FullScreen; enum NetworkType Network; char JoinIp[IP_MAX_LEN]; - char NetworkPort[PORT_MAX_LEN]; + unsigned int NetworkPort; unsigned int PoolSize; char ConfigFile[SYS_MAX_PATH]; char SavePath[SYS_MAX_PATH]; diff --git a/src/pc/configfile.c b/src/pc/configfile.c index 4b41760a4..e04e15dc6 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -21,6 +21,7 @@ enum ConfigOptionType { CONFIG_TYPE_UINT, CONFIG_TYPE_FLOAT, CONFIG_TYPE_BIND, + CONFIG_TYPE_STRING, }; struct ConfigOption { @@ -29,7 +30,8 @@ struct ConfigOption { union { bool *boolValue; unsigned int *uintValue; - float *floatValue; + float* floatValue; + char* stringValue; }; }; @@ -83,7 +85,7 @@ unsigned int configCameraAggr = 0; unsigned int configCameraPan = 0; unsigned int configCameraDegrade = 50; // 0 - 100% bool configCameraInvertX = false; -bool configCameraInvertY = false; +bool configCameraInvertY = true; bool configEnableCamera = true; bool configCameraAnalog = true; bool configCameraMouse = false; @@ -93,6 +95,12 @@ bool configHUD = true; #ifdef DISCORDRPC bool configDiscordRPC = true; #endif +// coop-specific +char configJoinIp[MAX_CONFIG_STRING] = ""; +unsigned int configJoinPort = DEFAULT_PORT; +unsigned int configHostPort = DEFAULT_PORT; +unsigned int configHostSaveSlot = 1; +unsigned int configPlayerInteraction = 1; static const struct ConfigOption options[] = { {.name = "fullscreen", .type = CONFIG_TYPE_BOOL, .boolValue = &configWindow.fullscreen}, @@ -141,6 +149,12 @@ static const struct ConfigOption options[] = { #ifdef DISCORDRPC {.name = "discordrpc_enable", .type = CONFIG_TYPE_BOOL, .boolValue = &configDiscordRPC}, #endif + // coop-specific + {.name = "coop_join_ip", .type = CONFIG_TYPE_STRING, .stringValue = (char*)&configJoinIp}, + {.name = "coop_join_port", .type = CONFIG_TYPE_UINT , .uintValue = &configJoinPort}, + {.name = "coop_host_port", .type = CONFIG_TYPE_UINT , .uintValue = &configHostPort}, + {.name = "coop_host_save_slot", .type = CONFIG_TYPE_UINT , .uintValue = &configHostSaveSlot}, + {.name = "coop_player_interaction", .type = CONFIG_TYPE_UINT , .uintValue = &configPlayerInteraction}, }; // Reads an entire line from a file (excluding the newline character) and returns an allocated string @@ -281,6 +295,10 @@ void configfile_load(const char *filename) { case CONFIG_TYPE_FLOAT: sscanf(tokens[1], "%f", option->floatValue); break; + case CONFIG_TYPE_STRING: + memset(option->stringValue, '\0', MAX_CONFIG_STRING); + strncpy(option->stringValue, tokens[1], MAX_CONFIG_STRING); + break; default: assert(0); // bad type } @@ -328,6 +346,9 @@ void configfile_save(const char *filename) { fprintf(file, "%04x ", option->uintValue[i]); fprintf(file, "\n"); break; + case CONFIG_TYPE_STRING: + fprintf(file, "%s %s\n", option->name, option->stringValue); + break; default: assert(0); // unknown type } diff --git a/src/pc/configfile.h b/src/pc/configfile.h index b92ae7bea..b5f30e7a7 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -7,6 +7,9 @@ #define MAX_BINDS 3 #define MAX_VOLUME 127 +#define MAX_CONFIG_STRING 64 + +#define DEFAULT_PORT 7777 typedef struct { unsigned int x, y, w, h; @@ -59,6 +62,11 @@ extern bool configSkipIntro; #ifdef DISCORDRPC extern bool configDiscordRPC; #endif +extern char configJoinIp[]; +extern unsigned int configJoinPort; +extern unsigned int configHostPort; +extern unsigned int configHostSaveSlot; +extern unsigned int configPlayerInteraction; void configfile_load(const char *filename); void configfile_save(const char *filename); diff --git a/src/pc/controller/controller_keyboard.c b/src/pc/controller/controller_keyboard.c index 1cc5d646c..08d0676c0 100644 --- a/src/pc/controller/controller_keyboard.c +++ b/src/pc/controller/controller_keyboard.c @@ -29,7 +29,7 @@ static int num_keybinds = 0; static u32 keyboard_lastkey = VK_INVALID; -char textInput[MAX_TEXT_INPUT]; +char gTextInput[MAX_TEXT_INPUT]; static bool inTextInput = false; u8 held_ctrl, held_shift, held_alt; @@ -77,7 +77,7 @@ bool keyboard_on_key_down(int scancode) { // perform text-input-specific actions switch (scancode) { case SCANCODE_BACKSPACE: - textInput[max(strlen(textInput) - 1, 0)] = '\0'; + gTextInput[max(strlen(gTextInput) - 1, 0)] = '\0'; break; case SCANCODE_ESCAPE: if (textInputOnEscape != NULL) { textInputOnEscape(); } @@ -129,7 +129,7 @@ char* keyboard_start_text_input(enum TextInputMode inInputMode, void (*onEscape) textInputOnEnter = onEnter; // clear buffer - for (int i = 0; i < MAX_TEXT_INPUT; i++) { textInput[i] = '\0'; } + for (int i = 0; i < MAX_TEXT_INPUT; i++) { gTextInput[i] = '\0'; } // clear held-value for modifiers held_ctrl = 0; @@ -182,14 +182,14 @@ void keyboard_on_text_input(char* text) { // sanity check input if (text == NULL) { return; } - int i = strlen(textInput); + int i = strlen(gTextInput); while (*text != '\0') { // make sure we don't overrun the buffer if (i >= MAX_TEXT_INPUT) { break; } // copy over character if we're allowed to input it if (keyboard_allow_character_input(*text)) { - textInput[i++] = *text; + gTextInput[i++] = *text; } text++; diff --git a/src/pc/controller/controller_keyboard.h b/src/pc/controller/controller_keyboard.h index f148ab384..43213630c 100644 --- a/src/pc/controller/controller_keyboard.h +++ b/src/pc/controller/controller_keyboard.h @@ -11,7 +11,7 @@ extern "C" { #endif #define MAX_TEXT_INPUT 256 -extern char textInput[]; +extern char gTextInput[]; enum TextInputMode { TIM_IP, diff --git a/src/pc/network/network.c b/src/pc/network/network.c index 52ac3bb00..1086c14f6 100644 --- a/src/pc/network/network.c +++ b/src/pc/network/network.c @@ -3,6 +3,7 @@ #include "object_fields.h" #include "object_constants.h" #include "socket/socket.h" +#include "pc/configfile.h" enum NetworkType networkType; static SOCKET gSocket; @@ -16,12 +17,19 @@ struct ServerSettings gServerSettings = { .playerInteractions = PLAYER_INTERACTIONS_SOLID, }; -void network_init(enum NetworkType inNetworkType, char* ip, char* port) { +void network_init(enum NetworkType inNetworkType, char* ip, unsigned int port) { networkType = inNetworkType; if (networkType == NT_NONE) { return; } - if (port == NULL) { - port = NETWORK_DEFAULT_PORT; + + // sanity check port + if (port == 0) { + port = (networkType == NT_CLIENT) ? configJoinPort : configHostPort; + if (port == 0) { port = DEFAULT_PORT; } + } + + if (networkType == NT_SERVER) { + gServerSettings.playerInteractions = configPlayerInteraction; } // Create a receiver socket to receive datagrams @@ -30,12 +38,12 @@ void network_init(enum NetworkType inNetworkType, char* ip, char* port) { // Bind the socket to any address and the specified port. if (networkType == NT_SERVER) { - int rc = socket_bind(gSocket, atoi(port)); + int rc = socket_bind(gSocket, port); if (rc != NO_ERROR) { return; } } else { // Save the port to send to txAddr.sin_family = AF_INET; - txAddr.sin_port = htons(atoi(port)); + txAddr.sin_port = htons(port); txAddr.sin_addr.s_addr = inet_addr(ip); } diff --git a/src/pc/network/network.h b/src/pc/network/network.h index f0e045541..ec2f0a693 100644 --- a/src/pc/network/network.h +++ b/src/pc/network/network.h @@ -14,7 +14,6 @@ #define MAX_SYNC_OBJECT_FIELDS 64 #define PACKET_LENGTH 1024 #define NETWORKTYPESTR (networkType == NT_CLIENT ? "Client" : "Server") -#define NETWORK_DEFAULT_PORT "7777" enum PacketType { PACKET_ACK, @@ -82,7 +81,7 @@ extern bool networkLevelLoaded; extern struct ServerSettings gServerSettings; -void network_init(enum NetworkType inNetworkType, char* ip, char* port); +void network_init(enum NetworkType inNetworkType, char* ip, unsigned int port); void network_on_init_level(void); void network_on_loaded_level(void);