mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-22 12:05:11 +00:00
Complete rewrite of level-change/area-change system
Now level changes and area changes are separated. Entity deletions are properly tracked on level change or area change. Late entity synchronization is now triggered on any area change.
This commit is contained in:
parent
0b3a97d405
commit
6bfdcbcb7b
25 changed files with 779 additions and 528 deletions
|
@ -426,6 +426,7 @@ static void level_cmd_23(void) {
|
||||||
|
|
||||||
static void level_cmd_init_mario(void) {
|
static void level_cmd_init_mario(void) {
|
||||||
u32 behaviorArg = CMD_GET(u32, 4);
|
u32 behaviorArg = CMD_GET(u32, 4);
|
||||||
|
behaviorArg = behaviorArg;
|
||||||
void* behaviorScript = CMD_GET(void*, 8);
|
void* behaviorScript = CMD_GET(void*, 8);
|
||||||
struct GraphNode* unk18 = gLoadedGraphNodes[CMD_GET(u8, 3)];
|
struct GraphNode* unk18 = gLoadedGraphNodes[CMD_GET(u8, 3)];
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,6 @@ s32 approach_forward_vel(f32 *arr, f32 spC, f32 sp10) {
|
||||||
|
|
||||||
void chuckya_act_0(void) {
|
void chuckya_act_0(void) {
|
||||||
struct Object* player = nearest_player_to_object(o);
|
struct Object* player = nearest_player_to_object(o);
|
||||||
int distanceToPlayer = dist_between_objects(o, player);
|
|
||||||
int angleToPlayer = obj_angle_to_object(o, player);
|
int angleToPlayer = obj_angle_to_object(o, player);
|
||||||
s32 sp3C;
|
s32 sp3C;
|
||||||
UNUSED u8 pad[16];
|
UNUSED u8 pad[16];
|
||||||
|
|
|
@ -51,7 +51,6 @@ void set_home_to_mario(void) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
struct Object* player = nearest_player_to_object(o);
|
|
||||||
if (parentIsMario) {
|
if (parentIsMario) {
|
||||||
o->oHomeX = o->parentObj->oPosX;
|
o->oHomeX = o->parentObj->oPosX;
|
||||||
o->oHomeZ = o->parentObj->oPosZ;
|
o->oHomeZ = o->parentObj->oPosZ;
|
||||||
|
|
|
@ -116,6 +116,7 @@ extern s8 gRedCoinsCollected;
|
||||||
void create_dl_identity_matrix(void);
|
void create_dl_identity_matrix(void);
|
||||||
void create_dl_translation_matrix(s8 pushOp, f32 x, f32 y, f32 z);
|
void create_dl_translation_matrix(s8 pushOp, f32 x, f32 y, f32 z);
|
||||||
void create_dl_ortho_matrix(void);
|
void create_dl_ortho_matrix(void);
|
||||||
|
void render_generic_char(u8 c);
|
||||||
void str_ascii_to_dialog(const char* string, u8* dialog, u16 length);
|
void str_ascii_to_dialog(const char* string, u8* dialog, u16 length);
|
||||||
f32 get_generic_dialog_width(u8* dialog);
|
f32 get_generic_dialog_width(u8* dialog);
|
||||||
f32 get_generic_ascii_string_width(const char* ascii);
|
f32 get_generic_ascii_string_width(const char* ascii);
|
||||||
|
|
|
@ -103,8 +103,14 @@ void network_on_loaded_level(void) {
|
||||||
// check for level change
|
// check for level change
|
||||||
struct NetworkPlayer* np = gNetworkPlayerLocal;
|
struct NetworkPlayer* np = gNetworkPlayerLocal;
|
||||||
if (np != NULL) {
|
if (np != NULL) {
|
||||||
network_send_level_area();
|
bool levelMatch = (np->currCourseNum == gCurrCourseNum
|
||||||
network_send_location_request();
|
&& np->currActNum == gCurrActNum
|
||||||
|
&& np->currLevelNum == gCurrLevelNum);
|
||||||
|
if (np->currLevelSyncValid && levelMatch && np->currAreaIndex != gCurrAreaIndex) {
|
||||||
|
network_send_change_area();
|
||||||
|
} else {
|
||||||
|
network_send_change_level();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// request my chunk of reserved sync ids
|
// request my chunk of reserved sync ids
|
||||||
|
@ -118,6 +124,9 @@ void network_send_to(u8 localIndex, struct Packet* p) {
|
||||||
if (gNetworkType == NT_NONE) { LOG_ERROR("network type error none!"); return; }
|
if (gNetworkType == NT_NONE) { LOG_ERROR("network type error none!"); return; }
|
||||||
if (p->error) { LOG_ERROR("packet error!"); return; }
|
if (p->error) { LOG_ERROR("packet error!"); return; }
|
||||||
if (gNetworkSystem == NULL) { LOG_ERROR("no network system attached"); return; }
|
if (gNetworkSystem == NULL) { LOG_ERROR("no network system attached"); return; }
|
||||||
|
if (p->buffer[0] != PACKET_JOIN_REQUEST && p->buffer[0] != PACKET_KICK && p->buffer[0] != PACKET_ACK && gNetworkPlayerLocal != NULL && gNetworkPlayerServer->localIndex != gNetworkPlayerLocal->localIndex) {
|
||||||
|
assert(localIndex != gNetworkPlayerLocal->localIndex);
|
||||||
|
}
|
||||||
|
|
||||||
// set the flags again
|
// set the flags again
|
||||||
packet_set_flags(p);
|
packet_set_flags(p);
|
||||||
|
|
|
@ -33,10 +33,24 @@ struct NetworkPlayer* network_player_from_global_index(u8 globalIndex) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NetworkPlayer* get_network_player_from_valid_location(s16 courseNum, s16 actNum, s16 levelNum, s16 areaIndex) {
|
struct NetworkPlayer* get_network_player_from_level(s16 courseNum, s16 actNum, s16 levelNum) {
|
||||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||||
struct NetworkPlayer* np = &gNetworkPlayers[i];
|
struct NetworkPlayer* np = &gNetworkPlayers[i];
|
||||||
if (!np->connected) { continue; }
|
if (!np->connected) { continue; }
|
||||||
|
if (!np->currLevelSyncValid) { continue; }
|
||||||
|
if (np->currCourseNum != courseNum) { continue; }
|
||||||
|
if (np->currActNum != actNum) { continue; }
|
||||||
|
if (np->currLevelNum != levelNum) { continue; }
|
||||||
|
return np;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NetworkPlayer* get_network_player_from_area(s16 courseNum, s16 actNum, s16 levelNum, s16 areaIndex) {
|
||||||
|
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||||
|
struct NetworkPlayer* np = &gNetworkPlayers[i];
|
||||||
|
if (!np->connected) { continue; }
|
||||||
|
if (!np->currLevelSyncValid) { continue; }
|
||||||
if (!np->currAreaSyncValid) { continue; }
|
if (!np->currAreaSyncValid) { continue; }
|
||||||
if (np->currCourseNum != courseNum) { continue; }
|
if (np->currCourseNum != courseNum) { continue; }
|
||||||
if (np->currActNum != actNum) { continue; }
|
if (np->currActNum != actNum) { continue; }
|
||||||
|
@ -100,6 +114,10 @@ u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex) {
|
||||||
np->currAreaIndex = -1;
|
np->currAreaIndex = -1;
|
||||||
np->currAreaSyncValid = false;
|
np->currAreaSyncValid = false;
|
||||||
gNetworkPlayerLocal = np;
|
gNetworkPlayerLocal = np;
|
||||||
|
|
||||||
|
if (gNetworkType == NT_SERVER) {
|
||||||
|
gNetworkPlayerServer = gNetworkPlayerLocal;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ struct NetworkPlayer {
|
||||||
s16 currActNum;
|
s16 currActNum;
|
||||||
s16 currLevelNum;
|
s16 currLevelNum;
|
||||||
s16 currAreaIndex;
|
s16 currAreaIndex;
|
||||||
|
bool currLevelSyncValid;
|
||||||
bool currAreaSyncValid;
|
bool currAreaSyncValid;
|
||||||
u8 fadeOpacity;
|
u8 fadeOpacity;
|
||||||
u16 rxSeqIds[MAX_RX_SEQ_IDS];
|
u16 rxSeqIds[MAX_RX_SEQ_IDS];
|
||||||
|
@ -41,7 +42,8 @@ extern struct NetworkPlayer* gNetworkPlayerServer;
|
||||||
bool network_player_any_connected(void);
|
bool network_player_any_connected(void);
|
||||||
u8 network_player_connected_count(void);
|
u8 network_player_connected_count(void);
|
||||||
struct NetworkPlayer* network_player_from_global_index(u8 globalIndex);
|
struct NetworkPlayer* network_player_from_global_index(u8 globalIndex);
|
||||||
struct NetworkPlayer* get_network_player_from_valid_location(s16 courseNum, s16 actNum, s16 levelNum, s16 areaIndex);
|
struct NetworkPlayer* get_network_player_from_level(s16 courseNum, s16 actNum, s16 levelNum);
|
||||||
|
struct NetworkPlayer* get_network_player_from_area(s16 courseNum, s16 actNum, s16 levelNum, s16 areaIndex);
|
||||||
void network_player_update(void);
|
void network_player_update(void);
|
||||||
u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex);
|
u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex);
|
||||||
u8 network_player_disconnected(u8 globalIndex);
|
u8 network_player_disconnected(u8 globalIndex);
|
||||||
|
|
|
@ -59,14 +59,21 @@ void packet_receive(struct Packet* p) {
|
||||||
case PACKET_SAVE_FILE: network_receive_save_file(p); break;
|
case PACKET_SAVE_FILE: network_receive_save_file(p); break;
|
||||||
case PACKET_NETWORK_PLAYERS: network_receive_network_players(p); break;
|
case PACKET_NETWORK_PLAYERS: network_receive_network_players(p); break;
|
||||||
case PACKET_DEATH: network_receive_death(p); break;
|
case PACKET_DEATH: network_receive_death(p); break;
|
||||||
case PACKET_LEVEL_AREA: network_receive_level_area(p); break;
|
|
||||||
case PACKET_LEVEL_AREA_VALID: network_receive_level_area_valid(p); break;
|
// location
|
||||||
case PACKET_LOCATION_REQUEST: network_receive_location_request(p); break;
|
case PACKET_CHANGE_LEVEL: network_receive_change_level(p); break;
|
||||||
case PACKET_LOCATION_REQUEST_CLIENT: network_receive_location_request_client(p); break;
|
case PACKET_CHANGE_AREA: network_receive_change_area(p); break;
|
||||||
case PACKET_LOCATION_RESPONSE: network_receive_location_response(p); break;
|
case PACKET_LEVEL_AREA_REQUEST: network_receive_level_area_request(p); break;
|
||||||
case PACKET_MACRO_DELETIONS: network_receive_macro_deletions(p); break;
|
case PACKET_LEVEL_REQUEST: network_receive_level_request(p); break;
|
||||||
case PACKET_SPAWN_INFO_DELETIONS: network_receive_spawn_info_deletions(p); break;
|
case PACKET_LEVEL: network_receive_level(p); break;
|
||||||
///
|
case PACKET_AREA_REQUEST: network_receive_area_request(p); break;
|
||||||
|
case PACKET_AREA: network_receive_area(p); break;
|
||||||
|
case PACKET_SYNC_VALID: network_receive_sync_valid(p); break;
|
||||||
|
case PACKET_LEVEL_SPAWN_INFO: network_receive_level_spawn_info(p); break;
|
||||||
|
case PACKET_LEVEL_MACRO: network_receive_level_macro(p); break;
|
||||||
|
case PACKET_LEVEL_AREA_INFORM: network_receive_level_area_inform(p); break;
|
||||||
|
|
||||||
|
// custom
|
||||||
case PACKET_CUSTOM: network_receive_custom(p); break;
|
case PACKET_CUSTOM: network_receive_custom(p); break;
|
||||||
default: LOG_ERROR("received unknown packet: %d", p->buffer[0]);
|
default: LOG_ERROR("received unknown packet: %d", p->buffer[0]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#define PACKET_LENGTH 1024
|
#define PACKET_LENGTH 1024
|
||||||
#define PACKET_DESTINATION_BROADCAST ((u8)-1)
|
#define PACKET_DESTINATION_BROADCAST ((u8)-1)
|
||||||
|
|
||||||
|
struct NetworkPlayer;
|
||||||
|
|
||||||
enum PacketType {
|
enum PacketType {
|
||||||
PACKET_ACK,
|
PACKET_ACK,
|
||||||
PACKET_PLAYER,
|
PACKET_PLAYER,
|
||||||
|
@ -31,13 +33,19 @@ enum PacketType {
|
||||||
PACKET_SAVE_FILE,
|
PACKET_SAVE_FILE,
|
||||||
PACKET_NETWORK_PLAYERS,
|
PACKET_NETWORK_PLAYERS,
|
||||||
PACKET_DEATH,
|
PACKET_DEATH,
|
||||||
PACKET_LEVEL_AREA,
|
|
||||||
PACKET_LEVEL_AREA_VALID,
|
PACKET_CHANGE_LEVEL,
|
||||||
PACKET_LOCATION_REQUEST,
|
PACKET_CHANGE_AREA,
|
||||||
PACKET_LOCATION_REQUEST_CLIENT,
|
PACKET_LEVEL_AREA_REQUEST,
|
||||||
PACKET_LOCATION_RESPONSE,
|
PACKET_LEVEL_REQUEST,
|
||||||
PACKET_MACRO_DELETIONS,
|
PACKET_LEVEL,
|
||||||
PACKET_SPAWN_INFO_DELETIONS,
|
PACKET_AREA_REQUEST,
|
||||||
|
PACKET_AREA,
|
||||||
|
PACKET_SYNC_VALID,
|
||||||
|
PACKET_LEVEL_SPAWN_INFO,
|
||||||
|
PACKET_LEVEL_MACRO,
|
||||||
|
PACKET_LEVEL_AREA_INFORM,
|
||||||
|
|
||||||
///
|
///
|
||||||
PACKET_CUSTOM = 255,
|
PACKET_CUSTOM = 255,
|
||||||
};
|
};
|
||||||
|
@ -74,6 +82,8 @@ u8 packet_initial_read(struct Packet* packet);
|
||||||
void packet_read(struct Packet* packet, void* data, u16 length);
|
void packet_read(struct Packet* packet, void* data, u16 length);
|
||||||
u32 packet_hash(struct Packet* packet);
|
u32 packet_hash(struct Packet* packet);
|
||||||
bool packet_check_hash(struct Packet* packet);
|
bool packet_check_hash(struct Packet* packet);
|
||||||
|
void packet_ordered_begin(void);
|
||||||
|
void packet_ordered_end(void);
|
||||||
|
|
||||||
// packet_reliable.c
|
// packet_reliable.c
|
||||||
void network_forget_all_reliable(void);
|
void network_forget_all_reliable(void);
|
||||||
|
@ -170,30 +180,48 @@ void network_receive_network_players(struct Packet* p);
|
||||||
void network_send_death(void);
|
void network_send_death(void);
|
||||||
void network_receive_death(struct Packet* p);
|
void network_receive_death(struct Packet* p);
|
||||||
|
|
||||||
// packet_level_area.c
|
// packet_change_level.c
|
||||||
void network_send_level_area(void);
|
void network_send_change_level(void);
|
||||||
void network_receive_level_area(struct Packet* p);
|
void network_receive_change_level(struct Packet* p);
|
||||||
void network_send_level_area_valid(u8 toGlobalIndex);
|
|
||||||
void network_receive_level_area_valid(struct Packet* p);
|
|
||||||
|
|
||||||
// packet_location_request.c
|
// packet_change_area.c
|
||||||
void network_send_location_request(void);
|
void network_send_change_area(void);
|
||||||
void network_receive_location_request(struct Packet* p);
|
void network_receive_change_area(struct Packet* p);
|
||||||
|
|
||||||
// packet_location_request_client.c
|
// packet_level_area_request.c
|
||||||
void network_send_location_request_client(u8 destGlobalIndex, u8 srcGlobalIndex);
|
void network_send_level_area_request(struct NetworkPlayer* fromNp, struct NetworkPlayer* toNp);
|
||||||
void network_receive_location_request_client(struct Packet* p);
|
void network_receive_level_area_request(struct Packet* p);
|
||||||
|
|
||||||
// packet_location_response.c
|
// packet_level_request.c
|
||||||
void network_send_location_response(u8 destGlobalIndex);
|
void network_send_level_request(struct NetworkPlayer* fromNp, struct NetworkPlayer* toNp);
|
||||||
void network_receive_location_response(struct Packet* p);
|
void network_receive_level_request(struct Packet* p);
|
||||||
|
|
||||||
// packet_macro_deletions.c
|
// packet_level.c
|
||||||
void network_send_macro_deletions(u8 destGlobalIndex);
|
void network_send_level(struct NetworkPlayer* toNp, bool sendArea);
|
||||||
void network_receive_macro_deletions(struct Packet* p);
|
void network_receive_level(struct Packet* p);
|
||||||
|
|
||||||
// packet_spawn_info_deletions.c
|
// packet_area_request.c
|
||||||
void network_send_spawn_info_deletions(u8 destGlobalIndex);
|
void network_send_area_request(struct NetworkPlayer* fromNp, struct NetworkPlayer* toNp);
|
||||||
void network_receive_spawn_info_deletions(struct Packet* p);
|
void network_receive_area_request(struct Packet* p);
|
||||||
|
|
||||||
|
// packet_area.c
|
||||||
|
void network_send_area(struct NetworkPlayer* toNp);
|
||||||
|
void network_receive_area(struct Packet* p);
|
||||||
|
|
||||||
|
// packet_sync_valid.c
|
||||||
|
void network_send_sync_valid(struct NetworkPlayer* toNp);
|
||||||
|
void network_receive_sync_valid(struct Packet* p);
|
||||||
|
|
||||||
|
// packet_level_spawn_info.c
|
||||||
|
void network_send_level_spawn_info(struct NetworkPlayer* destNp);
|
||||||
|
void network_receive_level_spawn_info(struct Packet* p);
|
||||||
|
|
||||||
|
// packet_level_macro.c
|
||||||
|
void network_send_level_macro(struct NetworkPlayer* destNp);
|
||||||
|
void network_receive_level_macro(struct Packet* p);
|
||||||
|
|
||||||
|
// packet_level_area_inform.c
|
||||||
|
void network_send_level_area_inform(struct NetworkPlayer* np);
|
||||||
|
void network_receive_level_area_inform(struct Packet* p);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
156
src/pc/network/packets/packet_area.c
Normal file
156
src/pc/network/packets/packet_area.c
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "../network.h"
|
||||||
|
#include "game/interaction.h"
|
||||||
|
#include "game/level_update.h"
|
||||||
|
#include "game/area.h"
|
||||||
|
#include "game/object_helpers.h"
|
||||||
|
#include "behavior_table.h"
|
||||||
|
#include "object_constants.h"
|
||||||
|
#include "object_fields.h"
|
||||||
|
#include "model_ids.h"
|
||||||
|
//#define DISABLE_MODULE_LOG 1
|
||||||
|
#include "pc/debuglog.h"
|
||||||
|
|
||||||
|
void network_send_area(struct NetworkPlayer* toNp) {
|
||||||
|
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
|
||||||
|
|
||||||
|
packet_ordered_begin();
|
||||||
|
{
|
||||||
|
struct Packet p;
|
||||||
|
packet_init(&p, PACKET_AREA, true, false);
|
||||||
|
|
||||||
|
// level location
|
||||||
|
packet_write(&p, &gCurrCourseNum, sizeof(s16));
|
||||||
|
packet_write(&p, &gCurrActNum, sizeof(s16));
|
||||||
|
packet_write(&p, &gCurrLevelNum, sizeof(s16));
|
||||||
|
packet_write(&p, &gCurrAreaIndex, sizeof(s16));
|
||||||
|
|
||||||
|
// count respawners and write
|
||||||
|
u8 respawnerCount = 0;
|
||||||
|
for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
|
||||||
|
struct SyncObject* so = &gSyncObjects[i];
|
||||||
|
if (so == NULL || so->o == NULL || so->o->behavior != bhvRespawner) { continue; }
|
||||||
|
respawnerCount++;
|
||||||
|
}
|
||||||
|
packet_write(&p, &respawnerCount, sizeof(u8));
|
||||||
|
|
||||||
|
// write respawners
|
||||||
|
for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
|
||||||
|
struct SyncObject* so = &gSyncObjects[i];
|
||||||
|
if (so == NULL || so->o == NULL || so->o->behavior != bhvRespawner) { continue; }
|
||||||
|
u32 behaviorToRespawn = get_id_from_behavior(so->o->oRespawnerBehaviorToRespawn);
|
||||||
|
packet_write(&p, &so->o->oPosX, sizeof(f32));
|
||||||
|
packet_write(&p, &so->o->oPosY, sizeof(f32));
|
||||||
|
packet_write(&p, &so->o->oPosZ, sizeof(f32));
|
||||||
|
packet_write(&p, &so->o->oBehParams, sizeof(s32));
|
||||||
|
packet_write(&p, &so->o->oRespawnerModelToRespawn, sizeof(s32));
|
||||||
|
packet_write(&p, &so->o->oRespawnerMinSpawnDist, sizeof(f32));
|
||||||
|
packet_write(&p, &behaviorToRespawn, sizeof(s32));
|
||||||
|
packet_write(&p, &so->o->oSyncID, sizeof(u32));
|
||||||
|
LOG_INFO("tx respawner");
|
||||||
|
}
|
||||||
|
|
||||||
|
// send area packet
|
||||||
|
network_send_to(toNp->localIndex, &p);
|
||||||
|
|
||||||
|
// send non-static objects
|
||||||
|
for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
|
||||||
|
struct SyncObject* so = &gSyncObjects[i];
|
||||||
|
if (so == NULL || so->o == NULL || so->o->oSyncID != (u32)i) { continue; }
|
||||||
|
if (so->staticLevelSpawn) { continue; }
|
||||||
|
if (so->o->behavior == bhvRespawner) { continue; }
|
||||||
|
struct Object* spawn_objects[] = { so->o };
|
||||||
|
|
||||||
|
// TODO: move find model to a utility file/function
|
||||||
|
// find model
|
||||||
|
u32 model = 0;
|
||||||
|
for (int j = 0; j < 256; j++) {
|
||||||
|
if (so->o->header.gfx.sharedChild == gLoadedGraphNodes[j]) {
|
||||||
|
model = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 models[] = { model };
|
||||||
|
network_send_spawn_objects_to(toNp->localIndex, spawn_objects, models, 1);
|
||||||
|
LOG_INFO("tx non-static");
|
||||||
|
}
|
||||||
|
|
||||||
|
// send last reliable ent packet
|
||||||
|
for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
|
||||||
|
struct SyncObject* so = &gSyncObjects[i];
|
||||||
|
if (so == NULL || so->o == NULL) { continue; }
|
||||||
|
struct Packet* entPacket = get_last_sync_ent_reliable_packet(i);
|
||||||
|
if (entPacket->error) { continue; }
|
||||||
|
struct Packet p2 = { 0 };
|
||||||
|
packet_duplicate(entPacket, &p2);
|
||||||
|
network_send_to(toNp->localIndex, &p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// send sync valid
|
||||||
|
network_send_sync_valid(toNp);
|
||||||
|
}
|
||||||
|
packet_ordered_end();
|
||||||
|
|
||||||
|
LOG_INFO("tx area");
|
||||||
|
}
|
||||||
|
|
||||||
|
void network_receive_area(struct Packet* p) {
|
||||||
|
LOG_INFO("rx area");
|
||||||
|
|
||||||
|
// read level location
|
||||||
|
s16 courseNum, actNum, levelNum, areaIndex;
|
||||||
|
packet_read(p, &courseNum, sizeof(s16));
|
||||||
|
packet_read(p, &actNum, sizeof(s16));
|
||||||
|
packet_read(p, &levelNum, sizeof(s16));
|
||||||
|
packet_read(p, &areaIndex, sizeof(s16));
|
||||||
|
|
||||||
|
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum;
|
||||||
|
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
|
||||||
|
LOG_ERROR("rx area: received an improper location");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read respawner count
|
||||||
|
u8 respawnerCount = 0;
|
||||||
|
packet_read(p, &respawnerCount, sizeof(u8));
|
||||||
|
|
||||||
|
// read respawners
|
||||||
|
for (int i = 0; i < respawnerCount; i++) {
|
||||||
|
f32 posX, posY, posZ;
|
||||||
|
packet_read(p, &posX, sizeof(f32));
|
||||||
|
packet_read(p, &posY, sizeof(f32));
|
||||||
|
packet_read(p, &posZ, sizeof(f32));
|
||||||
|
|
||||||
|
s32 behParams, respawnerModelToRespawn;
|
||||||
|
packet_read(p, &behParams, sizeof(s32));
|
||||||
|
packet_read(p, &respawnerModelToRespawn, sizeof(s32));
|
||||||
|
|
||||||
|
f32 respawnerMinSpawnDist;
|
||||||
|
packet_read(p, &respawnerMinSpawnDist, sizeof(f32));
|
||||||
|
|
||||||
|
u32 behaviorToRespawn, syncId;
|
||||||
|
packet_read(p, &behaviorToRespawn, sizeof(u32));
|
||||||
|
packet_read(p, &syncId, sizeof(u32));
|
||||||
|
|
||||||
|
struct SyncObject* so = &gSyncObjects[syncId];
|
||||||
|
|
||||||
|
LOG_INFO("rx respawner");
|
||||||
|
if (so->staticLevelSpawn) {
|
||||||
|
struct Object* respawner = spawn_object_abs_with_rot(gMarioStates[0].marioObj, 0, MODEL_NONE, bhvRespawner, posX, posY, posZ, 0, 0, 0);
|
||||||
|
respawner->parentObj = respawner;
|
||||||
|
respawner->oBehParams = behParams;
|
||||||
|
respawner->oRespawnerModelToRespawn = respawnerModelToRespawn;
|
||||||
|
respawner->oRespawnerMinSpawnDist = respawnerMinSpawnDist;
|
||||||
|
respawner->oRespawnerBehaviorToRespawn = get_behavior_from_id(behaviorToRespawn);
|
||||||
|
respawner->oSyncID = syncId;
|
||||||
|
|
||||||
|
struct Object* o = so->o;
|
||||||
|
o->oSyncID = 0;
|
||||||
|
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
|
||||||
|
|
||||||
|
so->o = respawner;
|
||||||
|
LOG_INFO("rx respawner replaced!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
49
src/pc/network/packets/packet_area_request.c
Normal file
49
src/pc/network/packets/packet_area_request.c
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "../network.h"
|
||||||
|
//#define DISABLE_MODULE_LOG 1
|
||||||
|
#include "pc/debuglog.h"
|
||||||
|
|
||||||
|
void network_send_area_request(struct NetworkPlayer* fromNp, struct NetworkPlayer* toNp) {
|
||||||
|
if (gNetworkType == NT_SERVER && toNp == gNetworkPlayerLocal) {
|
||||||
|
// requesting server's area, send it immediately
|
||||||
|
network_send_area(fromNp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Packet p;
|
||||||
|
packet_init(&p, PACKET_AREA_REQUEST, true, false);
|
||||||
|
packet_write(&p, &fromNp->globalIndex, sizeof(u8));
|
||||||
|
packet_write(&p, &fromNp->currCourseNum, sizeof(s16));
|
||||||
|
packet_write(&p, &fromNp->currActNum, sizeof(s16));
|
||||||
|
packet_write(&p, &fromNp->currLevelNum, sizeof(s16));
|
||||||
|
packet_write(&p, &fromNp->currAreaIndex, sizeof(s16));
|
||||||
|
network_send_to(toNp->localIndex, &p);
|
||||||
|
LOG_INFO("tx area request");
|
||||||
|
}
|
||||||
|
|
||||||
|
void network_receive_area_request(struct Packet* p) {
|
||||||
|
LOG_INFO("rx area request");
|
||||||
|
|
||||||
|
u8 globalIndex;
|
||||||
|
s16 courseNum, actNum, levelNum, areaIndex;
|
||||||
|
packet_read(p, &globalIndex, sizeof(u8));
|
||||||
|
packet_read(p, &courseNum, sizeof(s16));
|
||||||
|
packet_read(p, &actNum, sizeof(s16));
|
||||||
|
packet_read(p, &levelNum, sizeof(s16));
|
||||||
|
packet_read(p, &areaIndex, sizeof(s16));
|
||||||
|
|
||||||
|
struct NetworkPlayer* toNp = network_player_from_global_index(globalIndex);
|
||||||
|
if (toNp == NULL || toNp->localIndex == UNKNOWN_LOCAL_INDEX || !toNp->connected) {
|
||||||
|
LOG_ERROR("Receiving area request from inactive player!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
|
||||||
|
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
|
||||||
|
LOG_ERROR("rx area request: received an improper location");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send area
|
||||||
|
network_send_area(toNp);
|
||||||
|
}
|
77
src/pc/network/packets/packet_change_area.c
Normal file
77
src/pc/network/packets/packet_change_area.c
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "../network.h"
|
||||||
|
#include "level_table.h"
|
||||||
|
//#define DISABLE_MODULE_LOG 1
|
||||||
|
#include "pc/debuglog.h"
|
||||||
|
|
||||||
|
static void player_changed_area(struct NetworkPlayer* np, s16 courseNum, s16 actNum, s16 levelNum, s16 areaIndex) {
|
||||||
|
// set NetworkPlayer variables
|
||||||
|
np->currCourseNum = courseNum;
|
||||||
|
np->currActNum = actNum;
|
||||||
|
np->currLevelNum = levelNum;
|
||||||
|
np->currAreaIndex = areaIndex;
|
||||||
|
np->currAreaSyncValid = false;
|
||||||
|
network_send_level_area_inform(np);
|
||||||
|
|
||||||
|
// find a NetworkPlayer at that area
|
||||||
|
struct NetworkPlayer* npLevelAreaMatch = get_network_player_from_area(courseNum, actNum, levelNum, areaIndex);
|
||||||
|
|
||||||
|
if (npLevelAreaMatch == NULL) {
|
||||||
|
// no NetworkPlayer in the level
|
||||||
|
network_send_sync_valid(np);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// matching NetworkPlayer is client
|
||||||
|
network_send_area_request(np, npLevelAreaMatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void network_send_change_area(void) {
|
||||||
|
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
|
||||||
|
|
||||||
|
// override castle act to 0 to prevent instancing of the hub
|
||||||
|
if (gCurrCourseNum == 0 && (gCurrLevelNum == LEVEL_CASTLE || gCurrLevelNum == LEVEL_CASTLE_GROUNDS || gCurrLevelNum == LEVEL_CASTLE_COURTYARD)) {
|
||||||
|
gCurrActNum = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gNetworkType == NT_SERVER) {
|
||||||
|
player_changed_area(gNetworkPlayerLocal, gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Packet p;
|
||||||
|
packet_init(&p, PACKET_CHANGE_AREA, true, false);
|
||||||
|
packet_write(&p, &gCurrCourseNum, sizeof(s16));
|
||||||
|
packet_write(&p, &gCurrActNum, sizeof(s16));
|
||||||
|
packet_write(&p, &gCurrLevelNum, sizeof(s16));
|
||||||
|
packet_write(&p, &gCurrAreaIndex, sizeof(s16));
|
||||||
|
network_send_to(gNetworkPlayerServer->localIndex, &p);
|
||||||
|
|
||||||
|
struct NetworkPlayer* np = gNetworkPlayerLocal;
|
||||||
|
np->currCourseNum = gCurrCourseNum;
|
||||||
|
np->currActNum = gCurrActNum;
|
||||||
|
np->currLevelNum = gCurrLevelNum;
|
||||||
|
np->currAreaIndex = gCurrAreaIndex;
|
||||||
|
np->currAreaSyncValid = false;
|
||||||
|
|
||||||
|
LOG_INFO("tx change area");
|
||||||
|
}
|
||||||
|
|
||||||
|
void network_receive_change_area(struct Packet* p) {
|
||||||
|
LOG_INFO("rx change area");
|
||||||
|
|
||||||
|
assert(gNetworkType == NT_SERVER);
|
||||||
|
struct NetworkPlayer* np = &gNetworkPlayers[p->localIndex];
|
||||||
|
if (np == NULL || np->localIndex == UNKNOWN_LOCAL_INDEX || !np->connected) {
|
||||||
|
LOG_ERROR("Receiving change area from inactive player!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s16 courseNum, actNum, levelNum, areaIndex;
|
||||||
|
packet_read(p, &courseNum, sizeof(s16));
|
||||||
|
packet_read(p, &actNum, sizeof(s16));
|
||||||
|
packet_read(p, &levelNum, sizeof(s16));
|
||||||
|
packet_read(p, &areaIndex, sizeof(s16));
|
||||||
|
|
||||||
|
player_changed_area(np, courseNum, actNum, levelNum, areaIndex);
|
||||||
|
}
|
85
src/pc/network/packets/packet_change_level.c
Normal file
85
src/pc/network/packets/packet_change_level.c
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "../network.h"
|
||||||
|
#include "level_table.h"
|
||||||
|
//#define DISABLE_MODULE_LOG 1
|
||||||
|
#include "pc/debuglog.h"
|
||||||
|
|
||||||
|
static void player_changed_level(struct NetworkPlayer* np, s16 courseNum, s16 actNum, s16 levelNum, s16 areaIndex) {
|
||||||
|
// set NetworkPlayer variables
|
||||||
|
np->currCourseNum = courseNum;
|
||||||
|
np->currActNum = actNum;
|
||||||
|
np->currLevelNum = levelNum;
|
||||||
|
np->currAreaIndex = areaIndex;
|
||||||
|
np->currLevelSyncValid = false;
|
||||||
|
np->currAreaSyncValid = false;
|
||||||
|
network_send_level_area_inform(np);
|
||||||
|
|
||||||
|
// find a NetworkPlayer around that location
|
||||||
|
struct NetworkPlayer* npLevelAreaMatch = get_network_player_from_area(courseNum, actNum, levelNum, areaIndex);
|
||||||
|
struct NetworkPlayer* npLevelMatch = get_network_player_from_level(courseNum, actNum, levelNum);
|
||||||
|
struct NetworkPlayer* npAny = (npLevelAreaMatch == NULL) ? npLevelMatch : npLevelAreaMatch;
|
||||||
|
|
||||||
|
if (npAny == NULL) {
|
||||||
|
// no NetworkPlayer in the level
|
||||||
|
network_send_sync_valid(np);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// matching NetworkPlayer is client
|
||||||
|
if (npAny == npLevelAreaMatch) {
|
||||||
|
network_send_level_area_request(np, npAny);
|
||||||
|
} else {
|
||||||
|
network_send_level_request(np, npAny);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void network_send_change_level(void) {
|
||||||
|
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
|
||||||
|
|
||||||
|
// override castle act to 0 to prevent instancing of the hub
|
||||||
|
if (gCurrCourseNum == 0 && (gCurrLevelNum == LEVEL_CASTLE || gCurrLevelNum == LEVEL_CASTLE_GROUNDS || gCurrLevelNum == LEVEL_CASTLE_COURTYARD)) {
|
||||||
|
gCurrActNum = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gNetworkType == NT_SERVER) {
|
||||||
|
player_changed_level(gNetworkPlayerLocal, gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Packet p;
|
||||||
|
packet_init(&p, PACKET_CHANGE_LEVEL, true, false);
|
||||||
|
packet_write(&p, &gCurrCourseNum, sizeof(s16));
|
||||||
|
packet_write(&p, &gCurrActNum, sizeof(s16));
|
||||||
|
packet_write(&p, &gCurrLevelNum, sizeof(s16));
|
||||||
|
packet_write(&p, &gCurrAreaIndex, sizeof(s16));
|
||||||
|
network_send_to(gNetworkPlayerServer->localIndex, &p);
|
||||||
|
|
||||||
|
struct NetworkPlayer* np = gNetworkPlayerLocal;
|
||||||
|
np->currCourseNum = gCurrCourseNum;
|
||||||
|
np->currActNum = gCurrActNum;
|
||||||
|
np->currLevelNum = gCurrLevelNum;
|
||||||
|
np->currAreaIndex = gCurrAreaIndex;
|
||||||
|
np->currAreaSyncValid = false;
|
||||||
|
np->currLevelSyncValid = false;
|
||||||
|
|
||||||
|
LOG_INFO("tx change level");
|
||||||
|
}
|
||||||
|
|
||||||
|
void network_receive_change_level(struct Packet* p) {
|
||||||
|
LOG_INFO("rx change level");
|
||||||
|
|
||||||
|
assert(gNetworkType == NT_SERVER);
|
||||||
|
struct NetworkPlayer* np = &gNetworkPlayers[p->localIndex];
|
||||||
|
if (np == NULL || np->localIndex == UNKNOWN_LOCAL_INDEX || !np->connected) {
|
||||||
|
LOG_ERROR("Receiving change level from inactive player!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s16 courseNum, actNum, levelNum, areaIndex;
|
||||||
|
packet_read(p, &courseNum, sizeof(s16));
|
||||||
|
packet_read(p, &actNum, sizeof(s16));
|
||||||
|
packet_read(p, &levelNum, sizeof(s16));
|
||||||
|
packet_read(p, &areaIndex, sizeof(s16));
|
||||||
|
|
||||||
|
player_changed_level(np, courseNum, actNum, levelNum, areaIndex);
|
||||||
|
}
|
67
src/pc/network/packets/packet_level.c
Normal file
67
src/pc/network/packets/packet_level.c
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "../network.h"
|
||||||
|
#include "game/interaction.h"
|
||||||
|
#include "game/level_update.h"
|
||||||
|
//#define DISABLE_MODULE_LOG 1
|
||||||
|
#include "pc/debuglog.h"
|
||||||
|
|
||||||
|
void network_send_level(struct NetworkPlayer* toNp, bool sendArea) {
|
||||||
|
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum;
|
||||||
|
|
||||||
|
packet_ordered_begin();
|
||||||
|
{
|
||||||
|
struct Packet p;
|
||||||
|
packet_init(&p, PACKET_LEVEL, true, false);
|
||||||
|
|
||||||
|
// level location
|
||||||
|
packet_write(&p, &gCurrCourseNum, sizeof(s16));
|
||||||
|
packet_write(&p, &gCurrActNum, sizeof(s16));
|
||||||
|
packet_write(&p, &gCurrLevelNum, sizeof(s16));
|
||||||
|
|
||||||
|
// level variables
|
||||||
|
packet_write(&p, &gMarioStates[0].numCoins, sizeof(s16));
|
||||||
|
packet_write(&p, &gPssSlideStarted, sizeof(u8));
|
||||||
|
packet_write(&p, &gHudDisplay.timer, sizeof(u16));
|
||||||
|
|
||||||
|
// send level packet
|
||||||
|
network_send_to(toNp->localIndex, &p);
|
||||||
|
|
||||||
|
// send macro deletions
|
||||||
|
network_send_level_macro(toNp);
|
||||||
|
|
||||||
|
// send spawn info
|
||||||
|
network_send_level_spawn_info(toNp);
|
||||||
|
|
||||||
|
if (sendArea) {
|
||||||
|
// send the area
|
||||||
|
network_send_area(toNp);
|
||||||
|
} else {
|
||||||
|
// send sync valid
|
||||||
|
network_send_sync_valid(toNp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
packet_ordered_end();
|
||||||
|
|
||||||
|
LOG_INFO("tx level");
|
||||||
|
}
|
||||||
|
|
||||||
|
void network_receive_level(struct Packet* p) {
|
||||||
|
LOG_INFO("rx level");
|
||||||
|
|
||||||
|
// read level location
|
||||||
|
s16 courseNum, actNum, levelNum;
|
||||||
|
packet_read(p, &courseNum, sizeof(s16));
|
||||||
|
packet_read(p, &actNum, sizeof(s16));
|
||||||
|
packet_read(p, &levelNum, sizeof(s16));
|
||||||
|
|
||||||
|
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum;
|
||||||
|
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum) {
|
||||||
|
LOG_ERROR("rx level: received an improper location");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read level variables
|
||||||
|
packet_write(p, &gMarioStates[0].numCoins, sizeof(s16));
|
||||||
|
packet_write(p, &gPssSlideStarted, sizeof(u8));
|
||||||
|
packet_write(p, &gHudDisplay.timer, sizeof(u16));
|
||||||
|
}
|
|
@ -1,147 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include "level_table.h"
|
|
||||||
#include "../network.h"
|
|
||||||
#include "menu/custom_menu_system.h"
|
|
||||||
//#define DISABLE_MODULE_LOG 1
|
|
||||||
#include "pc/debuglog.h"
|
|
||||||
|
|
||||||
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
|
|
||||||
static u16 currLevelAreaSeqId = 0;
|
|
||||||
|
|
||||||
void network_send_level_area(void) {
|
|
||||||
// override castle act to 0 to prevent instancing of the hub
|
|
||||||
if (gCurrCourseNum == 0 && (gCurrLevelNum == LEVEL_CASTLE || gCurrLevelNum == LEVEL_CASTLE_GROUNDS || gCurrLevelNum == LEVEL_CASTLE_COURTYARD)) {
|
|
||||||
gCurrActNum = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Packet p;
|
|
||||||
currLevelAreaSeqId++;
|
|
||||||
packet_init(&p, PACKET_LEVEL_AREA, true, false);
|
|
||||||
packet_write(&p, &gNetworkPlayerLocal->globalIndex, sizeof(u8));
|
|
||||||
packet_write(&p, &currLevelAreaSeqId, sizeof(u16));
|
|
||||||
packet_write(&p, &gCurrCourseNum, sizeof(s16));
|
|
||||||
packet_write(&p, &gCurrActNum, sizeof(s16));
|
|
||||||
packet_write(&p, &gCurrLevelNum, sizeof(s16));
|
|
||||||
packet_write(&p, &gCurrAreaIndex, sizeof(s16));
|
|
||||||
network_send(&p);
|
|
||||||
|
|
||||||
struct NetworkPlayer* np = gNetworkPlayerLocal;
|
|
||||||
if (np != NULL) {
|
|
||||||
np->currLevelAreaSeqId = currLevelAreaSeqId;
|
|
||||||
np->currCourseNum = gCurrCourseNum;
|
|
||||||
np->currActNum = gCurrActNum;
|
|
||||||
np->currLevelNum = gCurrLevelNum;
|
|
||||||
np->currAreaIndex = gCurrAreaIndex;
|
|
||||||
np->currAreaSyncValid = false;
|
|
||||||
|
|
||||||
//LOG_INFO("set currAreaSyncValid to false");
|
|
||||||
}
|
|
||||||
|
|
||||||
//LOG_INFO("tx location: [%d, %d, %d, %d]", gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void network_receive_level_area(struct Packet* p) {
|
|
||||||
u8 globalIndex;
|
|
||||||
u16 levelAreaSeqId;
|
|
||||||
s16 courseNum, actNum, levelNum, areaIndex;
|
|
||||||
|
|
||||||
packet_read(p, &globalIndex, sizeof(u8));
|
|
||||||
packet_read(p, &levelAreaSeqId, sizeof(u16));
|
|
||||||
packet_read(p, &courseNum, sizeof(s16));
|
|
||||||
packet_read(p, &actNum, sizeof(s16));
|
|
||||||
packet_read(p, &levelNum, sizeof(s16));
|
|
||||||
packet_read(p, &areaIndex, sizeof(s16));
|
|
||||||
|
|
||||||
struct NetworkPlayer* np = network_player_from_global_index(globalIndex);
|
|
||||||
if (np == gNetworkPlayerLocal) {
|
|
||||||
LOG_ERROR("Receiving level area from myself!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (np == NULL || np->localIndex == UNKNOWN_LOCAL_INDEX || !np->connected) {
|
|
||||||
LOG_ERROR("Receiving level area from inactive player global %d!", np->globalIndex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (levelAreaSeqId <= np->currLevelAreaSeqId) {
|
|
||||||
LOG_ERROR("Receiving old level area (%d <= %d) from local %d, global %d!", levelAreaSeqId, np->currLevelAreaSeqId, p->localIndex, np->globalIndex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
np->currLevelAreaSeqId = levelAreaSeqId;
|
|
||||||
np->currCourseNum = courseNum;
|
|
||||||
np->currActNum = actNum;
|
|
||||||
np->currLevelNum = levelNum;
|
|
||||||
np->currAreaIndex = areaIndex;
|
|
||||||
|
|
||||||
//LOG_INFO("rx location: [%d, %d, %d, %d] from local %d, global %d", courseNum, actNum, levelNum, areaIndex, p->localIndex, np->globalIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static void network_send_level_area_valid_server(u8 toGlobalIndex) {
|
|
||||||
struct NetworkPlayer* np = network_player_from_global_index(toGlobalIndex);
|
|
||||||
if (np == NULL || !np->connected) {
|
|
||||||
LOG_ERROR("tried to send level area valid to invalid player");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Packet p;
|
|
||||||
packet_init(&p, PACKET_LEVEL_AREA_VALID, true, false);
|
|
||||||
packet_write(&p, &np->currCourseNum, sizeof(s16));
|
|
||||||
packet_write(&p, &np->currActNum, sizeof(s16));
|
|
||||||
packet_write(&p, &np->currLevelNum, sizeof(s16));
|
|
||||||
packet_write(&p, &np->currAreaIndex, sizeof(s16));
|
|
||||||
network_send_to(np->localIndex, &p);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void network_send_level_area_valid_client() {
|
|
||||||
struct Packet p;
|
|
||||||
packet_init(&p, PACKET_LEVEL_AREA_VALID, true, false);
|
|
||||||
network_send_to(gNetworkPlayerServer->localIndex, &p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void network_send_level_area_valid(u8 toGlobalIndex) {
|
|
||||||
if (gNetworkType == NT_SERVER) {
|
|
||||||
network_send_level_area_valid_server(toGlobalIndex);
|
|
||||||
} else if (toGlobalIndex != 0) {
|
|
||||||
LOG_ERROR("client tried to send 'level area valid' to non-server");
|
|
||||||
} else {
|
|
||||||
network_send_level_area_valid_client();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void network_receive_level_area_valid_server(struct Packet* p) {
|
|
||||||
struct NetworkPlayer* np = &gNetworkPlayers[p->localIndex];
|
|
||||||
if (np == NULL || !np->connected) {
|
|
||||||
LOG_ERROR("network_receive_level_area_valid_server(): invalid network player");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
np->currAreaSyncValid = true;
|
|
||||||
//LOG_INFO("set global %d's currAreaSyncValid to true", np->globalIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void network_receive_level_area_valid_client(struct Packet* p) {
|
|
||||||
s16 courseNum, actNum, levelNum, areaIndex;
|
|
||||||
packet_read(p, &courseNum, sizeof(s16));
|
|
||||||
packet_read(p, &actNum, sizeof(s16));
|
|
||||||
packet_read(p, &levelNum, sizeof(s16));
|
|
||||||
packet_read(p, &areaIndex, sizeof(s16));
|
|
||||||
|
|
||||||
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
|
|
||||||
LOG_ERROR("tried to validate a level area that isn't current");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
gNetworkPlayerLocal->currAreaSyncValid = true;
|
|
||||||
network_send_level_area_valid_client();
|
|
||||||
//LOG_INFO("set currAreaSyncValid to true (3)");
|
|
||||||
}
|
|
||||||
|
|
||||||
void network_receive_level_area_valid(struct Packet* p) {
|
|
||||||
if (gNetworkType == NT_SERVER) {
|
|
||||||
network_receive_level_area_valid_server(p);
|
|
||||||
} else {
|
|
||||||
network_receive_level_area_valid_client(p);
|
|
||||||
}
|
|
||||||
}
|
|
45
src/pc/network/packets/packet_level_area_inform.c
Normal file
45
src/pc/network/packets/packet_level_area_inform.c
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "../network.h"
|
||||||
|
#include "level_table.h"
|
||||||
|
//#define DISABLE_MODULE_LOG 1
|
||||||
|
#include "pc/debuglog.h"
|
||||||
|
|
||||||
|
void network_send_level_area_inform(struct NetworkPlayer* np) {
|
||||||
|
assert(gNetworkType == NT_SERVER);
|
||||||
|
|
||||||
|
struct Packet p;
|
||||||
|
packet_init(&p, PACKET_LEVEL_AREA_INFORM, true, false);
|
||||||
|
packet_write(&p, &np->globalIndex, sizeof(u8));
|
||||||
|
packet_write(&p, &np->currCourseNum, sizeof(s16));
|
||||||
|
packet_write(&p, &np->currActNum, sizeof(s16));
|
||||||
|
packet_write(&p, &np->currLevelNum, sizeof(s16));
|
||||||
|
packet_write(&p, &np->currAreaIndex, sizeof(s16));
|
||||||
|
network_send(&p);
|
||||||
|
|
||||||
|
LOG_INFO("tx level area inform");
|
||||||
|
}
|
||||||
|
|
||||||
|
void network_receive_level_area_inform(struct Packet* p) {
|
||||||
|
LOG_INFO("rx level area inform");
|
||||||
|
|
||||||
|
assert(gNetworkType != NT_SERVER);
|
||||||
|
|
||||||
|
u8 globalIndex;
|
||||||
|
s16 courseNum, actNum, levelNum, areaIndex;
|
||||||
|
packet_read(p, &globalIndex, sizeof(u8));
|
||||||
|
packet_read(p, &courseNum, sizeof(s16));
|
||||||
|
packet_read(p, &actNum, sizeof(s16));
|
||||||
|
packet_read(p, &levelNum, sizeof(s16));
|
||||||
|
packet_read(p, &areaIndex, sizeof(s16));
|
||||||
|
|
||||||
|
struct NetworkPlayer* np = network_player_from_global_index(globalIndex);
|
||||||
|
if (np == NULL || np->localIndex == UNKNOWN_LOCAL_INDEX || !np->connected) {
|
||||||
|
LOG_ERROR("Receiving level area inform from inactive player!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
np->currCourseNum = courseNum;
|
||||||
|
np->currActNum = actNum;
|
||||||
|
np->currLevelNum = levelNum;
|
||||||
|
np->currAreaIndex = areaIndex;
|
||||||
|
}
|
49
src/pc/network/packets/packet_level_area_request.c
Normal file
49
src/pc/network/packets/packet_level_area_request.c
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "../network.h"
|
||||||
|
//#define DISABLE_MODULE_LOG 1
|
||||||
|
#include "pc/debuglog.h"
|
||||||
|
|
||||||
|
void network_send_level_area_request(struct NetworkPlayer* fromNp, struct NetworkPlayer* toNp) {
|
||||||
|
if (gNetworkType == NT_SERVER && toNp == gNetworkPlayerLocal) {
|
||||||
|
// requesting server's level area, send it immediately
|
||||||
|
network_send_level(fromNp, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Packet p;
|
||||||
|
packet_init(&p, PACKET_LEVEL_AREA_REQUEST, true, false);
|
||||||
|
packet_write(&p, &fromNp->globalIndex, sizeof(u8));
|
||||||
|
packet_write(&p, &fromNp->currCourseNum, sizeof(s16));
|
||||||
|
packet_write(&p, &fromNp->currActNum, sizeof(s16));
|
||||||
|
packet_write(&p, &fromNp->currLevelNum, sizeof(s16));
|
||||||
|
packet_write(&p, &fromNp->currAreaIndex, sizeof(s16));
|
||||||
|
network_send_to(toNp->localIndex, &p);
|
||||||
|
LOG_INFO("tx level area request");
|
||||||
|
}
|
||||||
|
|
||||||
|
void network_receive_level_area_request(struct Packet* p) {
|
||||||
|
LOG_INFO("rx level area request");
|
||||||
|
|
||||||
|
u8 globalIndex;
|
||||||
|
s16 courseNum, actNum, levelNum, areaIndex;
|
||||||
|
packet_read(p, &globalIndex, sizeof(u8));
|
||||||
|
packet_read(p, &courseNum, sizeof(s16));
|
||||||
|
packet_read(p, &actNum, sizeof(s16));
|
||||||
|
packet_read(p, &levelNum, sizeof(s16));
|
||||||
|
packet_read(p, &areaIndex, sizeof(s16));
|
||||||
|
|
||||||
|
struct NetworkPlayer* toNp = network_player_from_global_index(globalIndex);
|
||||||
|
if (toNp == NULL || toNp->localIndex == UNKNOWN_LOCAL_INDEX || !toNp->connected) {
|
||||||
|
LOG_ERROR("Receiving level area request from inactive player!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
|
||||||
|
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
|
||||||
|
LOG_ERROR("rx level area request: received an improper location");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send level area
|
||||||
|
network_send_level(toNp, true);
|
||||||
|
}
|
|
@ -25,23 +25,22 @@ static struct Object* get_object_matching_respawn_info(s16* respawnInfo) {
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
void network_send_macro_deletions_area(u8 destGlobalIndex, u8 areaIndex) {
|
static void network_send_level_macro_area(struct NetworkPlayer* destNp, u8 areaIndex) {
|
||||||
// check that the area is active
|
// check that the area is active
|
||||||
struct Area* area = &gAreaData[areaIndex];
|
struct Area* area = &gAreaData[areaIndex];
|
||||||
if (area->unk04 == NULL) { return; }
|
if (area->unk04 == NULL) { return; }
|
||||||
|
|
||||||
struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex);
|
|
||||||
if (destNp == NULL || !destNp->connected) {
|
if (destNp == NULL || !destNp->connected) {
|
||||||
LOG_ERROR("network_send_macro_deletions_area: dest np is invalid");
|
LOG_ERROR("network_send_level_macro: dest np is invalid");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// write header
|
// write header
|
||||||
struct Packet p;
|
struct Packet p;
|
||||||
packet_init(&p, PACKET_MACRO_DELETIONS, true, false);
|
packet_init(&p, PACKET_LEVEL_MACRO, true, false);
|
||||||
packet_write(&p, &gCurrCourseNum, sizeof(s16));
|
packet_write(&p, &gCurrCourseNum, sizeof(s16));
|
||||||
packet_write(&p, &gCurrActNum, sizeof(s16));
|
packet_write(&p, &gCurrActNum, sizeof(s16));
|
||||||
packet_write(&p, &gCurrLevelNum, sizeof(s16));
|
packet_write(&p, &gCurrLevelNum, sizeof(s16));
|
||||||
packet_write(&p, &gCurrAreaIndex, sizeof(s16));
|
packet_write(&p, &gCurrAreaIndex, sizeof(s16));
|
||||||
|
|
||||||
// write this area's index
|
// write this area's index
|
||||||
|
@ -54,7 +53,7 @@ void network_send_macro_deletions_area(u8 destGlobalIndex, u8 areaIndex) {
|
||||||
|
|
||||||
// loop through macro objects for deletions
|
// loop through macro objects for deletions
|
||||||
s16* macroObjList = area->macroObjects;
|
s16* macroObjList = area->macroObjects;
|
||||||
while (*macroObjList != -1) {
|
while (macroObjList != NULL && *macroObjList != -1) {
|
||||||
// grab preset ID
|
// grab preset ID
|
||||||
s32 presetID = (*macroObjList & 0x1FF) - 31; // Preset identifier for MacroObjectPresets array
|
s32 presetID = (*macroObjList & 0x1FF) - 31; // Preset identifier for MacroObjectPresets array
|
||||||
if (presetID < 0) { break; }
|
if (presetID < 0) { break; }
|
||||||
|
@ -68,7 +67,7 @@ void network_send_macro_deletions_area(u8 destGlobalIndex, u8 areaIndex) {
|
||||||
*macroDeletionCount = *macroDeletionCount + 1;
|
*macroDeletionCount = *macroDeletionCount + 1;
|
||||||
u16 offset = respawnInfo - area->macroObjects;
|
u16 offset = respawnInfo - area->macroObjects;
|
||||||
packet_write(&p, &offset, sizeof(u16));
|
packet_write(&p, &offset, sizeof(u16));
|
||||||
LOG_INFO("tx macro deletion: offset %d", offset);
|
LOG_INFO("tx macro: offset %d", offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +77,7 @@ void network_send_macro_deletions_area(u8 destGlobalIndex, u8 areaIndex) {
|
||||||
|
|
||||||
// loop through macro objects for special cases
|
// loop through macro objects for special cases
|
||||||
macroObjList = area->macroObjects;
|
macroObjList = area->macroObjects;
|
||||||
while (*macroObjList != -1) {
|
while (macroObjList != NULL && *macroObjList != -1) {
|
||||||
// grab preset ID
|
// grab preset ID
|
||||||
s32 presetID = (*macroObjList & 0x1FF) - 31; // Preset identifier for MacroObjectPresets array
|
s32 presetID = (*macroObjList & 0x1FF) - 31; // Preset identifier for MacroObjectPresets array
|
||||||
if (presetID < 0) { break; }
|
if (presetID < 0) { break; }
|
||||||
|
@ -101,33 +100,32 @@ void network_send_macro_deletions_area(u8 destGlobalIndex, u8 areaIndex) {
|
||||||
// send the packet if there are deletions
|
// send the packet if there are deletions
|
||||||
if (*macroDeletionCount > 0 || *macroSpecialCount > 0) {
|
if (*macroDeletionCount > 0 || *macroSpecialCount > 0) {
|
||||||
network_send_to(destNp->localIndex, &p);
|
network_send_to(destNp->localIndex, &p);
|
||||||
LOG_INFO("tx macro deletion for area %d (count %d)", areaIndex, *macroDeletionCount);
|
LOG_INFO("tx macro for area %d (count %d, %d)", areaIndex, *macroDeletionCount, *macroSpecialCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void network_send_macro_deletions(u8 destGlobalIndex) {
|
void network_send_level_macro(struct NetworkPlayer* destNp) {
|
||||||
if (!gNetworkPlayerLocal->currAreaSyncValid) {
|
if (!gNetworkPlayerLocal->currLevelSyncValid) {
|
||||||
LOG_ERROR("my area is invalid");
|
LOG_ERROR("my area is invalid");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex);
|
|
||||||
if (destNp == NULL || !destNp->connected) {
|
if (destNp == NULL || !destNp->connected) {
|
||||||
LOG_ERROR("network_send_macro_deletions: dest np is invalid");
|
LOG_ERROR("network_send_level_macro: dest np is invalid");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
network_send_macro_deletions_area(destGlobalIndex, i);
|
network_send_level_macro_area(destNp, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void network_receive_macro_deletions(struct Packet* p) {
|
void network_receive_level_macro(struct Packet* p) {
|
||||||
s16 courseNum, actNum, levelNum, areaIndex;
|
s16 courseNum, actNum, levelNum, areaIndex;
|
||||||
packet_read(p, &courseNum, sizeof(s16));
|
packet_read(p, &courseNum, sizeof(s16));
|
||||||
packet_read(p, &actNum, sizeof(s16));
|
packet_read(p, &actNum, sizeof(s16));
|
||||||
packet_read(p, &levelNum, sizeof(s16));
|
packet_read(p, &levelNum, sizeof(s16));
|
||||||
packet_read(p, &areaIndex, sizeof(s16));
|
packet_read(p, &areaIndex, sizeof(s16));
|
||||||
|
|
||||||
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum) {
|
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum) {
|
||||||
LOG_ERROR("Receiving 'location response' with the wrong location!");
|
LOG_ERROR("Receiving 'location response' with the wrong location!");
|
||||||
|
@ -140,7 +138,7 @@ void network_receive_macro_deletions(struct Packet* p) {
|
||||||
// read and execute macro deletions
|
// read and execute macro deletions
|
||||||
u8 macroDeletionCount;
|
u8 macroDeletionCount;
|
||||||
packet_read(p, ¯oDeletionCount, sizeof(u8));
|
packet_read(p, ¯oDeletionCount, sizeof(u8));
|
||||||
LOG_INFO("rx macro deletions (count %d)", macroDeletionCount);
|
LOG_INFO("rx macro (count %d)", macroDeletionCount);
|
||||||
|
|
||||||
while (macroDeletionCount-- > 0) {
|
while (macroDeletionCount-- > 0) {
|
||||||
u16 offset;
|
u16 offset;
|
||||||
|
@ -166,7 +164,6 @@ void network_receive_macro_deletions(struct Packet* p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// read and execute macro specials
|
// read and execute macro specials
|
||||||
|
|
||||||
u8 macroSpecialCount;
|
u8 macroSpecialCount;
|
||||||
packet_read(p, ¯oSpecialCount, sizeof(u8));
|
packet_read(p, ¯oSpecialCount, sizeof(u8));
|
||||||
while (macroSpecialCount-- > 0) {
|
while (macroSpecialCount-- > 0) {
|
47
src/pc/network/packets/packet_level_request.c
Normal file
47
src/pc/network/packets/packet_level_request.c
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "../network.h"
|
||||||
|
//#define DISABLE_MODULE_LOG 1
|
||||||
|
#include "pc/debuglog.h"
|
||||||
|
|
||||||
|
void network_send_level_request(struct NetworkPlayer* fromNp, struct NetworkPlayer* toNp) {
|
||||||
|
if (gNetworkType == NT_SERVER && toNp == gNetworkPlayerLocal) {
|
||||||
|
// requesting server's level, send it immediately
|
||||||
|
network_send_level(fromNp, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Packet p;
|
||||||
|
packet_init(&p, PACKET_LEVEL_REQUEST, true, false);
|
||||||
|
packet_write(&p, &fromNp->globalIndex, sizeof(u8));
|
||||||
|
packet_write(&p, &fromNp->currCourseNum, sizeof(s16));
|
||||||
|
packet_write(&p, &fromNp->currActNum, sizeof(s16));
|
||||||
|
packet_write(&p, &fromNp->currLevelNum, sizeof(s16));
|
||||||
|
network_send_to(toNp->localIndex, &p);
|
||||||
|
LOG_INFO("tx level request");
|
||||||
|
}
|
||||||
|
|
||||||
|
void network_receive_level_request(struct Packet* p) {
|
||||||
|
LOG_INFO("rx level request");
|
||||||
|
|
||||||
|
u8 globalIndex;
|
||||||
|
s16 courseNum, actNum, levelNum;
|
||||||
|
packet_read(p, &globalIndex, sizeof(u8));
|
||||||
|
packet_read(p, &courseNum, sizeof(s16));
|
||||||
|
packet_read(p, &actNum, sizeof(s16));
|
||||||
|
packet_read(p, &levelNum, sizeof(s16));
|
||||||
|
|
||||||
|
struct NetworkPlayer* toNp = network_player_from_global_index(globalIndex);
|
||||||
|
if (toNp == NULL || toNp->localIndex == UNKNOWN_LOCAL_INDEX || !toNp->connected) {
|
||||||
|
LOG_ERROR("Receiving level request from inactive player!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum;
|
||||||
|
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum) {
|
||||||
|
LOG_ERROR("rx level request: received an improper location");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send level
|
||||||
|
network_send_level(toNp, false);
|
||||||
|
}
|
|
@ -13,7 +13,7 @@
|
||||||
#define DISABLE_MODULE_LOG 1
|
#define DISABLE_MODULE_LOG 1
|
||||||
#include "pc/debuglog.h"
|
#include "pc/debuglog.h"
|
||||||
|
|
||||||
static struct Object* get_object_matching_respawn_info(s32* respawnInfo) {
|
static struct Object* get_object_matching_respawn_info(u32* respawnInfo) {
|
||||||
for (int i = 0; i < OBJECT_POOL_CAPACITY; i++) {
|
for (int i = 0; i < OBJECT_POOL_CAPACITY; i++) {
|
||||||
struct Object* o = &gObjectPool[i];
|
struct Object* o = &gObjectPool[i];
|
||||||
if (o->respawnInfo == respawnInfo) { return o; }
|
if (o->respawnInfo == respawnInfo) { return o; }
|
||||||
|
@ -24,20 +24,19 @@ static struct Object* get_object_matching_respawn_info(s32* respawnInfo) {
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
void network_send_spawn_info_deletions_area(u8 destGlobalIndex, u8 areaIndex) {
|
static void network_send_level_spawn_info_area(struct NetworkPlayer* destNp, u8 areaIndex) {
|
||||||
// check that the area is active
|
// check that the area is active
|
||||||
struct Area* area = &gAreaData[areaIndex];
|
struct Area* area = &gAreaData[areaIndex];
|
||||||
if (area->unk04 == NULL) { return; }
|
if (area->unk04 == NULL) { return; }
|
||||||
|
|
||||||
struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex);
|
|
||||||
if (destNp == NULL || !destNp->connected) {
|
if (destNp == NULL || !destNp->connected) {
|
||||||
LOG_ERROR("network_send_spawn_info_deletions_area: dest np is invalid");
|
LOG_ERROR("network_send_level_spawn_info_area: dest np is invalid");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// write header
|
// write header
|
||||||
struct Packet p;
|
struct Packet p;
|
||||||
packet_init(&p, PACKET_SPAWN_INFO_DELETIONS, true, false);
|
packet_init(&p, PACKET_LEVEL_SPAWN_INFO, true, false);
|
||||||
packet_write(&p, &gCurrCourseNum, sizeof(s16));
|
packet_write(&p, &gCurrCourseNum, sizeof(s16));
|
||||||
packet_write(&p, &gCurrActNum, sizeof(s16));
|
packet_write(&p, &gCurrActNum, sizeof(s16));
|
||||||
packet_write(&p, &gCurrLevelNum, sizeof(s16));
|
packet_write(&p, &gCurrLevelNum, sizeof(s16));
|
||||||
|
@ -70,28 +69,27 @@ void network_send_spawn_info_deletions_area(u8 destGlobalIndex, u8 areaIndex) {
|
||||||
// send the packet if there are deletions
|
// send the packet if there are deletions
|
||||||
if (*spawnInfoDeletionCount > 0) {
|
if (*spawnInfoDeletionCount > 0) {
|
||||||
network_send_to(destNp->localIndex, &p);
|
network_send_to(destNp->localIndex, &p);
|
||||||
LOG_INFO("tx spawn info deletion for area %d (count %d)", areaIndex, *spawnInfoDeletionCount);
|
LOG_INFO("tx spawn info for area %d (count %d)", areaIndex, *spawnInfoDeletionCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void network_send_spawn_info_deletions(u8 destGlobalIndex) {
|
void network_send_level_spawn_info(struct NetworkPlayer* destNp) {
|
||||||
if (!gNetworkPlayerLocal->currAreaSyncValid) {
|
if (!gNetworkPlayerLocal->currAreaSyncValid) {
|
||||||
LOG_ERROR("my area is invalid");
|
LOG_ERROR("my area is invalid");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex);
|
|
||||||
if (destNp == NULL || !destNp->connected) {
|
if (destNp == NULL || !destNp->connected) {
|
||||||
LOG_ERROR("network_send_spawn_info_deletions: dest np is invalid");
|
LOG_ERROR("network_send_level_spawn_info: dest np is invalid");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
network_send_spawn_info_deletions_area(destGlobalIndex, i);
|
network_send_level_spawn_info_area(destNp, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void network_receive_spawn_info_deletions(struct Packet* p) {
|
void network_receive_level_spawn_info(struct Packet* p) {
|
||||||
s16 courseNum, actNum, levelNum, areaIndex;
|
s16 courseNum, actNum, levelNum, areaIndex;
|
||||||
packet_read(p, &courseNum, sizeof(s16));
|
packet_read(p, &courseNum, sizeof(s16));
|
||||||
packet_read(p, &actNum, sizeof(s16));
|
packet_read(p, &actNum, sizeof(s16));
|
||||||
|
@ -106,7 +104,7 @@ void network_receive_spawn_info_deletions(struct Packet* p) {
|
||||||
u8 thisAreaIndex, spawnInfoDeletionCount;
|
u8 thisAreaIndex, spawnInfoDeletionCount;
|
||||||
packet_read(p, &thisAreaIndex, sizeof(u8));
|
packet_read(p, &thisAreaIndex, sizeof(u8));
|
||||||
packet_read(p, &spawnInfoDeletionCount, sizeof(u8));
|
packet_read(p, &spawnInfoDeletionCount, sizeof(u8));
|
||||||
LOG_INFO("rx spawn info deletions (count %d)", spawnInfoDeletionCount);
|
LOG_INFO("rx spawn info (count %d)", spawnInfoDeletionCount);
|
||||||
if (spawnInfoDeletionCount <= 0) { return; }
|
if (spawnInfoDeletionCount <= 0) { return; }
|
||||||
|
|
||||||
struct SpawnInfo* spawnInfo = gAreaData[thisAreaIndex].objectSpawnInfos;
|
struct SpawnInfo* spawnInfo = gAreaData[thisAreaIndex].objectSpawnInfos;
|
|
@ -1,60 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include "../network.h"
|
|
||||||
//#define DISABLE_MODULE_LOG 1
|
|
||||||
#include "pc/debuglog.h"
|
|
||||||
|
|
||||||
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
|
|
||||||
|
|
||||||
void network_send_location_request(void) {
|
|
||||||
if (gNetworkType == NT_SERVER) {
|
|
||||||
struct NetworkPlayer* np = get_network_player_from_valid_location(gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex);
|
|
||||||
if (np == NULL) {
|
|
||||||
gNetworkPlayerLocal->currAreaSyncValid = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
network_send_location_request_client(gNetworkPlayerLocal->globalIndex, np->globalIndex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Packet p;
|
|
||||||
packet_init(&p, PACKET_LOCATION_REQUEST, true, false);
|
|
||||||
packet_write(&p, &gCurrCourseNum, sizeof(s16));
|
|
||||||
packet_write(&p, &gCurrActNum, sizeof(s16));
|
|
||||||
packet_write(&p, &gCurrLevelNum, sizeof(s16));
|
|
||||||
packet_write(&p, &gCurrAreaIndex, sizeof(s16));
|
|
||||||
network_send_to(0, &p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void network_receive_location_request(struct Packet* p) {
|
|
||||||
if (gNetworkType != NT_SERVER) {
|
|
||||||
LOG_ERROR("non-server is receiving a location request!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NetworkPlayer* np = &gNetworkPlayers[p->localIndex];
|
|
||||||
if (np == NULL || np->localIndex == UNKNOWN_LOCAL_INDEX || !np->connected) {
|
|
||||||
LOG_ERROR("Receiving location request from inactive player!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
s16 courseNum, actNum, levelNum, areaIndex;
|
|
||||||
packet_read(p, &courseNum, sizeof(s16));
|
|
||||||
packet_read(p, &actNum, sizeof(s16));
|
|
||||||
packet_read(p, &levelNum, sizeof(s16));
|
|
||||||
packet_read(p, &areaIndex, sizeof(s16));
|
|
||||||
|
|
||||||
np->currCourseNum = courseNum;
|
|
||||||
np->currActNum = actNum;
|
|
||||||
np->currLevelNum = levelNum;
|
|
||||||
np->currAreaIndex = areaIndex;
|
|
||||||
np->currAreaSyncValid = false;
|
|
||||||
|
|
||||||
struct NetworkPlayer* np2 = get_network_player_from_valid_location(courseNum, actNum, levelNum, areaIndex);
|
|
||||||
if (np2 == NULL) {
|
|
||||||
network_send_level_area_valid(np->globalIndex);
|
|
||||||
} else if (np2 == gNetworkPlayerLocal) {
|
|
||||||
network_send_location_response(np->globalIndex);
|
|
||||||
} else {
|
|
||||||
network_send_location_request_client(np->globalIndex, np2->globalIndex);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include "../network.h"
|
|
||||||
//#define DISABLE_MODULE_LOG 1
|
|
||||||
#include "pc/debuglog.h"
|
|
||||||
|
|
||||||
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
|
|
||||||
|
|
||||||
void network_send_location_request_client(u8 destGlobalIndex, u8 srcGlobalIndex) {
|
|
||||||
if (gNetworkType != NT_SERVER) {
|
|
||||||
LOG_ERROR("client can't send a 'client location request'");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex);
|
|
||||||
if (destNp == NULL || !destNp->connected) {
|
|
||||||
LOG_ERROR("network_send_client_location_request: dest np is invalid (global %d)", destGlobalIndex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Packet p;
|
|
||||||
packet_init(&p, PACKET_LOCATION_REQUEST_CLIENT, true, false);
|
|
||||||
packet_write(&p, &destGlobalIndex, sizeof(u8));
|
|
||||||
packet_write(&p, &destNp->currCourseNum, sizeof(s16));
|
|
||||||
packet_write(&p, &destNp->currActNum, sizeof(s16));
|
|
||||||
packet_write(&p, &destNp->currLevelNum, sizeof(s16));
|
|
||||||
packet_write(&p, &destNp->currAreaIndex, sizeof(s16));
|
|
||||||
|
|
||||||
struct NetworkPlayer* srcNp = network_player_from_global_index(srcGlobalIndex);
|
|
||||||
if (srcNp == NULL || !srcNp->connected || !srcNp->currAreaSyncValid) {
|
|
||||||
LOG_ERROR("network_send_client_location_request: source np is invalid (global %d)", srcGlobalIndex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
network_send_to(srcNp->localIndex, &p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void network_receive_location_request_client(struct Packet* p) {
|
|
||||||
if (gNetworkType == NT_SERVER) {
|
|
||||||
LOG_ERROR("server is receiving a 'client location request'!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 destGlobalIndex;
|
|
||||||
s16 courseNum, actNum, levelNum, areaIndex;
|
|
||||||
packet_read(p, &destGlobalIndex, sizeof(u8));
|
|
||||||
packet_read(p, &courseNum, sizeof(s16));
|
|
||||||
packet_read(p, &actNum, sizeof(s16));
|
|
||||||
packet_read(p, &levelNum, sizeof(s16));
|
|
||||||
packet_read(p, &areaIndex, sizeof(s16));
|
|
||||||
|
|
||||||
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
|
|
||||||
LOG_ERROR("Receiving 'client location request' with the wrong location!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
network_send_location_response(destGlobalIndex);
|
|
||||||
}
|
|
|
@ -1,189 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include "../network.h"
|
|
||||||
#include "game/interaction.h"
|
|
||||||
#include "game/object_list_processor.h"
|
|
||||||
#include "game/object_helpers.h"
|
|
||||||
#include "game/interaction.h"
|
|
||||||
#include "game/level_update.h"
|
|
||||||
#include "game/macro_special_objects.h"
|
|
||||||
#include "object_constants.h"
|
|
||||||
#include "object_fields.h"
|
|
||||||
#include "behavior_table.h"
|
|
||||||
#include "model_ids.h"
|
|
||||||
//#define DISABLE_MODULE_LOG 1
|
|
||||||
#include "pc/debuglog.h"
|
|
||||||
|
|
||||||
void network_send_location_response(u8 destGlobalIndex) {
|
|
||||||
if (!gNetworkPlayerLocal->currAreaSyncValid) {
|
|
||||||
LOG_ERROR("my area is invalid");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex);
|
|
||||||
if (destNp == NULL || !destNp->connected) {
|
|
||||||
LOG_ERROR("network_send_location_response: dest np is invalid");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Packet p;
|
|
||||||
packet_init(&p, PACKET_LOCATION_RESPONSE, true, false);
|
|
||||||
packet_write(&p, &gCurrCourseNum, sizeof(s16));
|
|
||||||
packet_write(&p, &gCurrActNum, sizeof(s16));
|
|
||||||
packet_write(&p, &gCurrLevelNum, sizeof(s16));
|
|
||||||
packet_write(&p, &gCurrAreaIndex, sizeof(s16));
|
|
||||||
|
|
||||||
// level variables
|
|
||||||
packet_write(&p, &gMarioStates[0].numCoins, sizeof(s16));
|
|
||||||
packet_write(&p, &gPssSlideStarted, sizeof(u8));
|
|
||||||
packet_write(&p, &gHudDisplay.timer, sizeof(u16));
|
|
||||||
|
|
||||||
// respawners
|
|
||||||
u8 respawnerCount = 0;
|
|
||||||
for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
|
|
||||||
struct SyncObject* so = &gSyncObjects[i];
|
|
||||||
if (so == NULL || so->o == NULL || so->o->behavior != bhvRespawner) { continue; }
|
|
||||||
respawnerCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
packet_write(&p, &respawnerCount, sizeof(u8));
|
|
||||||
for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
|
|
||||||
struct SyncObject* so = &gSyncObjects[i];
|
|
||||||
if (so == NULL || so->o == NULL || so->o->behavior != bhvRespawner) { continue; }
|
|
||||||
u32 behaviorToRespawn = get_id_from_behavior(so->o->oRespawnerBehaviorToRespawn);
|
|
||||||
packet_write(&p, &so->o->oPosX, sizeof(f32));
|
|
||||||
packet_write(&p, &so->o->oPosY, sizeof(f32));
|
|
||||||
packet_write(&p, &so->o->oPosZ, sizeof(f32));
|
|
||||||
packet_write(&p, &so->o->oBehParams, sizeof(s32));
|
|
||||||
packet_write(&p, &so->o->oRespawnerModelToRespawn, sizeof(s32));
|
|
||||||
packet_write(&p, &so->o->oRespawnerMinSpawnDist, sizeof(f32));
|
|
||||||
packet_write(&p, &behaviorToRespawn, sizeof(s32));
|
|
||||||
packet_write(&p, &so->o->oSyncID, sizeof(u32));
|
|
||||||
LOG_INFO("tx respawner");
|
|
||||||
}
|
|
||||||
|
|
||||||
network_send_to(destNp->localIndex, &p);
|
|
||||||
|
|
||||||
// send macro deletions
|
|
||||||
network_send_macro_deletions(destGlobalIndex);
|
|
||||||
|
|
||||||
// send spawn info
|
|
||||||
network_send_spawn_info_deletions(destGlobalIndex);
|
|
||||||
|
|
||||||
// send non-static objects
|
|
||||||
for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
|
|
||||||
struct SyncObject* so = &gSyncObjects[i];
|
|
||||||
if (so == NULL || so->o == NULL || so->o->oSyncID != i) { continue; }
|
|
||||||
if (so->staticLevelSpawn) { continue; }
|
|
||||||
if (so->o->behavior == bhvRespawner) { continue; }
|
|
||||||
struct Object* spawn_objects[] = { so->o };
|
|
||||||
|
|
||||||
// TODO: move find model to a utility file/function
|
|
||||||
// find model
|
|
||||||
u32 model = 0;
|
|
||||||
for (int j = 0; j < 256; j++) {
|
|
||||||
if (so->o->header.gfx.sharedChild == gLoadedGraphNodes[j]) {
|
|
||||||
model = j;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 models[] = { model };
|
|
||||||
network_send_spawn_objects_to(destNp->localIndex, spawn_objects, models, 1);
|
|
||||||
LOG_INFO("tx non-static");
|
|
||||||
}
|
|
||||||
|
|
||||||
// send last reliable ent packet
|
|
||||||
for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
|
|
||||||
struct SyncObject* so = &gSyncObjects[i];
|
|
||||||
if (so == NULL || so->o == NULL) { continue; }
|
|
||||||
struct Packet* entPacket = get_last_sync_ent_reliable_packet(i);
|
|
||||||
if (entPacket->error) { continue; }
|
|
||||||
struct Packet p2 = { 0 };
|
|
||||||
packet_duplicate(entPacket, &p2);
|
|
||||||
network_send_to(destNp->localIndex, &p2);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_INFO("tx location response");
|
|
||||||
}
|
|
||||||
|
|
||||||
void network_receive_location_response(struct Packet* p) {
|
|
||||||
s16 courseNum, actNum, levelNum, areaIndex;
|
|
||||||
packet_read(p, &courseNum, sizeof(s16));
|
|
||||||
packet_read(p, &actNum, sizeof(s16));
|
|
||||||
packet_read(p, &levelNum, sizeof(s16));
|
|
||||||
packet_read(p, &areaIndex, sizeof(s16));
|
|
||||||
|
|
||||||
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
|
|
||||||
LOG_ERROR("Receiving 'location response' with the wrong location!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gNetworkPlayerLocal->currAreaSyncValid) {
|
|
||||||
LOG_ERROR("Receiving 'location response' when our location is already valid!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
s16 numCoins;
|
|
||||||
packet_read(p, &numCoins, sizeof(s16));
|
|
||||||
|
|
||||||
u8 pssSlideStarted;
|
|
||||||
u16 hudDisplayTimer;
|
|
||||||
packet_read(p, &pssSlideStarted, sizeof(u8));
|
|
||||||
packet_read(p, &hudDisplayTimer, sizeof(u16));
|
|
||||||
if (pssSlideStarted) {
|
|
||||||
level_control_timer(TIMER_CONTROL_SHOW);
|
|
||||||
level_control_timer(TIMER_CONTROL_START);
|
|
||||||
gPssSlideStarted = TRUE;
|
|
||||||
gHudDisplay.timer = hudDisplayTimer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read respawners
|
|
||||||
u8 respawnerCount = 0;
|
|
||||||
packet_read(p, &respawnerCount, sizeof(u8));
|
|
||||||
|
|
||||||
for (int i = 0; i < respawnerCount; i++) {
|
|
||||||
f32 posX, posY, posZ;
|
|
||||||
packet_read(p, &posX, sizeof(f32));
|
|
||||||
packet_read(p, &posY, sizeof(f32));
|
|
||||||
packet_read(p, &posZ, sizeof(f32));
|
|
||||||
|
|
||||||
s32 behParams, respawnerModelToRespawn;
|
|
||||||
packet_read(p, &behParams, sizeof(s32));
|
|
||||||
packet_read(p, &respawnerModelToRespawn, sizeof(s32));
|
|
||||||
|
|
||||||
f32 respawnerMinSpawnDist;
|
|
||||||
packet_read(p, &respawnerMinSpawnDist, sizeof(f32));
|
|
||||||
|
|
||||||
u32 behaviorToRespawn, syncId;
|
|
||||||
packet_read(p, &behaviorToRespawn, sizeof(u32));
|
|
||||||
packet_read(p, &syncId, sizeof(u32));
|
|
||||||
|
|
||||||
struct SyncObject* so = &gSyncObjects[syncId];
|
|
||||||
|
|
||||||
LOG_INFO("rx respawner");
|
|
||||||
if (so->staticLevelSpawn) {
|
|
||||||
struct Object* respawner = spawn_object_abs_with_rot(gMarioStates[0].marioObj, 0, MODEL_NONE, bhvRespawner, posX, posY, posZ, 0, 0, 0);
|
|
||||||
respawner->parentObj = respawner;
|
|
||||||
respawner->oBehParams = behParams;
|
|
||||||
respawner->oRespawnerModelToRespawn = respawnerModelToRespawn;
|
|
||||||
respawner->oRespawnerMinSpawnDist = respawnerMinSpawnDist;
|
|
||||||
respawner->oRespawnerBehaviorToRespawn = get_behavior_from_id(behaviorToRespawn);
|
|
||||||
respawner->oSyncID = syncId;
|
|
||||||
|
|
||||||
struct Object* o = so->o;
|
|
||||||
o->oSyncID = 0;
|
|
||||||
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
|
|
||||||
|
|
||||||
so->o = respawner;
|
|
||||||
LOG_INFO("rx respawner replaced!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gMarioStates[0].numCoins = numCoins;
|
|
||||||
gNetworkPlayerLocal->currAreaSyncValid = true;
|
|
||||||
|
|
||||||
if (gNetworkType != NT_SERVER) {
|
|
||||||
network_send_level_area_valid(0);
|
|
||||||
}
|
|
||||||
LOG_INFO("rx location response");
|
|
||||||
}
|
|
|
@ -140,3 +140,11 @@ bool packet_check_hash(struct Packet* packet) {
|
||||||
memcpy(&packetHash, &packet->buffer[packet->dataLength], sizeof(u32));
|
memcpy(&packetHash, &packet->buffer[packet->dataLength], sizeof(u32));
|
||||||
return localHash == packetHash;
|
return localHash == packetHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void packet_ordered_begin(void) {
|
||||||
|
// TODO: implement ordered packet streams
|
||||||
|
}
|
||||||
|
|
||||||
|
void packet_ordered_end(void) {
|
||||||
|
// TODO: implement ordered packet streams
|
||||||
|
}
|
||||||
|
|
62
src/pc/network/packets/packet_sync_valid.c
Normal file
62
src/pc/network/packets/packet_sync_valid.c
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "../network.h"
|
||||||
|
//#define DISABLE_MODULE_LOG 1
|
||||||
|
#include "pc/debuglog.h"
|
||||||
|
|
||||||
|
void network_send_sync_valid(struct NetworkPlayer* toNp) {
|
||||||
|
// set the NetworkPlayers sync valid
|
||||||
|
toNp->currLevelSyncValid = true;
|
||||||
|
toNp->currAreaSyncValid = true;
|
||||||
|
|
||||||
|
if (toNp == gNetworkPlayerLocal) {
|
||||||
|
// the player is the server, no need to send it
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 myGlobalIndex = gNetworkPlayerLocal->globalIndex;
|
||||||
|
struct Packet p;
|
||||||
|
packet_init(&p, PACKET_SYNC_VALID, true, false);
|
||||||
|
packet_write(&p, &toNp->currCourseNum, sizeof(s16));
|
||||||
|
packet_write(&p, &toNp->currActNum, sizeof(s16));
|
||||||
|
packet_write(&p, &toNp->currLevelNum, sizeof(s16));
|
||||||
|
packet_write(&p, &toNp->currAreaIndex, sizeof(s16));
|
||||||
|
packet_write(&p, &myGlobalIndex, sizeof(u8));
|
||||||
|
network_send_to(toNp->localIndex, &p);
|
||||||
|
|
||||||
|
LOG_INFO("tx sync valid");
|
||||||
|
}
|
||||||
|
|
||||||
|
void network_receive_sync_valid(struct Packet* p) {
|
||||||
|
LOG_INFO("rx sync valid");
|
||||||
|
|
||||||
|
s16 courseNum, actNum, levelNum, areaIndex;
|
||||||
|
u8 fromGlobalIndex;
|
||||||
|
packet_read(p, &courseNum, sizeof(s16));
|
||||||
|
packet_read(p, &actNum, sizeof(s16));
|
||||||
|
packet_read(p, &levelNum, sizeof(s16));
|
||||||
|
packet_read(p, &areaIndex, sizeof(s16));
|
||||||
|
packet_read(p, &fromGlobalIndex, sizeof(u8));
|
||||||
|
|
||||||
|
if (gNetworkType != NT_SERVER) {
|
||||||
|
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
|
||||||
|
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
|
||||||
|
LOG_ERROR("rx sync valid: received an improper location");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NetworkPlayer* np = (gNetworkType != NT_SERVER) ? gNetworkPlayerLocal : &gNetworkPlayers[p->localIndex];
|
||||||
|
if (np == NULL || np->localIndex == UNKNOWN_LOCAL_INDEX || !np->connected) {
|
||||||
|
LOG_ERROR("Receiving sync valid from inactive player!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
np->currLevelSyncValid = true;
|
||||||
|
np->currAreaSyncValid = true;
|
||||||
|
|
||||||
|
// inform server
|
||||||
|
if (fromGlobalIndex != gNetworkPlayerServer->globalIndex) {
|
||||||
|
LOG_INFO("informing server of sync valid");
|
||||||
|
network_send_sync_valid(gNetworkPlayerServer);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue