mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-11-14 07:47:13 +00:00
The die request, the smash request, the loaded notice, chat commands and the racing pickup notice were handled for whichever object they named. They are now only handled for the player that sent them, or for the vehicle that player drives where the client sends them for it. A racing pickup also has to be an object of a race track that is not a player, a vehicle or the zone's own object. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
257 lines
8.5 KiB
C++
257 lines
8.5 KiB
C++
#include "RacingMessages.h"
|
|
|
|
#include "CheatDetection.h"
|
|
#include "PossessorComponent.h"
|
|
#include "BitStreamUtils.h"
|
|
#include "CharacterComponent.h"
|
|
#include "Entity.h"
|
|
#include "EntityManager.h"
|
|
#include "Game.h"
|
|
#include "GeneralUtils.h"
|
|
#include "Logger.h"
|
|
#include "ModuleAssemblyComponent.h"
|
|
#include "PossessableComponent.h"
|
|
#include "RacingControlComponent.h"
|
|
#include "dZoneManager.h"
|
|
|
|
namespace GameMessages {
|
|
void ModuleAssemblyDBDataForClient::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(assemblyID);
|
|
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, blob);
|
|
}
|
|
|
|
bool ModuleAssemblyDBDataForClient::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(assemblyID));
|
|
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, blob));
|
|
return true;
|
|
}
|
|
|
|
void ModuleAssemblyQueryData::Handle(Entity& entity, const SystemAddress& sysAddr) {
|
|
auto* moduleAssemblyComponent = entity.GetComponent<ModuleAssemblyComponent>();
|
|
|
|
LOG("Got Query from %i", entity.GetLOT());
|
|
|
|
if (moduleAssemblyComponent != nullptr) {
|
|
LOG("Returning assembly %s", GeneralUtils::UTF16ToWTF8(moduleAssemblyComponent->GetAssemblyPartsLOTs()).c_str());
|
|
|
|
ModuleAssemblyDBDataForClient response;
|
|
response.target = entity.GetObjectID();
|
|
response.assemblyID = moduleAssemblyComponent->GetSubKey();
|
|
response.blob = moduleAssemblyComponent->GetAssemblyPartsLOTs();
|
|
response.Send(UNASSIGNED_SYSTEM_ADDRESS);
|
|
}
|
|
}
|
|
|
|
void ModularAssemblyNIFCompleted::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(objectID);
|
|
}
|
|
|
|
bool ModularAssemblyNIFCompleted::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(objectID));
|
|
return true;
|
|
}
|
|
|
|
void NotifyVehicleOfRacingObject::Serialize(RakNet::BitStream& bitStream) const {
|
|
BitStreamUtils::WriteOptional(bitStream, racingObjectID, LWOOBJID_EMPTY);
|
|
}
|
|
|
|
bool NotifyVehicleOfRacingObject::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, racingObjectID, LWOOBJID_EMPTY));
|
|
return true;
|
|
}
|
|
|
|
void RacingPlayerLoaded::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(vehicleID);
|
|
}
|
|
|
|
bool RacingPlayerLoaded::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
VALIDATE_READ(bitStream.Read(vehicleID));
|
|
return true;
|
|
}
|
|
|
|
void VehicleUnlockInput::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(bLockWheels);
|
|
}
|
|
|
|
bool VehicleUnlockInput::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(bLockWheels));
|
|
return true;
|
|
}
|
|
|
|
void VehicleSetWheelLockState::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(bExtraFriction);
|
|
bitStream.Write(bLocked);
|
|
}
|
|
|
|
bool VehicleSetWheelLockState::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(bExtraFriction));
|
|
VALIDATE_READ(bitStream.Read(bLocked));
|
|
return true;
|
|
}
|
|
|
|
void RacingSetPlayerResetInfo::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(currentLap);
|
|
bitStream.Write(furthestResetPlane);
|
|
bitStream.Write(playerID);
|
|
bitStream.Write(respawnPos);
|
|
bitStream.Write(upcomingPlane);
|
|
}
|
|
|
|
bool RacingSetPlayerResetInfo::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(currentLap));
|
|
VALIDATE_READ(bitStream.Read(furthestResetPlane));
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
VALIDATE_READ(bitStream.Read(respawnPos));
|
|
VALIDATE_READ(bitStream.Read(upcomingPlane));
|
|
return true;
|
|
}
|
|
|
|
void RacingResetPlayerToLastReset::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
}
|
|
|
|
bool RacingResetPlayerToLastReset::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
return true;
|
|
}
|
|
|
|
void VehicleStopBoost::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(bAffectPassive);
|
|
}
|
|
|
|
bool VehicleStopBoost::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(bAffectPassive));
|
|
return true;
|
|
}
|
|
|
|
void NotifyRacingClient::Serialize(RakNet::BitStream& bitStream) const {
|
|
BitStreamUtils::WriteOptional(bitStream, eventType, eRacingClientNotificationType::INVALID);
|
|
bitStream.Write(param1);
|
|
bitStream.Write(paramObj);
|
|
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, paramStr);
|
|
bitStream.Write(singleClient);
|
|
}
|
|
|
|
bool NotifyRacingClient::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, eventType, eRacingClientNotificationType::INVALID));
|
|
VALIDATE_READ(bitStream.Read(param1));
|
|
VALIDATE_READ(bitStream.Read(paramObj));
|
|
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, paramStr));
|
|
VALIDATE_READ(bitStream.Read(singleClient));
|
|
return true;
|
|
}
|
|
|
|
void RacingClientReady::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
}
|
|
|
|
bool RacingClientReady::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
return true;
|
|
}
|
|
|
|
void RacingClientReady::Handle(Entity& entity, const SystemAddress& sysAddr) {
|
|
auto* player = Game::entityManager->GetEntity(playerID);
|
|
|
|
if (player == nullptr) {
|
|
return;
|
|
}
|
|
|
|
auto* racingControlComponent = Game::zoneManager->GetZoneControlObject()->GetComponent<RacingControlComponent>();
|
|
|
|
if (racingControlComponent == nullptr) {
|
|
return;
|
|
}
|
|
|
|
racingControlComponent->OnRacingClientReady(player);
|
|
}
|
|
|
|
void RacingPlayerInfoResetFinished::Serialize(RakNet::BitStream& bitStream) const {
|
|
bitStream.Write(playerID);
|
|
}
|
|
|
|
bool RacingPlayerInfoResetFinished::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(bitStream.Read(playerID));
|
|
return true;
|
|
}
|
|
|
|
void RacingPlayerInfoResetFinished::Handle(Entity& entity, const SystemAddress& sysAddr) {
|
|
auto* player = Game::entityManager->GetEntity(playerID);
|
|
|
|
if (player == nullptr) {
|
|
return;
|
|
}
|
|
|
|
auto* zoneController = Game::zoneManager->GetZoneControlObject();
|
|
|
|
auto* racingControlComponent = zoneController->GetComponent<RacingControlComponent>();
|
|
|
|
LOG("Got finished: %i", entity.GetLOT());
|
|
|
|
if (racingControlComponent != nullptr) {
|
|
racingControlComponent->OnRacingPlayerInfoResetFinished(player);
|
|
}
|
|
}
|
|
|
|
void VehicleNotifyHitImaginationServer::Serialize(RakNet::BitStream& bitStream) const {
|
|
BitStreamUtils::WriteOptional(bitStream, pickupObjID, LWOOBJID_EMPTY);
|
|
BitStreamUtils::WriteOptional(bitStream, pickupSpawnerID, LWOOBJID_EMPTY);
|
|
BitStreamUtils::WriteOptional(bitStream, pickupSpawnerIndex, -1);
|
|
BitStreamUtils::WriteOptional(bitStream, vehiclePosition, NiPoint3Constant::ZERO);
|
|
}
|
|
|
|
bool VehicleNotifyHitImaginationServer::Deserialize(RakNet::BitStream& bitStream) {
|
|
VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, pickupObjID, LWOOBJID_EMPTY));
|
|
VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, pickupSpawnerID, LWOOBJID_EMPTY));
|
|
VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, pickupSpawnerIndex, -1));
|
|
VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, vehiclePosition, NiPoint3Constant::ZERO));
|
|
return true;
|
|
}
|
|
|
|
void VehicleNotifyHitImaginationServer::Handle(Entity& vehicle, const SystemAddress& sysAddr) {
|
|
auto* pickup = Game::entityManager->GetEntity(pickupObjID);
|
|
|
|
if (pickup == nullptr) {
|
|
return;
|
|
}
|
|
|
|
// A player reports the pickups their own vehicle drove through
|
|
if (!CheatDetection::IsSendersPlayer(vehicle.GetObjectID(), sysAddr)) {
|
|
LOG("Object %llu (LOT %i) is not the vehicle of the player that reported a pickup for it", vehicle.GetObjectID(), vehicle.GetLOT());
|
|
return;
|
|
}
|
|
|
|
// Pickups are objects of a race track, and never a player, a vehicle or the zone's own object
|
|
const auto* const zoneControl = Game::zoneManager->GetZoneControlObject();
|
|
if (!zoneControl || !zoneControl->GetComponent<RacingControlComponent>()
|
|
|| pickup == zoneControl || pickup->IsPlayer()
|
|
|| pickup->GetComponent<PossessableComponent>() || pickup->GetComponent<PossessorComponent>()) {
|
|
LOG("Object %llu (LOT %i) is not a pickup of a race track", pickupObjID, pickup->GetLOT());
|
|
return;
|
|
}
|
|
|
|
// The sender is the vehicle; credit its driver if it has one.
|
|
Entity* entity = &vehicle;
|
|
auto* possessableComponent = entity->GetComponent<PossessableComponent>();
|
|
|
|
if (possessableComponent != nullptr) {
|
|
entity = Game::entityManager->GetEntity(possessableComponent->GetPossessor());
|
|
|
|
if (entity == nullptr) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
auto* characterComponent = entity->GetComponent<CharacterComponent>();
|
|
if (characterComponent != nullptr) {
|
|
characterComponent->UpdatePlayerStatistic(RacingImaginationPowerUpsCollected);
|
|
}
|
|
|
|
pickup->OnFireEventServerSide(entity, "powerup");
|
|
|
|
pickup->Kill(entity);
|
|
}
|
|
}
|