diff --git a/src/game/behaviors/chain_chomp.inc.c b/src/game/behaviors/chain_chomp.inc.c index e950a55a6..6e704a6e6 100644 --- a/src/game/behaviors/chain_chomp.inc.c +++ b/src/game/behaviors/chain_chomp.inc.c @@ -39,9 +39,11 @@ void bhv_chain_chomp_chain_part_update(void) { struct ChainSegment *segment = &o->parentObj->oChainChompSegments[o->oBehParams2ndByte]; // Set position relative to the pivot - o->oPosX = o->parentObj->parentObj->oPosX + segment->posX; - o->oPosY = o->parentObj->parentObj->oPosY + segment->posY; - o->oPosZ = o->parentObj->parentObj->oPosZ + segment->posZ; + if (segment) { + o->oPosX = o->parentObj->parentObj->oPosX + segment->posX; + o->oPosY = o->parentObj->parentObj->oPosY + segment->posY; + o->oPosZ = o->parentObj->parentObj->oPosZ + segment->posZ; + } } else if (o->parentObj->oChainChompReleaseStatus != CHAIN_CHOMP_NOT_RELEASED) { cur_obj_update_floor_and_walls(); cur_obj_move_standard(78); @@ -370,6 +372,11 @@ static void chain_chomp_act_move(void) { cur_obj_move_standard(78); + // if we haven't initialized chain chomp segments, do it now + if (o->oChainChompSegments == NULL) { + chain_chomp_act_uninitialized(); + } + // Segment 0 connects the pivot to the chain chomp itself o->oChainChompSegments[0].posX = o->oPosX - o->parentObj->oPosX; o->oChainChompSegments[0].posY = o->oPosY - o->parentObj->oPosY; diff --git a/src/pc/crash_handler.c b/src/pc/crash_handler.c index f39287e48..00bb69c2c 100644 --- a/src/pc/crash_handler.c +++ b/src/pc/crash_handler.c @@ -443,9 +443,8 @@ static CRASH_HANDLER_TYPE crash_handler(EXCEPTION_POINTERS *ExceptionInfo) { crash_handler_add_info_int(&pText, 315, -4 + (8 * 3), "Players", network_player_connected_count()); s32 syncObjects = 0; - for (s32 i = 0; i < MAX_SYNC_OBJECTS; i++) { - struct SyncObject* so = sync_object_get(i); - if (so && so->o != NULL) { syncObjects++; } + for (struct SyncObject* so = sync_object_get_first(); so != NULL; so = sync_object_get_next()) { + if (so->o != NULL) { syncObjects++; } } crash_handler_add_info_int(&pText, 315, -4 + (8 * 4), "SyncObj", syncObjects); diff --git a/src/pc/network/network_player.c b/src/pc/network/network_player.c index bfbe977ca..35dd59aab 100644 --- a/src/pc/network/network_player.c +++ b/src/pc/network/network_player.c @@ -238,12 +238,11 @@ u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex, u8 mode np->onRxSeqId = 0; if (localIndex != 0) { - for (s32 j = 0; j < MAX_SYNC_OBJECTS; j++) { - struct SyncObject* so = sync_object_get(j); - if (!so) { continue; } + for (struct SyncObject* so = sync_object_get_first(); so != NULL; so = sync_object_get_next()) { so->rxEventId[localIndex] = 0; } } + for (s32 j = 0; j < MAX_RX_SEQ_IDS; j++) { np->rxSeqIds[j] = 0; np->rxPacketHash[j] = 0; } packet_ordered_clear(globalIndex); @@ -301,11 +300,11 @@ u8 network_player_disconnected(u8 globalIndex) { np->currAreaSyncValid = false; gNetworkSystem->clear_id(i); network_forget_all_reliable_from(i); - for (s32 j = 0; j < MAX_SYNC_OBJECTS; j++) { - struct SyncObject* so = sync_object_get(j); - if (!so) { continue; } + + for (struct SyncObject* so = sync_object_get_first(); so != NULL; so = sync_object_get_next()) { so->rxEventId[i] = 0; } + LOG_INFO("player disconnected, local %d, global %d", i, globalIndex); // display popup @@ -368,20 +367,14 @@ void network_player_update_course_level(struct NetworkPlayer* np, s16 courseNum, if (np == gNetworkPlayerLocal) { network_send_level_area_inform(); - for (s32 i = 0; i < MAX_SYNC_OBJECTS; i++) { - struct SyncObject* so = sync_object_get(i); - if (so == NULL) { continue; } + for (struct SyncObject* so = sync_object_get_first(); so != NULL; so = sync_object_get_next()) { so->txEventId = 0; } } else { - - for (s32 i = 0; i < MAX_SYNC_OBJECTS; i++) { - struct SyncObject* so = sync_object_get(i); - if (so == NULL) { continue; } + for (struct SyncObject* so = sync_object_get_first(); so != NULL; so = sync_object_get_next()) { so->rxEventId[np->localIndex] = 0; } - } } } diff --git a/src/pc/network/packets/packet_area.c b/src/pc/network/packets/packet_area.c index 80b34b605..a1b975ac8 100644 --- a/src/pc/network/packets/packet_area.c +++ b/src/pc/network/packets/packet_area.c @@ -67,16 +67,17 @@ void network_send_area(struct NetworkPlayer* toNp) { // count respawners and write u8 respawnerCount = 0; - for (s32 i = 0; i < MAX_SYNC_OBJECTS; i++) { - struct SyncObject* so = sync_object_get(i); - if (so == NULL || so->o == NULL || so->o->behavior != smlua_override_behavior(bhvRespawner)) { continue; } - respawnerCount++; + + for (struct SyncObject* so = sync_object_get_first(); so != NULL; so = sync_object_get_next()) { + if (so->o != NULL && so->o->behavior == smlua_override_behavior(bhvRespawner)) { + respawnerCount++; + } } + packet_write(&p, &respawnerCount, sizeof(u8)); // write respawners - for (s32 i = 0; i < MAX_SYNC_OBJECTS; i++) { - struct SyncObject* so = sync_object_get(i); + for (struct SyncObject* so = sync_object_get_first(); so != NULL; so = sync_object_get_next()) { if (so == NULL || so->o == NULL || so->o->behavior != smlua_override_behavior(bhvRespawner)) { continue; } u32 behaviorToRespawn = get_id_from_behavior(so->o->oRespawnerBehaviorToRespawn); packet_write(&p, &so->o->oPosX, sizeof(f32)); @@ -94,9 +95,8 @@ void network_send_area(struct NetworkPlayer* toNp) { network_send_to(toNp->localIndex, &p); // send non-static objects - for (s32 i = RESERVED_IDS_SYNC_OBJECT_OFFSET; i < MAX_SYNC_OBJECTS; i++) { - struct SyncObject* so = sync_object_get(i); - if (so == NULL || so->o == NULL || so->o->oSyncID != (u32)i) { continue; } + for (struct SyncObject* so = sync_object_get_first_non_static(); so != NULL; so = sync_object_get_next()) { + if (so == NULL || so->o == NULL || so->o->oSyncID != so->id) { continue; } if (so->o->behavior == smlua_override_behavior(bhvRespawner)) { continue; } struct Object* spawn_objects[] = { so->o }; @@ -116,11 +116,10 @@ void network_send_area(struct NetworkPlayer* toNp) { } // send last reliable ent packet - for (s32 i = 0; i < MAX_SYNC_OBJECTS; i++) { - struct SyncObject* so = sync_object_get(i); + for (struct SyncObject* so = sync_object_get_first(); so != NULL; so = sync_object_get_next()) { if (so == NULL || so->o == NULL) { continue; } if (so->lastReliablePacketIsStale) { continue; } - struct Packet* entPacket = sync_object_get_last_reliable_packet(i); + struct Packet* entPacket = sync_object_get_last_reliable_packet(so->id); if (entPacket->error) { continue; } struct Packet p2 = { 0 }; packet_duplicate(entPacket, &p2); @@ -218,7 +217,7 @@ void network_receive_area(struct Packet* p) { struct SyncObject* so = sync_object_get(syncId); - if (so == NULL || syncId >= MAX_SYNC_OBJECTS) { + if (so == NULL) { LOG_ERROR("rx area: Sync object was NULL, Skipping respawner."); LOG_DEBUG("rx area debug: Sync Object DEBUG:\n\n \ POS X: %f\n \ diff --git a/src/pc/network/packets/packet_debug_sync.c b/src/pc/network/packets/packet_debug_sync.c index 2552e3d37..2b8d454a1 100644 --- a/src/pc/network/packets/packet_debug_sync.c +++ b/src/pc/network/packets/packet_debug_sync.c @@ -4,55 +4,51 @@ static void print_sync_object_table(void) { LOG_INFO("Sync Object Table"); - for (s32 i = 0; i < MAX_SYNC_OBJECTS; i++) { - struct SyncObject* so = sync_object_get(i); + for (struct SyncObject* so = sync_object_get_first(); so != NULL; so = sync_object_get_next()) { if (!so || !so->o) { continue; } u32 behaviorId = get_id_from_behavior(so->behavior); - LOG_INFO("%03d: %08X", i, behaviorId); + LOG_INFO("%03d: %08X", so->id, behaviorId); behaviorId = behaviorId; // suppress warning } LOG_INFO(" "); } void network_send_debug_sync(void) { - u8 objectCount = 0; - for (s32 i = 0; i < MAX_SYNC_OBJECTS; i++) { - struct SyncObject* so = sync_object_get(i); + u16 objectCount = 0; + for (struct SyncObject* so = sync_object_get_first(); so != NULL; so = sync_object_get_next()) { if (!so || !so->o) { continue; } objectCount++; } struct Packet p = { 0 }; packet_init(&p, PACKET_DEBUG_SYNC, true, PLMT_AREA); - packet_write(&p, &objectCount, sizeof(u8)); - for (s32 i = 0; i < MAX_SYNC_OBJECTS; i++) { - struct SyncObject* so = sync_object_get(i); + packet_write(&p, &objectCount, sizeof(u16)); + for (struct SyncObject* so = sync_object_get_first(); so != NULL; so = sync_object_get_next()) { if (!so || !so->o) { continue; } u32 behaviorId = get_id_from_behavior((so->behavior == NULL) ? so->behavior : so->o->behavior); - packet_write(&p, &i, sizeof(u8)); + packet_write(&p, &so->id, sizeof(u32)); packet_write(&p, &behaviorId, sizeof(u32)); } network_send(&p); } void network_receive_debug_sync(struct Packet* p) { - u8 objectCount = 0; - u32 remoteBehaviorIds[MAX_SYNC_OBJECTS] = { 0 }; + u16 objectCount = 0; + u32 remoteBehaviorIds[1024] = { 0 }; - packet_read(p, &objectCount, sizeof(u8)); + packet_read(p, &objectCount, sizeof(u16)); for (s32 i = 0; i < objectCount; i++) { - u8 j; + u32 j; u32 behaviorId; - packet_read(p, &j, sizeof(u8)); + packet_read(p, &j, sizeof(u32)); packet_read(p, &behaviorId, sizeof(u32)); remoteBehaviorIds[j] = behaviorId; } bool hasMismatch = false; - for (s32 i = 0; i < MAX_SYNC_OBJECTS; i++) { - struct SyncObject* so = sync_object_get(i); + for (struct SyncObject* so = sync_object_get_first(); so != NULL; so = sync_object_get_next()) { u32 localBehaviorId = (so && so->o) ? get_id_from_behavior(so->behavior) : 0; - u32 remoteBehaviorId = remoteBehaviorIds[i]; + u32 remoteBehaviorId = remoteBehaviorIds[so->id]; if (localBehaviorId != remoteBehaviorId) { hasMismatch = true; break; @@ -62,11 +58,10 @@ void network_receive_debug_sync(struct Packet* p) { LOG_INFO(" "); LOG_INFO("Sync Object Table Mismatch"); - for (s32 i = 0; i < MAX_SYNC_OBJECTS; i++) { - struct SyncObject* so = sync_object_get(i); + for (struct SyncObject* so = sync_object_get_first(); so != NULL; so = sync_object_get_next()) { u32 localBehaviorId = (so && so->o) ? get_id_from_behavior(so->behavior) : 0; - u32 remoteBehaviorId = remoteBehaviorIds[i]; + u32 remoteBehaviorId = remoteBehaviorIds[so->id]; if (localBehaviorId == 0 && remoteBehaviorId == 0) { continue; } - LOG_INFO("%03d: %04X %04X %s", i, localBehaviorId, remoteBehaviorId, (localBehaviorId == remoteBehaviorId) ? " " : "<<<"); + LOG_INFO("%03d: %04X %04X %s", so->id, localBehaviorId, remoteBehaviorId, (localBehaviorId == remoteBehaviorId) ? " " : "<<<"); } } diff --git a/src/pc/network/packets/packet_object.c b/src/pc/network/packets/packet_object.c index bd93f9a79..400ab1ff2 100644 --- a/src/pc/network/packets/packet_object.c +++ b/src/pc/network/packets/packet_object.c @@ -468,13 +468,12 @@ void network_update_objects(void) { } #endif - for (u32 i = 1; i < MAX_SYNC_OBJECTS; i++) { - struct SyncObject* so = sync_object_get(i); + for (struct SyncObject* so = sync_object_get_first(); so != NULL; so = sync_object_get_next()) { if (!so || !so->o) { continue; } // check for stale sync object - if (so->o->oSyncID != i) { - LOG_ERROR("sync id mismatch: %d vs %d (behavior %d)", so->o->oSyncID, i, get_id_from_behavior(so->o->behavior)); + if (so->o->oSyncID != so->id) { + LOG_ERROR("sync id mismatch: %d vs %d (behavior %d)", so->o->oSyncID, so->id, get_id_from_behavior(so->o->behavior)); sync_object_forget(so->id); continue; } diff --git a/src/pc/network/packets/packet_spawn_objects.c b/src/pc/network/packets/packet_spawn_objects.c index 942c21b5a..77d89e3ea 100644 --- a/src/pc/network/packets/packet_spawn_objects.c +++ b/src/pc/network/packets/packet_spawn_objects.c @@ -191,10 +191,6 @@ void network_receive_spawn_objects(struct Packet* p) { if (data.parentId == (u32)-1) { o->parentObj = o; } if (o->oSyncID != 0 && o->oSyncID >= RESERVED_IDS_SYNC_OBJECT_OFFSET) { - if (o->oSyncID >= MAX_SYNC_OBJECTS) { - LOG_ERROR("Invalid spawn object sync id: %u", o->oSyncID); - return; - } // check if they've allocated one of their reserved sync objects struct SyncObject* so = sync_object_get(o->oSyncID); if (so) { @@ -204,6 +200,9 @@ void network_receive_spawn_objects(struct Packet* p) { for (s32 j = 0; j < MAX_PLAYERS; j++) { so->rxEventId[j] = 0; } + } else { + LOG_ERROR("Invalid spawn object sync id: %u", o->oSyncID); + return; } } diff --git a/src/pc/network/sync_object.c b/src/pc/network/sync_object.c index e7f628feb..69e9790b0 100644 --- a/src/pc/network/sync_object.c +++ b/src/pc/network/sync_object.c @@ -12,8 +12,11 @@ #include "pc/debuglog.h" #include "pc/utils/misc.h" +#define MAX_SYNC_OBJECTS 256 // note: increasing this requires code to be rewritten + struct SyncObject sSyncObjects[MAX_SYNC_OBJECTS] = { 0 }; -u32 sNextSyncId = 0; +static u32 sNextSyncId = 0; +static u32 sIterateSyncId = 0; //////////// // system // @@ -155,6 +158,22 @@ struct SyncObject* sync_object_get(u32 syncId) { return &sSyncObjects[syncId]; } +struct SyncObject* sync_object_get_first(void) { + sIterateSyncId = 0; + return &sSyncObjects[sIterateSyncId]; +} + +struct SyncObject* sync_object_get_first_non_static(void) { + sIterateSyncId = RESERVED_IDS_SYNC_OBJECT_OFFSET; + return &sSyncObjects[sIterateSyncId]; +} + +struct SyncObject* sync_object_get_next(void) { + sIterateSyncId++; + if (sIterateSyncId >= MAX_SYNC_OBJECTS) { return NULL; } + return &sSyncObjects[sIterateSyncId]; +} + struct Object* sync_object_get_object(u32 syncId) { struct SyncObject* so = sync_object_get(syncId); return so ? so->o : NULL; diff --git a/src/pc/network/sync_object.h b/src/pc/network/sync_object.h index 2747203d8..c5469cee6 100644 --- a/src/pc/network/sync_object.h +++ b/src/pc/network/sync_object.h @@ -1,7 +1,6 @@ #ifndef SYNC_OBJECT_H #define SYNC_OBJECT_H -#define MAX_SYNC_OBJECTS 256 // note: increasing this requires code to be rewritten #define MAX_SYNC_OBJECT_FIELDS 64 #include "pc/network/packets/packet.h" @@ -54,6 +53,9 @@ void sync_object_init_field_with_size(struct Object *o, void* field, u8 size); ///////////// struct SyncObject* sync_object_get(u32 syncId); +struct SyncObject* sync_object_get_first(void); +struct SyncObject* sync_object_get_first_non_static(void); +struct SyncObject* sync_object_get_next(void); struct Object* sync_object_get_object(u32 syncId); bool sync_object_is_initialized(u32 syncId); bool sync_object_is_owned_locally(u32 syncId);