Allow the ability to change server settings/mods while hosting

This commit is contained in:
MysterD 2023-03-29 17:36:13 -07:00
parent 2acb51b314
commit 341953390c
17 changed files with 189 additions and 24 deletions

View file

@ -185,7 +185,6 @@ const Gfx dl_font_normal_display_list[] = {
static void djui_font_normal_render_char(char c) {
extern const u8* const font_normal_chars[];
// replace undisplayable characters
//if ((u8)c < ' ' || (u8)c > ('~' + 3)) { c = '?'; }
if (!djui_font_valid_smcode(c)) { c = '?'; }
if (c == ' ') { return; }
void* fontChar = (void*)font_normal_chars[(u8)c - '!'];

View file

@ -56,14 +56,22 @@ static void djui_panel_host_do_host(struct DjuiBase* caller) {
}
configHostPort = atoi(sInputboxPort->buffer);
djui_panel_host_message_create(caller);
if (gNetworkType == NT_SERVER) {
network_rehost_begin();
} else {
djui_panel_host_message_create(caller);
}
}
void djui_panel_host_create(struct DjuiBase* caller) {
f32 bodyHeight = 32 * 4 + 64 * 4 + 16 * 5;
struct DjuiBase* defaultBase = NULL;
struct DjuiThreePanel* panel = djui_panel_menu_create(bodyHeight, "\\#ff0800\\H\\#1be700\\O\\#00b3ff\\S\\#ffef00\\T");
struct DjuiThreePanel* panel = djui_panel_menu_create(bodyHeight,
(gNetworkType == NT_SERVER)
? "\\#ff0800\\S\\#1be700\\E\\#00b3ff\\R\\#ffef00\\V\\#ff0800\\E\\#1be700\\R"
: "\\#ff0800\\H\\#1be700\\O\\#00b3ff\\S\\#ffef00\\T");
struct DjuiFlowLayout* body = (struct DjuiFlowLayout*)djui_three_panel_get_body(panel);
{
#ifdef DISCORD_SDK
@ -72,6 +80,10 @@ void djui_panel_host_create(struct DjuiBase* caller) {
djui_base_set_size_type(&selectionbox1->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&selectionbox1->base, 1.0f, 32);
djui_interactable_hook_value_change(&selectionbox1->base, djui_panel_host_network_system_change);
if (gNetworkType == NT_SERVER) {
djui_base_set_enabled(&selectionbox1->base, false);
}
#endif
struct DjuiRect* rect1 = djui_rect_create(&body->base);
@ -84,6 +96,9 @@ void djui_panel_host_create(struct DjuiBase* caller) {
djui_base_set_color(&text1->base, 200, 200, 200, 255);
djui_base_set_size(&text1->base, 0.485f, 64);
djui_base_set_alignment(&text1->base, DJUI_HALIGN_LEFT, DJUI_VALIGN_TOP);
if (gNetworkType == NT_SERVER) {
djui_base_set_enabled(&text1->base, false);
}
struct DjuiInputbox* inputbox1 = djui_inputbox_create(&rect1->base, 32);
djui_base_set_size_type(&inputbox1->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
@ -144,19 +159,22 @@ void djui_panel_host_create(struct DjuiBase* caller) {
djui_base_set_size(&rect3->base, 1.0f, 64);
djui_base_set_color(&rect3->base, 0, 0, 0, 0);
{
struct DjuiButton* button1 = djui_button_create(&rect3->base, "Back");
struct DjuiButton* button1 = djui_button_create(&rect3->base, (gNetworkType == NT_SERVER) ? "Cancel" : "Back");
djui_base_set_size_type(&button1->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&button1->base, 0.485f, 64);
djui_base_set_alignment(&button1->base, DJUI_HALIGN_LEFT, DJUI_VALIGN_TOP);
djui_button_set_style(button1, 1);
djui_interactable_hook_click(&button1->base, djui_panel_menu_back);
struct DjuiButton* button2 = djui_button_create(&rect3->base, "Host");
struct DjuiButton* button2 = djui_button_create(&rect3->base, (gNetworkType == NT_SERVER) ? "Apply" : "Host");
djui_base_set_size_type(&button2->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&button2->base, 0.485f, 64);
djui_base_set_alignment(&button2->base, DJUI_HALIGN_RIGHT, DJUI_VALIGN_TOP);
djui_interactable_hook_click(&button2->base, djui_panel_host_do_host);
defaultBase = &button2->base;
defaultBase = (gNetworkType == NT_SERVER)
? &button1->base
: &button2->base;
}
}

View file

@ -27,12 +27,13 @@ Direct connections \\#ffa0a0\\require you\\#c8c8c8\\ to configure port forwardin
Forward port '\\#d0d0ff\\%d\\#c8c8c8\\' for UDP.\
";
void djui_panel_host_message_do_host(UNUSED struct DjuiBase* caller) {
void djui_panel_do_host(void) {
stop_demo(NULL);
djui_panel_shutdown();
extern s16 gCurrSaveFileNum;
gCurrSaveFileNum = configHostSaveSlot;
update_all_mario_stars();
#ifndef DISCORD_SDK
configNetworkSystem = 1;
network_set_system(NS_SOCKET);
@ -43,17 +44,26 @@ void djui_panel_host_message_do_host(UNUSED struct DjuiBase* caller) {
network_set_system(NS_SOCKET);
}
#endif
network_init(NT_SERVER);
djui_panel_modlist_create(NULL);
fake_lvl_init_from_save_file();
extern s16 gChangeLevelTransition;
gChangeLevelTransition = gLevelValues.entryLevel;
if (gMarioState->marioObj) vec3f_copy(gMarioState->marioObj->header.gfx.cameraToObject, gGlobalSoundSource);
play_character_sound(gMarioState, CHAR_SOUND_OKEY_DOKEY);
extern void play_transition(s16 transType, s16 time, u8 red, u8 green, u8 blue);
play_transition(0x09, 0x14, 0x00, 0x00, 0x00);
}
void djui_panel_host_message_do_host(UNUSED struct DjuiBase* caller) {
network_reset_reconnect_and_rehost();
djui_panel_do_host();
}
void djui_panel_host_message_create(struct DjuiBase* caller) {
f32 warningLines = 0;
char* warningMessage = NULL;

View file

@ -149,6 +149,7 @@ void djui_panel_join_do_join(struct DjuiBase* caller) {
djui_inputbox_select_all(sInputboxIp);
return;
}
network_reset_reconnect_and_rehost();
djui_panel_join_ip_text_set_new();
network_set_system(NS_SOCKET);
network_init(NT_CLIENT);

View file

@ -16,6 +16,8 @@ void djui_panel_join_message_error(char* message) {
}
void djui_panel_join_message_cancel(struct DjuiBase* caller) {
if (network_is_reconnecting()) { return; }
network_reset_reconnect_and_rehost();
network_shutdown(true, false, false);
djui_panel_menu_back(caller);
}

View file

@ -13,6 +13,7 @@ static void djui_panel_pause_resume(UNUSED struct DjuiBase* caller) {
}
static void djui_panel_pause_quit_yes(UNUSED struct DjuiBase* caller) {
network_reset_reconnect_and_rehost();
network_shutdown(true, false, false);
}
@ -35,8 +36,9 @@ static void djui_panel_pause_quit(struct DjuiBase* caller) {
void djui_panel_pause_create(struct DjuiBase* caller) {
if (gDjuiChatBoxFocus) { djui_chat_box_toggle(); }
f32 bodyHeight = 64 * 5 + 16 * 4;
f32 bodyHeight = 64 * 4 + 16 * 3;
if (gServerSettings.enableCheats) { bodyHeight += 64 + 16; }
if (gNetworkType == NT_SERVER) { bodyHeight += 64 + 16; }
struct DjuiBase* defaultBase = NULL;
struct DjuiThreePanel* panel = djui_panel_menu_create(bodyHeight, "\\#ff0800\\P\\#1be700\\A\\#00b3ff\\U\\#ffef00\\S\\#ff0800\\E");
@ -77,16 +79,23 @@ void djui_panel_pause_create(struct DjuiBase* caller) {
djui_base_set_size(&button5->base, 1.0f, 64);
djui_interactable_hook_click(&button5->base, djui_panel_pause_resume);
struct DjuiButton* button6;
if (gNetworkType == NT_SERVER) {
button6 = djui_button_create(&body->base, "Stop Hosting");
} else {
button6 = djui_button_create(&body->base, "Disconnect");
struct DjuiButton* button6 = djui_button_create(&body->base, "Server Settings");
djui_base_set_size_type(&button6->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&button6->base, 1.0f, 64);
djui_interactable_hook_click(&button6->base, djui_panel_host_create);
}
djui_base_set_size_type(&button6->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&button6->base, 1.0f, 64);
djui_interactable_hook_click(&button6->base, djui_panel_pause_quit);
djui_button_set_style(button6, 1);
struct DjuiButton* button7;
if (gNetworkType == NT_SERVER) {
button7 = djui_button_create(&body->base, "Stop Hosting");
} else {
button7 = djui_button_create(&body->base, "Disconnect");
}
djui_base_set_size_type(&button7->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&button7->base, 1.0f, 64);
djui_interactable_hook_click(&button7->base, djui_panel_pause_quit);
djui_button_set_style(button7, 1);
}
djui_panel_add(caller, &panel->base, defaultBase);

View file

@ -24,6 +24,7 @@ static void on_activity_join_callback(UNUSED void* data, enum EDiscordResult res
LOGFILE_ERROR(LFT_DISCORD, "Joined lobby when already connected somewhere!");
return;
}
network_reset_reconnect_and_rehost();
network_init(NT_CLIENT);
gCurActivity.type = DiscordActivityType_Playing;

View file

@ -22,6 +22,7 @@ struct DiscordApplication app = { 0 };
bool gDiscordInitialized = false;
bool gDiscordFailed = false;
bool alreadyRun = false;
bool gDiscordReconnecting = false;
static void discord_sdk_log_callback(UNUSED void* hook_data, enum EDiscordLogLevel level, const char* message) {
LOGFILE_INFO(LFT_DISCORD, "callback (%d): %s", level, message);
@ -107,6 +108,7 @@ static void ns_discord_update(void) {
}
static bool ns_discord_initialize(enum NetworkType networkType) {
if (gDiscordReconnecting) { return true; }
#ifdef DEBUG
set_instance_env_variable();
#endif
@ -179,6 +181,7 @@ static bool ns_discord_initialize(enum NetworkType networkType) {
}
static void ns_discord_shutdown(void) {
if (gDiscordReconnecting) { return; }
if (!gDiscordInitialized) { return; }
discord_lobby_leave();
gActivityLock = false;

View file

@ -29,6 +29,7 @@ void discord_fatal(int rc);
extern struct NetworkSystem gNetworkSystemDiscord;
extern bool gDiscordInitialized;
extern bool gDiscordFailed;
extern bool gDiscordReconnecting;
struct DiscordApplication {
struct IDiscordCore* core;

View file

@ -59,6 +59,11 @@ u8 gDebugPacketIdBuffer[256] = { 0xFF };
u8 gDebugPacketSentBuffer[256] = { 0 };
u8 gDebugPacketOnBuffer = 0;
u32 gNetworkStartupTimer = 0;
u32 sNetworkReconnectTimer = 0;
u32 sNetworkRehostTimer = 0;
enum NetworkSystemType sNetworkReconnectType = NT_NONE;
struct StringLinkedList gRegisteredMods = { 0 };
struct ServerSettings gServerSettings = {
@ -88,6 +93,7 @@ bool network_init(enum NetworkType inNetworkType) {
// reset override hide hud
extern u8 gOverrideHideHud;
gOverrideHideHud = 0;
gNetworkStartupTimer = 5 * 30;
// sanity check network system
if (gNetworkSystem == NULL) {
@ -287,6 +293,9 @@ void network_send_to(u8 localIndex, struct Packet* p) {
// send
if (!tooManyPackets) {
if (p->keepSendingAfterDisconnect) {
localIndex = 0; // Force this type of packet to use the saved addr
}
int rc = gNetworkSystem->send(localIndex, p->addr, p->buffer, p->cursor + sizeof(u32));
if (rc == SOCKET_ERROR) { LOG_ERROR("send error %d", rc); return; }
}
@ -377,6 +386,76 @@ void* network_duplicate_address(u8 localIndex) {
return gNetworkSystem->dup_addr(localIndex);
}
void network_reset_reconnect_and_rehost(void) {
gNetworkStartupTimer = 0;
sNetworkReconnectTimer = 0;
sNetworkRehostTimer = 0;
sNetworkReconnectType = NT_NONE;
gDiscordReconnecting = false;
}
void network_reconnect_begin(void) {
if (sNetworkReconnectTimer > 0) {
return;
}
sNetworkReconnectTimer = 2 * 30;
sNetworkReconnectType = (gNetworkSystem == &gNetworkSystemDiscord)
? NS_DISCORD
: NS_SOCKET;
gDiscordReconnecting = true;
network_shutdown(false, false, false);
gDiscordReconnecting = false;
djui_connect_menu_open();
}
static void network_reconnect_update(void) {
if (sNetworkReconnectTimer <= 0) { return; }
if (--sNetworkReconnectTimer != 0) { return; }
if (sNetworkReconnectType == NS_SOCKET) {
network_set_system(NS_SOCKET);
}
gDiscordReconnecting = true;
network_init(NT_CLIENT);
gDiscordReconnecting = false;
network_send_mod_list_request();
}
bool network_is_reconnecting(void) {
return sNetworkReconnectTimer > 0;
}
void network_rehost_begin(void) {
for (int i = 1; i < MAX_PLAYERS; i++) {
struct NetworkPlayer* np = &gNetworkPlayers[i];
if (!np->connected) { continue; }
network_send_kick(i, EKT_REJOIN);
network_player_disconnected(i);
}
gDiscordReconnecting = true;
network_shutdown(false, false, false);
gDiscordReconnecting = false;
sNetworkRehostTimer = 2;
}
static void network_rehost_update(void) {
extern void djui_panel_do_host(void);
if (sNetworkRehostTimer <= 0) { return; }
if (--sNetworkRehostTimer != 0) { return; }
gDiscordReconnecting = true;
djui_panel_do_host();
gDiscordReconnecting = false;
}
static void network_update_area_timer(void) {
bool brokenClock = false;
#ifdef DEVELOPMENT
@ -410,6 +489,14 @@ static void network_update_area_timer(void) {
}
void network_update(void) {
if (gNetworkStartupTimer > 0) {
gNetworkStartupTimer--;
}
network_rehost_update();
network_reconnect_update();
// check for level loaded event
if (networkLoadingLevel < LOADING_LEVEL_THRESHOLD) {
networkLoadingLevel++;
@ -499,7 +586,9 @@ void network_shutdown(bool sendLeaving, bool exiting, bool popup) {
}
gNetworkPlayerServer = NULL;
gNetworkType = NT_NONE;
if (sNetworkReconnectTimer <= 0 || sNetworkReconnectType != NS_DISCORD) {
gNetworkType = NT_NONE;
}
#ifdef DISCORD_SDK

View file

@ -88,6 +88,7 @@ extern u16 gNetworkRequestLocationTimer;
extern u8 gDebugPacketIdBuffer[];
extern u8 gDebugPacketSentBuffer[];
extern u8 gDebugPacketOnBuffer;
extern u32 gNetworkStartupTimer;
// network.c
void network_set_system(enum NetworkSystemType nsType);
@ -99,6 +100,10 @@ void network_send_to(u8 localIndex, struct Packet* p);
void network_send(struct Packet* p);
void network_receive(u8 localIndex, void* addr, u8* data, u16 dataLength);
void* network_duplicate_address(u8 localIndex);
void network_reset_reconnect_and_rehost(void);
void network_reconnect_begin(void);
bool network_is_reconnecting(void);
void network_rehost_begin(void);
void network_update(void);
void network_register_mod(char* modName);
void network_shutdown(bool sendLeaving, bool exiting, bool popup);

View file

@ -148,9 +148,6 @@ void network_player_palette_to_color(struct NetworkPlayer *np, enum PlayerParts
void network_player_update(void) {
for (s32 i = 0; i < MAX_PLAYERS; i++) {
struct NetworkPlayer *np = &gNetworkPlayers[i];
if (np->connected && gMarioStates[np->localIndex].interactObj) {
//LOG_INFO("%u :: %u", np->globalIndex, gMarioStates[np->localIndex].interactObj->oSyncID); // DO NOT COMMIT
}
if (!np->connected && i > 0) { continue; }
network_player_update_model(i);

View file

@ -130,6 +130,10 @@ void packet_receive(struct Packet* p) {
// refuse packets from unknown players other than join request
if (gNetworkType == NT_SERVER && p->localIndex == UNKNOWN_LOCAL_INDEX && !network_allow_unknown_local_index(packetType)) {
if (gNetworkStartupTimer > 0) {
LOG_INFO("refusing packet from unknown player on startup, packetType: %d", packetType);
return;
}
if (packetType != PACKET_PLAYER) {
LOG_INFO("closing connection for packetType: %d", packetType);
network_send_kick(0, EKT_CLOSE_CONNECTION);

View file

@ -96,6 +96,7 @@ struct Packet {
bool levelAreaMustMatch;
bool levelMustMatch;
bool requestBroadcast;
bool keepSendingAfterDisconnect;
u8 destGlobalId;
u16 seqId;
bool sent;
@ -114,6 +115,7 @@ enum KickReasonType {
EKT_FULL_PARTY,
EKT_KICKED,
EKT_BANNED,
EKT_REJOIN,
};
enum ChatConfirmCommand {

View file

@ -2,11 +2,15 @@
#include "../network.h"
#include "pc/debuglog.h"
#include "pc/djui/djui.h"
#include "pc/utils/misc.h"
f32 lastReconnectTime = -9999999;
void network_send_kick(u8 localIndex, enum KickReasonType kickReason) {
u8 kickReasonType = kickReason;
struct Packet p = { 0 };
packet_init(&p, PACKET_KICK, false, PLMT_NONE);
packet_init(&p, PACKET_KICK, true, PLMT_NONE);
p.keepSendingAfterDisconnect = (kickReason == EKT_REJOIN);
packet_write(&p, &kickReasonType, sizeof(u8));
network_send_to(localIndex, &p);
}
@ -30,7 +34,17 @@ void network_receive_kick(struct Packet* p) {
case EKT_FULL_PARTY: djui_popup_create("\\#ffa0a0\\Disconnected:\\#c8c8c8\\ The party is full.", 1); break;
case EKT_KICKED: djui_popup_create("\\#ffa0a0\\Disconnected:\\#c8c8c8\\ The server kicked you.", 1); break;
case EKT_BANNED: djui_popup_create("\\#ffa0a0\\Disconnected:\\#c8c8c8\\ The server banned you.", 1); break;
case EKT_REJOIN: djui_popup_create("\\#ffa0a0\\Disconnected:\\#c8c8c8\\ Rejoining...", 1); break;
default: djui_popup_create("\\#ffa0a0\\Disconnected:\\#c8c8c8\\ Host has closed the connection.", 1); break;
}
network_shutdown(false, false, false);
if (kickReason == EKT_REJOIN) {
f32 now = clock_elapsed();
if ((now - lastReconnectTime) > 3) {
lastReconnectTime = now;
network_reconnect_begin();
}
} else {
network_shutdown(false, false, false);
}
}

View file

@ -27,6 +27,7 @@ void packet_init(struct Packet* packet, enum PacketType packetType, bool reliabl
packet->orderedFromGlobalId = sOrderedPackets ? gNetworkPlayerLocal->globalIndex : 0;
packet->orderedGroupId = sOrderedPackets ? sCurrentOrderedGroupId : 0;
packet->orderedSeqId = 0;
packet->keepSendingAfterDisconnect = false;
packet_write(packet, &packetType, sizeof(u8));

View file

@ -35,7 +35,14 @@ static void remove_node_from_list(struct PacketLinkedList* node) {
}
void network_forget_all_reliable(void) {
while (head != NULL) { remove_node_from_list(head); }
struct PacketLinkedList* node = head;
while (node != NULL) {
struct PacketLinkedList* next = node->next;
if (!node->p.keepSendingAfterDisconnect) {
remove_node_from_list(head);
}
node = next;
}
}
void network_forget_all_reliable_from(u8 localIndex) {
@ -44,7 +51,9 @@ void network_forget_all_reliable_from(u8 localIndex) {
while (node != NULL) {
struct PacketLinkedList* next = node->next;
if (node->p.localIndex == localIndex) {
remove_node_from_list(node);
if (!node->p.keepSendingAfterDisconnect) {
remove_node_from_list(node);
}
}
node = next;
}