Batch multiple player positions in a single packet

This commit is contained in:
SoWeBegin
2025-09-20 07:06:33 -07:00
parent 0f91933d32
commit 347e690deb
11 changed files with 124 additions and 30 deletions

View File

@@ -24,6 +24,7 @@ namespace Cast
std::uint16_t m_serverId;
Cast::Network::SessionsManager m_sessionsManager{};
static inline Cast::Classes::RoomsManager m_roomsManager{};
std::shared_ptr<asio::steady_timer> m_positionTimer;
tcp::acceptor m_mainServerAcceptor;
std::optional<tcp::socket> m_mainSocket;
@@ -34,6 +35,7 @@ namespace Cast
CastServer(ioContext& io_context, const std::string& serverIp, std::uint16_t port, std::uint16_t mainPort, std::uint16_t serverId);
void asyncAccept();
void asyncAcceptMainServer();
void tickPositionFlush();
};
}

View File

@@ -27,9 +27,13 @@ namespace Cast
std::uint32_t m_roomNumber = -1;
std::uint32_t m_serverId{};
std::vector<Common::Network::UnecryptedPacket> m_pendingPositions;
public:
bool m_hasMatchStarted{};
bool m_isInvisible{};
std::uint32_t m_roomTick{};
// Arena Mode
bool m_isArenaMode{};
@@ -124,6 +128,10 @@ namespace Cast
void shuffleCoordinates();
void respawnEveryoneArena();
void enqueuePosition(Common::Network::UnecryptedPacket&& pkt);
void flushPendingPositions();
};
}
}

View File

