Added mod registration system

Allows mods to register themselves so that mismatches don't occur. This
does not automagically detect when someone modified the game, so the
mods will have to insert a function like this into their patch:

static void __attribute__((constructor)) _register_this_mod() {
    network_register_mod("mod name here");
}
This commit is contained in:
MysterD 2020-10-04 16:41:55 -07:00
parent 259ddac5ba
commit ed06b57649
10 changed files with 145 additions and 6 deletions

View file

@ -308,7 +308,7 @@ LEVEL_DIRS := $(patsubst levels/%,%,$(dir $(wildcard levels/*/header.h)))
# Hi, I'm a PC
SRC_DIRS := src src/engine src/game src/audio src/menu src/buffers actors levels bin data assets src/pc src/pc/gfx src/pc/audio src/pc/controller src/pc/fs src/pc/fs/packtypes
SRC_DIRS += src/pc/network src/pc/network/packets src/pc/network/socket
SRC_DIRS += src/pc/network src/pc/network/packets src/pc/network/socket src/pc/utils
ASM_DIRS :=
#ifeq ($(DISCORDRPC),1)

View file

@ -3986,6 +3986,7 @@
<ClCompile Include="..\src\pc\pc_main.c" />
<ClCompile Include="..\src\pc\platform.c" />
<ClCompile Include="..\src\pc\ultra_reimplementation.c" />
<ClCompile Include="..\src\pc\utils\string_linked_list.c" />
<ClCompile Include="..\text\define_courses.inc.c" />
<ClCompile Include="..\text\define_text.inc.c" />
<ClCompile Include="..\tools\aifc_decode.c" />
@ -4338,6 +4339,7 @@
<ClInclude Include="..\src\pc\network\socket\socket.h" />
<ClInclude Include="..\src\pc\network\socket\socket_linux.h" />
<ClInclude Include="..\src\pc\network\socket\socket_windows.h" />
<ClInclude Include="..\src\pc\utils\string_linked_list.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View file

@ -3433,6 +3433,9 @@
<Filter Include="Header Files\src\pc\network\discord">
<UniqueIdentifier>{7fd7fed2-3f22-4bbf-a118-8ff54107c341}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\src\pc\utils">
<UniqueIdentifier>{451cd85d-8a2c-4aa5-87c7-d1415974ba96}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\actors\amp\anims\anim_0800401C.inc.c">
@ -15069,6 +15072,9 @@
<ClCompile Include="..\src\pc\network\packets\packet_instant_warp.c">
<Filter>Source Files\src\pc\network\packets</Filter>
</ClCompile>
<ClCompile Include="..\src\pc\utils\string_linked_list.c">
<Filter>Source Files\src\pc\utils</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\actors\common0.h">
@ -16021,5 +16027,8 @@
<ClInclude Include="..\src\pc\network\network_player.h">
<Filter>Header Files\src\pc\network</Filter>
</ClInclude>
<ClInclude Include="..\src\pc\utils\string_linked_list.h">
<Filter>Source Files\src\pc\utils</Filter>
</ClInclude>
</ItemGroup>
</Project>

View file

@ -282,8 +282,8 @@ void custom_menu_goto_game(s16 saveFileNum) {
sGotoGame = saveFileNum;
}
void custom_menu_version_mismatch(void) {
void custom_menu_connection_error(char* message) {
play_sound(SOUND_MARIO_MAMA_MIA, gDefaultSoundArgs);
strcpy(sConnectionJoinError, "Your versions don't match, both should rebuild!");
strcpy(sConnectionJoinError, message);
network_shutdown();
}

View file

@ -8,6 +8,6 @@ void custom_menu_init(struct CustomMenu* head);
void custom_menu_loop(void);
void custom_menu_on_load_save_file(s8 saveFileNum);
void custom_menu_goto_game(s16 saveFileNum);
void custom_menu_version_mismatch(void);
void custom_menu_connection_error(char* message);
#endif // CUSTOM_MENU_H

View file

@ -23,13 +23,13 @@ struct NetworkSystem* gNetworkSystem = &gNetworkSystemSocket;
u8 networkLoadingLevel = 0;
bool gNetworkLevelLoaded = false;
clock_t gLastNetworkSend = 0;
struct StringLinkedList gRegisteredMods = { 0 };
struct ServerSettings gServerSettings = {
.playerInteractions = PLAYER_INTERACTIONS_SOLID,
.playerKnockbackStrength = 25,
};
void network_set_system(enum NetworkSystemType nsType) {
switch (nsType) {
case NS_SOCKET: gNetworkSystem = &gNetworkSystemSocket; break;
@ -176,6 +176,11 @@ void network_update(void) {
}
}
void network_register_mod(char* modName) {
if (string_linked_list_contains(&gRegisteredMods, modName)) { return; }
string_linked_list_append(&gRegisteredMods, modName);
}
void network_shutdown(void) {
network_forget_all_reliable();
if (gNetworkType == NT_NONE) { return; }

View file

@ -7,6 +7,7 @@
#include <assert.h>
#include "network_player.h"
#include "packets/packet.h"
#include "pc/utils/string_linked_list.h"
#include "../cliopts.h"
#define SET_BIT(val, num) ((((u8)(val)) & 0x01) << (num));
@ -81,6 +82,7 @@ extern bool gNetworkLevelLoaded;
extern struct SyncObject gSyncObjects[];
extern struct ServerSettings gServerSettings;
extern clock_t gLastNetworkSend;
extern struct StringLinkedList gRegisteredMods;
// network.c
void network_set_system(enum NetworkSystemType nsType);
@ -91,6 +93,7 @@ void network_send_to(u8 localIndex, struct Packet* p);
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);
#endif

View file

@ -60,6 +60,20 @@ void network_send_join(struct Packet* joinRequestPacket) {
packet_write(&p, &gServerSettings.playerKnockbackStrength, sizeof(u8));
packet_write(&p, &gServerSettings.stayInLevelAfterStar, sizeof(u8));
packet_write(&p, eeprom, sizeof(u8) * 512);
u8 modCount = string_linked_list_count(&gRegisteredMods);
packet_write(&p, &modCount, sizeof(u8));
struct StringLinkedList* node = &gRegisteredMods;
char nullchar = '\0';
while (node != NULL && node->string != NULL) {
int length = strlen(node->string);
packet_write(&p, node->string, sizeof(char) * length);
packet_write(&p, &nullchar, sizeof(char));
LOG_INFO("sending registered mod: %s", node->string);
node = node->next;
}
network_send_to(joinRequestPacket->localIndex , &p);
LOG_INFO("sending join packet");
@ -73,6 +87,7 @@ void network_receive_join(struct Packet* p) {
char hash[HASH_LENGTH] = GIT_HASH;
char remoteHash[HASH_LENGTH] = { 0 };
u8 myGlobalIndex = UNKNOWN_GLOBAL_INDEX;
u8 modCount = 0;
if (gNetworkPlayerLocal != NULL && gNetworkPlayerLocal->connected) {
LOG_ERROR("Received join packet, but already in-game!");
@ -82,7 +97,7 @@ void network_receive_join(struct Packet* p) {
// verify version
packet_read(p, &remoteHash, sizeof(u8) * HASH_LENGTH);
if (memcmp(hash, remoteHash, HASH_LENGTH) != 0) {
custom_menu_version_mismatch();
custom_menu_connection_error("Your versions don't match, both should rebuild!");
return;
}
@ -92,6 +107,23 @@ void network_receive_join(struct Packet* p) {
packet_read(p, &gServerSettings.playerKnockbackStrength, sizeof(u8));
packet_read(p, &gServerSettings.stayInLevelAfterStar, sizeof(u8));
packet_read(p, eeprom, sizeof(u8) * 512);
packet_read(p, &modCount, sizeof(u8));
struct StringLinkedList head = { 0 };
for (int i = 0; i < modCount; i++) {
char* modName = (char*) &p->buffer[p->cursor];
int length = strlen(modName);
LOG_INFO("host has mod: %s", modName);
string_linked_list_append(&head, modName);
p->cursor += length + 1;
}
if (string_linked_list_mismatch(&gRegisteredMods, &head)) {
string_linked_list_free(&head);
custom_menu_connection_error("Your mods don't match!");
return;
}
string_linked_list_free(&head);
network_player_connected(NPT_SERVER, 0);
network_player_connected(NPT_LOCAL, myGlobalIndex);

View file

@ -0,0 +1,73 @@
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "string_linked_list.h"
void string_linked_list_append(struct StringLinkedList* node, char* string) {
int length = strlen(string);
while (1) {
if (node->string == NULL) {
node->string = malloc(sizeof(char) * (length + 1));
memset(node->string, 0, sizeof(char) * (length + 1));
strncpy(node->string, string, length);
return;
}
if (node->next == NULL) {
node->next = malloc(sizeof(struct StringLinkedList));
memset(node->next, 0, sizeof(struct StringLinkedList));
}
node = node->next;
}
}
bool string_linked_list_contains(struct StringLinkedList* node, char* string) {
int length1 = strlen(string);
while (node != NULL && node->string != NULL) {
int length2 = strlen(node->string);
if (length1 == length2 && (strcmp(string, node->string) == 0)) {
return true;
}
node = node->next;
}
return false;
}
bool string_linked_list_mismatch(struct StringLinkedList* a, struct StringLinkedList* b) {
struct StringLinkedList* a1 = a;
while (a1 != NULL && a1->string != NULL) {
if (!string_linked_list_contains(b, a1->string)) { return true; }
a1 = a1->next;
}
struct StringLinkedList* b1 = b;
while (b1 != NULL && b1->string != NULL) {
if (!string_linked_list_contains(a, b1->string)) { return true; }
b1 = b1->next;
}
return false;
}
int string_linked_list_count(struct StringLinkedList* node) {
int count = 0;
while (node != NULL) {
if (node->string != NULL) {
count++;
}
node = node->next;
}
return count;
}
void string_linked_list_free(struct StringLinkedList* node) {
struct StringLinkedList* head = node;
struct StringLinkedList* prevNode = head;
while (node != NULL) {
if (node->string != NULL) { free(node->string); }
node = node->next;
if (prevNode != NULL && prevNode != head) { free(prevNode); }
prevNode = node;
}
if (prevNode != NULL && prevNode != head) { free(prevNode); }
}

View file

@ -0,0 +1,15 @@
#ifndef STRING_LINKED_LIST_H
#define STRING_LINKED_LIST_H
struct StringLinkedList {
char* string;
struct StringLinkedList* next;
};
void string_linked_list_append(struct StringLinkedList* node, char* string);
bool string_linked_list_contains(struct StringLinkedList* node, char* string);
bool string_linked_list_mismatch(struct StringLinkedList* a, struct StringLinkedList* b);
int string_linked_list_count(struct StringLinkedList* node);
void string_linked_list_free(struct StringLinkedList* node);
#endif