mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-21 19:45:10 +00:00
Synchronized save files
Now when a client joins, it will request the entire 512 byte EEPROM from the server and refuse to continue until the server replies with the contents. Then the client will override all reads and writes to the EEPROM/save file. Thus, a client will never overwrite their local save. Fixes #21
This commit is contained in:
parent
1289f863ca
commit
4a2c218f11
12 changed files with 129 additions and 21 deletions
|
@ -3960,6 +3960,7 @@
|
|||
<ClCompile Include="..\src\pc\network\packets\packet_read_write.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_reliable.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_reservation.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_save_file.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_spawn_objects.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_spawn_star.c" />
|
||||
<ClCompile Include="..\src\pc\network\socket\socket.c" />
|
||||
|
|
|
@ -15009,6 +15009,9 @@
|
|||
<ClCompile Include="..\src\pc\network\packets\packet_custom.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_save_file.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\actors\common0.h">
|
||||
|
|
|
@ -570,7 +570,7 @@ void thread5_game_loop(UNUSED void *arg) {
|
|||
init_rumble_pak_scheduler_queue();
|
||||
init_controllers();
|
||||
create_thread_6();
|
||||
save_file_load_all();
|
||||
save_file_load_all(FALSE);
|
||||
|
||||
set_vblank_handler(2, &gGameVblankHandler, &gGameVblankQueue, (OSMesg) 1);
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "thread6.h"
|
||||
#include "macros.h"
|
||||
#include "pc/ini.h"
|
||||
#include "pc/network/network.h"
|
||||
|
||||
#define MENU_DATA_MAGIC 0x4849
|
||||
#define SAVE_FILE_MAGIC 0x4441
|
||||
|
@ -345,16 +346,17 @@ void save_file_do_save(s32 fileIndex) {
|
|||
if (fileIndex < 0 || fileIndex >= NUM_SAVE_FILES)
|
||||
return;
|
||||
|
||||
if (gSaveFileModified)
|
||||
#ifdef TEXTSAVES
|
||||
{
|
||||
if (gSaveFileModified && networkType != NT_CLIENT) {
|
||||
// Write to text file
|
||||
write_text_save(fileIndex);
|
||||
gSaveFileModified = FALSE;
|
||||
gMainMenuDataModified = FALSE;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
|
||||
if (gSaveFileModified) {
|
||||
// Compute checksum
|
||||
add_save_block_signature(&gSaveBuffer.files[fileIndex][0],
|
||||
sizeof(gSaveBuffer.files[fileIndex][0]), SAVE_FILE_MAGIC);
|
||||
|
@ -369,7 +371,6 @@ void save_file_do_save(s32 fileIndex) {
|
|||
gSaveFileModified = FALSE;
|
||||
}
|
||||
save_main_menu_data();
|
||||
#endif
|
||||
}
|
||||
|
||||
void save_file_erase(s32 fileIndex) {
|
||||
|
@ -396,7 +397,18 @@ BAD_RETURN(s32) save_file_copy(s32 srcFileIndex, s32 destFileIndex) {
|
|||
save_file_do_save(destFileIndex);
|
||||
}
|
||||
|
||||
void save_file_load_all(void) {
|
||||
#ifdef TEXTSAVES
|
||||
static void save_file_load_textsaves(void) {
|
||||
for (file = 0; file < NUM_SAVE_FILES; file++) {
|
||||
read_text_save(file);
|
||||
}
|
||||
gSaveFileModified = TRUE;
|
||||
gMainMenuDataModified = TRUE;
|
||||
stub_save_file_1();
|
||||
}
|
||||
#endif
|
||||
|
||||
void save_file_load_all(u8 reload) {
|
||||
s32 file;
|
||||
|
||||
gMainMenuDataModified = FALSE;
|
||||
|
@ -405,19 +417,19 @@ void save_file_load_all(void) {
|
|||
bzero(&gSaveBuffer, sizeof(gSaveBuffer));
|
||||
|
||||
#ifdef TEXTSAVES
|
||||
for (file = 0; file < NUM_SAVE_FILES; file++) {
|
||||
read_text_save(file);
|
||||
if (!reload) {
|
||||
save_file_load_textsaves();
|
||||
return;
|
||||
}
|
||||
gSaveFileModified = TRUE;
|
||||
gMainMenuDataModified = TRUE;
|
||||
#else
|
||||
s32 validSlots;
|
||||
#endif
|
||||
|
||||
read_eeprom_data(&gSaveBuffer, sizeof(gSaveBuffer));
|
||||
|
||||
if (save_file_need_bswap(&gSaveBuffer))
|
||||
save_file_bswap(&gSaveBuffer);
|
||||
|
||||
// Verify the main menu data and create a backup copy if only one of the slots is valid.
|
||||
s32 validSlots;
|
||||
validSlots = verify_save_block_signature(&gSaveBuffer.menuData[0], sizeof(gSaveBuffer.menuData[0]), MENU_DATA_MAGIC);
|
||||
validSlots |= verify_save_block_signature(&gSaveBuffer.menuData[1], sizeof(gSaveBuffer.menuData[1]),MENU_DATA_MAGIC) << 1;
|
||||
switch (validSlots) {
|
||||
|
@ -448,7 +460,6 @@ void save_file_load_all(void) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
#endif // TEXTSAVES
|
||||
stub_save_file_1();
|
||||
}
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ extern s8 gSaveFileModified;
|
|||
void save_file_do_save(s32 fileIndex);
|
||||
void save_file_erase(s32 fileIndex);
|
||||
BAD_RETURN(s32) save_file_copy(s32 srcFileIndex, s32 destFileIndex);
|
||||
void save_file_load_all(void);
|
||||
void save_file_load_all(u8 reload);
|
||||
void save_file_reload(void);
|
||||
void save_file_collect_star_or_key(s16 coinScore, s16 starIndex);
|
||||
s32 save_file_exists(s32 fileIndex);
|
||||
|
|
|
@ -382,6 +382,7 @@ void exit_join_to_network_menu(void) {
|
|||
&& sCursorClickingTimer == 2) {
|
||||
play_sound(SOUND_MENU_CAMERA_ZOOM_OUT, gDefaultSoundArgs);
|
||||
sMainMenuButtons[MENU_BUTTON_JOIN]->oMenuButtonState = MENU_BUTTON_STATE_SHRINKING;
|
||||
network_shutdown();
|
||||
keyboard_stop_text_input();
|
||||
}
|
||||
// End exit
|
||||
|
@ -399,7 +400,8 @@ void keyboard_exit_join_to_network_menu(void) {
|
|||
}
|
||||
|
||||
void join_server_as_client(void) {
|
||||
sCursorClickingTimer = 2;
|
||||
if (networkType != NT_NONE) { return; }
|
||||
|
||||
char delims[] = { ' ' };
|
||||
|
||||
// trim whitespace
|
||||
|
@ -420,8 +422,13 @@ void join_server_as_client(void) {
|
|||
return;
|
||||
}
|
||||
|
||||
keyboard_stop_text_input();
|
||||
network_init(NT_CLIENT, textInput, port);
|
||||
sSelectedFileNum = 1;
|
||||
}
|
||||
|
||||
void joined_server_as_client(s16 fileIndex) {
|
||||
if (networkType != NT_CLIENT) { return; }
|
||||
sSelectedFileNum = fileIndex;
|
||||
}
|
||||
|
||||
void render_network_mode_menu_buttons(struct Object* soundModeButton) {
|
||||
|
@ -3054,7 +3061,7 @@ s32 lvl_init_menu_values_and_cursor_pos(UNUSED s32 arg, UNUSED s32 unused) {
|
|||
sClickPos[0] = -10000;
|
||||
sClickPos[1] = -10000;
|
||||
sCursorClickingTimer = 0;
|
||||
sSelectedFileNum = 0;
|
||||
if (networkType != NT_CLIENT) { sSelectedFileNum = 0; }
|
||||
sSelectedFileIndex = MENU_BUTTON_NONE;
|
||||
sFadeOutText = FALSE;
|
||||
sStatusMessageID = 0;
|
||||
|
@ -3080,7 +3087,7 @@ s32 lvl_init_menu_values_and_cursor_pos(UNUSED s32 arg, UNUSED s32 unused) {
|
|||
sCursorPos[1] = -24.0f;
|
||||
|
||||
// immediately jump in
|
||||
if (networkType != NT_NONE) {
|
||||
if (networkType == NT_SERVER) {
|
||||
sSelectedFileNum = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -143,5 +143,6 @@ void bhv_menu_button_manager_loop(void);
|
|||
Gfx *geo_file_select_strings_and_menu_cursor(s32 callContext, UNUSED struct GraphNode *node, UNUSED Mat4 mtx);
|
||||
s32 lvl_init_menu_values_and_cursor_pos(UNUSED s32 arg, UNUSED s32 unused);
|
||||
s32 lvl_update_obj_and_load_file_selected(UNUSED s32 arg, UNUSED s32 unused);
|
||||
void joined_server_as_client(s16 fileIndex);
|
||||
|
||||
#endif // FILE_SELECT_H
|
||||
|
|
|
@ -34,6 +34,10 @@ void network_init(enum NetworkType inNetworkType, char* ip, char* port) {
|
|||
txAddr.sin_port = htons(atoi(port));
|
||||
txAddr.sin_addr.s_addr = inet_addr(ip);
|
||||
}
|
||||
|
||||
if (networkType == NT_CLIENT) {
|
||||
network_send_save_file_request();
|
||||
}
|
||||
}
|
||||
|
||||
void network_on_init_level(void) {
|
||||
|
@ -108,6 +112,8 @@ void network_update(void) {
|
|||
case PACKET_COLLECT_ITEM: network_receive_collect_item(&p); break;
|
||||
case PACKET_RESERVATION_REQUEST: network_receive_reservation_request(&p); break;
|
||||
case PACKET_RESERVATION: network_receive_reservation(&p); break;
|
||||
case PACKET_SAVE_FILE_REQUEST: network_receive_save_file_request(&p); break;
|
||||
case PACKET_SAVE_FILE: network_receive_save_file(&p); break;
|
||||
case PACKET_CUSTOM: network_receive_custom(&p); break;
|
||||
default: printf("%s received unknown packet: %d\n", NETWORKTYPESTR, p.buffer[0]);
|
||||
}
|
||||
|
@ -123,4 +129,5 @@ void network_update(void) {
|
|||
void network_shutdown(void) {
|
||||
if (networkType == NT_NONE) { return; }
|
||||
socket_close(gSocket);
|
||||
networkType = NT_NONE;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@ enum PacketType {
|
|||
PACKET_COLLECT_ITEM,
|
||||
PACKET_RESERVATION_REQUEST,
|
||||
PACKET_RESERVATION,
|
||||
PACKET_SAVE_FILE_REQUEST,
|
||||
PACKET_SAVE_FILE,
|
||||
PACKET_CUSTOM = 255,
|
||||
};
|
||||
|
||||
|
@ -127,10 +129,15 @@ void network_send_collect_item(struct Object* o);
|
|||
void network_receive_collect_item(struct Packet* p);
|
||||
|
||||
void network_send_reservation_request(void);
|
||||
void network_receive_reservation_request(struct Packet* p);
|
||||
void network_receive_reservation_request(UNUSED struct Packet* p);
|
||||
void network_send_reservation(void);
|
||||
void network_receive_reservation(struct Packet* p);
|
||||
|
||||
void network_send_save_file_request(void);
|
||||
void network_receive_save_file_request(UNUSED struct Packet* p);
|
||||
void network_send_save_file(void);
|
||||
void network_receive_save_file(struct Packet* p);
|
||||
|
||||
u8 network_register_custom_packet(void (*send_callback)(struct Packet* p, void* params), void (*receive_callback)(struct Packet* p));
|
||||
void network_send_custom(u8 customId, bool reliable, void* params);
|
||||
void network_receive_custom(struct Packet* p);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include <stdio.h>
|
||||
#include "../network.h"
|
||||
|
||||
#define MAX_CUSTOM_PACKETS 32
|
||||
#define MAX_CUSTOM_PACKETS 128
|
||||
|
||||
struct NetworkCustomPacket {
|
||||
void (*send_callback)(struct Packet* p, void* params);
|
||||
|
|
59
src/pc/network/packets/packet_save_file.c
Normal file
59
src/pc/network/packets/packet_save_file.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
#include <stdio.h>
|
||||
#include "../network.h"
|
||||
#include "object_fields.h"
|
||||
#include "object_constants.h"
|
||||
#include "behavior_table.h"
|
||||
#include "course_table.h"
|
||||
#include "src/game/interaction.h"
|
||||
#include "src/engine/math_util.h"
|
||||
#include "src/game/save_file.h"
|
||||
#include "src/menu/file_select.h"
|
||||
#include "src/pc/fs/fs.h"
|
||||
#include "PR/os_eeprom.h"
|
||||
|
||||
extern u8* gOverrideEeprom;
|
||||
static u8 eeprom[512] = { 0 };
|
||||
|
||||
void network_send_save_file_request(void) {
|
||||
assert(networkType == NT_CLIENT);
|
||||
|
||||
gOverrideEeprom = eeprom;
|
||||
|
||||
struct Packet p;
|
||||
packet_init(&p, PACKET_SAVE_FILE_REQUEST, true);
|
||||
network_send(&p);
|
||||
}
|
||||
|
||||
void network_receive_save_file_request(UNUSED struct Packet* p) {
|
||||
assert(networkType == NT_SERVER);
|
||||
network_send_save_file();
|
||||
}
|
||||
|
||||
void network_send_save_file(void) {
|
||||
assert(networkType == NT_SERVER);
|
||||
|
||||
fs_file_t* fp = fs_open(SAVE_FILENAME);
|
||||
if (fp != NULL) {
|
||||
fs_read(fp, eeprom, 512);
|
||||
fs_close(fp);
|
||||
}
|
||||
|
||||
struct Packet p;
|
||||
packet_init(&p, PACKET_SAVE_FILE, true);
|
||||
packet_write(&p, &gCurrSaveFileNum, sizeof(s16));
|
||||
packet_write(&p, eeprom, sizeof(u8) * 512);
|
||||
network_send(&p);
|
||||
}
|
||||
|
||||
void network_receive_save_file(struct Packet* p) {
|
||||
assert(networkType == NT_CLIENT);
|
||||
|
||||
gOverrideEeprom = eeprom;
|
||||
|
||||
// find all reserved objects
|
||||
packet_read(p, &gCurrSaveFileNum, sizeof(s16));
|
||||
packet_read(p, eeprom, sizeof(u8) * 512);
|
||||
|
||||
save_file_load_all(TRUE);
|
||||
joined_server_as_client(gCurrSaveFileNum);
|
||||
}
|
|
@ -9,6 +9,8 @@
|
|||
#include <emscripten.h>
|
||||
#endif
|
||||
|
||||
u8* gOverrideEeprom = NULL;
|
||||
|
||||
extern OSMgrArgs piMgrArgs;
|
||||
|
||||
u64 osClockRate = 62500000;
|
||||
|
@ -124,6 +126,11 @@ s32 osEepromProbe(UNUSED OSMesgQueue *mq) {
|
|||
}
|
||||
|
||||
s32 osEepromLongRead(UNUSED OSMesgQueue *mq, u8 address, u8 *buffer, int nbytes) {
|
||||
if (gOverrideEeprom != NULL) {
|
||||
memcpy(buffer, gOverrideEeprom + address * 8, nbytes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 content[512];
|
||||
s32 ret = -1;
|
||||
|
||||
|
@ -162,6 +169,11 @@ s32 osEepromLongRead(UNUSED OSMesgQueue *mq, u8 address, u8 *buffer, int nbytes)
|
|||
}
|
||||
|
||||
s32 osEepromLongWrite(UNUSED OSMesgQueue *mq, u8 address, u8 *buffer, int nbytes) {
|
||||
if (gOverrideEeprom != NULL) {
|
||||
memcpy(gOverrideEeprom + address * 8, buffer, nbytes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 content[512] = {0};
|
||||
if (address != 0 || nbytes != 512) {
|
||||
osEepromLongRead(mq, 0, content, 512);
|
||||
|
|
Loading…
Reference in a new issue