General network code clean up

Marked globals, rearranged functions, added comments
This commit is contained in:
MysterD 2020-09-06 11:02:41 -07:00
parent bed036bcfb
commit b9750057d5
21 changed files with 186 additions and 160 deletions

View file

@ -72,7 +72,7 @@ u16 random_u16(void) {
// override this function for synchronized entities
if (gCurrentObject->oSyncID != 0) {
struct SyncObject* so = &syncObjects[gCurrentObject->oSyncID];
struct SyncObject* so = &gSyncObjects[gCurrentObject->oSyncID];
if (so->o != NULL && !so->keepRandomSeed) {
gSavedSeed16 = gRandomSeed16;
force_replicable_seed(FALSE);

View file

@ -537,7 +537,7 @@ void bhv_boo_loop(void) {
else {
if (network_sync_object_initialized(o)) {
network_send_object_reliability(o, TRUE);
network_forget_sync_object(&syncObjects[o->oSyncID]);
network_forget_sync_object(&gSyncObjects[o->oSyncID]);
}
}
@ -752,7 +752,7 @@ void bhv_big_boo_loop(void) {
} else if (o->oHealth <= 0) {
if (network_sync_object_initialized(o)) {
network_send_object_reliability(o, TRUE);
network_forget_sync_object(&syncObjects[o->oSyncID]);
network_forget_sync_object(&gSyncObjects[o->oSyncID]);
}
}
@ -858,7 +858,7 @@ void bhv_merry_go_round_boo_manager_loop(void) {
switch (o->oAction) {
case 0:
if (distanceToPlayer < 1000.0f) {
if (networkType == NT_SERVER && o->oMerryGoRoundBooManagerNumBoosKilled < 5) {
if (gNetworkType == NT_SERVER && o->oMerryGoRoundBooManagerNumBoosKilled < 5) {
if (o->oMerryGoRoundBooManagerNumBoosSpawned < 5) {
if (o->oMerryGoRoundBooManagerNumBoosSpawned - o->oMerryGoRoundBooManagerNumBoosKilled < 2) {
struct Object* boo = spawn_object(o, MODEL_BOO, bhvMerryGoRoundBoo);
@ -877,7 +877,7 @@ void bhv_merry_go_round_boo_manager_loop(void) {
}
if (o->oMerryGoRoundBooManagerNumBoosKilled > 4) {
if (networkType == NT_SERVER) {
if (gNetworkType == NT_SERVER) {
struct Object* boo = spawn_object(o, MODEL_BOO, bhvMerryGoRoundBigBoo);
obj_copy_behavior_params(boo, o);

View file

@ -12,7 +12,7 @@ void bhv_wf_breakable_wall_loop(void) {
if (!o->oBreakableWallForce) {
o->oBreakableWallForce = TRUE;
network_send_object(o);
syncObjects[o->oSyncID].syncDeathEvent = FALSE;
gSyncObjects[o->oSyncID].syncDeathEvent = FALSE;
}
if (cur_obj_has_behavior(bhvWfBreakableWallRight))
play_puzzle_jingle();

View file

@ -4,7 +4,7 @@ void bhv_cannon_closed_init(void) {
struct Object *cannon;
if (save_file_is_cannon_unlocked() == 1) {
if (!networkLevelLoaded || networkType == NT_SERVER) {
if (!gNetworkLevelLoaded || gNetworkType == NT_SERVER) {
// If the cannon is open, spawn a cannon and despawn the object.
cannon = spawn_object(o, MODEL_CANNON_BASE, bhvCannon);
cannon->parentObj = cannon;
@ -12,7 +12,7 @@ void bhv_cannon_closed_init(void) {
cannon->oPosX = o->oHomeX;
cannon->oPosY = o->oHomeY;
cannon->oPosZ = o->oHomeZ;
if (networkLevelLoaded) {
if (gNetworkLevelLoaded) {
network_set_sync_id(cannon);
struct Object* spawn_objects[] = { cannon };
u32 models[] = { MODEL_CANNON_BASE };

View file

@ -173,11 +173,11 @@ void bookshelf_manager_act_0(void) {
void bookshelf_manager_act_1(void) {
struct MarioState* marioState = nearest_mario_state_to_object(o);
if (o->oBookSwitchManagerUnkF8 == 0) {
if (networkType == NT_SERVER && obj_is_near_to_and_facing_mario(marioState, 500.0f, 0x3000)) {
if (gNetworkType == NT_SERVER && obj_is_near_to_and_facing_mario(marioState, 500.0f, 0x3000)) {
o->oBookSwitchManagerUnkF8 = 1;
network_send_object(o);
}
} else if (o->oTimer > 60 && networkType == NT_SERVER) {
} else if (o->oTimer > 60 && gNetworkType == NT_SERVER) {
o->oAction = 2;
o->oBookSwitchManagerUnkF8 = 0;
network_send_object(o);
@ -188,12 +188,12 @@ void bookshelf_manager_act_2(void) {
if (!(o->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM)) {
if (o->oBookSwitchManagerUnkF4 < 0) {
if (o->oTimer > 30) {
if (networkType == NT_SERVER) {
if (gNetworkType == NT_SERVER) {
o->oBookSwitchManagerUnkF4 = o->oBookSwitchManagerUnkF8 = 0;
network_send_object(o);
}
} else if (o->oTimer > 10) {
if (networkType == NT_SERVER) {
if (gNetworkType == NT_SERVER) {
o->oBookSwitchManagerUnkF8 = 1;
network_send_object(o);
}
@ -201,7 +201,7 @@ void bookshelf_manager_act_2(void) {
} else {
if (o->oBookSwitchManagerUnkF4 >= 3) {
if (o->oTimer > 100) {
if (networkType == NT_SERVER) {
if (gNetworkType == NT_SERVER) {
o->parentObj = cur_obj_nearest_object_with_behavior(bhvHauntedBookshelf);
o->parentObj->oAction = 1;
o->oPosX = o->parentObj->oPosX;
@ -216,7 +216,7 @@ void bookshelf_manager_act_2(void) {
o->oTimer = 0;
}
}
} else if (networkType == NT_SERVER) {
} else if (gNetworkType == NT_SERVER) {
o->oAction = 4;
network_send_object(o);
}
@ -224,7 +224,7 @@ void bookshelf_manager_act_2(void) {
void bookshelf_manager_act_3(void) {
if (o->oTimer > 85) {
if (networkType == NT_SERVER) {
if (gNetworkType == NT_SERVER) {
o->oAction = 4;
network_send_object(o);
}
@ -237,7 +237,7 @@ void bookshelf_manager_act_3(void) {
void bookshelf_manager_act_4(void) {
if (o->oBookSwitchManagerUnkF4 >= 3) {
obj_mark_for_deletion(o);
} else if (networkType == NT_SERVER) {
} else if (gNetworkType == NT_SERVER) {
o->oAction = 0;
network_send_object(o);
}
@ -308,7 +308,7 @@ void bhv_book_switch_loop(void) {
cur_obj_become_intangible();
}
if (networkType == NT_SERVER && o->oAction != 1) {
if (gNetworkType == NT_SERVER && o->oAction != 1) {
o->oAction = 1;
network_send_object(o);
}
@ -320,7 +320,7 @@ void bhv_book_switch_loop(void) {
if (approach_f32_ptr(&o->oBookSwitchUnkF4, 50.0f, 20.0f)) {
if (o->parentObj->oBookSwitchManagerUnkF4 >= 0 && o->oTimer > 60) {
if (sp3C == 1 || sp3C == 2 || sp3C == 6) {
if (networkType == NT_SERVER && o->oAction != 2) {
if (gNetworkType == NT_SERVER && o->oAction != 2) {
o->oAction = 2;
network_send_object(o);
}
@ -335,7 +335,7 @@ void bhv_book_switch_loop(void) {
if (o->oAction != 0) {
if (o->parentObj->oBookSwitchManagerUnkF4 == o->oBehParams2ndByte) {
play_sound(SOUND_GENERAL2_RIGHT_ANSWER, gDefaultSoundArgs);
if (networkType == NT_SERVER) {
if (gNetworkType == NT_SERVER) {
o->parentObj->oBookSwitchManagerUnkF4 += 1;
network_send_object(o->parentObj);
}
@ -348,7 +348,7 @@ void bhv_book_switch_loop(void) {
sp34 = 0;
}
if (networkType == NT_SERVER) {
if (gNetworkType == NT_SERVER) {
book = spawn_object_abs_with_rot(o, 0, MODEL_BOOKEND, bhvFlyingBookend,
0x1FC * sp36 - 0x8CA, 890, sp34, 0,
0x8000 * sp36 + 0x4000, 0);
@ -361,13 +361,13 @@ void bhv_book_switch_loop(void) {
}
}
if (networkType == NT_SERVER) {
if (gNetworkType == NT_SERVER) {
o->parentObj->oBookSwitchManagerUnkF4 = -1;
network_send_object(o->parentObj);
}
}
if (networkType == NT_SERVER && o->oAction != 0) {
if (gNetworkType == NT_SERVER && o->oAction != 0) {
o->oAction = 0;
network_send_object(o);
}

View file

@ -296,7 +296,7 @@ void render_hud_mario_lives(void) {
#ifdef VERSION_JP
char* displayHead = ",";
#else
char* displayHead = (networkType == NT_SERVER) ? "," : ".";
char* displayHead = (gNetworkType == NT_SERVER) ? "," : ".";
#endif
print_text(GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(22), HUD_TOP_Y, displayHead); // 'Mario Head' glyph
if (gHudDisplay.lives == -1) { return; }

View file

@ -681,7 +681,7 @@ void initiate_painting_warp(void) {
} else if (pWarpNode->id != 0) {
initiate_painting_warp_node(pWarpNode, false);
gControlPainting = true;
gWaitingForRemotePainting = (networkType != NT_NONE);
gWaitingForRemotePainting = (gNetworkType != NT_NONE);
set_mario_action(gMarioState, ACT_DISAPPEARED, 0);
gMarioState->marioObj->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
}
@ -1028,14 +1028,14 @@ s32 play_mode_normal(void) {
if (sWarpDest.type == WARP_TYPE_NOT_WARPING) {
set_play_mode(PLAY_MODE_CHANGE_LEVEL);
} else {
set_play_mode((networkType != NT_NONE) ? PLAY_MODE_SYNC_LEVEL : PLAY_MODE_CHANGE_LEVEL);
set_play_mode((gNetworkType != NT_NONE) ? PLAY_MODE_SYNC_LEVEL : PLAY_MODE_CHANGE_LEVEL);
network_send_level_warp();
}
} else if (sTransitionTimer != 0) {
if (sWarpDest.type == WARP_TYPE_NOT_WARPING || gCurrentArea->index == sWarpDest.areaIdx) {
set_play_mode(PLAY_MODE_CHANGE_AREA);
} else {
set_play_mode((networkType != NT_NONE) ? PLAY_MODE_SYNC_LEVEL : PLAY_MODE_CHANGE_AREA);
set_play_mode((gNetworkType != NT_NONE) ? PLAY_MODE_SYNC_LEVEL : PLAY_MODE_CHANGE_AREA);
network_send_level_warp();
}
} else if (pressed_pause()) {
@ -1065,7 +1065,7 @@ s32 play_mode_paused(void) {
fade_into_special_warp(0, 0);
gSavedCourseNum = COURSE_NONE;
}
set_play_mode((networkType != NT_NONE) ? PLAY_MODE_SYNC_LEVEL : PLAY_MODE_CHANGE_LEVEL);
set_play_mode((gNetworkType != NT_NONE) ? PLAY_MODE_SYNC_LEVEL : PLAY_MODE_CHANGE_LEVEL);
network_send_level_warp();
} else if (gPauseScreenMode == 3) {
// We should only be getting "int 3" to here

View file

@ -1877,7 +1877,7 @@ s32 execute_mario_action(UNUSED struct Object *o) {
}
// two-player hack: drop held object if server is holding it
if (networkType == NT_CLIENT && gMarioState->playerIndex == 0 && gMarioState->heldObj != NULL) {
if (gNetworkType == NT_CLIENT && gMarioState->playerIndex == 0 && gMarioState->heldObj != NULL) {
u8 inCutscene = ((gMarioState->action & ACT_GROUP_MASK) != ACT_GROUP_CUTSCENE);
if (!inCutscene && gMarioState->heldObj == gMarioStates[0].heldObj) {
drop_and_set_mario_action(gMarioState, ACT_IDLE, 0);
@ -2027,7 +2027,7 @@ void init_mario(void) {
vec3f_set(gMarioState->vel, 0, 0, 0);
// two-player hack
if ((networkType == NT_CLIENT && isLocal) || (networkType == NT_SERVER && !isLocal)) {
if ((gNetworkType == NT_CLIENT && isLocal) || (gNetworkType == NT_SERVER && !isLocal)) {
gMarioState->pos[0] += 50.0f * coss(gMarioState->faceAngle[1]);
gMarioState->pos[2] += 50.0f * sins(gMarioState->faceAngle[1]);
} else {
@ -2076,9 +2076,9 @@ void init_mario(void) {
// set mario/luigi model
if (isLocal) {
gMarioState->marioObj->header.gfx.sharedChild = gLoadedGraphNodes[(networkType == NT_SERVER) ? MODEL_MARIO : MODEL_LUIGI];
gMarioState->marioObj->header.gfx.sharedChild = gLoadedGraphNodes[(gNetworkType == NT_SERVER) ? MODEL_MARIO : MODEL_LUIGI];
} else {
gMarioState->marioObj->header.gfx.sharedChild = gLoadedGraphNodes[(networkType == NT_SERVER) ? MODEL_LUIGI2 : MODEL_MARIO2];
gMarioState->marioObj->header.gfx.sharedChild = gLoadedGraphNodes[(gNetworkType == NT_SERVER) ? MODEL_LUIGI2 : MODEL_MARIO2];
}
skippy:

View file

@ -1166,7 +1166,7 @@ void cur_obj_get_thrown_or_placed(f32 forwardVel, f32 velY, s32 thrownAction) {
cur_obj_move_after_thrown_or_dropped(forwardVel, velY);
}
if (o->oSyncID != 0 && syncObjects[o->oSyncID].owned) {
if (o->oSyncID != 0 && gSyncObjects[o->oSyncID].owned) {
network_send_object(o);
}
}
@ -1178,7 +1178,7 @@ void cur_obj_get_dropped(void) {
o->oHeldState = HELD_FREE;
cur_obj_move_after_thrown_or_dropped(0.0f, 0.0f);
if (o->oSyncID != 0 && syncObjects[o->oSyncID].owned) {
if (o->oSyncID != 0 && gSyncObjects[o->oSyncID].owned) {
network_send_object(o);
}
}

View file

@ -347,7 +347,7 @@ void save_file_do_save(s32 fileIndex) {
return;
#ifdef TEXTSAVES
if (gSaveFileModified && networkType != NT_CLIENT) {
if (gSaveFileModified && gNetworkType != NT_CLIENT) {
// Write to text file
write_text_save(fileIndex);
gSaveFileModified = FALSE;

View file

@ -198,7 +198,7 @@ void unload_object(struct Object *obj) {
obj->header.gfx.node.flags &= ~GRAPH_RENDER_CYLBOARD;
obj->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
if (obj->oSyncID != 0 && syncObjects[obj->oSyncID].syncDeathEvent) {
if (obj->oSyncID != 0 && gSyncObjects[obj->oSyncID].syncDeathEvent) {
network_send_object(obj);
}

View file

@ -403,7 +403,7 @@ void keyboard_exit_join_to_network_menu(void) {
}
void join_server_as_client(void) {
if (networkType != NT_NONE) { return; }
if (gNetworkType != NT_NONE) { return; }
char delims[] = { ' ' };
@ -441,7 +441,7 @@ void join_server_as_client(void) {
}
void joined_server_as_client(s16 fileIndex) {
if (networkType != NT_CLIENT) { return; }
if (gNetworkType != NT_CLIENT) { return; }
sSelectedFileNum = fileIndex;
}
@ -561,7 +561,7 @@ void print_join_mode_menu_strings(void) {
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (12 * 2), gTextInput);
// Print status
if (networkType == NT_CLIENT) {
if (gNetworkType == NT_CLIENT) {
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (12 * 14), "Connecting...");
} else if (strlen(gTextInput) > 0) {
print_generic_ascii_string(JOIN_LEVEL_NAME_X, 191 - (12 * 14), "Press (ENTER) to join.");
@ -1856,7 +1856,7 @@ void handle_cursor_button_input(void) {
sClickPos[1] = sCursorPos[1];
sCursorClickingTimer = 1;
}
if (networkType == NT_SERVER) {
if (gNetworkType == NT_SERVER) {
sClickPos[0] = sCursorPos[0];
sClickPos[1] = sCursorPos[1];
sCursorClickingTimer = 1;
@ -3092,7 +3092,7 @@ s32 lvl_init_menu_values_and_cursor_pos(UNUSED s32 arg, UNUSED s32 unused) {
sClickPos[0] = -10000;
sClickPos[1] = -10000;
sCursorClickingTimer = 0;
if (networkType != NT_CLIENT) { sSelectedFileNum = 0; }
if (gNetworkType != NT_CLIENT) { sSelectedFileNum = 0; }
sSelectedFileIndex = MENU_BUTTON_NONE;
sFadeOutText = FALSE;
sStatusMessageID = 0;
@ -3118,7 +3118,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_SERVER) {
if (gNetworkType == NT_SERVER) {
sSelectedFileNum = configHostSaveSlot;
}

View file

@ -5,67 +5,76 @@
#include "socket/socket.h"
#include "pc/configfile.h"
enum NetworkType networkType;
// Mario 64 specific externs
extern u8 gInsidePainting;
extern s16 sCurrPlayMode;
enum NetworkType gNetworkType;
static SOCKET gSocket;
struct sockaddr_in txAddr;
#define LOADING_LEVEL_THRESHOLD 10
u8 networkLoadingLevel = 0;
bool networkLevelLoaded = false;
bool gNetworkLevelLoaded = false;
struct ServerSettings gServerSettings = {
.playerInteractions = PLAYER_INTERACTIONS_SOLID,
};
void network_init(enum NetworkType inNetworkType, char* ip, unsigned int port) {
networkType = inNetworkType;
if (networkType == NT_NONE) { return; }
// set network type
gNetworkType = inNetworkType;
if (gNetworkType == NT_NONE) { return; }
// sanity check port
if (port == 0) {
port = (networkType == NT_CLIENT) ? configJoinPort : configHostPort;
port = (gNetworkType == NT_CLIENT) ? configJoinPort : configHostPort;
if (port == 0) { port = DEFAULT_PORT; }
}
if (networkType == NT_SERVER) {
// set server settings
if (gNetworkType == NT_SERVER) {
gServerSettings.playerInteractions = configPlayerInteraction;
}
// Create a receiver socket to receive datagrams
// create a receiver socket to receive datagrams
gSocket = socket_initialize();
if (gSocket == INVALID_SOCKET) { return; }
// Bind the socket to any address and the specified port.
if (networkType == NT_SERVER) {
// connect
if (gNetworkType == NT_SERVER) {
// bind the socket to any address and the specified port.
int rc = socket_bind(gSocket, port);
if (rc != NO_ERROR) { return; }
} else {
// Save the port to send to
// save the port to send to
txAddr.sin_family = AF_INET;
txAddr.sin_port = htons(port);
txAddr.sin_addr.s_addr = inet_addr(ip);
}
if (networkType == NT_CLIENT) {
// send connection request
if (gNetworkType == NT_CLIENT) {
network_send_save_file_request();
}
}
void network_on_init_level(void) {
// reset loading timer
networkLoadingLevel = 0;
networkLevelLoaded = false;
gNetworkLevelLoaded = false;
}
void network_on_loaded_level(void) {
if (networkType == NT_CLIENT) {
// request my chunk of reserved sync ids
if (gNetworkType == NT_CLIENT) {
network_send_reservation_request();
}
}
void network_send(struct Packet* p) {
// sanity checks
if (networkType == NT_NONE) { return; }
if (gNetworkType == NT_NONE) { return; }
if (p->error) { printf("%s packet error!\n", NETWORKTYPESTR); return; }
// remember reliable packets
@ -82,14 +91,17 @@ void network_send(struct Packet* p) {
}
void network_update(void) {
if (networkType == NT_NONE) { return; }
if (!networkLevelLoaded) {
if (gNetworkType == NT_NONE) { return; }
// check for level loaded event
if (!gNetworkLevelLoaded) {
if (networkLoadingLevel++ >= LOADING_LEVEL_THRESHOLD) {
networkLevelLoaded = true;
gNetworkLevelLoaded = true;
network_on_loaded_level();
}
}
// figure out which update loop to run
if (gInsidePainting && sCurrPlayMode == PLAY_MODE_CHANGE_LEVEL) {
network_update_inside_painting();
} else if (sCurrPlayMode == PLAY_MODE_NORMAL) {
@ -97,6 +109,7 @@ void network_update(void) {
network_update_objects();
}
// receive packets
do {
// receive packet
struct Packet p = { .cursor = 3 };
@ -139,7 +152,8 @@ void network_update(void) {
}
void network_shutdown(void) {
if (networkType == NT_NONE) { return; }
if (gNetworkType == NT_NONE) { return; }
// close down socket
socket_close(gSocket);
networkType = NT_NONE;
gNetworkType = NT_NONE;
}

View file

@ -7,13 +7,16 @@
#include <assert.h>
#include "../cliopts.h"
// Mario 64 specific externs
extern struct MarioState gMarioStates[];
#define SYNC_DISTANCE_ONLY_DEATH -1.0f
#define SYNC_DISTANCE_ONLY_EVENTS -2.0f
#define SYNC_DISTANCE_INFINITE 0
#define MAX_SYNC_OBJECTS 256
#define MAX_SYNC_OBJECTS 256 // note: increasing this requires code to be rewritten
#define MAX_SYNC_OBJECT_FIELDS 64
#define PACKET_LENGTH 1024
#define NETWORKTYPESTR (networkType == NT_CLIENT ? "Client" : "Server")
#define NETWORKTYPESTR (gNetworkType == NT_CLIENT ? "Client" : "Server")
enum PacketType {
PACKET_ACK,
@ -72,83 +75,92 @@ struct ServerSettings {
enum PlayerInteractions playerInteractions;
};
extern struct MarioState gMarioStates[];
extern u8 gInsidePainting;
extern s16 sCurrPlayMode;
extern enum NetworkType networkType;
extern struct SyncObject syncObjects[];
extern bool networkLevelLoaded;
// Networking-specific externs
extern bool gNetworkLevelLoaded;
extern enum NetworkType gNetworkType;
extern struct SyncObject gSyncObjects[];
extern struct ServerSettings gServerSettings;
// network.c
void network_init(enum NetworkType inNetworkType, char* ip, unsigned int port);
void network_on_init_level(void);
void network_on_loaded_level(void);
void network_clear_sync_objects(void);
struct SyncObject* network_init_object(struct Object *object, float maxSyncDistance);
void network_init_object_field(struct Object* o, void* field);
void network_send(struct Packet* p);
void network_update(void);
void network_shutdown(void);
// packet read / write
// packet_read_write.c
void packet_init(struct Packet* packet, enum PacketType packetType, bool reliable);
void packet_write(struct Packet* packet, void* data, u16 length);
void packet_read(struct Packet* packet, void* data, u16 length);
u32 packet_hash(struct Packet* packet);
bool packet_check_hash(struct Packet* packet);
// packet headers
// packet_reliable.c
void network_send_ack(struct Packet* p);
void network_receive_ack(struct Packet* p);
void network_remember_reliable(struct Packet* p);
void network_update_reliable(void);
// packet_player.c
void network_update_player(void);
void network_receive_player(struct Packet* p);
void network_forget_sync_object(struct SyncObject* so);
// packet_object.c
struct SyncObject* network_init_object(struct Object* object, float maxSyncDistance);
void network_init_object_field(struct Object* o, void* field);
bool network_owns_object(struct Object* o);
void network_set_sync_id(struct Object* o);
bool network_sync_object_initialized(struct Object* o);
void network_update_objects(void);
void network_clear_sync_objects(void);
void network_set_sync_id(struct Object* o);
void network_send_object(struct Object* o);
void network_send_object_reliability(struct Object* o, bool reliable);
void network_receive_object(struct Packet* p);
void network_forget_sync_object(struct SyncObject* so);
void network_update_objects(void);
// packet_spawn_object.c
void network_send_spawn_objects(struct Object* objects[], u32 models[], u8 objectCount);
void network_receive_spawn_objects(struct Packet* p);
// packet_spawn_star.c
void network_send_spawn_star(struct Object* o, u8 starType, f32 x, f32 y, f32 z, u32 behParams);
void network_receive_spawn_star(struct Packet* p);
// packet_level_warp.c
void network_send_level_warp(void);
void network_receive_level_warp(struct Packet* p);
// packet_inside_painting.c
void network_update_inside_painting(void);
void network_send_inside_painting(void);
void network_receive_inside_painting(struct Packet* p);
// packet_collect_star.c
void network_send_collect_star(struct Object* o, s16 coinScore, s16 starIndex);
void network_receive_collect_star(struct Packet* p);
// packet_collect_coin.c
void network_send_collect_coin(struct Object* o);
void network_receive_collect_coin(struct Packet* p);
// packet_collect_item.c
void network_send_collect_item(struct Object* o);
void network_receive_collect_item(struct Packet* p);
// packet_reservation.c
void network_send_reservation_request(void);
void network_receive_reservation_request(UNUSED struct Packet* p);
void network_send_reservation(void);
void network_receive_reservation(struct Packet* p);
// packet_save_file.c
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);
// packet_custom.c
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);

View file

@ -42,7 +42,7 @@ void network_receive_inside_painting(struct Packet* p) {
struct PacketDataInsidePainting remote = { 0 };
packet_read(p, &remote, sizeof(struct PacketDataInsidePainting));
if (networkType == NT_CLIENT && gControlPainting && remote.controlPainting) {
if (gNetworkType == NT_CLIENT && gControlPainting && remote.controlPainting) {
// we both think we should control the painting, host wins the tie
gControlPainting = false;
}

View file

@ -53,7 +53,7 @@ void network_receive_level_warp(struct Packet* p) {
case WARP_TYPE_CHANGE_LEVEL: sCurrPlayMode = PLAY_MODE_CHANGE_LEVEL; break;
}
} else {
if (networkType == NT_CLIENT) {
if (gNetworkType == NT_CLIENT) {
if (remoteWarpDest.type == WARP_TYPE_NOT_WARPING) { return; }
// two-player hack: would need to use player index as priority
sWarpDest = remoteWarpDest;

View file

@ -9,10 +9,10 @@
#include "src/game/object_helpers.h"
static u8 nextSyncID = 1;
struct SyncObject syncObjects[MAX_SYNC_OBJECTS] = { 0 };
struct SyncObject gSyncObjects[MAX_SYNC_OBJECTS] = { 0 };
// todo: move this to somewhere more general
float player_distance(struct MarioState* marioState, struct Object* o) {
static float player_distance(struct MarioState* marioState, struct Object* o) {
if (marioState->marioObj == NULL) { return 0; }
f32 mx = marioState->marioObj->header.gfx.pos[0] - o->oPosX;
f32 my = marioState->marioObj->header.gfx.pos[1] - o->oPosY;
@ -23,29 +23,16 @@ float player_distance(struct MarioState* marioState, struct Object* o) {
return sqrt(mx + my + mz);
}
void network_clear_sync_objects(void) {
for (u16 i = 0; i < MAX_SYNC_OBJECTS; i++) {
network_forget_sync_object(&syncObjects[i]);
static bool should_own_object(struct SyncObject* so) {
if (gMarioStates[0].heldByObj == so->o) { return true; }
for (int i = 0; i < MAX_PLAYERS; i++) {
if (gMarioStates[i].heldByObj == so->o) { return false; }
}
nextSyncID = 1;
}
void network_set_sync_id(struct Object* o) {
if (o->oSyncID != 0) { return; }
// two-player hack
u8 reserveId = (networkLevelLoaded && networkType == NT_CLIENT) ? 1 : 0;
for (u16 i = 0; i < MAX_SYNC_OBJECTS; i++) {
if (syncObjects[nextSyncID].reserved == reserveId && syncObjects[nextSyncID].o == NULL) { break; }
nextSyncID = (nextSyncID + 1) % MAX_SYNC_OBJECTS;
}
assert(syncObjects[nextSyncID].o == NULL);
assert(syncObjects[nextSyncID].reserved == reserveId);
o->oSyncID = nextSyncID;
nextSyncID = (nextSyncID + 1) % MAX_SYNC_OBJECTS;
assert(o->oSyncID < MAX_SYNC_OBJECTS);
if (so->o->oHeldState == HELD_HELD && so->o->heldByPlayerIndex == 0) { return true; }
if (player_distance(&gMarioStates[0], so->o) > player_distance(&gMarioStates[1], so->o)) { return false; }
if (so->o->oHeldState == HELD_HELD && so->o->heldByPlayerIndex != 0) { return false; }
return true;
}
struct SyncObject* network_init_object(struct Object *o, float maxSyncDistance) {
@ -53,7 +40,7 @@ struct SyncObject* network_init_object(struct Object *o, float maxSyncDistance)
network_set_sync_id(o);
// set default values for sync object
struct SyncObject* so = &syncObjects[o->oSyncID];
struct SyncObject* so = &gSyncObjects[o->oSyncID];
so->o = o;
so->reserved = 0;
so->maxSyncDistance = maxSyncDistance;
@ -77,27 +64,52 @@ struct SyncObject* network_init_object(struct Object *o, float maxSyncDistance)
void network_init_object_field(struct Object *o, void* field) {
assert(o->oSyncID != 0);
// remember to synchronize this extra field
struct SyncObject* so = &syncObjects[o->oSyncID];
struct SyncObject* so = &gSyncObjects[o->oSyncID];
u8 index = so->extraFieldCount++;
so->extraFields[index] = field;
}
bool network_owns_object(struct Object* o) {
struct SyncObject* so = &syncObjects[o->oSyncID];
struct SyncObject* so = &gSyncObjects[o->oSyncID];
if (so == NULL) { return false; }
return so->owned;
}
bool network_sync_object_initialized(struct Object* o) {
if (o->oSyncID == 0) { return false; }
if (syncObjects[o->oSyncID].behavior == NULL) { return false; }
if (gSyncObjects[o->oSyncID].behavior == NULL) { return false; }
return true;
}
void network_clear_sync_objects(void) {
for (u16 i = 0; i < MAX_SYNC_OBJECTS; i++) {
network_forget_sync_object(&gSyncObjects[i]);
}
nextSyncID = 1;
}
void network_set_sync_id(struct Object* o) {
if (o->oSyncID != 0) { return; }
// two-player hack
u8 reserveId = (gNetworkLevelLoaded && gNetworkType == NT_CLIENT) ? 1 : 0;
for (u16 i = 0; i < MAX_SYNC_OBJECTS; i++) {
if (gSyncObjects[nextSyncID].reserved == reserveId && gSyncObjects[nextSyncID].o == NULL) { break; }
nextSyncID = (nextSyncID + 1) % MAX_SYNC_OBJECTS;
}
assert(gSyncObjects[nextSyncID].o == NULL);
assert(gSyncObjects[nextSyncID].reserved == reserveId);
o->oSyncID = nextSyncID;
nextSyncID = (nextSyncID + 1) % MAX_SYNC_OBJECTS;
assert(o->oSyncID < MAX_SYNC_OBJECTS);
}
// ----- header ----- //
static void packet_write_object_header(struct Packet* p, struct Object* o) {
struct SyncObject* so = &syncObjects[o->oSyncID];
struct SyncObject* so = &gSyncObjects[o->oSyncID];
enum BehaviorId behaviorId = get_id_from_behavior(o->behavior);
packet_write(p, &o->oSyncID, sizeof(u32));
@ -130,14 +142,14 @@ static struct SyncObject* packet_read_object_header(struct Packet* p) {
}
// extract object, sanity check
struct Object* o = syncObjects[syncId].o;
struct Object* o = gSyncObjects[syncId].o;
if (o == NULL) {
printf("%s invalid SyncObject!\n", NETWORKTYPESTR);
return NULL;
}
// retrieve SyncObject, check if we should update using callback
struct SyncObject* so = &syncObjects[syncId];
struct SyncObject* so = &gSyncObjects[syncId];
if (so->ignore_if_true != NULL && (*so->ignore_if_true)(so->o)) {
return NULL;
}
@ -167,7 +179,7 @@ static struct SyncObject* packet_read_object_header(struct Packet* p) {
// ----- full sync ----- //
static void packet_write_object_full_sync(struct Packet* p, struct Object* o) {
struct SyncObject* so = &syncObjects[o->oSyncID];
struct SyncObject* so = &gSyncObjects[o->oSyncID];
if (!so->fullObjectSync) { return; }
// write all of raw data
@ -175,7 +187,7 @@ static void packet_write_object_full_sync(struct Packet* p, struct Object* o) {
}
static void packet_read_object_full_sync(struct Packet* p, struct Object* o) {
struct SyncObject* so = &syncObjects[o->oSyncID];
struct SyncObject* so = &gSyncObjects[o->oSyncID];
if (!so->fullObjectSync) { return; }
// read all of raw data
@ -185,7 +197,7 @@ static void packet_read_object_full_sync(struct Packet* p, struct Object* o) {
// ----- standard fields ----- //
static void packet_write_object_standard_fields(struct Packet* p, struct Object* o) {
struct SyncObject* so = &syncObjects[o->oSyncID];
struct SyncObject* so = &gSyncObjects[o->oSyncID];
if (so->fullObjectSync) { return; }
if (so->maxSyncDistance == SYNC_DISTANCE_ONLY_DEATH) { return; }
if (so->maxSyncDistance == SYNC_DISTANCE_ONLY_EVENTS) { return; }
@ -205,7 +217,7 @@ static void packet_write_object_standard_fields(struct Packet* p, struct Object*
}
static void packet_read_object_standard_fields(struct Packet* p, struct Object* o) {
struct SyncObject* so = &syncObjects[o->oSyncID];
struct SyncObject* so = &gSyncObjects[o->oSyncID];
if (so->fullObjectSync) { return; }
if (so->maxSyncDistance == SYNC_DISTANCE_ONLY_DEATH) { return; }
if (so->maxSyncDistance == SYNC_DISTANCE_ONLY_EVENTS) { return; }
@ -227,7 +239,7 @@ static void packet_read_object_standard_fields(struct Packet* p, struct Object*
// ----- extra fields ----- //
static void packet_write_object_extra_fields(struct Packet* p, struct Object* o) {
struct SyncObject* so = &syncObjects[o->oSyncID];
struct SyncObject* so = &gSyncObjects[o->oSyncID];
if (so->maxSyncDistance == SYNC_DISTANCE_ONLY_DEATH) { return; }
// write the count
@ -241,7 +253,7 @@ static void packet_write_object_extra_fields(struct Packet* p, struct Object* o)
}
static void packet_read_object_extra_fields(struct Packet* p, struct Object* o) {
struct SyncObject* so = &syncObjects[o->oSyncID];
struct SyncObject* so = &gSyncObjects[o->oSyncID];
if (so->maxSyncDistance == SYNC_DISTANCE_ONLY_DEATH) { return; }
// read the count and sanity check
@ -261,13 +273,13 @@ static void packet_read_object_extra_fields(struct Packet* p, struct Object* o)
// ----- only death ----- //
static void packet_write_object_only_death(struct Packet* p, struct Object* o) {
struct SyncObject* so = &syncObjects[o->oSyncID];
struct SyncObject* so = &gSyncObjects[o->oSyncID];
if (so->maxSyncDistance != SYNC_DISTANCE_ONLY_DEATH) { return; }
packet_write(p, &o->activeFlags, sizeof(s16));
}
static void packet_read_object_only_death(struct Packet* p, struct Object* o) {
struct SyncObject* so = &syncObjects[o->oSyncID];
struct SyncObject* so = &gSyncObjects[o->oSyncID];
if (so->maxSyncDistance != SYNC_DISTANCE_ONLY_DEATH) { return; }
s16 activeFlags;
packet_read(p, &activeFlags, sizeof(u16));
@ -283,7 +295,7 @@ static void packet_read_object_only_death(struct Packet* p, struct Object* o) {
void network_send_object(struct Object* o) {
// sanity check SyncObject
if (!network_sync_object_initialized(o)) { return; }
struct SyncObject* so = &syncObjects[o->oSyncID];
struct SyncObject* so = &gSyncObjects[o->oSyncID];
if (so == NULL) { return; }
if (o->behavior != so->behavior && !allowable_behavior_change(so, so->behavior)) {
printf("network_send_object() BEHAVIOR MISMATCH!\n");
@ -303,7 +315,7 @@ void network_send_object(struct Object* o) {
void network_send_object_reliability(struct Object* o, bool reliable) {
// sanity check SyncObject
if (!network_sync_object_initialized(o)) { return; }
struct SyncObject* so = &syncObjects[o->oSyncID];
struct SyncObject* so = &gSyncObjects[o->oSyncID];
if (so == NULL) { return; }
if (o->behavior != so->behavior && !allowable_behavior_change(so, so->behavior)) {
@ -362,18 +374,6 @@ void network_receive_object(struct Packet* p) {
}
}
bool should_own_object(struct SyncObject* so) {
if (gMarioStates[0].heldByObj == so->o) { return true; }
for (int i = 0; i < MAX_PLAYERS; i++) {
if (gMarioStates[i].heldByObj == so->o) { return false; }
}
if (so->o->oHeldState == HELD_HELD && so->o->heldByPlayerIndex == 0) { return true; }
if (player_distance(&gMarioStates[0], so->o) > player_distance(&gMarioStates[1], so->o)) { return false; }
if (so->o->oHeldState == HELD_HELD && so->o->heldByPlayerIndex != 0) { return false; }
return true;
}
void network_forget_sync_object(struct SyncObject* so) {
so->o = NULL;
so->behavior = NULL;
@ -383,7 +383,7 @@ void network_forget_sync_object(struct SyncObject* so) {
void network_update_objects(void) {
for (u32 i = 1; i < nextSyncID; i++) {
struct SyncObject* so = &syncObjects[i];
struct SyncObject* so = &gSyncObjects[i];
if (so->o == NULL) { continue; }
// check for stale sync object
@ -400,7 +400,7 @@ void network_update_objects(void) {
// check for 'only death' event
if (so->maxSyncDistance == SYNC_DISTANCE_ONLY_DEATH) {
if (so->o->activeFlags != ACTIVE_FLAG_DEACTIVATED) { continue; }
network_send_object(syncObjects[i].o);
network_send_object(gSyncObjects[i].o);
continue;
}
@ -419,7 +419,7 @@ void network_update_objects(void) {
if (timeSinceUpdate < updateRate) { continue; }
// update!
network_send_object(syncObjects[i].o);
network_send_object(gSyncObjects[i].o);
}
}

View file

@ -66,9 +66,9 @@ void network_receive_player(struct Packet* p) {
}
// find and set their held object
if (heldSyncID != 0 && syncObjects[heldSyncID].o != NULL) {
if (heldSyncID != 0 && gSyncObjects[heldSyncID].o != NULL) {
// TODO: do we have to move graphics nodes around to make this visible?
struct Object* heldObj = syncObjects[heldSyncID].o;
struct Object* heldObj = gSyncObjects[heldSyncID].o;
gMarioStates[1].heldObj = heldObj;
heldObj->oHeldState = HELD_HELD;
heldObj->heldByPlayerIndex = 1;
@ -77,9 +77,9 @@ void network_receive_player(struct Packet* p) {
}
// find and set their held-by object
if (heldBySyncID != 0 && syncObjects[heldBySyncID].o != NULL) {
if (heldBySyncID != 0 && gSyncObjects[heldBySyncID].o != NULL) {
// TODO: do we have to move graphics nodes around to make this visible?
gMarioStates[1].heldByObj = syncObjects[heldBySyncID].o;
gMarioStates[1].heldByObj = gSyncObjects[heldBySyncID].o;
} else {
gMarioStates[1].heldByObj = NULL;
}

View file

@ -10,7 +10,7 @@
#define RESERVATION_COUNT 10
void network_send_reservation_request(void) {
assert(networkType == NT_CLIENT);
assert(gNetworkType == NT_CLIENT);
struct Packet p;
packet_init(&p, PACKET_RESERVATION_REQUEST, true);
@ -18,19 +18,19 @@ void network_send_reservation_request(void) {
}
void network_receive_reservation_request(UNUSED struct Packet* p) {
assert(networkType == NT_SERVER);
assert(gNetworkType == NT_SERVER);
network_send_reservation();
}
void network_send_reservation(void) {
assert(networkType == NT_SERVER);
assert(gNetworkType == NT_SERVER);
u8 clientPlayerIndex = 1; // two-player hack
// find all reserved objects
u8 reservedObjs[RESERVATION_COUNT] = { 0 };
u16 reservedIndex = 0;
for (u16 i = 1; i < MAX_SYNC_OBJECTS; i++) {
if (syncObjects[i].reserved == clientPlayerIndex) {
if (gSyncObjects[i].reserved == clientPlayerIndex) {
reservedObjs[reservedIndex++] = i;
if (reservedIndex >= RESERVATION_COUNT) { break; }
}
@ -39,9 +39,9 @@ void network_send_reservation(void) {
if (reservedIndex < RESERVATION_COUNT) {
// reserve the rest
for (u16 i = MAX_SYNC_OBJECTS - 1; i > 0; i--) {
if (syncObjects[i].o != NULL) { continue; }
if (syncObjects[i].reserved != 0) { continue; }
syncObjects[i].reserved = clientPlayerIndex;
if (gSyncObjects[i].o != NULL) { continue; }
if (gSyncObjects[i].reserved != 0) { continue; }
gSyncObjects[i].reserved = clientPlayerIndex;
reservedObjs[reservedIndex++] = i;
if (reservedIndex >= RESERVATION_COUNT) { break; }
}
@ -54,7 +54,7 @@ void network_send_reservation(void) {
}
void network_receive_reservation(struct Packet* p) {
assert(networkType == NT_CLIENT);
assert(gNetworkType == NT_CLIENT);
u8 clientPlayerIndex = 1; // two-player hack
// find all reserved objects
@ -64,7 +64,7 @@ void network_receive_reservation(struct Packet* p) {
for (u16 i = 0; i < RESERVATION_COUNT; i++) {
u16 index = reservedObjs[i];
if (index == 0) { continue; }
if (syncObjects[index].o != NULL) { continue; }
syncObjects[index].reserved = clientPlayerIndex;
if (gSyncObjects[index].o != NULL) { continue; }
gSyncObjects[index].reserved = clientPlayerIndex;
}
}

View file

@ -15,7 +15,7 @@ extern u8* gOverrideEeprom;
static u8 eeprom[512] = { 0 };
void network_send_save_file_request(void) {
assert(networkType == NT_CLIENT);
assert(gNetworkType == NT_CLIENT);
gOverrideEeprom = eeprom;
@ -25,12 +25,12 @@ void network_send_save_file_request(void) {
}
void network_receive_save_file_request(UNUSED struct Packet* p) {
assert(networkType == NT_SERVER);
assert(gNetworkType == NT_SERVER);
network_send_save_file();
}
void network_send_save_file(void) {
assert(networkType == NT_SERVER);
assert(gNetworkType == NT_SERVER);
fs_file_t* fp = fs_open(SAVE_FILENAME);
if (fp != NULL) {
@ -47,7 +47,7 @@ void network_send_save_file(void) {
}
void network_receive_save_file(struct Packet* p) {
assert(networkType == NT_CLIENT);
assert(gNetworkType == NT_CLIENT);
gOverrideEeprom = eeprom;

View file

@ -87,7 +87,7 @@ void network_receive_spawn_objects(struct Packet* p) {
onRemoteSpawnId = (onRemoteSpawnId + 1) % MAX_REMOTE_SPAWN_IDS;
// two-player hack
u8 reserveId = (networkLevelLoaded && networkType == NT_SERVER) ? 1 : 0;
u8 reserveId = (gNetworkLevelLoaded && gNetworkType == NT_SERVER) ? 1 : 0;
bool receivedReservedSyncObject = false;
struct Object* spawned[MAX_SPAWN_OBJECTS_PER_PACKET] = { 0 };
@ -106,7 +106,7 @@ void network_receive_spawn_objects(struct Packet* p) {
} else {
// this object has a known parent
parentObj = (i == 0)
? syncObjects[data.parentId].o
? gSyncObjects[data.parentId].o
: spawned[data.parentId];
if (parentObj == NULL) { continue; }
}
@ -119,9 +119,9 @@ void network_receive_spawn_objects(struct Packet* p) {
if (data.parentId == (u8)-1) { o->parentObj = o; }
// they've allocated one of their reserved sync objects
if (o->oSyncID != 0 && syncObjects[o->oSyncID].reserved == reserveId) {
syncObjects[o->oSyncID].o = o;
syncObjects[o->oSyncID].reserved = 0;
if (o->oSyncID != 0 && gSyncObjects[o->oSyncID].reserved == reserveId) {
gSyncObjects[o->oSyncID].o = o;
gSyncObjects[o->oSyncID].reserved = 0;
receivedReservedSyncObject = true;
}
@ -129,7 +129,7 @@ void network_receive_spawn_objects(struct Packet* p) {
}
// update their block of reserved ids
if (networkType == NT_SERVER && receivedReservedSyncObject) {
if (gNetworkType == NT_SERVER && receivedReservedSyncObject) {
network_send_reservation();
}
}