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
This commit is contained in:
MysterD 2021-06-09 22:35:34 -07:00
parent 6e7c542068
commit 0b3a97d405
26 changed files with 1045 additions and 744 deletions

View file

@ -3968,10 +3968,15 @@
<ClCompile Include="..\src\pc\network\packets\packet_collect_star.c" />
<ClCompile Include="..\src\pc\network\packets\packet_custom.c" />
<ClCompile Include="..\src\pc\network\packets\packet_death.c" />
<ClCompile Include="..\src\pc\network\packets\packet_location_request.c" />
<ClCompile Include="..\src\pc\network\packets\packet_kick.c" />
<ClCompile Include="..\src\pc\network\packets\packet_join.c" />
<ClCompile Include="..\src\pc\network\packets\packet_keep_alive.c" />
<ClCompile Include="..\src\pc\network\packets\packet_leaving.c" />
<ClCompile Include="..\src\pc\network\packets\packet_level_area.c" />
<ClCompile Include="..\src\pc\network\packets\packet_location_request_client.c" />
<ClCompile Include="..\src\pc\network\packets\packet_location_response.c" />
<ClCompile Include="..\src\pc\network\packets\packet_macro_deletions.c" />
<ClCompile Include="..\src\pc\network\packets\packet_network_players.c" />
<ClCompile Include="..\src\pc\network\packets\packet_object.c" />
<ClCompile Include="..\src\pc\network\packets\packet_player.c" />
@ -3979,6 +3984,7 @@
<ClCompile Include="..\src\pc\network\packets\packet_reliable.c" />
<ClCompile Include="..\src\pc\network\packets\packet_reservation.c" />
<ClCompile Include="..\src\pc\network\packets\packet_save_file.c" />
<ClCompile Include="..\src\pc\network\packets\packet_spawn_info_deletions.c" />
<ClCompile Include="..\src\pc\network\packets\packet_spawn_objects.c" />
<ClCompile Include="..\src\pc\network\packets\packet_spawn_star.c" />
<ClCompile Include="..\src\pc\network\socket\socket.c" />

View file

@ -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;
}

View file

@ -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 &

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}

370
src/game/macro_presets.c Normal file
View file

@ -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}
};

View file

@ -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);

View file

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

View file

@ -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) {

View file

@ -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) {

View file

@ -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);

View file

@ -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]);

View file

@ -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

View file

@ -1,62 +1,10 @@
#include <stdio.h>
#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);
}
}

View file

@ -0,0 +1,57 @@
#include <stdio.h>
#include "../network.h"
//#define DISABLE_MODULE_LOG 1
#include "pc/debuglog.h"
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
void network_send_location_request_client(u8 destGlobalIndex, u8 srcGlobalIndex) {
if (gNetworkType != NT_SERVER) {
LOG_ERROR("client can't send a 'client location request'");
return;
}
struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex);
if (destNp == NULL || !destNp->connected) {
LOG_ERROR("network_send_client_location_request: dest np is invalid (global %d)", destGlobalIndex);
return;
}
struct Packet p;
packet_init(&p, PACKET_LOCATION_REQUEST_CLIENT, true, false);
packet_write(&p, &destGlobalIndex, sizeof(u8));
packet_write(&p, &destNp->currCourseNum, sizeof(s16));
packet_write(&p, &destNp->currActNum, sizeof(s16));
packet_write(&p, &destNp->currLevelNum, sizeof(s16));
packet_write(&p, &destNp->currAreaIndex, sizeof(s16));
struct NetworkPlayer* srcNp = network_player_from_global_index(srcGlobalIndex);
if (srcNp == NULL || !srcNp->connected || !srcNp->currAreaSyncValid) {
LOG_ERROR("network_send_client_location_request: source np is invalid (global %d)", srcGlobalIndex);
return;
}
network_send_to(srcNp->localIndex, &p);
}
void network_receive_location_request_client(struct Packet* p) {
if (gNetworkType == NT_SERVER) {
LOG_ERROR("server is receiving a 'client location request'!");
return;
}
u8 destGlobalIndex;
s16 courseNum, actNum, levelNum, areaIndex;
packet_read(p, &destGlobalIndex, sizeof(u8));
packet_read(p, &courseNum, sizeof(s16));
packet_read(p, &actNum, sizeof(s16));
packet_read(p, &levelNum, sizeof(s16));
packet_read(p, &areaIndex, sizeof(s16));
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
LOG_ERROR("Receiving 'client location request' with the wrong location!");
return;
}
network_send_location_response(destGlobalIndex);
}

