From 0b3a97d405080efb9d758393287758a3a372421e Mon Sep 17 00:00:00 2001 From: MysterD Date: Wed, 9 Jun 2021 22:35:34 -0700 Subject: [PATCH] Improvements to late-join synchronization Removed (slightly) old coin and static ent removal system Resynchronized respawners Added packet for macro deletions better than previous system since the entities don't need a sync id and we can synchronize deletion station across areas allows the synchronization of odd entities like lines of coins Added packet for spawn info deletions Split packet_location_request into multiple files --- build-windows-visual-studio/sm64ex.vcxproj | 6 + data/behavior_table.c | 17 - developer/network.sh | 8 +- include/behavior_table.h | 1 - include/macro_presets.h | 369 +---------------- include/object_fields.h | 1 - src/game/behaviors/bobomb.inc.c | 10 +- src/game/behaviors/breakable_box_small.inc.c | 4 +- src/game/behaviors/corkbox.inc.c | 17 +- src/game/behaviors/snowman.inc.c | 2 +- src/game/behaviors/yoshi.inc.c | 2 +- src/game/interaction.c | 3 - src/game/macro_presets.c | 370 ++++++++++++++++++ src/game/obj_behaviors.h | 2 +- src/pc/controller/controller_keyboard_debug.c | 2 +- src/pc/network/network.c | 9 - src/pc/network/network_player.c | 14 + src/pc/network/network_player.h | 1 + src/pc/network/packets/packet.c | 4 +- src/pc/network/packets/packet.h | 25 +- .../network/packets/packet_location_request.c | 313 +-------------- .../packets/packet_location_request_client.c | 57 +++ .../packets/packet_location_response.c | 189 +++++++++ .../network/packets/packet_macro_deletions.c | 205 ++++++++++ src/pc/network/packets/packet_object.c | 18 +- .../packets/packet_spawn_info_deletions.c | 140 +++++++ 26 files changed, 1045 insertions(+), 744 deletions(-) create mode 100644 src/game/macro_presets.c create mode 100644 src/pc/network/packets/packet_location_request_client.c create mode 100644 src/pc/network/packets/packet_location_response.c create mode 100644 src/pc/network/packets/packet_macro_deletions.c create mode 100644 src/pc/network/packets/packet_spawn_info_deletions.c diff --git a/build-windows-visual-studio/sm64ex.vcxproj b/build-windows-visual-studio/sm64ex.vcxproj index 7864faca..3b2ac0e5 100644 --- a/build-windows-visual-studio/sm64ex.vcxproj +++ b/build-windows-visual-studio/sm64ex.vcxproj @@ -3968,10 +3968,15 @@ + + + + + @@ -3979,6 +3984,7 @@ + diff --git a/data/behavior_table.c b/data/behavior_table.c index 2b1311f5..fbe918cd 100644 --- a/data/behavior_table.c +++ b/data/behavior_table.c @@ -529,20 +529,3 @@ const BehaviorScript* get_behavior_from_id(enum BehaviorId id) { } return gBehaviorTable[id]; } - -u8 is_behavior_a_coin(const BehaviorScript* behavior) { - return behavior == bhvCoinFormationSpawn - || behavior == bhvCoinFormation - || behavior == bhvOneCoin - || behavior == bhvYellowCoin - || behavior == bhvTemporaryYellowCoin - || behavior == bhvThreeCoinsSpawn - || behavior == bhvTenCoinsSpawn - || behavior == bhvHiddenBlueCoin - || behavior == bhvMovingYellowCoin - || behavior == bhvMovingBlueCoin - || behavior == bhvBlueCoinSliding - || behavior == bhvBlueCoinJumping - || behavior == bhvRedCoin - || behavior == bhvBowserCourseRedCoinStar; -} diff --git a/developer/network.sh b/developer/network.sh index b274aefe..0d095ced 100644 --- a/developer/network.sh +++ b/developer/network.sh @@ -18,10 +18,10 @@ fi #exit # no debug, direct -$FILE --server 27015 --configfile sm64config_server.txt & -sleep 7 -$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt & -exit +#$FILE --server 27015 --configfile sm64config_server.txt & +#sleep 7 +#$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt & +#exit # debug on server #$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt & diff --git a/include/behavior_table.h b/include/behavior_table.h index 0dc8fe7d..142df2f9 100644 --- a/include/behavior_table.h +++ b/include/behavior_table.h @@ -526,6 +526,5 @@ enum BehaviorId { enum BehaviorId get_id_from_behavior(const BehaviorScript* behavior); const BehaviorScript* get_behavior_from_id(enum BehaviorId id); -u8 is_behavior_a_coin(const BehaviorScript* behavior); #endif diff --git a/include/macro_presets.h b/include/macro_presets.h index a7ad50f6..861dfb49 100644 --- a/include/macro_presets.h +++ b/include/macro_presets.h @@ -12,373 +12,6 @@ struct MacroPreset /*0x06*/ s16 param; }; -struct MacroPreset MacroObjectPresets[] = { - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvOneCoin, MODEL_YELLOW_COIN, 0}, - {bhvMovingBlueCoin, MODEL_BLUE_COIN, 0}, - {bhvBlueCoinSliding, MODEL_BLUE_COIN, 0}, // unused - {bhvRedCoin, MODEL_RED_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvCoinFormation, MODEL_NONE, 0}, - {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_RING}, - {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_ARROW}, - {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING}, - {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING | COIN_FORMATION_FLAG_VERTICAL}, - {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING | COIN_FORMATION_FLAG_RING}, - {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING | COIN_FORMATION_FLAG_RING | COIN_FORMATION_FLAG_VERTICAL}, - {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING | COIN_FORMATION_FLAG_ARROW}, // unused - {bhvHiddenStarTrigger, MODEL_NONE, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvUnusedFakeStar, MODEL_STAR, 0}, // unused - {bhvMessagePanel, MODEL_WOODEN_SIGNPOST, 0}, - {bhvCannonClosed, MODEL_DL_CANNON_LID, 0}, - {bhvBobombBuddyOpensCannon, MODEL_BOBOMB_BUDDY, 0}, - {bhvButterfly, MODEL_BUTTERFLY, 0}, // unused - {bhvBouncingFireball, MODEL_NONE, 0}, // unused - {bhvLargeFishGroup, MODEL_NONE, 0}, // unused - {bhvLargeFishGroup, MODEL_NONE, 1}, - {bhvBetaFishSplashSpawner, MODEL_NONE, 0}, - {bhvHidden1upInPoleSpawner, MODEL_NONE, 0}, - {bhvGoomba, MODEL_GOOMBA, 1}, - {bhvGoomba, MODEL_GOOMBA, 2}, - {bhvGoombaTripletSpawner, MODEL_NONE, 0}, - {bhvGoombaTripletSpawner, MODEL_NONE, 8}, // unused - {bhvSignOnWall, MODEL_NONE, 0}, - {bhvChuckya, MODEL_CHUCKYA, 0}, - {bhvCannon, MODEL_CANNON_BASE, 0}, - {bhvGoomba, MODEL_GOOMBA, 0}, - {bhvHomingAmp, MODEL_AMP, 0}, - {bhvCirclingAmp, MODEL_AMP, 0}, - {bhvCarrySomething1, MODEL_UNKNOWN_7D, 0}, // unused - {bhvBetaTrampolineTop, MODEL_TRAMPOLINE, 0}, // unused - {bhvFreeBowlingBall, MODEL_BOWLING_BALL, 0}, // unused - {bhvSnufit, MODEL_SNUFIT, 0}, - {bhvRecoveryHeart, MODEL_HEART, 0}, - {bhv1upSliding, MODEL_1UP, 0}, - {bhv1Up, MODEL_1UP, 0}, - {bhv1upJumpOnApproach, MODEL_1UP, 0}, // unused - {bhvHidden1up, MODEL_1UP, 0}, - {bhvHidden1upTrigger, MODEL_NONE, 0}, - {bhv1Up, MODEL_1UP, 1}, - {bhv1Up, MODEL_1UP, 2}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvBlueCoinSwitch, MODEL_BLUE_COIN_SWITCH, 0}, - {bhvHiddenBlueCoin, MODEL_BLUE_COIN, 0}, - {bhvCapSwitch, MODEL_CAP_SWITCH, 0}, // unused - {bhvCapSwitch, MODEL_CAP_SWITCH, 1}, // unused - {bhvCapSwitch, MODEL_CAP_SWITCH, 2}, // unused - {bhvCapSwitch, MODEL_CAP_SWITCH, 3}, // unused - {bhvWaterLevelDiamond, MODEL_BREAKABLE_BOX, 0}, // unused - {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 0}, - {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 1}, - {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 2}, - {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 3}, - {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 4}, // unused - {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 5}, - {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 6}, - {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 7}, - {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 8}, - {bhvBreakableBox, MODEL_BREAKABLE_BOX, 0}, - {bhvBreakableBox, MODEL_BREAKABLE_BOX, 1}, - {bhvPushableMetalBox, MODEL_METAL_BOX, 0}, - {bhvBreakableBoxSmall, MODEL_BREAKABLE_BOX_SMALL, 0}, - {bhvFloorSwitchHiddenObjects, MODEL_PURPLE_SWITCH, 0}, - {bhvHiddenObject, MODEL_BREAKABLE_BOX, 0}, - {bhvHiddenObject, MODEL_BREAKABLE_BOX, 1}, // unused - {bhvHiddenObject, MODEL_BREAKABLE_BOX, 2}, // unused - {bhvBreakableBox, MODEL_BREAKABLE_BOX, 3}, - {bhvKoopaShellUnderwater, MODEL_KOOPA_SHELL, 0}, - {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 9}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvBulletBill, MODEL_BULLET_BILL, 0}, // unused - {bhvHeaveHo, MODEL_HEAVE_HO, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvThwomp2, MODEL_THWOMP, 0}, // unused - {bhvFireSpitter, MODEL_BOWLING_BALL, 0}, - {bhvFlyGuy, MODEL_FLYGUY, 1}, - {bhvJumpingBox, MODEL_BREAKABLE_BOX, 0}, - {bhvTripletButterfly, MODEL_BUTTERFLY, 0}, - {bhvTripletButterfly, MODEL_BUTTERFLY, 4}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvSmallBully, MODEL_BULLY, 0}, - {bhvSmallBully, MODEL_BULLY_BOSS, 0}, // unused - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvStub1D0C, MODEL_UNKNOWN_58, 0}, // unused - {bhvBouncingFireball, MODEL_NONE, 0}, - {bhvFlamethrower, MODEL_NONE, 4}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvWoodenPost, MODEL_WOODEN_POST, 0}, - {bhvWaterBombSpawner, MODEL_NONE, 0}, - {bhvEnemyLakitu, MODEL_ENEMY_LAKITU, 0}, - {bhvKoopa, MODEL_KOOPA_WITH_SHELL, 2}, // unused - {bhvKoopaRaceEndpoint, MODEL_NONE, 0}, // unused - {bhvBobomb, MODEL_BLACK_BOBOMB, 0}, - {bhvWaterBombCannon, MODEL_CANNON_BASE, 0}, // unused - {bhvBobombBuddyOpensCannon, MODEL_BOBOMB_BUDDY, 0}, // unused - {bhvWaterBombCannon, MODEL_CANNON_BASE, 0}, - {bhvBobomb, MODEL_BLACK_BOBOMB, 1}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvUnusedFakeStar, MODEL_UNKNOWN_54, 0}, // unused - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvUnagi, MODEL_UNAGI, 0}, // unused - {bhvSushiShark, MODEL_SUSHI, 0}, // unused - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvStaticObject, MODEL_KLEPTO, 0}, // unused - {bhvTweester, MODEL_TWEESTER, 0}, // unused - {bhvPokey, MODEL_NONE, 0}, - {bhvPokey, MODEL_NONE, 0}, // unused - {bhvToxBox, MODEL_SSL_TOX_BOX, 0}, // unused - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvMontyMole, MODEL_MONTY_MOLE, 0}, // unused - {bhvMontyMole, MODEL_MONTY_MOLE, 1}, - {bhvMontyMoleHole, MODEL_DL_MONTY_MOLE_HOLE, 0}, - {bhvFlyGuy, MODEL_FLYGUY, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvWigglerHead, MODEL_WIGGLER_HEAD, 0}, // unused - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvSpindrift, MODEL_SPINDRIFT, 0}, - {bhvMrBlizzard, MODEL_MR_BLIZZARD_HIDDEN, 0}, - {bhvMrBlizzard, MODEL_MR_BLIZZARD_HIDDEN, 0}, // unused - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvSmallPenguin, MODEL_PENGUIN, 0}, // unused - {bhvTuxiesMother, MODEL_PENGUIN, 0}, // unused - {bhvTuxiesMother, MODEL_PENGUIN, 0}, // unused - {bhvMrBlizzard, MODEL_MR_BLIZZARD_HIDDEN, 1}, // unused - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvHauntedChair, MODEL_HAUNTED_CHAIR, 0}, // unused - {bhvHauntedChair, MODEL_HAUNTED_CHAIR, 0}, - {bhvHauntedChair, MODEL_HAUNTED_CHAIR, 0}, // unused - {bhvGhostHuntBoo, MODEL_BOO, 0}, // unused - {bhvGhostHuntBoo, MODEL_BOO, 0}, // unused - {bhvCourtyardBooTriplet, MODEL_BOO, 0}, // unused - {bhvBooWithCage, MODEL_BOO, 0}, // unused - {bhvAlphaBooKey, MODEL_BETA_BOO_KEY, 0}, // unused - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvChirpChirp, MODEL_NONE, 0}, - {bhvSeaweedBundle, MODEL_NONE, 0}, - {bhvBetaChestBottom, MODEL_TREASURE_CHEST_BASE, 0}, // unused - {bhvBowserBomb, MODEL_WATER_MINE, 0}, // unused - {bhvLargeFishGroup, MODEL_NONE, 2}, // unused - {bhvLargeFishGroup, MODEL_NONE, 3}, - {bhvJetStreamRingSpawner, MODEL_WATER_RING, 0}, // unused - {bhvJetStreamRingSpawner, MODEL_WATER_RING, 0}, // unused - {bhvSkeeter, MODEL_SKEETER, 0}, - {bhvClamShell, MODEL_CLAM_SHELL, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvMacroUkiki, MODEL_UKIKI, 0}, // unused - {bhvMacroUkiki, MODEL_UKIKI, 1}, // unused - {bhvPiranhaPlant, MODEL_PIRANHA_PLANT, 0}, // unused - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvSmallWhomp, MODEL_WHOMP, 0}, - {bhvChainChomp, MODEL_CHAIN_CHOMP, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvKoopa, MODEL_KOOPA_WITH_SHELL, 1}, - {bhvKoopa, MODEL_KOOPA_WITHOUT_SHELL, 0}, // unused - {bhvWoodenPost, MODEL_WOODEN_POST, 0}, // unused - {bhvFirePiranhaPlant, MODEL_PIRANHA_PLANT, 0}, - {bhvFirePiranhaPlant, MODEL_PIRANHA_PLANT, 1}, // unused - {bhvKoopa, MODEL_KOOPA_WITH_SHELL, 4}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvMoneybagHidden, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvSwoop, MODEL_SWOOP, 0}, - {bhvSwoop, MODEL_SWOOP, 1}, - {bhvMrI, MODEL_NONE, 0}, - {bhvScuttlebugSpawn, MODEL_NONE, 0}, - {bhvScuttlebug, MODEL_SCUTTLEBUG, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_UNKNOWN_54, 0}, // unused - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvTTCRotatingSolid, MODEL_TTC_ROTATING_CUBE, 0}, - {bhvTTCRotatingSolid, MODEL_TTC_ROTATING_PRISM, 1}, - {bhvTTCPendulum, MODEL_TTC_PENDULUM, 0}, - {bhvTTCTreadmill, MODEL_TTC_LARGE_TREADMILL, 0}, - {bhvTTCTreadmill, MODEL_TTC_SMALL_TREADMILL, 1}, - {bhvTTCMovingBar, MODEL_TTC_PUSH_BLOCK, 0}, - {bhvTTCCog, MODEL_TTC_ROTATING_HEXAGON, 0}, - {bhvTTCCog, MODEL_TTC_ROTATING_TRIANGLE, 2}, - {bhvTTCPitBlock, MODEL_TTC_PIT_BLOCK, 0}, - {bhvTTCPitBlock, MODEL_TTC_PIT_BLOCK_UNUSED, 1}, // unused - {bhvTTCElevator, MODEL_TTC_ELEVATOR_PLATFORM, 0}, - {bhvTTC2DRotator, MODEL_TTC_CLOCK_HAND, 0}, - {bhvTTCSpinner, MODEL_TTC_SPINNER, 0}, - {bhvTTC2DRotator, MODEL_TTC_SMALL_GEAR, 1}, - {bhvTTC2DRotator, MODEL_TTC_LARGE_GEAR, 1}, - {bhvTTCTreadmill, MODEL_TTC_LARGE_TREADMILL, 2}, - {bhvTTCTreadmill, MODEL_TTC_SMALL_TREADMILL, 3}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 10}, - {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 11}, - {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 12}, - {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 13}, // unused - {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 14}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvSlidingPlatform2, MODEL_BITS_SLIDING_PLATFORM, 0}, // unused - {bhvSlidingPlatform2, MODEL_BITS_TWIN_SLIDING_PLATFORMS, 0}, // unused - {bhvAnotherTiltingPlatform, MODEL_BITDW_SLIDING_PLATFORM, 0}, // unused - {bhvOctagonalPlatformRotating, MODEL_BITS_OCTAGONAL_PLATFORM, 0}, // unused - {bhvAnimatesOnFloorSwitchPress, MODEL_BITS_STAIRCASE, 0}, // unused - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvFerrisWheelAxle, MODEL_BITS_FERRIS_WHEEL_AXLE, 0}, // unused - {bhvActivatedBackAndForthPlatform, MODEL_BITS_ARROW_PLATFORM, 0}, // unused - {bhvSeesawPlatform, MODEL_BITS_SEESAW_PLATFORM, 0}, // unused - {bhvSeesawPlatform, MODEL_BITS_TILTING_W_PLATFORM, 0}, // unused - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, - {bhvYellowCoin, MODEL_YELLOW_COIN, 0} -}; +extern struct MacroPreset MacroObjectPresets[]; #endif // MACRO_PRESETS_H diff --git a/include/object_fields.h b/include/object_fields.h index 3b507da0..a6d771ce 100644 --- a/include/object_fields.h +++ b/include/object_fields.h @@ -406,7 +406,6 @@ #ifndef VERSION_JP #define /*0x1B0*/ oCoinUnk1B0 OBJECT_FIELD_S32(0x4A) #endif -#define /*0x110*/ oCoinID OBJECT_FIELD_S16(0x49, 0) /* Collision Particle */ #define /*0x0F4*/ oCollisionParticleUnkF4 OBJECT_FIELD_F32(0x1B) diff --git a/src/game/behaviors/bobomb.inc.c b/src/game/behaviors/bobomb.inc.c index f519f2a8..0eb3944e 100644 --- a/src/game/behaviors/bobomb.inc.c +++ b/src/game/behaviors/bobomb.inc.c @@ -39,7 +39,7 @@ void bobomb_act_explode(void) { explosion->oGraphYOffset += 100.0f; bobomb_spawn_coin(); - create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000, o->oSyncID); + create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000); o->activeFlags = ACTIVE_FLAG_DEACTIVATED; } } @@ -130,12 +130,12 @@ void generic_bobomb_free_loop(void) { case BOBOMB_ACT_LAVA_DEATH: if (obj_lava_death() == 1) - create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000, o->oSyncID); + create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000); break; case BOBOMB_ACT_DEATH_PLANE_DEATH: o->activeFlags = ACTIVE_FLAG_DEACTIVATED; - create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000, o->oSyncID); + create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000); break; } @@ -157,12 +157,12 @@ void stationary_bobomb_free_loop(void) { case BOBOMB_ACT_LAVA_DEATH: if (obj_lava_death() == 1) - create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000, o->oSyncID); + create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000); break; case BOBOMB_ACT_DEATH_PLANE_DEATH: o->activeFlags = ACTIVE_FLAG_DEACTIVATED; - create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000, o->oSyncID); + create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000); break; } diff --git a/src/game/behaviors/breakable_box_small.inc.c b/src/game/behaviors/breakable_box_small.inc.c index 7462f36d..327b2c9a 100644 --- a/src/game/behaviors/breakable_box_small.inc.c +++ b/src/game/behaviors/breakable_box_small.inc.c @@ -70,7 +70,7 @@ void breakable_box_small_released_loop(void) { // Despawn, and create a corkbox respawner if (o->oBreakableBoxSmallFramesSinceReleased > 900) { - create_respawner(MODEL_BREAKABLE_BOX_SMALL, bhvBreakableBoxSmall, 3000, o->oSyncID); + create_respawner(MODEL_BREAKABLE_BOX_SMALL, bhvBreakableBoxSmall, 3000); o->activeFlags = ACTIVE_FLAG_DEACTIVATED; } } @@ -87,7 +87,7 @@ void breakable_box_small_idle_loop(void) { case 101: o->activeFlags = ACTIVE_FLAG_DEACTIVATED; - create_respawner(MODEL_BREAKABLE_BOX_SMALL, bhvBreakableBoxSmall, 3000, o->oSyncID); + create_respawner(MODEL_BREAKABLE_BOX_SMALL, bhvBreakableBoxSmall, 3000); break; } diff --git a/src/game/behaviors/corkbox.inc.c b/src/game/behaviors/corkbox.inc.c index e19ba4f3..9db8c013 100644 --- a/src/game/behaviors/corkbox.inc.c +++ b/src/game/behaviors/corkbox.inc.c @@ -42,23 +42,30 @@ void bhv_respawner_loop(void) { struct Object *spawnedObject; if (!is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, o->oRespawnerMinSpawnDist)) { + u32 syncID = o->oSyncID; spawnedObject = spawn_object(o, o->oRespawnerModelToRespawn, o->oRespawnerBehaviorToRespawn); spawnedObject->oBehParams = o->oBehParams; - spawnedObject->oSyncID = o->oSyncID; + spawnedObject->oSyncID = syncID; + network_override_object(syncID, spawnedObject); + o->oSyncID = 0; + o->activeFlags = ACTIVE_FLAG_DEACTIVATED; } } -void create_respawner(s32 model, const BehaviorScript *behToSpawn, s32 minSpawnDist, u32 syncID) { +void create_respawner(s32 model, const BehaviorScript *behToSpawn, s32 minSpawnDist) { struct Object *respawner = spawn_object_abs_with_rot(o, 0, MODEL_NONE, bhvRespawner, o->oHomeX, o->oHomeY, o->oHomeZ, 0, 0, 0); + u8 syncID = o->oSyncID; respawner->oBehParams = o->oBehParams; respawner->oRespawnerModelToRespawn = model; respawner->oRespawnerMinSpawnDist = minSpawnDist; respawner->oRespawnerBehaviorToRespawn = behToSpawn; respawner->oSyncID = syncID; - network_forget_sync_object(&gSyncObjects[syncID]); - network_init_object(respawner, SYNC_DISTANCE_ONLY_EVENTS); - o->oSyncID = 0; + if (gSyncObjects[syncID].staticLevelSpawn) { + network_override_object(syncID, respawner); + o->oSyncID = 0; + o->oFlags |= OBJ_FLAG_PERSISTENT_RESPAWN; // pretty sure this is required + } } diff --git a/src/game/behaviors/snowman.inc.c b/src/game/behaviors/snowman.inc.c index ae08b065..6ec9b522 100644 --- a/src/game/behaviors/snowman.inc.c +++ b/src/game/behaviors/snowman.inc.c @@ -103,7 +103,7 @@ void snowmans_bottom_act_2(void) { } if (o->oTimer == 200) { - create_respawner(MODEL_CCM_SNOWMAN_BASE, bhvSnowmansBottom, 3000, o->oSyncID); + create_respawner(MODEL_CCM_SNOWMAN_BASE, bhvSnowmansBottom, 3000); o->activeFlags = ACTIVE_FLAG_DEACTIVATED; } } diff --git a/src/game/behaviors/yoshi.inc.c b/src/game/behaviors/yoshi.inc.c index 438a5646..b2b60d9f 100644 --- a/src/game/behaviors/yoshi.inc.c +++ b/src/game/behaviors/yoshi.inc.c @@ -47,7 +47,7 @@ void yoshi_walk_loop(void) { o->oAction = YOSHI_ACT_TALK; if (o->oPosY < 2100.0f) { - create_respawner(MODEL_YOSHI, bhvYoshi, 3000, o->oSyncID); + create_respawner(MODEL_YOSHI, bhvYoshi, 3000); o->activeFlags = ACTIVE_FLAG_DEACTIVATED; } } diff --git a/src/game/interaction.c b/src/game/interaction.c index 2ed9e9be..5e1499c3 100644 --- a/src/game/interaction.c +++ b/src/game/interaction.c @@ -838,9 +838,6 @@ u32 interact_coin(struct MarioState *m, UNUSED u32 interactType, struct Object * } network_send_collect_coin(o); - if (o->oCoinID > 0) { - coin_collection_remember(o->oCoinID); - } return FALSE; } diff --git a/src/game/macro_presets.c b/src/game/macro_presets.c new file mode 100644 index 00000000..d498cbb6 --- /dev/null +++ b/src/game/macro_presets.c @@ -0,0 +1,370 @@ +#include "macro_presets.h" + +struct MacroPreset MacroObjectPresets[] = { + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvOneCoin, MODEL_YELLOW_COIN, 0}, + {bhvMovingBlueCoin, MODEL_BLUE_COIN, 0}, + {bhvBlueCoinSliding, MODEL_BLUE_COIN, 0}, // unused + {bhvRedCoin, MODEL_RED_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvCoinFormation, MODEL_NONE, 0}, + {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_RING}, + {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_ARROW}, + {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING}, + {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING | COIN_FORMATION_FLAG_VERTICAL}, + {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING | COIN_FORMATION_FLAG_RING}, + {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING | COIN_FORMATION_FLAG_RING | COIN_FORMATION_FLAG_VERTICAL}, + {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING | COIN_FORMATION_FLAG_ARROW}, // unused + {bhvHiddenStarTrigger, MODEL_NONE, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvUnusedFakeStar, MODEL_STAR, 0}, // unused + {bhvMessagePanel, MODEL_WOODEN_SIGNPOST, 0}, + {bhvCannonClosed, MODEL_DL_CANNON_LID, 0}, + {bhvBobombBuddyOpensCannon, MODEL_BOBOMB_BUDDY, 0}, + {bhvButterfly, MODEL_BUTTERFLY, 0}, // unused + {bhvBouncingFireball, MODEL_NONE, 0}, // unused + {bhvLargeFishGroup, MODEL_NONE, 0}, // unused + {bhvLargeFishGroup, MODEL_NONE, 1}, + {bhvBetaFishSplashSpawner, MODEL_NONE, 0}, + {bhvHidden1upInPoleSpawner, MODEL_NONE, 0}, + {bhvGoomba, MODEL_GOOMBA, 1}, + {bhvGoomba, MODEL_GOOMBA, 2}, + {bhvGoombaTripletSpawner, MODEL_NONE, 0}, + {bhvGoombaTripletSpawner, MODEL_NONE, 8}, // unused + {bhvSignOnWall, MODEL_NONE, 0}, + {bhvChuckya, MODEL_CHUCKYA, 0}, + {bhvCannon, MODEL_CANNON_BASE, 0}, + {bhvGoomba, MODEL_GOOMBA, 0}, + {bhvHomingAmp, MODEL_AMP, 0}, + {bhvCirclingAmp, MODEL_AMP, 0}, + {bhvCarrySomething1, MODEL_UNKNOWN_7D, 0}, // unused + {bhvBetaTrampolineTop, MODEL_TRAMPOLINE, 0}, // unused + {bhvFreeBowlingBall, MODEL_BOWLING_BALL, 0}, // unused + {bhvSnufit, MODEL_SNUFIT, 0}, + {bhvRecoveryHeart, MODEL_HEART, 0}, + {bhv1upSliding, MODEL_1UP, 0}, + {bhv1Up, MODEL_1UP, 0}, + {bhv1upJumpOnApproach, MODEL_1UP, 0}, // unused + {bhvHidden1up, MODEL_1UP, 0}, + {bhvHidden1upTrigger, MODEL_NONE, 0}, + {bhv1Up, MODEL_1UP, 1}, + {bhv1Up, MODEL_1UP, 2}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvBlueCoinSwitch, MODEL_BLUE_COIN_SWITCH, 0}, + {bhvHiddenBlueCoin, MODEL_BLUE_COIN, 0}, + {bhvCapSwitch, MODEL_CAP_SWITCH, 0}, // unused + {bhvCapSwitch, MODEL_CAP_SWITCH, 1}, // unused + {bhvCapSwitch, MODEL_CAP_SWITCH, 2}, // unused + {bhvCapSwitch, MODEL_CAP_SWITCH, 3}, // unused + {bhvWaterLevelDiamond, MODEL_BREAKABLE_BOX, 0}, // unused + {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 0}, + {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 1}, + {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 2}, + {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 3}, + {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 4}, // unused + {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 5}, + {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 6}, + {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 7}, + {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 8}, + {bhvBreakableBox, MODEL_BREAKABLE_BOX, 0}, + {bhvBreakableBox, MODEL_BREAKABLE_BOX, 1}, + {bhvPushableMetalBox, MODEL_METAL_BOX, 0}, + {bhvBreakableBoxSmall, MODEL_BREAKABLE_BOX_SMALL, 0}, + {bhvFloorSwitchHiddenObjects, MODEL_PURPLE_SWITCH, 0}, + {bhvHiddenObject, MODEL_BREAKABLE_BOX, 0}, + {bhvHiddenObject, MODEL_BREAKABLE_BOX, 1}, // unused + {bhvHiddenObject, MODEL_BREAKABLE_BOX, 2}, // unused + {bhvBreakableBox, MODEL_BREAKABLE_BOX, 3}, + {bhvKoopaShellUnderwater, MODEL_KOOPA_SHELL, 0}, + {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 9}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvBulletBill, MODEL_BULLET_BILL, 0}, // unused + {bhvHeaveHo, MODEL_HEAVE_HO, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvThwomp2, MODEL_THWOMP, 0}, // unused + {bhvFireSpitter, MODEL_BOWLING_BALL, 0}, + {bhvFlyGuy, MODEL_FLYGUY, 1}, + {bhvJumpingBox, MODEL_BREAKABLE_BOX, 0}, + {bhvTripletButterfly, MODEL_BUTTERFLY, 0}, + {bhvTripletButterfly, MODEL_BUTTERFLY, 4}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvSmallBully, MODEL_BULLY, 0}, + {bhvSmallBully, MODEL_BULLY_BOSS, 0}, // unused + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvStub1D0C, MODEL_UNKNOWN_58, 0}, // unused + {bhvBouncingFireball, MODEL_NONE, 0}, + {bhvFlamethrower, MODEL_NONE, 4}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvWoodenPost, MODEL_WOODEN_POST, 0}, + {bhvWaterBombSpawner, MODEL_NONE, 0}, + {bhvEnemyLakitu, MODEL_ENEMY_LAKITU, 0}, + {bhvKoopa, MODEL_KOOPA_WITH_SHELL, 2}, // unused + {bhvKoopaRaceEndpoint, MODEL_NONE, 0}, // unused + {bhvBobomb, MODEL_BLACK_BOBOMB, 0}, + {bhvWaterBombCannon, MODEL_CANNON_BASE, 0}, // unused + {bhvBobombBuddyOpensCannon, MODEL_BOBOMB_BUDDY, 0}, // unused + {bhvWaterBombCannon, MODEL_CANNON_BASE, 0}, + {bhvBobomb, MODEL_BLACK_BOBOMB, 1}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvUnusedFakeStar, MODEL_UNKNOWN_54, 0}, // unused + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvUnagi, MODEL_UNAGI, 0}, // unused + {bhvSushiShark, MODEL_SUSHI, 0}, // unused + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvStaticObject, MODEL_KLEPTO, 0}, // unused + {bhvTweester, MODEL_TWEESTER, 0}, // unused + {bhvPokey, MODEL_NONE, 0}, + {bhvPokey, MODEL_NONE, 0}, // unused + {bhvToxBox, MODEL_SSL_TOX_BOX, 0}, // unused + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvMontyMole, MODEL_MONTY_MOLE, 0}, // unused + {bhvMontyMole, MODEL_MONTY_MOLE, 1}, + {bhvMontyMoleHole, MODEL_DL_MONTY_MOLE_HOLE, 0}, + {bhvFlyGuy, MODEL_FLYGUY, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvWigglerHead, MODEL_WIGGLER_HEAD, 0}, // unused + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvSpindrift, MODEL_SPINDRIFT, 0}, + {bhvMrBlizzard, MODEL_MR_BLIZZARD_HIDDEN, 0}, + {bhvMrBlizzard, MODEL_MR_BLIZZARD_HIDDEN, 0}, // unused + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvSmallPenguin, MODEL_PENGUIN, 0}, // unused + {bhvTuxiesMother, MODEL_PENGUIN, 0}, // unused + {bhvTuxiesMother, MODEL_PENGUIN, 0}, // unused + {bhvMrBlizzard, MODEL_MR_BLIZZARD_HIDDEN, 1}, // unused + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvHauntedChair, MODEL_HAUNTED_CHAIR, 0}, // unused + {bhvHauntedChair, MODEL_HAUNTED_CHAIR, 0}, + {bhvHauntedChair, MODEL_HAUNTED_CHAIR, 0}, // unused + {bhvGhostHuntBoo, MODEL_BOO, 0}, // unused + {bhvGhostHuntBoo, MODEL_BOO, 0}, // unused + {bhvCourtyardBooTriplet, MODEL_BOO, 0}, // unused + {bhvBooWithCage, MODEL_BOO, 0}, // unused + {bhvAlphaBooKey, MODEL_BETA_BOO_KEY, 0}, // unused + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvChirpChirp, MODEL_NONE, 0}, + {bhvSeaweedBundle, MODEL_NONE, 0}, + {bhvBetaChestBottom, MODEL_TREASURE_CHEST_BASE, 0}, // unused + {bhvBowserBomb, MODEL_WATER_MINE, 0}, // unused + {bhvLargeFishGroup, MODEL_NONE, 2}, // unused + {bhvLargeFishGroup, MODEL_NONE, 3}, + {bhvJetStreamRingSpawner, MODEL_WATER_RING, 0}, // unused + {bhvJetStreamRingSpawner, MODEL_WATER_RING, 0}, // unused + {bhvSkeeter, MODEL_SKEETER, 0}, + {bhvClamShell, MODEL_CLAM_SHELL, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvMacroUkiki, MODEL_UKIKI, 0}, // unused + {bhvMacroUkiki, MODEL_UKIKI, 1}, // unused + {bhvPiranhaPlant, MODEL_PIRANHA_PLANT, 0}, // unused + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvSmallWhomp, MODEL_WHOMP, 0}, + {bhvChainChomp, MODEL_CHAIN_CHOMP, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvKoopa, MODEL_KOOPA_WITH_SHELL, 1}, + {bhvKoopa, MODEL_KOOPA_WITHOUT_SHELL, 0}, // unused + {bhvWoodenPost, MODEL_WOODEN_POST, 0}, // unused + {bhvFirePiranhaPlant, MODEL_PIRANHA_PLANT, 0}, + {bhvFirePiranhaPlant, MODEL_PIRANHA_PLANT, 1}, // unused + {bhvKoopa, MODEL_KOOPA_WITH_SHELL, 4}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvMoneybagHidden, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvSwoop, MODEL_SWOOP, 0}, + {bhvSwoop, MODEL_SWOOP, 1}, + {bhvMrI, MODEL_NONE, 0}, + {bhvScuttlebugSpawn, MODEL_NONE, 0}, + {bhvScuttlebug, MODEL_SCUTTLEBUG, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_UNKNOWN_54, 0}, // unused + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvTTCRotatingSolid, MODEL_TTC_ROTATING_CUBE, 0}, + {bhvTTCRotatingSolid, MODEL_TTC_ROTATING_PRISM, 1}, + {bhvTTCPendulum, MODEL_TTC_PENDULUM, 0}, + {bhvTTCTreadmill, MODEL_TTC_LARGE_TREADMILL, 0}, + {bhvTTCTreadmill, MODEL_TTC_SMALL_TREADMILL, 1}, + {bhvTTCMovingBar, MODEL_TTC_PUSH_BLOCK, 0}, + {bhvTTCCog, MODEL_TTC_ROTATING_HEXAGON, 0}, + {bhvTTCCog, MODEL_TTC_ROTATING_TRIANGLE, 2}, + {bhvTTCPitBlock, MODEL_TTC_PIT_BLOCK, 0}, + {bhvTTCPitBlock, MODEL_TTC_PIT_BLOCK_UNUSED, 1}, // unused + {bhvTTCElevator, MODEL_TTC_ELEVATOR_PLATFORM, 0}, + {bhvTTC2DRotator, MODEL_TTC_CLOCK_HAND, 0}, + {bhvTTCSpinner, MODEL_TTC_SPINNER, 0}, + {bhvTTC2DRotator, MODEL_TTC_SMALL_GEAR, 1}, + {bhvTTC2DRotator, MODEL_TTC_LARGE_GEAR, 1}, + {bhvTTCTreadmill, MODEL_TTC_LARGE_TREADMILL, 2}, + {bhvTTCTreadmill, MODEL_TTC_SMALL_TREADMILL, 3}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 10}, + {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 11}, + {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 12}, + {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 13}, // unused + {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 14}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvSlidingPlatform2, MODEL_BITS_SLIDING_PLATFORM, 0}, // unused + {bhvSlidingPlatform2, MODEL_BITS_TWIN_SLIDING_PLATFORMS, 0}, // unused + {bhvAnotherTiltingPlatform, MODEL_BITDW_SLIDING_PLATFORM, 0}, // unused + {bhvOctagonalPlatformRotating, MODEL_BITS_OCTAGONAL_PLATFORM, 0}, // unused + {bhvAnimatesOnFloorSwitchPress, MODEL_BITS_STAIRCASE, 0}, // unused + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvFerrisWheelAxle, MODEL_BITS_FERRIS_WHEEL_AXLE, 0}, // unused + {bhvActivatedBackAndForthPlatform, MODEL_BITS_ARROW_PLATFORM, 0}, // unused + {bhvSeesawPlatform, MODEL_BITS_SEESAW_PLATFORM, 0}, // unused + {bhvSeesawPlatform, MODEL_BITS_TILTING_W_PLATFORM, 0}, // unused + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0}, + {bhvYellowCoin, MODEL_YELLOW_COIN, 0} +}; diff --git a/src/game/obj_behaviors.h b/src/game/obj_behaviors.h index 8b5fbea7..35355f12 100644 --- a/src/game/obj_behaviors.h +++ b/src/game/obj_behaviors.h @@ -87,7 +87,7 @@ void bhv_bobomb_bully_death_smoke_init(void); void bhv_bobomb_explosion_bubble_init(void); void bhv_bobomb_explosion_bubble_loop(void); void bhv_respawner_loop(void); -void create_respawner(s32 arg0, const BehaviorScript *behToSpawn, s32 minSpawnDist, u32 syncID); +void create_respawner(s32 arg0, const BehaviorScript *behToSpawn, s32 minSpawnDist); void bhv_small_bully_init(void); void bhv_big_bully_init(void); void bully_check_mario_collision(void); diff --git a/src/pc/controller/controller_keyboard_debug.c b/src/pc/controller/controller_keyboard_debug.c index ed99ae47..573a9bb5 100644 --- a/src/pc/controller/controller_keyboard_debug.c +++ b/src/pc/controller/controller_keyboard_debug.c @@ -7,7 +7,7 @@ #ifdef DEBUG -static u8 warpToLevel = LEVEL_BOB; +static u8 warpToLevel = LEVEL_CCM; #define SCANCODE_0 0x0B #define SCANCODE_1 0x02 diff --git a/src/pc/network/network.c b/src/pc/network/network.c index ae8d3542..7ff16cd9 100644 --- a/src/pc/network/network.c +++ b/src/pc/network/network.c @@ -100,15 +100,6 @@ void network_on_loaded_level(void) { gSyncObjects[i].staticLevelSpawn = true; } - // give all coins an ID - u8 coinId = 0; - for (int i = 0; i < OBJECT_POOL_CAPACITY; i++) { - struct Object* o = &gObjectPool[i]; - if (o->activeFlags & ACTIVE_FLAG_DEACTIVATED) { continue; } - if (!is_behavior_a_coin(o->behavior)) { continue; } - o->oCoinID = ++coinId; - } - // check for level change struct NetworkPlayer* np = gNetworkPlayerLocal; if (np != NULL) { diff --git a/src/pc/network/network_player.c b/src/pc/network/network_player.c index 6cdf8d75..cf7a016d 100644 --- a/src/pc/network/network_player.c +++ b/src/pc/network/network_player.c @@ -33,6 +33,20 @@ struct NetworkPlayer* network_player_from_global_index(u8 globalIndex) { return NULL; } +struct NetworkPlayer* get_network_player_from_valid_location(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->currAreaSyncValid) { continue; } + if (np->currCourseNum != courseNum) { continue; } + if (np->currActNum != actNum) { continue; } + if (np->currLevelNum != levelNum) { continue; } + if (np->currAreaIndex != areaIndex) { continue; } + return np; + } + return NULL; +} + void network_player_update(void) { float elapsed = (clock() - gLastNetworkSend) / (float)CLOCKS_PER_SEC; if (elapsed > NETWORK_PLAYER_TIMEOUT / 3.0f) { diff --git a/src/pc/network/network_player.h b/src/pc/network/network_player.h index dd91d2fd..95078746 100644 --- a/src/pc/network/network_player.h +++ b/src/pc/network/network_player.h @@ -41,6 +41,7 @@ extern struct NetworkPlayer* gNetworkPlayerServer; bool network_player_any_connected(void); u8 network_player_connected_count(void); 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); void network_player_update(void); u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex); u8 network_player_disconnected(u8 globalIndex); diff --git a/src/pc/network/packets/packet.c b/src/pc/network/packets/packet.c index 8e4c4e6c..6e227b51 100644 --- a/src/pc/network/packets/packet.c +++ b/src/pc/network/packets/packet.c @@ -62,8 +62,10 @@ void packet_receive(struct Packet* p) { case PACKET_LEVEL_AREA: network_receive_level_area(p); break; case PACKET_LEVEL_AREA_VALID: network_receive_level_area_valid(p); break; case PACKET_LOCATION_REQUEST: network_receive_location_request(p); break; - case PACKET_CLIENT_LOCATION_REQUEST: network_receive_client_location_request(p); break; + case PACKET_LOCATION_REQUEST_CLIENT: network_receive_location_request_client(p); break; case PACKET_LOCATION_RESPONSE: network_receive_location_response(p); break; + case PACKET_MACRO_DELETIONS: network_receive_macro_deletions(p); break; + case PACKET_SPAWN_INFO_DELETIONS: network_receive_spawn_info_deletions(p); break; /// case PACKET_CUSTOM: network_receive_custom(p); break; default: LOG_ERROR("received unknown packet: %d", p->buffer[0]); diff --git a/src/pc/network/packets/packet.h b/src/pc/network/packets/packet.h index 53f427d9..255bb492 100644 --- a/src/pc/network/packets/packet.h +++ b/src/pc/network/packets/packet.h @@ -34,8 +34,10 @@ enum PacketType { PACKET_LEVEL_AREA, PACKET_LEVEL_AREA_VALID, PACKET_LOCATION_REQUEST, - PACKET_CLIENT_LOCATION_REQUEST, + PACKET_LOCATION_REQUEST_CLIENT, PACKET_LOCATION_RESPONSE, + PACKET_MACRO_DELETIONS, + PACKET_SPAWN_INFO_DELETIONS, /// PACKET_CUSTOM = 255, }; @@ -87,6 +89,7 @@ void network_receive_player(struct Packet* p); // packet_object.c struct Packet* get_last_sync_ent_reliable_packet(u8 syncId); void forget_ent_reliable_packet(struct Object* o); +void network_override_object(u8 syncId, struct Object* o); struct SyncObject* network_init_object(struct Object* object, float maxSyncDistance); void network_init_object_field(struct Object* o, void* field); bool network_owns_object(struct Object* o); @@ -174,15 +177,23 @@ void network_send_level_area_valid(u8 toGlobalIndex); void network_receive_level_area_valid(struct Packet* p); // packet_location_request.c -void coin_collection_remember(u8 coinId); -void coin_collection_clear(void); -void static_spawn_removal_remember(u8 syncId); -void static_spawn_removal_clear(void); void network_send_location_request(void); void network_receive_location_request(struct Packet* p); -void network_send_client_location_request(u8 destGlobalIndex, u8 srcGlobalIndex); -void network_receive_client_location_request(struct Packet* p); + +// packet_location_request_client.c +void network_send_location_request_client(u8 destGlobalIndex, u8 srcGlobalIndex); +void network_receive_location_request_client(struct Packet* p); + +// packet_location_response.c void network_send_location_response(u8 destGlobalIndex); void network_receive_location_response(struct Packet* p); +// packet_macro_deletions.c +void network_send_macro_deletions(u8 destGlobalIndex); +void network_receive_macro_deletions(struct Packet* p); + +// packet_spawn_info_deletions.c +void network_send_spawn_info_deletions(u8 destGlobalIndex); +void network_receive_spawn_info_deletions(struct Packet* p); + #endif diff --git a/src/pc/network/packets/packet_location_request.c b/src/pc/network/packets/packet_location_request.c index 6bcd6e74..08f022e3 100644 --- a/src/pc/network/packets/packet_location_request.c +++ b/src/pc/network/packets/packet_location_request.c @@ -1,62 +1,10 @@ #include #include "../network.h" -#include "menu/custom_menu_system.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 "object_constants.h" -#include "object_fields.h" -#include "behavior_table.h" -#include "model_ids.h" //#define DISABLE_MODULE_LOG 1 #include "pc/debuglog.h" extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex; -#define MAX_STATIC_SPAWN_REMOVAL 256 -u8 sStaticSpawnRemoval[MAX_STATIC_SPAWN_REMOVAL] = { 0 }; -u8 sStaticSpawnRemovalIndex = 0; - -#define MAX_COIN_COLLECTION 128 -u8 sCoinCollection[MAX_STATIC_SPAWN_REMOVAL] = { 0 }; -u8 sCoinCollectionIndex = 0; - -void coin_collection_remember(u8 coinId) { - sCoinCollection[sCoinCollectionIndex++] = coinId; - if (sStaticSpawnRemovalIndex >= MAX_COIN_COLLECTION) { sStaticSpawnRemovalIndex = MAX_COIN_COLLECTION - 1; } -} - -void coin_collection_clear(void) { - sCoinCollectionIndex = 0; -} - -void static_spawn_removal_remember(u8 syncId) { - sStaticSpawnRemoval[sStaticSpawnRemovalIndex++] = syncId; - if (sStaticSpawnRemovalIndex == 0) { sStaticSpawnRemovalIndex = MAX_STATIC_SPAWN_REMOVAL - 1; } -} - -void static_spawn_removal_clear(void) { - sStaticSpawnRemovalIndex = 0; -} - -struct NetworkPlayer* get_network_player_from_valid_location(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->currAreaSyncValid) { continue; } - if (np->currCourseNum != courseNum) { continue; } - if (np->currActNum != actNum) { continue; } - if (np->currLevelNum != levelNum) { continue; } - if (np->currAreaIndex != areaIndex) { continue; } - return np; - } - return NULL; -} - -/////////////////////////////////////////////////////////////////////////////// - void network_send_location_request(void) { if (gNetworkType == NT_SERVER) { struct NetworkPlayer* np = get_network_player_from_valid_location(gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex); @@ -64,7 +12,7 @@ void network_send_location_request(void) { gNetworkPlayerLocal->currAreaSyncValid = true; return; } - network_send_client_location_request(gNetworkPlayerLocal->globalIndex, np->globalIndex); + network_send_location_request_client(gNetworkPlayerLocal->globalIndex, np->globalIndex); return; } @@ -107,263 +55,6 @@ void network_receive_location_request(struct Packet* p) { } else if (np2 == gNetworkPlayerLocal) { network_send_location_response(np->globalIndex); } else { - network_send_client_location_request(np->globalIndex, np2->globalIndex); + network_send_location_request_client(np->globalIndex, np2->globalIndex); } } - -/////////////////////////////////////////////////////////////////////////////// - -void network_send_client_location_request(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_CLIENT_LOCATION_REQUEST, 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_client_location_request(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); -} - -/////////////////////////////////////////////////////////////////////////////// - -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)); - - // static spawn removal - packet_write(&p, &sStaticSpawnRemovalIndex, sizeof(u8)); - for (int i = 0; i < sStaticSpawnRemovalIndex; i++) { - packet_write(&p, &sStaticSpawnRemoval[i], sizeof(u8)); - } - - // coin collection - packet_write(&p, &sCoinCollectionIndex, sizeof(u8)); - for (int i = 0; i < sCoinCollectionIndex; i++) { - packet_write(&p, &sCoinCollection[i], sizeof(u8)); - } - - // 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->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->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)); - } - - network_send_to(destNp->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 != 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); - } - - // 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); - } -} - -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; - } - - u8 staticSpawnRemovals; - static_spawn_removal_clear(); - - // read static spawn removals - packet_read(p, &staticSpawnRemovals, sizeof(u8)); - for (int i = 0; i < staticSpawnRemovals; i++) { - u8 syncId; - packet_read(p, &syncId, sizeof(u8)); - struct SyncObject* so = &gSyncObjects[syncId]; - if (so != NULL) { - if (so->o != NULL) { - obj_mark_for_deletion(so->o); - } - network_forget_sync_object(so); - } - } - - // read coin collections - packet_read(p, &sCoinCollectionIndex, sizeof(u8)); - for (int i = 0; i < sCoinCollectionIndex; i++) { - packet_read(p, &sCoinCollection[i], sizeof(u8)); - } - - // collect the coins - for (int i = 0; i < OBJECT_POOL_CAPACITY; i++) { - struct Object* o = &gObjectPool[i]; - if (o->activeFlags & ACTIVE_FLAG_DEACTIVATED) { continue; } - if (!is_behavior_a_coin(o->behavior)) { continue; } - for (int j = 0; j < sCoinCollectionIndex; j++) { - if (o->oCoinID == sCoinCollection[j]) { - o->oInteractStatus = INT_STATUS_INTERACTED; - } - } - } - - // 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 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; - - network_forget_sync_object(&gSyncObjects[syncId]); - network_init_object(respawner, SYNC_DISTANCE_ONLY_EVENTS); - } - - gMarioStates[0].numCoins = numCoins; - gNetworkPlayerLocal->currAreaSyncValid = true; - - if (gNetworkType != NT_SERVER) { - network_send_level_area_valid(0); - } -} \ No newline at end of file diff --git a/src/pc/network/packets/packet_location_request_client.c b/src/pc/network/packets/packet_location_request_client.c new file mode 100644 index 00000000..3bb59d69 --- /dev/null +++ b/src/pc/network/packets/packet_location_request_client.c @@ -0,0 +1,57 @@ +#include +#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); +} diff --git a/src/pc/network/packets/packet_location_response.c b/src/pc/network/packets/packet_location_response.c new file mode 100644 index 00000000..0bb6f0cd --- /dev/null +++ b/src/pc/network/packets/packet_location_response.c @@ -0,0 +1,189 @@ +#include +#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"); +} \ No newline at end of file diff --git a/src/pc/network/packets/packet_macro_deletions.c b/src/pc/network/packets/packet_macro_deletions.c new file mode 100644 index 00000000..54a02899 --- /dev/null +++ b/src/pc/network/packets/packet_macro_deletions.c @@ -0,0 +1,205 @@ +#include +#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 "macro_presets.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" + +static struct Object* get_object_matching_respawn_info(s16* respawnInfo) { + for (int i = 0; i < OBJECT_POOL_CAPACITY; i++) { + struct Object* o = &gObjectPool[i]; + if (o->respawnInfo == respawnInfo) { return o; } + } + + return NULL; +} + +//// + +void network_send_macro_deletions_area(u8 destGlobalIndex, u8 areaIndex) { + // check that the area is active + struct Area* area = &gAreaData[areaIndex]; + if (area->unk04 == NULL) { return; } + + struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex); + if (destNp == NULL || !destNp->connected) { + LOG_ERROR("network_send_macro_deletions_area: dest np is invalid"); + return; + } + + // write header + struct Packet p; + packet_init(&p, PACKET_MACRO_DELETIONS, 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)); + + // write this area's index + packet_write(&p, &areaIndex, sizeof(u8)); + + // write the amount of deletions + u8 zero = 0; + u8* macroDeletionCount = &p.buffer[p.cursor]; + packet_write(&p, &zero, sizeof(u8)); + + // loop through macro objects for deletions + s16* macroObjList = area->macroObjects; + while (*macroObjList != -1) { + // grab preset ID + s32 presetID = (*macroObjList & 0x1FF) - 31; // Preset identifier for MacroObjectPresets array + if (presetID < 0) { break; } + + // parse respawn info + macroObjList += 4; + s16* respawnInfo = macroObjList++; + + // if a macro object was destroyed, send its respawnInfo offset + if (((*respawnInfo >> 8) & RESPAWN_INFO_DONT_RESPAWN) == RESPAWN_INFO_DONT_RESPAWN) { + *macroDeletionCount = *macroDeletionCount + 1; + u16 offset = respawnInfo - area->macroObjects; + packet_write(&p, &offset, sizeof(u16)); + LOG_INFO("tx macro deletion: offset %d", offset); + } + } + + // write the amount of special cases + u8* macroSpecialCount = &p.buffer[p.cursor]; + packet_write(&p, &zero, sizeof(u8)); + + // loop through macro objects for special cases + macroObjList = area->macroObjects; + while (*macroObjList != -1) { + // grab preset ID + s32 presetID = (*macroObjList & 0x1FF) - 31; // Preset identifier for MacroObjectPresets array + if (presetID < 0) { break; } + + // parse respawn info + macroObjList += 4; + s16* respawnInfo = macroObjList++; + + // check for special cases + const BehaviorScript* behavior = MacroObjectPresets[presetID].behavior; + if (behavior == bhvCoinFormation && *respawnInfo != 0) { + *macroSpecialCount = *macroSpecialCount + 1; + u16 offset = respawnInfo - area->macroObjects; + packet_write(&p, &offset, sizeof(u16)); + packet_write(&p, respawnInfo, sizeof(s16)); + LOG_INFO("tx macro special: offset %d, respawnInfo %d", offset, *respawnInfo); + } + } + + // send the packet if there are deletions + if (*macroDeletionCount > 0 || *macroSpecialCount > 0) { + network_send_to(destNp->localIndex, &p); + LOG_INFO("tx macro deletion for area %d (count %d)", areaIndex, *macroDeletionCount); + } +} + +void network_send_macro_deletions(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_macro_deletions: dest np is invalid"); + return; + } + + for (int i = 0; i < 8; i++) { + network_send_macro_deletions_area(destGlobalIndex, i); + } +} + +void network_receive_macro_deletions(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) { + LOG_ERROR("Receiving 'location response' with the wrong location!"); + return; + } + + u8 thisAreaIndex; + packet_read(p, &thisAreaIndex, sizeof(u8)); + + // read and execute macro deletions + u8 macroDeletionCount; + packet_read(p, ¯oDeletionCount, sizeof(u8)); + LOG_INFO("rx macro deletions (count %d)", macroDeletionCount); + + while (macroDeletionCount-- > 0) { + u16 offset; + packet_read(p, &offset, sizeof(u16)); + LOG_INFO("rx macro deletion: offset %d", offset); + + // mark respawninfo as dont respawn + s16* respawnInfo = gAreaData[thisAreaIndex].macroObjects + offset; + *respawnInfo |= RESPAWN_INFO_DONT_RESPAWN << 8; + + struct Object* o = get_object_matching_respawn_info(respawnInfo); + if (o != NULL) { + obj_mark_for_deletion(o); + LOG_INFO("rx macro deletion: object"); + if (o->oSyncID != 0) { + struct SyncObject* so = &gSyncObjects[o->oSyncID]; + if (so->o == o) { + network_forget_sync_object(so); + LOG_INFO("rx macro deletion: sync object"); + } + } + } + } + + // read and execute macro specials + + u8 macroSpecialCount; + packet_read(p, ¯oSpecialCount, sizeof(u8)); + while (macroSpecialCount-- > 0) { + u16 offset; + packet_read(p, &offset, sizeof(u16)); + + s16* respawnInfo = gAreaData[thisAreaIndex].macroObjects + offset; + packet_read(p, respawnInfo, sizeof(s16)); + LOG_INFO("rx macro special: offset %d, respawnInfo %d", offset, *respawnInfo); + + s32 presetID = (*(respawnInfo - 4) & 0x1FF) - 31; + const BehaviorScript* behavior = MacroObjectPresets[presetID].behavior; + + struct Object* o = get_object_matching_respawn_info(respawnInfo); + if (o != NULL) { + LOG_INFO("rx macro special: object"); + // coin formation + if (behavior == bhvCoinFormation) { + o->oBehParams = *respawnInfo; + o->oCoinUnkF4 = (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 (o2->behavior != bhvCoinFormationSpawn && o2->behavior != bhvYellowCoin) { continue; } + if (o->oCoinUnkF4 & (1 << childIndex++)) { + obj_mark_for_deletion(o2); + } + } + LOG_INFO("rx macro special: coin formation"); + } + } + } +} \ No newline at end of file diff --git a/src/pc/network/packets/packet_object.c b/src/pc/network/packets/packet_object.c index ad5a366e..881bfc0e 100644 --- a/src/pc/network/packets/packet_object.c +++ b/src/pc/network/packets/packet_object.c @@ -63,7 +63,14 @@ static bool should_own_object(struct SyncObject* so) { return true; } +void network_override_object(u8 syncId, struct Object* o) { + gSyncObjects[syncId].o = 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); + // generate new sync ID network_set_sync_id(o); @@ -90,7 +97,7 @@ 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 = false; + so->staticLevelSpawn = wasStaticRespawner; memset(so->extraFields, 0, sizeof(void*) * MAX_SYNC_OBJECT_FIELDS); sLastSyncEntReliablePacket[o->oSyncID].error = true; @@ -137,8 +144,6 @@ void network_clear_sync_objects(void) { network_forget_sync_object(&gSyncObjects[i]); } nextSyncID = 1; - static_spawn_removal_clear(); - coin_collection_clear(); } void network_set_sync_id(struct Object* o) { @@ -372,6 +377,8 @@ static void packet_read_object_only_death(struct Packet* p, struct Object* o) { void network_send_object(struct Object* o) { // sanity check SyncObject if (!network_sync_object_initialized(o)) { return; } + if (o->behavior == bhvRespawner) { return; } + struct SyncObject* so = &gSyncObjects[o->oSyncID]; if (so == NULL) { return; } if (o != so->o) { @@ -493,20 +500,19 @@ 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) { u8 syncId = so->o->oSyncID; struct SyncObject* so2 = &gSyncObjects[syncId]; if (so == so2) { - static_spawn_removal_remember(syncId); sLastSyncEntReliablePacket[syncId].error = true; } } + so->o = NULL; so->behavior = NULL; so->reserved = 0; so->owned = false; - so->staticLevelSpawn = false; - } void network_update_objects(void) { diff --git a/src/pc/network/packets/packet_spawn_info_deletions.c b/src/pc/network/packets/packet_spawn_info_deletions.c new file mode 100644 index 00000000..38400754 --- /dev/null +++ b/src/pc/network/packets/packet_spawn_info_deletions.c @@ -0,0 +1,140 @@ +#include +#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" + +static struct Object* get_object_matching_respawn_info(s32* respawnInfo) { + for (int i = 0; i < OBJECT_POOL_CAPACITY; i++) { + struct Object* o = &gObjectPool[i]; + if (o->respawnInfo == respawnInfo) { return o; } + } + + return NULL; +} + +//// + +void network_send_spawn_info_deletions_area(u8 destGlobalIndex, u8 areaIndex) { + // check that the area is active + struct Area* area = &gAreaData[areaIndex]; + if (area->unk04 == NULL) { return; } + + struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex); + if (destNp == NULL || !destNp->connected) { + LOG_ERROR("network_send_spawn_info_deletions_area: dest np is invalid"); + return; + } + + // write header + struct Packet p; + packet_init(&p, PACKET_SPAWN_INFO_DELETIONS, 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)); + + // write this area's index + packet_write(&p, &areaIndex, sizeof(u8)); + + // write the amount of deletions + u8 zero = 0; + u8* spawnInfoDeletionCount = &p.buffer[p.cursor]; + packet_write(&p, &zero, sizeof(u8)); + + // loop through spawn infos + struct SpawnInfo* spawnInfo = area->objectSpawnInfos; + u16 spawnInfoIndex = 0; + + while (spawnInfo != NULL) { + // if a spawn info object was destroyed, send its spawn info index + if (((spawnInfo->behaviorArg >> 8) & RESPAWN_INFO_DONT_RESPAWN) == RESPAWN_INFO_DONT_RESPAWN) { + *spawnInfoDeletionCount = *spawnInfoDeletionCount + 1; + packet_write(&p, &spawnInfoIndex, sizeof(u16)); + LOG_INFO("tx spawn info deletion: index %d", spawnInfoIndex); + } + + spawnInfo = spawnInfo->next; + spawnInfoIndex++; + } + + // send the packet if there are deletions + if (*spawnInfoDeletionCount > 0) { + network_send_to(destNp->localIndex, &p); + LOG_INFO("tx spawn info deletion for area %d (count %d)", areaIndex, *spawnInfoDeletionCount); + } +} + +void network_send_spawn_info_deletions(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_spawn_info_deletions: dest np is invalid"); + return; + } + + for (int i = 0; i < 8; i++) { + network_send_spawn_info_deletions_area(destGlobalIndex, i); + } +} + +void network_receive_spawn_info_deletions(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) { + LOG_ERROR("Receiving 'location response' with the wrong location!"); + return; + } + + u8 thisAreaIndex, spawnInfoDeletionCount; + packet_read(p, &thisAreaIndex, sizeof(u8)); + packet_read(p, &spawnInfoDeletionCount, sizeof(u8)); + LOG_INFO("rx spawn info deletions (count %d)", spawnInfoDeletionCount); + if (spawnInfoDeletionCount <= 0) { return; } + + struct SpawnInfo* spawnInfo = gAreaData[thisAreaIndex].objectSpawnInfos; + u16 spawnInfoIndex = 0; + + u16 spawnInfoDeleteIndex; + packet_read(p, &spawnInfoDeleteIndex, sizeof(u16)); + + while (spawnInfo != NULL && spawnInfoDeletionCount > 0) { + if (spawnInfoIndex == spawnInfoDeleteIndex) { + u32* respawnInfo = &spawnInfo->behaviorArg; + struct Object* o = get_object_matching_respawn_info(respawnInfo); + if (o != NULL) { + obj_mark_for_deletion(o); + LOG_INFO("rx spawn info deletion: object"); + if (o->oSyncID != 0) { + struct SyncObject* so = &gSyncObjects[o->oSyncID]; + if (so->o == o) { + network_forget_sync_object(so); + LOG_INFO("rx spawn info deletion: sync object"); + } + } + } + spawnInfoDeletionCount--; + packet_read(p, &spawnInfoDeleteIndex, sizeof(u16)); + } + + spawnInfo = spawnInfo->next; + spawnInfoIndex++; + } +} \ No newline at end of file