Networking updates. Don't bother testing this to see if things are any better, because they aren't. :p

git-svn-id: https://svn.eduke32.com/eduke32@3079 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
terminx 2012-10-14 21:52:51 +00:00
parent d5f7e5becf
commit 901b1bff0f
3 changed files with 84 additions and 59 deletions

View file

@ -89,7 +89,7 @@ extern "C" {
#define GAMETICSPERSEC 26 #define GAMETICSPERSEC 26
#define PACKBUF_SIZE 16384 #define PACKBUF_SIZE 32768
#define TILE_SAVESHOT (MAXTILES-1) #define TILE_SAVESHOT (MAXTILES-1)
#define TILE_LOADSHOT (MAXTILES-3) #define TILE_LOADSHOT (MAXTILES-3)

View file

@ -58,11 +58,9 @@ int16_t g_netStatnums[10] = { STAT_PROJECTILE, STAT_PLAYER, STAT_STANDABLE, STAT
STAT_EFFECTOR, STAT_ACTOR, STAT_ZOMBIEACTOR, STAT_MISC, MAXSTATUS STAT_EFFECTOR, STAT_ACTOR, STAT_ZOMBIEACTOR, STAT_MISC, MAXSTATUS
}; };
int32_t lastupdate[MAXSPRITES];
int32_t lastsectupdate[MAXSECTORS];
int32_t lastwallupdate[MAXWALLS];
#pragma pack(push,1) #pragma pack(push,1)
netmapstate_t *g_multiMapState[MAXPLAYERS]; netmapstate_t *g_multiMapState[MAXPLAYERS];
netmapstate_t *g_pendingMapState[MAXPLAYERS];
netmapstate_t *g_multiMapRevisions[NET_REVISIONS]; netmapstate_t *g_multiMapRevisions[NET_REVISIONS];
netmapstate_t *streamoutput = NULL; netmapstate_t *streamoutput = NULL;
#pragma pack(pop) #pragma pack(pop)
@ -75,6 +73,13 @@ static void alloc_multimapstate(int32_t i)
if (g_multiMapState[i] == NULL) if (g_multiMapState[i] == NULL)
G_GameExit("OUT OF MEMORY in alloc_multimapstate"); G_GameExit("OUT OF MEMORY in alloc_multimapstate");
} }
if (g_pendingMapState[i] == NULL)
{
g_pendingMapState[i] = Bcalloc(1, sizeof(netmapstate_t));
if (g_pendingMapState[i] == NULL)
G_GameExit("OUT OF MEMORY in alloc_multimapstate");
}
} }
void Net_SaveMapState(netmapstate_t *save) void Net_SaveMapState(netmapstate_t *save)
@ -103,7 +108,7 @@ void Net_SaveMapState(netmapstate_t *save)
save->scriptptrs[i] = 0; save->scriptptrs[i] = 0;
Bmemcpy(&save->actor[0],&actor[0],offsetof(netactor_t, t_data[0])*MAXSPRITES); Bmemcpy(&save->actor[0],&actor[0],sizeof(netactor_t)*MAXSPRITES);
for (i=MAXSPRITES-1; i>=0; i--) for (i=MAXSPRITES-1; i>=0; i--)
for (j=0;j<10;j++) for (j=0;j<10;j++)
@ -177,7 +182,7 @@ void Net_RestoreMapState(netmapstate_t *save)
intptr_t j; intptr_t j;
char phealth[MAXPLAYERS]; char phealth[MAXPLAYERS];
initprintf("restoring revision %d\n", save->revision);
Bassert(save->crc == crc32once((uint8_t *)save, offsetof(netmapstate_t, crc))); Bassert(save->crc == crc32once((uint8_t *)save, offsetof(netmapstate_t, crc)));
for (i=0; i<playerswhenstarted; i++) for (i=0; i<playerswhenstarted; i++)
@ -201,7 +206,7 @@ void Net_RestoreMapState(netmapstate_t *save)
Bmemcpy(&prevspritestat[0],&save->prevspritestat[0],sizeof(prevspritestat)); Bmemcpy(&prevspritestat[0],&save->prevspritestat[0],sizeof(prevspritestat));
Bmemcpy(&nextspritestat[0],&save->nextspritestat[0],sizeof(nextspritestat)); Bmemcpy(&nextspritestat[0],&save->nextspritestat[0],sizeof(nextspritestat));
Bmemcpy(&actor[0],&save->actor[0],offsetof(netactor_t, t_data)*MAXSPRITES); Bmemcpy(&actor[0],&save->actor[0],sizeof(netactor_t)*MAXSPRITES);
for (i=MAXSPRITES-1; i>=0; i--) for (i=MAXSPRITES-1; i>=0; i--)
@ -599,6 +604,7 @@ void Net_SyncPlayer(ENetEvent *event)
g_player[i].netsynctime = totalclock; g_player[i].netsynctime = totalclock;
g_player[i].playerquitflag = 1; g_player[i].playerquitflag = 1;
g_player[i].revision = g_netMapRevision;
for (j=0; j<playerswhenstarted-1; j++) connectpoint2[j] = j+1; for (j=0; j<playerswhenstarted-1; j++) connectpoint2[j] = j+1;
connectpoint2[playerswhenstarted-1] = -1; connectpoint2[playerswhenstarted-1] = -1;
@ -661,10 +667,6 @@ void Net_SyncPlayer(ENetEvent *event)
initprintf("Error compressing map state for transfer!\n"); initprintf("Error compressing map state for transfer!\n");
Bfree(buf); Bfree(buf);
/*
Bfree(g_multiMapState);
g_multiMapState = NULL;
*/
} }
} }
} }
@ -692,11 +694,14 @@ static int32_t NewGameCommon(uint8_t *pbuf)
{ {
P_ResetWeapons(i); P_ResetWeapons(i);
P_ResetInventory(i); P_ResetInventory(i);
g_player[i].revision = 0;
} }
G_NewGame(ud.volume_number,ud.level_number,ud.player_skill); G_NewGame(ud.volume_number,ud.level_number,ud.player_skill);
ud.coop = ud.m_coop; ud.coop = ud.m_coop;
g_netMapRevision = 0;
if (G_EnterLevel(MODE_GAME)) if (G_EnterLevel(MODE_GAME))
{ {
G_BackToMenu(); G_BackToMenu();
@ -879,7 +884,7 @@ void Net_ParseServerPacket(ENetEvent *event)
// Bmemcpy(&g_player[i].ps->opos.x, &g_player[i].ps->pos.x, sizeof(vec3_t)); // Bmemcpy(&g_player[i].ps->opos.x, &g_player[i].ps->pos.x, sizeof(vec3_t));
// Bmemcpy(&g_player[i].ps->pos.x, &pbuf[j], sizeof(vec3_t) * 2); Bmemcpy(&g_player[i].ps->pos.x, &pbuf[j], sizeof(vec3_t) * 2);
Bmemcpy(&sprite[g_player[i].ps->i], &pbuf[j], sizeof(vec3_t)); Bmemcpy(&sprite[g_player[i].ps->i], &pbuf[j], sizeof(vec3_t));
sprite[g_player[i].ps->i].z += PHEIGHT; sprite[g_player[i].ps->i].z += PHEIGHT;
@ -1007,6 +1012,12 @@ void Net_ParseServerPacket(ENetEvent *event)
if (!(g_player[myconnectindex].ps->gm & MODE_GAME) || g_netSync) if (!(g_player[myconnectindex].ps->gm & MODE_GAME) || g_netSync)
return; return;
if (*(uint32_t *)&pbuf[1] != g_multiMapState[0]->revision)
{
initprintf("base revision mismatch, expected %d and found %d\n", g_player[myconnectindex].revision, *(uint32_t *)&pbuf[1]);
return;
}
if (!streamoutput) if (!streamoutput)
streamoutput = (netmapstate_t *)Bcalloc(1, sizeof(netmapstate_t)); streamoutput = (netmapstate_t *)Bcalloc(1, sizeof(netmapstate_t));
@ -1014,22 +1025,31 @@ void Net_ParseServerPacket(ENetEvent *event)
usize_t osize = 0; usize_t osize = 0;
int ret; int ret;
j = 0; packbufleng = qlz_size_decompressed((char *)&pbuf[5]);
packbufleng = qlz_size_decompressed((char *)&pbuf[1]);
pbuf = (uint8_t *)Bmalloc(packbufleng<<1); pbuf = (uint8_t *)Bmalloc(packbufleng<<1);
packbufleng = qlz_decompress((char *)&event->packet->data[1], (char *)(pbuf), state_decompress); packbufleng = qlz_decompress((char *)&event->packet->data[5], (char *)(pbuf), state_decompress);
initprintf("packbufleng: %d\n", packbufleng); initprintf("packbufleng: %d\n", packbufleng);
ret = xd3_decode_memory((const uint8_t *)pbuf, packbufleng, ret = xd3_decode_memory((const uint8_t *)pbuf, packbufleng,
(const uint8_t *)g_multiMapState[0], sizeof(netmapstate_t), (const uint8_t *)g_multiMapState[0], sizeof(netmapstate_t),
(uint8_t *)streamoutput, &osize, sizeof(netmapstate_t), XD3_COMPLEVEL_1|XD3_NOCOMPRESS); (uint8_t *)streamoutput, &osize, sizeof(netmapstate_t), XD3_COMPLEVEL_1|XD3_NOCOMPRESS);
initprintf("xdelta3 returned %d\n", ret);
if (ret)
{
initprintf("xdelta3 returned %d\n", ret);
Bfree(pbuf);
break;
}
if (sizeof(netmapstate_t) != osize) if (sizeof(netmapstate_t) != osize)
initprintf("decompressed data size mismatch!\n"); initprintf("decompressed data size mismatch!\n");
Net_RestoreMapState(streamoutput); else
{
Net_RestoreMapState(streamoutput);
g_player[myconnectindex].revision = streamoutput->revision;
Bmemcpy(g_multiMapState[0], streamoutput, sizeof(netmapstate_t));
}
Bfree(pbuf); Bfree(pbuf);
} }
@ -1042,6 +1062,8 @@ void Net_ParseServerPacket(ENetEvent *event)
if (g_netSync) if (g_netSync)
{ {
Net_RestoreMapState(g_multiMapState[0]);
packbuf[0] = PACKET_PLAYER_READY; packbuf[0] = PACKET_PLAYER_READY;
packbuf[1] = myconnectindex; packbuf[1] = myconnectindex;
@ -1050,7 +1072,6 @@ void Net_ParseServerPacket(ENetEvent *event)
g_netSync = 0; g_netSync = 0;
Net_RestoreMapState(g_multiMapState[0]);
g_player[myconnectindex].ps->gm = MODE_GAME; g_player[myconnectindex].ps->gm = MODE_GAME;
ready2send = 1; ready2send = 1;
} }
@ -1138,7 +1159,7 @@ void Net_ParseClientPacket(ENetEvent *event)
{ {
uint8_t *pbuf = event->packet->data; uint8_t *pbuf = event->packet->data;
int32_t packbufleng = event->packet->dataLength; int32_t packbufleng = event->packet->dataLength;
int16_t i, j; int16_t j;
int32_t other = pbuf[--packbufleng]; int32_t other = pbuf[--packbufleng];
input_t *nsyn; input_t *nsyn;
@ -1149,7 +1170,8 @@ void Net_ParseClientPacket(ENetEvent *event)
{ {
case PACKET_SLAVE_TO_MASTER: //[1] (receive slave sync buffer) case PACKET_SLAVE_TO_MASTER: //[1] (receive slave sync buffer)
{ {
const intptr_t playeridx = (intptr_t)event->peer->data; const int32_t playeridx = (int32_t)(intptr_t)event->peer->data;
uint32_t rev;
j = 0; j = 0;
@ -1159,10 +1181,26 @@ void Net_ParseClientPacket(ENetEvent *event)
nsyn = (input_t *)&inputfifo[0][0]; nsyn = (input_t *)&inputfifo[0][0];
g_player[other].revision = *(uint32_t *)&pbuf[j]; alloc_multimapstate(playeridx);
rev = *(uint32_t *)&pbuf[j];
if (g_player[playeridx].revision != rev)
{
g_player[playeridx].ready = 1;
g_player[playeridx].revision = rev;
if (rev != g_pendingMapState[playeridx]->revision)
initprintf("wtf? expected confirmation of revision %d from player %d, got revision %d\n",
g_pendingMapState[playeridx]->revision, playeridx, rev);
else
{
Bmemcpy(g_multiMapState[playeridx], g_pendingMapState[playeridx], sizeof(netmapstate_t));
initprintf("player %d now at base revision %d\n", playeridx, g_player[playeridx].revision);
}
}
j += sizeof(uint32_t); j += sizeof(uint32_t);
alloc_multimapstate(playeridx);
// XXX: g_multiMapRevisions[...] is NULL when started like // XXX: g_multiMapRevisions[...] is NULL when started like
// (peer 1)$ eduke32 -server // (peer 1)$ eduke32 -server
// (peer 2)$ eduke32 -connect localhost // (peer 2)$ eduke32 -connect localhost
@ -1220,6 +1258,8 @@ void Net_ParseClientPacket(ENetEvent *event)
P_ResetPlayer(other); P_ResetPlayer(other);
g_player[other].ready = 1;
j = 0; j = 0;
packbuf[j++] = PACKET_PLAYER_SPAWN; packbuf[j++] = PACKET_PLAYER_SPAWN;
packbuf[j++] = other; packbuf[j++] = other;
@ -1231,28 +1271,6 @@ void Net_ParseClientPacket(ENetEvent *event)
enet_host_broadcast(g_netServer, CHAN_GAMESTATE, enet_packet_create(packbuf, j, ENET_PACKET_FLAG_RELIABLE)); enet_host_broadcast(g_netServer, CHAN_GAMESTATE, enet_packet_create(packbuf, j, ENET_PACKET_FLAG_RELIABLE));
// a player connecting is a good time to mark things as needing to be updated
// we invalidate everything that has changed since we started sending the snapshot of the map to the new player
{
int32_t zz, i, nexti;
for (zz = 0; (unsigned)zz < (sizeof(g_netStatnums)/sizeof(g_netStatnums[0])); zz++)
for (TRAVERSE_SPRITE_STAT(headspritestat[g_netStatnums[zz]], i, nexti))
{
if (lastupdate[i] >= g_player[other].netsynctime)
lastupdate[i] = 0;
}
}
for (i=numwalls-1; i>=0; i--)
if (lastwallupdate[i] >= g_player[other].netsynctime)
lastwallupdate[i] = 0;
for (i=numsectors-1; i>=0; i--)
if (lastsectupdate[i] >= g_player[other].netsynctime)
lastsectupdate[i] = 0;
break; break;
@ -1268,6 +1286,7 @@ void Net_ParseClientPacket(ENetEvent *event)
case PACKET_NEW_GAME: case PACKET_NEW_GAME:
NewGameCommon(pbuf); NewGameCommon(pbuf);
return;
case PACKET_AUTH: case PACKET_AUTH:
{ {
@ -1581,6 +1600,8 @@ void Net_ClientMove(void)
} }
char g_netCompressBuf[PACKBUF_SIZE+400];
void Net_UpdateClients(void) void Net_UpdateClients(void)
{ {
input_t *osyn = (input_t *)&inputfifo[1][0]; input_t *osyn = (input_t *)&inputfifo[1][0];
@ -1728,8 +1749,6 @@ void Net_UpdateClients(void)
} }
{ {
char buf[PACKBUF_SIZE+400];
#if 1 #if 1
// We're screwed anyway if this fails: // We're screwed anyway if this fails:
Bassert(siz <= PACKBUF_SIZE); Bassert(siz <= PACKBUF_SIZE);
@ -1740,7 +1759,7 @@ void Net_UpdateClients(void)
return; return;
} }
#endif #endif
siz = qlz_compress(packbuf+1, buf, siz, state_compress); siz = qlz_compress(packbuf+1, g_netCompressBuf, siz, state_compress);
if (siz >= PACKBUF_SIZE-1) if (siz >= PACKBUF_SIZE-1)
{ {
@ -1748,7 +1767,7 @@ void Net_UpdateClients(void)
return; return;
} }
Bmemcpy(packbuf+1, buf, siz); Bmemcpy(packbuf+1, g_netCompressBuf, siz);
siz++; siz++;
} }
@ -1774,13 +1793,16 @@ void Net_StreamLevel(void)
ENetPeer *const currentPeer = &g_netServer->peers[pi]; ENetPeer *const currentPeer = &g_netServer->peers[pi];
const intptr_t playeridx = (intptr_t)currentPeer->data; const intptr_t playeridx = (intptr_t)currentPeer->data;
if (currentPeer->state != ENET_PEER_STATE_CONNECTED) if (currentPeer->state != ENET_PEER_STATE_CONNECTED || !g_player[playeridx].playerquitflag || !g_player[playeridx].ready)
continue; continue;
packbuf[siz++] = PACKET_MAP_STREAM; g_player[playeridx].ready = 0;
packbuf[0] = PACKET_MAP_STREAM;
*(uint32_t *)&packbuf[1] = g_player[playeridx].revision; // base revision for this update
if (g_multiMapRevisions[g_netMapRevision&(NET_REVISIONS-1)] == NULL) if (g_multiMapRevisions[g_netMapRevision&(NET_REVISIONS-1)] == NULL)
g_multiMapRevisions[g_netMapRevision&(NET_REVISIONS-1)] = Bcalloc(1, sizeof(netmapstate_t)); g_multiMapRevisions[g_netMapRevision&(NET_REVISIONS-1)] = (netmapstate_t *)Bcalloc(1, sizeof(netmapstate_t));
Net_SaveMapState(g_multiMapRevisions[g_netMapRevision&(NET_REVISIONS-1)]); Net_SaveMapState(g_multiMapRevisions[g_netMapRevision&(NET_REVISIONS-1)]);
@ -1788,11 +1810,11 @@ void Net_StreamLevel(void)
(const uint8_t *)g_multiMapState[playeridx], sizeof(netmapstate_t), (const uint8_t *)g_multiMapState[playeridx], sizeof(netmapstate_t),
(uint8_t *)streamoutput, &osize, sizeof(netmapstate_t), XD3_COMPLEVEL_1|XD3_NOCOMPRESS); (uint8_t *)streamoutput, &osize, sizeof(netmapstate_t), XD3_COMPLEVEL_1|XD3_NOCOMPRESS);
g_netMapRevision++; Bmemcpy(g_pendingMapState[playeridx], g_multiMapRevisions[g_netMapRevision&(NET_REVISIONS-1)], sizeof(netmapstate_t));
initprintf("upd %u->%u: ", g_player[playeridx].revision, g_netMapRevision);
{ {
char buf[PACKBUF_SIZE+400];
if (osize >= PACKBUF_SIZE) if (osize >= PACKBUF_SIZE)
{ {
// XXX: this currently happens when e.g. switching levels // XXX: this currently happens when e.g. switching levels
@ -1801,7 +1823,7 @@ void Net_StreamLevel(void)
return; return;
} }
siz = qlz_compress((char *)streamoutput, buf, osize, state_compress); siz = qlz_compress((char *)streamoutput, g_netCompressBuf, osize, state_compress);
if (siz >= PACKBUF_SIZE-1) if (siz >= PACKBUF_SIZE-1)
{ {
@ -1810,16 +1832,19 @@ void Net_StreamLevel(void)
return; return;
} }
Bmemcpy(packbuf+1, buf, siz); Bmemcpy(packbuf+1+sizeof(uint32_t), g_netCompressBuf, siz);
siz++; siz++;
siz += sizeof(uint32_t);
} }
packbuf[siz++] = myconnectindex; packbuf[siz++] = myconnectindex;
initprintf("revision %u: final packet size: %d\n", g_netMapRevision-1, siz); initprintf("final packet size: %d\n", siz);
enet_peer_send(currentPeer, CHAN_GAMESTATE, enet_packet_create(packbuf, siz, ENET_PACKET_FLAG_RELIABLE)); enet_peer_send(currentPeer, CHAN_GAMESTATE, enet_packet_create(packbuf, siz, ENET_PACKET_FLAG_RELIABLE));
} }
g_netMapRevision++;
} }
void faketimerhandler(void) void faketimerhandler(void)

View file

@ -89,7 +89,7 @@ enum netmode_t
#pragma pack(push,1) #pragma pack(push,1)
typedef struct { typedef struct {
int32_t revision; uint32_t revision;
int32_t animategoal[MAXANIMATES], animatevel[MAXANIMATES], g_animateCount; int32_t animategoal[MAXANIMATES], animatevel[MAXANIMATES], g_animateCount;
int32_t animateptr[MAXANIMATES]; int32_t animateptr[MAXANIMATES];
// int32_t lockclock; // int32_t lockclock;