@@ -14,8 +14,14 @@ namespace Cast
{
private:
std::array<std::shared_ptr<Cast::Classes::Room>, Common::Constants::maxSessionsPerServer + 1> m_playerSessionIdToRoom{};
std::vector<std::shared_ptr<Cast::Classes::Room>> m_rooms{};
public:
const auto& getAllRooms() const
{
return m_rooms;
}
void addRoom(std::shared_ptr<Room> room, std::uint64_t playerId);
void switchRoomJoinOrExit(std::shared_ptr<Cast::Network::Session> session, std::uint64_t hostSessionId = -1);
@@ -32,6 +38,8 @@ namespace Cast
void playerForwardToHost(std::uint64_t hostSessionId, std::uint64_t senderSessionId, Common::Network::UnecryptedPacket& packet);
void setRoomTick(std::uint64_t hostSessionId, std::uint64_t tick);
void hostForwardToPlayer(std::uint64_t hostSessionId, std::uint64_t receiverSessionId, Common::Network::UnecryptedPacket& packet, bool useHostSessionIdInTcpHeader = true);
void setMapFor(std::uint64_t playerId, std::uint32_t map);

View File

@@ -17,9 +17,14 @@ namespace Cast
{
namespace Handlers
{
std::uint32_t getPositionTickMs(std::uint64_t timeSinceLastRestart, std::uint64_t roomTick)
{
return Common::Utils::getCurrentTimestampMs() - timeSinceLastRestart;
}
inline void handlePlayerPosition(const Common::Network::UnecryptedPacket& request, std::shared_ptr<Cast::Network::Session> session,
Cast::Classes::RoomsManager& roomsManager, std::uint32_t serverId, Cast::Network::SessionsManager& sm,
Ac::AntiCheatManager& acManager)
Ac::AntiCheatManager& acManager, std::uint64_t timeSinceLastRestart)
{
using namespace Cast::Structures;
@@ -29,6 +34,8 @@ namespace Cast
Cast::Structures::ClientPlayerInfoBasic playerPositionFromClient = Cast::Details::parseData<Cast::Structures::ClientPlayerInfoBasic>(request);
if (playerPositionFromClient.isBad()) return;
room->m_roomTick = playerPositionFromClient.matchTick;
if (room->m_isInvisible || session->m_isInvisible)
{
@@ -57,20 +64,17 @@ namespace Cast
const auto fullSize = request.getFullSize();
if (fullSize == 36)
// Note: melee worked without warping, and the only thing melee doesn't have is bullets! That may be the issue with all-weapons FFA warps
if (fullSize == 36)
{
Cast::Structures::ClientPlayerInfoBullet playerPositionBullet{};
std::memcpy(&playerPositionBullet, request.getData(), sizeof(playerPositionBullet));
if (playerPositionBullet.isBad())
{
::Utils::Logger::log("Bad Player Respawn Position", ::Utils::LogType::Warning, "Cast::handlePlayerPosition");
return;
}
if (playerPositionBullet.isBad()) return;
PlayerInfoResponseWithBullets playerInfoResponseWithBullets;
// playerInfoResponseWithBullets.tick = playerPositionFromClient.matchTick;
playerInfoResponseWithBullets.specificInfo.enableBullet = true;
playerInfoResponseWithBullets.tick = playerPositionFromClient.matchTick;
playerInfoResponseWithBullets.specificInfo.enableJump = false;
playerInfoResponseWithBullets.position = playerPositionFromClient.position;
playerInfoResponseWithBullets.direction = playerPositionFromClient.direction;
playerInfoResponseWithBullets.specificInfo.animation1 = playerPositionFromClient.animation1;
@@ -83,9 +87,8 @@ namespace Cast
playerInfoResponseWithBullets.currentWeapon = playerPositionBullet.bulletStruct.bullet4;
response.setData(reinterpret_cast<std::uint8_t*>(&playerInfoResponseWithBullets), sizeof(playerInfoResponseWithBullets));
}
else if (fullSize == 40)
else if (fullSize == 40) // bullet+jump+movement+rotation (simplified)
{
Cast::Structures::ClientPlayerInfoComplete playerPositionComplete{};
std::memcpy(&playerPositionComplete, request.getData(), request.getDataSize());
@@ -97,8 +100,9 @@ namespace Cast
PlayerInfoResponseWithBullets playerInfoResponseWithBullets;
playerInfoResponseWithBullets.specificInfo.enableBullet = true;
playerInfoResponseWithBullets.specificInfo.enableJump = true;
playerInfoResponseWithBullets.tick = playerPositionFromClient.matchTick;
// playerInfoResponseWithBullets.tick = playerPositionFromClient.matchTick;
playerInfoResponseWithBullets.position = playerPositionFromClient.position;
playerInfoResponseWithBullets.direction = playerPositionFromClient.direction;
playerInfoResponseWithBullets.specificInfo.animation1 = playerPositionFromClient.animation1;
@@ -109,9 +113,7 @@ namespace Cast
playerInfoResponseWithBullets.specificInfo.sessionId = static_cast<std::uint32_t>(session->getId());
playerInfoResponseWithBullets.bullets = playerPositionBullet.bulletStruct;
playerInfoResponseWithBullets.currentWeapon = playerPositionBullet.bulletStruct.bullet4;
PlayerInfoResponseComplete playerInfoResponseComplete{ playerInfoResponseWithBullets };
playerInfoResponseComplete.playerInfoBasicResponse.specificInfo.enableJump = true;
playerInfoResponseComplete.jump = playerPositionComplete.jumpStruct;
response.setData(reinterpret_cast<std::uint8_t*>(&playerInfoResponseComplete), sizeof(playerInfoResponseComplete));
@@ -119,7 +121,7 @@ namespace Cast
else
{
PlayerInfoBasicResponse playerInfoBasicResponse;
playerInfoBasicResponse.tick = playerPositionFromClient.matchTick;
// playerInfoBasicResponse.tick = playerPositionFromClient.matchTick;
playerInfoBasicResponse.position = playerPositionFromClient.position;
playerInfoBasicResponse.direction = playerPositionFromClient.direction;
playerInfoBasicResponse.currentWeapon = playerPositionFromClient.weapon;
@@ -129,7 +131,8 @@ namespace Cast
playerInfoBasicResponse.rotation2 = request.getOption();
playerInfoBasicResponse.rotation3 = playerPositionFromClient.rotation;
playerInfoBasicResponse.specificInfo.sessionId = static_cast<std::uint32_t>(session->getId());
playerInfoBasicResponse.specificInfo.enableJump = false;
playerInfoBasicResponse.specificInfo.enableBullet = false;
if (fullSize == 28)
{
@@ -139,7 +142,6 @@ namespace Cast
{
playerInfoBasicResponse.specificInfo.enableJump = true;
PlayerInfoResponseWithJump playerInfoResponseWithJump{ playerInfoBasicResponse };
Cast::Structures::ClientPlayerInfoJump playerPositionJump{};
std::memcpy(&playerPositionJump, request.getData(), request.getDataSize());
@@ -156,7 +158,8 @@ namespace Cast
}
// reminder: this is correct, dont use exceptSelf as that causes log errors in SysLog (host receives [322] command not found)
room->broadcastToRoom(response);
// room->broadcastToRoom(response);
room->enqueuePosition(std::move(response));
}
}
}

View File

@@ -30,6 +30,10 @@ namespace Cast
bool m_isInMatch{ 0 };
std::string m_nickname;
bool m_isInvisible{};
Cast::Structures::ClientPlayerInfoBasic m_lastClientPosition{};
std::uint32_t m_lastRotation1{};
std::uint32_t m_lastRotation2{};
std::uint32_t m_lastRotation3{};
public:
explicit Session(asio::ip::tcp::socket&& socket, std::function<void(std::size_t)> fnct)

View File

@@ -133,6 +133,13 @@ PACK_PUSH(1)
{
return position.isBadPos() || direction.isBadDir();
}
bool hasMoved(const PositionStruct& newPos) const
{
return position.positionX != newPos.positionX ||
position.positionY != newPos.positionY ||
position.positionZ != newPos.positionZ;
}
};
PACK_POP()

View File

@@ -28,7 +28,7 @@ PACK_POP()
PACK_PUSH(1)
struct PlayerInfoBasicResponse
{
std::uint32_t tick{};
// std::uint32_t tick{};
SpecificInfo specificInfo{};
Cast::Structures::PositionStruct position;
Cast::Structures::DirectionStruct direction;
@@ -50,7 +50,7 @@ PACK_POP()
PACK_PUSH(1)
struct PlayerInfoResponseWithBullets
{
std::uint32_t tick{};
// std::uint32_t tick{};
SpecificInfo specificInfo{};
Cast::Structures::PositionStruct position;
Cast::Structures::DirectionStruct direction;

View File

@@ -73,7 +73,7 @@ namespace Cast
return parseDataImpl<T, Common::Network::UnecryptedPacket, Warn>(request, offset, location);
}
bool mustBroadcastDeath(std::uint32_t mode)
inline bool mustBroadcastDeath(std::uint32_t mode)
{
return (mode == Common::Enums::Elimination || mode == Common::Enums::CaptureTheBattery
|| mode == Common::Enums::BombBattle || mode == Common::Enums::Clan_BombBattle