Added server settings: shared lives and skip intro

Adds button to the host menu to allow shared lives.
Resolves #37

Buttons are now resizeable. Use gButtonScale.<size> (large, medium, or small).
It could be argued that we don't need the small size. However, it may be beneficial for the future if the menu becomes more complex.

large is the normal default size. Or at least it was the size already being used by sm64ex-coop (0.11111111f)

Note: Buttons for changing menu's should be gButtonScale.large as the menu animation is made for large buttons. To keep consistency it's probably a good idea for buttons that transfer you to a new menu to always be set to large. As such, I didn't feel it necessary to extend this feature to these methods: bhv_menu_button_growing_from_custom and bhv_menu_button_shrinking_to_custom.

Resolves #60
This commit is contained in:
MegaMech 2020-10-16 03:58:57 -06:00 committed by GitHub
parent 1a0b3ff79d
commit e447332cec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 103 additions and 35 deletions

View file

@ -1356,7 +1356,7 @@ s32 init_level(void) {
if (gMarioState->action != ACT_UNINITIALIZED) { if (gMarioState->action != ACT_UNINITIALIZED) {
if (save_file_exists(gCurrSaveFileNum - 1)) { if (save_file_exists(gCurrSaveFileNum - 1)) {
set_mario_action(gMarioState, ACT_IDLE, 0); set_mario_action(gMarioState, ACT_IDLE, 0);
} else if (gCLIOpts.SkipIntro == 0 && configSkipIntro == 0) { } else if (gCLIOpts.SkipIntro == 0 && configSkipIntro == 0 && gServerSettings.skipIntro == 0) {
set_mario_action(gMarioState, ACT_INTRO_CUTSCENE, 0); set_mario_action(gMarioState, ACT_INTRO_CUTSCENE, 0);
val4 = 1; val4 = 1;
} }

View file

@ -391,6 +391,9 @@ void mario_set_bubbled(struct MarioState* m) {
set_mario_action(m, ACT_BUBBLED, 0); set_mario_action(m, ACT_BUBBLED, 0);
if (m->numLives != -1) { if (m->numLives != -1) {
m->numLives--; m->numLives--;
if (gServerSettings.shareLives) {
network_send_death();
}
} }
m->healCounter = 0; m->healCounter = 0;
m->hurtCounter = 31; m->hurtCounter = 31;

View file

@ -26,6 +26,7 @@
char sConnectionJoinError[128] = { 0 }; char sConnectionJoinError[128] = { 0 };
char gConnectionText[128] = { 0 }; char gConnectionText[128] = { 0 };
struct CustomMenu* sConnectMenu = NULL; struct CustomMenu* sConnectMenu = NULL;
u8 gOpenConnectMenu = FALSE; u8 gOpenConnectMenu = FALSE;
s8 sGotoGame = 0; s8 sGotoGame = 0;
@ -42,9 +43,9 @@ static void menu_main_draw_strings(void) {
static void host_menu_draw_strings(void) { static void host_menu_draw_strings(void) {
#ifdef DISCORD_SDK #ifdef DISCORD_SDK
#define HOST_MENU_MAX_ITEMS 4 #define HOST_MENU_MAX_ITEMS 6
#else #else
#define HOST_MENU_MAX_ITEMS 3 #define HOST_MENU_MAX_ITEMS 5
#endif #endif
// set up server setting strings // set up server setting strings
@ -66,23 +67,26 @@ static void host_menu_draw_strings(void) {
buttonText[2] = configStayInLevelAfterStar ? "Stay in level after star." : "Leave level after star."; buttonText[2] = configStayInLevelAfterStar ? "Stay in level after star." : "Leave level after star.";
buttonText[3] = configSkipIntro ? "Skip intro cutscene." : "Play intro cutscene.";
buttonText[4] = configShareLives ? "Share lives." : "Lives are not shared.";
#ifdef DISCORD_SDK #ifdef DISCORD_SDK
buttonText[3] = (configNetworkSystem == 0) ? "Host through Discord." : "Host direct connection."; buttonText[5] = (configNetworkSystem == 0) ? "Host through Discord." : "Host direct connection.";
#endif #endif
// display server setting strings // display server setting strings
for (int i = 0; i < HOST_MENU_MAX_ITEMS; i++) { for (int i = 0; i < HOST_MENU_MAX_ITEMS; i++) {
print_generic_ascii_string(95, 158 + -35 * i, buttonText[i]); print_generic_ascii_string(95, 173 + -29 * i, buttonText[i]);
} }
// display direct connection warning // display direct connection warning
if (configNetworkSystem != 0) { if (configNetworkSystem != 0) {
print_generic_ascii_string(0, 30, "For direct connections -");
f32 red = (f32)fabs(sin(gGlobalTimer / 20.0f)); f32 red = (f32)fabs(sin(gGlobalTimer / 20.0f));
gDPSetEnvColor(gDisplayListHead++, 222, 222 * red, 222 * red, gMenuStringAlpha); gDPSetEnvColor(gDisplayListHead++, 222, 222 * red, 222 * red, gMenuStringAlpha);
char warning[128]; char warning[128];
snprintf(warning, 127, "You must forward port '%d' in your router or use Hamachi.", configHostPort); snprintf(warning, 127, "Port forward '%d' in network router settings or use Hamachi.", configHostPort);
print_generic_ascii_string(0, 15, warning); print_generic_ascii_string(0, 5, warning);
} else if ((configNetworkSystem == 0) && gDiscordFailed) { } else if ((configNetworkSystem == 0) && gDiscordFailed) {
f32 red = (f32)fabs(sin(gGlobalTimer / 20.0f)); f32 red = (f32)fabs(sin(gGlobalTimer / 20.0f));
gDPSetEnvColor(gDisplayListHead++, 222, 222 * red, 222 * red, gMenuStringAlpha); gDPSetEnvColor(gDisplayListHead++, 222, 222 * red, 222 * red, gMenuStringAlpha);
@ -134,6 +138,14 @@ static void host_menu_setting_stay_in_level(void) {
configStayInLevelAfterStar = (configStayInLevelAfterStar == 0) ? 1 : 0; configStayInLevelAfterStar = (configStayInLevelAfterStar == 0) ? 1 : 0;
} }
static void host_menu_setting_skip_intro(void) {
configSkipIntro = (configSkipIntro == 1) ? 0 : 1;
}
static void host_menu_setting_share_lives(void) {
configShareLives = (configShareLives == 0) ? 1 : 0;
}
#ifdef DISCORD_SDK #ifdef DISCORD_SDK
static void join_menu_draw_strings(void) { static void join_menu_draw_strings(void) {
print_generic_ascii_string(30, 155, "Accept a Discord game invite in order to join."); print_generic_ascii_string(30, 155, "Accept a Discord game invite in order to join.");
@ -217,7 +229,7 @@ static void connect_menu_on_click(void) {
// fill in our last attempt // fill in our last attempt
if (configJoinPort == 0 || configJoinPort > 65535) { configJoinPort = DEFAULT_PORT; } if (configJoinPort == 0 || configJoinPort > 65535) { configJoinPort = DEFAULT_PORT; }
// only print custom port // only print custom port
if (configJoinPort == DEFAULT_PORT) { if (configJoinPort == DEFAULT_PORT) {
sprintf(gTextInput, "%s", configJoinIp); sprintf(gTextInput, "%s", configJoinIp);
@ -243,29 +255,32 @@ void custom_menu_init(struct CustomMenu* head) {
head->draw_strings = menu_main_draw_strings; head->draw_strings = menu_main_draw_strings;
// create sub menus and buttons // create sub menus and buttons
struct CustomMenu* hostMenu = custom_menu_create(head, "HOST", -266, 0); struct CustomMenu* hostMenu = custom_menu_create(head, "HOST", -266, 0, gButtonScale.large);
hostMenu->headerY = 30;
hostMenu->draw_strings = host_menu_draw_strings; hostMenu->draw_strings = host_menu_draw_strings;
custom_menu_create_button(hostMenu, "CANCEL", 700, -400 + (250 * 3), SOUND_MENU_CAMERA_ZOOM_OUT, custom_menu_close); custom_menu_create_button(hostMenu, "CANCEL", 700, -196 + (210 * 3), gButtonScale.large, SOUND_MENU_CAMERA_ZOOM_OUT, custom_menu_close);
custom_menu_create_button(hostMenu, "HOST", 700, -400, SOUND_MENU_CAMERA_ZOOM_IN, host_menu_do_host); custom_menu_create_button(hostMenu, "HOST", 700, -220, gButtonScale.large, SOUND_MENU_CAMERA_ZOOM_IN, host_menu_do_host);
custom_menu_create_button(hostMenu, "", -700, -400 + (250 * 3), SOUND_ACTION_BONK, host_menu_setting_interaction); custom_menu_create_button(hostMenu, "", -700, -180 + (210 * 3), gButtonScale.medium, SOUND_ACTION_BONK, host_menu_setting_interaction);
custom_menu_create_button(hostMenu, "", -700, -400 + (250 * 2), SOUND_ACTION_BONK, host_menu_setting_knockback); custom_menu_create_button(hostMenu, "", -700, -180 + (210 * 2), gButtonScale.medium, SOUND_ACTION_BONK, host_menu_setting_knockback);
custom_menu_create_button(hostMenu, "", -700, -400 + (250 * 1), SOUND_ACTION_BONK, host_menu_setting_stay_in_level); custom_menu_create_button(hostMenu, "", -700, -180 + (210 * 1), gButtonScale.medium, SOUND_ACTION_BONK, host_menu_setting_stay_in_level);
custom_menu_create_button(hostMenu, "", -700, -180 + (210 * 0), gButtonScale.medium, SOUND_ACTION_BONK, host_menu_setting_skip_intro);
custom_menu_create_button(hostMenu, "", -700, -180 + (210 * -1), gButtonScale.medium, SOUND_ACTION_BONK, host_menu_setting_share_lives);
#ifdef DISCORD_SDK #ifdef DISCORD_SDK
custom_menu_create_button(hostMenu, "", -700, -400 + (250 * 0), SOUND_ACTION_BONK, host_menu_setting_network_system); custom_menu_create_button(hostMenu, "", -700, -180 + (210 * -2), gButtonScale.medium, SOUND_ACTION_BONK, host_menu_setting_network_system);
#endif #endif
#ifdef DISCORD_SDK #ifdef DISCORD_SDK
struct CustomMenu* joinMenu = custom_menu_create(head, "JOIN", 266, 0); struct CustomMenu* joinMenu = custom_menu_create(head, "JOIN", 266, 0, gButtonScale.large);
custom_menu_create_button(joinMenu, "CANCEL", -266, -320, SOUND_MENU_CAMERA_ZOOM_OUT, custom_menu_close); custom_menu_create_button(joinMenu, "CANCEL", -266, -320, gButtonScale.large, SOUND_MENU_CAMERA_ZOOM_OUT, custom_menu_close);
joinMenu->draw_strings = join_menu_draw_strings; joinMenu->draw_strings = join_menu_draw_strings;
struct CustomMenu* connectMenu = custom_menu_create(joinMenu, "CONNECT", 266, -320); struct CustomMenu* connectMenu = custom_menu_create(joinMenu, "CONNECT", 266, -320, gButtonScale.large);
#else #else
struct CustomMenu* connectMenu = custom_menu_create(head, "CONNECT", 266, 0); struct CustomMenu* connectMenu = custom_menu_create(head, "CONNECT", 266, 0, gButtonScale.large);
#endif #endif
connectMenu->me->on_click = connect_menu_on_click; connectMenu->me->on_click = connect_menu_on_click;
connectMenu->on_close = connect_menu_on_close; connectMenu->on_close = connect_menu_on_close;
connectMenu->draw_strings = connect_menu_draw_strings; connectMenu->draw_strings = connect_menu_draw_strings;
custom_menu_create_button(connectMenu, "CANCEL", 0, -400, SOUND_MENU_CAMERA_ZOOM_OUT, custom_menu_close); custom_menu_create_button(connectMenu, "CANCEL", 0, -400, gButtonScale.large, SOUND_MENU_CAMERA_ZOOM_OUT, custom_menu_close);
sConnectMenu = connectMenu; sConnectMenu = connectMenu;
} }

View file

@ -20,6 +20,11 @@
static struct CustomMenu* sHead = NULL; static struct CustomMenu* sHead = NULL;
static struct CustomMenu* sCurrentMenu = NULL; static struct CustomMenu* sCurrentMenu = NULL;
static struct CustomMenu* sLastMenu = NULL; static struct CustomMenu* sLastMenu = NULL;
struct CustomMenuButtonScale gButtonScale = {
.small = 0.08111111f,
.medium = 0.09511111f,
.large = 0.11111111f,
};
u8 gMenuStringAlpha = 255; u8 gMenuStringAlpha = 255;
@ -29,7 +34,7 @@ struct ErrorDialog {
}; };
static struct ErrorDialog* sErrorDialog = NULL; static struct ErrorDialog* sErrorDialog = NULL;
struct CustomMenuButton* custom_menu_create_button(struct CustomMenu* parent, char* label, u16 x, u16 y, s32 clickSound, void (*on_click)(void)) { struct CustomMenuButton* custom_menu_create_button(struct CustomMenu* parent, char* label, u16 x, u16 y, f32 scale, s32 clickSound, void (*on_click)(void)) {
struct CustomMenuButton* button = calloc(1, sizeof(struct CustomMenuButton)); struct CustomMenuButton* button = calloc(1, sizeof(struct CustomMenuButton));
if (parent->buttons == NULL) { if (parent->buttons == NULL) {
parent->buttons = button; parent->buttons = button;
@ -45,7 +50,8 @@ struct CustomMenuButton* custom_menu_create_button(struct CustomMenu* parent, ch
button->clickSound = clickSound; button->clickSound = clickSound;
struct Object* obj = spawn_object_rel_with_rot(parent->me->object, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, x * -1, y, -1, 0, 0x8000, 0); struct Object* obj = spawn_object_rel_with_rot(parent->me->object, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, x * -1, y, -1, 0, 0x8000, 0);
obj->oMenuButtonScale = 0.11111111f;
obj->oMenuButtonScale = scale;
obj->oFaceAngleRoll = 0; obj->oFaceAngleRoll = 0;
obj->oMenuButtonTimer = 0; obj->oMenuButtonTimer = 0;
obj->oMenuButtonOrigPosX = obj->oParentRelativePosX; obj->oMenuButtonOrigPosX = obj->oParentRelativePosX;
@ -57,8 +63,8 @@ struct CustomMenuButton* custom_menu_create_button(struct CustomMenu* parent, ch
return button; return button;
} }
struct CustomMenu* custom_menu_create(struct CustomMenu* parent, char* label, u16 x, u16 y) { struct CustomMenu* custom_menu_create(struct CustomMenu* parent, char* label, u16 x, u16 y, f32 scale) {
struct CustomMenuButton* button = custom_menu_create_button(parent, label, x, y, SOUND_MENU_CAMERA_ZOOM_IN, NULL); struct CustomMenuButton* button = custom_menu_create_button(parent, label, x, y, scale, SOUND_MENU_CAMERA_ZOOM_IN, NULL);
struct CustomMenu* menu = calloc(1, sizeof(struct CustomMenu)); struct CustomMenu* menu = calloc(1, sizeof(struct CustomMenu));
menu->parent = parent; menu->parent = parent;
menu->depth = parent->depth + 1; menu->depth = parent->depth + 1;
@ -183,13 +189,15 @@ void custom_menu_close_system(void) {
static s32 cursor_inside_button(struct CustomMenuButton* button, f32 cursorX, f32 cursorY) { static s32 cursor_inside_button(struct CustomMenuButton* button, f32 cursorX, f32 cursorY) {
f32 x = button->object->oParentRelativePosX; f32 x = button->object->oParentRelativePosX;
f32 y = button->object->oParentRelativePosY; f32 y = button->object->oParentRelativePosY;
f32 scale = button->object->oMenuButtonScale;
x *= -0.137f; x *= -0.137f;
y *= 0.137f; y *= 0.137f;
s16 maxX = x + 25.0f; s16 maxX = x + scale * 185.0f;
s16 minX = x - 25.0f; s16 minX = x - scale * 185.0f;
s16 maxY = y + 21.0f; s16 maxY = y + scale * 185.0f;
s16 minY = y - 21.0f; s16 minY = y - scale * 101.0f;
return (cursorX < maxX && minX < cursorX && cursorY < maxY && minY < cursorY); return (cursorX < maxX && minX < cursorX && cursorY < maxY && minY < cursorY);
} }
@ -236,7 +244,7 @@ void custom_menu_cursor_click(f32 cursorX, f32 cursorY) {
} }
if (didSomething) { break; } if (didSomething) { break; }
} }
button = button->next; button = button->next;
} }
} }
@ -254,7 +262,7 @@ void custom_menu_print_strings(void) {
// figure out alpha // figure out alpha
struct Object* curObj = sCurrentMenu->me->object; struct Object* curObj = sCurrentMenu->me->object;
struct Object* lastObj = (sLastMenu != NULL) ? sLastMenu->me->object : NULL; struct Object* lastObj = (sLastMenu != NULL) ? sLastMenu->me->object : NULL;
if (curObj != NULL && lastObj != NULL) { if (curObj != NULL && lastObj != NULL) {
if (curObj->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN && lastObj->oMenuButtonState != MENU_BUTTON_STATE_SHRINKING) { if (curObj->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN && lastObj->oMenuButtonState != MENU_BUTTON_STATE_SHRINKING) {
if (gMenuStringAlpha < 250) { if (gMenuStringAlpha < 250) {
@ -398,4 +406,4 @@ void custom_menu_error(char* message) {
item = item->next; item = item->next;
} }
} }
} }

View file

@ -21,11 +21,18 @@ struct CustomMenu {
void (*on_close)(void); void (*on_close)(void);
}; };
struct CustomMenuButtonScale {
f32 small;
f32 medium;
f32 large;
};
extern struct CustomMenuButtonScale gButtonScale;
extern u8 gMenuStringAlpha; extern u8 gMenuStringAlpha;
void custom_menu_system_init(void); void custom_menu_system_init(void);
struct CustomMenu* custom_menu_create(struct CustomMenu* parent, char* label, u16 x, u16 y); struct CustomMenu* custom_menu_create(struct CustomMenu* parent, char* label, u16 x, u16 y, f32 scale);
struct CustomMenuButton* custom_menu_create_button(struct CustomMenu* parent, char* label, u16 x, u16 y, s32 clickSound, void (*on_click)(void)); struct CustomMenuButton* custom_menu_create_button(struct CustomMenu* parent, char* label, u16 x, u16 y, f32 scale, s32 clickSound, void (*on_click)(void));
void custom_menu_system_loop(void); void custom_menu_system_loop(void);
void custom_menu_print_strings(void); void custom_menu_print_strings(void);

View file

@ -92,6 +92,7 @@ bool configCameraAnalog = true;
bool configCameraMouse = false; bool configCameraMouse = false;
#endif #endif
bool configSkipIntro = 0; bool configSkipIntro = 0;
bool configShareLives = 0;
bool configHUD = true; bool configHUD = true;
#ifdef DISCORDRPC #ifdef DISCORDRPC
bool configDiscordRPC = true; bool configDiscordRPC = true;
@ -151,6 +152,7 @@ static const struct ConfigOption options[] = {
{.name = "bettercam_degrade", .type = CONFIG_TYPE_UINT, .uintValue = &configCameraDegrade}, {.name = "bettercam_degrade", .type = CONFIG_TYPE_UINT, .uintValue = &configCameraDegrade},
#endif #endif
{.name = "skip_intro", .type = CONFIG_TYPE_BOOL, .boolValue = &configSkipIntro}, {.name = "skip_intro", .type = CONFIG_TYPE_BOOL, .boolValue = &configSkipIntro},
{.name = "share_lives", .type = CONFIG_TYPE_BOOL, .boolValue = &configShareLives},
#ifdef DISCORDRPC #ifdef DISCORDRPC
{.name = "discordrpc_enable", .type = CONFIG_TYPE_BOOL, .boolValue = &configDiscordRPC}, {.name = "discordrpc_enable", .type = CONFIG_TYPE_BOOL, .boolValue = &configDiscordRPC},
#endif #endif

View file

@ -60,6 +60,7 @@ extern bool configCameraAnalog;
#endif #endif
extern bool configHUD; extern bool configHUD;
extern bool configSkipIntro; extern bool configSkipIntro;
extern bool configShareLives;
#ifdef DISCORDRPC #ifdef DISCORDRPC
extern bool configDiscordRPC; extern bool configDiscordRPC;
#endif #endif

View file

@ -28,6 +28,8 @@ struct StringLinkedList gRegisteredMods = { 0 };
struct ServerSettings gServerSettings = { struct ServerSettings gServerSettings = {
.playerInteractions = PLAYER_INTERACTIONS_SOLID, .playerInteractions = PLAYER_INTERACTIONS_SOLID,
.playerKnockbackStrength = 25, .playerKnockbackStrength = 25,
.skipIntro = 0,
.shareLives = 0,
}; };
void network_set_system(enum NetworkSystemType nsType) { void network_set_system(enum NetworkSystemType nsType) {
@ -51,6 +53,8 @@ bool network_init(enum NetworkType inNetworkType) {
gServerSettings.playerInteractions = configPlayerInteraction; gServerSettings.playerInteractions = configPlayerInteraction;
gServerSettings.playerKnockbackStrength = configPlayerKnockbackStrength; gServerSettings.playerKnockbackStrength = configPlayerKnockbackStrength;
gServerSettings.stayInLevelAfterStar = configStayInLevelAfterStar; gServerSettings.stayInLevelAfterStar = configStayInLevelAfterStar;
gServerSettings.skipIntro = configSkipIntro;
gServerSettings.shareLives = configShareLives;
// initialize the network system // initialize the network system
int rc = gNetworkSystem->initialize(inNetworkType); int rc = gNetworkSystem->initialize(inNetworkType);

View file

@ -74,6 +74,8 @@ struct ServerSettings {
enum PlayerInteractions playerInteractions; enum PlayerInteractions playerInteractions;
u8 playerKnockbackStrength; u8 playerKnockbackStrength;
u8 stayInLevelAfterStar; u8 stayInLevelAfterStar;
u8 skipIntro;
u8 shareLives;
}; };
// Networking-specific externs // Networking-specific externs

View file

@ -55,6 +55,7 @@ void packet_receive(struct Packet* p) {
case PACKET_SAVE_FILE: network_receive_save_file(p); break; case PACKET_SAVE_FILE: network_receive_save_file(p); break;
case PACKET_INSTANT_WARP: network_receive_instant_warp(p); break; case PACKET_INSTANT_WARP: network_receive_instant_warp(p); break;
case PACKET_NETWORK_PLAYERS: network_receive_network_players(p); break; case PACKET_NETWORK_PLAYERS: network_receive_network_players(p); break;
case PACKET_DEATH: network_receive_death(p); break;
/// ///
case PACKET_CUSTOM: network_receive_custom(p); break; case PACKET_CUSTOM: network_receive_custom(p); break;
default: LOG_ERROR("received unknown packet: %d", p->buffer[0]); default: LOG_ERROR("received unknown packet: %d", p->buffer[0]);
@ -73,4 +74,4 @@ void packet_receive(struct Packet* p) {
} }
} }
} }
} }

View file

@ -32,6 +32,7 @@ enum PacketType {
PACKET_SAVE_FILE, PACKET_SAVE_FILE,
PACKET_INSTANT_WARP, PACKET_INSTANT_WARP,
PACKET_NETWORK_PLAYERS, PACKET_NETWORK_PLAYERS,
PACKET_DEATH,
/// ///
PACKET_CUSTOM = 255, PACKET_CUSTOM = 255,
}; };

View file

@ -0,0 +1,20 @@
#include <stdio.h>
#include "sm64.h"
#include "../network.h"
extern struct MarioState gMarioStates[];
void network_send_death(void) {
if (gMarioStates[0].numLives < -1) { gMarioStates[0].numLives = -1; }
struct Packet p = { 0 };
packet_init(&p, PACKET_DEATH, true, false);
packet_write(&p, &gMarioStates[0].numLives, sizeof(u8));
network_send(&p);
}
void network_receive_death(struct Packet* p) {
u8 numLives = 0;
packet_read(p, &numLives, sizeof(u8));
if (numLives < gMarioStates[0].numLives) {
gMarioStates[0].numLives = numLives;
}
}

View file

@ -61,6 +61,8 @@ void network_send_join(struct Packet* joinRequestPacket) {
packet_write(&p, &gServerSettings.playerInteractions, sizeof(u8)); packet_write(&p, &gServerSettings.playerInteractions, sizeof(u8));
packet_write(&p, &gServerSettings.playerKnockbackStrength, sizeof(u8)); packet_write(&p, &gServerSettings.playerKnockbackStrength, sizeof(u8));
packet_write(&p, &gServerSettings.stayInLevelAfterStar, sizeof(u8)); packet_write(&p, &gServerSettings.stayInLevelAfterStar, sizeof(u8));
packet_write(&p, &gServerSettings.skipIntro, sizeof(u8));
packet_write(&p, &gServerSettings.shareLives, sizeof(u8));
packet_write(&p, eeprom, sizeof(u8) * 512); packet_write(&p, eeprom, sizeof(u8) * 512);
u8 modCount = string_linked_list_count(&gRegisteredMods); u8 modCount = string_linked_list_count(&gRegisteredMods);
@ -124,6 +126,8 @@ void network_receive_join(struct Packet* p) {
packet_read(p, &gServerSettings.playerInteractions, sizeof(u8)); packet_read(p, &gServerSettings.playerInteractions, sizeof(u8));
packet_read(p, &gServerSettings.playerKnockbackStrength, sizeof(u8)); packet_read(p, &gServerSettings.playerKnockbackStrength, sizeof(u8));
packet_read(p, &gServerSettings.stayInLevelAfterStar, sizeof(u8)); packet_read(p, &gServerSettings.stayInLevelAfterStar, sizeof(u8));
packet_read(p, &gServerSettings.skipIntro, sizeof(u8));
packet_read(p, &gServerSettings.shareLives, sizeof(u8));
packet_read(p, eeprom, sizeof(u8) * 512); packet_read(p, eeprom, sizeof(u8) * 512);
packet_read(p, &modCount, sizeof(u8)); packet_read(p, &modCount, sizeof(u8));