Skip to content

Commit

Permalink
fix: the door problem (again)
Browse files Browse the repository at this point in the history
  • Loading branch information
RobbeBryssinck committed May 28, 2022
1 parent 6cd70c5 commit 77c0098
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 25 deletions.
6 changes: 6 additions & 0 deletions Code/client/Services/CharacterService.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ struct DialogueEvent;
struct NotifyDialogue;
struct SubtitleEvent;
struct NotifySubtitle;
struct NotifyActorTeleport;

struct Actor;
struct World;
Expand Down Expand Up @@ -79,9 +80,13 @@ struct CharacterService
void OnNotifyDialogue(const NotifyDialogue& acMessage) noexcept;
void OnSubtitleEvent(const SubtitleEvent& acEvent) noexcept;
void OnNotifySubtitle(const NotifySubtitle& acMessage) noexcept;
void OnNotifyActorTeleport(const NotifyActorTeleport& acMessage) noexcept;

private:

void MoveActor(const Actor* apActor, const GameId& acWorldSpaceId, const GameId& acCellId,
const Vector3_NetQuantize& acPosition) const noexcept;

void ProcessNewEntity(entt::entity aEntity) const noexcept;
void RequestServerAssignment(entt::entity aEntity) const noexcept;
void CancelServerAssignment(entt::entity aEntity, uint32_t aFormId) const noexcept;
Expand Down Expand Up @@ -130,4 +135,5 @@ struct CharacterService
entt::scoped_connection m_dialogueSyncConnection;
entt::scoped_connection m_subtitleEventConnection;
entt::scoped_connection m_subtitleSyncConnection;
entt::scoped_connection m_actorTeleportConnection;
};
83 changes: 64 additions & 19 deletions Code/client/Services/Generic/CharacterService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
#include <Messages/NotifyDialogue.h>
#include <Messages/SubtitleRequest.h>
#include <Messages/NotifySubtitle.h>
#include <Messages/NotifyActorTeleport.h>

#include <World.h>
#include <Games/TES.h>
Expand Down Expand Up @@ -112,6 +113,8 @@ CharacterService::CharacterService(World& aWorld, entt::dispatcher& aDispatcher,

m_subtitleEventConnection = m_dispatcher.sink<SubtitleEvent>().connect<&CharacterService::OnSubtitleEvent>(this);
m_subtitleSyncConnection = m_dispatcher.sink<NotifySubtitle>().connect<&CharacterService::OnNotifySubtitle>(this);

m_actorTeleportConnection = m_dispatcher.sink<NotifyActorTeleport>().connect<&CharacterService::OnNotifyActorTeleport>(this);
}

void CharacterService::OnActorAdded(const ActorAddedEvent& acEvent) noexcept
Expand Down Expand Up @@ -302,23 +305,7 @@ void CharacterService::OnAssignCharacter(const AssignCharacterResponse& acMessag
if (pActor->actorState.IsWeaponDrawn() != acMessage.IsWeaponDrawn)
m_weaponDrawUpdates[pActor->formID] = {0, acMessage.IsWeaponDrawn};

const uint32_t cCellId = m_world.GetModSystem().GetGameId(acMessage.CellId);
TESObjectCELL* pCell = Cast<TESObjectCELL>(TESForm::GetById(cCellId));

// In case of lazy-loading of exterior cells
if (!pCell)
{
const uint32_t cWorldSpaceId = m_world.GetModSystem().GetGameId(acMessage.WorldSpaceId);
TESWorldSpace* const pWorldSpace = Cast<TESWorldSpace>(TESForm::GetById(cWorldSpaceId));
if (pWorldSpace)
{
GridCellCoords coordinates = GridCellCoords::CalculateGridCellCoords(acMessage.Position);
pCell = pWorldSpace->LoadCell(coordinates.X, coordinates.Y);
}
}

if (pCell)
pActor->MoveTo(pCell, acMessage.Position);
MoveActor(pActor, acMessage.WorldSpaceId, acMessage.CellId, acMessage.Position);
}
}

Expand Down Expand Up @@ -586,7 +573,7 @@ void CharacterService::OnOwnershipTransfer(const NotifyOwnershipTransfer& acMess

spdlog::warn("Actor for ownership transfer not found {:X}", acMessage.ServerId);

RequestOwnershipTransfer request;
RequestOwnershipTransfer request{};
request.ServerId = acMessage.ServerId;

m_transport.Send(request);
Expand Down Expand Up @@ -1126,6 +1113,42 @@ void CharacterService::OnNotifySubtitle(const NotifySubtitle& acMessage) noexcep
SubtitleManager::Get()->ShowSubtitle(pActor, acMessage.Text.c_str());
}

void CharacterService::OnNotifyActorTeleport(const NotifyActorTeleport& acMessage) noexcept
{
auto& modSystem = m_world.GetModSystem();

const uint32_t cActorId = World::Get().GetModSystem().GetGameId(acMessage.FormId);
Actor* pActor = Cast<Actor>(TESForm::GetById(cActorId));
if (!pActor)
{
spdlog::error(__FUNCTION__ ": failed to retrieve actor to teleport.");
return;
}

MoveActor(pActor, acMessage.WorldSpaceId, acMessage.CellId, acMessage.Position);
}

