Files
ToyBattlesHQ/CastServer/include/Handlers/PlayerPositionHandler.h
2025-09-20 07:06:33 -07:00

168 lines
8.9 KiB
C++

#ifndef PLAYER_POSITION_HANDLER_H
#define PLAYER_POSITION_HANDLER_H
#include "../Network/CastSession.h"
#include "../Network/SessionsManager.h"
#include "../Structures/PlayerPositionFromServer.h"
#include "../Structures/SuicideStruct.h"
#include "Utils/Logger.h"
#include "AntiCheat/AntiCheat.h"
#include "AntiCheat/Event.h"
#include "../Utils/Utilities.h"
#include <Utils/Utils.h>
#include <cstring>
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, std::uint64_t timeSinceLastRestart)
{
using namespace Cast::Structures;
auto roomOpt = roomsManager.getRoom(session->getId());
if (!roomOpt) return;
auto& room = *roomOpt;
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)
{
playerPositionFromClient.position.positionZ = 0;
}
if (room->m_isAssassinMode)
{
const auto seid = session->getId();
if (room->m_assassinBlueUid.session == seid)
{
room->m_blueAssassinPos = playerPositionFromClient.position;
}
else if (room->m_assassinRedUid.session == seid)
{
room->m_redAssassinPos = playerPositionFromClient.position;;
}
}
else
{
acManager.submitEvent(std::make_unique<Ac::PacketFloodingEvent>(session, 20, 1000, "Speed hack (Cheat Engine)", 281));
}
static Common::Network::UnecryptedPacket response{ 1440, 322, 1 };
response.setCommand(322, 0, 0, 1);
const auto fullSize = request.getFullSize();
// 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()) return;
PlayerInfoResponseWithBullets playerInfoResponseWithBullets;
// playerInfoResponseWithBullets.tick = playerPositionFromClient.matchTick;
playerInfoResponseWithBullets.specificInfo.enableBullet = true;
playerInfoResponseWithBullets.specificInfo.enableJump = false;
playerInfoResponseWithBullets.position = playerPositionFromClient.position;
playerInfoResponseWithBullets.direction = playerPositionFromClient.direction;
playerInfoResponseWithBullets.specificInfo.animation1 = playerPositionFromClient.animation1;
playerInfoResponseWithBullets.specificInfo.animation2 = playerPositionFromClient.animation2;
playerInfoResponseWithBullets.rotation1 = request.getExtra();
playerInfoResponseWithBullets.rotation2 = request.getOption();
playerInfoResponseWithBullets.rotation3 = playerPositionFromClient.rotation;
playerInfoResponseWithBullets.specificInfo.sessionId = static_cast<std::uint32_t>(session->getId());
playerInfoResponseWithBullets.bullets = playerPositionBullet.bulletStruct;
playerInfoResponseWithBullets.currentWeapon = playerPositionBullet.bulletStruct.bullet4;
response.setData(reinterpret_cast<std::uint8_t*>(&playerInfoResponseWithBullets), sizeof(playerInfoResponseWithBullets));
}
else if (fullSize == 40) // bullet+jump+movement+rotation (simplified)
{
Cast::Structures::ClientPlayerInfoComplete playerPositionComplete{};
std::memcpy(&playerPositionComplete, request.getData(), request.getDataSize());
if (playerPositionComplete.isBad()) return;
Cast::Structures::ClientPlayerInfoBullet playerPositionBullet{};
std::memcpy(&playerPositionBullet, request.getData(), sizeof(playerPositionBullet));
if (playerPositionBullet.isBad()) return;
PlayerInfoResponseWithBullets playerInfoResponseWithBullets;
playerInfoResponseWithBullets.specificInfo.enableBullet = true;
playerInfoResponseWithBullets.specificInfo.enableJump = true;
// playerInfoResponseWithBullets.tick = playerPositionFromClient.matchTick;
playerInfoResponseWithBullets.position = playerPositionFromClient.position;
playerInfoResponseWithBullets.direction = playerPositionFromClient.direction;
playerInfoResponseWithBullets.specificInfo.animation1 = playerPositionFromClient.animation1;
playerInfoResponseWithBullets.specificInfo.animation2 = playerPositionFromClient.animation2;
playerInfoResponseWithBullets.rotation1 = request.getExtra();
playerInfoResponseWithBullets.rotation2 = request.getOption();
playerInfoResponseWithBullets.rotation3 = playerPositionFromClient.rotation;
playerInfoResponseWithBullets.specificInfo.sessionId = static_cast<std::uint32_t>(session->getId());
playerInfoResponseWithBullets.bullets = playerPositionBullet.bulletStruct;
playerInfoResponseWithBullets.currentWeapon = playerPositionBullet.bulletStruct.bullet4;
PlayerInfoResponseComplete playerInfoResponseComplete{ playerInfoResponseWithBullets };
playerInfoResponseComplete.jump = playerPositionComplete.jumpStruct;
response.setData(reinterpret_cast<std::uint8_t*>(&playerInfoResponseComplete), sizeof(playerInfoResponseComplete));
}
else
{
PlayerInfoBasicResponse playerInfoBasicResponse;
// playerInfoBasicResponse.tick = playerPositionFromClient.matchTick;
playerInfoBasicResponse.position = playerPositionFromClient.position;
playerInfoBasicResponse.direction = playerPositionFromClient.direction;
playerInfoBasicResponse.currentWeapon = playerPositionFromClient.weapon;
playerInfoBasicResponse.specificInfo.animation1 = playerPositionFromClient.animation1;
playerInfoBasicResponse.specificInfo.animation2 = playerPositionFromClient.animation2;
playerInfoBasicResponse.rotation1 = request.getExtra();
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)
{
response.setData(reinterpret_cast<std::uint8_t*>(&playerInfoBasicResponse), sizeof(playerInfoBasicResponse));
}
else if (fullSize == 32)
{
playerInfoBasicResponse.specificInfo.enableJump = true;
PlayerInfoResponseWithJump playerInfoResponseWithJump{ playerInfoBasicResponse };
Cast::Structures::ClientPlayerInfoJump playerPositionJump{};
std::memcpy(&playerPositionJump, request.getData(), request.getDataSize());
if (playerPositionJump.isBad()) return;
playerInfoResponseWithJump.jump = playerPositionJump.jumpStruct;
response.setData(reinterpret_cast<std::uint8_t*>(&playerInfoResponseWithJump), sizeof(playerInfoResponseWithJump));
}
else
{
::Utils::Logger::log("Unknown player position case!", ::Utils::LogType::Error, "Cast::handlePlayerPosition");
return;
}
}
// reminder: this is correct, dont use exceptSelf as that causes log errors in SysLog (host receives [322] command not found)
// room->broadcastToRoom(response);
room->enqueuePosition(std::move(response));
}
}
}
#endif