Deterministically set the sync ID for level objects that spawn from spawninfo, macros, and special

This commit is contained in:
MysterD 2023-03-26 21:10:38 -07:00
parent 3477206253
commit 2daa6edaa4
9 changed files with 102 additions and 42 deletions

View File

@ -430,6 +430,7 @@ static void level_cmd_begin_area(void) {
gAreas[areaIndex].unk04 = screenArea;
gAreas[areaIndex].numRedCoins = 0;
gAreas[areaIndex].numSecrets = 0;
gAreas[areaIndex].nextSyncID = 10;
if (node != NULL) {
gAreas[areaIndex].camera = (struct Camera *) node->config.camera;
@ -516,6 +517,7 @@ static void level_cmd_init_mario(void) {
spawnInfo->behaviorScript = behaviorScript;
spawnInfo->unk18 = unk18;
spawnInfo->next = NULL;
spawnInfo->syncID = 0;
if (lastSpawnInfo != NULL) {
lastSpawnInfo->next = spawnInfo;
@ -551,6 +553,9 @@ static void level_cmd_place_object(void) {
spawnInfo->unk18 = gLoadedGraphNodes[model];
spawnInfo->next = gAreas[sCurrAreaIndex].objectSpawnInfos;
spawnInfo->syncID = gAreas[sCurrAreaIndex].nextSyncID;
gAreas[sCurrAreaIndex].nextSyncID += 10;
gAreas[sCurrAreaIndex].objectSpawnInfos = spawnInfo;
area_check_red_coin_or_secret(spawnInfo->behaviorScript, false);
}
@ -947,6 +952,10 @@ static void level_cmd_place_object_ext(void) {
spawnInfo->unk18 = gLoadedGraphNodes[model];
spawnInfo->next = gAreas[sCurrAreaIndex].objectSpawnInfos;
spawnInfo->syncID = spawnInfo->next
? spawnInfo->next->syncID + 10
: 10;
gAreas[sCurrAreaIndex].objectSpawnInfos = spawnInfo;
area_check_red_coin_or_secret(spawnInfo->behaviorScript, false);
}
@ -1013,6 +1022,10 @@ static void level_cmd_place_object_ext2(void) {
spawnInfo->unk18 = gLoadedGraphNodes[smlua_model_util_load_with_pool(modelId, sLevelPool)];
spawnInfo->next = gAreas[sCurrAreaIndex].objectSpawnInfos;
spawnInfo->syncID = spawnInfo->next
? spawnInfo->next->syncID + 10
: 10;
gAreas[sCurrAreaIndex].objectSpawnInfos = spawnInfo;
area_check_red_coin_or_secret(spawnInfo->behaviorScript, false);
}

View File

@ -86,6 +86,7 @@ struct Area
/*????*/ u8 *macroObjectsAltered;
/*????*/ u8 numRedCoins;
/*????*/ u8 numSecrets;
/*????*/ u32 nextSyncID;
};
// All the transition data to be used in screen_transition.c

View File

@ -10,7 +10,7 @@
#include "macro_presets.h"
#include "special_presets.h"
#include "src/pc/network/sync_object.h"
/*
* Converts the rotation value supplied by macro objects into one
* that can be used by in-game objects.
@ -43,14 +43,16 @@ s16 convert_rotation(s16 inRotation) {
* parameters filling up the upper 2 bytes of newObj->oBehParams.
* The object will not spawn if 'behavior' is NULL.
*/
void spawn_macro_abs_yrot_2params(s32 model, const BehaviorScript *behavior, s16 x, s16 y, s16 z, s16 ry, s16 params) {
struct Object* spawn_macro_abs_yrot_2params(s32 model, const BehaviorScript *behavior, s16 x, s16 y, s16 z, s16 ry, s16 params) {
if (behavior != NULL) {
struct Object *newObj = spawn_object_abs_with_rot(
&gMacroObjectDefaultParent, 0, model, behavior, x, y, z, 0, convert_rotation(ry), 0);
if (newObj != NULL) {
newObj->oBehParams = ((u32) params) << 16;
}
return newObj;
}
return NULL;
}
/*
@ -58,30 +60,34 @@ void spawn_macro_abs_yrot_2params(s32 model, const BehaviorScript *behavior, s16
* a single parameter filling up the upper byte of newObj->oBehParams.
* The object will not spawn if 'behavior' is NULL.
*/
void spawn_macro_abs_yrot_param1(s32 model, const BehaviorScript *behavior, s16 x, s16 y, s16 z, s16 ry, s16 param) {
struct Object* spawn_macro_abs_yrot_param1(s32 model, const BehaviorScript *behavior, s16 x, s16 y, s16 z, s16 ry, s16 param) {
if (behavior != NULL) {
struct Object *newObj = spawn_object_abs_with_rot(
&gMacroObjectDefaultParent, 0, model, behavior, x, y, z, 0, convert_rotation(ry), 0);
if (newObj != NULL) {
newObj->oBehParams = ((u32) param) << 24;
}
return newObj;
}
return NULL;
}
/*
* Spawns an object at an absolute location with currently 3 unknown variables that get converted to
* floats. Oddly enough, this function doesn't care if 'behavior' is NULL or not.
*/
void spawn_macro_abs_special(s32 model, const BehaviorScript *behavior, s16 x, s16 y, s16 z, s16 unkA, s16 unkB,
struct Object* spawn_macro_abs_special(s32 model, const BehaviorScript *behavior, s16 x, s16 y, s16 z, s16 unkA, s16 unkB,
s16 unkC) {
struct Object *newObj =
spawn_object_abs_with_rot(&gMacroObjectDefaultParent, 0, model, behavior, x, y, z, 0, 0, 0);
if (newObj == NULL) { return; }
if (newObj == NULL) { return NULL; }
// Are all three of these values unused?
newObj->oMacroUnk108 = (f32) unkA;
newObj->oMacroUnk10C = (f32) unkB;
newObj->oMacroUnk110 = (f32) unkC;
return newObj;
}
static void spawn_macro_coin_unknown(const BehaviorScript *behavior, s16 a1[]) {
@ -174,8 +180,12 @@ void spawn_macro_objects(s16 areaIndex, s16 *macroObjList) {
newObj->respawnInfoType = RESPAWN_INFO_TYPE_16;
newObj->respawnInfo = macroObjList - 1;
newObj->parentObj = newObj;
newObj->oSyncID = gAreas[areaIndex].nextSyncID;
sync_object_set_id(newObj);
}
}
gAreas[areaIndex].nextSyncID += 10;
}
}
@ -209,39 +219,47 @@ void spawn_macro_objects_hardcoded(s16 areaIndex, s16 *macroObjList) {
// Spawn objects based on hardcoded presets, and most seem to be for Big Boo's Haunt.
// However, BBH doesn't use this function so this might just be an early test?
struct Object* obj = NULL;
switch (macroObjPreset) {
case 0:
spawn_macro_abs_yrot_2params(MODEL_NONE, bhvBooBossSpawnedBridge, macroObjX, macroObjY,
macroObjZ, macroObjRY, 0);
obj = spawn_macro_abs_yrot_2params(MODEL_NONE, bhvBooBossSpawnedBridge, macroObjX, macroObjY,
macroObjZ, macroObjRY, 0);
break;
case 1:
spawn_macro_abs_yrot_2params(MODEL_BBH_TILTING_FLOOR_PLATFORM,
bhvBbhTiltingTrapPlatform, macroObjX, macroObjY, macroObjZ,
macroObjRY, 0);
obj = spawn_macro_abs_yrot_2params(MODEL_BBH_TILTING_FLOOR_PLATFORM,
bhvBbhTiltingTrapPlatform, macroObjX, macroObjY, macroObjZ,
macroObjRY, 0);
break;
case 2:
spawn_macro_abs_yrot_2params(MODEL_BBH_TUMBLING_PLATFORM, bhvBbhTumblingBridge,
macroObjX, macroObjY, macroObjZ, macroObjRY, 0);
obj = spawn_macro_abs_yrot_2params(MODEL_BBH_TUMBLING_PLATFORM, bhvBbhTumblingBridge,
macroObjX, macroObjY, macroObjZ, macroObjRY, 0);
break;
case 3:
spawn_macro_abs_yrot_2params(MODEL_BBH_MOVING_BOOKSHELF, bhvHauntedBookshelf, macroObjX,
macroObjY, macroObjZ, macroObjRY, 0);
obj = spawn_macro_abs_yrot_2params(MODEL_BBH_MOVING_BOOKSHELF, bhvHauntedBookshelf, macroObjX,
macroObjY, macroObjZ, macroObjRY, 0);
break;
case 4:
spawn_macro_abs_yrot_2params(MODEL_BBH_MESH_ELEVATOR, bhvMeshElevator, macroObjX,
macroObjY, macroObjZ, macroObjRY, 0);
obj = spawn_macro_abs_yrot_2params(MODEL_BBH_MESH_ELEVATOR, bhvMeshElevator, macroObjX,
macroObjY, macroObjZ, macroObjRY, 0);
break;
case 20:
spawn_macro_abs_yrot_2params(MODEL_YELLOW_COIN, bhvYellowCoin, macroObjX, macroObjY,
macroObjZ, macroObjRY, 0);
obj = spawn_macro_abs_yrot_2params(MODEL_YELLOW_COIN, bhvYellowCoin, macroObjX, macroObjY,
macroObjZ, macroObjRY, 0);
break;
case 21:
spawn_macro_abs_yrot_2params(MODEL_YELLOW_COIN, bhvYellowCoin, macroObjX, macroObjY,
macroObjZ, macroObjRY, 0);
obj = spawn_macro_abs_yrot_2params(MODEL_YELLOW_COIN, bhvYellowCoin, macroObjX, macroObjY,
macroObjZ, macroObjRY, 0);
break;
default:
break;
}
if (obj != NULL) {
obj->oSyncID = gAreas[areaIndex].nextSyncID;
sync_object_set_id(obj);
}
gAreas[areaIndex].nextSyncID += 10;
}
}
@ -292,21 +310,22 @@ void spawn_special_objects(s16 areaIndex, s16 **specialObjList) {
type = SpecialObjectPresets[offset].type;
defaultParam = SpecialObjectPresets[offset].defParam;
struct Object* obj = NULL;
switch (type) {
case SPTYPE_NO_YROT_OR_PARAMS:
spawn_macro_abs_yrot_2params(model, behavior, x, y, z, 0, 0);
obj = spawn_macro_abs_yrot_2params(model, behavior, x, y, z, 0, 0);
break;
case SPTYPE_YROT_NO_PARAMS:
extraParams[0] = **specialObjList; // Y-rotation
(*specialObjList)++;
spawn_macro_abs_yrot_2params(model, behavior, x, y, z, extraParams[0], 0);
obj = spawn_macro_abs_yrot_2params(model, behavior, x, y, z, extraParams[0], 0);
break;
case SPTYPE_PARAMS_AND_YROT:
extraParams[0] = **specialObjList; // Y-rotation
(*specialObjList)++;
extraParams[1] = **specialObjList; // Params
(*specialObjList)++;
spawn_macro_abs_yrot_2params(model, behavior, x, y, z, extraParams[0], extraParams[1]);
obj = spawn_macro_abs_yrot_2params(model, behavior, x, y, z, extraParams[0], extraParams[1]);
break;
case SPTYPE_UNKNOWN:
extraParams[0] =
@ -318,17 +337,24 @@ void spawn_special_objects(s16 areaIndex, s16 **specialObjList) {
extraParams[2] =
**specialObjList; // Unknown, gets put into obj->oMacroUnk110 as a float
(*specialObjList)++;
spawn_macro_abs_special(model, behavior, x, y, z, extraParams[0], extraParams[1],
extraParams[2]);
obj = spawn_macro_abs_special(model, behavior, x, y, z, extraParams[0], extraParams[1],
extraParams[2]);
break;
case SPTYPE_DEF_PARAM_AND_YROT:
extraParams[0] = **specialObjList; // Y-rotation
(*specialObjList)++;
spawn_macro_abs_yrot_param1(model, behavior, x, y, z, extraParams[0], defaultParam);
obj = spawn_macro_abs_yrot_param1(model, behavior, x, y, z, extraParams[0], defaultParam);
break;
default:
break;
}
if (obj != NULL) {
obj->oSyncID = gAreas[areaIndex].nextSyncID;
sync_object_set_id(obj);
}
gAreas[areaIndex].nextSyncID += 10;
}
}

View File

@ -7,9 +7,9 @@
s16 convert_rotation(s16 inRotation);
void spawn_macro_abs_yrot_2params(s32 model, const BehaviorScript *behavior, s16 x, s16 y, s16 z, s16 ry, s16 params);
void spawn_macro_abs_yrot_param1(s32 model, const BehaviorScript *behavior, s16 x, s16 y, s16 z, s16 ry, s16 params);
void spawn_macro_abs_special(s32 model, const BehaviorScript *behavior, s16 x, s16 y, s16 z, s16 unkA, s16 unkB, s16 unkC);
struct Object* spawn_macro_abs_yrot_2params(s32 model, const BehaviorScript *behavior, s16 x, s16 y, s16 z, s16 ry, s16 params);
struct Object* spawn_macro_abs_yrot_param1(s32 model, const BehaviorScript *behavior, s16 x, s16 y, s16 z, s16 ry, s16 params);
struct Object* spawn_macro_abs_special(s32 model, const BehaviorScript *behavior, s16 x, s16 y, s16 z, s16 unkA, s16 unkB, s16 unkC);
void spawn_macro_objects(s16 areaIndex, s16 *macroObjList);
void spawn_macro_objects_hardcoded(s16 areaIndex, s16 *macroObjList);

View File

@ -554,6 +554,12 @@ void spawn_objects_from_info(UNUSED s32 unused, struct SpawnInfo *spawnInfo) {
object->behavior = smlua_override_behavior(script);
object->unused1 = 0;
// set the sync id
if (spawnInfo->syncID) {
object->oSyncID = spawnInfo->syncID;
sync_object_set_id(object);
}
// Record death/collection in the SpawnInfo
object->respawnInfoType = RESPAWN_INFO_TYPE_32;
object->respawnInfo = &spawnInfo->behaviorArg;

View File

@ -32,6 +32,8 @@ static bool sHoldingShift = false;
#define SCANCODE_ALT 0x38
#define SCANCODE_SHIFT 0x2A
extern void print_sync_object_table(void);
static void debug_breakpoint_here(void) {
// create easy breakpoint position for debugging
}
@ -103,12 +105,13 @@ void debug_keyboard_on_key_down(int scancode) {
case SCANCODE_ALT: sHoldingAlt = true; break;
case SCANCODE_SHIFT: sHoldingShift = true; break;
case SCANCODE_3: debug_breakpoint_here(); break;
case SCANCODE_1: if (sHoldingAlt) { debug_warp_level1(); } break;
case SCANCODE_2: if (sHoldingAlt) { debug_warp_level2(); } break;
case SCANCODE_4: if (sHoldingAlt) { debug_warp_level3(); } break;
case SCANCODE_8: if (sHoldingAlt) { debug_spawn_object(); } break;
case SCANCODE_9: if (sHoldingAlt) { debug_warp_to(); } break;
case SCANCODE_0: if (sHoldingAlt) { debug_suicide(); } break;
case SCANCODE_1: if (sHoldingAlt) { debug_warp_level1(); } break;
case SCANCODE_2: if (sHoldingAlt) { debug_warp_level2(); } break;
case SCANCODE_4: if (sHoldingAlt) { debug_warp_level3(); } break;
case SCANCODE_5: if (sHoldingAlt) { print_sync_object_table(); } break;
case SCANCODE_8: if (sHoldingAlt) { debug_spawn_object(); } break;
case SCANCODE_9: if (sHoldingAlt) { debug_warp_to(); } break;
case SCANCODE_0: if (sHoldingAlt) { debug_suicide(); } break;
case SCANCODE_F5: debug_reload_lua(); break;
}
}

View File

@ -2,12 +2,15 @@
#include "behavior_table.h"
#include "pc/debuglog.h"
static void print_sync_object_table(void) {
void print_sync_object_table(void) {
LOG_INFO("Sync Object Table");
for (struct SyncObject* so = sync_object_get_first(); so != NULL; so = sync_object_get_next()) {
for (u32 i = 0; i < SYNC_ID_BLOCK_SIZE * (MAX_PLAYERS + 1); i++) {
struct SyncObject* so = sync_object_get(i);
if (!so || !so->o) { continue; }
u32 behaviorId = get_id_from_behavior(so->behavior);
LOG_INFO("%03d: %08X", so->id, behaviorId);
char* behaviorName = (char*)get_behavior_name_from_id(behaviorId);
if (!behaviorName) { behaviorName = "UNKNOWN"; }
LOG_INFO("%04d: %08X :: %s", so->id, behaviorId, behaviorName);
behaviorId = behaviorId; // suppress warning
}
LOG_INFO(" ");
@ -37,7 +40,7 @@ void network_receive_debug_sync(struct Packet* p) {
struct SyncObject* so = sync_object_get(id);
if (!so) {
LOG_INFO("Sync Table Missing: %03d : %08X :: %s", id, behaviorId, behaviorName);
LOG_INFO("Sync Table Missing: %04d : %08X :: %s", id, behaviorId, behaviorName);
return;
}
@ -46,7 +49,7 @@ void network_receive_debug_sync(struct Packet* p) {
if (!localBehaviorName) { localBehaviorName = "UNKNOWN"; }
if (localBehaviorId != behaviorId) {
LOG_INFO("Sync Table MisMatch: %03d : %08X != %08X :: (%s != %s)", id, localBehaviorId, behaviorId, localBehaviorName, behaviorName);
LOG_INFO("Sync Table MisMatch: %04d : %08X != %08X :: (%s != %s)", id, localBehaviorId, behaviorId, localBehaviorName, behaviorName);
return;
}

View File

@ -27,7 +27,7 @@ struct SyncObjectForgetEntry {
};
struct SyncObjectForgetEntry* sForgetList = NULL;
static u32 sNextSyncId = 0;
static u32 sNextSyncId = SYNC_ID_BLOCK_SIZE / 2;
static u32 sIterateIndex = 0;
static bool sFreeingAll = false;
@ -72,7 +72,7 @@ void sync_objects_update(void) {
}
void sync_objects_clear(void) {
sNextSyncId = 0;
sNextSyncId = SYNC_ID_BLOCK_SIZE / 2;
network_on_init_area();
sFreeingAll = true;

8
src/pc/network/syncid.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef SYNCID_H
#define SYNCID_H
struct SyncIdPool {
};
#endif