Many fixes for external gem multiplayer components and component network inputs, fixes an uninitialized variable resulting in continual desyncs, restructures our public includes to match the directory structure of source, allows autogen artefacts to be included by external gems, allowing for external multiplayer components to interact with multiplayer gem components with no extra code
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Source/Components/LocalPredictionPlayerInputComponent.h>
|
||||
#include <Multiplayer/Components/LocalPredictionPlayerInputComponent.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzNetworking/Serialization/HashSerializer.h>
|
||||
@@ -81,12 +81,7 @@ namespace Multiplayer
|
||||
, m_migrateStartHandler([this](ClientInputId migratedInputId) { OnMigrateStart(migratedInputId); })
|
||||
, m_migrateEndHandler([this]() { OnMigrateEnd(); })
|
||||
{
|
||||
if (GetNetEntityRole() == NetEntityRole::Autonomous)
|
||||
{
|
||||
m_autonomousUpdateEvent.Enqueue(AZ::TimeMs{ 1 }, true);
|
||||
parent.GetNetBindComponent()->AddEntityMigrationStartEventHandler(m_migrateStartHandler);
|
||||
parent.GetNetBindComponent()->AddEntityMigrationEndEventHandler(m_migrateEndHandler);
|
||||
}
|
||||
;
|
||||
}
|
||||
|
||||
void LocalPredictionPlayerInputComponentController::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
|
||||
@@ -96,6 +91,13 @@ namespace Multiplayer
|
||||
m_allowMigrateClientInput = true;
|
||||
m_serverMigrateFrameId = GetNetworkTime()->GetHostFrameId();
|
||||
}
|
||||
|
||||
if (IsAutonomous())
|
||||
{
|
||||
m_autonomousUpdateEvent.Enqueue(AZ::TimeMs{ 1 }, true);
|
||||
GetParent().GetNetBindComponent()->AddEntityMigrationStartEventHandler(m_migrateStartHandler);
|
||||
GetParent().GetNetBindComponent()->AddEntityMigrationEndEventHandler(m_migrateEndHandler);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPredictionPlayerInputComponentController::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.h>
|
||||
#include <Multiplayer/NetBindComponent.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
using CorrectionEvent = AZ::Event<>;
|
||||
|
||||
class LocalPredictionPlayerInputComponent
|
||||
: public LocalPredictionPlayerInputComponentBase
|
||||
{
|
||||
public:
|
||||
AZ_MULTIPLAYER_COMPONENT(Multiplayer::LocalPredictionPlayerInputComponent, s_localPredictionPlayerInputComponentConcreteUuid, Multiplayer::LocalPredictionPlayerInputComponentBase);
|
||||
|
||||
static void Reflect([[maybe_unused]] AZ::ReflectContext* context);
|
||||
|
||||
void OnInit() override;
|
||||
void OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
void OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
};
|
||||
|
||||
class LocalPredictionPlayerInputComponentController
|
||||
: public LocalPredictionPlayerInputComponentControllerBase
|
||||
{
|
||||
public:
|
||||
LocalPredictionPlayerInputComponentController(LocalPredictionPlayerInputComponent& parent);
|
||||
|
||||
void OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
void OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
|
||||
void HandleSendClientInput
|
||||
(
|
||||
AzNetworking::IConnection* invokingConnection,
|
||||
const Multiplayer::NetworkInputArray& inputArray,
|
||||
const AZ::HashValue32& stateHash,
|
||||
const AzNetworking::PacketEncodingBuffer& clientState
|
||||
) override;
|
||||
|
||||
void HandleSendMigrateClientInput
|
||||
(
|
||||
AzNetworking::IConnection* invokingConnection,
|
||||
const Multiplayer::NetworkInputMigrationVector& inputArray
|
||||
) override;
|
||||
|
||||
void HandleSendClientInputCorrection
|
||||
(
|
||||
AzNetworking::IConnection* invokingConnection,
|
||||
const Multiplayer::ClientInputId& inputId,
|
||||
const AzNetworking::PacketEncodingBuffer& correction
|
||||
) override;
|
||||
|
||||
//! Return true if we're currently replaying inputs after a correction.
|
||||
//! If this value returns true, effects, audio, and other cosmetic triggers should be suppressed
|
||||
//! @return true if we're within correction scope and replaying inputs
|
||||
bool IsReplayingInput() const;
|
||||
|
||||
//! Return true if we're currently migrating from one host to another.
|
||||
//! @return boolean true if we're currently migrating from one host to another
|
||||
bool IsMigrating() const;
|
||||
|
||||
ClientInputId GetLastInputId() const;
|
||||
HostFrameId GetInputFrameId(const NetworkInput& input) const;
|
||||
|
||||
void CorrectionEventAddHandle(CorrectionEvent::Handler& handler);
|
||||
|
||||
private:
|
||||
|
||||
void OnMigrateStart(ClientInputId migratedInputId);
|
||||
void OnMigrateEnd();
|
||||
void UpdateAutonomous(AZ::TimeMs deltaTimeMs);
|
||||
void UpdateBankedTime(AZ::TimeMs deltaTimeMs);
|
||||
|
||||
// Implicitly sorted player input history, back() is the input that corresponds to the latest client input Id
|
||||
NetworkInputHistory m_inputHistory;
|
||||
|
||||
// Anti-cheat accumulator for clients who purposely mess with their clock rate
|
||||
NetworkInputArray m_lastInputReceived;
|
||||
|
||||
AZ::ScheduledEvent m_autonomousUpdateEvent; // Drives autonomous input collection
|
||||
AZ::ScheduledEvent m_updateBankedTimeEvent; // Drives authority bank time updates
|
||||
|
||||
CorrectionEvent m_correctionEvent;
|
||||
EntityMigrationStartEvent::Handler m_migrateStartHandler;
|
||||
EntityMigrationEndEvent::Handler m_migrateEndHandler;
|
||||
|
||||
double m_moveAccumulator = 0.0;
|
||||
double m_clientBankedTime = 0.0;
|
||||
|
||||
AZ::TimeMs m_lastInputReceivedTimeMs = AZ::TimeMs{ 0 };
|
||||
AZ::TimeMs m_lastCorrectionSentTimeMs = AZ::TimeMs{ 0 };
|
||||
|
||||
ClientInputId m_clientInputId = ClientInputId{ 0 };
|
||||
ClientInputId m_lastCorrectionInputId = ClientInputId{ 0 };
|
||||
ClientInputId m_lastMigratedInputId = ClientInputId{ 0 }; // Used to resend inputs that were queued during a migration event
|
||||
HostFrameId m_serverMigrateFrameId = InvalidHostFrameId;
|
||||
|
||||
bool m_replayingInput = false; // True if we're replaying inputs under a correction event (use this to suppress effects or audio)
|
||||
bool m_allowMigrateClientInput = false; // True if this component was migrated, we will allow the client to send us migrated inputs (one time only)
|
||||
};
|
||||
}
|
||||
@@ -10,8 +10,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Multiplayer/MultiplayerComponent.h>
|
||||
#include <Multiplayer/NetBindComponent.h>
|
||||
#include <Multiplayer/Components/MultiplayerComponent.h>
|
||||
#include <Multiplayer/Components/NetBindComponent.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
namespace Multiplayer
|
||||
@@ -46,9 +46,24 @@ namespace Multiplayer
|
||||
return m_netBindComponent ? m_netBindComponent->GetNetEntityId() : InvalidNetEntityId;
|
||||
}
|
||||
|
||||
NetEntityRole MultiplayerComponent::GetNetEntityRole() const
|
||||
bool MultiplayerComponent::IsAuthority() const
|
||||
{
|
||||
return m_netBindComponent ? m_netBindComponent->GetNetEntityRole() : NetEntityRole::InvalidRole;
|
||||
return m_netBindComponent ? m_netBindComponent->IsAuthority() : false;
|
||||
}
|
||||
|
||||
bool MultiplayerComponent::IsAutonomous() const
|
||||
{
|
||||
return m_netBindComponent ? m_netBindComponent->IsAutonomous() : false;
|
||||
}
|
||||
|
||||
bool MultiplayerComponent::IsServer() const
|
||||
{
|
||||
return m_netBindComponent ? m_netBindComponent->IsServer() : false;
|
||||
}
|
||||
|
||||
bool MultiplayerComponent::IsClient() const
|
||||
{
|
||||
return m_netBindComponent ? m_netBindComponent->IsClient() : false;
|
||||
}
|
||||
|
||||
ConstNetworkEntityHandle MultiplayerComponent::GetEntityHandle() const
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Multiplayer/MultiplayerComponentRegistry.h>
|
||||
#include <Multiplayer/Components/MultiplayerComponentRegistry.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
@@ -21,6 +21,12 @@ namespace Multiplayer
|
||||
return netComponentId;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<IMultiplayerComponentInput> MultiplayerComponentRegistry::AllocateComponentInput(NetComponentId netComponentId)
|
||||
{
|
||||
const ComponentData& componentData = GetMultiplayerComponentData(netComponentId);
|
||||
return AZStd::move(componentData.m_allocComponentInputFunction());
|
||||
}
|
||||
|
||||
const char* MultiplayerComponentRegistry::GetComponentGemName(NetComponentId netComponentId) const
|
||||
{
|
||||
const ComponentData& componentData = GetMultiplayerComponentData(netComponentId);
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Multiplayer/MultiplayerController.h>
|
||||
#include <Multiplayer/MultiplayerComponent.h>
|
||||
#include <Multiplayer/NetBindComponent.h>
|
||||
#include <Multiplayer/Components/MultiplayerController.h>
|
||||
#include <Multiplayer/Components/MultiplayerComponent.h>
|
||||
#include <Multiplayer/Components/NetBindComponent.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
@@ -27,9 +27,14 @@ namespace Multiplayer
|
||||
return m_owner.GetNetEntityId();
|
||||
}
|
||||
|
||||
NetEntityRole MultiplayerController::GetNetEntityRole() const
|
||||
bool MultiplayerController::IsAuthority() const
|
||||
{
|
||||
return GetNetBindComponent()->GetNetEntityRole();
|
||||
return GetNetBindComponent() ? GetNetBindComponent()->IsAuthority() : false;
|
||||
}
|
||||
|
||||
bool MultiplayerController::IsAutonomous() const
|
||||
{
|
||||
return GetNetBindComponent() ? GetNetBindComponent()->IsAutonomous() : false;
|
||||
}
|
||||
|
||||
AZ::Entity* MultiplayerController::GetEntity() const
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Multiplayer/NetBindComponent.h>
|
||||
#include <Multiplayer/NetworkEntityRpcMessage.h>
|
||||
#include <Multiplayer/NetworkEntityUpdateMessage.h>
|
||||
#include <Multiplayer/NetworkInput.h>
|
||||
#include <Multiplayer/INetworkEntityManager.h>
|
||||
#include <Multiplayer/MultiplayerComponent.h>
|
||||
#include <Multiplayer/MultiplayerController.h>
|
||||
#include <Multiplayer/Components/NetBindComponent.h>
|
||||
#include <Multiplayer/Components/MultiplayerComponent.h>
|
||||
#include <Multiplayer/Components/MultiplayerController.h>
|
||||
#include <Multiplayer/NetworkEntity/INetworkEntityManager.h>
|
||||
#include <Multiplayer/NetworkEntity/NetworkEntityRpcMessage.h>
|
||||
#include <Multiplayer/NetworkEntity/NetworkEntityUpdateMessage.h>
|
||||
#include <Multiplayer/NetworkInput/NetworkInput.h>
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/Console/ILogger.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
@@ -110,6 +110,22 @@ namespace Multiplayer
|
||||
return (m_netEntityRole == NetEntityRole::Authority);
|
||||
}
|
||||
|
||||
bool NetBindComponent::IsAutonomous() const
|
||||
{
|
||||
return (m_netEntityRole == NetEntityRole::Autonomous)
|
||||
|| (m_netEntityRole == NetEntityRole::Authority) && m_allowAutonomy;
|
||||
}
|
||||
|
||||
bool NetBindComponent::IsServer() const
|
||||
{
|
||||
return (m_netEntityRole == NetEntityRole::Server);
|
||||
}
|
||||
|
||||
bool NetBindComponent::IsClient() const
|
||||
{
|
||||
return (m_netEntityRole == NetEntityRole::Client);
|
||||
}
|
||||
|
||||
bool NetBindComponent::HasController() const
|
||||
{
|
||||
return (m_netEntityRole == NetEntityRole::Authority)
|
||||
@@ -136,14 +152,21 @@ namespace Multiplayer
|
||||
return m_netEntityHandle;
|
||||
}
|
||||
|
||||
void NetBindComponent::SetAllowAutonomy(bool value)
|
||||
{
|
||||
// This flag allows a player host to autonomously control their player entity, even though the entity is in an authority role
|
||||
m_allowAutonomy = value;
|
||||
}
|
||||
|
||||
MultiplayerComponentInputVector NetBindComponent::AllocateComponentInputs()
|
||||
{
|
||||
MultiplayerComponentInputVector componentInputs;
|
||||
const size_t multiplayerComponentSize = m_multiplayerInputComponentVector.size();
|
||||
for (size_t i = 0; i < multiplayerComponentSize; ++i)
|
||||
{
|
||||
// TODO: ComponentInput factory, needs multiplayer component architecture and autogen
|
||||
AZStd::unique_ptr<IMultiplayerComponentInput> componentInput = nullptr; // ComponentInputFactory(multiplayerComponent->GetComponentId());
|
||||
const NetComponentId netComponentId = m_multiplayerInputComponentVector[i]->GetNetComponentId();
|
||||
AZStd::unique_ptr<IMultiplayerComponentInput> componentInput = AZStd::move(GetMultiplayerComponentRegistry()->AllocateComponentInput(netComponentId));
|
||||
|
||||
if (componentInput != nullptr)
|
||||
{
|
||||
componentInputs.emplace_back(AZStd::move(componentInput));
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Source/Components/NetworkTransformComponent.h>
|
||||
#include <Multiplayer/Components/NetworkTransformComponent.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/EBus/IEventScheduler.h>
|
||||
@@ -96,7 +96,7 @@ namespace Multiplayer
|
||||
|
||||
void NetworkTransformComponentController::OnTransformChangedEvent(const AZ::Transform& worldTm)
|
||||
{
|
||||
if (GetNetEntityRole() == NetEntityRole::Authority)
|
||||
if (IsAuthority())
|
||||
{
|
||||
SetRotation(worldTm.GetRotation());
|
||||
SetTranslation(worldTm.GetTranslation());
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Source/AutoGen/NetworkTransformComponent.AutoComponent.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
class NetworkTransformComponent
|
||||
: public NetworkTransformComponentBase
|
||||
{
|
||||
public:
|
||||
AZ_MULTIPLAYER_COMPONENT(Multiplayer::NetworkTransformComponent, s_networkTransformComponentConcreteUuid, Multiplayer::NetworkTransformComponentBase);
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
NetworkTransformComponent();
|
||||
|
||||
void OnInit() override;
|
||||
void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
|
||||
private:
|
||||
void OnRotationChangedEvent(const AZ::Quaternion& rotation);
|
||||
void OnTranslationChangedEvent(const AZ::Vector3& translation);
|
||||
void OnScaleChangedEvent(const AZ::Vector3& scale);
|
||||
|
||||
AZ::Event<AZ::Quaternion>::Handler m_rotationEventHandler;
|
||||
AZ::Event<AZ::Vector3>::Handler m_translationEventHandler;
|
||||
AZ::Event<AZ::Vector3>::Handler m_scaleEventHandler;
|
||||
};
|
||||
|
||||
class NetworkTransformComponentController
|
||||
: public NetworkTransformComponentControllerBase
|
||||
{
|
||||
public:
|
||||
NetworkTransformComponentController(NetworkTransformComponent& parent);
|
||||
|
||||
void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
|
||||
private:
|
||||
void OnTransformChangedEvent(const AZ::Transform& worldTm);
|
||||
|
||||
AZ::TransformChangedEvent::Handler m_transformChangedHandler;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user