mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-04-27 04:21:42 +00:00
Complete rewrite of entity ID reservation system
Now "syncId"s can only be reserved at ID 127+. This ensures that static level objects and spawned reserved objects never clash. The server keeps track of every player's list of reserved IDs, as well as when an ID is used, or when an entity using that ID is destroyed. This is much more complicated than it used to be, but this complication is required due to players being allowed to be in different areas of the game.
This commit is contained in:
parent
fde6eaf0a3
commit
7ae26b3ea0
20 changed files with 692 additions and 146 deletions
|
|
@ -3859,6 +3859,7 @@
|
|||
<ClCompile Include="..\src\game\interaction.c" />
|
||||
<ClCompile Include="..\src\game\level_geo.c" />
|
||||
<ClCompile Include="..\src\game\level_update.c" />
|
||||
<ClCompile Include="..\src\game\macro_presets.c" />
|
||||
<ClCompile Include="..\src\game\macro_special_objects.c" />
|
||||
<ClCompile Include="..\src\game\main.c" />
|
||||
<ClCompile Include="..\src\game\mario.c" />
|
||||
|
|
@ -3962,31 +3963,41 @@
|
|||
<ClCompile Include="..\src\pc\network\network.c" />
|
||||
<ClCompile Include="..\src\pc\network\network_player.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_area.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_area_request.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_change_area.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_level.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_level_area_inform.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_level_request.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_change_level.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_chat.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_collect_coin.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_collect_item.c" />
|
||||
<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_level_area_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_level_macro.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_level_respawn_info.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_ordered.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_player.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_read_write.c" />
|
||||
<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_reservation_list.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_reservation_release.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_reservation_use.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_level_spawn_info.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\packets\packet_sync_valid.c" />
|
||||
<ClCompile Include="..\src\pc\network\reservation_area.c" />
|
||||
<ClCompile Include="..\src\pc\network\socket\socket.c" />
|
||||
<ClCompile Include="..\src\pc\network\socket\socket_linux.c" />
|
||||
<ClCompile Include="..\src\pc\network\socket\socket_windows.c" />
|
||||
|
|
@ -4348,6 +4359,7 @@
|
|||
<ClInclude Include="..\src\pc\network\discord\user.h" />
|
||||
<ClInclude Include="..\src\pc\network\network.h" />
|
||||
<ClInclude Include="..\src\pc\network\network_player.h" />
|
||||
<ClInclude Include="..\src\pc\network\reservation_area.h" />
|
||||
<ClInclude Include="..\src\pc\network\socket\socket.h" />
|
||||
<ClInclude Include="..\src\pc\network\socket\socket_linux.h" />
|
||||
<ClInclude Include="..\src\pc\network\socket\socket_windows.h" />
|
||||
|
|
|
|||
|
|
@ -3436,6 +3436,15 @@
|
|||
<Filter Include="Source Files\src\pc\utils">
|
||||
<UniqueIdentifier>{451cd85d-8a2c-4aa5-87c7-d1415974ba96}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\src\pc\network\packets\location">
|
||||
<UniqueIdentifier>{8503d4ed-8d6c-4888-a861-c50644924389}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\src\pc\network\packets\fundamental">
|
||||
<UniqueIdentifier>{2ffc6d25-bc31-400f-b587-58a915c565e1}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\src\pc\network\packets\reservation-area">
|
||||
<UniqueIdentifier>{9ddfaa87-399e-4f61-aae3-f91af79e14cc}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\actors\amp\anims\anim_0800401C.inc.c">
|
||||
|
|
@ -14964,12 +14973,6 @@
|
|||
<ClCompile Include="..\src\pc\network\packets\packet_player.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_read_write.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_reliable.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_collect_star.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -15006,9 +15009,6 @@
|
|||
<ClCompile Include="..\actors\luigi\model.inc.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_reservation.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_custom.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -15051,9 +15051,6 @@
|
|||
<ClCompile Include="..\src\pc\network\packets\packet_join.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_keep_alive.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -15081,6 +15078,69 @@
|
|||
<ClCompile Include="..\src\pc\network\packets\packet_death.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\game\macro_presets.c">
|
||||
<Filter>Source Files\src\game</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_level.c">
|
||||
<Filter>Source Files\src\pc\network\packets\location</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_level_request.c">
|
||||
<Filter>Source Files\src\pc\network\packets\location</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_sync_valid.c">
|
||||
<Filter>Source Files\src\pc\network\packets\location</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_change_level.c">
|
||||
<Filter>Source Files\src\pc\network\packets\location</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_level_area_request.c">
|
||||
<Filter>Source Files\src\pc\network\packets\location</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_area.c">
|
||||
<Filter>Source Files\src\pc\network\packets\location</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_level_area_inform.c">
|
||||
<Filter>Source Files\src\pc\network\packets\location</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_change_area.c">
|
||||
<Filter>Source Files\src\pc\network\packets\location</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_area_request.c">
|
||||
<Filter>Source Files\src\pc\network\packets\location</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_level_macro.c">
|
||||
<Filter>Source Files\src\pc\network\packets\location</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_level_spawn_info.c">
|
||||
<Filter>Source Files\src\pc\network\packets\location</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_level_respawn_info.c">
|
||||
<Filter>Source Files\src\pc\network\packets\location</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet.c">
|
||||
<Filter>Source Files\src\pc\network\packets\fundamental</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_ordered.c">
|
||||
<Filter>Source Files\src\pc\network\packets\fundamental</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_reliable.c">
|
||||
<Filter>Source Files\src\pc\network\packets\fundamental</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_read_write.c">
|
||||
<Filter>Source Files\src\pc\network\packets\fundamental</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_reservation_use.c">
|
||||
<Filter>Source Files\src\pc\network\packets\reservation-area</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_reservation_release.c">
|
||||
<Filter>Source Files\src\pc\network\packets\reservation-area</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_reservation_list.c">
|
||||
<Filter>Source Files\src\pc\network\packets\reservation-area</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\reservation_area.c">
|
||||
<Filter>Source Files\src\pc\network</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\actors\common0.h">
|
||||
|
|
@ -16051,5 +16111,8 @@
|
|||
<ClInclude Include="..\include\luigi_audio_defines.h">
|
||||
<Filter>Header Files\include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\pc\network\reservation_area.h">
|
||||
<Filter>Header Files\src\pc\network</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -5,6 +5,12 @@
|
|||
#include "game/mario.h"
|
||||
#include "sm64.h"
|
||||
|
||||
#include "object_fields.h"
|
||||
#include "object_constants.h"
|
||||
#include "src/game/object_helpers.h"
|
||||
#include "behavior_data.h"
|
||||
#include "behavior_table.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
static u8 warpToLevel = LEVEL_CCM;
|
||||
|
|
@ -107,6 +113,15 @@ static void debug_suicide(void) {
|
|||
gMarioStates[0].hurtCounter = 31;
|
||||
}
|
||||
|
||||
static void debug_spawn_object(void) {
|
||||
struct Object* box = spawn_object(gMarioStates[0].marioObj, MODEL_BREAKABLE_BOX_SMALL, bhvBreakableBoxSmall);
|
||||
network_set_sync_id(box);
|
||||
|
||||
struct Object* spawn_objects[] = { box };
|
||||
u32 models[] = { MODEL_BREAKABLE_BOX_SMALL };
|
||||
network_send_spawn_objects(spawn_objects, models, 1);
|
||||
}
|
||||
|
||||
void debug_keyboard_on_key_down(int scancode) {
|
||||
scancode = scancode;
|
||||
switch (scancode & 0xFF) {
|
||||
|
|
@ -114,6 +129,7 @@ void debug_keyboard_on_key_down(int scancode) {
|
|||
#ifdef DEVELOPMENT
|
||||
case SCANCODE_6: debug_warp_level(warpToLevel); break;
|
||||
case SCANCODE_7: debug_warp_area(); break;
|
||||
case SCANCODE_8: debug_spawn_object(); break;
|
||||
case SCANCODE_9: debug_warp_to(); break;
|
||||
case SCANCODE_0: debug_suicide(); break;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -112,11 +112,6 @@ void network_on_loaded_level(void) {
|
|||
network_send_change_level();
|
||||
}
|
||||
}
|
||||
|
||||
// request my chunk of reserved sync ids
|
||||
if (gNetworkType == NT_CLIENT) {
|
||||
network_send_reservation_request();
|
||||
}
|
||||
}
|
||||
|
||||
void network_send_to(u8 localIndex, struct Packet* p) {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ struct NetworkSystem {
|
|||
|
||||
struct SyncObject {
|
||||
struct Object* o;
|
||||
u16 reserved;
|
||||
float maxSyncDistance;
|
||||
bool owned;
|
||||
bool staticLevelSpawn;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include "network_player.h"
|
||||
#include "game/chat.h"
|
||||
#include "game/mario_misc.h"
|
||||
#include "reservation_area.h"
|
||||
#include "pc/debuglog.h"
|
||||
|
||||
struct NetworkPlayer gNetworkPlayers[MAX_PLAYERS] = { 0 };
|
||||
|
|
@ -190,6 +191,7 @@ u8 network_player_disconnected(u8 globalIndex) {
|
|||
LOG_INFO("player disconnected, local %d, global %d", i, globalIndex);
|
||||
chat_add_message_ext("player disconnected", CMT_SYSTEM, get_player_color(globalIndex, 0));
|
||||
packet_ordered_clear(globalIndex);
|
||||
reservation_area_change(np);
|
||||
return i;
|
||||
}
|
||||
return UNKNOWN_GLOBAL_INDEX;
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ void packet_process(struct Packet* p) {
|
|||
case PACKET_COLLECT_STAR: network_receive_collect_star(p); break;
|
||||
case PACKET_COLLECT_COIN: network_receive_collect_coin(p); break;
|
||||
case PACKET_COLLECT_ITEM: network_receive_collect_item(p); break;
|
||||
case PACKET_RESERVATION_REQUEST: network_receive_reservation_request(p); break;
|
||||
case PACKET_RESERVATION: network_receive_reservation(p); break;
|
||||
case PACKET_UNUSED1: break;
|
||||
case PACKET_UNUSED2: break;
|
||||
case PACKET_JOIN_REQUEST: network_receive_join_request(p); break;
|
||||
case PACKET_JOIN: network_receive_join(p); break;
|
||||
case PACKET_CHAT: network_receive_chat(p); break;
|
||||
|
|
@ -25,7 +25,12 @@ void packet_process(struct Packet* p) {
|
|||
case PACKET_NETWORK_PLAYERS: network_receive_network_players(p); break;
|
||||
case PACKET_DEATH: network_receive_death(p); break;
|
||||
|
||||
// location
|
||||
// reservation area
|
||||
case PACKET_RESERVATION_LIST: network_receive_reservation_list(p); break;
|
||||
case PACKET_RESERVATION_USE: network_receive_reservation_use(p); break;
|
||||
case PACKET_RESERVATION_RELEASE: network_receive_reservation_release(p); break;
|
||||
|
||||
// location
|
||||
case PACKET_CHANGE_LEVEL: network_receive_change_level(p); break;
|
||||
case PACKET_CHANGE_AREA: network_receive_change_area(p); break;
|
||||
case PACKET_LEVEL_AREA_REQUEST: network_receive_level_area_request(p); break;
|
||||
|
|
@ -39,7 +44,7 @@ void packet_process(struct Packet* p) {
|
|||
case PACKET_LEVEL_AREA_INFORM: network_receive_level_area_inform(p); break;
|
||||
case PACKET_LEVEL_RESPAWN_INFO: network_receive_level_respawn_info(p); break;
|
||||
|
||||
// custom
|
||||
// custom
|
||||
case PACKET_CUSTOM: network_receive_custom(p); break;
|
||||
default: LOG_ERROR("received unknown packet: %d", p->buffer[0]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ enum PacketType {
|
|||
PACKET_COLLECT_STAR,
|
||||
PACKET_COLLECT_COIN,
|
||||
PACKET_COLLECT_ITEM,
|
||||
PACKET_RESERVATION_REQUEST,
|
||||
PACKET_RESERVATION,
|
||||
PACKET_UNUSED1,
|
||||
PACKET_UNUSED2,
|
||||
PACKET_JOIN_REQUEST,
|
||||
PACKET_JOIN,
|
||||
PACKET_CHAT,
|
||||
|
|
@ -34,6 +34,10 @@ enum PacketType {
|
|||
PACKET_NETWORK_PLAYERS,
|
||||
PACKET_DEATH,
|
||||
|
||||
PACKET_RESERVATION_LIST,
|
||||
PACKET_RESERVATION_USE,
|
||||
PACKET_RESERVATION_RELEASE,
|
||||
|
||||
PACKET_CHANGE_LEVEL,
|
||||
PACKET_CHANGE_AREA,
|
||||
PACKET_LEVEL_AREA_REQUEST,
|
||||
|
|
@ -148,12 +152,6 @@ void network_receive_collect_coin(struct Packet* p);
|
|||
void network_send_collect_item(struct Object* o);
|
||||
void network_receive_collect_item(struct Packet* p);
|
||||
|
||||
// packet_reservation.c
|
||||
void network_send_reservation_request(void);
|
||||
void network_receive_reservation_request(struct Packet* p);
|
||||
void network_send_reservation(u8 toLocalIndex);
|
||||
void network_receive_reservation(struct Packet* p);
|
||||
|
||||
// packet_join.c
|
||||
void network_send_join_request(void);
|
||||
void network_receive_join_request(struct Packet* p);
|
||||
|
|
@ -241,4 +239,16 @@ void network_receive_level_area_inform(struct Packet* p);
|
|||
void network_send_level_respawn_info(struct Object* o, u8 respawnInfoBits);
|
||||
void network_receive_level_respawn_info(struct Packet* p);
|
||||
|
||||
// packet_reservation_list.c
|
||||
void network_send_reservation_list(struct NetworkPlayer* np, u8 syncIds[]);
|
||||
void network_receive_reservation_list(struct Packet* p);
|
||||
|
||||
// packet_reservation_use.c
|
||||
void network_send_reservation_use(u8 syncId);
|
||||
void network_receive_reservation_use(struct Packet* p);
|
||||
|
||||
// packet_reservation_release.c
|
||||
void network_send_reservation_release(u8 syncId);
|
||||
void network_receive_reservation_release(struct Packet* p);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include <stdio.h>
|
||||
#include "../network.h"
|
||||
#include "../reservation_area.h"
|
||||
#include "level_table.h"
|
||||
//#define DISABLE_MODULE_LOG 1
|
||||
#include "pc/debuglog.h"
|
||||
|
|
@ -12,6 +13,7 @@ static void player_changed_area(struct NetworkPlayer* np, s16 courseNum, s16 act
|
|||
np->currAreaIndex = areaIndex;
|
||||
np->currAreaSyncValid = false;
|
||||
network_send_level_area_inform(np);
|
||||
reservation_area_change(np);
|
||||
|
||||
// find a NetworkPlayer at that area
|
||||
struct NetworkPlayer* npLevelAreaMatch = get_network_player_from_area(courseNum, actNum, levelNum, areaIndex);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include <stdio.h>
|
||||
#include "../network.h"
|
||||
#include "../reservation_area.h"
|
||||
#include "level_table.h"
|
||||
//#define DISABLE_MODULE_LOG 1
|
||||
#include "pc/debuglog.h"
|
||||
|
|
@ -13,6 +14,7 @@ static void player_changed_level(struct NetworkPlayer* np, s16 courseNum, s16 ac
|
|||
np->currLevelSyncValid = false;
|
||||
np->currAreaSyncValid = false;
|
||||
network_send_level_area_inform(np);
|
||||
reservation_area_change(np);
|
||||
|
||||
// find a NetworkPlayer around that location
|
||||
struct NetworkPlayer* npLevelAreaMatch = get_network_player_from_area(courseNum, actNum, levelNum, areaIndex);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include <stdio.h>
|
||||
#include "../network.h"
|
||||
#include "../reservation_area.h"
|
||||
#include "game/chat.h"
|
||||
#include "pc/debuglog.h"
|
||||
|
||||
|
|
@ -39,6 +40,7 @@ void network_send_chat(char* message, u8 rgb[3]) {
|
|||
|
||||
#ifdef DEVELOPMENT
|
||||
print_network_player_table();
|
||||
reservation_area_debug();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -55,8 +57,9 @@ void network_receive_chat(struct Packet* p) {
|
|||
// add the message
|
||||
chat_add_message_ext(remoteMessage, CMT_REMOTE, rgb);
|
||||
LOG_INFO("rx chat: %s", remoteMessage);
|
||||
|
||||
/*
|
||||
#ifdef DEVELOPMENT
|
||||
print_network_player_table();
|
||||
#endif
|
||||
*/
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include "../network.h"
|
||||
#include "../reservation_area.h"
|
||||
#include "object_fields.h"
|
||||
#include "object_constants.h"
|
||||
#include "behavior_data.h"
|
||||
|
|
@ -10,7 +11,6 @@
|
|||
#include "src/game/obj_behaviors.h"
|
||||
#include "pc/debuglog.h"
|
||||
|
||||
static u8 nextSyncID = 1;
|
||||
struct SyncObject gSyncObjects[MAX_SYNC_OBJECTS] = { 0 };
|
||||
struct Packet sLastSyncEntReliablePacket[MAX_SYNC_OBJECTS] = { 0 };
|
||||
|
||||
|
|
@ -77,7 +77,6 @@ struct SyncObject* network_init_object(struct Object *o, float maxSyncDistance)
|
|||
// set default values for sync object
|
||||
struct SyncObject* so = &gSyncObjects[o->oSyncID];
|
||||
so->o = o;
|
||||
so->reserved = 0;
|
||||
so->maxSyncDistance = maxSyncDistance;
|
||||
so->owned = false;
|
||||
so->clockSinceUpdate = clock();
|
||||
|
|
@ -143,22 +142,28 @@ void network_clear_sync_objects(void) {
|
|||
for (u16 i = 0; i < MAX_SYNC_OBJECTS; i++) {
|
||||
network_forget_sync_object(&gSyncObjects[i]);
|
||||
}
|
||||
nextSyncID = 1;
|
||||
}
|
||||
|
||||
void network_set_sync_id(struct Object* o) {
|
||||
if (o->oSyncID != 0) { return; }
|
||||
|
||||
u8 reserveId = gNetworkLevelLoaded ? gNetworkPlayerLocal->globalIndex : 0;
|
||||
|
||||
for (u16 i = 0; i < MAX_SYNC_OBJECTS; i++) {
|
||||
if (gSyncObjects[nextSyncID].reserved == reserveId && gSyncObjects[nextSyncID].o == NULL) { break; }
|
||||
nextSyncID = (nextSyncID + 1) % MAX_SYNC_OBJECTS;
|
||||
u8 syncId = 0;
|
||||
if (!gNetworkLevelLoaded) {
|
||||
// while loading, just fill in sync ids from 1 to MAX_SYNC_OBJECTS
|
||||
for (int i = 1; i < MAX_SYNC_OBJECTS; i++) {
|
||||
if (gSyncObjects[i].o != NULL) { continue; }
|
||||
syncId = i;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// no longer loading, require reserved id
|
||||
syncId = reservation_area_local_grab_id();
|
||||
}
|
||||
assert(gSyncObjects[nextSyncID].o == NULL);
|
||||
assert(gSyncObjects[nextSyncID].reserved == reserveId);
|
||||
o->oSyncID = nextSyncID;
|
||||
nextSyncID = (nextSyncID + 1) % MAX_SYNC_OBJECTS;
|
||||
|
||||
assert(syncId != 0);
|
||||
assert(gSyncObjects[syncId].o == NULL);
|
||||
|
||||
o->oSyncID = syncId;
|
||||
|
||||
if (gNetworkLevelLoaded) {
|
||||
LOG_INFO("set sync id for object w/behavior %d", get_id_from_behavior(o->behavior));
|
||||
|
|
@ -398,14 +403,15 @@ void network_send_object(struct Object* o) {
|
|||
void network_send_object_reliability(struct Object* o, bool reliable) {
|
||||
// sanity check SyncObject
|
||||
if (!network_sync_object_initialized(o)) { return; }
|
||||
struct SyncObject* so = &gSyncObjects[o->oSyncID];
|
||||
u8 syncId = o->oSyncID;
|
||||
struct SyncObject* so = &gSyncObjects[syncId];
|
||||
if (so == NULL) { return; }
|
||||
if (o != so->o) {
|
||||
LOG_ERROR("object mismatch for %d", o->oSyncID);
|
||||
LOG_ERROR("object mismatch for %d", syncId);
|
||||
return;
|
||||
}
|
||||
if (o->behavior != so->behavior && !allowable_behavior_change(so, so->behavior)) {
|
||||
LOG_ERROR("behavior mismatch for %d: %04X vs %04X", o->oSyncID, get_id_from_behavior(o->behavior), get_id_from_behavior(so->behavior));
|
||||
LOG_ERROR("behavior mismatch for %d: %04X vs %04X", syncId, get_id_from_behavior(o->behavior), get_id_from_behavior(so->behavior));
|
||||
network_forget_sync_object(so);
|
||||
return;
|
||||
}
|
||||
|
|
@ -426,9 +432,14 @@ void network_send_object_reliability(struct Object* o, bool reliable) {
|
|||
// check for object death
|
||||
if (o->activeFlags == ACTIVE_FLAG_DEACTIVATED) {
|
||||
network_forget_sync_object(so);
|
||||
if (gNetworkType == NT_SERVER) {
|
||||
reservation_area_release(gNetworkPlayerLocal, syncId);
|
||||
} else {
|
||||
network_send_reservation_release(syncId);
|
||||
}
|
||||
} else {
|
||||
// remember packet
|
||||
packet_duplicate(&p, &sLastSyncEntReliablePacket[o->oSyncID]);
|
||||
packet_duplicate(&p, &sLastSyncEntReliablePacket[syncId]);
|
||||
}
|
||||
|
||||
// send the packet out
|
||||
|
|
@ -511,12 +522,11 @@ void network_forget_sync_object(struct SyncObject* so) {
|
|||
|
||||
so->o = NULL;
|
||||
so->behavior = NULL;
|
||||
so->reserved = 0;
|
||||
so->owned = false;
|
||||
}
|
||||
|
||||
void network_update_objects(void) {
|
||||
for (u32 i = 1; i < nextSyncID; i++) {
|
||||
for (u32 i = 1; i < MAX_SYNC_OBJECTS; i++) {
|
||||
struct SyncObject* so = &gSyncObjects[i];
|
||||
if (so->o == NULL) { continue; }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,73 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include "../network.h"
|
||||
#include "object_fields.h"
|
||||
#include "object_constants.h"
|
||||
#include "behavior_table.h"
|
||||
#include "course_table.h"
|
||||
#include "src/game/interaction.h"
|
||||
#include "src/engine/math_util.h"
|
||||
#define DISABLE_MODULE_LOG 1
|
||||
#include "pc/debuglog.h"
|
||||
|
||||
#define RESERVATION_COUNT 5
|
||||
|
||||
void network_send_reservation_request(void) {
|
||||
assert(gNetworkType == NT_CLIENT);
|
||||
|
||||
struct Packet p;
|
||||
packet_init(&p, PACKET_RESERVATION_REQUEST, true, false);
|
||||
network_send_to(gNetworkPlayerServer->localIndex , &p);
|
||||
}
|
||||
|
||||
void network_receive_reservation_request(struct Packet* p) {
|
||||
assert(gNetworkType == NT_SERVER);
|
||||
network_send_reservation(p->localIndex);
|
||||
}
|
||||
|
||||
void network_send_reservation(u8 toLocalIndex) {
|
||||
assert(gNetworkType == NT_SERVER);
|
||||
assert(toLocalIndex != 0);
|
||||
|
||||
// find all reserved objects
|
||||
u8 reservedObjs[RESERVATION_COUNT] = { 0 };
|
||||
u16 reservedIndex = 0;
|
||||
for (u16 i = 1; i < MAX_SYNC_OBJECTS; i++) {
|
||||
if (gSyncObjects[i].reserved == toLocalIndex) {
|
||||
reservedObjs[reservedIndex++] = i;
|
||||
if (reservedIndex >= RESERVATION_COUNT) { break; }
|
||||
}
|
||||
}
|
||||
|
||||
if (reservedIndex < RESERVATION_COUNT) {
|
||||
// reserve the rest
|
||||
for (u16 i = MAX_SYNC_OBJECTS - 1; i > 0; i--) {
|
||||
if (gSyncObjects[i].o != NULL) { continue; }
|
||||
if (gSyncObjects[i].reserved != 0) { continue; }
|
||||
gSyncObjects[i].reserved = toLocalIndex;
|
||||
reservedObjs[reservedIndex++] = i;
|
||||
if (reservedIndex >= RESERVATION_COUNT) { break; }
|
||||
}
|
||||
}
|
||||
|
||||
struct Packet p;
|
||||
packet_init(&p, PACKET_RESERVATION, true, false);
|
||||
packet_write(&p, reservedObjs, sizeof(u8) * RESERVATION_COUNT);
|
||||
network_send_to(toLocalIndex, &p);
|
||||
LOG_INFO("sent reservation list to %d", toLocalIndex);
|
||||
}
|
||||
|
||||
void network_receive_reservation(struct Packet* p) {
|
||||
assert(gNetworkType == NT_CLIENT);
|
||||
|
||||
// find all reserved objects
|
||||
u8 reservedObjs[RESERVATION_COUNT] = { 0 };
|
||||
packet_read(p, reservedObjs, sizeof(u8) * RESERVATION_COUNT);
|
||||
|
||||
for (u16 i = 0; i < RESERVATION_COUNT; i++) {
|
||||
u16 index = reservedObjs[i];
|
||||
if (index == 0) { continue; }
|
||||
if (gSyncObjects[index].o != NULL) { continue; }
|
||||
gSyncObjects[index].reserved = gNetworkPlayerLocal->globalIndex;
|
||||
}
|
||||
LOG_INFO("received reservation list");
|
||||
}
|
||||
52
src/pc/network/packets/packet_reservation_list.c
Normal file
52
src/pc/network/packets/packet_reservation_list.c
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#include <stdio.h>
|
||||
#include "../network.h"
|
||||
#include "../reservation_area.h"
|
||||
#include "object_fields.h"
|
||||
#include "object_constants.h"
|
||||
#include "behavior_table.h"
|
||||
#include "course_table.h"
|
||||
#include "src/game/interaction.h"
|
||||
#include "src/engine/math_util.h"
|
||||
#define DISABLE_MODULE_LOG 1
|
||||
#include "pc/debuglog.h"
|
||||
|
||||
void network_send_reservation_list(struct NetworkPlayer* np, u8 syncIds[]) {
|
||||
assert(gNetworkType == NT_SERVER);
|
||||
|
||||
struct Packet p;
|
||||
packet_init(&p, PACKET_RESERVATION_LIST, true, false);
|
||||
|
||||
packet_write(&p, &np->currCourseNum, sizeof(u8));
|
||||
packet_write(&p, &np->currActNum, sizeof(u8));
|
||||
packet_write(&p, &np->currLevelNum, sizeof(u8));
|
||||
packet_write(&p, &np->currAreaIndex, sizeof(u8));
|
||||
|
||||
for (int i = 0; i < RESERVED_IDS_PER_PLAYER_COUNT; i++) {
|
||||
packet_write(&p, &syncIds[i], sizeof(u8));
|
||||
}
|
||||
|
||||
network_send_to(np->localIndex, &p);
|
||||
}
|
||||
|
||||
void network_receive_reservation_list(struct Packet* p) {
|
||||
assert(gNetworkType == NT_CLIENT);
|
||||
|
||||
u8 courseNum, actNum, levelNum, areaIndex;
|
||||
packet_read(p, &courseNum, sizeof(u8));
|
||||
packet_read(p, &actNum, sizeof(u8));
|
||||
packet_read(p, &levelNum, sizeof(u8));
|
||||
packet_read(p, &areaIndex, sizeof(u8));
|
||||
|
||||
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
|
||||
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
|
||||
LOG_ERROR("received an improper location");
|
||||
return;
|
||||
}
|
||||
|
||||
u8 syncIds[RESERVED_IDS_PER_PLAYER_COUNT];
|
||||
for (int i = 0; i < RESERVED_IDS_PER_PLAYER_COUNT; i++) {
|
||||
packet_read(p, &syncIds[i], sizeof(u8));
|
||||
}
|
||||
|
||||
reservation_area_local_update(courseNum, actNum, levelNum, areaIndex, syncIds);
|
||||
}
|
||||
58
src/pc/network/packets/packet_reservation_release.c
Normal file
58
src/pc/network/packets/packet_reservation_release.c
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#include <stdio.h>
|
||||
#include "../network.h"
|
||||
#include "../reservation_area.h"
|
||||
#include "object_fields.h"
|
||||
#include "object_constants.h"
|
||||
#include "behavior_table.h"
|
||||
#include "course_table.h"
|
||||
#include "src/game/interaction.h"
|
||||
#include "src/engine/math_util.h"
|
||||
#define DISABLE_MODULE_LOG 1
|
||||
#include "pc/debuglog.h"
|
||||
|
||||
void network_send_reservation_release(u8 syncId) {
|
||||
assert(gNetworkType == NT_CLIENT);
|
||||
|
||||
// make sure this is a reserved id
|
||||
if (syncId < RESERVED_IDS_SYNC_OBJECT_OFFSET) { return; }
|
||||
|
||||
struct Packet p;
|
||||
packet_init(&p, PACKET_RESERVATION_RELEASE, true, false);
|
||||
|
||||
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
|
||||
packet_write(&p, &gCurrCourseNum, sizeof(u8));
|
||||
packet_write(&p, &gCurrActNum, sizeof(u8));
|
||||
packet_write(&p, &gCurrLevelNum, sizeof(u8));
|
||||
packet_write(&p, &gCurrAreaIndex, sizeof(u8));
|
||||
|
||||
packet_write(&p, &syncId, sizeof(u8));
|
||||
|
||||
network_send_to(gNetworkPlayerServer->localIndex, &p);
|
||||
}
|
||||
|
||||
void network_receive_reservation_release(struct Packet* p) {
|
||||
assert(gNetworkType == NT_SERVER);
|
||||
|
||||
struct NetworkPlayer* np = &gNetworkPlayers[p->localIndex];
|
||||
if (np == NULL || np->localIndex == UNKNOWN_LOCAL_INDEX || !np->connected) {
|
||||
LOG_ERROR("Receiving from inactive player!");
|
||||
return;
|
||||
}
|
||||
|
||||
u8 courseNum, actNum, levelNum, areaIndex;
|
||||
packet_read(p, &courseNum, sizeof(u8));
|
||||
packet_read(p, &actNum, sizeof(u8));
|
||||
packet_read(p, &levelNum, sizeof(u8));
|
||||
packet_read(p, &areaIndex, sizeof(u8));
|
||||
|
||||
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
|
||||
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
|
||||
LOG_ERROR("received an improper location");
|
||||
return;
|
||||
}
|
||||
|
||||
u8 syncId;
|
||||
packet_read(p, &syncId, sizeof(u8));
|
||||
|
||||
reservation_area_release(np, syncId);
|
||||
}
|
||||
58
src/pc/network/packets/packet_reservation_use.c
Normal file
58
src/pc/network/packets/packet_reservation_use.c
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#include <stdio.h>
|
||||
#include "../network.h"
|
||||
#include "../reservation_area.h"
|
||||
#include "object_fields.h"
|
||||
#include "object_constants.h"
|
||||
#include "behavior_table.h"
|
||||
#include "course_table.h"
|
||||
#include "src/game/interaction.h"
|
||||
#include "src/engine/math_util.h"
|
||||
#define DISABLE_MODULE_LOG 1
|
||||
#include "pc/debuglog.h"
|
||||
|
||||
void network_send_reservation_use(u8 syncId) {
|
||||
assert(gNetworkType == NT_CLIENT);
|
||||
|
||||
// make sure this is a reserved id
|
||||
if (syncId < RESERVED_IDS_SYNC_OBJECT_OFFSET) { return; }
|
||||
|
||||
struct Packet p;
|
||||
packet_init(&p, PACKET_RESERVATION_USE, true, false);
|
||||
|
||||
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
|
||||
packet_write(&p, &gCurrCourseNum, sizeof(u8));
|
||||
packet_write(&p, &gCurrActNum, sizeof(u8));
|
||||
packet_write(&p, &gCurrLevelNum, sizeof(u8));
|
||||
packet_write(&p, &gCurrAreaIndex, sizeof(u8));
|
||||
|
||||
packet_write(&p, &syncId, sizeof(u8));
|
||||
|
||||
network_send_to(gNetworkPlayerServer->localIndex, &p);
|
||||
}
|
||||
|
||||
void network_receive_reservation_use(struct Packet* p) {
|
||||
assert(gNetworkType == NT_SERVER);
|
||||
|
||||
struct NetworkPlayer* np = &gNetworkPlayers[p->localIndex];
|
||||
if (np == NULL || np->localIndex == UNKNOWN_LOCAL_INDEX || !np->connected) {
|
||||
LOG_ERROR("Receiving from inactive player!");
|
||||
return;
|
||||
}
|
||||
|
||||
u8 courseNum, actNum, levelNum, areaIndex;
|
||||
packet_read(p, &courseNum, sizeof(u8));
|
||||
packet_read(p, &actNum, sizeof(u8));
|
||||
packet_read(p, &levelNum, sizeof(u8));
|
||||
packet_read(p, &areaIndex, sizeof(u8));
|
||||
|
||||
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
|
||||
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
|
||||
LOG_ERROR("received an improper location");
|
||||
return;
|
||||
}
|
||||
|
||||
u8 syncId;
|
||||
packet_read(p, &syncId, sizeof(u8));
|
||||
|
||||
reservation_area_use(np, syncId);
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#include <stdio.h>
|
||||
#include "../network.h"
|
||||
#include "../reservation_area.h"
|
||||
#include "object_fields.h"
|
||||
#include "object_constants.h"
|
||||
#include "src/game/object_helpers.h"
|
||||
|
|
@ -48,7 +49,16 @@ void network_send_spawn_objects_to(u8 sendToLocalIndex, struct Object* objects[]
|
|||
assert(objectCount < MAX_SPAWN_OBJECTS_PER_PACKET);
|
||||
|
||||
struct Packet p;
|
||||
packet_init(&p, PACKET_SPAWN_OBJECTS, true, true);
|
||||
packet_init(&p, PACKET_SPAWN_OBJECTS, true, false);
|
||||
|
||||
// level location
|
||||
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
|
||||
packet_write(&p, &gCurrCourseNum, sizeof(s16));
|
||||
packet_write(&p, &gCurrActNum, sizeof(s16));
|
||||
packet_write(&p, &gCurrLevelNum, sizeof(s16));
|
||||
packet_write(&p, &gCurrAreaIndex, sizeof(s16));
|
||||
|
||||
// objects
|
||||
packet_write(&p, &objectCount, sizeof(u8));
|
||||
|
||||
for (u8 i = 0; i < objectCount; i++) {
|
||||
|
|
@ -74,13 +84,22 @@ void network_send_spawn_objects_to(u8 sendToLocalIndex, struct Object* objects[]
|
|||
}
|
||||
|
||||
void network_receive_spawn_objects(struct Packet* p) {
|
||||
// read level location
|
||||
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));
|
||||
|
||||
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
|
||||
if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
|
||||
LOG_ERROR("received an improper location");
|
||||
return;
|
||||
}
|
||||
|
||||
u8 objectCount = 0;
|
||||
|
||||
packet_read(p, &objectCount, sizeof(u8));
|
||||
|
||||
u8 reserveId = gNetworkLevelLoaded ? gNetworkPlayers[p->localIndex].globalIndex : 0;
|
||||
bool receivedReservedSyncObject = false;
|
||||
|
||||
struct Object* spawned[MAX_SPAWN_OBJECTS_PER_PACKET] = { 0 };
|
||||
for (u8 i = 0; i < objectCount; i++) {
|
||||
struct SpawnObjectData data = { 0 };
|
||||
|
|
@ -129,20 +148,11 @@ void network_receive_spawn_objects(struct Packet* p) {
|
|||
// correct the temporary parent with the object itself
|
||||
if (data.parentId == (u8)-1) { o->parentObj = o; }
|
||||
|
||||
if (o->oSyncID != 0) {
|
||||
if (o->oSyncID != 0 && o->oSyncID >= RESERVED_IDS_SYNC_OBJECT_OFFSET) {
|
||||
// check if they've allocated one of their reserved sync objects
|
||||
receivedReservedSyncObject = (o->oSyncID != 0 && gSyncObjects[o->oSyncID].reserved == reserveId);
|
||||
if (receivedReservedSyncObject || gNetworkLevelSyncing) {
|
||||
gSyncObjects[o->oSyncID].o = o;
|
||||
gSyncObjects[o->oSyncID].reserved = 0;
|
||||
}
|
||||
gSyncObjects[o->oSyncID].o = o;
|
||||
}
|
||||
|
||||
spawned[i] = o;
|
||||
}
|
||||
|
||||
// update their block of reserved ids
|
||||
if (gNetworkType == NT_SERVER && receivedReservedSyncObject) {
|
||||
network_send_reservation(p->localIndex);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
300
src/pc/network/reservation_area.c
Normal file
300
src/pc/network/reservation_area.c
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
#include <stdio.h>
|
||||
#include "reservation_area.h"
|
||||
#include "network.h"
|
||||
#include "object_fields.h"
|
||||
#include "object_constants.h"
|
||||
#include "behavior_table.h"
|
||||
#include "course_table.h"
|
||||
#include "src/game/interaction.h"
|
||||
#include "src/engine/math_util.h"
|
||||
//#define DISABLE_MODULE_LOG 1
|
||||
#include "pc/debuglog.h"
|
||||
|
||||
#define RESERVED_IDS_PER_AREA 127
|
||||
#define RESERVED_IDS_UNRESERVED ((u8)-1)
|
||||
#define RESERVED_IDS_USED ((u8)-2)
|
||||
|
||||
struct ReservationArea {
|
||||
u8 courseNum;
|
||||
u8 actNum;
|
||||
u8 levelNum;
|
||||
u8 areaIndex;
|
||||
u8 playersActive;
|
||||
u8 reservedIds[RESERVED_IDS_PER_AREA];
|
||||
struct ReservationArea* next;
|
||||
};
|
||||
|
||||
struct ReservationArea* sReservationAreas = NULL;
|
||||
struct ReservationArea* sReservationAreaPerPlayer[MAX_PLAYERS] = { NULL };
|
||||
|
||||
struct LocalReservationArea {
|
||||
u8 courseNum;
|
||||
u8 actNum;
|
||||
u8 levelNum;
|
||||
u8 areaIndex;
|
||||
u8 reservedIds[RESERVED_IDS_PER_PLAYER_COUNT];
|
||||
};
|
||||
struct LocalReservationArea sLocalReservationArea = { 0 };
|
||||
|
||||
void reservation_area_debug(void) {
|
||||
printf("\n============ %02d ============\n", gNetworkPlayerLocal->globalIndex);
|
||||
|
||||
printf("reservation area per player:\n");
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
struct ReservationArea* ra = sReservationAreaPerPlayer[i];
|
||||
if (ra != NULL) {
|
||||
printf(" %d : (%d, %d, %d, %d)\n", i, ra->courseNum, ra->actNum, ra->levelNum, ra->areaIndex);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("reservation areas:\n");
|
||||
struct ReservationArea* ra = sReservationAreas;
|
||||
while (ra != NULL) {
|
||||
printf(" (%d, %d, %d, %d) : %d\n", ra->courseNum, ra->actNum, ra->levelNum, ra->areaIndex, ra->playersActive);
|
||||
|
||||
printf(" ");
|
||||
u8 idsUntilBreak = 10;
|
||||
for (int i = 0; i < RESERVED_IDS_PER_AREA; i++) {
|
||||
switch (ra->reservedIds[i])
|
||||
{
|
||||
case RESERVED_IDS_UNRESERVED: printf("UNR "); break;
|
||||
case RESERVED_IDS_USED: printf("USD "); break;
|
||||
default: printf("%03d ", ra->reservedIds[i]); break;
|
||||
}
|
||||
if (--idsUntilBreak == 0) {
|
||||
printf("\n ");
|
||||
idsUntilBreak = 10;
|
||||
}
|
||||
}
|
||||
printf("\n\n");
|
||||
ra = ra->next;
|
||||
}
|
||||
|
||||
printf("local reservation area:\n");
|
||||
struct LocalReservationArea* la = &sLocalReservationArea;
|
||||
printf(" (%d, %d, %d, %d) : ", la->courseNum, la->actNum, la->levelNum, la->areaIndex);
|
||||
for (int i = 0; i < RESERVED_IDS_PER_PLAYER_COUNT; i++) {
|
||||
switch (la->reservedIds[i])
|
||||
{
|
||||
case RESERVED_IDS_UNRESERVED: printf("UNR "); break;
|
||||
case RESERVED_IDS_USED: printf("USD "); break;
|
||||
default: printf("%03d ", la->reservedIds[i]); break;
|
||||
}
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
static void reservation_area_refresh_ids(struct NetworkPlayer* np) {
|
||||
bool informPlayer = false;
|
||||
|
||||
// make sure player has a RA
|
||||
struct ReservationArea* ra = sReservationAreaPerPlayer[np->globalIndex];
|
||||
if (ra == NULL) { return; }
|
||||
|
||||
// count current reserved ids
|
||||
u8 reservedIds[RESERVED_IDS_PER_PLAYER_COUNT] = { RESERVED_IDS_UNRESERVED };
|
||||
u8 reservedIdCount = 0;
|
||||
for (int i = 0; i < RESERVED_IDS_PER_AREA; i++) {
|
||||
if (ra->reservedIds[i] != np->globalIndex) { continue; }
|
||||
reservedIds[reservedIdCount] = i + RESERVED_IDS_SYNC_OBJECT_OFFSET;
|
||||
reservedIdCount++;
|
||||
}
|
||||
|
||||
// fill in missing reserved ids
|
||||
if (reservedIdCount < RESERVED_IDS_PER_PLAYER_COUNT) {
|
||||
for (int i = 0; i < RESERVED_IDS_PER_AREA; i++) {
|
||||
if (ra->reservedIds[i] != RESERVED_IDS_UNRESERVED) { continue; }
|
||||
ra->reservedIds[i] = np->globalIndex;
|
||||
informPlayer = true;
|
||||
reservedIds[reservedIdCount] = i + RESERVED_IDS_SYNC_OBJECT_OFFSET;
|
||||
reservedIdCount++;
|
||||
if (reservedIdCount >= RESERVED_IDS_PER_PLAYER_COUNT) { break; }
|
||||
}
|
||||
}
|
||||
|
||||
if (gNetworkType == NT_SERVER && np == gNetworkPlayerLocal) {
|
||||
// refresh server's local
|
||||
sLocalReservationArea.courseNum = np->currCourseNum;
|
||||
sLocalReservationArea.actNum = np->currActNum;
|
||||
sLocalReservationArea.levelNum = np->currLevelNum;
|
||||
sLocalReservationArea.areaIndex = np->currAreaIndex;
|
||||
|
||||
for (int i = 0; i < RESERVED_IDS_PER_PLAYER_COUNT; i++) {
|
||||
sLocalReservationArea.reservedIds[i] = reservedIds[i];
|
||||
}
|
||||
} else if (informPlayer) {
|
||||
// inform remote player of reservation list
|
||||
network_send_reservation_list(np, reservedIds);
|
||||
}
|
||||
}
|
||||
|
||||
static void reservation_area_unload(struct ReservationArea* unloadRa) {
|
||||
struct ReservationArea* ra = sReservationAreas;
|
||||
struct ReservationArea* lastRa = NULL;
|
||||
while (ra != NULL) {
|
||||
if (ra == unloadRa) {
|
||||
if (lastRa == NULL) {
|
||||
sReservationAreas = ra->next;
|
||||
} else {
|
||||
lastRa->next = ra->next;
|
||||
}
|
||||
free(unloadRa);
|
||||
return;
|
||||
}
|
||||
lastRa = ra;
|
||||
ra = ra->next;
|
||||
}
|
||||
assert(false);
|
||||
}
|
||||
|
||||
static void reservation_area_player_left(struct NetworkPlayer* np) {
|
||||
// make sure player has a RA
|
||||
struct ReservationArea* ra = sReservationAreaPerPlayer[np->globalIndex];
|
||||
if (ra == NULL) { return; }
|
||||
|
||||
// remove player's reserved ids
|
||||
for (int i = 0; i < RESERVED_IDS_PER_AREA; i++) {
|
||||
if (ra->reservedIds[i] == np->globalIndex) {
|
||||
ra->reservedIds[i] = RESERVED_IDS_UNRESERVED;
|
||||
}
|
||||
}
|
||||
|
||||
// remove player from RA, unload if sensible
|
||||
ra->playersActive--;
|
||||
if (ra->playersActive == 0) {
|
||||
reservation_area_unload(ra);
|
||||
}
|
||||
sReservationAreaPerPlayer[np->globalIndex] = NULL;
|
||||
}
|
||||
|
||||
void reservation_area_change(struct NetworkPlayer* np) {
|
||||
// check for disconnection
|
||||
if (!np->connected) {
|
||||
reservation_area_player_left(np);
|
||||
return;
|
||||
}
|
||||
|
||||
// make sure the location actually changed
|
||||
struct ReservationArea* ra = sReservationAreaPerPlayer[np->globalIndex];
|
||||
if (ra != NULL && ra->courseNum == np->currCourseNum && ra->actNum == np->currActNum && ra->levelNum == np->currLevelNum && ra->areaIndex == np->currAreaIndex) {
|
||||
return;
|
||||
}
|
||||
|
||||
// remove from the old reservation area
|
||||
reservation_area_player_left(np);
|
||||
|
||||
// find the reservation area
|
||||
ra = sReservationAreas;
|
||||
struct ReservationArea* lastRa = ra;
|
||||
while (ra != NULL) {
|
||||
if (ra->courseNum == np->currCourseNum && ra->actNum == np->currActNum && ra->levelNum == np->currLevelNum && ra->areaIndex == np->currAreaIndex) {
|
||||
// add to new reservation area
|
||||
ra->playersActive++;
|
||||
sReservationAreaPerPlayer[np->globalIndex] = ra;
|
||||
reservation_area_refresh_ids(np);
|
||||
return;
|
||||
}
|
||||
lastRa = ra;
|
||||
ra = ra->next;
|
||||
}
|
||||
|
||||
// allocate the reservation area
|
||||
ra = malloc(sizeof(struct ReservationArea));
|
||||
ra->courseNum = np->currCourseNum;
|
||||
ra->actNum = np->currActNum;
|
||||
ra->levelNum = np->currLevelNum;
|
||||
ra->areaIndex = np->currAreaIndex;
|
||||
for (int i = 0; i < RESERVED_IDS_PER_AREA; i++) {
|
||||
ra->reservedIds[i] = RESERVED_IDS_UNRESERVED;
|
||||
}
|
||||
|
||||
ra->playersActive = 1;
|
||||
ra->next = NULL;
|
||||
|
||||
sReservationAreaPerPlayer[np->globalIndex] = ra;
|
||||
|
||||
// fix up linked list
|
||||
if (lastRa == NULL) {
|
||||
sReservationAreas = ra;
|
||||
} else {
|
||||
lastRa->next = ra;
|
||||
}
|
||||
|
||||
// refresh ids
|
||||
reservation_area_refresh_ids(np);
|
||||
}
|
||||
|
||||
void reservation_area_use(struct NetworkPlayer* np, u8 syncId) {
|
||||
// make sure player has a RA
|
||||
struct ReservationArea* ra = sReservationAreaPerPlayer[np->globalIndex];
|
||||
if (ra == NULL) { return; }
|
||||
|
||||
u8 offset = syncId - RESERVED_IDS_SYNC_OBJECT_OFFSET;
|
||||
|
||||
// sanity check
|
||||
if (offset >= RESERVED_IDS_PER_AREA) { return; }
|
||||
|
||||
ra->reservedIds[offset] = RESERVED_IDS_USED;
|
||||
|
||||
reservation_area_refresh_ids(np);
|
||||
}
|
||||
|
||||
void reservation_area_release(struct NetworkPlayer* np, u8 syncId) {
|
||||
// make sure player has a RA
|
||||
struct ReservationArea* ra = sReservationAreaPerPlayer[np->globalIndex];
|
||||
if (ra == NULL) { return; }
|
||||
|
||||
u8 offset = syncId - RESERVED_IDS_SYNC_OBJECT_OFFSET;
|
||||
|
||||
// sanity check
|
||||
if (offset >= RESERVED_IDS_PER_AREA) { return; }
|
||||
|
||||
ra->reservedIds[offset] = RESERVED_IDS_UNRESERVED;
|
||||
|
||||
reservation_area_refresh_ids(np);
|
||||
}
|
||||
|
||||
void reservation_area_local_update(u8 courseNum, u8 actNum, u8 levelNum, u8 areaIndex, u8 syncIds[]) {
|
||||
sLocalReservationArea.courseNum = courseNum;
|
||||
sLocalReservationArea.actNum = actNum;
|
||||
sLocalReservationArea.levelNum = levelNum;
|
||||
sLocalReservationArea.areaIndex = areaIndex;
|
||||
|
||||
for (int i = 0; i < RESERVED_IDS_PER_PLAYER_COUNT; i++) {
|
||||
sLocalReservationArea.reservedIds[i] = syncIds[i];
|
||||
}
|
||||
}
|
||||
|
||||
u8 reservation_area_local_grab_id(void) {
|
||||
struct LocalReservationArea* la = &sLocalReservationArea;
|
||||
|
||||
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
|
||||
if (la->courseNum != gCurrCourseNum || la->actNum != gCurrActNum || la->levelNum != gCurrLevelNum || la->areaIndex != gCurrAreaIndex) {
|
||||
// invalid location
|
||||
return 0;
|
||||
}
|
||||
|
||||
// grab a sync id from reserved list
|
||||
u8 syncId = 0;
|
||||
for (int i = 0; i < RESERVED_IDS_PER_PLAYER_COUNT; i++) {
|
||||
if (la->reservedIds[i] == 0 || la->reservedIds[i] == RESERVED_IDS_UNRESERVED || la->reservedIds[i] == RESERVED_IDS_USED) { continue; }
|
||||
|
||||
// found one
|
||||
syncId = la->reservedIds[i];
|
||||
la->reservedIds[i] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// sanity check
|
||||
if (syncId == 0) { return 0; }
|
||||
|
||||
// inform the server that we used that id
|
||||
if (gNetworkType == NT_SERVER) {
|
||||
reservation_area_use(gNetworkPlayerLocal, syncId);
|
||||
} else {
|
||||
network_send_reservation_use(syncId);
|
||||
}
|
||||
|
||||
return syncId;
|
||||
}
|
||||
22
src/pc/network/reservation_area.h
Normal file
22
src/pc/network/reservation_area.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef RESERVATION_AREA_H
|
||||
#define RESERVATION_AREA_H
|
||||
|
||||
#include "PR/ultratypes.h"
|
||||
#include <time.h>
|
||||
#include <types.h>
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define RESERVED_IDS_PER_PLAYER_COUNT 5
|
||||
#define RESERVED_IDS_SYNC_OBJECT_OFFSET 127
|
||||
|
||||
struct NetworkPlayer;
|
||||
|
||||
void reservation_area_debug(void);
|
||||
void reservation_area_change(struct NetworkPlayer* np);
|
||||
void reservation_area_use(struct NetworkPlayer* np, u8 syncId);
|
||||
void reservation_area_release(struct NetworkPlayer* np, u8 syncId);
|
||||
void reservation_area_local_update(u8 courseNum, u8 actNum, u8 levelNum, u8 areaIndex, u8 syncIds[]);
|
||||
u8 reservation_area_local_grab_id(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
#define VERSION_H
|
||||
|
||||
#define UNSTABLE_BRANCH
|
||||
#define VERSION_NUMBER 3
|
||||
#define VERSION_NUMBER 4
|
||||
|
||||
#define MAX_VERSION_LENGTH 10
|
||||
char* get_version(void);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue