Enhancements to networked player infrastructure
This commit is contained in:
parent
dc4974005d
commit
96a698aec3
|
@ -3973,6 +3973,7 @@
|
|||
<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_warp.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_player.c" />
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_read_write.c" />
|
||||
|
|
|
@ -15078,6 +15078,9 @@
|
|||
<ClCompile Include="..\src\game\rng_position.c">
|
||||
<Filter>Source Files\src\game</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\network\packets\packet_network_players.c">
|
||||
<Filter>Source Files\src\pc\network\packets</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\actors\common0.h">
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
set -e
|
||||
if [ $# -eq 0 ]; then
|
||||
make BETTERCAMERA=1 NODRAWINGDISTANCE=1 DEBUG=1 IMMEDIATELOAD=1 DEVELOPMENT=1 STRICT=1 -j
|
||||
else
|
||||
make BETTERCAMERA=1 NODRAWINGDISTANCE=1 DEBUG=1 IMMEDIATELOAD=1 DEVELOPMENT=1 -j
|
||||
fi
|
||||
|
||||
# find file
|
||||
FILE=./build/us_pc/sm64.us.f3dex2e.exe
|
||||
if [ ! -f "$FILE" ]; then
|
||||
FILE=./build/us_pc/sm64.us.f3dex2e
|
||||
fi
|
||||
|
||||
# no debug, discord
|
||||
#$FILE --discord 2 --configfile sm64config_server.txt &
|
||||
#$FILE --discord 1 --configfile sm64config_client.txt &
|
||||
#exit
|
||||
|
||||
# no debug, direct
|
||||
#$FILE --server 27015 --configfile sm64config_server.txt &
|
||||
#$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt &
|
||||
#exit
|
||||
|
||||
# debug on server
|
||||
#$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt &
|
||||
#winpty cgdb $FILE -ex 'break debug_breakpoint_here' -ex 'run --server 27015 --configfile sm64config_server.txt' -ex 'quit'
|
||||
#exit
|
||||
|
||||
###################
|
||||
# debug on client #
|
||||
###################
|
||||
|
||||
$FILE --server 27015 --configfile sm64config_p1.txt &
|
||||
$FILE --client 127.0.0.1 27015 --configfile sm64config_p2.txt &
|
||||
|
||||
# debug if cgdb exists
|
||||
if ! [ -x "$(command -v cgdb)" ]; then
|
||||
$FILE --client 127.0.0.1 27015 --configfile sm64config_p3.txt &
|
||||
else
|
||||
winpty cgdb $FILE -ex 'break debug_breakpoint_here' -ex 'run --client 127.0.0.1 27015 --configfile sm64config_p3.txt' -ex 'quit'
|
||||
fi
|
|
@ -664,15 +664,25 @@ static void level_cmd_unload_area(void) {
|
|||
}
|
||||
|
||||
static void level_cmd_set_mario_start_pos(void) {
|
||||
s8 areaIndex = CMD_GET(u8, 2);
|
||||
#if IS_64_BIT
|
||||
s16 x = CMD_GET(s16, 6);
|
||||
s16 y = CMD_GET(s16, 8);
|
||||
s16 z = CMD_GET(s16, 10);
|
||||
#else
|
||||
Vec3s pos = { 0 };
|
||||
vec3s_copy(pos, CMD_GET(Vec3s, 6));
|
||||
#endif
|
||||
s16 angle = CMD_GET(s16, 4);
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
gPlayerSpawnInfos[i].areaIndex = CMD_GET(u8, 2);
|
||||
gPlayerSpawnInfos[i].areaIndex = areaIndex;
|
||||
|
||||
#if IS_64_BIT
|
||||
vec3s_set(gPlayerSpawnInfos[i].startPos, CMD_GET(s16, 6), CMD_GET(s16, 8), CMD_GET(s16, 10));
|
||||
#else
|
||||
vec3s_copy(gPlayerSpawnInfos[i].startPos, CMD_GET(Vec3s, 6));
|
||||
#endif
|
||||
vec3s_set(gPlayerSpawnInfos[i].startAngle, 0, CMD_GET(s16, 4) * 0x8000 / 180, 0);
|
||||
#if IS_64_BIT
|
||||
vec3s_set(gPlayerSpawnInfos[i].startPos, x, y, z);
|
||||
#else
|
||||
vec3s_copy(gPlayerSpawnInfos[i].startPos, pos);
|
||||
#endif
|
||||
vec3s_set(gPlayerSpawnInfos[i].startAngle, 0, angle * 0x8000 / 180, 0);
|
||||
}
|
||||
sCurrentCmd = CMD_NEXT;
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ Gfx *geo_move_mario_part_from_parent(s32 run, UNUSED struct GraphNode *node, Mat
|
|||
|
||||
if (run == TRUE) {
|
||||
sp1C = (struct Object *) gCurGraphNodeObject;
|
||||
if (sp1C == gMarioObject && sp1C->prevObj != NULL) {
|
||||
if (sp1C->behavior == bhvMario && sp1C->prevObj != NULL) {
|
||||
create_transformation_from_matrices(sp20, mtx, *gCurGraphNodeCamera->matrixPtr);
|
||||
obj_update_pos_from_parent_transformation(sp20, sp1C->prevObj);
|
||||
obj_set_gfx_pos_from_pos(sp1C->prevObj);
|
||||
|
|
|
@ -2124,11 +2124,7 @@ static void init_single_mario(struct MarioState* m) {
|
|||
|
||||
// set mario/luigi model
|
||||
// two-player hack
|
||||
if (isLocal) {
|
||||
m->marioObj->header.gfx.sharedChild = gLoadedGraphNodes[(gNetworkType == NT_SERVER) ? MODEL_MARIO : MODEL_LUIGI];
|
||||
} else {
|
||||
m->marioObj->header.gfx.sharedChild = gLoadedGraphNodes[(gNetworkType == NT_CLIENT) ? MODEL_MARIO : MODEL_LUIGI];
|
||||
}
|
||||
m->marioObj->header.gfx.sharedChild = gLoadedGraphNodes[(gNetworkPlayers[0].globalIndex == 1) ? MODEL_LUIGI : MODEL_MARIO];
|
||||
}
|
||||
|
||||
void init_mario(void) {
|
||||
|
|
|
@ -61,7 +61,7 @@ struct LandingAction sBackflipLandAction = {
|
|||
4, 0, ACT_FREEFALL, ACT_BACKFLIP_LAND_STOP, ACT_BACKFLIP, ACT_FREEFALL, ACT_BEGIN_SLIDING,
|
||||
};
|
||||
|
||||
Mat4 sFloorAlignMatrix[2];
|
||||
Mat4 sFloorAlignMatrix[MAX_PLAYERS];
|
||||
|
||||
s16 tilt_body_running(struct MarioState *m) {
|
||||
s16 pitch = find_floor_slope(m, 0);
|
||||
|
|
|
@ -418,7 +418,6 @@ Gfx* geo_mario_tilt_torso(s32 callContext, struct GraphNode* node, Mat4* mtx) {
|
|||
rotNode->rotation[0] = bodyState->torsoAngle[1];
|
||||
rotNode->rotation[1] = bodyState->torsoAngle[2];
|
||||
rotNode->rotation[2] = bodyState->torsoAngle[0];
|
||||
|
||||
// update torso position in bodyState
|
||||
get_pos_from_transform_mtx(bodyState->torsoPos, *curTransform, *gCurGraphNodeCamera->matrixPtr);
|
||||
}
|
||||
|
@ -491,17 +490,18 @@ Gfx* geo_switch_mario_hand(s32 callContext, struct GraphNode* node, UNUSED Mat4*
|
|||
*/
|
||||
Gfx* geo_mario_hand_foot_scaler(s32 callContext, struct GraphNode* node, Mat4* mtx) {
|
||||
Mat4 * curTransform = mtx;
|
||||
static s16 sMarioAttackAnimCounter = 0;
|
||||
static s16 sMarioAttackAnimCounter[MAX_PLAYERS] = { 0 };
|
||||
struct GraphNodeGenerated* asGenerated = (struct GraphNodeGenerated*) node;
|
||||
struct GraphNodeScale* scaleNode = (struct GraphNodeScale*) node->next;
|
||||
u8 index = geo_get_processing_object_index();
|
||||
struct MarioBodyState* bodyState = geo_get_body_state();
|
||||
|
||||
if (callContext == GEO_CONTEXT_RENDER) {
|
||||
scaleNode->scale = 1.0f;
|
||||
if (asGenerated->parameter == bodyState->punchState >> 6) {
|
||||
if (sMarioAttackAnimCounter != gAreaUpdateCounter && (bodyState->punchState & 0x3F) > 0) {
|
||||
if (sMarioAttackAnimCounter[index] != gAreaUpdateCounter && (bodyState->punchState & 0x3F) > 0) {
|
||||
bodyState->punchState -= 1;
|
||||
sMarioAttackAnimCounter = gAreaUpdateCounter;
|
||||
sMarioAttackAnimCounter[index] = gAreaUpdateCounter;
|
||||
}
|
||||
scaleNode->scale =
|
||||
gMarioAttackScaleAnimation[asGenerated->parameter * 6 + (bodyState->punchState & 0x3F)]
|
||||
|
@ -510,7 +510,7 @@ Gfx* geo_mario_hand_foot_scaler(s32 callContext, struct GraphNode* node, Mat4* m
|
|||
// update hand/foot position in bodyState
|
||||
get_pos_from_transform_mtx(bodyState->handFootPos[(asGenerated->parameter & 0x03)],
|
||||
*curTransform,
|
||||
*gCurGraphNodeCamera->matrixPtr);
|
||||
*gCurGraphNodeCamera->matrixPtr);
|
||||
|
||||
}
|
||||
return NULL;
|
||||
|
|
|
@ -516,7 +516,9 @@ void spawn_objects_from_info(UNUSED s32 unused, struct SpawnInfo *spawnInfo) {
|
|||
u16 playerIndex = (spawnInfo->behaviorArg & ~(1 << 31));
|
||||
object->oBehParams = playerIndex + 1;
|
||||
gMarioObjects[playerIndex] = object;
|
||||
if (playerIndex == 0) { gMarioObject = object; }
|
||||
if (playerIndex == 0) {
|
||||
gMarioObject = object;
|
||||
}
|
||||
geo_make_first_child(&object->header.gfx.node);
|
||||
}
|
||||
|
||||
|
|
|
@ -1068,6 +1068,7 @@ static void interpolate_matrix(Mat4 result, Mat4 a, Mat4 b) {
|
|||
* Process an object node.
|
||||
*/
|
||||
static void geo_process_object(struct Object *node) {
|
||||
struct Object* lastProcessingObject = gCurGraphNodeProcessingObject;
|
||||
gCurGraphNodeProcessingObject = node;
|
||||
Mat4 mtxf;
|
||||
s32 hasAnimation = (node->header.gfx.node.flags & GRAPH_RENDER_HAS_ANIMATION) != 0;
|
||||
|
@ -1192,7 +1193,7 @@ static void geo_process_object(struct Object *node) {
|
|||
node->header.gfx.throwMatrix = NULL;
|
||||
node->header.gfx.throwMatrixInterpolated = NULL;
|
||||
}
|
||||
gCurGraphNodeProcessingObject = NULL;
|
||||
gCurGraphNodeProcessingObject = lastProcessingObject;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -121,10 +121,11 @@ static void ns_discord_shutdown(void) {
|
|||
}
|
||||
|
||||
struct NetworkSystem gNetworkSystemDiscord = {
|
||||
.initialize = ns_discord_initialize,
|
||||
.save_id = ns_discord_save_id,
|
||||
.clear_id = ns_discord_clear_id,
|
||||
.update = ns_discord_update,
|
||||
.send = ns_discord_network_send,
|
||||
.shutdown = ns_discord_shutdown,
|
||||
.initialize = ns_discord_initialize,
|
||||
.save_id = ns_discord_save_id,
|
||||
.clear_id = ns_discord_clear_id,
|
||||
.update = ns_discord_update,
|
||||
.send = ns_discord_network_send,
|
||||
.shutdown = ns_discord_shutdown,
|
||||
.canBroadcast = true,
|
||||
};
|
||||
|
|
|
@ -38,6 +38,7 @@ struct NetworkSystem {
|
|||
void (*update)(void);
|
||||
int (*send)(u8 localIndex, u8* data, u16 dataLength);
|
||||
void (*shutdown)(void);
|
||||
bool canBroadcast;
|
||||
};
|
||||
|
||||
struct SyncObject {
|
||||
|
|
|
@ -103,7 +103,7 @@ u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex) {
|
|||
gNetworkSystem->save_id(i);
|
||||
if (type == NPT_SERVER) { gNetworkPlayerServer = np; }
|
||||
else { chat_add_message("player connected", CMT_SYSTEM); }
|
||||
LOG_INFO("player connected, local %d, global %d", i, globalIndex);
|
||||
LOG_INFO("player connected, local %d, global %d", i, np->globalIndex);
|
||||
extern s16 sCurrPlayMode;
|
||||
if (gNetworkType == NT_SERVER && sCurrPlayMode == PLAY_MODE_SYNC_LEVEL) {
|
||||
network_send_level_warp_repeat();
|
||||
|
|
|
@ -39,6 +39,7 @@ void packet_receive(struct Packet* p) {
|
|||
case PACKET_LEAVING: network_receive_leaving(p); break;
|
||||
case PACKET_SAVE_FILE: network_receive_save_file(p); break;
|
||||
case PACKET_INSTANT_WARP: network_receive_instant_warp(p); break;
|
||||
case PACKET_NETWORK_PLAYERS: network_receive_network_players(p); break;
|
||||
///
|
||||
case PACKET_CUSTOM: network_receive_custom(p); break;
|
||||
default: LOG_ERROR("received unknown packet: %d", p->buffer[0]);
|
||||
|
|
|
@ -31,6 +31,7 @@ enum PacketType {
|
|||
PACKET_LEAVING,
|
||||
PACKET_SAVE_FILE,
|
||||
PACKET_INSTANT_WARP,
|
||||
PACKET_NETWORK_PLAYERS,
|
||||
///
|
||||
PACKET_CUSTOM = 255,
|
||||
};
|
||||
|
@ -159,4 +160,8 @@ void network_receive_save_file(struct Packet* p);
|
|||
void network_send_instant_warp(void);
|
||||
void network_receive_instant_warp(struct Packet* p);
|
||||
|
||||
// packet_network_players.c
|
||||
void network_send_network_players(void);
|
||||
void network_receive_network_players(struct Packet* p);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -75,8 +75,9 @@ void network_send_join(struct Packet* joinRequestPacket) {
|
|||
}
|
||||
|
||||
network_send_to(joinRequestPacket->localIndex , &p);
|
||||
|
||||
LOG_INFO("sending join packet");
|
||||
|
||||
network_send_network_players();
|
||||
}
|
||||
|
||||
void network_receive_join(struct Packet* p) {
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
#include <stdio.h>
|
||||
#include "../network.h"
|
||||
#include "object_fields.h"
|
||||
#include "behavior_data.h"
|
||||
#include "src/game/behavior_actions.h"
|
||||
#include "pc/debuglog.h"
|
||||
|
||||
static void network_send_to_network_players(u8 sendToLocalIndex) {
|
||||
assert(gNetworkType == NT_SERVER);
|
||||
assert(sendToLocalIndex != 0);
|
||||
|
||||
u8 connectedCount = network_player_connected_count();
|
||||
|
||||
struct Packet p;
|
||||
packet_init(&p, PACKET_NETWORK_PLAYERS, true, false);
|
||||
packet_write(&p, &connectedCount, sizeof(u8));
|
||||
for (int i = 1; i < MAX_PLAYERS; i++) {
|
||||
if (!gNetworkPlayers[i].connected) { continue; }
|
||||
u8 npType = gNetworkPlayers[i].type;
|
||||
if (npType == NPT_LOCAL) { npType = NPT_SERVER; }
|
||||
else if (i == sendToLocalIndex) { npType = NPT_LOCAL; }
|
||||
packet_write(&p, &npType, sizeof(u8));
|
||||
packet_write(&p, &gNetworkPlayers[i].globalIndex, sizeof(u8));
|
||||
LOG_INFO("send network player [%d == %d]", gNetworkPlayers[i].globalIndex, npType);
|
||||
}
|
||||
|
||||
network_send_to(sendToLocalIndex, &p);
|
||||
LOG_INFO("sent list of %d network players to %d", connectedCount, sendToLocalIndex);
|
||||
}
|
||||
|
||||
void network_send_network_players(void) {
|
||||
assert(gNetworkType == NT_SERVER);
|
||||
LOG_INFO("sending list of network players to all");
|
||||
for (int i = 1; i < MAX_PLAYERS; i++) {
|
||||
if (!gNetworkPlayers[i].connected) { continue; }
|
||||
network_send_to_network_players(i);
|
||||
}
|
||||
}
|
||||
|
||||
void network_receive_network_players(struct Packet* p) {
|
||||
LOG_INFO("receiving list of network players");
|
||||
if (gNetworkType != NT_CLIENT) {
|
||||
LOG_ERROR("received list of clients as a non-client");
|
||||
return;
|
||||
}
|
||||
u8 connectedCount = 0;
|
||||
packet_read(p, &connectedCount, sizeof(u8));
|
||||
for (int i = 0; i < connectedCount; i++) {
|
||||
u8 npType, globalIndex;
|
||||
packet_read(p, &npType, sizeof(u8));
|
||||
packet_read(p, &globalIndex, sizeof(u8));
|
||||
network_player_connected(npType, globalIndex);
|
||||
LOG_INFO("received network player [%d == %d]", globalIndex, npType);
|
||||
}
|
||||
}
|
|
@ -154,26 +154,33 @@ static void write_packet_data(struct PacketPlayerData* data, struct MarioState*
|
|||
*platformSyncID = data->platformSyncID;
|
||||
}
|
||||
|
||||
void network_send_player(void) {
|
||||
if (gMarioStates[0].marioObj == NULL) { return; }
|
||||
void network_send_player(u8 localIndex) {
|
||||
if (gMarioStates[localIndex].marioObj == NULL) { return; }
|
||||
|
||||
struct PacketPlayerData data = { 0 };
|
||||
read_packet_data(&data, &gMarioStates[0]);
|
||||
read_packet_data(&data, &gMarioStates[localIndex]);
|
||||
|
||||
struct Packet p;
|
||||
packet_init(&p, PACKET_PLAYER, false, false);
|
||||
packet_write(&p, &gNetworkPlayers[localIndex].globalIndex, sizeof(u8));
|
||||
packet_write(&p, &data, sizeof(struct PacketPlayerData));
|
||||
// two-player hack: should be network_send_to_all_except()
|
||||
network_send(&p);
|
||||
}
|
||||
|
||||
void network_receive_player(struct Packet* p) {
|
||||
struct MarioState* m = &gMarioStates[1];
|
||||
u8 globalIndex = 0;
|
||||
packet_read(p, &globalIndex, sizeof(u8));
|
||||
struct NetworkPlayer* np = network_player_from_global_index(globalIndex);
|
||||
if (np == NULL || np->localIndex == UNKNOWN_LOCAL_INDEX || !np->connected) { return; }
|
||||
|
||||
struct MarioState* m = &gMarioStates[np->localIndex];
|
||||
if (m == NULL || m->marioObj == NULL) { return; }
|
||||
|
||||
// save previous state
|
||||
struct PacketPlayerData oldData = { 0 };
|
||||
read_packet_data(&oldData, m);
|
||||
u16 playerIndex = m->playerIndex;
|
||||
u16 playerIndex = np->localIndex;
|
||||
u32 oldBehParams = m->marioObj->oBehParams;
|
||||
|
||||
// load mario information from packet
|
||||
|
@ -187,14 +194,10 @@ void network_receive_player(struct Packet* p) {
|
|||
|
||||
// check player level/area
|
||||
u8 levelAreaMismatch = TRUE;
|
||||
if (p->localIndex != UNKNOWN_LOCAL_INDEX) {
|
||||
struct NetworkPlayer* np = &gNetworkPlayers[p->localIndex];
|
||||
np->currLevelNum = data.currLevelNum;
|
||||
np->currAreaIndex = data.currAreaIndex;
|
||||
levelAreaMismatch = (data.currLevelNum != gCurrLevelNum || data.currAreaIndex != gCurrAreaIndex);
|
||||
if (levelAreaMismatch) { np->fadeOpacity = 0; }
|
||||
}
|
||||
if (levelAreaMismatch) { return; }
|
||||
np->currLevelNum = data.currLevelNum;
|
||||
np->currAreaIndex = data.currAreaIndex;
|
||||
levelAreaMismatch = (data.currLevelNum != gCurrLevelNum || data.currAreaIndex != gCurrAreaIndex);
|
||||
if (levelAreaMismatch) { np->fadeOpacity = 0; return; }
|
||||
|
||||
// apply data from packet to mario state
|
||||
u8 heldSyncID = 0;
|
||||
|
@ -301,8 +304,16 @@ void network_receive_player(struct Packet* p) {
|
|||
if (m->action != oldData.action) {
|
||||
m->actionTimer = 0;
|
||||
}
|
||||
|
||||
// set model
|
||||
m->marioObj->header.gfx.sharedChild = gLoadedGraphNodes[(np->globalIndex == 1) ? MODEL_LUIGI : MODEL_MARIO];
|
||||
|
||||
// broadcast player packet
|
||||
if (gNetworkType == NT_SERVER && !gNetworkSystem->canBroadcast) {
|
||||
network_send_player(globalIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void network_update_player(void) {
|
||||
network_send_player();
|
||||
network_send_player(0);
|
||||
}
|
||||
|
|
|
@ -138,10 +138,11 @@ static void ns_socket_shutdown(void) {
|
|||
}
|
||||
|
||||
struct NetworkSystem gNetworkSystemSocket = {
|
||||
.initialize = ns_socket_initialize,
|
||||
.save_id = ns_socket_save_id,
|
||||
.clear_id = ns_socket_clear_id,
|
||||
.update = ns_socket_update,
|
||||
.send = ns_socket_send,
|
||||
.shutdown = ns_socket_shutdown,
|
||||
.initialize = ns_socket_initialize,
|
||||
.save_id = ns_socket_save_id,
|
||||
.clear_id = ns_socket_clear_id,
|
||||
.update = ns_socket_update,
|
||||
.send = ns_socket_send,
|
||||
.shutdown = ns_socket_shutdown,
|
||||
.canBroadcast = false,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue