mirror of
				https://github.com/coop-deluxe/sm64coopdx.git
				synced 2025-10-30 08:01:01 +00:00 
			
		
		
		
	Synchronize late-join coin collection
This commit is contained in:
		
							parent
							
								
									4be00a2eb1
								
							
						
					
					
						commit
						5db1a9e827
					
				
					 9 changed files with 86 additions and 12 deletions
				
			
		| 
						 | 
				
			
			@ -529,3 +529,20 @@ 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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -526,5 +526,6 @@ 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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -406,6 +406,7 @@
 | 
			
		|||
#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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -838,6 +838,9 @@ 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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,8 @@
 | 
			
		|||
#include "network.h"
 | 
			
		||||
#include "object_fields.h"
 | 
			
		||||
#include "object_constants.h"
 | 
			
		||||
#include "game/object_list_processor.h"
 | 
			
		||||
#include "behavior_table.h"
 | 
			
		||||
#include "socket/socket.h"
 | 
			
		||||
#ifdef DISCORD_SDK
 | 
			
		||||
#include "discord/discord.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -98,6 +100,15 @@ 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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -173,6 +173,8 @@ 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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,7 +34,7 @@ void network_send_level_area(void) {
 | 
			
		|||
        np->currAreaIndex      = gCurrAreaIndex;
 | 
			
		||||
        np->currAreaSyncValid  = false;
 | 
			
		||||
 | 
			
		||||
        LOG_INFO("set currAreaSyncValid to false");
 | 
			
		||||
        //LOG_INFO("set currAreaSyncValid to false");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //LOG_INFO("tx location: [%d, %d, %d, %d]", gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex);
 | 
			
		||||
| 
						 | 
				
			
			@ -118,7 +118,7 @@ static void network_receive_level_area_valid_server(struct Packet* p) {
 | 
			
		|||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    np->currAreaSyncValid = true;
 | 
			
		||||
    LOG_INFO("set global %d's currAreaSyncValid to true", np->globalIndex);
 | 
			
		||||
    //LOG_INFO("set global %d's currAreaSyncValid to true", np->globalIndex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void network_receive_level_area_valid_client(struct Packet* p) {
 | 
			
		||||
| 
						 | 
				
			
			@ -135,7 +135,7 @@ static void network_receive_level_area_valid_client(struct Packet* p) {
 | 
			
		|||
 | 
			
		||||
    gNetworkPlayerLocal->currAreaSyncValid = true;
 | 
			
		||||
    network_send_level_area_valid_client();
 | 
			
		||||
    LOG_INFO("set currAreaSyncValid to true (3)");
 | 
			
		||||
    //LOG_INFO("set currAreaSyncValid to true (3)");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void network_receive_level_area_valid(struct Packet* p) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +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 "object_constants.h"
 | 
			
		||||
#include "object_fields.h"
 | 
			
		||||
//#define DISABLE_MODULE_LOG 1
 | 
			
		||||
#include "pc/debuglog.h"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -10,6 +14,19 @@ extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
 | 
			
		|||
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; }
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +57,7 @@ void network_send_location_request(void) {
 | 
			
		|||
        struct NetworkPlayer* np = get_network_player_from_valid_location(gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex);
 | 
			
		||||
        if (np == NULL) {
 | 
			
		||||
            gNetworkPlayerLocal->currAreaSyncValid = true;
 | 
			
		||||
            LOG_INFO("set currAreaSyncValid to true (1)");
 | 
			
		||||
            //LOG_INFO("set currAreaSyncValid to true (1)");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        //LOG_INFO("network_send_location_request()");
 | 
			
		||||
| 
						 | 
				
			
			@ -81,7 +98,7 @@ void network_receive_location_request(struct Packet* p) {
 | 
			
		|||
    np->currLevelNum      = levelNum;
 | 
			
		||||
    np->currAreaIndex     = areaIndex;
 | 
			
		||||
    np->currAreaSyncValid = false;
 | 
			
		||||
    LOG_INFO("set global %d's currAreaSyncValid to false", np->globalIndex);
 | 
			
		||||
    //LOG_INFO("set global %d's currAreaSyncValid to false", np->globalIndex);
 | 
			
		||||
 | 
			
		||||
    //LOG_INFO("network_receive_location_request() { %d, %d, %d, %d }", courseNum, actNum, levelNum, areaIndex);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -180,6 +197,11 @@ void network_send_location_response(u8 destGlobalIndex) {
 | 
			
		|||
        packet_write(&p, &sStaticSpawnRemoval[i], sizeof(u8));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    packet_write(&p, &sCoinCollectionIndex, sizeof(u8));
 | 
			
		||||
    for (int i = 0; i < sCoinCollectionIndex; i++) {
 | 
			
		||||
        packet_write(&p, &sCoinCollection[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(destNp->localIndex, &p);
 | 
			
		||||
| 
						 | 
				
			
			@ -202,20 +224,17 @@ void network_receive_location_response(struct Packet* p) {
 | 
			
		|||
    packet_read(p, &levelNum,        sizeof(s16));
 | 
			
		||||
    packet_read(p, &areaIndex,       sizeof(s16));
 | 
			
		||||
 | 
			
		||||
    // TODO: read entities here!
 | 
			
		||||
 | 
			
		||||
    //LOG_INFO("network_receive_location_response() { %d, %d, %d, %d, %d }", destGlobalIndex, courseNum, actNum, levelNum, areaIndex);
 | 
			
		||||
 | 
			
		||||
    if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
 | 
			
		||||
        LOG_ERROR("Receiving 'location response' with the wrong location!");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    // TODO: apply entities!
 | 
			
		||||
 | 
			
		||||
    if (gNetworkType == NT_SERVER) {
 | 
			
		||||
    /*if (gNetworkType == NT_SERVER) {
 | 
			
		||||
        struct NetworkPlayer* srcNp = &gNetworkPlayers[p->localIndex];
 | 
			
		||||
        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!");
 | 
			
		||||
| 
						 | 
				
			
			@ -228,6 +247,7 @@ void network_receive_location_response(struct Packet* p) {
 | 
			
		|||
    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;
 | 
			
		||||
| 
						 | 
				
			
			@ -236,15 +256,33 @@ void network_receive_location_response(struct Packet* p) {
 | 
			
		|||
        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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 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;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    gMarioStates[0].numCoins = numCoins;
 | 
			
		||||
    gNetworkPlayerLocal->currAreaSyncValid = true;
 | 
			
		||||
    LOG_INFO("set currAreaSyncValid to true (2)");
 | 
			
		||||
    //LOG_INFO("set currAreaSyncValid to true (2)");
 | 
			
		||||
    if (gNetworkType != NT_SERVER) {
 | 
			
		||||
        network_send_level_area_valid(0);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -138,6 +138,7 @@ void network_clear_sync_objects(void) {
 | 
			
		|||
    }
 | 
			
		||||
    nextSyncID = 1;
 | 
			
		||||
    static_spawn_removal_clear();
 | 
			
		||||
    coin_collection_clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void network_set_sync_id(struct Object* o) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue