diff --git a/build-windows-visual-studio/sm64ex.sln b/build-windows-visual-studio/sm64ex.sln
index 46771206a..9a5c15673 100644
--- a/build-windows-visual-studio/sm64ex.sln
+++ b/build-windows-visual-studio/sm64ex.sln
@@ -16,11 +16,9 @@ Global
{8ADFCAB9-E7D6-4588-86B5-A128DA4F811D}.Debug|x64.ActiveCfg = Debug|x64
{8ADFCAB9-E7D6-4588-86B5-A128DA4F811D}.Debug|x64.Build.0 = Debug|x64
{8ADFCAB9-E7D6-4588-86B5-A128DA4F811D}.Debug|x86.ActiveCfg = Debug|Win32
- {8ADFCAB9-E7D6-4588-86B5-A128DA4F811D}.Debug|x86.Build.0 = Debug|Win32
{8ADFCAB9-E7D6-4588-86B5-A128DA4F811D}.Release|x64.ActiveCfg = Release|x64
{8ADFCAB9-E7D6-4588-86B5-A128DA4F811D}.Release|x64.Build.0 = Release|x64
{8ADFCAB9-E7D6-4588-86B5-A128DA4F811D}.Release|x86.ActiveCfg = Release|Win32
- {8ADFCAB9-E7D6-4588-86B5-A128DA4F811D}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/build-windows-visual-studio/sm64ex.vcxproj b/build-windows-visual-studio/sm64ex.vcxproj
index 3cf256957..bb0113029 100644
--- a/build-windows-visual-studio/sm64ex.vcxproj
+++ b/build-windows-visual-studio/sm64ex.vcxproj
@@ -72,6 +72,8 @@
true
../;../include/;../src/;$(IncludePath)
+ $(SolutionDir)\..\build\us_pc\
+ sm64.us.f3dex2e
true
diff --git a/build-windows-visual-studio/sm64ex.vcxproj.user b/build-windows-visual-studio/sm64ex.vcxproj.user
index 88a550947..2fe7459af 100644
--- a/build-windows-visual-studio/sm64ex.vcxproj.user
+++ b/build-windows-visual-studio/sm64ex.vcxproj.user
@@ -1,4 +1,7 @@
-
+
+ WindowsLocalDebugger
+ true
+
\ No newline at end of file
diff --git a/src/pc/network/network.c b/src/pc/network/network.c
index 2c7b92bed..2ab068ef1 100644
--- a/src/pc/network/network.c
+++ b/src/pc/network/network.c
@@ -29,7 +29,6 @@ bool gNetworkAreaLoaded = false;
bool gNetworkAreaSyncing = true;
u32 gNetworkAreaTimer = 0;
-clock_t gLastNetworkSend = 0;
struct StringLinkedList gRegisteredMods = { 0 };
struct ServerSettings gServerSettings = {
@@ -114,8 +113,12 @@ void network_send_to(u8 localIndex, struct Packet* p) {
if (gNetworkType == NT_NONE) { LOG_ERROR("network type error none!"); return; }
if (p->error) { LOG_ERROR("packet error!"); return; }
if (gNetworkSystem == NULL) { LOG_ERROR("no network system attached"); return; }
- if (p->buffer[0] != PACKET_JOIN_REQUEST && p->buffer[0] != PACKET_KICK && p->buffer[0] != PACKET_ACK && gNetworkPlayerLocal != NULL && gNetworkPlayerServer->localIndex != gNetworkPlayerLocal->localIndex) {
- assert(localIndex != gNetworkPlayerLocal->localIndex);
+ if (localIndex == 0) {
+ if (p->buffer[0] != PACKET_JOIN_REQUEST && p->buffer[0] != PACKET_KICK && p->buffer[0] != PACKET_ACK) {
+ LOG_ERROR("\n####################\nsending to myself, packetType: %d\n####################\n", p->packetType);
+ assert(false);
+ return;
+ }
}
if (gNetworkType == NT_SERVER) {
@@ -143,7 +146,7 @@ void network_send_to(u8 localIndex, struct Packet* p) {
network_remember_reliable(p);
// set ordered data (MUST BE IMMEDITAELY BEFORE HASING+SENDING)
- if (p->orderedGroupId != 0) {
+ if (p->orderedGroupId != 0 && !p->sent) {
packet_set_ordered_data(p);
}
@@ -156,12 +159,14 @@ void network_send_to(u8 localIndex, struct Packet* p) {
localIndex = gNetworkPlayerServer->localIndex;
}
+ assert(p->dataLength < PACKET_LENGTH);
+
// send
int rc = gNetworkSystem->send(localIndex, p->buffer, p->cursor + sizeof(u32));
if (rc == SOCKET_ERROR) { LOG_ERROR("send error %d", rc); return; }
p->sent = true;
- gLastNetworkSend = clock();
+ gNetworkPlayers[localIndex].lastSent = clock();
}
void network_send(struct Packet* p) {
@@ -174,7 +179,6 @@ void network_send(struct Packet* p) {
int i = gNetworkPlayerServer->localIndex;
p->localIndex = i;
network_send_to(i, p);
- gLastNetworkSend = clock();
return;
}
}
@@ -194,7 +198,6 @@ void network_send(struct Packet* p) {
p->localIndex = i;
network_send_to(i, p);
}
- gLastNetworkSend = clock();
}
void network_receive(u8 localIndex, u8* data, u16 dataLength) {
diff --git a/src/pc/network/network.h b/src/pc/network/network.h
index d0fbb2254..ff2864f77 100644
--- a/src/pc/network/network.h
+++ b/src/pc/network/network.h
@@ -86,7 +86,6 @@ extern bool gNetworkAreaSyncing;
extern u32 gNetworkAreaTimer;
extern struct SyncObject gSyncObjects[];
extern struct ServerSettings gServerSettings;
-extern clock_t gLastNetworkSend;
extern struct StringLinkedList gRegisteredMods;
// network.c
diff --git a/src/pc/network/network_player.c b/src/pc/network/network_player.c
index 9af54352d..49cf1f163 100644
--- a/src/pc/network/network_player.c
+++ b/src/pc/network/network_player.c
@@ -80,19 +80,21 @@ struct NetworkPlayer* get_network_player_smallest_global(void) {
}
void network_player_update(void) {
- float elapsed = (clock() - gLastNetworkSend) / (float)CLOCKS_PER_SEC;
- if (elapsed > NETWORK_PLAYER_TIMEOUT / 3.0f) {
- network_send_keep_alive();
- }
-#ifndef DEVELOPMENT
+//#ifndef DEVELOPMENT
if (gNetworkType == NT_SERVER) {
for (int i = 1; i < MAX_PLAYERS; i++) {
struct NetworkPlayer* np = &gNetworkPlayers[i];
if (!np->connected) { continue; }
float elapsed = (clock() - np->lastReceived) / (float)CLOCKS_PER_SEC;
if (elapsed > NETWORK_PLAYER_TIMEOUT) {
+ LOG_INFO("dropping player %d", i);
network_player_disconnected(i);
+ continue;
+ }
+ elapsed = (clock() - np->lastSent) / (float)CLOCKS_PER_SEC;
+ if (elapsed > NETWORK_PLAYER_TIMEOUT / 3.0f) {
+ network_send_keep_alive(np->localIndex);
}
}
} else if (gNetworkType == NT_CLIENT) {
@@ -100,15 +102,23 @@ void network_player_update(void) {
struct NetworkPlayer* np = gNetworkPlayerServer;
if (!np->connected) { return; }
float elapsed = (clock() - np->lastReceived) / (float)CLOCKS_PER_SEC;
+
if (elapsed <= NETWORK_PLAYER_TIMEOUT * 1.5f) {
connectionAlive = true;
return;
}
+
if (!connectionAlive) {
+ LOG_INFO("dropping due to no server connectivity");
network_shutdown();
}
+
+ elapsed = (clock() - np->lastSent) / (float)CLOCKS_PER_SEC;
+ if (elapsed > NETWORK_PLAYER_TIMEOUT / 3.0f) {
+ network_send_keep_alive(np->localIndex);
+ }
}
-#endif
+//#endif
}
u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex) {
@@ -149,6 +159,7 @@ u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex) {
if (np->globalIndex != globalIndex) { continue; }
np->localIndex = i;
np->lastReceived = clock();
+ np->lastSent = clock();
if (gNetworkType == NT_SERVER || type == NPT_SERVER) { gNetworkSystem->save_id(i, 0); }
LOG_ERROR("player connected, reusing local %d, global %d, duplicate event?", i, globalIndex);
return i;
@@ -174,6 +185,7 @@ u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex) {
np->globalIndex = (gNetworkType == NT_SERVER) ? i : globalIndex;
np->type = type;
np->lastReceived = clock();
+ np->lastSent = clock();
if (gNetworkType == NT_SERVER || type == NPT_SERVER) { gNetworkSystem->save_id(i, 0); }
for (int j = 0; j < MAX_SYNC_OBJECTS; j++) { gSyncObjects[j].rxEventId[i] = 0; }
if (type == NPT_SERVER) { gNetworkPlayerServer = np; }
diff --git a/src/pc/network/network_player.h b/src/pc/network/network_player.h
index 7da84bce9..294a1430f 100644
--- a/src/pc/network/network_player.h
+++ b/src/pc/network/network_player.h
@@ -23,6 +23,7 @@ struct NetworkPlayer {
u8 localIndex;
u8 globalIndex;
clock_t lastReceived;
+ clock_t lastSent;
u16 currLevelAreaSeqId;
s16 currCourseNum;
s16 currActNum;
diff --git a/src/pc/network/packets/packet.h b/src/pc/network/packets/packet.h
index 8614b676f..f3afbfbed 100644
--- a/src/pc/network/packets/packet.h
+++ b/src/pc/network/packets/packet.h
@@ -177,7 +177,7 @@ void network_send_kick(enum KickReasonType kickReason);
void network_receive_kick(struct Packet* p);
// packet_keep_alive.c
-void network_send_keep_alive(void);
+void network_send_keep_alive(u8 localIndex);
void network_receive_keep_alive(struct Packet* p);
// packet_leaving.c
diff --git a/src/pc/network/packets/packet_join.c b/src/pc/network/packets/packet_join.c
index ed87e20c3..aac852fc9 100644
--- a/src/pc/network/packets/packet_join.c
+++ b/src/pc/network/packets/packet_join.c
@@ -38,12 +38,6 @@ void network_receive_join_request(struct Packet* p) {
void network_send_join(struct Packet* joinRequestPacket) {
assert(gNetworkType == NT_SERVER);
- fs_file_t* fp = fs_open(SAVE_FILENAME);
- if (fp != NULL) {
- fs_read(fp, eeprom, 512);
- fs_close(fp);
- }
-
// do connection event
joinRequestPacket->localIndex = network_player_connected(NPT_CLIENT, joinRequestPacket->localIndex);
if (joinRequestPacket->localIndex == UNKNOWN_LOCAL_INDEX) {
@@ -51,6 +45,12 @@ void network_send_join(struct Packet* joinRequestPacket) {
return;
}
+ fs_file_t* fp = fs_open(SAVE_FILENAME);
+ if (fp != NULL) {
+ fs_read(fp, eeprom, 512);
+ fs_close(fp);
+ }
+
char version[MAX_VERSION_LENGTH] = { 0 };
snprintf(version, MAX_VERSION_LENGTH, "%s", get_version());
LOG_INFO("sending version: %s", version);
diff --git a/src/pc/network/packets/packet_keep_alive.c b/src/pc/network/packets/packet_keep_alive.c
index 0eb230aa4..ea2714e22 100644
--- a/src/pc/network/packets/packet_keep_alive.c
+++ b/src/pc/network/packets/packet_keep_alive.c
@@ -2,15 +2,10 @@
#include "../network.h"
#include "pc/debuglog.h"
-void network_send_keep_alive(void) {
+void network_send_keep_alive(u8 localIndex) {
struct Packet p;
packet_init(&p, PACKET_KEEP_ALIVE, false, false);
- if (gNetworkType == NT_SERVER) {
- network_send(&p);
- } else {
- network_send_to(gNetworkPlayerServer->localIndex, &p);
- }
- gLastNetworkSend = clock();
+ network_send_to(localIndex, &p);
LOG_INFO("sending keep alive");
}
diff --git a/src/pc/network/packets/packet_level_respawn_info.c b/src/pc/network/packets/packet_level_respawn_info.c
index a79e1b745..42bfc9859 100644
--- a/src/pc/network/packets/packet_level_respawn_info.c
+++ b/src/pc/network/packets/packet_level_respawn_info.c
@@ -126,7 +126,7 @@ void network_send_level_respawn_info(struct Object* o, u8 respawnInfoBits) {
// send the packet
if (gNetworkType == NT_SERVER) {
// broadcast
- for (int i = 0; i < MAX_PLAYERS; i++) {
+ for (int i = 1; i < MAX_PLAYERS; i++) {
struct NetworkPlayer* np = &gNetworkPlayers[i];
if (!np->connected) { continue; }
if (!np->currLevelSyncValid) { continue; }
@@ -174,7 +174,7 @@ void network_receive_level_respawn_info(struct Packet* p) {
}
// broadcast this change to the other players in that level
- for (int i = 0; i < MAX_PLAYERS; i++) {
+ for (int i = 1; i < MAX_PLAYERS; i++) {
struct NetworkPlayer* np = &gNetworkPlayers[i];
if (!np->connected) { continue; }
if (!np->currLevelSyncValid) { continue; }
diff --git a/src/pc/network/packets/packet_read_write.c b/src/pc/network/packets/packet_read_write.c
index 78dffe796..f17fb6b9c 100644
--- a/src/pc/network/packets/packet_read_write.c
+++ b/src/pc/network/packets/packet_read_write.c
@@ -14,6 +14,7 @@ static u8 sCurrentOrderedSeqId = 0;
void packet_init(struct Packet* packet, enum PacketType packetType, bool reliable, bool levelAreaMustMatch) {
memset(packet->buffer, 0, PACKET_LENGTH);
+ packet->packetType = packetType;
packet->cursor = 0;
packet->dataLength = 0;
packet->error = false;
@@ -69,6 +70,7 @@ void packet_init(struct Packet* packet, enum PacketType packetType, bool reliabl
void packet_duplicate(struct Packet* srcPacket, struct Packet* dstPacket) {
memset(dstPacket->buffer, 0, PACKET_LENGTH);
+ dstPacket->packetType = srcPacket->packetType;
dstPacket->cursor = 0;
dstPacket->dataLength = 0;
dstPacket->error = srcPacket->error;
@@ -90,6 +92,8 @@ void packet_duplicate(struct Packet* srcPacket, struct Packet* dstPacket) {
dstPacket->seqId = sNextSeqNum;
sNextSeqNum++;
if (sNextSeqNum == 0) { sNextSeqNum++; }
+ } else {
+ dstPacket->seqId = 0;
}
memcpy(&dstPacket->buffer[1], &dstPacket->seqId, 2);
diff --git a/src/pc/network/packets/packet_reliable.c b/src/pc/network/packets/packet_reliable.c
index 13fa3b53f..bfaeff20a 100644
--- a/src/pc/network/packets/packet_reliable.c
+++ b/src/pc/network/packets/packet_reliable.c
@@ -101,8 +101,13 @@ void network_update_reliable(void) {
float elapsed = (clock() - node->lastSend) / CLOCKS_PER_SEC;
float maxElapsed = (node->sendAttempts * node->sendAttempts * RELIABLE_RESEND_RATE) / ((float)MAX_RESEND_ATTEMPTS);
if (elapsed > maxElapsed) {
+ if (node->p.packetType == PACKET_JOIN_REQUEST && gNetworkPlayerServer != NULL) {
+ node->p.localIndex = gNetworkPlayerServer->localIndex;
+ }
// resend
+ node->p.sent = true;
network_send_to(node->p.localIndex, &node->p);
+
node->lastSend = clock();
node->sendAttempts++;
if (node->sendAttempts >= MAX_RESEND_ATTEMPTS) {
diff --git a/src/pc/network/socket/socket.c b/src/pc/network/socket/socket.c
index 4387c34e8..f22c6333d 100644
--- a/src/pc/network/socket/socket.c
+++ b/src/pc/network/socket/socket.c
@@ -24,10 +24,12 @@ static int socket_bind(SOCKET socket, unsigned int port) {
static int socket_send(SOCKET socket, struct sockaddr_in* addr, u8* buffer, u16 bufferLength) {
int addrSize = sizeof(struct sockaddr_in);
int rc = sendto(socket, (char*)buffer, bufferLength, 0, (struct sockaddr*)addr, addrSize);
- if (rc == SOCKET_ERROR) {
- LOG_ERROR("sendto failed with error: %d", SOCKET_LAST_ERROR);
- }
+ if (rc != SOCKET_ERROR) { return NO_ERROR; }
+ int error = SOCKET_LAST_ERROR;
+ if (error == SOCKET_EWOULDBLOCK) { return NO_ERROR; }
+
+ LOG_ERROR("sendto failed with error: %d", error);
return rc;
}
@@ -49,7 +51,7 @@ static int socket_receive(SOCKET socket, struct sockaddr_in* rxAddr, u8* buffer,
if (error != SOCKET_EWOULDBLOCK && error != SOCKET_ECONNRESET) {
LOG_ERROR("recvfrom failed with error %d", SOCKET_LAST_ERROR);
}
- return rc;
+ return SOCKET_ERROR;
}
*receiveLength = rc;
@@ -118,10 +120,11 @@ static void ns_socket_update(void) {
if (gNetworkType == NT_NONE) { return; }
do {
// receive packet
- u8 data[PACKET_LENGTH];
+ u8 data[PACKET_LENGTH + 1];
u16 dataLength = 0;
u8 localIndex = UNKNOWN_LOCAL_INDEX;
- int rc = socket_receive(curSocket, &addr[0], data, PACKET_LENGTH, &dataLength, &localIndex);
+ int rc = socket_receive(curSocket, &addr[0], data, PACKET_LENGTH + 1, &dataLength, &localIndex);
+ assert(dataLength < PACKET_LENGTH);
if (rc != NO_ERROR) { break; }
network_receive(localIndex, data, dataLength);
} while (true);
@@ -132,7 +135,11 @@ static int ns_socket_send(u8 localIndex, u8* data, u16 dataLength) {
if (gNetworkType == NT_SERVER && gNetworkPlayers[localIndex].type != NPT_CLIENT) { return SOCKET_ERROR; }
if (gNetworkType == NT_CLIENT && gNetworkPlayers[localIndex].type != NPT_SERVER) { return SOCKET_ERROR; }
}
- return socket_send(curSocket, &addr[localIndex], data, dataLength);
+ int rc = socket_send(curSocket, &addr[localIndex], data, dataLength);
+ if (rc) {
+ LOG_ERROR(" localIndex: %d, packetType: %d, dataLength: %d", localIndex, data[0], dataLength);
+ }
+ return rc;
}
static void ns_socket_shutdown(void) {
diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c
index fcb0bbeab..93a5b0f60 100644
--- a/src/pc/pc_main.c
+++ b/src/pc/pc_main.c
@@ -311,7 +311,9 @@ void main_func(void) {
#ifdef DISCORDRPC
discord_update_rich_presence();
#endif
+#ifdef DEBUG
fflush(stdout);
+#endif
}
#endif
}