void CharacterService::MoveActor(const Actor* apActor, const GameId& acWorldSpaceId, const GameId& acCellId, const Vector3_NetQuantize& acPosition) const noexcept
{
const uint32_t cCellId = m_world.GetModSystem().GetGameId(acCellId);
TESObjectCELL* pCell = Cast<TESObjectCELL>(TESForm::GetById(cCellId));

// In case of lazy-loading of exterior cells
if (!pCell)
{
const uint32_t cWorldSpaceId = m_world.GetModSystem().GetGameId(acWorldSpaceId);
TESWorldSpace* const pWorldSpace = Cast<TESWorldSpace>(TESForm::GetById(cWorldSpaceId));
if (pWorldSpace)
{
GridCellCoords coordinates = GridCellCoords::CalculateGridCellCoords(acPosition);
pCell = pWorldSpace->LoadCell(coordinates.X, coordinates.Y);
}
}

if (pCell)
apActor->MoveTo(pCell, acPosition);
}

void CharacterService::ProcessNewEntity(entt::entity aEntity) const noexcept
{
if (!m_transport.IsOnline())
Expand Down Expand Up @@ -1338,9 +1361,31 @@ void CharacterService::CancelServerAssignment(const entt::entity aEntity, const
{
auto& localComponent = m_world.get<LocalComponent>(aEntity);

RequestOwnershipTransfer request;
RequestOwnershipTransfer request{};
request.ServerId = localComponent.Id;

if (Actor* pActor = Cast<Actor>(TESForm::GetById(aFormId)))
{
if (pActor->IsTemporary())
{
auto& modSystem = m_world.GetModSystem();

if (TESWorldSpace* pWorldSpace = pActor->GetWorldSpace())
{
if (!modSystem.GetServerModId(pWorldSpace->formID, request.WorldSpaceId))
spdlog::error("World space id not found, despite having a world space, {:X}", pWorldSpace->formID);
}

if (TESObjectCELL* pCell = pActor->GetParentCell())
{
if (!modSystem.GetServerModId(pCell->formID, request.CellId))
spdlog::error("Cell id not found, despite having a cell, {:X}", pCell->formID);
}

request.Position = pActor->position;
}
}

m_transport.Send(request);

m_world.remove<LocalAnimationComponent, LocalComponent>(aEntity);
Expand Down
19 changes: 19 additions & 0 deletions Code/encoding/Messages/NotifyActorTeleport.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include <Messages/NotifyActorTeleport.h>

void NotifyActorTeleport::SerializeRaw(TiltedPhoques::Buffer::Writer& aWriter) const noexcept
{
FormId.Serialize(aWriter);
WorldSpaceId.Serialize(aWriter);
CellId.Serialize(aWriter);
Position.Serialize(aWriter);
}

void NotifyActorTeleport::DeserializeRaw(TiltedPhoques::Buffer::Reader& aReader) noexcept
{
ServerMessage::DeserializeRaw(aReader);

FormId.Deserialize(aReader);
WorldSpaceId.Deserialize(aReader);
CellId.Deserialize(aReader);
Position.Deserialize(aReader);
}
31 changes: 31 additions & 0 deletions Code/encoding/Messages/NotifyActorTeleport.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include "Message.h"
#include <Structs/GameId.h>
#include <Structs/Vector3_NetQuantize.h>

struct NotifyActorTeleport final : ServerMessage
{
static constexpr ServerOpcode Opcode = kNotifyActorTeleport;

NotifyActorTeleport() : ServerMessage(Opcode)
{
}

void SerializeRaw(TiltedPhoques::Buffer::Writer& aWriter) const noexcept override;
void DeserializeRaw(TiltedPhoques::Buffer::Reader& aReader) noexcept override;

bool operator==(const NotifyActorTeleport& acRhs) const noexcept
{
return GetOpcode() == acRhs.GetOpcode() &&
FormId == acRhs.FormId &&
WorldSpaceId == acRhs.WorldSpaceId &&
CellId == acRhs.CellId &&
Position == acRhs.Position;
}

GameId FormId{};
GameId WorldSpaceId{};
GameId CellId{};
Vector3_NetQuantize Position{};
};
6 changes: 6 additions & 0 deletions Code/encoding/Messages/RequestOwnershipTransfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@
void RequestOwnershipTransfer::SerializeRaw(TiltedPhoques::Buffer::Writer& aWriter) const noexcept
{
Serialization::WriteVarInt(aWriter, ServerId);
WorldSpaceId.Serialize(aWriter);
CellId.Serialize(aWriter);
Position.Serialize(aWriter);
}

void RequestOwnershipTransfer::DeserializeRaw(TiltedPhoques::Buffer::Reader& aReader) noexcept
{
ClientMessage::DeserializeRaw(aReader);

ServerId = Serialization::ReadVarInt(aReader) & 0xFFFFFFFF;
WorldSpaceId.Deserialize(aReader);
CellId.Deserialize(aReader);
Position.Deserialize(aReader);
}
14 changes: 12 additions & 2 deletions Code/encoding/Messages/RequestOwnershipTransfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

#include "Message.h"

#include <Structs/GameId.h>
#include <Structs/Vector3_NetQuantize.h>

struct RequestOwnershipTransfer final : ClientMessage
{
static constexpr ClientOpcode Opcode = kRequestOwnershipTransfer;
Expand All @@ -17,8 +20,15 @@ struct RequestOwnershipTransfer final : ClientMessage

bool operator==(const RequestOwnershipTransfer& achRhs) const noexcept
{
return ServerId == achRhs.ServerId && GetOpcode() == achRhs.GetOpcode();
return GetOpcode() == achRhs.GetOpcode() &&
ServerId == achRhs.ServerId &&
WorldSpaceId == achRhs.WorldSpaceId &&
CellId == achRhs.CellId &&
Position == achRhs.Position;
}

uint32_t ServerId;
uint32_t ServerId{};
GameId WorldSpaceId{};
GameId CellId{};
Vector3_NetQuantize Position{};
};
4 changes: 3 additions & 1 deletion Code/encoding/Messages/ServerMessageFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include <Messages/NotifyDialogue.h>
#include <Messages/NotifySubtitle.h>
#include <Messages/NotifyPlayerDialogue.h>
#include <Messages/NotifyActorTeleport.h>

using TiltedPhoques::UniquePtr;

Expand All @@ -65,7 +66,8 @@ struct ServerMessageFactory
NotifyObjectInventoryChanges, NotifySpellCast, NotifyProjectileLaunch, NotifyInterruptCast,
NotifyAddTarget, NotifyScriptAnimation, NotifyDrawWeapon, NotifyMount, NotifyNewPackage,
NotifyRespawn, NotifySyncExperience, NotifyEquipmentChanges, NotifyChatMessageBroadcast,
TeleportCommandResponse, NotifyPlayerRespawn, NotifyDialogue, NotifySubtitle, NotifyPlayerDialogue>;
TeleportCommandResponse, NotifyPlayerRespawn, NotifyDialogue, NotifySubtitle, NotifyPlayerDialogue,
NotifyActorTeleport>;

return s_visitor(std::forward<T>(func));
}
Expand Down
1 change: 1 addition & 0 deletions Code/encoding/Opcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,5 +93,6 @@ enum ServerOpcode : unsigned char
kNotifyDialogue,
kNotifySubtitle,
kNotifyPlayerDialogue,
kNotifyActorTeleport,
kServerOpcodeMax
};
26 changes: 23 additions & 3 deletions Code/server/Services/CharacterService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include <Messages/NotifyDialogue.h>
#include <Messages/SubtitleRequest.h>
#include <Messages/NotifySubtitle.h>
#include <Messages/NotifyActorTeleport.h>

CharacterService::CharacterService(World& aWorld, entt::dispatcher& aDispatcher) noexcept
: m_world(aWorld)
Expand Down Expand Up @@ -229,7 +230,7 @@ void CharacterService::OnOwnershipTransferRequest(const PacketEvent<RequestOwner
{
auto& message = acMessage.Packet;

OwnerView<CharacterComponent, CellIdComponent> view(m_world, acMessage.GetSender());
OwnerView<FormIdComponent, CharacterComponent, CellIdComponent, MovementComponent> view(m_world, acMessage.GetSender());

const auto it = view.find(static_cast<entt::entity>(message.ServerId));
if (it == view.end())
Expand All @@ -238,6 +239,26 @@ void CharacterService::OnOwnershipTransferRequest(const PacketEvent<RequestOwner
return;
}

if (message.WorldSpaceId || message.CellId)
{
auto& formIdComponent = view.get<FormIdComponent>(*it);

NotifyActorTeleport notify{};
notify.FormId = formIdComponent.Id;
notify.WorldSpaceId = message.WorldSpaceId;
notify.CellId = message.CellId;
notify.Position = message.Position;

auto& cellIdComponent = view.get<CellIdComponent>(*it);
cellIdComponent.WorldSpaceId = message.WorldSpaceId;
cellIdComponent.Cell = message.CellId;
cellIdComponent.CenterCoords = GridCellCoords::CalculateGridCellCoords(message.Position);

auto& movementComponent = view.get<MovementComponent>(*it);
movementComponent.Position = message.Position;
movementComponent.Sent = true;
}

auto& characterOwnerComponent = view.get<OwnerComponent>(*it);
characterOwnerComponent.InvalidOwners.push_back(acMessage.pPlayer);

Expand Down Expand Up @@ -613,8 +634,7 @@ void CharacterService::CreateCharacter(const PacketEvent<AssignCharacterRequest>
if (message.WorldSpaceId != GameId{})
{
cellIdComponent.WorldSpaceId = message.WorldSpaceId;
auto coords = GridCellCoords::CalculateGridCellCoords(message.Position.x, message.Position.y);
cellIdComponent.CenterCoords = coords;
cellIdComponent.CenterCoords = GridCellCoords::CalculateGridCellCoords(message.Position);
}

auto& characterComponent = m_world.emplace<CharacterComponent>(cEntity);
Expand Down

0 comments on commit 77c0098

Please sign in to comment.