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