mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-28 23:01:41 +00:00
- misc fixes to client server handshaking and playsim ticking
This commit is contained in:
parent
beed2817f2
commit
6827e56a4e
10 changed files with 211 additions and 105 deletions
|
@ -986,11 +986,6 @@ public:
|
||||||
return LastTic;
|
return LastTic;
|
||||||
}
|
}
|
||||||
|
|
||||||
int BaseMakeTic() const
|
|
||||||
{
|
|
||||||
return LastTic + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int LastTic = 0;
|
int LastTic = 0;
|
||||||
int CurrentTic = 0;
|
int CurrentTic = 0;
|
||||||
|
@ -1038,7 +1033,7 @@ public:
|
||||||
|
|
||||||
for (int i = 0; i < tics; i++)
|
for (int i = 0; i < tics; i++)
|
||||||
{
|
{
|
||||||
network->SetCurrentTic(gametime.BaseGameTic() + i, gametime.BaseMakeTic() + i);
|
network->SetCurrentTic(gametime.BaseGameTic() + i);
|
||||||
network->WriteLocalInput(G_BuildTiccmd());
|
network->WriteLocalInput(G_BuildTiccmd());
|
||||||
|
|
||||||
if (advancedemo)
|
if (advancedemo)
|
||||||
|
@ -1095,6 +1090,8 @@ void D_DoomLoop()
|
||||||
|
|
||||||
if (wantToRestart)
|
if (wantToRestart)
|
||||||
{
|
{
|
||||||
|
P_UnPredictPlayer();
|
||||||
|
|
||||||
wantToRestart = false;
|
wantToRestart = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,45 +228,31 @@ int DoomComImpl::FindNode(const sockaddr_in *address)
|
||||||
|
|
||||||
void DoomComImpl::PacketSend(const NetPacket &packet)
|
void DoomComImpl::PacketSend(const NetPacket &packet)
|
||||||
{
|
{
|
||||||
int c;
|
|
||||||
|
|
||||||
// FIXME: Catch this before we've overflown the buffer. With long chat
|
|
||||||
// text and lots of backup tics, it could conceivably happen. (Though
|
|
||||||
// apparently it hasn't yet, which is good.)
|
|
||||||
if (packet.size > MAX_MSGLEN)
|
|
||||||
{
|
|
||||||
I_FatalError("Netbuffer overflow!");
|
|
||||||
}
|
|
||||||
assert(!(packet.data[0] & NCMD_COMPRESSED));
|
assert(!(packet.data[0] & NCMD_COMPRESSED));
|
||||||
|
|
||||||
uLong size = TRANSMIT_SIZE - 1;
|
|
||||||
if (packet.size >= 10)
|
if (packet.size >= 10)
|
||||||
{
|
{
|
||||||
mTransmitBuffer[0] = packet.data[0] | NCMD_COMPRESSED;
|
mTransmitBuffer[0] = packet.data[0] | NCMD_COMPRESSED;
|
||||||
c = compress2(mTransmitBuffer + 1, &size, packet.data + 1, packet.size - 1, 9);
|
|
||||||
|
uLong size = TRANSMIT_SIZE - 1;
|
||||||
|
int c = compress2(mTransmitBuffer + 1, &size, packet.data + 1, packet.size - 1, 9);
|
||||||
size += 1;
|
size += 1;
|
||||||
|
|
||||||
|
if (c == Z_OK && size < (uLong)packet.size)
|
||||||
|
{
|
||||||
|
sendto(mSocket, (char *)mTransmitBuffer, size, 0, (sockaddr *)&mNodeEndpoints[packet.node], sizeof(mNodeEndpoints[packet.node]));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet.size <= TRANSMIT_SIZE)
|
||||||
|
{
|
||||||
|
sendto(mSocket, (char *)packet.data, packet.size, 0, (sockaddr *)&mNodeEndpoints[packet.node], sizeof(mNodeEndpoints[packet.node]));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
c = -1; // Just some random error code to avoid sending the compressed buffer.
|
I_Error("NetPacket is too large to be transmitted");
|
||||||
}
|
}
|
||||||
if (c == Z_OK && size < (uLong)packet.size)
|
|
||||||
{
|
|
||||||
c = sendto(mSocket, (char *)mTransmitBuffer, size, 0, (sockaddr *)&mNodeEndpoints[packet.node], sizeof(mNodeEndpoints[packet.node]));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (packet.size > TRANSMIT_SIZE)
|
|
||||||
{
|
|
||||||
I_Error("Net compression failed (zlib error %d)", c);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c = sendto(mSocket, (char *)packet.data, packet.size, 0, (sockaddr *)&mNodeEndpoints[packet.node], sizeof(mNodeEndpoints[packet.node]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if (c == -1)
|
|
||||||
// I_Error ("SendPacket error: %s",strerror(errno));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoomComImpl::PacketGet(NetPacket &packet)
|
void DoomComImpl::PacketGet(NetPacket &packet)
|
||||||
|
@ -303,7 +289,8 @@ void DoomComImpl::PacketGet(NetPacket &packet)
|
||||||
Close(node);
|
Close(node);
|
||||||
packet.node = node;
|
packet.node = node;
|
||||||
packet.size = 0;
|
packet.size = 0;
|
||||||
packet.stream.pbStreamEnd = packet.stream.pbStream;
|
packet.stream.pbStream = packet.data;
|
||||||
|
packet.stream.pbStreamEnd = packet.data + packet.size;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (err != WSAEWOULDBLOCK)
|
else if (err != WSAEWOULDBLOCK)
|
||||||
|
@ -314,7 +301,8 @@ void DoomComImpl::PacketGet(NetPacket &packet)
|
||||||
{
|
{
|
||||||
packet.node = -1;
|
packet.node = -1;
|
||||||
packet.size = 0;
|
packet.size = 0;
|
||||||
packet.stream.pbStreamEnd = packet.stream.pbStream;
|
packet.stream.pbStream = packet.data;
|
||||||
|
packet.stream.pbStreamEnd = packet.data + packet.size;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -325,7 +313,7 @@ void DoomComImpl::PacketGet(NetPacket &packet)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
packet.data[0] = mTransmitBuffer[0] & ~NCMD_COMPRESSED;
|
packet.data[0] = mTransmitBuffer[0] & ~NCMD_COMPRESSED;
|
||||||
if (mTransmitBuffer[0] & NCMD_COMPRESSED)
|
if ((mTransmitBuffer[0] & NCMD_COMPRESSED) && size > 1)
|
||||||
{
|
{
|
||||||
uLongf msgsize = MAX_MSGLEN - 1;
|
uLongf msgsize = MAX_MSGLEN - 1;
|
||||||
int err = uncompress(packet.data + 1, &msgsize, mTransmitBuffer + 1, size - 1);
|
int err = uncompress(packet.data + 1, &msgsize, mTransmitBuffer + 1, size - 1);
|
||||||
|
@ -343,7 +331,8 @@ void DoomComImpl::PacketGet(NetPacket &packet)
|
||||||
|
|
||||||
packet.node = node;
|
packet.node = node;
|
||||||
packet.size = (short)size;
|
packet.size = (short)size;
|
||||||
packet.stream.pbStreamEnd = packet.stream.pbStream + packet.size;
|
packet.stream.pbStream = packet.data;
|
||||||
|
packet.stream.pbStreamEnd = packet.data + packet.size;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,9 @@ struct NetPacket
|
||||||
const uint8_t &operator[](int i) const { return data[i]; }
|
const uint8_t &operator[](int i) const { return data[i]; }
|
||||||
|
|
||||||
BYTESTREAM_s stream;
|
BYTESTREAM_s stream;
|
||||||
|
|
||||||
|
NetPacket(const NetPacket &) = delete;
|
||||||
|
NetPacket &operator=(const NetPacket &) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Network packet data.
|
// Network packet data.
|
||||||
|
|
|
@ -63,8 +63,8 @@ public:
|
||||||
// Check for incoming packets
|
// Check for incoming packets
|
||||||
virtual void Update() = 0;
|
virtual void Update() = 0;
|
||||||
|
|
||||||
// Set current tic for reading and writing
|
// Set current tic time
|
||||||
virtual void SetCurrentTic(int receivetic, int sendtic) = 0;
|
virtual void SetCurrentTic(int localtic) = 0;
|
||||||
|
|
||||||
// Send any pending outgoing data
|
// Send any pending outgoing data
|
||||||
virtual void EndCurrentTic() = 0;
|
virtual void EndCurrentTic() = 0;
|
||||||
|
|
|
@ -82,6 +82,7 @@ NetClient::NetClient(FString server)
|
||||||
packet.node = mServerNode;
|
packet.node = mServerNode;
|
||||||
|
|
||||||
NetCommand cmd ( NetPacketType::ConnectRequest );
|
NetCommand cmd ( NetPacketType::ConnectRequest );
|
||||||
|
cmd.addString("ZDoom Connect Request");
|
||||||
cmd.writeCommandToPacket ( packet );
|
cmd.writeCommandToPacket ( packet );
|
||||||
|
|
||||||
mComm->PacketSend(packet);
|
mComm->PacketSend(packet);
|
||||||
|
@ -149,26 +150,62 @@ void NetClient::Update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetClient::SetCurrentTic(int receivetic, int sendtic)
|
void NetClient::SetCurrentTic(int tictime)
|
||||||
{
|
{
|
||||||
gametic = receivetic;
|
gametic = tictime;
|
||||||
mSendTic = sendtic;
|
mSendTic = gametic + 10;
|
||||||
|
|
||||||
|
int jitter = 2;
|
||||||
|
if (mLastReceivedTic == -1)
|
||||||
|
{
|
||||||
|
mServerTic = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (mServerTicDelta == -1 || std::abs(gametic + mServerTicDelta - mLastReceivedTic) > jitter)
|
||||||
|
{
|
||||||
|
//Printf("netcable icon! ;)\n");
|
||||||
|
mServerTicDelta = mLastReceivedTic - gametic - jitter;
|
||||||
|
}
|
||||||
|
|
||||||
|
mServerTic = MAX(gametic + mServerTicDelta, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
mCurrentInput[consoleplayer] = mSentInput[gametic % BACKUPTICS];
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetClient::EndCurrentTic()
|
void NetClient::EndCurrentTic()
|
||||||
{
|
{
|
||||||
|
mCurrentCommands = mSendCommands;
|
||||||
|
mSendCommands.Clear();
|
||||||
|
|
||||||
|
if (mStatus != NodeStatus::InGame)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int targettic = (mSendTic + mServerTicDelta);
|
||||||
|
|
||||||
NetPacket packet;
|
NetPacket packet;
|
||||||
packet.node = mServerNode;
|
packet.node = mServerNode;
|
||||||
|
|
||||||
NetCommand cmd ( NetPacketType::Tic );
|
NetCommand cmd ( NetPacketType::Tic );
|
||||||
cmd.addByte ( 0 ); // target gametic
|
cmd.addByte (targettic); // target gametic
|
||||||
cmd.addBuffer ( &mCurrentInput[consoleplayer].ucmd, sizeof(usercmd_t) );
|
cmd.addBuffer ( &mSentInput[(mSendTic - 1) % BACKUPTICS].ucmd, sizeof(usercmd_t) );
|
||||||
cmd.writeCommandToPacket ( packet );
|
cmd.writeCommandToPacket ( packet );
|
||||||
|
|
||||||
mComm->PacketSend(packet);
|
mComm->PacketSend(packet);
|
||||||
|
|
||||||
mCurrentCommands = mSendCommands;
|
TicUpdate &update = mTicUpdates[mServerTic % BACKUPTICS];
|
||||||
mSendCommands.Clear();
|
if (update.received)
|
||||||
|
{
|
||||||
|
if (playeringame[consoleplayer] && players[consoleplayer].mo)
|
||||||
|
{
|
||||||
|
players[consoleplayer].mo->SetXYZ(update.x, update.y, update.z);
|
||||||
|
players[consoleplayer].mo->Angles.Yaw = update.yaw;
|
||||||
|
players[consoleplayer].mo->Angles.Pitch = update.pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
update.received = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int NetClient::GetSendTick() const
|
int NetClient::GetSendTick() const
|
||||||
|
@ -196,8 +233,7 @@ void NetClient::RunCommands(int player)
|
||||||
|
|
||||||
void NetClient::WriteLocalInput(ticcmd_t cmd)
|
void NetClient::WriteLocalInput(ticcmd_t cmd)
|
||||||
{
|
{
|
||||||
mCurrentInput[consoleplayer] = cmd;
|
mSentInput[(mSendTic - 1) % BACKUPTICS] = cmd;
|
||||||
mSentInput[gametic % BACKUPTICS] = cmd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetClient::WriteBotInput(int player, const ticcmd_t &cmd)
|
void NetClient::WriteBotInput(int player, const ticcmd_t &cmd)
|
||||||
|
@ -284,25 +320,42 @@ void NetClient::OnDisconnect(const NetPacket &packet)
|
||||||
mStatus = NodeStatus::Closed;
|
mStatus = NodeStatus::Closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetClient::UpdateLastReceivedTic(int tic)
|
||||||
|
{
|
||||||
|
if (mLastReceivedTic != -1)
|
||||||
|
{
|
||||||
|
int delta = tic - (mLastReceivedTic & 0xff);
|
||||||
|
if (delta > 128) delta -= 256;
|
||||||
|
else if (delta < -128) delta += 256;
|
||||||
|
mLastReceivedTic += delta;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mLastReceivedTic = tic;
|
||||||
|
}
|
||||||
|
mLastReceivedTic = MAX(mLastReceivedTic, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void NetClient::OnTic(NetPacket &packet)
|
void NetClient::OnTic(NetPacket &packet)
|
||||||
{
|
{
|
||||||
int tic = packet.stream.ReadByte();
|
UpdateLastReceivedTic(packet.stream.ReadByte());
|
||||||
float x = packet.stream.ReadFloat();
|
|
||||||
float y = packet.stream.ReadFloat();
|
|
||||||
float z = packet.stream.ReadFloat();
|
|
||||||
float yaw = packet.stream.ReadFloat();
|
|
||||||
float pitch = packet.stream.ReadFloat();
|
|
||||||
|
|
||||||
if (playeringame[consoleplayer] && players[consoleplayer].mo)
|
TicUpdate update;
|
||||||
{
|
update.received = true;
|
||||||
players[consoleplayer].mo->SetXYZ(x, y, z);
|
update.x = packet.stream.ReadFloat();
|
||||||
players[consoleplayer].mo->Angles.Yaw = yaw;
|
update.y = packet.stream.ReadFloat();
|
||||||
players[consoleplayer].mo->Angles.Pitch = pitch;
|
update.z = packet.stream.ReadFloat();
|
||||||
}
|
update.yaw = packet.stream.ReadFloat();
|
||||||
|
update.pitch = packet.stream.ReadFloat();
|
||||||
|
|
||||||
|
mTicUpdates[mLastReceivedTic % BACKUPTICS] = update;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetClient::OnSpawnPlayer(NetPacket &packet)
|
void NetClient::OnSpawnPlayer(NetPacket &packet)
|
||||||
{
|
{
|
||||||
|
// To do: this needs a tic and should be inserted in mTicUpdates.
|
||||||
|
// Otherwise it might not arrive at the intended moment in time.
|
||||||
|
|
||||||
int player = packet.stream.ReadByte();
|
int player = packet.stream.ReadByte();
|
||||||
const float x = packet.stream.ReadFloat();
|
const float x = packet.stream.ReadFloat();
|
||||||
const float y = packet.stream.ReadFloat();
|
const float y = packet.stream.ReadFloat();
|
||||||
|
@ -320,7 +373,7 @@ void NetClient::OnSpawnPlayer(NetPacket &packet)
|
||||||
|
|
||||||
// This player is now in the game.
|
// This player is now in the game.
|
||||||
playeringame[player] = true;
|
playeringame[player] = true;
|
||||||
player_t p = players[player];
|
player_t &p = players[player];
|
||||||
|
|
||||||
if ( cl_showspawnnames )
|
if ( cl_showspawnnames )
|
||||||
Printf ( "Spawning player %d at %f,%f,%f (id %d)\n", player, x, y, z, netID );
|
Printf ( "Spawning player %d at %f,%f,%f (id %d)\n", player, x, y, z, netID );
|
||||||
|
|
|
@ -30,7 +30,7 @@ public:
|
||||||
|
|
||||||
void Update() override;
|
void Update() override;
|
||||||
|
|
||||||
void SetCurrentTic(int receivetic, int sendtic) override;
|
void SetCurrentTic(int tictime) override;
|
||||||
void EndCurrentTic() override;
|
void EndCurrentTic() override;
|
||||||
|
|
||||||
int GetSendTick() const override;
|
int GetSendTick() const override;
|
||||||
|
@ -56,11 +56,28 @@ private:
|
||||||
void OnTic(NetPacket &packet);
|
void OnTic(NetPacket &packet);
|
||||||
void OnSpawnPlayer(NetPacket &packet);
|
void OnSpawnPlayer(NetPacket &packet);
|
||||||
|
|
||||||
|
void UpdateLastReceivedTic(int tic);
|
||||||
|
|
||||||
std::unique_ptr<doomcom_t> mComm;
|
std::unique_ptr<doomcom_t> mComm;
|
||||||
int mServerNode = -1;
|
int mServerNode = -1;
|
||||||
int mPlayer = -1;
|
int mPlayer = -1;
|
||||||
NodeStatus mStatus = NodeStatus::Closed;
|
NodeStatus mStatus = NodeStatus::Closed;
|
||||||
|
|
||||||
int mSendTic = 0;
|
int mSendTic = 0;
|
||||||
|
int mServerTic = 0;
|
||||||
|
int mServerTicDelta = -1;
|
||||||
|
int mLastReceivedTic = -1;
|
||||||
|
|
||||||
|
struct TicUpdate
|
||||||
|
{
|
||||||
|
bool received = false;
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
float yaw;
|
||||||
|
float pitch;
|
||||||
|
};
|
||||||
|
TicUpdate mTicUpdates[BACKUPTICS];
|
||||||
|
|
||||||
ticcmd_t mCurrentInput[MAXPLAYERS];
|
ticcmd_t mCurrentInput[MAXPLAYERS];
|
||||||
ticcmd_t mSentInput[BACKUPTICS];
|
ticcmd_t mSentInput[BACKUPTICS];
|
||||||
|
|
|
@ -76,16 +76,17 @@ NetServer::NetServer()
|
||||||
|
|
||||||
void NetServer::Update()
|
void NetServer::Update()
|
||||||
{
|
{
|
||||||
|
// Read all packets currently available from clients
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
NetPacket packet;
|
NetPacket packet;
|
||||||
mComm->PacketGet(packet);
|
mComm->PacketGet(packet);
|
||||||
if (packet.node == -1)
|
if (packet.node == -1)
|
||||||
break;
|
break; // No more packets. We are done.
|
||||||
|
|
||||||
NetNode &node = mNodes[packet.node];
|
NetNode &node = mNodes[packet.node];
|
||||||
|
|
||||||
if (packet.size == 0)
|
if (packet.size == 0) // Connection to node closed (timed out)
|
||||||
{
|
{
|
||||||
OnClose(node, packet);
|
OnClose(node, packet);
|
||||||
}
|
}
|
||||||
|
@ -108,15 +109,27 @@ void NetServer::Update()
|
||||||
case NetPacketType::Tic: OnTic(node, packet); break;
|
case NetPacketType::Tic: OnTic(node, packet); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetServer::SetCurrentTic(int receivetic, int sendtic)
|
void NetServer::SetCurrentTic(int tictime)
|
||||||
{
|
{
|
||||||
gametic = receivetic;
|
gametic = tictime;
|
||||||
mSendTic = sendtic;
|
|
||||||
|
for (int i = 0; i < MAXNETNODES; i++)
|
||||||
|
{
|
||||||
|
NetNode &node = mNodes[i];
|
||||||
|
if (node.Status == NodeStatus::InGame && node.Player != -1)
|
||||||
|
{
|
||||||
|
NetNode::TicUpdate &update = node.TicUpdates[gametic % BACKUPTICS];
|
||||||
|
if (update.received)
|
||||||
|
{
|
||||||
|
mCurrentInput[node.Player].ucmd = update.input;
|
||||||
|
update.received = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetServer::EndCurrentTic()
|
void NetServer::EndCurrentTic()
|
||||||
|
@ -160,7 +173,7 @@ void NetServer::EndCurrentTic()
|
||||||
|
|
||||||
int NetServer::GetSendTick() const
|
int NetServer::GetSendTick() const
|
||||||
{
|
{
|
||||||
return mSendTic;
|
return gametic;
|
||||||
}
|
}
|
||||||
|
|
||||||
ticcmd_t NetServer::GetPlayerInput(int player) const
|
ticcmd_t NetServer::GetPlayerInput(int player) const
|
||||||
|
@ -223,7 +236,7 @@ void NetServer::OnClose(NetNode &node, const NetPacket &packet)
|
||||||
{
|
{
|
||||||
if (node.Status == NodeStatus::InGame)
|
if (node.Status == NodeStatus::InGame)
|
||||||
{
|
{
|
||||||
Printf("Player %d left the server", node.Player);
|
Printf("Player %d left the server\n", node.Player);
|
||||||
|
|
||||||
playeringame[node.Player] = false;
|
playeringame[node.Player] = false;
|
||||||
players[node.Player].settings_controller = false;
|
players[node.Player].settings_controller = false;
|
||||||
|
@ -234,29 +247,49 @@ void NetServer::OnClose(NetNode &node, const NetPacket &packet)
|
||||||
mComm->Close(packet.node);
|
mComm->Close(packet.node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetServer::OnConnectRequest(NetNode &node, const NetPacket &packet)
|
void NetServer::OnConnectRequest(NetNode &node, NetPacket &packet)
|
||||||
{
|
{
|
||||||
// Search for a spot in the player list
|
// Make the initial connect packet a bit more complex than a bunch of zeros..
|
||||||
if (node.Status != NodeStatus::InGame)
|
if (strcmp(packet.stream.ReadString(), "ZDoom Connect Request") != 0)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAXPLAYERS; i++)
|
if (node.Status == NodeStatus::InGame)
|
||||||
{
|
{
|
||||||
if (!playeringame[i])
|
Printf("Junk data received from a joined player\n");
|
||||||
{
|
}
|
||||||
node.Player = i;
|
else
|
||||||
playeringame[i] = true;
|
{
|
||||||
players[i].settings_controller = false;
|
node.Status = NodeStatus::Closed;
|
||||||
break;
|
mComm->Close(packet.node);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.Status == NodeStatus::InGame)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Search for a spot in the player list
|
||||||
|
for (int i = 0; i < MAXPLAYERS; i++)
|
||||||
|
{
|
||||||
|
if (!playeringame[i])
|
||||||
|
{
|
||||||
|
node.Player = i;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.Player != -1) // Join accepted.
|
if (node.Player != -1) // Join accepted.
|
||||||
{
|
{
|
||||||
Printf("Player %d joined the server", node.Player);
|
Printf("Player %d joined the server\n", node.Player);
|
||||||
|
|
||||||
|
for (int i = 0; i < BACKUPTICS; i++)
|
||||||
|
node.TicUpdates[i].received = false;
|
||||||
|
|
||||||
|
node.Status = NodeStatus::InGame;
|
||||||
mNodeForPlayer[node.Player] = packet.node;
|
mNodeForPlayer[node.Player] = packet.node;
|
||||||
|
|
||||||
|
playeringame[node.Player] = true;
|
||||||
|
players[node.Player].settings_controller = false;
|
||||||
|
|
||||||
NetPacket response;
|
NetPacket response;
|
||||||
response.node = packet.node;
|
response.node = packet.node;
|
||||||
|
|
||||||
|
@ -267,8 +300,6 @@ void NetServer::OnConnectRequest(NetNode &node, const NetPacket &packet)
|
||||||
|
|
||||||
mComm->PacketSend(response);
|
mComm->PacketSend(response);
|
||||||
|
|
||||||
node.Status = NodeStatus::InGame;
|
|
||||||
|
|
||||||
FullUpdate ( node );
|
FullUpdate ( node );
|
||||||
}
|
}
|
||||||
else // Server is full.
|
else // Server is full.
|
||||||
|
@ -294,7 +325,7 @@ void NetServer::OnDisconnect(NetNode &node, const NetPacket &packet)
|
||||||
{
|
{
|
||||||
if (node.Status == NodeStatus::InGame)
|
if (node.Status == NodeStatus::InGame)
|
||||||
{
|
{
|
||||||
Printf("Player %d left the server", node.Player);
|
Printf("Player %d left the server\n", node.Player);
|
||||||
|
|
||||||
playeringame[node.Player] = false;
|
playeringame[node.Player] = false;
|
||||||
players[node.Player].settings_controller = false;
|
players[node.Player].settings_controller = false;
|
||||||
|
@ -307,16 +338,29 @@ void NetServer::OnDisconnect(NetNode &node, const NetPacket &packet)
|
||||||
|
|
||||||
void NetServer::OnTic(NetNode &node, NetPacket &packet)
|
void NetServer::OnTic(NetNode &node, NetPacket &packet)
|
||||||
{
|
{
|
||||||
if (node.Status == NodeStatus::InGame)
|
if (node.Status != NodeStatus::InGame)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int tic = packet.stream.ReadByte();
|
||||||
|
|
||||||
|
int delta = tic - (gametic & 0xff);
|
||||||
|
if (delta > 128) delta -= 256;
|
||||||
|
else if (delta < -128) delta += 256;
|
||||||
|
tic = gametic + delta;
|
||||||
|
|
||||||
|
if (tic <= gametic)
|
||||||
{
|
{
|
||||||
/* gametic */ packet.stream.ReadByte();
|
// Packet arrived too late.
|
||||||
packet.stream.ReadBuffer ( &mCurrentInput[node.Player].ucmd, sizeof(usercmd_t));
|
tic = gametic + 1;
|
||||||
}
|
|
||||||
else
|
if (tic < 0 || node.TicUpdates[tic % BACKUPTICS].received)
|
||||||
{
|
return; // We already received the proper packet.
|
||||||
node.Status = NodeStatus::Closed;
|
|
||||||
mComm->Close(packet.node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetNode::TicUpdate update;
|
||||||
|
update.received = true;
|
||||||
|
packet.stream.ReadBuffer(&update.input, sizeof(usercmd_t));
|
||||||
|
node.TicUpdates[tic % BACKUPTICS] = update;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetServer::CmdSpawnPlayer(NetNode &node, int player)
|
void NetServer::CmdSpawnPlayer(NetNode &node, int player)
|
||||||
|
|
|
@ -38,7 +38,13 @@ struct NetNode
|
||||||
int Gametic = 0;
|
int Gametic = 0;
|
||||||
int Player = -1;
|
int Player = -1;
|
||||||
|
|
||||||
ticcmd_t PlayerMovement;
|
struct TicUpdate
|
||||||
|
{
|
||||||
|
bool received = false;
|
||||||
|
usercmd_t input;
|
||||||
|
};
|
||||||
|
TicUpdate TicUpdates[BACKUPTICS];
|
||||||
|
|
||||||
FDynamicBuffer Commands; // "NetSpecs"
|
FDynamicBuffer Commands; // "NetSpecs"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -49,7 +55,7 @@ public:
|
||||||
|
|
||||||
void Update() override;
|
void Update() override;
|
||||||
|
|
||||||
void SetCurrentTic(int receivetic, int sendtic) override;
|
void SetCurrentTic(int tictime) override;
|
||||||
void EndCurrentTic() override;
|
void EndCurrentTic() override;
|
||||||
|
|
||||||
int GetSendTick() const override;
|
int GetSendTick() const override;
|
||||||
|
@ -70,7 +76,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnClose(NetNode &node, const NetPacket &packet);
|
void OnClose(NetNode &node, const NetPacket &packet);
|
||||||
void OnConnectRequest(NetNode &node, const NetPacket &packet);
|
void OnConnectRequest(NetNode &node, NetPacket &packet);
|
||||||
void OnDisconnect(NetNode &node, const NetPacket &packet);
|
void OnDisconnect(NetNode &node, const NetPacket &packet);
|
||||||
void OnTic(NetNode &node, NetPacket &packet);
|
void OnTic(NetNode &node, NetPacket &packet);
|
||||||
|
|
||||||
|
@ -80,7 +86,6 @@ private:
|
||||||
std::unique_ptr<doomcom_t> mComm;
|
std::unique_ptr<doomcom_t> mComm;
|
||||||
NetNode mNodes[MAXNETNODES];
|
NetNode mNodes[MAXNETNODES];
|
||||||
int mNodeForPlayer[MAXPLAYERS];
|
int mNodeForPlayer[MAXPLAYERS];
|
||||||
int mSendTic = 0;
|
|
||||||
|
|
||||||
ticcmd_t mCurrentInput[MAXPLAYERS];
|
ticcmd_t mCurrentInput[MAXPLAYERS];
|
||||||
FDynamicBuffer mCurrentCommands;
|
FDynamicBuffer mCurrentCommands;
|
||||||
|
|
|
@ -82,10 +82,9 @@ void NetSinglePlayer::Update()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetSinglePlayer::SetCurrentTic(int receivetic, int sendtic)
|
void NetSinglePlayer::SetCurrentTic(int tictime)
|
||||||
{
|
{
|
||||||
gametic = receivetic;
|
gametic = tictime;
|
||||||
mSendTic = sendtic;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetSinglePlayer::EndCurrentTic()
|
void NetSinglePlayer::EndCurrentTic()
|
||||||
|
@ -96,7 +95,7 @@ void NetSinglePlayer::EndCurrentTic()
|
||||||
|
|
||||||
int NetSinglePlayer::GetSendTick() const
|
int NetSinglePlayer::GetSendTick() const
|
||||||
{
|
{
|
||||||
return mSendTic;
|
return gametic;
|
||||||
}
|
}
|
||||||
|
|
||||||
ticcmd_t NetSinglePlayer::GetPlayerInput(int player) const
|
ticcmd_t NetSinglePlayer::GetPlayerInput(int player) const
|
||||||
|
|
|
@ -30,7 +30,7 @@ public:
|
||||||
|
|
||||||
void Update() override;
|
void Update() override;
|
||||||
|
|
||||||
void SetCurrentTic(int receivetic, int sendtic) override;
|
void SetCurrentTic(int tictime) override;
|
||||||
void EndCurrentTic() override;
|
void EndCurrentTic() override;
|
||||||
|
|
||||||
int GetSendTick() const override;
|
int GetSendTick() const override;
|
||||||
|
@ -53,6 +53,5 @@ private:
|
||||||
ticcmd_t mCurrentInput[MAXPLAYERS];
|
ticcmd_t mCurrentInput[MAXPLAYERS];
|
||||||
FDynamicBuffer mCurrentCommands;
|
FDynamicBuffer mCurrentCommands;
|
||||||
|
|
||||||
int mSendTic = 0;
|
|
||||||
FDynamicBuffer mSendCommands;
|
FDynamicBuffer mSendCommands;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue