Fixed how "levelAreaMustMatch" packets are sent/processed

Instead of the server dropping them immediately, the server only drops the processing. This allows it to broadcast/send the packet to the correct client without the server processing it.

Fixed how "static" level objects were detected. The old way was error prone and would consider spawned objects to be static anyway.

Made ERROR_LOGs always show up, "disabling" logging only turns off INFO_LOGs now.
This commit is contained in:
MysterD 2021-06-13 17:47:58 -07:00
parent 7ae26b3ea0
commit 59d08a90b9
22 changed files with 122 additions and 92 deletions

View file

@ -63,7 +63,7 @@ void create_respawner(s32 model, const BehaviorScript *behToSpawn, s32 minSpawnD
respawner->oRespawnerBehaviorToRespawn = behToSpawn;
respawner->oSyncID = syncID;
if (gSyncObjects[syncID].staticLevelSpawn) {
if (syncID < RESERVED_IDS_SYNC_OBJECT_OFFSET) {
network_override_object(syncID, respawner);
o->oSyncID = 0;
o->oFlags |= OBJ_FLAG_PERSISTENT_RESPAWN; // pretty sure this is required

View file

@ -32,6 +32,7 @@
#include "spawn_object.h"
#include "spawn_sound.h"
#include "pc/network/network.h"
#include "pc/network/reservation_area.h"
#include "game/rng_position.h"
/**

View file

@ -45,6 +45,7 @@
#include "seq_ids.h"
#include "spawn_sound.h"
#include "pc/network/network.h"
#include "pc/network/reservation_area.h"
#define POS_OP_SAVE_POSITION 0
#define POS_OP_COMPUTE_VELOCITY 1

View file

@ -13,7 +13,7 @@
#ifdef DEBUG
static u8 warpToLevel = LEVEL_CCM;
static u8 warpToLevel = LEVEL_BOB;
#define SCANCODE_0 0x0B
#define SCANCODE_1 0x02

View file

@ -2,39 +2,43 @@
#include <time.h>
#include "pc/network/network.h"
#if defined(DEBUG) && !defined(DISABLE_MODULE_LOG)
static void debuglog_print_timestamp(void) {
time_t ltime = time(NULL);
char* str = asctime(localtime(&ltime));
printf("%.*s", (int)strlen(str) - 1, str);
static void _debuglog_print_timestamp(void) {
time_t ltime = time(NULL);
char* str = asctime(localtime(&ltime));
printf("%.*s", (int)strlen(str) - 1, str);
}
static void debuglog_print_network_type(void) {
printf(" [%02d] ", (gNetworkPlayerLocal != NULL) ? gNetworkPlayerLocal->globalIndex : -1);
}
static void _debuglog_print_network_type(void) {
printf(" [%02d] ", (gNetworkPlayerLocal != NULL) ? gNetworkPlayerLocal->globalIndex : -1);
}
static void debuglog_print_log_type(char* logType) {
printf("[%s] ", logType);
}
static void _debuglog_print_log_type(char* logType) {
printf("[%s] ", logType);
}
static void debuglog_print_short_filename(char* filename) {
char* last = strrchr(filename, '/');
if (last != NULL) {
printf("%s: ", last + 1);
} else {
printf("???: ");
}
static void _debuglog_print_short_filename(char* filename) {
char* last = strrchr(filename, '/');
if (last != NULL) {
printf("%s: ", last + 1);
}
static void debuglog_print_log(char* logType, char* filename) {
debuglog_print_timestamp();
debuglog_print_network_type();
debuglog_print_log_type(logType);
debuglog_print_short_filename(filename);
else {
printf("???: ");
}
}
#define LOG_INFO(...) ( debuglog_print_log("INFO ", __FILE__), printf(__VA_ARGS__), printf("\n") )
#define LOG_ERROR(...) ( debuglog_print_log("ERROR", __FILE__), printf(__VA_ARGS__), printf("\n") )
static void _debuglog_print_log(char* logType, char* filename) {
_debuglog_print_timestamp();
_debuglog_print_network_type();
_debuglog_print_log_type(logType);
_debuglog_print_short_filename(filename);
}
#if defined(DEBUG) && defined(DISABLE_MODULE_LOG)
#define LOG_INFO(...)
#define LOG_ERROR(...) ( _debuglog_print_log("ERROR", __FILE__), printf(__VA_ARGS__), printf("\n") )
#elif defined(DEBUG) && !defined(DISABLE_MODULE_LOG)
#define LOG_INFO(...) ( _debuglog_print_log("INFO ", __FILE__), printf(__VA_ARGS__), printf("\n") )
#define LOG_ERROR(...) ( _debuglog_print_log("ERROR", __FILE__), printf(__VA_ARGS__), printf("\n") )
#else
#define LOG_INFO(...)
#define LOG_ERROR(...)

View file

@ -95,11 +95,6 @@ void network_on_init_level(void) {
}
void network_on_loaded_level(void) {
// set all sync objects as staticLevelSpawn
for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
gSyncObjects[i].staticLevelSpawn = true;
}
// check for level change
struct NetworkPlayer* np = gNetworkPlayerLocal;
if (np != NULL) {
@ -174,7 +169,17 @@ void network_send(struct Packet* p) {
}
for (int i = 1; i < MAX_PLAYERS; i++) {
if (!gNetworkPlayers[i].connected) { continue; }
struct NetworkPlayer* np = &gNetworkPlayers[i];
if (!np->connected) { continue; }
// don't send a packet to a player that can't receive it
if (p->levelAreaMustMatch) {
if (p->courseNum != np->currCourseNum) { continue; }
if (p->actNum != np->currActNum) { continue; }
if (p->levelNum != np->currLevelNum) { continue; }
if (p->areaIndex != np->currAreaIndex) { continue; }
}
p->localIndex = i;
network_send_to(i, p);
}

View file

@ -45,7 +45,6 @@ struct SyncObject {
struct Object* o;
float maxSyncDistance;
bool owned;
bool staticLevelSpawn;
clock_t clockSinceUpdate;
void* behavior;
u16 txEventId;

View file

@ -3,6 +3,21 @@
#include "pc/debuglog.h"
void packet_process(struct Packet* p) {
if (p->levelAreaMustMatch) {
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
bool levelAreaMismatch =
(p->courseNum != gCurrCourseNum
|| p->actNum != gCurrActNum
|| p->levelNum != gCurrLevelNum
|| p->areaIndex != gCurrAreaIndex);
// drop packet
if (levelAreaMismatch) {
LOG_INFO("dropping level mismatch packet %d", p->packetType);
LOG_INFO(" (%d, %d, %d, %d) != (%d, %d, %d, %d)", p->courseNum, p->actNum, p->levelNum, p->areaIndex, gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex);
return;
}
}
switch (p->packetType) {
case PACKET_ACK: network_receive_ack(p); break;
case PACKET_PLAYER: network_receive_player(p); break;

View file

@ -70,6 +70,10 @@ struct Packet {
u8 orderedFromGlobalId;
u8 orderedGroupId;
u8 orderedSeqId;
u8 courseNum;
u8 actNum;
u8 levelNum;
u8 areaIndex;
u8 buffer[PACKET_LENGTH];
};

View file

@ -1,5 +1,6 @@
#include <stdio.h>
#include "../network.h"
#include "../reservation_area.h"
#include "game/interaction.h"
#include "game/level_update.h"
#include "game/area.h"
@ -54,10 +55,9 @@ void network_send_area(struct NetworkPlayer* toNp) {
network_send_to(toNp->localIndex, &p);
// send non-static objects
for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
for (int i = RESERVED_IDS_SYNC_OBJECT_OFFSET; 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 };
@ -136,7 +136,7 @@ void network_receive_area(struct Packet* p) {
struct SyncObject* so = &gSyncObjects[syncId];
LOG_INFO("rx respawner");
if (so->staticLevelSpawn) {
if (syncId < RESERVED_IDS_SYNC_OBJECT_OFFSET) {
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;

View file

@ -1,6 +1,6 @@
#include <stdio.h>
#include "../network.h"
//#define DISABLE_MODULE_LOG 1
#define DISABLE_MODULE_LOG 1
#include "pc/debuglog.h"
void network_send_area_request(struct NetworkPlayer* fromNp, struct NetworkPlayer* toNp) {

View file

@ -2,7 +2,7 @@
#include "../network.h"
#include "../reservation_area.h"
#include "level_table.h"
//#define DISABLE_MODULE_LOG 1
#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) {

View file

@ -2,7 +2,7 @@
#include "../network.h"
#include "../reservation_area.h"
#include "level_table.h"
//#define DISABLE_MODULE_LOG 1
#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) {

View file

@ -2,7 +2,7 @@
#include "../network.h"
#include "game/interaction.h"
#include "game/level_update.h"
//#define DISABLE_MODULE_LOG 1
#define DISABLE_MODULE_LOG 1
#include "pc/debuglog.h"
void network_send_level(struct NetworkPlayer* toNp, bool sendArea) {

View file

@ -1,6 +1,6 @@
#include <stdio.h>
#include "../network.h"
//#define DISABLE_MODULE_LOG 1
#define DISABLE_MODULE_LOG 1
#include "pc/debuglog.h"
void network_send_level_area_request(struct NetworkPlayer* fromNp, struct NetworkPlayer* toNp) {

View file

@ -11,7 +11,7 @@
#include "object_fields.h"
#include "behavior_table.h"
#include "model_ids.h"
#define DISABLE_MODULE_LOG 1
//#define DISABLE_MODULE_LOG 1
#include "pc/debuglog.h"
// TODO: move to common utility location
@ -88,7 +88,7 @@ static void network_send_level_macro_area(struct NetworkPlayer* destNp, u8 areaI
// check for special cases
const BehaviorScript* behavior = MacroObjectPresets[presetID].behavior;
if (behavior == bhvCoinFormation && *respawnInfo != 0) {
if ((behavior == bhvCoinFormation || behavior == bhvGoombaTripletSpawner) && *respawnInfo != 0) {
*macroSpecialCount = *macroSpecialCount + 1;
u16 offset = respawnInfo - area->macroObjects;
packet_write(&p, &offset, sizeof(u16));
@ -197,6 +197,21 @@ void network_receive_level_macro(struct Packet* p) {
}
LOG_INFO("rx macro special: coin formation");
}
else if (behavior == bhvGoombaTripletSpawner) {
o->oBehParams = *respawnInfo;
u8 goombaParams = (o->oBehParams >> 8) & 0xFF;
u8 childIndex = 0;
for (int i = 0; i < OBJECT_POOL_CAPACITY; i++) {
struct Object* o2 = &gObjectPool[i];
if (o2->parentObj != o) { continue; }
if (o2 == o) { continue; }
if (goombaParams & (1 << childIndex++)) {
obj_mark_for_deletion(o2);
}
}
LOG_INFO("rx macro special: goomba triplet %d", *respawnInfo);
}
}
}
}

View file

@ -1,6 +1,6 @@
#include <stdio.h>
#include "../network.h"
//#define DISABLE_MODULE_LOG 1
#define DISABLE_MODULE_LOG 1
#include "pc/debuglog.h"
void network_send_level_request(struct NetworkPlayer* fromNp, struct NetworkPlayer* toNp) {

View file

@ -10,7 +10,7 @@
#include "object_fields.h"
#include "behavior_table.h"
#include "model_ids.h"
#define DISABLE_MODULE_LOG 1
//#define DISABLE_MODULE_LOG 1
#include "pc/debuglog.h"
#define ERR_COULD_NOT_FIND_OBJECT ((u16)-1)
@ -133,15 +133,16 @@ void network_send_level_respawn_info(struct Object* o, u8 respawnInfoBits) {
if (np->currCourseNum != gCurrCourseNum) { continue; }
if (np->currActNum != gCurrActNum) { continue; }
if (np->currLevelNum != gCurrLevelNum) { continue; }
if (np == gNetworkPlayerLocal) { continue; }
struct Packet p2;
packet_duplicate(&p, &p2);
network_send_to(np->localIndex, &p2);
LOG_INFO("tx level respawn info to %d", np->globalIndex);
}
} else {
network_send_to(gNetworkPlayerServer->localIndex, &p);
LOG_INFO("tx level respawn info to %d", gNetworkPlayerServer->globalIndex);
}
LOG_INFO("tx level respawn info");
}
void network_receive_level_respawn_info(struct Packet* p) {

View file

@ -69,7 +69,7 @@ void network_override_object(u8 syncId, struct Object* o) {
struct SyncObject* network_init_object(struct Object *o, float maxSyncDistance) {
// HACK: an odd way to detect if this entity was spawned from a staticLevel respawner
bool wasStaticRespawner = (o->oSyncID != 0 && gSyncObjects[o->oSyncID].o == o && gSyncObjects[o->oSyncID].staticLevelSpawn);
bool wasStaticRespawner = (o->oSyncID != 0 && gSyncObjects[o->oSyncID].o == o && o->oSyncID < RESERVED_IDS_SYNC_OBJECT_OFFSET);
// generate new sync ID
network_set_sync_id(o);
@ -96,7 +96,6 @@ struct SyncObject* network_init_object(struct Object *o, float maxSyncDistance)
so->override_ownership = NULL;
so->syncDeathEvent = true;
so->randomSeed = (u16)(o->oSyncID * 7951);
so->staticLevelSpawn = wasStaticRespawner;
memset(so->extraFields, 0, sizeof(void*) * MAX_SYNC_OBJECT_FIELDS);
sLastSyncEntReliablePacket[o->oSyncID].error = true;
@ -512,7 +511,7 @@ void network_receive_object(struct Packet* p) {
void network_forget_sync_object(struct SyncObject* so) {
// invalidate last packet sent
if (so->staticLevelSpawn && so->o != NULL) {
if (so != NULL && so->o != NULL && so->o->oSyncID < RESERVED_IDS_SYNC_OBJECT_OFFSET) {
u8 syncId = so->o->oSyncID;
struct SyncObject* so2 = &gSyncObjects[syncId];
if (so == so2) {

View file

@ -56,10 +56,14 @@ void packet_init(struct Packet* packet, enum PacketType packetType, bool reliabl
// write location
if (levelAreaMustMatch) {
packet_write(packet, &gCurrCourseNum, sizeof(s16));
packet_write(packet, &gCurrActNum, sizeof(s16));
packet_write(packet, &gCurrLevelNum, sizeof(s16));
packet_write(packet, &gCurrAreaIndex, sizeof(s16));
packet_write(packet, &gCurrCourseNum, sizeof(u8));
packet_write(packet, &gCurrActNum, sizeof(u8));
packet_write(packet, &gCurrLevelNum, sizeof(u8));
packet_write(packet, &gCurrAreaIndex, sizeof(u8));
packet->courseNum = gCurrCourseNum;
packet->actNum = gCurrActNum;
packet->levelNum = gCurrLevelNum;
packet->areaIndex = gCurrAreaIndex;
}
}
@ -75,6 +79,10 @@ void packet_duplicate(struct Packet* srcPacket, struct Packet* dstPacket) {
dstPacket->sent = false;
dstPacket->orderedGroupId = srcPacket->orderedGroupId;
dstPacket->orderedSeqId = srcPacket->orderedSeqId;
dstPacket->courseNum = srcPacket->courseNum;
dstPacket->actNum = srcPacket->actNum;
dstPacket->levelNum = srcPacket->levelNum;
dstPacket->areaIndex = srcPacket->areaIndex;
memcpy(&dstPacket->buffer[0], &srcPacket->buffer[0], srcPacket->dataLength);
@ -122,27 +130,20 @@ u8 packet_initial_read(struct Packet* packet) {
// read destination
packet_read(packet, &packet->destGlobalId, sizeof(u8));
if (packet->levelAreaMustMatch) {
s16 currCourseNum, currActNum, currLevelNum, currAreaIndex;
packet_read(packet, &currCourseNum, sizeof(s16));
packet_read(packet, &currActNum, sizeof(s16));
packet_read(packet, &currLevelNum, sizeof(s16));
packet_read(packet, &currAreaIndex, sizeof(s16));
bool levelAreaMismatch =
(currCourseNum != gCurrCourseNum
|| currActNum != gCurrActNum
|| currLevelNum != gCurrLevelNum
|| currAreaIndex != gCurrAreaIndex);
// drop packet
if (levelAreaMismatch) { return FALSE; }
}
// read ordered packet information
if (packetIsOrdered) {
packet_read(packet, &packet->orderedFromGlobalId, sizeof(u8));
packet_read(packet, &packet->orderedGroupId, sizeof(u8));
packet_read(packet, &packet->orderedSeqId, sizeof(u8));
}
// read location
if (packet->levelAreaMustMatch) {
packet_read(packet, &packet->courseNum, sizeof(u8));
packet_read(packet, &packet->actNum, sizeof(u8));
packet_read(packet, &packet->levelNum, sizeof(u8));
packet_read(packet, &packet->areaIndex, sizeof(u8));
}
// don't drop packet
return TRUE;

View file

@ -47,16 +47,10 @@ void network_send_spawn_objects(struct Object* objects[], u32 models[], u8 objec
void network_send_spawn_objects_to(u8 sendToLocalIndex, struct Object* objects[], u32 models[], u8 objectCount) {
assert(objectCount < MAX_SPAWN_OBJECTS_PER_PACKET);
if (sendToLocalIndex == gNetworkPlayerLocal->localIndex) { return; }
struct Packet p;
packet_init(&p, PACKET_SPAWN_OBJECTS, true, false);
// level location
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
packet_write(&p, &gCurrCourseNum, sizeof(s16));
packet_write(&p, &gCurrActNum, sizeof(s16));
packet_write(&p, &gCurrLevelNum, sizeof(s16));
packet_write(&p, &gCurrAreaIndex, sizeof(s16));
packet_init(&p, PACKET_SPAWN_OBJECTS, true, true);
// objects
packet_write(&p, &objectCount, sizeof(u8));
@ -78,24 +72,15 @@ void network_send_spawn_objects_to(u8 sendToLocalIndex, struct Object* objects[]
if (sendToLocalIndex == PACKET_DESTINATION_BROADCAST) {
network_send(&p);
LOG_INFO("tx spawn objects (BROADCAST)");
} else {
network_send_to(sendToLocalIndex, &p);
LOG_INFO("tx spawn objects to %d", gNetworkPlayers[sendToLocalIndex].globalIndex);
}
}
void network_receive_spawn_objects(struct Packet* p) {
// 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, gCurrAreaIndex;
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
LOG_ERROR("received an improper location");
return;
}
LOG_INFO("rx spawn objects");
u8 objectCount = 0;
packet_read(p, &objectCount, sizeof(u8));

View file

@ -1,6 +1,6 @@
#include <stdio.h>
#include "../network.h"
//#define DISABLE_MODULE_LOG 1
#define DISABLE_MODULE_LOG 1
#include "pc/debuglog.h"
void network_send_sync_valid(struct NetworkPlayer* toNp) {