Keep track of static level spawn removals and sync them on location response

This commit is contained in:
MysterD 2021-06-07 19:25:31 -07:00
parent bbdc942501
commit e593bedc77
9 changed files with 142 additions and 63 deletions

View File

@ -176,7 +176,6 @@ void bhv_act_selector_loop(void) {
// This code filters selectable and non-selectable stars.
sSelectedActIndex = 0;
s8 oldIndex = sSelectableStarIndex;
handle_menu_scrolling(MENU_SCROLL_HORIZONTAL, &sSelectableStarIndex, 0, sObtainedStars);
starIndexCounter = sSelectableStarIndex;
@ -192,7 +191,6 @@ void bhv_act_selector_loop(void) {
}
} else {
// If all stars are collected then they are all selectable.
s8 oldIndex = sSelectableStarIndex;
handle_menu_scrolling(MENU_SCROLL_HORIZONTAL, &sSelectableStarIndex, 0, sVisibleStars - 1);
sSelectedActIndex = sSelectableStarIndex;
}

View File

@ -97,7 +97,7 @@ void network_on_loaded_level(void) {
struct NetworkPlayer* np = gNetworkPlayerLocal;
if (np != NULL) {
network_send_level_area();
network_send_entities_request();
network_send_location_request();
}
// request my chunk of reserved sync ids

View File

@ -54,11 +54,11 @@ void packet_receive(struct Packet* p) {
case PACKET_DEATH: network_receive_death(p); break;
case PACKET_LEVEL_AREA: network_receive_level_area(p); break;
case PACKET_LEVEL_AREA_VALID: network_receive_level_area_valid(p); break;
case PACKET_ENTITIES_REQUEST: network_receive_entities_request(p); break;
case PACKET_CLIENT_ENTITIES_REQUEST: network_receive_client_entities_request(p); break;
case PACKET_ENTITIES_RESPONSE: network_receive_entities_response(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_RESPONSE: network_receive_location_response(p); break;
///
case PACKET_CUSTOM: network_receive_custom(p); break;
case PACKET_CUSTOM: network_receive_custom(p); break;
default: LOG_ERROR("received unknown packet: %d", p->buffer[0]);
}
} else {
@ -72,8 +72,7 @@ void packet_receive(struct Packet* p) {
if (!gNetworkPlayers[i].connected) { continue; }
if (i == p->localIndex) { continue; }
struct Packet p2 = { 0 };
packet_init(&p2, packetType, p->reliable, p->levelAreaMustMatch);
packet_write(&p2, &p->buffer[p2.cursor], p->cursor - p2.cursor);
packet_duplicate(p, &p2);
network_send_to(i, &p2);
}
}

View File

@ -32,9 +32,9 @@ enum PacketType {
PACKET_DEATH,
PACKET_LEVEL_AREA,
PACKET_LEVEL_AREA_VALID,
PACKET_ENTITIES_REQUEST,
PACKET_CLIENT_ENTITIES_REQUEST,
PACKET_ENTITIES_RESPONSE,
PACKET_LOCATION_REQUEST,
PACKET_CLIENT_LOCATION_REQUEST,
PACKET_LOCATION_RESPONSE,
///
PACKET_CUSTOM = 255,
};
@ -62,6 +62,7 @@ void packet_receive(struct Packet* packet);
// packet_read_write.c
void packet_init(struct Packet* packet, enum PacketType packetType, bool reliable, bool levelAreaMustMatch);
void packet_duplicate(struct Packet* srcPacket, struct Packet* dstPacket);
void packet_set_flags(struct Packet* packet);
void packet_write(struct Packet* packet, void* data, u16 length);
u8 packet_initial_read(struct Packet* packet);
@ -166,12 +167,14 @@ void network_receive_level_area(struct Packet* p);
void network_send_level_area_valid(u8 toGlobalIndex);
void network_receive_level_area_valid(struct Packet* p);
// packet_entities_request.c
void network_send_entities_request(void);
void network_receive_entities_request(struct Packet* p);
void network_send_client_entities_request(u8 destGlobalIndex, u8 srcGlobalIndex);
void network_receive_client_entities_request(struct Packet* p);
void network_send_entities_response(u8 destGlobalIndex);
void network_receive_entities_response(struct Packet* p);
// packet_location_request.c
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);
void network_send_location_response(u8 destGlobalIndex);
void network_receive_location_response(struct Packet* p);
#endif

