mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-24 06:27:24 +00:00
Remove deps from dNet (#1401)
This commit is contained in:
parent
14c20fbd62
commit
b683413a60
50
dCommon/PositionUpdate.h
Normal file
50
dCommon/PositionUpdate.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#ifndef __POSITIONUPDATE__H__
|
||||||
|
#define __POSITIONUPDATE__H__
|
||||||
|
|
||||||
|
#include "NiPoint3.h"
|
||||||
|
#include "NiQuaternion.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct RemoteInputInfo {
|
||||||
|
RemoteInputInfo() {
|
||||||
|
m_RemoteInputX = 0;
|
||||||
|
m_RemoteInputY = 0;
|
||||||
|
m_IsPowersliding = false;
|
||||||
|
m_IsModified = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator=(const RemoteInputInfo& other) {
|
||||||
|
m_RemoteInputX = other.m_RemoteInputX;
|
||||||
|
m_RemoteInputY = other.m_RemoteInputY;
|
||||||
|
m_IsPowersliding = other.m_IsPowersliding;
|
||||||
|
m_IsModified = other.m_IsModified;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const RemoteInputInfo& other) {
|
||||||
|
return m_RemoteInputX == other.m_RemoteInputX && m_RemoteInputY == other.m_RemoteInputY && m_IsPowersliding == other.m_IsPowersliding && m_IsModified == other.m_IsModified;
|
||||||
|
}
|
||||||
|
|
||||||
|
float m_RemoteInputX;
|
||||||
|
float m_RemoteInputY;
|
||||||
|
bool m_IsPowersliding;
|
||||||
|
bool m_IsModified;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LocalSpaceInfo {
|
||||||
|
LWOOBJID objectId = LWOOBJID_EMPTY;
|
||||||
|
NiPoint3 position = NiPoint3::ZERO;
|
||||||
|
NiPoint3 linearVelocity = NiPoint3::ZERO;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PositionUpdate {
|
||||||
|
NiPoint3 position = NiPoint3::ZERO;
|
||||||
|
NiQuaternion rotation = NiQuaternion::IDENTITY;
|
||||||
|
bool onGround = false;
|
||||||
|
bool onRail = false;
|
||||||
|
NiPoint3 velocity = NiPoint3::ZERO;
|
||||||
|
NiPoint3 angularVelocity = NiPoint3::ZERO;
|
||||||
|
LocalSpaceInfo localSpaceInfo;
|
||||||
|
RemoteInputInfo remoteInputInfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__POSITIONUPDATE__H__
|
@ -25,6 +25,7 @@
|
|||||||
#include "eMissionTaskType.h"
|
#include "eMissionTaskType.h"
|
||||||
#include "eTriggerEventType.h"
|
#include "eTriggerEventType.h"
|
||||||
#include "eObjectBits.h"
|
#include "eObjectBits.h"
|
||||||
|
#include "PositionUpdate.h"
|
||||||
|
|
||||||
//Component includes:
|
//Component includes:
|
||||||
#include "Component.h"
|
#include "Component.h"
|
||||||
@ -2056,3 +2057,75 @@ uint8_t Entity::GetCollectibleID() const {
|
|||||||
auto* collectible = GetComponent<CollectibleComponent>();
|
auto* collectible = GetComponent<CollectibleComponent>();
|
||||||
return collectible ? collectible->GetCollectibleId() : 0;
|
return collectible ? collectible->GetCollectibleId() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Entity::ProcessPositionUpdate(PositionUpdate& update) {
|
||||||
|
if (!IsPlayer()) return;
|
||||||
|
auto* controllablePhysicsComponent = GetComponent<ControllablePhysicsComponent>();
|
||||||
|
if (!controllablePhysicsComponent) return;
|
||||||
|
|
||||||
|
auto* possessorComponent = GetComponent<PossessorComponent>();
|
||||||
|
bool updateChar = true;
|
||||||
|
|
||||||
|
if (possessorComponent) {
|
||||||
|
auto* possassableEntity = Game::entityManager->GetEntity(possessorComponent->GetPossessable());
|
||||||
|
|
||||||
|
if (possassableEntity) {
|
||||||
|
auto* possessableComponent = possassableEntity->GetComponent<PossessableComponent>();
|
||||||
|
|
||||||
|
// While possessing something, only update char if we are attached to the thing we are possessing
|
||||||
|
updateChar = possessableComponent && possessableComponent->GetPossessionType() == ePossessionType::ATTACHED_VISIBLE;
|
||||||
|
|
||||||
|
auto* havokVehiclePhysicsComponent = possassableEntity->GetComponent<HavokVehiclePhysicsComponent>();
|
||||||
|
if (havokVehiclePhysicsComponent) {
|
||||||
|
havokVehiclePhysicsComponent->SetPosition(update.position);
|
||||||
|
havokVehiclePhysicsComponent->SetRotation(update.rotation);
|
||||||
|
havokVehiclePhysicsComponent->SetIsOnGround(update.onGround);
|
||||||
|
havokVehiclePhysicsComponent->SetIsOnRail(update.onRail);
|
||||||
|
havokVehiclePhysicsComponent->SetVelocity(update.velocity);
|
||||||
|
havokVehiclePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3::ZERO);
|
||||||
|
havokVehiclePhysicsComponent->SetAngularVelocity(update.angularVelocity);
|
||||||
|
havokVehiclePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3::ZERO);
|
||||||
|
havokVehiclePhysicsComponent->SetRemoteInputInfo(update.remoteInputInfo);
|
||||||
|
} else {
|
||||||
|
// Need to get the mount's controllable physics
|
||||||
|
auto* possessedControllablePhysicsComponent = possassableEntity->GetComponent<ControllablePhysicsComponent>();
|
||||||
|
if (!possessedControllablePhysicsComponent) return;
|
||||||
|
possessedControllablePhysicsComponent->SetPosition(update.position);
|
||||||
|
possessedControllablePhysicsComponent->SetRotation(update.rotation);
|
||||||
|
possessedControllablePhysicsComponent->SetIsOnGround(update.onGround);
|
||||||
|
possessedControllablePhysicsComponent->SetIsOnRail(update.onRail);
|
||||||
|
possessedControllablePhysicsComponent->SetVelocity(update.velocity);
|
||||||
|
possessedControllablePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3::ZERO);
|
||||||
|
possessedControllablePhysicsComponent->SetAngularVelocity(update.angularVelocity);
|
||||||
|
possessedControllablePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3::ZERO);
|
||||||
|
}
|
||||||
|
Game::entityManager->SerializeEntity(possassableEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!updateChar) {
|
||||||
|
update.velocity = NiPoint3::ZERO;
|
||||||
|
update.angularVelocity = NiPoint3::ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle statistics
|
||||||
|
auto* characterComponent = GetComponent<CharacterComponent>();
|
||||||
|
if (characterComponent) {
|
||||||
|
characterComponent->TrackPositionUpdate(update.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
controllablePhysicsComponent->SetPosition(update.position);
|
||||||
|
controllablePhysicsComponent->SetRotation(update.rotation);
|
||||||
|
controllablePhysicsComponent->SetIsOnGround(update.onGround);
|
||||||
|
controllablePhysicsComponent->SetIsOnRail(update.onRail);
|
||||||
|
controllablePhysicsComponent->SetVelocity(update.velocity);
|
||||||
|
controllablePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3::ZERO);
|
||||||
|
controllablePhysicsComponent->SetAngularVelocity(update.angularVelocity);
|
||||||
|
controllablePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3::ZERO);
|
||||||
|
|
||||||
|
auto* player = static_cast<Player*>(this);
|
||||||
|
player->SetGhostReferencePoint(update.position);
|
||||||
|
Game::entityManager->QueueGhostUpdate(player->GetObjectID());
|
||||||
|
|
||||||
|
if (updateChar) Game::entityManager->SerializeEntity(this);
|
||||||
|
}
|
||||||
|
@ -31,6 +31,7 @@ class Component;
|
|||||||
class Item;
|
class Item;
|
||||||
class Character;
|
class Character;
|
||||||
class EntityCallbackTimer;
|
class EntityCallbackTimer;
|
||||||
|
class PositionUpdate;
|
||||||
enum class eTriggerEventType;
|
enum class eTriggerEventType;
|
||||||
enum class eGameMasterLevel : uint8_t;
|
enum class eGameMasterLevel : uint8_t;
|
||||||
enum class eReplicaComponentType : uint32_t;
|
enum class eReplicaComponentType : uint32_t;
|
||||||
@ -296,6 +297,8 @@ public:
|
|||||||
|
|
||||||
Entity* GetScheduledKiller() { return m_ScheduleKiller; }
|
Entity* GetScheduledKiller() { return m_ScheduleKiller; }
|
||||||
|
|
||||||
|
void ProcessPositionUpdate(PositionUpdate& update);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
LWOOBJID m_ObjectID;
|
LWOOBJID m_ObjectID;
|
||||||
|
|
||||||
|
@ -216,7 +216,52 @@ void UserManager::RequestCharacterList(const SystemAddress& sysAddr) {
|
|||||||
chars.push_back(character);
|
chars.push_back(character);
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldPackets::SendCharacterList(sysAddr, u);
|
RakNet::BitStream bitStream;
|
||||||
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::CHARACTER_LIST_RESPONSE);
|
||||||
|
|
||||||
|
std::vector<Character*> characters = u->GetCharacters();
|
||||||
|
bitStream.Write<uint8_t>(characters.size());
|
||||||
|
bitStream.Write<uint8_t>(0); //TODO: Pick the most recent played index. character index in front, just picking 0
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < characters.size(); ++i) {
|
||||||
|
bitStream.Write(characters[i]->GetObjectID());
|
||||||
|
bitStream.Write<uint32_t>(0);
|
||||||
|
|
||||||
|
bitStream.Write(LUWString(characters[i]->GetName()));
|
||||||
|
bitStream.Write(LUWString(characters[i]->GetUnapprovedName()));
|
||||||
|
|
||||||
|
bitStream.Write<uint8_t>(characters[i]->GetNameRejected());
|
||||||
|
bitStream.Write<uint8_t>(false);
|
||||||
|
|
||||||
|
bitStream.Write(LUString("", 10));
|
||||||
|
|
||||||
|
bitStream.Write(characters[i]->GetShirtColor());
|
||||||
|
bitStream.Write(characters[i]->GetShirtStyle());
|
||||||
|
bitStream.Write(characters[i]->GetPantsColor());
|
||||||
|
bitStream.Write(characters[i]->GetHairStyle());
|
||||||
|
bitStream.Write(characters[i]->GetHairColor());
|
||||||
|
bitStream.Write(characters[i]->GetLeftHand());
|
||||||
|
bitStream.Write(characters[i]->GetRightHand());
|
||||||
|
bitStream.Write(characters[i]->GetEyebrows());
|
||||||
|
bitStream.Write(characters[i]->GetEyes());
|
||||||
|
bitStream.Write(characters[i]->GetMouth());
|
||||||
|
bitStream.Write<uint32_t>(0);
|
||||||
|
|
||||||
|
bitStream.Write<uint16_t>(characters[i]->GetZoneID());
|
||||||
|
bitStream.Write<uint16_t>(characters[i]->GetZoneInstance());
|
||||||
|
bitStream.Write(characters[i]->GetZoneClone());
|
||||||
|
|
||||||
|
bitStream.Write(characters[i]->GetLastLogin());
|
||||||
|
|
||||||
|
const auto& equippedItems = characters[i]->GetEquippedItems();
|
||||||
|
bitStream.Write<uint16_t>(equippedItems.size());
|
||||||
|
|
||||||
|
for (uint32_t j = 0; j < equippedItems.size(); ++j) {
|
||||||
|
bitStream.Write(equippedItems[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet) {
|
void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet) {
|
||||||
@ -322,7 +367,7 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
|
|
||||||
WorldPackets::SendCharacterCreationResponse(sysAddr, eCharacterCreationResponse::SUCCESS);
|
WorldPackets::SendCharacterCreationResponse(sysAddr, eCharacterCreationResponse::SUCCESS);
|
||||||
UserManager::RequestCharacterList(sysAddr);
|
UserManager::RequestCharacterList(sysAddr);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet) {
|
void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet) {
|
||||||
|
@ -4,31 +4,7 @@
|
|||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
#include "PhysicsComponent.h"
|
#include "PhysicsComponent.h"
|
||||||
#include "eReplicaComponentType.h"
|
#include "eReplicaComponentType.h"
|
||||||
|
#include "PositionUpdate.h"
|
||||||
struct RemoteInputInfo {
|
|
||||||
RemoteInputInfo() {
|
|
||||||
m_RemoteInputX = 0;
|
|
||||||
m_RemoteInputY = 0;
|
|
||||||
m_IsPowersliding = false;
|
|
||||||
m_IsModified = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator=(const RemoteInputInfo& other) {
|
|
||||||
m_RemoteInputX = other.m_RemoteInputX;
|
|
||||||
m_RemoteInputY = other.m_RemoteInputY;
|
|
||||||
m_IsPowersliding = other.m_IsPowersliding;
|
|
||||||
m_IsModified = other.m_IsModified;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const RemoteInputInfo& other) {
|
|
||||||
return m_RemoteInputX == other.m_RemoteInputX && m_RemoteInputY == other.m_RemoteInputY && m_IsPowersliding == other.m_IsPowersliding && m_IsModified == other.m_IsModified;
|
|
||||||
}
|
|
||||||
|
|
||||||
float m_RemoteInputX;
|
|
||||||
float m_RemoteInputY;
|
|
||||||
bool m_IsPowersliding;
|
|
||||||
bool m_IsModified;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Physics component for vehicles.
|
* Physics component for vehicles.
|
||||||
|
@ -8,10 +8,5 @@ set(DNET_SOURCES "AuthPackets.cpp"
|
|||||||
"ZoneInstanceManager.cpp")
|
"ZoneInstanceManager.cpp")
|
||||||
|
|
||||||
add_library(dNet STATIC ${DNET_SOURCES})
|
add_library(dNet STATIC ${DNET_SOURCES})
|
||||||
target_include_directories(dNet PRIVATE
|
|
||||||
${PROJECT_SOURCE_DIR}/dGame/dComponents
|
target_link_libraries(dNet PUBLIC dCommon)
|
||||||
${PROJECT_SOURCE_DIR}/dScripts # transitive through components
|
|
||||||
)
|
|
||||||
target_link_libraries(dNet
|
|
||||||
PUBLIC dCommon dDatabase
|
|
||||||
INTERFACE dZoneManager)
|
|
||||||
|
@ -4,422 +4,120 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ClientPackets.h"
|
#include "ClientPackets.h"
|
||||||
#include "UserManager.h"
|
|
||||||
#include "User.h"
|
|
||||||
#include "Character.h"
|
|
||||||
#include "EntityManager.h"
|
|
||||||
#include "Entity.h"
|
|
||||||
#include "ControllablePhysicsComponent.h"
|
|
||||||
#include "Game.h"
|
|
||||||
#include "Logger.h"
|
|
||||||
#include "WorldPackets.h"
|
|
||||||
#include "NiPoint3.h"
|
|
||||||
#include "NiQuaternion.h"
|
|
||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
#include "BitStream.h"
|
#include "PositionUpdate.h"
|
||||||
#include "dChatFilter.h"
|
|
||||||
#include "WorldPackets.h"
|
|
||||||
#include "ChatPackets.h"
|
|
||||||
#include "dServer.h"
|
|
||||||
#include "GameMessages.h"
|
|
||||||
#include "dZoneManager.h"
|
|
||||||
#include "Player.h"
|
|
||||||
#include "Zone.h"
|
|
||||||
#include "PossessorComponent.h"
|
|
||||||
#include "PossessableComponent.h"
|
|
||||||
#include "HavokVehiclePhysicsComponent.h"
|
|
||||||
#include "dConfig.h"
|
|
||||||
#include "CharacterComponent.h"
|
|
||||||
#include "Database.h"
|
|
||||||
#include "eGameMasterLevel.h"
|
|
||||||
#include "eReplicaComponentType.h"
|
|
||||||
#include "CheatDetection.h"
|
|
||||||
#include "Amf3.h"
|
|
||||||
|
|
||||||
void ClientPackets::HandleChatMessage(const SystemAddress& sysAddr, Packet* packet) {
|
|
||||||
User* user = UserManager::Instance()->GetUser(sysAddr);
|
|
||||||
if (!user) {
|
|
||||||
LOG("Unable to get user to parse chat message");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user->GetIsMuted()) {
|
|
||||||
user->GetLastUsedChar()->SendMuteNotice();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
ChatMessage ClientPackets::HandleChatMessage(Packet* packet) {
|
||||||
CINSTREAM_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
|
|
||||||
char chatChannel;
|
ChatMessage message;
|
||||||
uint16_t unknown;
|
|
||||||
uint32_t messageLength;
|
uint32_t messageLength;
|
||||||
std::u16string message;
|
|
||||||
|
|
||||||
inStream.Read(chatChannel);
|
inStream.Read(message.chatChannel);
|
||||||
inStream.Read(unknown);
|
inStream.Read(message.unknown);
|
||||||
inStream.Read(messageLength);
|
inStream.Read(messageLength);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < (messageLength - 1); ++i) {
|
for (uint32_t i = 0; i < (messageLength - 1); ++i) {
|
||||||
uint16_t character;
|
uint16_t character;
|
||||||
inStream.Read(character);
|
inStream.Read(character);
|
||||||
message.push_back(character);
|
message.message.push_back(character);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string playerName = user->GetLastUsedChar()->GetName();
|
return message;
|
||||||
bool isMythran = user->GetLastUsedChar()->GetGMLevel() > eGameMasterLevel::CIVILIAN;
|
|
||||||
bool isOk = Game::chatFilter->IsSentenceOkay(GeneralUtils::UTF16ToWTF8(message), user->GetLastUsedChar()->GetGMLevel()).empty();
|
|
||||||
LOG_DEBUG("Msg: %s was approved previously? %i", GeneralUtils::UTF16ToWTF8(message).c_str(), user->GetLastChatMessageApproved());
|
|
||||||
if (!isOk) {
|
|
||||||
// Add a limit to the string converted by general utils because it is a user received string and may be a bad actor.
|
|
||||||
CheatDetection::ReportCheat(
|
|
||||||
user,
|
|
||||||
sysAddr,
|
|
||||||
"Player %s attempted to bypass chat filter with message: %s",
|
|
||||||
playerName.c_str(),
|
|
||||||
GeneralUtils::UTF16ToWTF8(message, 512).c_str());
|
|
||||||
}
|
|
||||||
if (!isOk && !isMythran) return;
|
|
||||||
|
|
||||||
std::string sMessage = GeneralUtils::UTF16ToWTF8(message);
|
|
||||||
LOG("%s: %s", playerName.c_str(), sMessage.c_str());
|
|
||||||
ChatPackets::SendChatMessage(sysAddr, chatChannel, playerName, user->GetLoggedInChar(), isMythran, message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientPackets::HandleClientPositionUpdate(const SystemAddress& sysAddr, Packet* packet) {
|
PositionUpdate ClientPackets::HandleClientPositionUpdate(Packet* packet) {
|
||||||
User* user = UserManager::Instance()->GetUser(sysAddr);
|
PositionUpdate update;
|
||||||
if (!user) {
|
|
||||||
LOG("Unable to get user to parse position update");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CINSTREAM_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
|
|
||||||
Entity* entity = Game::entityManager->GetEntity(user->GetLastUsedChar()->GetObjectID());
|
inStream.Read(update.position.x);
|
||||||
if (!entity) return;
|
inStream.Read(update.position.y);
|
||||||
|
inStream.Read(update.position.z);
|
||||||
|
|
||||||
ControllablePhysicsComponent* comp = static_cast<ControllablePhysicsComponent*>(entity->GetComponent(eReplicaComponentType::CONTROLLABLE_PHYSICS));
|
inStream.Read(update.rotation.x);
|
||||||
if (!comp) return;
|
inStream.Read(update.rotation.y);
|
||||||
|
inStream.Read(update.rotation.z);
|
||||||
|
inStream.Read(update.rotation.w);
|
||||||
|
|
||||||
/*
|
inStream.Read(update.onGround);
|
||||||
//If we didn't move, this will match and stop our velocity
|
inStream.Read(update.onRail);
|
||||||
if (packet->length == 37) {
|
|
||||||
NiPoint3 zeroVel(0.0f, 0.0f, 0.0f);
|
|
||||||
comp->SetVelocity(zeroVel);
|
|
||||||
comp->SetAngularVelocity(zeroVel);
|
|
||||||
comp->SetIsOnGround(true); //probably8
|
|
||||||
Game::entityManager->SerializeEntity(entity);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
auto* possessorComponent = entity->GetComponent<PossessorComponent>();
|
|
||||||
|
|
||||||
NiPoint3 position;
|
|
||||||
inStream.Read(position.x);
|
|
||||||
inStream.Read(position.y);
|
|
||||||
inStream.Read(position.z);
|
|
||||||
|
|
||||||
NiQuaternion rotation;
|
|
||||||
inStream.Read(rotation.x);
|
|
||||||
inStream.Read(rotation.y);
|
|
||||||
inStream.Read(rotation.z);
|
|
||||||
inStream.Read(rotation.w);
|
|
||||||
|
|
||||||
bool onGround = false;
|
|
||||||
bool onRail = false;
|
|
||||||
inStream.Read(onGround);
|
|
||||||
inStream.Read(onRail);
|
|
||||||
|
|
||||||
bool velocityFlag = false;
|
bool velocityFlag = false;
|
||||||
inStream.Read(velocityFlag);
|
inStream.Read(velocityFlag);
|
||||||
NiPoint3 velocity{};
|
|
||||||
if (velocityFlag) {
|
if (velocityFlag) {
|
||||||
inStream.Read(velocity.x);
|
inStream.Read(update.velocity.x);
|
||||||
inStream.Read(velocity.y);
|
inStream.Read(update.velocity.y);
|
||||||
inStream.Read(velocity.z);
|
inStream.Read(update.velocity.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool angVelocityFlag = false;
|
bool angVelocityFlag = false;
|
||||||
inStream.Read(angVelocityFlag);
|
inStream.Read(angVelocityFlag);
|
||||||
NiPoint3 angVelocity{};
|
|
||||||
if (angVelocityFlag) {
|
if (angVelocityFlag) {
|
||||||
inStream.Read(angVelocity.x);
|
inStream.Read(update.angularVelocity.x);
|
||||||
inStream.Read(angVelocity.y);
|
inStream.Read(update.angularVelocity.y);
|
||||||
inStream.Read(angVelocity.z);
|
inStream.Read(update.angularVelocity.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO figure out how to use these. Ignoring for now, but reading in if they exist.
|
// TODO figure out how to use these. Ignoring for now, but reading in if they exist.
|
||||||
bool hasLocalSpaceInfo{};
|
bool hasLocalSpaceInfo{};
|
||||||
LWOOBJID objectId{};
|
|
||||||
NiPoint3 localSpacePosition{};
|
|
||||||
bool hasLinearVelocity{};
|
|
||||||
NiPoint3 linearVelocity{};
|
|
||||||
if (inStream.Read(hasLocalSpaceInfo) && hasLocalSpaceInfo) {
|
if (inStream.Read(hasLocalSpaceInfo) && hasLocalSpaceInfo) {
|
||||||
inStream.Read(objectId);
|
inStream.Read(update.localSpaceInfo.objectId);
|
||||||
inStream.Read(localSpacePosition.x);
|
inStream.Read(update.localSpaceInfo.position.x);
|
||||||
inStream.Read(localSpacePosition.y);
|
inStream.Read(update.localSpaceInfo.position.y);
|
||||||
inStream.Read(localSpacePosition.z);
|
inStream.Read(update.localSpaceInfo.position.z);
|
||||||
|
bool hasLinearVelocity = false;
|
||||||
if (inStream.Read(hasLinearVelocity) && hasLinearVelocity) {
|
if (inStream.Read(hasLinearVelocity) && hasLinearVelocity) {
|
||||||
inStream.Read(linearVelocity.x);
|
inStream.Read(update.localSpaceInfo.linearVelocity.x);
|
||||||
inStream.Read(linearVelocity.y);
|
inStream.Read(update.localSpaceInfo.linearVelocity.y);
|
||||||
inStream.Read(linearVelocity.z);
|
inStream.Read(update.localSpaceInfo.linearVelocity.z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasRemoteInputInfo{};
|
bool hasRemoteInputInfo{};
|
||||||
RemoteInputInfo remoteInput{};
|
|
||||||
|
|
||||||
if (inStream.Read(hasRemoteInputInfo) && hasRemoteInputInfo) {
|
if (inStream.Read(hasRemoteInputInfo) && hasRemoteInputInfo) {
|
||||||
inStream.Read(remoteInput.m_RemoteInputX);
|
inStream.Read(update.remoteInputInfo.m_RemoteInputX);
|
||||||
inStream.Read(remoteInput.m_RemoteInputY);
|
inStream.Read(update.remoteInputInfo.m_RemoteInputY);
|
||||||
inStream.Read(remoteInput.m_IsPowersliding);
|
inStream.Read(update.remoteInputInfo.m_IsPowersliding);
|
||||||
inStream.Read(remoteInput.m_IsModified);
|
inStream.Read(update.remoteInputInfo.m_IsModified);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool updateChar = true;
|
return update;
|
||||||
|
|
||||||
if (possessorComponent != nullptr) {
|
|
||||||
auto* possassableEntity = Game::entityManager->GetEntity(possessorComponent->GetPossessable());
|
|
||||||
|
|
||||||
if (possassableEntity != nullptr) {
|
|
||||||
auto* possessableComponent = possassableEntity->GetComponent<PossessableComponent>();
|
|
||||||
if (possessableComponent) {
|
|
||||||
// While possessing something, only update char if we are attached to the thing we are possessing
|
|
||||||
if (possessableComponent->GetPossessionType() != ePossessionType::ATTACHED_VISIBLE) updateChar = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* havokVehiclePhysicsComponent = possassableEntity->GetComponent<HavokVehiclePhysicsComponent>();
|
|
||||||
if (havokVehiclePhysicsComponent != nullptr) {
|
|
||||||
havokVehiclePhysicsComponent->SetPosition(position);
|
|
||||||
havokVehiclePhysicsComponent->SetRotation(rotation);
|
|
||||||
havokVehiclePhysicsComponent->SetIsOnGround(onGround);
|
|
||||||
havokVehiclePhysicsComponent->SetIsOnRail(onRail);
|
|
||||||
havokVehiclePhysicsComponent->SetVelocity(velocity);
|
|
||||||
havokVehiclePhysicsComponent->SetDirtyVelocity(velocityFlag);
|
|
||||||
havokVehiclePhysicsComponent->SetAngularVelocity(angVelocity);
|
|
||||||
havokVehiclePhysicsComponent->SetDirtyAngularVelocity(angVelocityFlag);
|
|
||||||
havokVehiclePhysicsComponent->SetRemoteInputInfo(remoteInput);
|
|
||||||
} else {
|
|
||||||
// Need to get the mount's controllable physics
|
|
||||||
auto* controllablePhysicsComponent = possassableEntity->GetComponent<ControllablePhysicsComponent>();
|
|
||||||
if (!controllablePhysicsComponent) return;
|
|
||||||
controllablePhysicsComponent->SetPosition(position);
|
|
||||||
controllablePhysicsComponent->SetRotation(rotation);
|
|
||||||
controllablePhysicsComponent->SetIsOnGround(onGround);
|
|
||||||
controllablePhysicsComponent->SetIsOnRail(onRail);
|
|
||||||
controllablePhysicsComponent->SetVelocity(velocity);
|
|
||||||
controllablePhysicsComponent->SetDirtyVelocity(velocityFlag);
|
|
||||||
controllablePhysicsComponent->SetAngularVelocity(angVelocity);
|
|
||||||
controllablePhysicsComponent->SetDirtyAngularVelocity(angVelocityFlag);
|
|
||||||
}
|
|
||||||
Game::entityManager->SerializeEntity(possassableEntity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!updateChar) {
|
|
||||||
velocity = NiPoint3::ZERO;
|
|
||||||
angVelocity = NiPoint3::ZERO;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Handle statistics
|
|
||||||
auto* characterComponent = entity->GetComponent<CharacterComponent>();
|
|
||||||
if (characterComponent != nullptr) {
|
|
||||||
characterComponent->TrackPositionUpdate(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
comp->SetPosition(position);
|
|
||||||
comp->SetRotation(rotation);
|
|
||||||
comp->SetIsOnGround(onGround);
|
|
||||||
comp->SetIsOnRail(onRail);
|
|
||||||
comp->SetVelocity(velocity);
|
|
||||||
comp->SetDirtyVelocity(velocityFlag);
|
|
||||||
comp->SetAngularVelocity(angVelocity);
|
|
||||||
comp->SetDirtyAngularVelocity(angVelocityFlag);
|
|
||||||
|
|
||||||
auto* player = static_cast<Player*>(entity);
|
|
||||||
player->SetGhostReferencePoint(position);
|
|
||||||
Game::entityManager->QueueGhostUpdate(player->GetObjectID());
|
|
||||||
|
|
||||||
if (updateChar) Game::entityManager->SerializeEntity(entity);
|
|
||||||
|
|
||||||
//TODO: add moving platform stuffs
|
|
||||||
/*bool movingPlatformFlag;
|
|
||||||
inStream.Read(movingPlatformFlag);
|
|
||||||
if (movingPlatformFlag) {
|
|
||||||
LWOOBJID objectID;
|
|
||||||
NiPoint3 niData2;
|
|
||||||
|
|
||||||
inStream.Read(objectID);
|
|
||||||
inStream.Read(niData2.x);
|
|
||||||
inStream.Read(niData2.y);
|
|
||||||
inStream.Read(niData2.z);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool niData3Flag;
|
|
||||||
inStream.Read(niData3Flag);
|
|
||||||
if (niData3Flag) {
|
|
||||||
NiPoint3 niData3;
|
|
||||||
inStream.Read(niData3.x);
|
|
||||||
inStream.Read(niData3.y);
|
|
||||||
inStream.Read(niData3.z);
|
|
||||||
|
|
||||||
controllablePhysics->GetLocationData()->GetMovingPlatformData()->SetData3(niData3);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
for (int i = 0; i < Game::server->GetReplicaManager()->GetParticipantCount(); ++i)
|
|
||||||
{
|
|
||||||
const auto& player = Game::server->GetReplicaManager()->GetParticipantAtIndex(i);
|
|
||||||
|
|
||||||
if (entity->GetSystemAddress() == player)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Game::entityManager->SerializeEntity(entity, player);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientPackets::HandleChatModerationRequest(const SystemAddress& sysAddr, Packet* packet) {
|
ChatModerationRequest ClientPackets::HandleChatModerationRequest(Packet* packet) {
|
||||||
User* user = UserManager::Instance()->GetUser(sysAddr);
|
CINSTREAM_SKIP_HEADER;
|
||||||
if (!user) {
|
|
||||||
LOG("Unable to get user to parse chat moderation request");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* entity = Player::GetPlayer(sysAddr);
|
ChatModerationRequest request;
|
||||||
|
|
||||||
if (entity == nullptr) {
|
inStream.Read(request.chatLevel);
|
||||||
LOG("Unable to get player to parse chat moderation request");
|
inStream.Read(request.requestID);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the player has restricted chat access
|
|
||||||
auto* character = entity->GetCharacter();
|
|
||||||
|
|
||||||
if (character->HasPermission(ePermissionMap::RestrictedChatAccess)) {
|
|
||||||
// Send a message to the player
|
|
||||||
ChatPackets::SendSystemMessage(
|
|
||||||
sysAddr,
|
|
||||||
u"This character has restricted chat access."
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RakNet::BitStream stream(packet->data, packet->length, false);
|
|
||||||
|
|
||||||
uint64_t header;
|
|
||||||
stream.Read(header);
|
|
||||||
|
|
||||||
// Data
|
|
||||||
uint8_t chatLevel;
|
|
||||||
uint8_t requestID;
|
|
||||||
uint16_t messageLength;
|
|
||||||
|
|
||||||
std::string receiver = "";
|
|
||||||
std::string message = "";
|
|
||||||
|
|
||||||
stream.Read(chatLevel);
|
|
||||||
stream.Read(requestID);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < 42; ++i) {
|
for (uint32_t i = 0; i < 42; ++i) {
|
||||||
uint16_t character;
|
uint16_t character;
|
||||||
stream.Read(character);
|
inStream.Read(character);
|
||||||
receiver.push_back(static_cast<uint8_t>(character));
|
request.receiver.push_back(static_cast<uint8_t>(character));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!receiver.empty()) {
|
if (!request.receiver.empty()) {
|
||||||
if (std::string(receiver.c_str(), 4) == "[GM]") { // Shift the string forward if we are speaking to a GM as the client appends "[GM]" if they are
|
if (std::string(request.receiver.c_str(), 4) == "[GM]") { // Shift the string forward if we are speaking to a GM as the client appends "[GM]" if they are
|
||||||
receiver = std::string(receiver.c_str() + 4, receiver.size() - 4);
|
request.receiver = std::string(request.receiver.c_str() + 4, request.receiver.size() - 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.Read(messageLength);
|
uint16_t messageLength;
|
||||||
|
inStream.Read(messageLength);
|
||||||
for (uint32_t i = 0; i < messageLength; ++i) {
|
for (uint32_t i = 0; i < messageLength; ++i) {
|
||||||
uint16_t character;
|
uint16_t character;
|
||||||
stream.Read(character);
|
inStream.Read(character);
|
||||||
message.push_back(static_cast<uint8_t>(character));
|
request.message.push_back(static_cast<uint8_t>(character));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isBestFriend = false;
|
return request;
|
||||||
|
|
||||||
if (chatLevel == 1) {
|
|
||||||
// Private chat
|
|
||||||
LWOOBJID idOfReceiver = LWOOBJID_EMPTY;
|
|
||||||
|
|
||||||
{
|
|
||||||
auto characterIdFetch = Database::Get()->GetCharacterInfo(receiver);
|
|
||||||
|
|
||||||
if (characterIdFetch) {
|
|
||||||
idOfReceiver = characterIdFetch->id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const auto& bffMap = user->GetIsBestFriendMap();
|
|
||||||
if (bffMap.find(receiver) == bffMap.end() && idOfReceiver != LWOOBJID_EMPTY) {
|
|
||||||
auto bffInfo = Database::Get()->GetBestFriendStatus(entity->GetObjectID(), idOfReceiver);
|
|
||||||
|
|
||||||
if (bffInfo) {
|
|
||||||
isBestFriend = bffInfo->bestFriendStatus == 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isBestFriend) {
|
|
||||||
user->UpdateBestFriendValue(receiver, true);
|
|
||||||
}
|
|
||||||
} else if (bffMap.find(receiver) != bffMap.end()) {
|
|
||||||
isBestFriend = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::pair<uint8_t, uint8_t>> segments = Game::chatFilter->IsSentenceOkay(message, entity->GetGMLevel(), !(isBestFriend && chatLevel == 1));
|
|
||||||
|
|
||||||
bool bAllClean = segments.empty();
|
|
||||||
|
|
||||||
if (user->GetIsMuted()) {
|
|
||||||
bAllClean = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
user->SetLastChatMessageApproved(bAllClean);
|
|
||||||
WorldPackets::SendChatModerationResponse(sysAddr, bAllClean, requestID, receiver, segments);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientPackets::SendTop5HelpIssues(Packet* packet) {
|
int32_t ClientPackets::SendTop5HelpIssues(Packet* packet) {
|
||||||
auto* user = UserManager::Instance()->GetUser(packet->systemAddress);
|
|
||||||
if (!user) return;
|
|
||||||
auto* character = user->GetLastUsedChar();
|
|
||||||
if (!character) return;
|
|
||||||
auto * entity = character->GetEntity();
|
|
||||||
if (!entity) return;
|
|
||||||
|
|
||||||
CINSTREAM_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
int32_t language = 0;
|
int32_t language = 0;
|
||||||
inStream.Read(language);
|
inStream.Read(language);
|
||||||
|
return language;
|
||||||
// TODO: Handle different languages in a nice way
|
|
||||||
// 0: en_US
|
|
||||||
// 1: pl_US
|
|
||||||
// 2: de_DE
|
|
||||||
// 3: en_GB
|
|
||||||
|
|
||||||
AMFArrayValue data;
|
|
||||||
// Summaries
|
|
||||||
data.Insert("Summary0", Game::config->GetValue("help_0_summary"));
|
|
||||||
data.Insert("Summary1", Game::config->GetValue("help_1_summary"));
|
|
||||||
data.Insert("Summary2", Game::config->GetValue("help_2_summary"));
|
|
||||||
data.Insert("Summary3", Game::config->GetValue("help_3_summary"));
|
|
||||||
data.Insert("Summary4", Game::config->GetValue("help_4_summary"));
|
|
||||||
|
|
||||||
// Descriptions
|
|
||||||
data.Insert("Description0", Game::config->GetValue("help_0_description"));
|
|
||||||
data.Insert("Description1", Game::config->GetValue("help_1_description"));
|
|
||||||
data.Insert("Description2", Game::config->GetValue("help_2_description"));
|
|
||||||
data.Insert("Description3", Game::config->GetValue("help_3_description"));
|
|
||||||
data.Insert("Description4", Game::config->GetValue("help_4_description"));
|
|
||||||
|
|
||||||
GameMessages::SendUIMessageServerToSingleClient(entity, packet->systemAddress, "UIHelpTop5", data);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,31 @@
|
|||||||
#ifndef CLIENTPACKETS_H
|
#ifndef CLIENTPACKETS_H
|
||||||
#define CLIENTPACKETS_H
|
#define CLIENTPACKETS_H
|
||||||
|
|
||||||
#include "RakNetTypes.h"
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class PositionUpdate;
|
||||||
|
|
||||||
|
struct Packet;
|
||||||
|
|
||||||
|
struct ChatMessage {
|
||||||
|
uint8_t chatChannel = 0;
|
||||||
|
uint16_t unknown = 0;
|
||||||
|
std::u16string message;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ChatModerationRequest {
|
||||||
|
uint8_t chatLevel = 0;
|
||||||
|
uint8_t requestID = 0;
|
||||||
|
std::string receiver;
|
||||||
|
std::string message;
|
||||||
|
};
|
||||||
|
|
||||||
namespace ClientPackets {
|
namespace ClientPackets {
|
||||||
void HandleChatMessage(const SystemAddress& sysAddr, Packet* packet);
|
ChatMessage HandleChatMessage(Packet* packet);
|
||||||
void HandleClientPositionUpdate(const SystemAddress& sysAddr, Packet* packet);
|
PositionUpdate HandleClientPositionUpdate(Packet* packet);
|
||||||
void HandleChatModerationRequest(const SystemAddress& sysAddr, Packet* packet);
|
ChatModerationRequest HandleChatModerationRequest(Packet* packet);
|
||||||
void SendTop5HelpIssues(Packet* packet);
|
int32_t SendTop5HelpIssues(Packet* packet);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CLIENTPACKETS_H
|
#endif // CLIENTPACKETS_H
|
||||||
|
@ -1,26 +1,22 @@
|
|||||||
#include "dCommonVars.h"
|
|
||||||
#include "WorldPackets.h"
|
#include "WorldPackets.h"
|
||||||
|
#include "dCommonVars.h"
|
||||||
#include "BitStream.h"
|
#include "BitStream.h"
|
||||||
#include "PacketUtils.h"
|
#include "PacketUtils.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
#include "User.h"
|
|
||||||
#include "Character.h"
|
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include <iostream>
|
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "LDFFormat.h"
|
#include "LDFFormat.h"
|
||||||
#include "dServer.h"
|
#include "dServer.h"
|
||||||
#include "dZoneManager.h"
|
|
||||||
#include "CharacterComponent.h"
|
|
||||||
#include "ZCompression.h"
|
#include "ZCompression.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "BitStreamUtils.h"
|
#include "BitStreamUtils.h"
|
||||||
|
|
||||||
void WorldPackets::SendLoadStaticZone(const SystemAddress& sysAddr, float x, float y, float z, uint32_t checksum) {
|
#include <iostream>
|
||||||
|
|
||||||
|
void WorldPackets::SendLoadStaticZone(const SystemAddress& sysAddr, float x, float y, float z, uint32_t checksum, LWOZONEID zone) {
|
||||||
RakNet::BitStream bitStream;
|
RakNet::BitStream bitStream;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::LOAD_STATIC_ZONE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::LOAD_STATIC_ZONE);
|
||||||
|
|
||||||
auto zone = Game::zoneManager->GetZone()->GetZoneID();
|
|
||||||
bitStream.Write<uint16_t>(zone.GetMapID());
|
bitStream.Write<uint16_t>(zone.GetMapID());
|
||||||
bitStream.Write<uint16_t>(zone.GetInstanceID());
|
bitStream.Write<uint16_t>(zone.GetInstanceID());
|
||||||
//bitStream.Write<uint32_t>(zone.GetCloneID());
|
//bitStream.Write<uint32_t>(zone.GetCloneID());
|
||||||
@ -38,57 +34,6 @@ void WorldPackets::SendLoadStaticZone(const SystemAddress& sysAddr, float x, flo
|
|||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldPackets::SendCharacterList(const SystemAddress& sysAddr, User* user) {
|
|
||||||
if (!user) return;
|
|
||||||
|
|
||||||
RakNet::BitStream bitStream;
|
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::CHARACTER_LIST_RESPONSE);
|
|
||||||
|
|
||||||
std::vector<Character*> characters = user->GetCharacters();
|
|
||||||
bitStream.Write<uint8_t>(characters.size());
|
|
||||||
bitStream.Write<uint8_t>(0); //character index in front, just picking 0
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < characters.size(); ++i) {
|
|
||||||
bitStream.Write(characters[i]->GetObjectID());
|
|
||||||
bitStream.Write<uint32_t>(0);
|
|
||||||
|
|
||||||
bitStream.Write(LUWString(characters[i]->GetName()));
|
|
||||||
bitStream.Write(LUWString(characters[i]->GetUnapprovedName()));
|
|
||||||
|
|
||||||
bitStream.Write<uint8_t>(characters[i]->GetNameRejected());
|
|
||||||
bitStream.Write<uint8_t>(false);
|
|
||||||
|
|
||||||
bitStream.Write(LUString("", 10));
|
|
||||||
|
|
||||||
bitStream.Write(characters[i]->GetShirtColor());
|
|
||||||
bitStream.Write(characters[i]->GetShirtStyle());
|
|
||||||
bitStream.Write(characters[i]->GetPantsColor());
|
|
||||||
bitStream.Write(characters[i]->GetHairStyle());
|
|
||||||
bitStream.Write(characters[i]->GetHairColor());
|
|
||||||
bitStream.Write(characters[i]->GetLeftHand());
|
|
||||||
bitStream.Write(characters[i]->GetRightHand());
|
|
||||||
bitStream.Write(characters[i]->GetEyebrows());
|
|
||||||
bitStream.Write(characters[i]->GetEyes());
|
|
||||||
bitStream.Write(characters[i]->GetMouth());
|
|
||||||
bitStream.Write<uint32_t>(0);
|
|
||||||
|
|
||||||
bitStream.Write<uint16_t>(characters[i]->GetZoneID());
|
|
||||||
bitStream.Write<uint16_t>(characters[i]->GetZoneInstance());
|
|
||||||
bitStream.Write(characters[i]->GetZoneClone());
|
|
||||||
|
|
||||||
bitStream.Write(characters[i]->GetLastLogin());
|
|
||||||
|
|
||||||
const auto& equippedItems = characters[i]->GetEquippedItems();
|
|
||||||
bitStream.Write<uint16_t>(equippedItems.size());
|
|
||||||
|
|
||||||
for (uint32_t j = 0; j < equippedItems.size(); ++j) {
|
|
||||||
bitStream.Write(equippedItems[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SEND_PACKET;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldPackets::SendCharacterCreationResponse(const SystemAddress& sysAddr, eCharacterCreationResponse response) {
|
void WorldPackets::SendCharacterCreationResponse(const SystemAddress& sysAddr, eCharacterCreationResponse response) {
|
||||||
RakNet::BitStream bitStream;
|
RakNet::BitStream bitStream;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::CHARACTER_CREATE_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::CHARACTER_CREATE_RESPONSE);
|
||||||
@ -128,26 +73,20 @@ void WorldPackets::SendServerState(const SystemAddress& sysAddr) {
|
|||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, Entity* entity, const std::string& xmlData, const std::u16string& username, eGameMasterLevel gm) {
|
void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, int64_t reputation, LWOOBJID player, const std::string& xmlData, const std::u16string& username, eGameMasterLevel gm) {
|
||||||
RakNet::BitStream bitStream;
|
RakNet::BitStream bitStream;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::CREATE_CHARACTER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::CREATE_CHARACTER);
|
||||||
|
|
||||||
RakNet::BitStream data;
|
RakNet::BitStream data;
|
||||||
data.Write<uint32_t>(7); //LDF key count
|
data.Write<uint32_t>(7); //LDF key count
|
||||||
|
|
||||||
auto character = entity->GetComponent<CharacterComponent>();
|
std::unique_ptr<LDFData<LWOOBJID>> objid(new LDFData<LWOOBJID>(u"objid", player));
|
||||||
if (!character) {
|
std::unique_ptr<LDFData<LOT>> lot(new LDFData<LOT>(u"template", 1));
|
||||||
LOG("Entity is not a character?? what??");
|
std::unique_ptr<LDFData<std::string>> xmlConfigData(new LDFData<std::string>(u"xmlData", xmlData));
|
||||||
return;
|
std::unique_ptr<LDFData<std::u16string>> name(new LDFData<std::u16string>(u"name", username));
|
||||||
}
|
std::unique_ptr<LDFData<int32_t>> gmlevel(new LDFData<int32_t>(u"gmlevel", static_cast<int32_t>(gm)));
|
||||||
|
std::unique_ptr<LDFData<int32_t>> chatmode(new LDFData<int32_t>(u"chatmode", static_cast<int32_t>(gm)));
|
||||||
LDFData<LWOOBJID>* objid = new LDFData<LWOOBJID>(u"objid", entity->GetObjectID());
|
std::unique_ptr<LDFData<int64_t>> reputationLdf(new LDFData<int64_t>(u"reputation", reputation));
|
||||||
LDFData<LOT>* lot = new LDFData<LOT>(u"template", 1);
|
|
||||||
LDFData<std::string>* xmlConfigData = new LDFData<std::string>(u"xmlData", xmlData);
|
|
||||||
LDFData<std::u16string>* name = new LDFData<std::u16string>(u"name", username);
|
|
||||||
LDFData<int32_t>* gmlevel = new LDFData<int32_t>(u"gmlevel", static_cast<int32_t>(gm));
|
|
||||||
LDFData<int32_t>* chatmode = new LDFData<int32_t>(u"chatmode", static_cast<int32_t>(gm));
|
|
||||||
LDFData<int64_t>* reputation = new LDFData<int64_t>(u"reputation", character->GetReputation());
|
|
||||||
|
|
||||||
objid->WriteToPacket(&data);
|
objid->WriteToPacket(&data);
|
||||||
lot->WriteToPacket(&data);
|
lot->WriteToPacket(&data);
|
||||||
@ -155,15 +94,7 @@ void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, Entity* ent
|
|||||||
gmlevel->WriteToPacket(&data);
|
gmlevel->WriteToPacket(&data);
|
||||||
chatmode->WriteToPacket(&data);
|
chatmode->WriteToPacket(&data);
|
||||||
xmlConfigData->WriteToPacket(&data);
|
xmlConfigData->WriteToPacket(&data);
|
||||||
reputation->WriteToPacket(&data);
|
reputationLdf->WriteToPacket(&data);
|
||||||
|
|
||||||
delete objid;
|
|
||||||
delete lot;
|
|
||||||
delete xmlConfigData;
|
|
||||||
delete gmlevel;
|
|
||||||
delete chatmode;
|
|
||||||
delete name;
|
|
||||||
delete reputation;
|
|
||||||
|
|
||||||
//Compress the data before sending:
|
//Compress the data before sending:
|
||||||
const uint32_t reservedSize = ZCompression::GetMaxCompressedLength(data.GetNumberOfBytesUsed());
|
const uint32_t reservedSize = ZCompression::GetMaxCompressedLength(data.GetNumberOfBytesUsed());
|
||||||
@ -187,14 +118,12 @@ void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, Entity* ent
|
|||||||
* an assertion is done to prevent bad data from being saved or sent.
|
* an assertion is done to prevent bad data from being saved or sent.
|
||||||
*/
|
*/
|
||||||
#pragma warning(disable:6385) // C6385 Reading invalid data from 'compressedData'.
|
#pragma warning(disable:6385) // C6385 Reading invalid data from 'compressedData'.
|
||||||
for (size_t i = 0; i < size; i++)
|
bitStream.WriteAlignedBytes(compressedData, size);
|
||||||
bitStream.Write(compressedData[i]);
|
|
||||||
#pragma warning(default:6385)
|
#pragma warning(default:6385)
|
||||||
|
|
||||||
// PacketUtils::SavePacket("chardata.bin", (const char*)bitStream.GetData(), static_cast<uint32_t>(bitStream.GetNumberOfBytesUsed()));
|
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
delete[] compressedData;
|
delete[] compressedData;
|
||||||
LOG("Sent CreateCharacter for ID: %llu", entity->GetObjectID());
|
LOG("Sent CreateCharacter for ID: %llu", player);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldPackets::SendChatModerationResponse(const SystemAddress& sysAddr, bool requestAccepted, uint32_t requestID, const std::string& receiver, std::vector<std::pair<uint8_t, uint8_t>> unacceptedItems) {
|
void WorldPackets::SendChatModerationResponse(const SystemAddress& sysAddr, bool requestAccepted, uint32_t requestID, const std::string& receiver, std::vector<std::pair<uint8_t, uint8_t>> unacceptedItems) {
|
||||||
|
@ -2,9 +2,8 @@
|
|||||||
#define WORLDPACKETS_H
|
#define WORLDPACKETS_H
|
||||||
|
|
||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
|
||||||
#include "Entity.h"
|
|
||||||
|
|
||||||
class User;
|
class User;
|
||||||
struct SystemAddress;
|
struct SystemAddress;
|
||||||
@ -13,14 +12,13 @@ enum class eCharacterCreationResponse : uint8_t;
|
|||||||
enum class eRenameResponse : uint8_t;
|
enum class eRenameResponse : uint8_t;
|
||||||
|
|
||||||
namespace WorldPackets {
|
namespace WorldPackets {
|
||||||
void SendLoadStaticZone(const SystemAddress& sysAddr, float x, float y, float z, uint32_t checksum);
|
void SendLoadStaticZone(const SystemAddress& sysAddr, float x, float y, float z, uint32_t checksum, LWOZONEID zone);
|
||||||
void SendCharacterList(const SystemAddress& sysAddr, User* user);
|
|
||||||
void SendCharacterCreationResponse(const SystemAddress& sysAddr, eCharacterCreationResponse response);
|
void SendCharacterCreationResponse(const SystemAddress& sysAddr, eCharacterCreationResponse response);
|
||||||
void SendCharacterRenameResponse(const SystemAddress& sysAddr, eRenameResponse response);
|
void SendCharacterRenameResponse(const SystemAddress& sysAddr, eRenameResponse response);
|
||||||
void SendCharacterDeleteResponse(const SystemAddress& sysAddr, bool response);
|
void SendCharacterDeleteResponse(const SystemAddress& sysAddr, bool response);
|
||||||
void SendTransferToWorld(const SystemAddress& sysAddr, const std::string& serverIP, uint32_t serverPort, bool mythranShift);
|
void SendTransferToWorld(const SystemAddress& sysAddr, const std::string& serverIP, uint32_t serverPort, bool mythranShift);
|
||||||
void SendServerState(const SystemAddress& sysAddr);
|
void SendServerState(const SystemAddress& sysAddr);
|
||||||
void SendCreateCharacter(const SystemAddress& sysAddr, Entity* entity, const std::string& xmlData, const std::u16string& username, eGameMasterLevel gm);
|
void SendCreateCharacter(const SystemAddress& sysAddr, int64_t reputation, LWOOBJID player, const std::string& xmlData, const std::u16string& username, eGameMasterLevel gm);
|
||||||
void SendChatModerationResponse(const SystemAddress& sysAddr, bool requestAccepted, uint32_t requestID, const std::string& receiver, std::vector<std::pair<uint8_t, uint8_t>> unacceptedItems);
|
void SendChatModerationResponse(const SystemAddress& sysAddr, bool requestAccepted, uint32_t requestID, const std::string& receiver, std::vector<std::pair<uint8_t, uint8_t>> unacceptedItems);
|
||||||
void SendGMLevelChange(const SystemAddress& sysAddr, bool success, eGameMasterLevel highestLevel, eGameMasterLevel prevLevel, eGameMasterLevel newLevel);
|
void SendGMLevelChange(const SystemAddress& sysAddr, bool success, eGameMasterLevel highestLevel, eGameMasterLevel prevLevel, eGameMasterLevel newLevel);
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,7 @@
|
|||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
#include "StringifiedEnum.h"
|
#include "StringifiedEnum.h"
|
||||||
#include "Server.h"
|
#include "Server.h"
|
||||||
|
#include "PositionUpdate.h"
|
||||||
|
|
||||||
namespace Game {
|
namespace Game {
|
||||||
Logger* logger = nullptr;
|
Logger* logger = nullptr;
|
||||||
@ -713,7 +714,7 @@ void HandleMasterPacket(Packet* packet) {
|
|||||||
z = pos.z;
|
z = pos.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldPackets::SendLoadStaticZone(it->second.sysAddr, x, y, z, zone->GetChecksum());
|
WorldPackets::SendLoadStaticZone(it->second.sysAddr, x, y, z, zone->GetChecksum(), Game::zoneManager->GetZoneID());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Game::server->GetZoneID() == 0) {
|
if (Game::server->GetZoneID() == 0) {
|
||||||
@ -1005,7 +1006,10 @@ void HandlePacket(Packet* packet) {
|
|||||||
info.lot = 1;
|
info.lot = 1;
|
||||||
Entity* player = Game::entityManager->CreateEntity(info, UserManager::Instance()->GetUser(packet->systemAddress));
|
Entity* player = Game::entityManager->CreateEntity(info, UserManager::Instance()->GetUser(packet->systemAddress));
|
||||||
|
|
||||||
WorldPackets::SendCreateCharacter(packet->systemAddress, player, c->GetXMLData(), username, c->GetGMLevel());
|
auto* characterComponent = player->GetComponent<CharacterComponent>();
|
||||||
|
if (!characterComponent) return;
|
||||||
|
|
||||||
|
WorldPackets::SendCreateCharacter(packet->systemAddress, player->GetComponent<CharacterComponent>()->GetReputation(), player->GetObjectID(), c->GetXMLData(), username, c->GetGMLevel());
|
||||||
WorldPackets::SendServerState(packet->systemAddress);
|
WorldPackets::SendServerState(packet->systemAddress);
|
||||||
|
|
||||||
const auto respawnPoint = player->GetCharacter()->GetRespawnPoint(Game::zoneManager->GetZone()->GetWorldID());
|
const auto respawnPoint = player->GetCharacter()->GetRespawnPoint(Game::zoneManager->GetZone()->GetWorldID());
|
||||||
@ -1018,8 +1022,6 @@ void HandlePacket(Packet* packet) {
|
|||||||
|
|
||||||
Game::entityManager->ConstructAllEntities(packet->systemAddress);
|
Game::entityManager->ConstructAllEntities(packet->systemAddress);
|
||||||
|
|
||||||
auto* characterComponent = player->GetComponent<CharacterComponent>();
|
|
||||||
if (!characterComponent) return;
|
|
||||||
characterComponent->RocketUnEquip(player);
|
characterComponent->RocketUnEquip(player);
|
||||||
|
|
||||||
// Do charxml fixes here
|
// Do charxml fixes here
|
||||||
@ -1142,7 +1144,16 @@ void HandlePacket(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case eWorldMessageType::POSITION_UPDATE: {
|
case eWorldMessageType::POSITION_UPDATE: {
|
||||||
ClientPackets::HandleClientPositionUpdate(packet->systemAddress, packet);
|
auto positionUpdate = ClientPackets::HandleClientPositionUpdate(packet);
|
||||||
|
|
||||||
|
User* user = UserManager::Instance()->GetUser(packet->systemAddress);
|
||||||
|
if (!user) {
|
||||||
|
LOG("Unable to get user to parse position update");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* entity = Game::entityManager->GetEntity(user->GetLastUsedChar()->GetObjectID());
|
||||||
|
if (entity) entity->ProcessPositionUpdate(positionUpdate);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1190,7 +1201,74 @@ void HandlePacket(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case eWorldMessageType::STRING_CHECK: {
|
case eWorldMessageType::STRING_CHECK: {
|
||||||
ClientPackets::HandleChatModerationRequest(packet->systemAddress, packet);
|
auto request = ClientPackets::HandleChatModerationRequest(packet);
|
||||||
|
|
||||||
|
// TODO: Find a good home for the logic in this case.
|
||||||
|
User* user = UserManager::Instance()->GetUser(packet->systemAddress);
|
||||||
|
if (!user) {
|
||||||
|
LOG("Unable to get user to parse chat moderation request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* entity = Player::GetPlayer(packet->systemAddress);
|
||||||
|
|
||||||
|
if (entity == nullptr) {
|
||||||
|
LOG("Unable to get player to parse chat moderation request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the player has restricted chat access
|
||||||
|
auto* character = entity->GetCharacter();
|
||||||
|
|
||||||
|
if (character->HasPermission(ePermissionMap::RestrictedChatAccess)) {
|
||||||
|
// Send a message to the player
|
||||||
|
ChatPackets::SendSystemMessage(
|
||||||
|
packet->systemAddress,
|
||||||
|
u"This character has restricted chat access."
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isBestFriend = false;
|
||||||
|
|
||||||
|
if (request.chatLevel == 1) {
|
||||||
|
// Private chat
|
||||||
|
LWOOBJID idOfReceiver = LWOOBJID_EMPTY;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto characterIdFetch = Database::Get()->GetCharacterInfo(request.receiver);
|
||||||
|
|
||||||
|
if (characterIdFetch) {
|
||||||
|
idOfReceiver = characterIdFetch->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto& bffMap = user->GetIsBestFriendMap();
|
||||||
|
if (bffMap.find(request.receiver) == bffMap.end() && idOfReceiver != LWOOBJID_EMPTY) {
|
||||||
|
auto bffInfo = Database::Get()->GetBestFriendStatus(entity->GetObjectID(), idOfReceiver);
|
||||||
|
|
||||||
|
if (bffInfo) {
|
||||||
|
isBestFriend = bffInfo->bestFriendStatus == 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isBestFriend) {
|
||||||
|
user->UpdateBestFriendValue(request.receiver, true);
|
||||||
|
}
|
||||||
|
} else if (bffMap.find(request.receiver) != bffMap.end()) {
|
||||||
|
isBestFriend = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<uint8_t, uint8_t>> segments = Game::chatFilter->IsSentenceOkay(request.message, entity->GetGMLevel(), !(isBestFriend && request.chatLevel == 1));
|
||||||
|
|
||||||
|
bool bAllClean = segments.empty();
|
||||||
|
|
||||||
|
if (user->GetIsMuted()) {
|
||||||
|
bAllClean = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
user->SetLastChatMessageApproved(bAllClean);
|
||||||
|
WorldPackets::SendChatModerationResponse(packet->systemAddress, bAllClean, request.requestID, request.receiver, segments);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1198,7 +1276,29 @@ void HandlePacket(Packet* packet) {
|
|||||||
if (chatDisabled) {
|
if (chatDisabled) {
|
||||||
ChatPackets::SendMessageFail(packet->systemAddress);
|
ChatPackets::SendMessageFail(packet->systemAddress);
|
||||||
} else {
|
} else {
|
||||||
ClientPackets::HandleChatMessage(packet->systemAddress, packet);
|
auto chatMessage = ClientPackets::HandleChatMessage(packet);
|
||||||
|
|
||||||
|
// TODO: Find a good home for the logic in this case.
|
||||||
|
User* user = UserManager::Instance()->GetUser(packet->systemAddress);
|
||||||
|
if (!user) {
|
||||||
|
LOG("Unable to get user to parse chat message");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user->GetIsMuted()) {
|
||||||
|
user->GetLastUsedChar()->SendMuteNotice();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::string playerName = user->GetLastUsedChar()->GetName();
|
||||||
|
bool isMythran = user->GetLastUsedChar()->GetGMLevel() > eGameMasterLevel::CIVILIAN;
|
||||||
|
bool isOk = Game::chatFilter->IsSentenceOkay(GeneralUtils::UTF16ToWTF8(chatMessage.message), user->GetLastUsedChar()->GetGMLevel()).empty();
|
||||||
|
LOG_DEBUG("Msg: %s was approved previously? %i", GeneralUtils::UTF16ToWTF8(chatMessage.message).c_str(), user->GetLastChatMessageApproved());
|
||||||
|
if (!isOk) return;
|
||||||
|
if (!isOk && !isMythran) return;
|
||||||
|
|
||||||
|
std::string sMessage = GeneralUtils::UTF16ToWTF8(chatMessage.message);
|
||||||
|
LOG("%s: %s", playerName.c_str(), sMessage.c_str());
|
||||||
|
ChatPackets::SendChatMessage(packet->systemAddress, chatMessage.chatChannel, playerName, user->GetLoggedInChar(), isMythran, chatMessage.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -1224,7 +1324,37 @@ void HandlePacket(Packet* packet) {
|
|||||||
|
|
||||||
|
|
||||||
case eWorldMessageType::UI_HELP_TOP_5: {
|
case eWorldMessageType::UI_HELP_TOP_5: {
|
||||||
ClientPackets::SendTop5HelpIssues(packet);
|
auto language = ClientPackets::SendTop5HelpIssues(packet);
|
||||||
|
// TODO: Handle different languages in a nice way
|
||||||
|
// 0: en_US
|
||||||
|
// 1: pl_US
|
||||||
|
// 2: de_DE
|
||||||
|
// 3: en_GB
|
||||||
|
|
||||||
|
// TODO: Find a good home for the logic in this case.
|
||||||
|
auto* user = UserManager::Instance()->GetUser(packet->systemAddress);
|
||||||
|
if (!user) return;
|
||||||
|
auto* character = user->GetLastUsedChar();
|
||||||
|
if (!character) return;
|
||||||
|
auto* entity = character->GetEntity();
|
||||||
|
if (!entity) return;
|
||||||
|
|
||||||
|
AMFArrayValue data;
|
||||||
|
// Summaries
|
||||||
|
data.Insert("Summary0", Game::config->GetValue("help_0_summary"));
|
||||||
|
data.Insert("Summary1", Game::config->GetValue("help_1_summary"));
|
||||||
|
data.Insert("Summary2", Game::config->GetValue("help_2_summary"));
|
||||||
|
data.Insert("Summary3", Game::config->GetValue("help_3_summary"));
|
||||||
|
data.Insert("Summary4", Game::config->GetValue("help_4_summary"));
|
||||||
|
|
||||||
|
// Descriptions
|
||||||
|
data.Insert("Description0", Game::config->GetValue("help_0_description"));
|
||||||
|
data.Insert("Description1", Game::config->GetValue("help_1_description"));
|
||||||
|
data.Insert("Description2", Game::config->GetValue("help_2_description"));
|
||||||
|
data.Insert("Description3", Game::config->GetValue("help_3_description"));
|
||||||
|
data.Insert("Description4", Game::config->GetValue("help_4_description"));
|
||||||
|
|
||||||
|
GameMessages::SendUIMessageServerToSingleClient(entity, packet->systemAddress, "UIHelpTop5", data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user