From c8a45235cacff2ccb00dbbeecd59a12534283b19 Mon Sep 17 00:00:00 2001 From: MysterD Date: Tue, 13 Oct 2020 21:44:27 -0700 Subject: [PATCH] Removed two-player hacks from cannon and object packets Increased error checking of get_behavior_from_id Made failure logging for packet_object a lot better Changed debug logging to show global index instead of "Server/Client" Changed debug keyboard binds to support more keyboard types Made SyncObject's rxEventId de-duplication per-player instead of one-player Removed sizeof(enum) from packet_read/packet_write --- data/behavior_table.c | 3 + include/object_fields.h | 8 +- src/game/behaviors/cannon.inc.c | 94 ++++++++++--------- src/game/behaviors/koopa_shell.inc.c | 4 +- src/game/interaction.c | 2 + src/pc/controller/controller_keyboard_debug.c | 2 +- src/pc/debuglog.h | 2 +- src/pc/network/network.h | 2 +- src/pc/network/network_player.c | 2 + src/pc/network/packets/packet_collect_coin.c | 8 +- src/pc/network/packets/packet_collect_item.c | 4 +- src/pc/network/packets/packet_collect_star.c | 4 +- src/pc/network/packets/packet_kick.c | 4 +- src/pc/network/packets/packet_object.c | 64 ++++++++----- src/pc/network/packets/packet_spawn_objects.c | 4 +- 15 files changed, 117 insertions(+), 90 deletions(-) diff --git a/data/behavior_table.c b/data/behavior_table.c index a0b65e5d..fbe918cd 100644 --- a/data/behavior_table.c +++ b/data/behavior_table.c @@ -524,5 +524,8 @@ enum BehaviorId get_id_from_behavior(const BehaviorScript* behavior) { } const BehaviorScript* get_behavior_from_id(enum BehaviorId id) { + if (id < 0 || id >= id_bhv_max_count) { + return NULL; + } return gBehaviorTable[id]; } diff --git a/include/object_fields.h b/include/object_fields.h index 5a2b668e..a6d771ce 100644 --- a/include/object_fields.h +++ b/include/object_fields.h @@ -350,10 +350,10 @@ #define /*0x1AC*/ oTripletButterflyScalePhase OBJECT_FIELD_S32(0x49) /* Cannon */ -#define /*0x0F4*/ oCannonUnkF4 OBJECT_FIELD_S32(0x1B) -#define /*0x0F8*/ oCannonUnkF8 OBJECT_FIELD_S32(0x1C) -#define /*0x10C*/ oCannonUnk10C OBJECT_FIELD_S32(0x21) -#define /*0x110*/ oCannonIsLocal OBJECT_FIELD_S32(0x22) +#define /*0x0F4*/ oCannonUnkF4 OBJECT_FIELD_S32(0x1B) +#define /*0x0F8*/ oCannonUnkF8 OBJECT_FIELD_S32(0x1C) +#define /*0x10C*/ oCannonUnk10C OBJECT_FIELD_S32(0x21) +#define /*0x110*/ oCannonPlayerIndex OBJECT_FIELD_S32(0x22) /* Cap */ #define /*0x0F4*/ oCapUnkF4 OBJECT_FIELD_S32(0x1B) diff --git a/src/game/behaviors/cannon.inc.c b/src/game/behaviors/cannon.inc.c index 90982142..fccfaec3 100644 --- a/src/game/behaviors/cannon.inc.c +++ b/src/game/behaviors/cannon.inc.c @@ -29,7 +29,7 @@ void opened_cannon_act_0(void) { o->oAction = 4; o->oCannonUnk10C = 1; o->oCannonUnkF8 = 1; - o->oCannonIsLocal = TRUE; + o->oCannonPlayerIndex = 0; network_send_object(o); } else { o->oInteractStatus = 0; @@ -53,10 +53,12 @@ void opened_cannon_act_4(void) { o->oPosZ += (f32)((o->oTimer / 2 & 1) - 0.5) * 4; o->oAction = 6; } - if (!o->oCannonIsLocal) { - // two-player hack - gMarioStates[1].marioObj->oMarioCannonObjectYaw = o->oMoveAngleYaw; - gMarioStates[1].marioObj->oMarioCannonInputYaw = 0; + if (o->oCannonPlayerIndex != 0) { + struct MarioState* controlledBy = &gMarioStates[o->oCannonPlayerIndex]; + if (controlledBy->marioObj != NULL) { + controlledBy->marioObj->oMarioCannonObjectYaw = o->oMoveAngleYaw; + controlledBy->marioObj->oMarioCannonInputYaw = 0; + } } } @@ -74,16 +76,12 @@ void opened_cannon_act_6(void) { o->oCannonUnkF4 += 0x400; } else if (o->oTimer < 26) { } else { - if (o->oCannonIsLocal) { - gMarioStates[0].marioObj->oMarioCannonObjectYaw = o->oMoveAngleYaw; - gMarioStates[0].marioObj->oMarioCannonInputYaw = 0; - gMarioStates[0].faceAngle[0] = 8192; - } else { - // two-player hack - gMarioStates[1].marioObj->oMarioCannonObjectYaw = o->oMoveAngleYaw; - gMarioStates[1].marioObj->oMarioCannonInputYaw = 0; - gMarioStates[1].faceAngle[0] = 8192; + struct MarioState* controlledBy = &gMarioStates[o->oCannonPlayerIndex]; + if (controlledBy->marioObj != NULL) { + controlledBy->marioObj->oMarioCannonObjectYaw = o->oMoveAngleYaw; + controlledBy->marioObj->oMarioCannonInputYaw = 0; } + controlledBy->faceAngle[0] = 8192; o->oCannonUnkF4 = 0; o->oAction = 5; @@ -109,16 +107,18 @@ void opened_cannon_act_5(void) { void opened_cannon_act_1(void) { UNUSED s32 unused; - if (o->oCannonIsLocal) { // two-player hack + if (o->oCannonPlayerIndex == 0) { cur_obj_become_intangible(); cur_obj_disable_rendering(); } else { - struct MarioState* marioState = &gMarioStates[1]; // two-player hack - o->oMoveAnglePitch = 14563 + marioState->faceAngle[0] * -0.5f; - o->oMoveAngleYaw = marioState->marioObj->oMarioCannonObjectYaw + marioState->marioObj->oMarioCannonInputYaw; + struct MarioState* controlledBy = &gMarioStates[o->oCannonPlayerIndex]; + o->oMoveAnglePitch = 14563 + controlledBy->faceAngle[0] * -0.5f; + if (controlledBy->marioObj != NULL) { + o->oMoveAngleYaw = controlledBy->marioObj->oMarioCannonObjectYaw + controlledBy->marioObj->oMarioCannonInputYaw; + } } o->oCannonUnk10C = 0; - if (o->oCannonIsLocal) { + if (o->oCannonPlayerIndex == 0) { gMarioShotFromCannon = 1; } } @@ -131,7 +131,6 @@ void opened_cannon_act_3(void) { UNUSED s32 unused; if (o->oTimer > 3) { o->oAction = 0; - o->oCannonIsLocal = FALSE; if (o->heldByPlayerIndex == 0) { network_send_object(o); } } } @@ -144,39 +143,37 @@ u8 unused0EA1FC[] = { 2, 0, 0, 0, 0, 0, 0, 0, 63, 128, 0, 0, 2, 0, 0, 0 63, 128, 0, 0, 2, 0, 0, 0, 65, 160, 0, 0, 63, 128, 0, 0, 2, 0, 0, 0, 65, 160, 0, 0, 63, 128, 0, 0, 8, 0, 0, 0, 65, 32, 0, 0, 63, 128, 0, 0 }; -u8 cannon_ignore_remote_updates(void) { - // two-player hack - return ((gNetworkType == NT_SERVER) && o->oCannonIsLocal); -} - static void cannon_on_received_post(u8 fromLocalIndex) { // check if we're on in the cannon too struct MarioState* m = &gMarioStates[0]; - if (m->action != ACT_IN_CANNON) { return; } - if (m->interactObj != o) { return; } - // two-player hack - if (gNetworkType == NT_SERVER) { return; } + u8 shouldEject = (m->action == ACT_IN_CANNON) + && (m->interactObj == o) + && gNetworkPlayers[fromLocalIndex].globalIndex < gNetworkPlayerLocal->globalIndex; - // eject the player by shooting out of the cannon weakly - m->forwardVel = 10.0f * coss(m->faceAngle[0]); - m->vel[1] = 10.0f * sins(m->faceAngle[0]); - m->pos[0] += 120.0f * coss(m->faceAngle[0]) * sins(m->faceAngle[1]); - m->pos[1] += 120.0f * sins(m->faceAngle[0]); - m->pos[2] += 120.0f * coss(m->faceAngle[0]) * coss(m->faceAngle[1]); - set_mario_action(m, ACT_SHOT_FROM_CANNON, 0); + if (shouldEject) { + // eject the player by shooting out of the cannon weakly + m->forwardVel = 10.0f * coss(m->faceAngle[0]); + m->vel[1] = 10.0f * sins(m->faceAngle[0]); + m->pos[0] += 120.0f * coss(m->faceAngle[0]) * sins(m->faceAngle[1]); + m->pos[1] += 120.0f * sins(m->faceAngle[0]); + m->pos[2] += 120.0f * coss(m->faceAngle[0]) * coss(m->faceAngle[1]); + set_mario_action(m, ACT_SHOT_FROM_CANNON, 0); - // reset things that got messed up - m->marioObj->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE; - reset_camera(gCamera); - o->oCannonIsLocal = FALSE; - cur_obj_become_tangible(); - cur_obj_enable_rendering(); + // reset things that got messed up + m->marioObj->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE; + reset_camera(gCamera); + o->oCannonPlayerIndex = fromLocalIndex; + cur_obj_become_tangible(); + cur_obj_enable_rendering(); + } else { + o->oCannonPlayerIndex = fromLocalIndex; + } } static void bhv_cannon_base_sanity_check(void) { // figure out if it's still in use u8 inUse = FALSE; - if (o->oCannonIsLocal) { + if (o->oCannonPlayerIndex == 0) { inUse = (gMarioStates[0].action == ACT_IN_CANNON && gMarioStates[0].interactObj == o); } else { for (int i = 0; i < MAX_PLAYERS; i++) { @@ -208,11 +205,18 @@ static void bhv_cannon_base_sanity_check(void) { } } +void bhv_cannon_override_ownership(u8* shouldOverride, u8* shouldOwn) { + if ((o->oAction != 0) && (o->oCannonPlayerIndex == 0)) { + *shouldOverride = TRUE; + *shouldOwn = TRUE; + } +} + void bhv_cannon_base_loop(void) { if (!network_sync_object_initialized(o)) { struct SyncObject* so = network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS); - so->ignore_if_true = cannon_ignore_remote_updates; so->on_received_post = cannon_on_received_post; + so->override_ownership = bhv_cannon_override_ownership; network_init_object_field(o, &o->oAction); network_init_object_field(o, &o->oPrevAction); network_init_object_field(o, &o->oTimer); @@ -227,7 +231,7 @@ void bhv_cannon_base_loop(void) { bhv_cannon_base_sanity_check(); - if (o->oAction != 0 && !o->oCannonIsLocal) { + if ((o->oAction != 0) && (o->oCannonPlayerIndex != 0)) { cur_obj_push_mario_away_from_cylinder(220, 300); } diff --git a/src/game/behaviors/koopa_shell.inc.c b/src/game/behaviors/koopa_shell.inc.c index 2ca3c3fe..ca0e5d71 100644 --- a/src/game/behaviors/koopa_shell.inc.c +++ b/src/game/behaviors/koopa_shell.inc.c @@ -59,6 +59,7 @@ void bhv_koopa_shell_loop(void) { struct Surface *sp34; obj_set_hitbox(o, &sKoopaShellHitbox); cur_obj_scale(1.0f); + struct MarioState* marioState = nearest_mario_state_to_object(o); struct Object* player = NULL; switch (o->oAction) { case 0: @@ -66,8 +67,7 @@ void bhv_koopa_shell_loop(void) { cur_obj_if_hit_wall_bounce_away(); if (o->oInteractStatus & INT_STATUS_INTERACTED) { o->oAction++; - player = nearest_player_to_object(o); - o->heldByPlayerIndex = (player == gMarioObject) ? 0 : 1; + o->heldByPlayerIndex = marioState->playerIndex; } o->oFaceAngleYaw += 0x1000; cur_obj_move_standard(-20); diff --git a/src/game/interaction.c b/src/game/interaction.c index 67c8c2c6..083a2ae6 100644 --- a/src/game/interaction.c +++ b/src/game/interaction.c @@ -1188,10 +1188,12 @@ u32 interact_door(struct MarioState *m, UNUSED u32 interactType, struct Object * u32 interact_cannon_base(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { if (o->oAction != 0) { return FALSE; } + if (m->playerIndex != 0) { return FALSE; } if (m->action != ACT_IN_CANNON) { mario_stop_riding_and_holding(m); o->oInteractStatus = INT_STATUS_INTERACTED; + o->oCannonPlayerIndex = 0; m->interactObj = o; m->usedObj = o; return set_mario_action(m, ACT_IN_CANNON, 0); diff --git a/src/pc/controller/controller_keyboard_debug.c b/src/pc/controller/controller_keyboard_debug.c index 3484b46e..c9b5790a 100644 --- a/src/pc/controller/controller_keyboard_debug.c +++ b/src/pc/controller/controller_keyboard_debug.c @@ -117,7 +117,7 @@ static void debug_suicide(void) { void debug_keyboard_on_key_down(int scancode) { scancode = scancode; - switch (scancode) { + switch (scancode & 0xFF) { case SCANCODE_3: debug_breakpoint_here(); break; #ifdef DEVELOPMENT case SCANCODE_6: debug_warp_level(warpToLevel); break; diff --git a/src/pc/debuglog.h b/src/pc/debuglog.h index 1801c6fa..c38a38eb 100644 --- a/src/pc/debuglog.h +++ b/src/pc/debuglog.h @@ -10,7 +10,7 @@ } static void debuglog_print_network_type(void) { - printf(" [%s] ", NETWORKTYPESTR); + printf(" [%02d] ", (gNetworkPlayerLocal != NULL) ? gNetworkPlayerLocal->globalIndex : -1); } static void debuglog_print_log_type(char* logType) { diff --git a/src/pc/network/network.h b/src/pc/network/network.h index 0b5fc474..fc82ca1c 100644 --- a/src/pc/network/network.h +++ b/src/pc/network/network.h @@ -49,7 +49,7 @@ struct SyncObject { clock_t clockSinceUpdate; void* behavior; u16 txEventId; - u16 rxEventId; + u16 rxEventId[MAX_PLAYERS]; u16 randomSeed; u8 extraFieldCount; bool fullObjectSync; diff --git a/src/pc/network/network_player.c b/src/pc/network/network_player.c index 1d2b197d..7c85fdbb 100644 --- a/src/pc/network/network_player.c +++ b/src/pc/network/network_player.c @@ -103,6 +103,7 @@ u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex) { np->type = type; np->lastReceived = clock(); gNetworkSystem->save_id(i); + for (int j = 0; j < MAX_SYNC_OBJECTS; j++) { gSyncObjects[j].rxEventId[i] = 0; } if (type == NPT_SERVER) { gNetworkPlayerServer = np; } else { chat_add_message("player connected", CMT_SYSTEM); } LOG_INFO("player connected, local %d, global %d", i, np->globalIndex); @@ -139,6 +140,7 @@ u8 network_player_disconnected(u8 globalIndex) { if (gNetworkType == NT_SERVER) { network_send_leaving(np->globalIndex); } np->connected = false; gNetworkSystem->clear_id(i); + for (int j = 0; j < MAX_SYNC_OBJECTS; j++) { gSyncObjects[j].rxEventId[i] = 0; } LOG_INFO("player disconnected, local %d, global %d", i, globalIndex); chat_add_message("player disconnected", CMT_SYSTEM); return i; diff --git a/src/pc/network/packets/packet_collect_coin.c b/src/pc/network/packets/packet_collect_coin.c index a80cd216..aeb6dae6 100644 --- a/src/pc/network/packets/packet_collect_coin.c +++ b/src/pc/network/packets/packet_collect_coin.c @@ -48,7 +48,7 @@ void network_send_collect_coin(struct Object* o) { struct Packet p; packet_init(&p, PACKET_COLLECT_COIN, true, true); - packet_write(&p, &behaviorId, sizeof(enum BehaviorId)); + packet_write(&p, &behaviorId, sizeof(u16)); packet_write(&p, &o->oPosX, sizeof(f32) * 3); packet_write(&p, &gMarioStates[0].numCoins, sizeof(s16)); packet_write(&p, &o->oDamageOrCoinValue, sizeof(s32)); @@ -62,7 +62,7 @@ void network_receive_collect_coin(struct Packet* p) { s16 numCoins = 0; s32 coinValue = 0; - packet_read(p, &behaviorId, sizeof(enum BehaviorId)); + packet_read(p, &behaviorId, sizeof(u16)); packet_read(p, &pos, sizeof(f32) * 3); packet_read(p, &numCoins, sizeof(s16)); packet_read(p, &coinValue, sizeof(s32)); @@ -88,7 +88,7 @@ void network_receive_collect_coin(struct Packet* p) { if (COURSE_IS_MAIN_COURSE(gCurrCourseNum) && gMarioStates[0].numCoins - coin->oDamageOrCoinValue < 100 && gMarioStates[0].numCoins >= 100) { - bhv_spawn_star_no_level_exit(gMarioStates[1].marioObj, 6, FALSE); + bhv_spawn_star_no_level_exit(gMarioStates[p->localIndex].marioObj, 6, FALSE); } return; @@ -102,6 +102,6 @@ SANITY_CHECK_COINS:; if (COURSE_IS_MAIN_COURSE(gCurrCourseNum) && oldCoinCount < 100 && gMarioStates[0].numCoins >= 100) { - bhv_spawn_star_no_level_exit(gMarioStates[1].marioObj, 6, FALSE); + bhv_spawn_star_no_level_exit(gMarioStates[p->localIndex].marioObj, 6, FALSE); } } diff --git a/src/pc/network/packets/packet_collect_item.c b/src/pc/network/packets/packet_collect_item.c index bd81d972..d5a07558 100644 --- a/src/pc/network/packets/packet_collect_item.c +++ b/src/pc/network/packets/packet_collect_item.c @@ -45,7 +45,7 @@ void network_send_collect_item(struct Object* o) { struct Packet p; packet_init(&p, PACKET_COLLECT_ITEM, true, true); - packet_write(&p, &behaviorId, sizeof(enum BehaviorId)); + packet_write(&p, &behaviorId, sizeof(u16)); packet_write(&p, &o->oPosX, sizeof(f32) * 3); network_send(&p); @@ -55,7 +55,7 @@ void network_receive_collect_item(struct Packet* p) { enum BehaviorId behaviorId; f32 pos[3] = { 0 }; - packet_read(p, &behaviorId, sizeof(enum BehaviorId)); + packet_read(p, &behaviorId, sizeof(u16)); packet_read(p, &pos, sizeof(f32) * 3); const void* behavior = get_behavior_from_id(behaviorId); diff --git a/src/pc/network/packets/packet_collect_star.c b/src/pc/network/packets/packet_collect_star.c index 19ce155c..78bd656c 100644 --- a/src/pc/network/packets/packet_collect_star.c +++ b/src/pc/network/packets/packet_collect_star.c @@ -52,7 +52,7 @@ void network_send_collect_star(struct Object* o, s16 coinScore, s16 starIndex) { packet_write(&p, &gCurrSaveFileNum, sizeof(s16)); packet_write(&p, &gCurrCourseNum, sizeof(s16)); packet_write(&p, &o->oPosX, sizeof(f32) * 3); - packet_write(&p, &behaviorId, sizeof(enum BehaviorId)); + packet_write(&p, &behaviorId, sizeof(u16)); packet_write(&p, &coinScore, sizeof(s16)); packet_write(&p, &starIndex, sizeof(s16)); @@ -69,7 +69,7 @@ void network_receive_collect_star(struct Packet* p) { packet_read(p, &gCurrSaveFileNum, sizeof(s16)); packet_read(p, &gCurrCourseNum, sizeof(s16)); packet_read(p, &pos, sizeof(f32) * 3); - packet_read(p, &behaviorId, sizeof(enum BehaviorId)); + packet_read(p, &behaviorId, sizeof(u16)); packet_read(p, &coinScore, sizeof(s16)); packet_read(p, &starIndex, sizeof(s16)); diff --git a/src/pc/network/packets/packet_kick.c b/src/pc/network/packets/packet_kick.c index 682c586e..1593110b 100644 --- a/src/pc/network/packets/packet_kick.c +++ b/src/pc/network/packets/packet_kick.c @@ -6,7 +6,7 @@ void network_send_kick(enum KickReasonType kickReason) { struct Packet p; packet_init(&p, PACKET_KICK, false, false); - packet_write(&p, &kickReason, sizeof(enum KickReasonType)); + packet_write(&p, &kickReason, sizeof(u8)); network_send_to(0, &p); } @@ -22,7 +22,7 @@ void network_receive_kick(struct Packet* p) { } enum KickReasonType kickReason; - packet_read(p, &kickReason, sizeof(enum KickReasonType)); + packet_read(p, &kickReason, sizeof(u8)); switch (kickReason) { case EKT_FULL_PARTY: custom_menu_error("The party is full."); break; default: custom_menu_error("Host has closed the connection."); break; diff --git a/src/pc/network/packets/packet_object.c b/src/pc/network/packets/packet_object.c index 0e981859..579d4bf3 100644 --- a/src/pc/network/packets/packet_object.c +++ b/src/pc/network/packets/packet_object.c @@ -8,6 +8,7 @@ #include "src/game/memory.h" #include "src/game/object_helpers.h" #include "src/game/obj_behaviors.h" +#include "pc/debuglog.h" static u8 nextSyncID = 1; struct SyncObject gSyncObjects[MAX_SYNC_OBJECTS] = { 0 }; @@ -42,7 +43,10 @@ static bool should_own_object(struct SyncObject* so) { if (gMarioStates[i].heldByObj == so->o) { return false; } } if (so->o->oHeldState == HELD_HELD && so->o->heldByPlayerIndex == 0) { return true; } - if (player_distance(&gMarioStates[0], so->o) > player_distance(&gMarioStates[1], so->o)) { return false; } + for (int i = 0; i < MAX_PLAYERS; i++) { + if (!is_player_active(&gMarioStates[i])) { continue; } + if (player_distance(&gMarioStates[0], so->o) > player_distance(&gMarioStates[i], so->o)) { return false; } + } if (so->o->oHeldState == HELD_HELD && so->o->heldByPlayerIndex != 0) { return false; } return true; } @@ -60,7 +64,9 @@ struct SyncObject* network_init_object(struct Object *o, float maxSyncDistance) so->clockSinceUpdate = clock(); so->extraFieldCount = 0; so->behavior = (BehaviorScript*)o->behavior; - so->rxEventId = 0; + for (int i = 0; i < MAX_PLAYERS; i++) { + so->rxEventId[i] = 0; + } so->txEventId = 0; so->fullObjectSync = false; so->hasStandardFields = (maxSyncDistance >= 0); @@ -141,10 +147,11 @@ static void packet_write_object_header(struct Packet* p, struct Object* o) { struct SyncObject* so = &gSyncObjects[o->oSyncID]; enum BehaviorId behaviorId = get_id_from_behavior(o->behavior); + packet_write(p, &gNetworkPlayerLocal->globalIndex, sizeof(u8)); packet_write(p, &o->oSyncID, sizeof(u32)); packet_write(p, &so->txEventId, sizeof(u16)); packet_write(p, &so->randomSeed, sizeof(u16)); - packet_write(p, &behaviorId, sizeof(enum BehaviorId)); + packet_write(p, &behaviorId, sizeof(u16)); } static bool allowable_behavior_change(struct SyncObject* so, BehaviorScript* behavior) { @@ -162,19 +169,25 @@ static bool allowable_behavior_change(struct SyncObject* so, BehaviorScript* beh return true; } -static struct SyncObject* packet_read_object_header(struct Packet* p) { +static struct SyncObject* packet_read_object_header(struct Packet* p, u8* fromLocalIndex) { + // figure out where the packet came from + u8 fromGlobalIndex = 0; + packet_read(p, &fromGlobalIndex, sizeof(u8)); + struct NetworkPlayer* np = network_player_from_global_index(fromGlobalIndex); + *fromLocalIndex = (np != NULL) ? np->localIndex : p->localIndex; + // get sync ID, sanity check u32 syncId = 0; packet_read(p, &syncId, sizeof(u32)); if (syncId == 0 || syncId >= MAX_SYNC_OBJECTS) { - printf("%s invalid SyncID %d!\n", NETWORKTYPESTR, syncId); + LOG_ERROR("invalid SyncID: %d", syncId); return NULL; } // extract object, sanity check struct Object* o = gSyncObjects[syncId].o; if (o == NULL) { - printf("%s invalid SyncObject!\n", NETWORKTYPESTR); + LOG_ERROR("invalid SyncObject for %d", syncId); return NULL; } @@ -193,20 +206,23 @@ static struct SyncObject* packet_read_object_header(struct Packet* p) { // make sure this is the newest event possible u16 eventId = 0; packet_read(p, &eventId, sizeof(u16)); - if (so->rxEventId > eventId && (u16)abs(eventId - so->rxEventId) < USHRT_MAX / 2) { + if (so->rxEventId[*fromLocalIndex] > eventId && (u16)abs(eventId - so->rxEventId[*fromLocalIndex]) < USHRT_MAX / 2) { return NULL; } - so->rxEventId = eventId; + so->rxEventId[*fromLocalIndex] = eventId; // update the random seed packet_read(p, &so->randomSeed, sizeof(u16)); // make sure the behaviors match enum BehaviorId behaviorId; - packet_read(p, &behaviorId, sizeof(enum BehaviorId)); + packet_read(p, &behaviorId, sizeof(u16)); BehaviorScript* behavior = (BehaviorScript*)get_behavior_from_id(behaviorId); - if (o->behavior != behavior && !allowable_behavior_change(so, behavior)) { - printf("network_receive_object() behavior mismatch!\n"); + if (behavior == NULL) { + LOG_ERROR("unable to find behavior %04X for id %d", behaviorId, syncId); + return NULL; + } if (o->behavior != behavior && !allowable_behavior_change(so, behavior)) { + LOG_ERROR("behavior mismatch for %d: %04X vs %04X", syncId, get_id_from_behavior(o->behavior), get_id_from_behavior(behavior)); network_forget_sync_object(so); return NULL; } @@ -337,13 +353,13 @@ void network_send_object(struct Object* o) { if (!network_sync_object_initialized(o)) { return; } struct SyncObject* so = &gSyncObjects[o->oSyncID]; if (so == NULL) { return; } - if (o->behavior != so->behavior && !allowable_behavior_change(so, so->behavior)) { - printf("network_send_object() BEHAVIOR MISMATCH!\n"); + if (o != so->o) { + LOG_ERROR("object mismatch for %d", o->oSyncID); network_forget_sync_object(so); return; } - if (o != so->o) { - printf("network_send_object() OBJECT MISMATCH!\n"); + if (o->behavior != so->behavior && !allowable_behavior_change(so, so->behavior)) { + LOG_ERROR("behavior mismatch for %d: %04X vs %04X", o->oSyncID, get_id_from_behavior(o->behavior), get_id_from_behavior(so->behavior)); network_forget_sync_object(so); return; } @@ -357,14 +373,13 @@ void network_send_object_reliability(struct Object* o, bool reliable) { if (!network_sync_object_initialized(o)) { return; } struct SyncObject* so = &gSyncObjects[o->oSyncID]; if (so == NULL) { return; } - - if (o->behavior != so->behavior && !allowable_behavior_change(so, so->behavior)) { - printf("network_send_object() BEHAVIOR MISMATCH!\n"); + if (o != so->o) { + LOG_ERROR("object mismatch for %d", o->oSyncID); network_forget_sync_object(so); return; } - if (o != so->o) { - printf("network_send_object() OBJECT MISMATCH!\n"); + if (o->behavior != so->behavior && !allowable_behavior_change(so, so->behavior)) { + LOG_ERROR("behavior mismatch for %d: %04X vs %04X", o->oSyncID, get_id_from_behavior(o->behavior), get_id_from_behavior(so->behavior)); network_forget_sync_object(so); return; } @@ -393,7 +408,8 @@ void network_send_object_reliability(struct Object* o, bool reliable) { void network_receive_object(struct Packet* p) { // read the header and sanity check the packet - struct SyncObject* so = packet_read_object_header(p); + u8 fromLocalIndex = 0; + struct SyncObject* so = packet_read_object_header(p, &fromLocalIndex); if (so == NULL) { return; } struct Object* o = so->o; if (!network_sync_object_initialized(o)) { return; } @@ -412,7 +428,7 @@ void network_receive_object(struct Packet* p) { extern struct Object* gCurrentObject; struct Object* tmp = gCurrentObject; gCurrentObject = so->o; - (*so->on_received_pre)(p->localIndex); + (*so->on_received_pre)(fromLocalIndex); gCurrentObject = tmp; } @@ -432,7 +448,7 @@ void network_receive_object(struct Packet* p) { extern struct Object* gCurrentObject; struct Object* tmp = gCurrentObject; gCurrentObject = so->o; - (*so->on_received_post)(p->localIndex); + (*so->on_received_post)(fromLocalIndex); gCurrentObject = tmp; } @@ -464,7 +480,7 @@ void network_update_objects(void) { // check for stale sync object if (so->o->oSyncID != i) { - printf("ERROR! Sync ID mismatch!\n"); + LOG_ERROR("sync id mismatch: %d vs %d", so->o->oSyncID, i); network_forget_sync_object(so); continue; } diff --git a/src/pc/network/packets/packet_spawn_objects.c b/src/pc/network/packets/packet_spawn_objects.c index fd5ee4dd..05c18b2c 100644 --- a/src/pc/network/packets/packet_spawn_objects.c +++ b/src/pc/network/packets/packet_spawn_objects.c @@ -57,7 +57,7 @@ void network_send_spawn_objects(struct Object* objects[], u32 models[], u8 objec enum BehaviorId behaviorId = get_id_from_behavior(o->behavior); packet_write(&p, &parentId, sizeof(u8)); packet_write(&p, &model, sizeof(u32)); - packet_write(&p, &behaviorId, sizeof(enum BehaviorId)); + packet_write(&p, &behaviorId, sizeof(u16)); packet_write(&p, &o->activeFlags, sizeof(s16)); packet_write(&p, o->rawData.asU32, sizeof(s32) * 80); packet_write(&p, &o->header.gfx.scale[0], sizeof(f32)); @@ -99,7 +99,7 @@ void network_receive_spawn_objects(struct Packet* p) { Vec3f scale = { 0 }; packet_read(p, &data.parentId, sizeof(u8)); packet_read(p, &data.model, sizeof(u32)); - packet_read(p, &data.behaviorId, sizeof(enum BehaviorId)); + packet_read(p, &data.behaviorId, sizeof(u16)); packet_read(p, &data.activeFlags, sizeof(s16)); packet_read(p, &data.rawData, sizeof(s32) * 80); packet_read(p, &scale[0], sizeof(f32));