View File

@ -8,6 +8,7 @@
#include "src/engine/math_util.h"
#include "src/game/memory.h"
#include "src/game/object_helpers.h"
#include "pc/debuglog.h"
// defined in sparkle_spawn_star.inc.c
void bhv_spawn_star_no_level_exit(struct Object* object, u32 sp20, u8 networkSendEvent);

View File

@ -1,4 +1,5 @@
#include <stdio.h>
#include "level_table.h"
#include "../network.h"
#include "menu/custom_menu_system.h"
//#define DISABLE_MODULE_LOG 1
@ -8,6 +9,11 @@ extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
static u16 currLevelAreaSeqId = 0;
void network_send_level_area(void) {
// override castle act to 0 to prevent instancing of the hub
if (gCurrCourseNum == 0 && (gCurrLevelNum == LEVEL_CASTLE || gCurrLevelNum == LEVEL_CASTLE_GROUNDS || gCurrLevelNum == LEVEL_CASTLE_COURTYARD)) {
gCurrActNum = 0;
}
struct Packet p;
currLevelAreaSeqId++;
packet_init(&p, PACKET_LEVEL_AREA, true, false);

View File

@ -6,6 +6,19 @@
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
#define MAX_STATIC_SPAWN_REMOVAL 256
u8 sStaticSpawnRemoval[MAX_STATIC_SPAWN_REMOVAL] = { 0 };
u8 sStaticSpawnRemovalIndex = 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];
@ -22,7 +35,7 @@ struct NetworkPlayer* get_network_player_from_valid_location(s16 courseNum, s16
///////////////////////////////////////////////////////////////////////////////
void network_send_entities_request(void) {
void network_send_location_request(void) {
if (gNetworkType == NT_SERVER) {
struct NetworkPlayer* np = get_network_player_from_valid_location(gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex);
if (np == NULL) {
@ -30,30 +43,30 @@ void network_send_entities_request(void) {
LOG_INFO("set currAreaSyncValid to true (1)");
return;
}
//LOG_INFO("network_send_entities_request()");
network_send_client_entities_request(gNetworkPlayerLocal->globalIndex, np->globalIndex);
//LOG_INFO("network_send_location_request()");
network_send_client_location_request(gNetworkPlayerLocal->globalIndex, np->globalIndex);
return;
}
struct Packet p;
packet_init(&p, PACKET_ENTITIES_REQUEST, true, false);
packet_init(&p, PACKET_LOCATION_REQUEST, 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));
network_send_to(0, &p);
//LOG_INFO("network_send_entities_request() { %d, %d, %d, %d }", gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex);
//LOG_INFO("network_send_location_request() { %d, %d, %d, %d }", gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex);
}
void network_receive_entities_request(struct Packet* p) {
void network_receive_location_request(struct Packet* p) {
if (gNetworkType != NT_SERVER) {
LOG_ERROR("non-server is receiving an entities request!");
LOG_ERROR("non-server is receiving a location request!");
return;
}
struct NetworkPlayer* np = &gNetworkPlayers[p->localIndex];
if (np == NULL || np->localIndex == UNKNOWN_LOCAL_INDEX || !np->connected) {
LOG_ERROR("Receiving entities request from inactive player!");
LOG_ERROR("Receiving location request from inactive player!");
return;
}
@ -70,54 +83,54 @@ void network_receive_entities_request(struct Packet* p) {
np->currAreaSyncValid = false;
LOG_INFO("set global %d's currAreaSyncValid to false", np->globalIndex);
//LOG_INFO("network_receive_entities_request() { %d, %d, %d, %d }", courseNum, actNum, levelNum, areaIndex);
//LOG_INFO("network_receive_location_request() { %d, %d, %d, %d }", courseNum, actNum, levelNum, areaIndex);
struct NetworkPlayer* np2 = get_network_player_from_valid_location(courseNum, actNum, levelNum, areaIndex);
if (np2 == NULL) {
network_send_level_area_valid(np->globalIndex);
} else if (np2 == gNetworkPlayerLocal) {
network_send_entities_response(np->globalIndex);
network_send_location_response(np->globalIndex);
} else {
network_send_client_entities_request(np->globalIndex, np2->globalIndex);
network_send_client_location_request(np->globalIndex, np2->globalIndex);
}
}
///////////////////////////////////////////////////////////////////////////////
void network_send_client_entities_request(u8 destGlobalIndex, u8 srcGlobalIndex) {
void network_send_client_location_request(u8 destGlobalIndex, u8 srcGlobalIndex) {
if (gNetworkType != NT_SERVER) {
LOG_ERROR("client can't send a 'client entities request'");
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_entities_request: dest np is invalid (global %d)", destGlobalIndex);
LOG_ERROR("network_send_client_location_request: dest np is invalid (global %d)", destGlobalIndex);
return;
}
struct Packet p;
packet_init(&p, PACKET_CLIENT_ENTITIES_REQUEST, true, false);
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));
//LOG_INFO("network_send_client_entities_request() { %d, %d, %d, %d, %d }", destGlobalIndex, destNp->currCourseNum, destNp->currActNum, destNp->currLevelNum, destNp->currAreaIndex);
//LOG_INFO("network_send_client_location_request() { %d, %d, %d, %d, %d }", destGlobalIndex, destNp->currCourseNum, destNp->currActNum, destNp->currLevelNum, destNp->currAreaIndex);
struct NetworkPlayer* srcNp = network_player_from_global_index(srcGlobalIndex);
if (srcNp == NULL || !srcNp->connected || !srcNp->currAreaSyncValid) {
LOG_ERROR("network_send_client_entities_request: source np is invalid (global %d)", srcGlobalIndex);
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_entities_request(struct Packet* p) {
void network_receive_client_location_request(struct Packet* p) {
if (gNetworkType == NT_SERVER) {
LOG_ERROR("server is receiving a 'client entities request'!");
LOG_ERROR("server is receiving a 'client location request'!");
return;
}
@ -129,19 +142,19 @@ void network_receive_client_entities_request(struct Packet* p) {
packet_read(p, &levelNum, sizeof(s16));
packet_read(p, &areaIndex, sizeof(s16));
//LOG_INFO("network_receive_client_entities_request() { %d, %d, %d, %d, %d }", destGlobalIndex, courseNum, actNum, levelNum, areaIndex);
//LOG_INFO("network_receive_client_location_request() { %d, %d, %d, %d, %d }", destGlobalIndex, courseNum, actNum, levelNum, areaIndex);
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
LOG_ERROR("Receiving 'client entities request' with the wrong location!");
LOG_ERROR("Receiving 'client location request' with the wrong location!");
return;
}
network_send_entities_response(destGlobalIndex);
network_send_location_response(destGlobalIndex);
}
///////////////////////////////////////////////////////////////////////////////
void network_send_entities_response(u8 destGlobalIndex) {
void network_send_location_response(u8 destGlobalIndex) {
if (!gNetworkPlayerLocal->currAreaSyncValid) {
LOG_ERROR("my area is invalid");
return;
@ -149,20 +162,26 @@ void network_send_entities_response(u8 destGlobalIndex) {
struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex);
if (destNp == NULL || !destNp->connected) {
LOG_ERROR("network_send_entities_response: dest np is invalid");
LOG_ERROR("network_send_location_response: dest np is invalid");
return;
}
struct Packet p;
packet_init(&p, PACKET_ENTITIES_RESPONSE, true, false);
packet_init(&p, PACKET_LOCATION_RESPONSE, true, false);
packet_write(&p, &destGlobalIndex, sizeof(u8));
packet_write(&p, &gCurrCourseNum, sizeof(s16));
packet_write(&p, &gCurrActNum, sizeof(s16));
packet_write(&p, &gCurrLevelNum, sizeof(s16));
packet_write(&p, &gCurrAreaIndex, sizeof(s16));
// TODO: write entities here!
//LOG_INFO("network_send_entities_response() { %d, %d, %d, %d, %d } to: %d", destGlobalIndex, gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex, (gNetworkType == NT_SERVER) ? destNp->localIndex : 0);
packet_write(&p, &gMarioStates[0].numCoins, sizeof(s16));
packet_write(&p, &sStaticSpawnRemovalIndex, sizeof(u8));
for (int i = 0; i < sStaticSpawnRemovalIndex; i++) {
packet_write(&p, &sStaticSpawnRemoval[i], sizeof(u8));
}
//LOG_INFO("network_send_location_response() { %d, %d, %d, %d, %d } to: %d", destGlobalIndex, gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex, (gNetworkType == NT_SERVER) ? destNp->localIndex : 0);
network_send_to((gNetworkType == NT_SERVER) ? destNp->localIndex : 0, &p);
@ -172,7 +191,7 @@ void network_send_entities_response(u8 destGlobalIndex) {
}
void network_receive_entities_response(struct Packet* p) {
void network_receive_location_response(struct Packet* p) {
u8 destGlobalIndex;
s16 courseNum, actNum, levelNum, areaIndex;
packet_read(p, &destGlobalIndex, sizeof(u8));
@ -180,50 +199,71 @@ void network_receive_entities_response(struct Packet* p) {
packet_read(p, &actNum, sizeof(s16));
packet_read(p, &levelNum, sizeof(s16));
packet_read(p, &areaIndex, sizeof(s16));
// TODO: read entities here!
//LOG_INFO("network_receive_entities_response() { %d, %d, %d, %d, %d }", destGlobalIndex, courseNum, actNum, levelNum, areaIndex);
//LOG_INFO("network_receive_location_response() { %d, %d, %d, %d, %d }", destGlobalIndex, courseNum, actNum, levelNum, areaIndex);
if (gNetworkType == NT_SERVER && gNetworkPlayerLocal->globalIndex != destGlobalIndex) {
// recreate packet and send to destination
struct Packet p2;
packet_init(&p2, PACKET_ENTITIES_RESPONSE, true, false);
packet_write(&p2, &destGlobalIndex, sizeof(u8));
packet_write(&p2, &courseNum, sizeof(s16));
packet_write(&p2, &actNum, sizeof(s16));
packet_write(&p2, &levelNum, sizeof(s16));
packet_write(&p2, &areaIndex, sizeof(s16));
// TODO: write entities here!
packet_duplicate(p, &p2);
struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex);
if (destNp == NULL || !destNp->connected) {
LOG_ERROR("network_receive_entities_response: dest np is invalid");
LOG_ERROR("network_receive_location_response: dest np is invalid");
return;
}
struct NetworkPlayer* srcNp = &gNetworkPlayers[p->localIndex];
LOG_INFO("sending response from global %d to global %d", srcNp->globalIndex, destNp->globalIndex);
LOG_INFO("sending location response from global %d to global %d", srcNp->globalIndex, destNp->globalIndex);
network_send_to(destNp->localIndex, &p2);
return;
} else if (gNetworkPlayerLocal->globalIndex != destGlobalIndex) {
LOG_ERROR("Receiving 'entities response' meant for someone else!");
LOG_ERROR("Receiving 'location response' meant for someone else!");
return;
}
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
LOG_ERROR("Receiving 'entities response' with the wrong location!");
LOG_ERROR("Receiving 'location response' with the wrong location!");
return;
}
// TODO: apply entities!
if (gNetworkType == NT_SERVER) {
struct NetworkPlayer* srcNp = &gNetworkPlayers[p->localIndex];
LOG_INFO("sending response from global %d to global %d", srcNp->globalIndex, gNetworkPlayerLocal->globalIndex);
LOG_INFO("sending location response from global %d to global %d", srcNp->globalIndex, gNetworkPlayerLocal->globalIndex);
}
if (gNetworkPlayerLocal->currAreaSyncValid) {
LOG_ERROR("Receiving 'location response' when our location is already valid!");
return;
}
s16 numCoins;
packet_read(p, &numCoins, sizeof(s16));
u8 staticSpawnRemovals;
static_spawn_removal_clear();
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);
LOG_INFO("marking for deletion: %d", syncId);
}
network_forget_sync_object(so);
}
}
gMarioStates[0].numCoins = numCoins;
gNetworkPlayerLocal->currAreaSyncValid = true;
LOG_INFO("set currAreaSyncValid to true (2)");
if (gNetworkType != NT_SERVER) {
network_send_level_area_valid(0);
}
//LOG_INFO("network_receive_entities_response() ==> valid");
//LOG_INFO("network_receive_location_response() ==> valid");
}

View File

@ -78,6 +78,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;
memset(so->extraFields, 0, sizeof(void*) * MAX_SYNC_OBJECT_FIELDS);
return so;
@ -122,6 +123,7 @@ void network_clear_sync_objects(void) {
network_forget_sync_object(&gSyncObjects[i]);
}
nextSyncID = 1;
static_spawn_removal_clear();
}
void network_set_sync_id(struct Object* o) {
@ -468,6 +470,13 @@ void network_receive_object(struct Packet* p) {
}
void network_forget_sync_object(struct SyncObject* so) {
if (so->staticLevelSpawn && so->o != NULL) {
u8 syncId = so->o->oSyncID;
struct SyncObject* so2 = &gSyncObjects[syncId];
if (so == so2) {
static_spawn_removal_remember(syncId);
}
}
so->o = NULL;
so->behavior = NULL;
so->reserved = 0;

View File

@ -32,12 +32,35 @@ void packet_init(struct Packet* packet, enum PacketType packetType, bool reliabl
if (levelAreaMustMatch) {
packet_write(packet, &gCurrCourseNum, sizeof(s16));
packet_write(packet, &gCurrActNum, sizeof(s16));
packet_write(packet, &gCurrLevelNum, sizeof(s16));
packet_write(packet, &gCurrActNum, sizeof(s16));
packet_write(packet, &gCurrLevelNum, sizeof(s16));
packet_write(packet, &gCurrAreaIndex, sizeof(s16));
}
}
void packet_duplicate(struct Packet* srcPacket, struct Packet* dstPacket) {
memset(dstPacket->buffer, 0, PACKET_LENGTH);
dstPacket->cursor = 0;
dstPacket->dataLength = 0;
dstPacket->error = srcPacket->error;
dstPacket->reliable = srcPacket->reliable;
dstPacket->levelAreaMustMatch = srcPacket->levelAreaMustMatch;
dstPacket->requestBroadcast = srcPacket->requestBroadcast;
dstPacket->sent = false;
memcpy(&dstPacket->buffer[0], &srcPacket->buffer[0], srcPacket->dataLength);
if (dstPacket->reliable) {
dstPacket->seqId = nextSeqNum;
nextSeqNum++;
if (nextSeqNum == 0) { nextSeqNum++; }
}
memcpy(&dstPacket->buffer[1], &dstPacket->seqId, 2);
dstPacket->dataLength = srcPacket->dataLength;
dstPacket->cursor = dstPacket->dataLength;
}
void packet_set_flags(struct Packet* packet) {
u8 flags = 0;
flags |= SET_BIT(packet->levelAreaMustMatch, 0);