Added a join message screen

Displays an animation while joining
Shows version mismatch error in join message screen
Shows mod mismatch error in join message screen (displays mismatching mods now)
Displays party is full / host closed connection in join message screen
Added string builder
This commit is contained in:
MysterD 2021-07-05 16:53:09 -07:00
parent 13d504a953
commit 5c4677ca77
19 changed files with 193 additions and 25 deletions

View file

@ -3948,6 +3948,7 @@
<ClCompile Include="..\src\pc\djui\djui_panel_host.c" />
<ClCompile Include="..\src\pc\djui\djui_panel_host_message.c" />
<ClCompile Include="..\src\pc\djui\djui_panel_join.c" />
<ClCompile Include="..\src\pc\djui\djui_panel_join_message.c" />
<ClCompile Include="..\src\pc\djui\djui_panel_menu.c" />
<ClCompile Include="..\src\pc\djui\djui_selectionbox.c" />
<ClCompile Include="..\src\pc\djui\djui_cursor.c" />
@ -4036,6 +4037,7 @@
<ClCompile Include="..\src\pc\platform.c" />
<ClCompile Include="..\src\pc\ultra_reimplementation.c" />
<ClCompile Include="..\src\pc\utils\misc.c" />
<ClCompile Include="..\src\pc\utils\string_builder.c" />
<ClCompile Include="..\src\pc\utils\string_linked_list.c" />
<ClCompile Include="..\text\define_courses.inc.c" />
<ClCompile Include="..\text\define_text.inc.c" />
@ -4388,6 +4390,7 @@
<ClInclude Include="..\src\pc\djui\djui_panel_host.h" />
<ClInclude Include="..\src\pc\djui\djui_panel_host_message.h" />
<ClInclude Include="..\src\pc\djui\djui_panel_join.h" />
<ClInclude Include="..\src\pc\djui\djui_panel_join_message.h" />
<ClInclude Include="..\src\pc\djui\djui_panel_menu.h" />
<ClInclude Include="..\src\pc\djui\djui_selectionbox.h" />
<ClInclude Include="..\src\pc\djui\djui_cursor.h" />
@ -4426,6 +4429,7 @@
<ClInclude Include="..\src\pc\network\socket\socket_windows.h" />
<ClInclude Include="..\src\pc\network\version.h" />
<ClInclude Include="..\src\pc\utils\misc.h" />
<ClInclude Include="..\src\pc\utils\string_builder.h" />
<ClInclude Include="..\src\pc\utils\string_linked_list.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View file

@ -15246,6 +15246,12 @@
<ClCompile Include="..\src\pc\djui\djui_panel_join.c">
<Filter>Source Files\src\pc\djui\panel</Filter>
</ClCompile>
<ClCompile Include="..\src\pc\djui\djui_panel_join_message.c">
<Filter>Source Files\src\pc\djui\panel</Filter>
</ClCompile>
<ClCompile Include="..\src\pc\utils\string_builder.c">
<Filter>Source Files\src\pc\utils</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\actors\common0.h">
@ -16312,5 +16318,11 @@
<ClInclude Include="..\src\pc\djui\djui_panel_join.h">
<Filter>Source Files\src\pc\djui\panel</Filter>
</ClInclude>
<ClInclude Include="..\src\pc\djui\djui_panel_join_message.h">
<Filter>Source Files\src\pc\djui\panel</Filter>
</ClInclude>
<ClInclude Include="..\src\pc\utils\string_builder.h">
<Filter>Source Files\src\pc\utils</Filter>
</ClInclude>
</ItemGroup>
</Project>

View file

@ -35,6 +35,7 @@
#include "djui_panel_host.h"
#include "djui_panel_host_message.h"
#include "djui_panel_join.h"
#include "djui_panel_join_message.h"
#include "djui_panel_options.h"
#include "djui_panel_camera.h"
#include "djui_panel_controls.h"

View file