View file

@ -0,0 +1,189 @@
#include <stdio.h>
#include "../network.h"
#include "game/interaction.h"
#include "game/object_list_processor.h"
#include "game/object_helpers.h"
#include "game/interaction.h"
#include "game/level_update.h"
#include "game/macro_special_objects.h"
#include "object_constants.h"
#include "object_fields.h"
#include "behavior_table.h"
#include "model_ids.h"
//#define DISABLE_MODULE_LOG 1
#include "pc/debuglog.h"
void network_send_location_response(u8 destGlobalIndex) {
if (!gNetworkPlayerLocal->currAreaSyncValid) {
LOG_ERROR("my area is invalid");
return;
}
struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex);
if (destNp == NULL || !destNp->connected) {
LOG_ERROR("network_send_location_response: dest np is invalid");
return;
}
struct Packet p;
packet_init(&p, PACKET_LOCATION_RESPONSE, true, false);
packet_write(&p, &gCurrCourseNum, sizeof(s16));
packet_write(&p, &gCurrActNum, sizeof(s16));
packet_write(&p, &gCurrLevelNum, sizeof(s16));
packet_write(&p, &gCurrAreaIndex, sizeof(s16));
// level variables
packet_write(&p, &gMarioStates[0].numCoins, sizeof(s16));
packet_write(&p, &gPssSlideStarted, sizeof(u8));
packet_write(&p, &gHudDisplay.timer, sizeof(u16));
// respawners
u8 respawnerCount = 0;
for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
struct SyncObject* so = &gSyncObjects[i];
if (so == NULL || so->o == NULL || so->o->behavior != bhvRespawner) { continue; }
respawnerCount++;
}
packet_write(&p, &respawnerCount, sizeof(u8));
for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
struct SyncObject* so = &gSyncObjects[i];
if (so == NULL || so->o == NULL || so->o->behavior != bhvRespawner) { continue; }
u32 behaviorToRespawn = get_id_from_behavior(so->o->oRespawnerBehaviorToRespawn);
packet_write(&p, &so->o->oPosX, sizeof(f32));
packet_write(&p, &so->o->oPosY, sizeof(f32));
packet_write(&p, &so->o->oPosZ, sizeof(f32));
packet_write(&p, &so->o->oBehParams, sizeof(s32));
packet_write(&p, &so->o->oRespawnerModelToRespawn, sizeof(s32));
packet_write(&p, &so->o->oRespawnerMinSpawnDist, sizeof(f32));
packet_write(&p, &behaviorToRespawn, sizeof(s32));
packet_write(&p, &so->o->oSyncID, sizeof(u32));
LOG_INFO("tx respawner");
}
network_send_to(destNp->localIndex, &p);
// send macro deletions
network_send_macro_deletions(destGlobalIndex);
// send spawn info
network_send_spawn_info_deletions(destGlobalIndex);
// send non-static objects
for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
struct SyncObject* so = &gSyncObjects[i];
if (so == NULL || so->o == NULL || so->o->oSyncID != i) { continue; }
if (so->staticLevelSpawn) { continue; }
if (so->o->behavior == bhvRespawner) { continue; }
struct Object* spawn_objects[] = { so->o };
// TODO: move find model to a utility file/function
// find model
u32 model = 0;
for (int j = 0; j < 256; j++) {
if (so->o->header.gfx.sharedChild == gLoadedGraphNodes[j]) {
model = j;
break;
}
}
u32 models[] = { model };
network_send_spawn_objects_to(destNp->localIndex, spawn_objects, models, 1);
LOG_INFO("tx non-static");
}
// send last reliable ent packet
for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
struct SyncObject* so = &gSyncObjects[i];
if (so == NULL || so->o == NULL) { continue; }
struct Packet* entPacket = get_last_sync_ent_reliable_packet(i);
if (entPacket->error) { continue; }
struct Packet p2 = { 0 };
packet_duplicate(entPacket, &p2);
network_send_to(destNp->localIndex, &p2);
}
LOG_INFO("tx location response");
}
void network_receive_location_response(struct Packet* p) {
s16 courseNum, actNum, levelNum, areaIndex;
packet_read(p, &courseNum, sizeof(s16));
packet_read(p, &actNum, sizeof(s16));
packet_read(p, &levelNum, sizeof(s16));
packet_read(p, &areaIndex, sizeof(s16));
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
LOG_ERROR("Receiving 'location response' with the wrong location!");
return;
}
if (gNetworkPlayerLocal->currAreaSyncValid) {
LOG_ERROR("Receiving 'location response' when our location is already valid!");
return;
}
s16 numCoins;
packet_read(p, &numCoins, sizeof(s16));
u8 pssSlideStarted;
u16 hudDisplayTimer;
packet_read(p, &pssSlideStarted, sizeof(u8));
packet_read(p, &hudDisplayTimer, sizeof(u16));
if (pssSlideStarted) {
level_control_timer(TIMER_CONTROL_SHOW);
level_control_timer(TIMER_CONTROL_START);
gPssSlideStarted = TRUE;
gHudDisplay.timer = hudDisplayTimer;
}
// read respawners
u8 respawnerCount = 0;
packet_read(p, &respawnerCount, sizeof(u8));
for (int i = 0; i < respawnerCount; i++) {
f32 posX, posY, posZ;
packet_read(p, &posX, sizeof(f32));
packet_read(p, &posY, sizeof(f32));
packet_read(p, &posZ, sizeof(f32));
s32 behParams, respawnerModelToRespawn;
packet_read(p, &behParams, sizeof(s32));
packet_read(p, &respawnerModelToRespawn, sizeof(s32));
f32 respawnerMinSpawnDist;
packet_read(p, &respawnerMinSpawnDist, sizeof(f32));
u32 behaviorToRespawn, syncId;
packet_read(p, &behaviorToRespawn, sizeof(u32));
packet_read(p, &syncId, sizeof(u32));
struct SyncObject* so = &gSyncObjects[syncId];
LOG_INFO("rx respawner");
if (so->staticLevelSpawn) {
struct Object* respawner = spawn_object_abs_with_rot(gMarioStates[0].marioObj, 0, MODEL_NONE, bhvRespawner, posX, posY, posZ, 0, 0, 0);
respawner->parentObj = respawner;
respawner->oBehParams = behParams;
respawner->oRespawnerModelToRespawn = respawnerModelToRespawn;
respawner->oRespawnerMinSpawnDist = respawnerMinSpawnDist;
respawner->oRespawnerBehaviorToRespawn = get_behavior_from_id(behaviorToRespawn);
respawner->oSyncID = syncId;
struct Object* o = so->o;
o->oSyncID = 0;
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
so->o = respawner;
LOG_INFO("rx respawner replaced!");
}
}
gMarioStates[0].numCoins = numCoins;
gNetworkPlayerLocal->currAreaSyncValid = true;
if (gNetworkType != NT_SERVER) {
network_send_level_area_valid(0);
}
LOG_INFO("rx location response");
}

View file

@ -0,0 +1,205 @@
#include <stdio.h>
#include "../network.h"
#include "game/interaction.h"
#include "game/object_list_processor.h"
#include "game/object_helpers.h"
#include "game/interaction.h"
#include "game/level_update.h"
#include "game/macro_special_objects.h"
#include "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, &macroDeletionCount, 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, &macroSpecialCount, 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");
}
}
}
}

View file

@ -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) {

View file

@ -0,0 +1,140 @@
#include <stdio.h>
#include "../network.h"
#include "game/interaction.h"
#include "game/object_list_processor.h"
#include "game/object_helpers.h"
#include "game/interaction.h"
#include "game/level_update.h"
#include "game/macro_special_objects.h"
#include "object_constants.h"
#include "object_fields.h"
#include "behavior_table.h"
#include "model_ids.h"
#define DISABLE_MODULE_LOG 1
#include "pc/debuglog.h"
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++;
}
}