diff --git a/src/d_main.cpp b/src/d_main.cpp index 27a1cffca2c..daa5c50be27 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1061,7 +1061,7 @@ class PlaySim for (int i = 0; i < tics; i++) { - network->SetCurrentTic(gametime.BaseGameTic() + i); + network->BeginTic(); network->WriteLocalInput(G_BuildTiccmd()); if (advancedemo) @@ -1071,7 +1071,7 @@ class PlaySim M_Ticker(); G_Ticker(); - network->EndCurrentTic(); + network->EndTic(); LoopBackCommands(); } diff --git a/src/network/net.h b/src/network/net.h index 599aa35387f..aa11a8b8134 100644 --- a/src/network/net.h +++ b/src/network/net.h @@ -40,11 +40,9 @@ class Network // Check for incoming packets virtual void Update() = 0; - // Set current tic time - virtual void SetCurrentTic(int localtic) = 0; - - // Send any pending outgoing data - virtual void EndCurrentTic() = 0; + // Called when starting and ending a playsim tic + virtual void BeginTic() = 0; + virtual void EndTic() = 0; // Retrieve data about the current tic virtual int GetSendTick() const = 0; @@ -57,7 +55,6 @@ class Network // Statistics virtual int GetPing(int player) const = 0; - virtual int GetServerPing() const = 0; int GetHighPingThreshold() const { return ((BACKUPTICS / 2 - 1)) * (1000 / TICRATE); } // CCMDs diff --git a/src/network/netclient.cpp b/src/network/netclient.cpp index 28589fd6baf..8d2924eddde 100644 --- a/src/network/netclient.cpp +++ b/src/network/netclient.cpp @@ -77,13 +77,9 @@ NetClient::NetClient(FString server) mServerNode = mComm->Connect(server); mStatus = NodeStatus::InPreGame; - NetOutputPacket packet(mServerNode); - - NetCommand cmd ( NetPacketType::ConnectRequest ); - cmd.addString("ZDoom Connect Request"); - cmd.writeCommandToStream (packet.stream); - - mComm->PacketSend(packet); + NetCommand cmd(NetPacketType::ConnectRequest); + cmd.AddString("ZDoom Connect Request"); + cmd.WriteToNode(mOutput); } void NetClient::Update() @@ -95,77 +91,81 @@ void NetClient::Update() if (packet.node == -1) break; - if (packet.node != mServerNode) + if (packet.node == mServerNode) { - mComm->Close(packet.node); + mInput.ReceivedPacket(packet, mOutput); } - else if (packet.stream.IsAtEnd()) + else { - OnClose(); - break; + mComm->Close(packet.node); } - else + } + + while (mStatus == NodeStatus::InPreGame) + { + mOutput.Send(mComm.get(), mServerNode); + + ByteInputStream message = mInput.ReadMessage(); + if (message.IsAtEnd()) + break; + + NetPacketType type = (NetPacketType)message.ReadByte(); + switch (type) { - UpdateLastReceivedTic(packet.stream.ReadByte()); - - if (mStatus == NodeStatus::InPreGame) - { - ProcessCommands(packet.stream); - } - else - { - auto &ticUpdate = mTicUpdates[mLastReceivedTic % BACKUPTICS]; - ticUpdate.Resize(packet.stream.BytesLeft()); - packet.stream.ReadBuffer(ticUpdate.Data(), ticUpdate.Size()); - } + default: OnClose(); break; + case NetPacketType::ConnectResponse: OnConnectResponse(message); break; } + } - if (mStatus == NodeStatus::Closed) + if (mStatus == NodeStatus::Closed) + { + if (network.get() == this) + { + network.reset(new NetSinglePlayer()); + G_EndNetGame(); + } + else { - if (network.get() == this) - { - network.reset(new NetSinglePlayer()); - G_EndNetGame(); - } - else - { - netconnect.reset(); - } - return; + netconnect.reset(); } } } -void NetClient::SetCurrentTic(int tictime) +void NetClient::BeginTic() { - gametic = tictime; - mSendTic = gametic + 10; + // [BB] Don't check net packets while we are supposed to load a map. + // This way the commands from the full update will not be parsed before we loaded the map. + if ((gameaction == ga_newgame) || (gameaction == ga_newgame2)) + return; - if (abs(gametic + mServerTicDelta - mLastReceivedTic) > jitter) + while (mStatus == NodeStatus::InGame) { - mServerTicDelta = mLastReceivedTic - gametic - jitter; - } + ByteInputStream message = mInput.ReadMessage(); + if (message.IsAtEnd()) + break; - mServerTic = MAX(gametic + mServerTicDelta, 0); + //UpdateLastReceivedTic(message.ReadByte()); - mCurrentInput[consoleplayer] = mSentInput[gametic % BACKUPTICS]; + NetPacketType type = (NetPacketType)message.ReadByte(); + switch (type) + { + default: OnClose(); break; + case NetPacketType::Disconnect: OnDisconnect(); break; + case NetPacketType::Tic: OnTic(message); break; + case NetPacketType::SpawnActor: OnSpawnActor(message); break; + case NetPacketType::DestroyActor: OnDestroyActor(message); break; + } + } - // [BB] Don't check net packets while we are supposed to load a map. - // This way the commands from the full update will not be parsed before we loaded the map. - //if ((gameaction == ga_newgame) || (gameaction == ga_newgame2)) - // return; + gametic = mReceiveTic; + mSendTic++; - TArray &update = mTicUpdates[mServerTic % BACKUPTICS]; - if (update.Size() > 0) - { - ByteInputStream stream(update.Data(), update.Size()); - ProcessCommands(stream); - update.Clear(); - } + mCurrentInput[consoleplayer] = mSentInput[gametic % BACKUPTICS]; } -void NetClient::EndCurrentTic() +void NetClient::EndTic() { + mOutput.Send(mComm.get(), mServerNode); } int NetClient::GetSendTick() const @@ -189,16 +189,10 @@ void NetClient::WriteLocalInput(ticcmd_t ticcmd) if (mStatus == NodeStatus::InGame) { - int targettic = (mSendTic + mServerTicDelta); - - NetOutputPacket packet(mServerNode); - NetCommand cmd(NetPacketType::Tic); - cmd.addByte(targettic); // target gametic - cmd.addBuffer(&ticcmd.ucmd, sizeof(usercmd_t)); - cmd.writeCommandToStream(packet.stream); - - mComm->PacketSend(packet); + cmd.AddByte(mSendTic); + cmd.AddBuffer(&ticcmd.ucmd, sizeof(usercmd_t)); + cmd.WriteToNode(mOutput, true); } } @@ -209,12 +203,10 @@ void NetClient::WriteBotInput(int player, const ticcmd_t &cmd) int NetClient::GetPing(int player) const { - return 0; -} - -int NetClient::GetServerPing() const -{ - return 0; + if (player == consoleplayer) + return (mSendTic - mReceiveTic) * 1000 / TICRATE; + else + return 0; } void NetClient::ListPingTimes() @@ -234,39 +226,6 @@ void NetClient::ActorDestroyed(AActor *actor) { } -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::ProcessCommands(ByteInputStream &stream) -{ - while (stream.IsAtEnd() == false) - { - NetPacketType type = (NetPacketType)stream.ReadByte(); - switch (type) - { - default: OnClose(); break; - case NetPacketType::ConnectResponse: OnConnectResponse(stream); break; - case NetPacketType::Disconnect: OnDisconnect(); break; - case NetPacketType::Tic: OnTic(stream); break; - case NetPacketType::SpawnActor: OnSpawnActor(stream); break; - case NetPacketType::DestroyActor: OnDestroyActor(stream); break; - } - } -} - void NetClient::OnClose() { mComm->Close(mServerNode); @@ -293,7 +252,6 @@ void NetClient::OnConnectResponse(ByteInputStream &stream) { mPlayer = playernum; mStatus = NodeStatus::InGame; - mServerTicDelta = mLastReceivedTic - gametic - jitter; G_InitClientNetGame(mPlayer, "e1m1"); @@ -326,6 +284,14 @@ void NetClient::OnDisconnect() void NetClient::OnTic(ByteInputStream &stream) { + int inputtic = stream.ReadByte(); + int delta = (mSendTic & 0xff) - inputtic; + if (delta < -0x7f) + delta += 0xff; + else if (delta > 0x7f) + delta -= 0xff; + mReceiveTic = std::max(mSendTic - delta, 0); + DVector3 Pos, Vel; float yaw, pitch; Pos.X = stream.ReadFloat(); diff --git a/src/network/netclient.h b/src/network/netclient.h index 8c56854e6f0..8acd9a2993d 100644 --- a/src/network/netclient.h +++ b/src/network/netclient.h @@ -23,6 +23,7 @@ #include "netserver.h" #include "netcommand.h" +#include "netnode.h" #include "playsim/a_dynlight.h" class NetClient : public Network @@ -32,8 +33,8 @@ class NetClient : public Network void Update() override; - void SetCurrentTic(int tictime) override; - void EndCurrentTic() override; + void BeginTic() override; + void EndTic() override; int GetSendTick() const override; ticcmd_t GetPlayerInput(int player) const override; @@ -43,7 +44,6 @@ class NetClient : public Network void WriteBotInput(int player, const ticcmd_t &cmd) override; int GetPing(int player) const override; - int GetServerPing() const override; void ListPingTimes() override; void Network_Controller(int playernum, bool add) override; @@ -59,22 +59,15 @@ class NetClient : public Network void OnSpawnActor(ByteInputStream &stream); void OnDestroyActor(ByteInputStream &stream); - void ProcessCommands(ByteInputStream &stream); - void UpdateLastReceivedTic(int tic); - std::unique_ptr mComm; + NetNodeInput mInput; + NetNodeOutput mOutput; int mServerNode = -1; int mPlayer = -1; NodeStatus mStatus = NodeStatus::Closed; - int mSendTic = 0; - int mServerTic = 0; - int mServerTicDelta = -1; - int mLastReceivedTic = -1; - - int jitter = 2; - - TArray mTicUpdates[BACKUPTICS]; + int mReceiveTic = 0; + int mSendTic = 1; ticcmd_t mCurrentInput[MAXPLAYERS]; ticcmd_t mSentInput[BACKUPTICS]; diff --git a/src/network/netcommand.cpp b/src/network/netcommand.cpp index db06d85f3b3..135cb208567 100644 --- a/src/network/netcommand.cpp +++ b/src/network/netcommand.cpp @@ -18,6 +18,7 @@ #include "d_player.h" #include "netcommand.h" +#include "netnode.h" #include "i_net.h" extern bool netserver, netclient; @@ -411,31 +412,31 @@ NetCommand::NetCommand(const NetPacketType Header) // To do: improve memory handling here. 8 kb per command is very wasteful mStream.SetBuffer(MAX_UDP_PACKET); - addByte(static_cast(Header)); + AddByte(static_cast(Header)); } -void NetCommand::addInteger(const int IntValue, const int Size) +void NetCommand::AddInteger(const int IntValue, const int Size) { for (int i = 0; i < Size; ++i) mStream.WriteByte((IntValue >> (8 * i)) & 0xff); } -void NetCommand::addByte(const int ByteValue) +void NetCommand::AddByte(const int ByteValue) { - addInteger(static_cast (ByteValue), sizeof(uint8_t)); + AddInteger(static_cast (ByteValue), sizeof(uint8_t)); } -void NetCommand::addShort(const int ShortValue) +void NetCommand::AddShort(const int ShortValue) { - addInteger(static_cast (ShortValue), sizeof(int16_t)); + AddInteger(static_cast (ShortValue), sizeof(int16_t)); } -void NetCommand::addLong(const int32_t LongValue) +void NetCommand::AddLong(const int32_t LongValue) { - addInteger(LongValue, sizeof(int32_t)); + AddInteger(LongValue, sizeof(int32_t)); } -void NetCommand::addFloat(const float FloatValue) +void NetCommand::AddFloat(const float FloatValue) { union { @@ -443,25 +444,25 @@ void NetCommand::addFloat(const float FloatValue) int32_t l; } dat; dat.f = FloatValue; - addInteger(dat.l, sizeof(int32_t)); + AddInteger(dat.l, sizeof(int32_t)); } -void NetCommand::addBit(const bool value) +void NetCommand::AddBit(const bool value) { mStream.WriteBit(value); } -void NetCommand::addVariable(const int value) +void NetCommand::AddVariable(const int value) { mStream.WriteVariable(value); } -void NetCommand::addShortByte(int value, int bits) +void NetCommand::AddShortByte(int value, int bits) { mStream.WriteShortByte(value, bits); } -void NetCommand::addString(const char *pszString) +void NetCommand::AddString(const char *pszString) { const int len = (pszString != nullptr) ? (int)strlen(pszString) : 0; @@ -472,34 +473,29 @@ void NetCommand::addString(const char *pszString) } for (int i = 0; i < len; ++i) - addByte(pszString[i]); - addByte(0); + AddByte(pszString[i]); + AddByte(0); } -void NetCommand::addName(FName name) +void NetCommand::AddName(FName name) { if (name.IsPredefined()) { - addShort(name); + AddShort(name); } else { - addShort(-1); - addString(name); + AddShort(-1); + AddString(name); } } -void NetCommand::addBuffer(const void *pvBuffer, int nLength) +void NetCommand::AddBuffer(const void *pvBuffer, int nLength) { mStream.WriteBuffer(pvBuffer, nLength); } -void NetCommand::writeCommandToStream(ByteOutputStream &stream) const +void NetCommand::WriteToNode(NetNodeOutput& node, bool unreliable) const { - stream.WriteBuffer(mStream.GetData(), mStream.GetSize()); -} - -int NetCommand::getSize() const -{ - return mStream.GetSize(); + node.WriteMessage(mStream.GetData(), mStream.GetSize(), unreliable); } diff --git a/src/network/netcommand.h b/src/network/netcommand.h index 31c7e4fda78..c97108adcde 100644 --- a/src/network/netcommand.h +++ b/src/network/netcommand.h @@ -21,6 +21,8 @@ enum class NetPacketType DestroyActor }; +class NetNodeOutput; + class ByteInputStream { public: @@ -108,24 +110,21 @@ class ByteOutputStream class NetCommand { ByteOutputStream mStream; - bool mUnreliable = false; public: NetCommand ( const NetPacketType Header ); - void addInteger( const int IntValue, const int Size ); - void addByte ( const int ByteValue ); - void addShort ( const int ShortValue ); - void addLong ( const int32_t LongValue ); - void addFloat ( const float FloatValue ); - void addString ( const char *pszString ); - void addName ( FName name ); - void addBit ( const bool value ); - void addVariable ( const int value ); - void addShortByte ( int value, int bits ); - void addBuffer ( const void *pvBuffer, int nLength ); - void writeCommandToStream ( ByteOutputStream &stream ) const; - bool isUnreliable() const { return mUnreliable; } - void setUnreliable(bool a) { mUnreliable = a; } - int getSize() const; + void AddInteger( const int IntValue, const int Size ); + void AddByte ( const int ByteValue ); + void AddShort ( const int ShortValue ); + void AddLong ( const int32_t LongValue ); + void AddFloat ( const float FloatValue ); + void AddString ( const char *pszString ); + void AddName ( FName name ); + void AddBit ( const bool value ); + void AddVariable ( const int value ); + void AddShortByte ( int value, int bits ); + void AddBuffer ( const void *pvBuffer, int nLength ); + + void WriteToNode(NetNodeOutput &node, bool unreliable = false) const; }; diff --git a/src/network/netnode.cpp b/src/network/netnode.cpp index 0ad94c25e89..4b482c57980 100644 --- a/src/network/netnode.cpp +++ b/src/network/netnode.cpp @@ -9,6 +9,9 @@ void NetNodeOutput::WriteMessage(const void* data, size_t size, bool unreliable) void NetNodeOutput::Send(doomcom_t* comm, int nodeIndex) { + if (mMessages.empty()) + return; + NetOutputPacket packet(nodeIndex); packet.stream.WriteByte(0); packet.stream.WriteByte(mHeaderFlags); diff --git a/src/network/netserver.cpp b/src/network/netserver.cpp index 1eb62eb8062..f9d841b7ada 100644 --- a/src/network/netserver.cpp +++ b/src/network/netserver.cpp @@ -69,8 +69,6 @@ NetServer::NetServer() { Printf("Started hosting multiplayer game..\n"); - mBroadcastCommands.SetBuffer(MAX_MSGLEN); - for (int i = 0; i < MAXNETNODES; i++) mNodes[i].NodeIndex = i; @@ -81,132 +79,80 @@ NetServer::NetServer() void NetServer::Update() { - // Read all packets currently available from clients while (true) { NetInputPacket packet; mComm->PacketGet(packet); if (packet.node == -1) - break; // No more packets. We are done. - - NetNode &node = mNodes[packet.node]; + break; - if (packet.stream.IsAtEnd()) // Connection to node closed (timed out) + NetNode& node = mNodes[packet.node]; + if (packet.stream.IsAtEnd()) { - OnClose(node, packet.stream); + // Connection to node closed (timed out) + Close(node); } else { - while (packet.stream.IsAtEnd() == false) - { - NetPacketType type = (NetPacketType)packet.stream.ReadByte(); - switch (type) - { - default: OnClose(node, packet.stream); break; - case NetPacketType::ConnectRequest: OnConnectRequest(node, packet.stream); break; - case NetPacketType::Disconnect: OnDisconnect(node, packet.stream); break; - case NetPacketType::Tic: OnTic(node, packet.stream); break; - } - } + node.Input.ReceivedPacket(packet, node.Output); } } -} - -void NetServer::SetCurrentTic(int tictime) -{ - gametic = tictime; - for (int i = 0; i < MAXNETNODES; i++) + for (int nodeIndex = 0; nodeIndex < MAXNETNODES; nodeIndex++) { - NetNode &node = mNodes[i]; - if (node.Status == NodeStatus::InGame && node.Player != -1) + NetNode &node = mNodes[nodeIndex]; + while (node.Status != NodeStatus::Closed) { - NetNode::TicUpdate &update = node.TicUpdates[gametic % BACKUPTICS]; - if (update.received) + ByteInputStream message = node.Input.ReadMessage(); + if (message.IsAtEnd()) + break; + + NetPacketType type = (NetPacketType)message.ReadByte(); + switch (type) { - mCurrentInput[node.Player].ucmd = update.input; - update.received = false; + default: Close(node); break; + case NetPacketType::ConnectRequest: OnConnectRequest(node, message); break; + case NetPacketType::Disconnect: OnDisconnect(node, message); break; + case NetPacketType::Tic: OnTic(node, message); break; } } } } -void NetServer::EndCurrentTic() +void NetServer::BeginTic() +{ + gametic++; +} + +void NetServer::EndTic() { for (int i = 0; i < MAXNETNODES; i++) { if (mNodes[i].Status == NodeStatus::InGame) { - int player = mNodes[i].Player; - - NetOutputPacket packet(i); - packet.stream.WriteByte(gametic + 1); + //packet.stream.WriteByte(gametic + 1); if (mNodes[i].FirstTic) { + int player = mNodes[i].Player; + TThinkerIterator it = primaryLevel->GetThinkerIterator(); AActor *mo; while (mo = it.Next()) { if (mo != players[player].mo) { - CmdSpawnActor(packet.stream, mo); + CmdSpawnActor(i, mo); } } mNodes[i].FirstTic = false; } - packet.stream.WriteBuffer(mBroadcastCommands.GetData(), mBroadcastCommands.GetSize()); - - NetCommand cmd ( NetPacketType::Tic); - - if (playeringame[player] && players[player].mo) - { - cmd.addFloat(static_cast (players[player].mo->X())); - cmd.addFloat(static_cast (players[player].mo->Y())); - cmd.addFloat(static_cast (players[player].mo->Z())); - cmd.addFloat(static_cast (players[player].mo->Vel.X)); - cmd.addFloat(static_cast (players[player].mo->Vel.Y)); - cmd.addFloat(static_cast (players[player].mo->Vel.Z)); - cmd.addFloat(static_cast (players[player].mo->Angles.Yaw.Degrees)); - cmd.addFloat(static_cast (players[player].mo->Angles.Pitch.Degrees)); - } - else - { - cmd.addFloat(0.0f); - cmd.addFloat(0.0f); - cmd.addFloat(0.0f); - cmd.addFloat(0.0f); - cmd.addFloat(0.0f); - cmd.addFloat(0.0f); - cmd.addFloat(0.0f); - cmd.addFloat(0.0f); - } - - TThinkerIterator it = primaryLevel->GetThinkerIterator(); - AActor *mo; - while (mo = it.Next()) - { - if (mo != players[player].mo && mo->syncdata.NetID) - { - cmd.addShort(mo->syncdata.NetID); - cmd.addFloat(static_cast (mo->X())); - cmd.addFloat(static_cast (mo->Y())); - cmd.addFloat(static_cast (mo->Z())); - cmd.addFloat(static_cast (mo->Angles.Yaw.Degrees)); - cmd.addFloat(static_cast (mo->Angles.Pitch.Degrees)); - cmd.addShort(mo->sprite); - cmd.addByte(mo->frame); - } - } - cmd.addShort(-1); - - cmd.writeCommandToStream(packet.stream); - mComm->PacketSend(packet); + CmdTic(i); } - } - mBroadcastCommands.ResetPos(); + mNodes[i].Output.Send(mComm.get(), i); + } } int NetServer::GetSendTick() const @@ -239,11 +185,6 @@ int NetServer::GetPing(int player) const return 0; } -int NetServer::GetServerPing() const -{ - return 0; -} - void NetServer::ListPingTimes() { #if 0 @@ -257,21 +198,6 @@ void NetServer::Network_Controller(int playernum, bool add) { } -void NetServer::OnClose(NetNode &node, ByteInputStream &stream) -{ - if (node.Status == NodeStatus::InGame) - { - Printf("Player %d left the server\n", node.Player); - - playeringame[node.Player] = false; - players[node.Player].settings_controller = false; - node.Player = -1; - } - - node.Status = NodeStatus::Closed; - mComm->Close(node.NodeIndex); -} - void NetServer::OnConnectRequest(NetNode &node, ByteInputStream &stream) { // Make the initial connect packet a bit more complex than a bunch of zeros.. @@ -283,8 +209,7 @@ void NetServer::OnConnectRequest(NetNode &node, ByteInputStream &stream) } else { - node.Status = NodeStatus::Closed; - mComm->Close(node.NodeIndex); + Close(node); return; } } @@ -306,9 +231,6 @@ void NetServer::OnConnectRequest(NetNode &node, ByteInputStream &stream) { Printf("Player %d joined the server\n", node.Player); - for (int i = 0; i < BACKUPTICS; i++) - node.TicUpdates[i].received = false; - node.FirstTic = true; node.Status = NodeStatus::InGame; mNodeForPlayer[node.Player] = node.NodeIndex; @@ -316,48 +238,20 @@ void NetServer::OnConnectRequest(NetNode &node, ByteInputStream &stream) playeringame[node.Player] = true; players[node.Player].settings_controller = false; - NetOutputPacket response(node.NodeIndex); - response.stream.WriteByte(gametic); - - NetCommand cmd ( NetPacketType::ConnectResponse ); - cmd.addByte ( 1 ); // Protocol version - cmd.addByte ( node.Player ); - cmd.writeCommandToStream ( response.stream ); - - mComm->PacketSend(response); + CmdConnectResponse(node.NodeIndex); } else // Server is full. { - node.Status = NodeStatus::Closed; - - NetOutputPacket response(node.NodeIndex); - response.stream.WriteByte(gametic); - - NetCommand cmd ( NetPacketType::ConnectResponse ); - cmd.addByte ( 1 ); // Protocol version - cmd.addByte ( 255 ); - cmd.writeCommandToStream (response.stream); - - mComm->PacketSend(response); - - node.Status = NodeStatus::Closed; - mComm->Close(node.NodeIndex); + CmdConnectResponse(node.NodeIndex); + node.Output.Send(mComm.get(), node.NodeIndex); + Close(node); } } void NetServer::OnDisconnect(NetNode &node, ByteInputStream &stream) { - if (node.Status == NodeStatus::InGame) - { - Printf("Player %d left the server\n", node.Player); - - playeringame[node.Player] = false; - players[node.Player].settings_controller = false; - node.Player = -1; - } - - node.Status = NodeStatus::Closed; - mComm->Close(node.NodeIndex); + node.Output.Send(mComm.get(), node.NodeIndex); + Close(node); } void NetServer::OnTic(NetNode &node, ByteInputStream &stream) @@ -365,43 +259,89 @@ void NetServer::OnTic(NetNode &node, ByteInputStream &stream) if (node.Status != NodeStatus::InGame) return; - int tic = stream.ReadByte(); - int delta = tic - (gametic & 0xff); - if (delta > 128) delta -= 256; - else if (delta < -128) delta += 256; - tic = gametic + delta; + mCurrentInputTic[node.Player] = stream.ReadByte(); + stream.ReadBuffer(&mCurrentInput[node.Player].ucmd, sizeof(usercmd_t)); +} + +void NetServer::CmdConnectResponse(int nodeIndex) +{ + int player = mNodes[nodeIndex].Player; + if (player == -1) + player = 255; + + NetCommand cmd(NetPacketType::ConnectResponse); + cmd.AddByte(1); // Protocol version + cmd.AddByte(player); + WriteCommand(nodeIndex, cmd); +} + +void NetServer::CmdTic(int nodeIndex) +{ + int player = mNodes[nodeIndex].Player; - NetNode::TicUpdate update; - update.received = true; - stream.ReadBuffer(&update.input, sizeof(usercmd_t)); + NetCommand cmd(NetPacketType::Tic); - if (tic <= gametic) + cmd.AddByte(mCurrentInputTic[player]); + + if (playeringame[player] && players[player].mo) + { + cmd.AddFloat(static_cast (players[player].mo->X())); + cmd.AddFloat(static_cast (players[player].mo->Y())); + cmd.AddFloat(static_cast (players[player].mo->Z())); + cmd.AddFloat(static_cast (players[player].mo->Vel.X)); + cmd.AddFloat(static_cast (players[player].mo->Vel.Y)); + cmd.AddFloat(static_cast (players[player].mo->Vel.Z)); + cmd.AddFloat(static_cast (players[player].mo->Angles.Yaw.Degrees)); + cmd.AddFloat(static_cast (players[player].mo->Angles.Pitch.Degrees)); + } + else { - // Packet arrived too late. - tic = gametic + 1; + cmd.AddFloat(0.0f); + cmd.AddFloat(0.0f); + cmd.AddFloat(0.0f); + cmd.AddFloat(0.0f); + cmd.AddFloat(0.0f); + cmd.AddFloat(0.0f); + cmd.AddFloat(0.0f); + cmd.AddFloat(0.0f); + } - if (tic < 0 || node.TicUpdates[tic % BACKUPTICS].received) - return; // We already received the proper packet. + TThinkerIterator it = primaryLevel->GetThinkerIterator(); + AActor* mo; + while (mo = it.Next()) + { + if (mo != players[player].mo && mo->syncdata.NetID) + { + cmd.AddShort(mo->syncdata.NetID); + cmd.AddFloat(static_cast (mo->X())); + cmd.AddFloat(static_cast (mo->Y())); + cmd.AddFloat(static_cast (mo->Z())); + cmd.AddFloat(static_cast (mo->Angles.Yaw.Degrees)); + cmd.AddFloat(static_cast (mo->Angles.Pitch.Degrees)); + cmd.AddShort(mo->sprite); + cmd.AddByte(mo->frame); + } } + cmd.AddShort(-1); - node.TicUpdates[tic % BACKUPTICS] = update; + WriteCommand(nodeIndex, cmd, true); } -void NetServer::CmdSpawnActor(ByteOutputStream &stream, AActor *actor) +void NetServer::CmdSpawnActor(int nodeIndex, AActor *actor) { NetCommand cmd(NetPacketType::SpawnActor); - cmd.addShort(actor->syncdata.NetID); - cmd.addFloat(static_cast(actor->X())); - cmd.addFloat(static_cast(actor->Y())); - cmd.addFloat(static_cast(actor->Z())); - cmd.writeCommandToStream(stream); + cmd.AddShort(actor->syncdata.NetID); + cmd.AddFloat(static_cast(actor->X())); + cmd.AddFloat(static_cast(actor->Y())); + cmd.AddFloat(static_cast(actor->Z())); + WriteCommand(nodeIndex, cmd); } -void NetServer::CmdDestroyActor(ByteOutputStream &stream, AActor *actor) +void NetServer::CmdDestroyActor(int nodeIndex, AActor *actor) { NetCommand cmd(NetPacketType::DestroyActor); - cmd.addShort(actor->syncdata.NetID); - cmd.writeCommandToStream(stream); + cmd.AddShort(actor->syncdata.NetID); + WriteCommand(nodeIndex, cmd); } void NetServer::ActorSpawned(AActor *actor) @@ -409,11 +349,46 @@ void NetServer::ActorSpawned(AActor *actor) actor->syncdata.NetID = mNetIDList.getNewID(); mNetIDList.useID(actor->syncdata.NetID, actor); - CmdSpawnActor(mBroadcastCommands, actor); + CmdSpawnActor(-1, actor); } void NetServer::ActorDestroyed(AActor *actor) { - CmdDestroyActor(mBroadcastCommands, actor); + CmdDestroyActor(-1, actor); mNetIDList.freeID(actor->syncdata.NetID); } + +void NetServer::Close(NetNode &node) +{ + if (node.Status == NodeStatus::InGame) + { + Printf("Player %d left the server\n", node.Player); + + playeringame[node.Player] = false; + players[node.Player].settings_controller = false; + node.Player = -1; + } + + node.Status = NodeStatus::Closed; + node.Input = {}; + node.Output = {}; + mComm->Close(node.NodeIndex); +} + +void NetServer::WriteCommand(int nodeIndex, NetCommand& command, bool unreliable) +{ + if (nodeIndex == -1) + { + for (int i = 0; i < MAXNETNODES; i++) + { + if (mNodes[i].Status == NodeStatus::InGame) + { + command.WriteToNode(mNodes[i].Output, unreliable); + } + } + } + else + { + command.WriteToNode(mNodes[nodeIndex].Output, unreliable); + } +} diff --git a/src/network/netserver.h b/src/network/netserver.h index a5da4be0c29..362616e4044 100644 --- a/src/network/netserver.h +++ b/src/network/netserver.h @@ -23,6 +23,7 @@ #include "net.h" #include "netcommand.h" +#include "netnode.h" enum class NodeStatus { @@ -41,12 +42,8 @@ struct NetNode int NodeIndex = -1; bool FirstTic = true; - struct TicUpdate - { - bool received = false; - usercmd_t input; - }; - TicUpdate TicUpdates[BACKUPTICS]; + NetNodeInput Input; + NetNodeOutput Output; }; class NetServer : public Network @@ -56,8 +53,8 @@ class NetServer : public Network void Update() override; - void SetCurrentTic(int tictime) override; - void EndCurrentTic() override; + void BeginTic() override; + void EndTic() override; int GetSendTick() const override; ticcmd_t GetPlayerInput(int player) const override; @@ -67,7 +64,6 @@ class NetServer : public Network void WriteBotInput(int player, const ticcmd_t &cmd) override; int GetPing(int player) const override; - int GetServerPing() const override; void ListPingTimes() override; void Network_Controller(int playernum, bool add) override; @@ -76,21 +72,24 @@ class NetServer : public Network void ActorDestroyed(AActor *actor) override; private: - void OnClose(NetNode &node, ByteInputStream &stream); void OnConnectRequest(NetNode &node, ByteInputStream &stream); void OnDisconnect(NetNode &node, ByteInputStream &stream); void OnTic(NetNode &node, ByteInputStream &packet); - void CmdSpawnActor(ByteOutputStream &stream, AActor *actor); - void CmdDestroyActor(ByteOutputStream &stream, AActor *actor); + void CmdConnectResponse(int nodeIndex); + void CmdTic(int nodeIndex); + void CmdSpawnActor(int nodeIndex, AActor *actor); + void CmdDestroyActor(int nodeIndex, AActor *actor); + + void Close(NetNode &node); + void WriteCommand(int nodeIndex, NetCommand& command, bool unreliable = false); std::unique_ptr mComm; NetNode mNodes[MAXNETNODES]; int mNodeForPlayer[MAXPLAYERS]; ticcmd_t mCurrentInput[MAXPLAYERS]; + int mCurrentInputTic[MAXPLAYERS] = { 0 }; IDList mNetIDList; - - ByteOutputStream mBroadcastCommands; // Playsim events everyone should hear about }; diff --git a/src/network/netsingle.cpp b/src/network/netsingle.cpp index 61197800bb8..0b1b647b435 100644 --- a/src/network/netsingle.cpp +++ b/src/network/netsingle.cpp @@ -82,12 +82,12 @@ void NetSinglePlayer::Update() { } -void NetSinglePlayer::SetCurrentTic(int tictime) +void NetSinglePlayer::BeginTic() { - gametic = tictime; + gametic++; } -void NetSinglePlayer::EndCurrentTic() +void NetSinglePlayer::EndTic() { } @@ -121,11 +121,6 @@ int NetSinglePlayer::GetPing(int player) const return 0; } -int NetSinglePlayer::GetServerPing() const -{ - return 0; -} - void NetSinglePlayer::ListPingTimes() { } diff --git a/src/network/netsingle.h b/src/network/netsingle.h index 241f242f537..9ad3e502f9a 100644 --- a/src/network/netsingle.h +++ b/src/network/netsingle.h @@ -30,8 +30,8 @@ class NetSinglePlayer : public Network void Update() override; - void SetCurrentTic(int tictime) override; - void EndCurrentTic() override; + void BeginTic() override; + void EndTic() override; int GetSendTick() const override; ticcmd_t GetPlayerInput(int player) const override; @@ -41,7 +41,6 @@ class NetSinglePlayer : public Network void WriteBotInput(int player, const ticcmd_t &cmd) override; int GetPing(int player) const override; - int GetServerPing() const override; void ListPingTimes() override; void Network_Controller(int playernum, bool add) override; diff --git a/src/network/netsync.cpp b/src/network/netsync.cpp index 05ddc2df2ae..0439604ed30 100644 --- a/src/network/netsync.cpp +++ b/src/network/netsync.cpp @@ -41,10 +41,10 @@ class NetSyncWriter if (firstwrite) { firstwrite = false; - cmd.addShort(NetID); + cmd.AddShort(NetID); } - cmd.addByte(fieldindex); - cmd.addBuffer(actorval, (int)size); + cmd.AddByte(fieldindex); + cmd.AddBuffer(actorval, (int)size); memcpy(compval, actorval, size); } fieldindex++; @@ -54,7 +54,7 @@ class NetSyncWriter { if (!firstwrite) { - cmd.addByte(255); + cmd.AddByte(255); } }