@ -15,6 +15,7 @@ static f32 sMoveAmount = 0;
void djui_panel_add(struct DjuiBase* caller, struct DjuiBase* panelBase, struct DjuiBase* defaultElementBase) {
bool firstPanel = (sPanelList == NULL);
gDjuiPanelJoinMessageVisible = false;
// remember element that triggered this panel add
if (sPanelList != NULL) {
@ -76,6 +77,8 @@ void djui_panel_back(void) {
// play a sound
play_sound(SOUND_MENU_CLICK_FILE_SELECT, gDefaultSoundArgs);
gDjuiPanelJoinMessageVisible = false;
}
void djui_panel_update(void) {
@ -130,5 +133,7 @@ void djui_panel_shutdown(void) {
sPanelRemoving = NULL;
sMoveAmount = 0;
gInteractableOverridePad = false;
gDjuiPanelJoinMessageVisible = false;
gDjuiPanelMainCreated = false;
djui_cursor_set_visible(false);
}

View file

@ -16,9 +16,9 @@ Enter \\#d0d0ff\\direct connection\\#c8c8c8\\ IP and port:\
";
void djui_panel_join_do_join(struct DjuiBase* caller) {
djui_panel_shutdown();
network_set_system(NS_SOCKET);
network_init(NT_CLIENT);
djui_panel_join_message_create(caller);
}
void djui_panel_join_create(struct DjuiBase* caller) {

View file

@ -0,0 +1,75 @@
#include "djui.h"
#include "src/pc/network/network.h"
#include "src/pc/utils/misc.h"
#include "src/pc/configfile.h"
#define DJUI_JOIN_MESSAGE_ELAPSE 60
bool gDjuiPanelJoinMessageVisible = false;
static struct DjuiText* sPanelText = NULL;
static bool sDisplayingError = false;
void djui_panel_join_message_error(char* message) {
djui_panel_join_message_create(NULL);
sDisplayingError = true;
djui_text_set_text(sPanelText, message);
}
void djui_panel_join_message_cancel(struct DjuiBase* caller) {
network_shutdown(true);
djui_panel_menu_back(caller);
}
void djui_panel_join_message_render_pre(struct DjuiBase* base, UNUSED bool* unused) {
if (sDisplayingError) { return; }
struct DjuiText* text1 = (struct DjuiText*)base;
u16 lastElapse = (base->tag / DJUI_JOIN_MESSAGE_ELAPSE);
base->tag = (base->tag + 1) % (DJUI_JOIN_MESSAGE_ELAPSE * 3);
u16 elapse = (base->tag / DJUI_JOIN_MESSAGE_ELAPSE);
if (lastElapse != elapse) {
switch (base->tag / DJUI_JOIN_MESSAGE_ELAPSE) {
case 0: djui_text_set_text(text1, "..."); break;
case 1: djui_text_set_text(text1, "."); break;
default: djui_text_set_text(text1, ".."); break;
}
}
}
void djui_panel_join_message_create(struct DjuiBase* caller) {
// make sure main panel was created
if (!gDjuiPanelMainCreated) { djui_panel_main_create(caller); }
// don't recreate panel if it's already visible
if (gDjuiPanelJoinMessageVisible) { return; }
f32 bodyHeight = 64 + 16;
u16 directLines = 8;
f32 directTextHeight = 32 * 0.8125f * directLines + 8;
bodyHeight += directTextHeight + 16;
struct DjuiBase* defaultBase = NULL;
struct DjuiThreePanel* panel = djui_panel_menu_create(bodyHeight, "\\#ff0800\\J\\#1be700\\O\\#00b3ff\\I\\#ffef00\\N\\#1be700\\I\\#00b3ff\\N\\#ffef00\\G");
struct DjuiFlowLayout* body = (struct DjuiFlowLayout*)djui_three_panel_get_body(panel);
{
struct DjuiText* text1 = djui_text_create(&body->base, "...");
djui_base_set_size_type(&text1->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&text1->base, 1.0f, directTextHeight);
djui_base_set_color(&text1->base, 200, 200, 200, 255);
djui_text_set_alignment(text1, DJUI_HALIGN_CENTER, DJUI_VALIGN_CENTER);
text1->base.tag = 0;
text1->base.on_render_pre = djui_panel_join_message_render_pre;
sPanelText = text1;
struct DjuiButton* button1 = djui_button_create(&body->base, "Cancel");
djui_base_set_size_type(&button1->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&button1->base, 1.0f, 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_join_message_cancel);
defaultBase = &button1->base;
}
djui_panel_add(caller, &panel->base, defaultBase);
gDjuiPanelJoinMessageVisible = true;
sDisplayingError = false;
}

View file

@ -0,0 +1,7 @@
#pragma once
#include "djui.h"
extern bool gDjuiPanelJoinMessageVisible;
void djui_panel_join_message_error(char* message);
void djui_panel_join_message_create(struct DjuiBase* caller);

View file

@ -1,6 +1,8 @@
#include "djui.h"
#include "src/pc/controller/controller_sdl.h"
bool gDjuiPanelMainCreated = false;
void djui_panel_main_create(struct DjuiBase* caller) {
f32 bodyHeight = 64 * 4 + 16 * 3;
@ -43,4 +45,5 @@ void djui_panel_main_create(struct DjuiBase* caller) {
djui_panel_add(caller, &panel->base, defaultBase);
gInteractableOverridePad = true;
gDjuiPanelMainCreated = true;
}

View file

@ -1,4 +1,6 @@
#pragma once
#include "djui.h"
extern bool gDjuiPanelMainCreated;
void djui_panel_main_create(struct DjuiBase* caller);

View file

@ -148,7 +148,7 @@ static bool ns_discord_initialize(enum NetworkType networkType) {
DISCORD_REQUIRE(rc);
} else if (rc) {
LOG_ERROR("DiscordCreate failed: %d", rc);
djui_show_popup("Could not detect Discord.\n\nTry closing the game,\nrestarting Discord,\nand opening the game again.");
djui_show_popup("\\#ffa0a0\\Error:\\#c8c8c8\\ Could not detect Discord.\n\nTry closing the game, restarting Discord, and opening the game again.");
gDiscordFailed = true;
return false;
}

View file

@ -262,12 +262,12 @@ void network_register_mod(char* modName) {
string_linked_list_append(&gRegisteredMods, modName);
}
void network_shutdown(void) {
void network_shutdown(bool sendLeaving) {
network_forget_all_reliable();
if (gNetworkType == NT_NONE) { return; }
if (gNetworkSystem == NULL) { LOG_ERROR("no network system attached"); return; }
if (gNetworkPlayerLocal != NULL) { network_send_leaving(gNetworkPlayerLocal->globalIndex); }
if (gNetworkPlayerLocal != NULL && sendLeaving) { network_send_leaving(gNetworkPlayerLocal->globalIndex); }
network_player_shutdown();
gNetworkSystem->shutdown();

View file

@ -99,7 +99,7 @@ void network_send(struct Packet* p);
void network_receive(u8 localIndex, u8* data, u16 dataLength);
void network_update(void);
void network_register_mod(char* modName);
void network_shutdown(void);
void network_shutdown(bool sendLeaving);
// TODO: replace
void chat_add_message(char* message);

View file

@ -106,7 +106,7 @@ void network_player_update(void) {
}
}
if (!connectionAlive) {
network_shutdown();
network_shutdown(true);
}
}
#endif
@ -194,7 +194,7 @@ u8 network_player_disconnected(u8 globalIndex) {
LOG_ERROR("player disconnected, but it's local.. this shouldn't happen!");
return UNKNOWN_GLOBAL_INDEX;
} else {
network_shutdown();
network_shutdown(true);
}
}

View file

@ -72,8 +72,11 @@ void packet_receive(struct Packet* p) {
u8 packetType = (u8)p->buffer[0];
// refuse packets from unknown players other than join request
if (gNetworkType == NT_SERVER && p->localIndex == UNKNOWN_LOCAL_INDEX && packetType != PACKET_JOIN_REQUEST) {
network_send_kick(EKT_CLOSE_CONNECTION);
if (gNetworkType == NT_SERVER && p->localIndex == UNKNOWN_LOCAL_INDEX && packetType != PACKET_JOIN_REQUEST && packetType != PACKET_ACK) {
if (packetType != PACKET_PLAYER) {
LOG_INFO("closing connection for packetType: %d", packetType);
network_send_kick(EKT_CLOSE_CONNECTION);
}
return;
}

View file

@ -10,10 +10,11 @@
#include "src/pc/fs/fs.h"
#include "PR/os_eeprom.h"
#include "pc/network/version.h"
#include "pc/djui/djui.h"
#include "pc/utils/string_builder.h"
#define DISABLE_MODULE_LOG 1
#include "pc/debuglog.h"
extern u8* gOverrideEeprom;
static u8 eeprom[512] = { 0 };
@ -108,17 +109,11 @@ void network_receive_join(struct Packet* p) {
packet_read(p, &remoteVersion, sizeof(u8) * MAX_VERSION_LENGTH);
LOG_INFO("server has version: %s", version);
if (memcmp(version, remoteVersion, MAX_VERSION_LENGTH) != 0) {
network_shutdown(true);
LOG_ERROR("version mismatch");
// todo: hack: remove me in the future
// needed because the old style only had 8 characters for the version
if (strcmp("beta", remoteVersion) != 0) {
remoteVersion[8] = '\0';
}
char mismatchMessage[128] = { 0 };
snprintf(mismatchMessage, 128, "Version mismatch.\n\nYour version - %s\nTheir version - %s\n\nSomeone is out of date!\n", version, remoteVersion);
djui_show_popup(mismatchMessage);
char mismatchMessage[256] = { 0 };
snprintf(mismatchMessage, 256, "\\#ffa0a0\\Error:\\#c8c8c8\\ Version mismatch.\n\nYour version: \\#a0a0ff\\%s\\#c8c8c8\\\nTheir version: \\#a0a0ff\\%s\\#c8c8c8\\\n\nSomeone is out of date!\n", version, remoteVersion);
djui_panel_join_message_error(mismatchMessage);
return;
}
@ -142,8 +137,36 @@ void network_receive_join(struct Packet* p) {
}
if (string_linked_list_mismatch(&gRegisteredMods, &head)) {
network_shutdown(true);
struct StringBuilder* builder = string_builder_create(512);
string_builder_append(builder, "\\#ffa0a0\\Error:\\#c8c8c8\\ mods don't match.\n\n");
string_builder_append(builder, "\\#c8c8c8\\Yours: ");
struct StringLinkedList* node = &gRegisteredMods;
bool first = true;
while (node != NULL) {
string_builder_append(builder, first ? "\\#%s\\%s" : ", \\#%s\\%s",
string_linked_list_contains(&head, node->string) ? "a0ffa0" : "ffa0a0"
, node->string);
first = false;
node = node->next;
}
string_builder_append(builder, "\n\n\\#c8c8c8\\Theirs: ");
node = &head;
first = true;
while (node != NULL) {
string_builder_append(builder, first ? "\\#%s\\%s" : ", \\#%s\\%s",
string_linked_list_contains(&gRegisteredMods, node->string) ? "a0ffa0" : "ffa0a0"
, node->string);
first = false;
node = node->next;
}
djui_panel_join_message_error(builder->string);
string_builder_destroy(builder);
string_linked_list_free(&head);
djui_show_popup("Your mods don't match!");
return;
}
string_linked_list_free(&head);
@ -153,6 +176,7 @@ void network_receive_join(struct Packet* p) {
save_file_load_all(TRUE);
djui_panel_shutdown();
extern s16 gChangeLevel;
gChangeLevel = 16;
}

View file

@ -1,6 +1,7 @@
#include <stdio.h>
#include "../network.h"
#include "pc/debuglog.h"
#include "pc/djui/djui.h"
void network_send_kick(enum KickReasonType kickReason) {
u8 kickReasonType = kickReason;
@ -26,8 +27,8 @@ void network_receive_kick(struct Packet* p) {
enum KickReasonType kickReason = kickReasonType;
switch (kickReason) {
case EKT_FULL_PARTY: djui_show_popup("The party is full."); break;
default: djui_show_popup("Host has closed the connection."); break;
case EKT_FULL_PARTY: djui_panel_join_message_error("\\#ffa0a0\\Error:\\#c8c8c8\\ The party is full."); break;
default: djui_panel_join_message_error("\\#ffa0a0\\Error:\\#c8c8c8\\ Host has closed the connection."); break;
}
network_shutdown();
network_shutdown(false);
}

View file

@ -158,7 +158,7 @@ void game_deinit(void) {
controller_shutdown();
audio_shutdown();
gfx_shutdown();
network_shutdown();
network_shutdown(true);
inited = false;
}

View file

@ -0,0 +1,16 @@
#include <string.h>
#include <stdlib.h>
#include "string_builder.h"
struct StringBuilder* string_builder_create(int bufferLength) {
struct StringBuilder* builder = malloc(sizeof(struct StringBuilder));
builder->string = malloc(sizeof(char) * bufferLength);
builder->string[0] = '\0';
builder->bufferLength = bufferLength;
return builder;
}
void string_builder_destroy(struct StringBuilder* builder) {
free(builder->string);
free(builder);
}

View file

@ -0,0 +1,15 @@
#ifndef STRING_BUILDER_H
#define STRING_BUILDER_H
#include <stdio.h>
struct StringBuilder {
char* string;
int bufferLength;
};
struct StringBuilder* string_builder_create(int bufferLength);
#define string_builder_append(_builder, ...) snprintf((_builder->string + strlen(_builder->string)), (_builder->bufferLength - strlen(_builder->string)), __VA_ARGS__)
void string_builder_destroy(struct StringBuilder* builder);
#endif