Merge remote-tracking branch 'origin' into MultiplayerComponents
This commit is contained in:
@@ -383,6 +383,8 @@ namespace {{ Component.attrib['Namespace'] }}
|
||||
{{ DeclareNetworkPropertyAccessors(Component, 'Authority', 'Client', true)|indent(8) -}}
|
||||
{{ DeclareNetworkPropertyAccessors(Component, 'Authority', 'Autonomous', false)|indent(8) -}}
|
||||
{{ DeclareNetworkPropertyAccessors(Component, 'Authority', 'Autonomous', true)|indent(8) -}}
|
||||
{{ DeclareNetworkPropertyAccessors(Component, 'Autonomous', 'Authority', false)|indent(8) -}}
|
||||
{{ DeclareNetworkPropertyAccessors(Component, 'Autonomous', 'Authority', true)|indent(8) -}}
|
||||
{{ DeclareArchetypePropertyGetters(Component)|indent(8) -}}
|
||||
{{ DeclareRpcInvocations(Component, 'Server', 'Authority', false)|indent(8) -}}
|
||||
{{ DeclareRpcInvocations(Component, 'Server', 'Authority', true)|indent(8) -}}
|
||||
@@ -456,7 +458,6 @@ namespace {{ Component.attrib['Namespace'] }}
|
||||
{% endif %}
|
||||
|
||||
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Server', false)|indent(8) -}}
|
||||
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Autonomous', false)|indent(8) -}}
|
||||
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Client', false)|indent(8) -}}
|
||||
{{ DeclareArchetypePropertyGetters(Component)|indent(8) -}}
|
||||
{{ DeclareRpcInvocations(Component, 'Server', 'Authority', false)|indent(8) -}}
|
||||
@@ -481,8 +482,6 @@ namespace {{ Component.attrib['Namespace'] }}
|
||||
//! @}
|
||||
|
||||
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Server', true)|indent(8) -}}
|
||||
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Autonomous', true)|indent(8) -}}
|
||||
{{ DeclareNetworkPropertyGetters(Component, 'Autonomous', 'Authority', true)|indent(8) -}}
|
||||
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Client', true)|indent(8) -}}
|
||||
{{ DeclareRpcInvocations(Component, 'Server', 'Authority', true)|indent(8) -}}
|
||||
{{ AutoComponentMacros.DeclareRpcHandlers(Component, 'Authority', 'Client', false)|indent(8) -}}
|
||||
|
||||
@@ -118,22 +118,25 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(int32_t index
|
||||
|
||||
bool {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}PushBack(const {{ Property.attrib['Type'] }} &value)
|
||||
{
|
||||
if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.push_back(value))
|
||||
int32_t indexToSet = GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.size();
|
||||
if (indexToSet < {{ Property.attrib['Count'] }})
|
||||
{
|
||||
int32_t indexToSet = GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.size();
|
||||
GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.push_back(value);
|
||||
int32_t bitIndex = indexToSet + static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Start') }});
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(bitIndex, true);
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Size') }}), true);
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(aznumeric_cast<uint32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Size') }}), true);
|
||||
GetParent().MarkDirty();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}PopBack(const Multiplayer::NetworkInput&)
|
||||
{
|
||||
if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.pop_back())
|
||||
if (!GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.empty())
|
||||
{
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Size') }}), true);
|
||||
GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.pop_back();
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(aznumeric_cast<uint32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Size') }}), true);
|
||||
GetParent().MarkDirty();
|
||||
return true;
|
||||
}
|
||||
@@ -216,10 +219,11 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(int32_t index
|
||||
|
||||
bool {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}PushBack(const {{ Property.attrib['Type'] }} &value)
|
||||
{
|
||||
if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.push_back(value))
|
||||
int32_t indexToSet = GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.size();
|
||||
if (indexToSet < {{ Property.attrib['Count'] }})
|
||||
{
|
||||
uint32_t indexToSet = aznumeric_cast<uint32_t>(GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.size());
|
||||
uint32_t bitIndex = indexToSet + aznumeric_cast<uint32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Start') }});
|
||||
GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.push_back(value);
|
||||
int32_t bitIndex = indexToSet + static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Start') }});
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(bitIndex, true);
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(aznumeric_cast<uint32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Size') }}), true);
|
||||
GetParent().MarkDirty();
|
||||
@@ -230,9 +234,10 @@ bool {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}PushBack(const {{
|
||||
|
||||
bool {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}PopBack()
|
||||
{
|
||||
if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.pop_back())
|
||||
if (!GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.empty())
|
||||
{
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Size') }}), true);
|
||||
GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.pop_back();
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(aznumeric_cast<uint32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Size') }}), true);
|
||||
GetParent().MarkDirty();
|
||||
return true;
|
||||
}
|
||||
@@ -241,7 +246,7 @@ bool {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}PopBack()
|
||||
|
||||
void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}Clear()
|
||||
{
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Size') }}), true);
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(aznumeric_cast<uint32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Size') }}), true);
|
||||
GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.clear();
|
||||
GetParent().MarkDirty();
|
||||
}
|
||||
@@ -586,8 +591,16 @@ bool {{ ClassName }}::Serialize{{ AutoComponentMacros.GetNetPropertiesSetName(Re
|
||||
const uint32_t lastBit = static_cast<uint32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'End') }});
|
||||
{% endif %}
|
||||
|
||||
{% if Property.attrib['IsRewindable']|booleanTrue %}
|
||||
AzNetworking::FixedSizeBitsetView deltaRecord(replicationRecord.m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}, firstBit, lastBit - firstBit + 1);
|
||||
m_{{ LowerFirst(Property.attrib['Name']) }}.Serialize(serializer, deltaRecord);
|
||||
{% else %}
|
||||
{% if Property.attrib['Container'] == 'Vector' %}
|
||||
serializer.Serialize<AZStd::fixed_vector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>>(m_{{ LowerFirst(Property.attrib['Name']) }}, "{{ LowerFirst(Property.attrib['Name']) }}");
|
||||
{% elif Property.attrib['Container'] == 'Array' %}
|
||||
serializer.Serialize<AZStd::array<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>>(m_{{ LowerFirst(Property.attrib['Name']) }}, "{{ LowerFirst(Property.attrib['Name']) }}");
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
}
|
||||
{% else %}
|
||||
Multiplayer::SerializeNetworkPropertyHelper
|
||||
@@ -618,11 +631,11 @@ void {{ ClassName }}::NotifyChanges{{ AutoComponentMacros.GetNetPropertiesSetNam
|
||||
{% if (Property.attrib['GenerateEventBindings']|booleanTrue) %}
|
||||
{% if Property.attrib['Container'] != 'None' and Property.attrib['Container'] != 'Object' %}
|
||||
// NotifyChangesAuthorityToClientProperties for Arrays and Vectors
|
||||
for (uint32_t bitIndex = static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Start') }}), elementIndex = 0; bitIndex <= static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component, ReplicateFrom, ReplicateTo, Property, 'End') }}); ++bitIndex, ++elementIndex)
|
||||
for (uint32_t bitIndex = static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Start') }}), elementIndex = 0; bitIndex <= static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'End') }}); ++bitIndex, ++elementIndex)
|
||||
{
|
||||
if (replicationRecord.m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.GetBit(bitIndex){% if Property.attrib['Container'] == 'Vector' %} && elementIndex < m_{{ Property.attrib['Name'] }}.GetSize(){% endif %})
|
||||
if (replicationRecord.m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.GetBit(bitIndex){% if Property.attrib['Container'] == 'Vector' %} && elementIndex < m_{{ LowerFirst(Property.attrib['Name']) }}.size(){% endif %})
|
||||
{
|
||||
m_LowerFirst( Property.attrib['Name']) }}Event.Signal(elementIndex, m_{{ LowerFirst(Property.attrib['Name']) }}[elementIndex]);
|
||||
m_{{ LowerFirst(Property.attrib['Name']) }}Event.Signal(elementIndex, m_{{ LowerFirst(Property.attrib['Name']) }}[elementIndex]);
|
||||
}
|
||||
}
|
||||
{% if Property.attrib['Container'] == 'Vector' %}
|
||||
@@ -783,12 +796,27 @@ enum class NetworkProperties
|
||||
AZ_Warning("Network Property", false, "{{ ClassName }} Get{{ UpperFirst(Property.attrib['Name']) }} failed. Entity '%s' (id: %s) is missing {{ ClassName }}, be sure to add {{ ClassName }} to this entity.", entity->GetName().c_str(), id.ToString().c_str())
|
||||
return {{ Property.attrib['Type'] }}();
|
||||
}
|
||||
{% if (ReplicateTo == 'Autonomous') or (ReplicateFrom == 'Autonomous' and ReplicateTo == 'Authority') %}
|
||||
|
||||
// {{ UpperFirst(Property.attrib['Name']) }} is only sent and received between contoller objects (ie Authority, Autonomous); we must go through the controller in order to get this property
|
||||
{{ ClassName }}Controller* controller = static_cast<{{ ClassName }}Controller*>(networkComponent->GetController());
|
||||
if (!controller)
|
||||
{
|
||||
AZ_Warning("Network Property", false, "{{ ClassName }} Get{{ UpperFirst(Property.attrib['Name']) }} method failed. Entity '%s' (id: %s) {{ ClassName }} is missing the network controller. This property is replicated to autonomous network entities, because this entity doesn't have a controller, it must not be automonous. Please check your network context before attempting to get {{ UpperFirst(Property.attrib['Name']) }}.", entity->GetName().c_str(), id.ToString().c_str())
|
||||
return {{ Property.attrib['Type'] }}();
|
||||
}
|
||||
{% if Property.attrib['Container'] == 'Vector' or Property.attrib['Container'] == 'Array' %}
|
||||
return controller->Get{{ UpperFirst(Property.attrib['Name']) }}(index);
|
||||
{% else %}
|
||||
return controller->Get{{ UpperFirst(Property.attrib['Name']) }}();
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if Property.attrib['Container'] == 'Vector' or Property.attrib['Container'] == 'Array' %}
|
||||
return networkComponent->Get{{ UpperFirst(Property.attrib['Name']) }}(index);
|
||||
{% else %}
|
||||
return networkComponent->Get{{ UpperFirst(Property.attrib['Name']) }}();
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
})
|
||||
{% if Property.attrib['Container'] == 'Vector' or Property.attrib['Container'] == 'Array' %}
|
||||
->Method("Set{{ UpperFirst(Property.attrib['Name']) }}", [](AZ::EntityId id, int32_t index, const {{ Property.attrib['Type'] }}& value) -> void
|
||||
@@ -1467,12 +1495,8 @@ namespace {{ Component.attrib['Namespace'] }}
|
||||
}
|
||||
|
||||
{{ DefineNetworkPropertyGets(Component, 'Authority', 'Server', false, ComponentBaseName)|indent(4) -}}
|
||||
{{ DefineNetworkPropertyGets(Component, 'Authority', 'Autonomous', false, ComponentBaseName)|indent(4) -}}
|
||||
{{ DefineNetworkPropertyGets(Component, 'Autonomous', 'Authority', false, ComponentBaseName)|indent(4) -}}
|
||||
{{ DefineNetworkPropertyGets(Component, 'Authority', 'Client', false, ComponentBaseName)|indent(4) -}}
|
||||
{{ DefineNetworkPropertyGets(Component, 'Authority', 'Server', true, ComponentBaseName)|indent(4) -}}
|
||||
{{ DefineNetworkPropertyGets(Component, 'Authority', 'Autonomous', true, ComponentBaseName)|indent(4) -}}
|
||||
{{ DefineNetworkPropertyGets(Component, 'Autonomous', 'Authority', true, ComponentBaseName)|indent(4) -}}
|
||||
{{ DefineNetworkPropertyGets(Component, 'Authority', 'Client', true, ComponentBaseName)|indent(4) }}
|
||||
{{ DefineArchetypePropertyGets(Component, ClassType, ComponentBaseName)|indent(4) -}}
|
||||
{{ DefineRpcInvocations(Component, ComponentBaseName, 'Server', 'Authority', false)|indent(4) -}}
|
||||
|
||||
@@ -469,19 +469,16 @@ namespace Multiplayer
|
||||
m_connAcquiredEvent.Signal(datum);
|
||||
}
|
||||
|
||||
// Hosts will spawn a new default player prefab for the user that just connected
|
||||
if (GetAgentType() == MultiplayerAgentType::ClientServer
|
||||
|| GetAgentType() == MultiplayerAgentType::DedicatedServer)
|
||||
{
|
||||
PrefabEntityId playerPrefabEntityId(AZ::Name(static_cast<AZ::CVarFixedString>(sv_defaultPlayerSpawnAsset).c_str()), 1);
|
||||
INetworkEntityManager::EntityList entityList = m_networkEntityManager.CreateEntitiesImmediate(playerPrefabEntityId, NetEntityRole::Authority, AZ::Transform::CreateIdentity());
|
||||
|
||||
NetworkEntityHandle controlledEntity;
|
||||
if (entityList.size() > 0)
|
||||
NetworkEntityHandle controlledEntity = SpawnDefaultPlayerPrefab();
|
||||
if (controlledEntity.Exists())
|
||||
{
|
||||
controlledEntity = entityList[0];
|
||||
controlledEntity.GetNetBindComponent()->SetOwningConnectionId(connection->GetConnectionId());
|
||||
}
|
||||
|
||||
|
||||
if (connection->GetUserData() == nullptr) // Only add user data if the connect event handler has not already done so
|
||||
{
|
||||
connection->SetUserData(new ServerToClientConnectionData(connection, *this, controlledEntity));
|
||||
@@ -553,6 +550,17 @@ namespace Multiplayer
|
||||
}
|
||||
}
|
||||
m_agentType = multiplayerType;
|
||||
|
||||
// Spawn the default player for this host since the host is also a player (not a dedicated server)
|
||||
if (m_agentType == MultiplayerAgentType::ClientServer)
|
||||
{
|
||||
NetworkEntityHandle controlledEntity = SpawnDefaultPlayerPrefab();
|
||||
if (NetBindComponent* controlledEntityNetBindComponent = controlledEntity.GetNetBindComponent())
|
||||
{
|
||||
controlledEntityNetBindComponent->SetAllowAutonomy(true);
|
||||
}
|
||||
}
|
||||
|
||||
AZLOG_INFO("Multiplayer operating in %s mode", GetEnumString(m_agentType));
|
||||
}
|
||||
|
||||
@@ -728,6 +736,19 @@ namespace Multiplayer
|
||||
}
|
||||
}
|
||||
|
||||
NetworkEntityHandle MultiplayerSystemComponent::SpawnDefaultPlayerPrefab()
|
||||
{
|
||||
PrefabEntityId playerPrefabEntityId(AZ::Name(static_cast<AZ::CVarFixedString>(sv_defaultPlayerSpawnAsset).c_str()), 1);
|
||||
INetworkEntityManager::EntityList entityList = m_networkEntityManager.CreateEntitiesImmediate(playerPrefabEntityId, NetEntityRole::Authority, AZ::Transform::CreateIdentity());
|
||||
|
||||
NetworkEntityHandle controlledEntity;
|
||||
if (entityList.size() > 0)
|
||||
{
|
||||
controlledEntity = entityList[0];
|
||||
}
|
||||
return controlledEntity;
|
||||
}
|
||||
|
||||
void host([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
|
||||
{
|
||||
Multiplayer::MultiplayerAgentType serverType = sv_isDedicated ? MultiplayerAgentType::DedicatedServer : MultiplayerAgentType::ClientServer;
|
||||
|
||||
@@ -105,7 +105,8 @@ namespace Multiplayer
|
||||
void TickVisibleNetworkEntities(float deltaTime, float serverRateSeconds);
|
||||
void OnConsoleCommandInvoked(AZStd::string_view command, const AZ::ConsoleCommandContainer& args, AZ::ConsoleFunctorFlags flags, AZ::ConsoleInvokedFrom invokedFrom);
|
||||
void ExecuteConsoleCommandList(AzNetworking::IConnection* connection, const AZStd::fixed_vector<Multiplayer::LongNetworkString, 32>& commands);
|
||||
|
||||
NetworkEntityHandle SpawnDefaultPlayerPrefab();
|
||||
|
||||
AZ_CONSOLEFUNC(MultiplayerSystemComponent, DumpStats, AZ::ConsoleFunctorFlags::Null, "Dumps stats for the current multiplayer session");
|
||||
|
||||
AzNetworking::INetworkInterface* m_networkInterface = nullptr;
|
||||
|
||||
@@ -402,8 +402,12 @@ namespace Multiplayer
|
||||
const AZ::Transform& transform
|
||||
)
|
||||
{
|
||||
INetworkEntityManager::EntityList returnList;
|
||||
|
||||
EntityList returnList;
|
||||
if (!AZ::Data::AssetManager::IsReady())
|
||||
{
|
||||
return returnList;
|
||||
}
|
||||
|
||||
auto spawnableAssetId = m_networkPrefabLibrary.GetAssetIdByName(prefabEntryId.m_prefabName);
|
||||
// Required for sync-instantiation. Todo: keep the reference in NetworkSpawnableLibrary
|
||||
auto netSpawnableAsset = AZ::Data::AssetManager::Instance().GetAsset<AzFramework::Spawnable>(spawnableAssetId, AZ::Data::AssetLoadBehavior::PreLoad);
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Include/Multiplayer/Physics/PhysicsUtils.h>
|
||||
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzFramework/Physics/PhysicsScene.h>
|
||||
#include <AzFramework/Physics/Shape.h>
|
||||
#include <Multiplayer/NetworkTime/INetworkTime.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
template<typename RequestT>
|
||||
AzPhysics::SceneQueryHits SceneQueryInternal(const RequestT& request)
|
||||
{
|
||||
auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
|
||||
if (!sceneInterface)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
AzPhysics::SceneHandle sceneHandle = sceneInterface->GetSceneHandle(AzPhysics::DefaultPhysicsSceneName);
|
||||
if (sceneHandle == AzPhysics::InvalidSceneHandle)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
Multiplayer::INetworkTime* currentNetTime = Multiplayer::GetNetworkTime();
|
||||
|
||||
if(!currentNetTime->IsTimeRewound())
|
||||
{
|
||||
// If the time is not rewound, we simply execute the scene query as is.
|
||||
AzPhysics::SceneQueryHits result = sceneInterface->QueryScene(sceneHandle, &request);
|
||||
return result;
|
||||
}
|
||||
|
||||
// If the time is rewound, we want to query against rigid bodies present at the same frame ID: the same as the current rewound time is.
|
||||
RequestT netSceneQueryRequest = request;
|
||||
netSceneQueryRequest.m_filterCallback = [&request, currentFrameId = (uint32_t)currentNetTime->GetHostFrameId()](
|
||||
const AzPhysics::SimulatedBody* body, const ::Physics::Shape* shape)
|
||||
{
|
||||
if (body->GetFrameId() == AzPhysics::SimulatedBody::UndefinedFrameId || body->GetFrameId() == currentFrameId)
|
||||
{
|
||||
if (request.m_filterCallback)
|
||||
{
|
||||
return request.m_filterCallback(body, shape);
|
||||
}
|
||||
|
||||
// Overlap filter callbacks return true/false rather than Touch/Block/None
|
||||
if constexpr (AZStd::is_same_v<RequestT, AzPhysics::OverlapRequest>)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return AzPhysics::SceneQuery::QueryHitType::Touch;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (AZStd::is_same_v<RequestT, AzPhysics::OverlapRequest>)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return AzPhysics::SceneQuery::QueryHitType::None;
|
||||
}
|
||||
};
|
||||
|
||||
// Execute the scene query modified for the time rewind.
|
||||
AzPhysics::SceneQueryHits result = sceneInterface->QueryScene(sceneHandle, &netSceneQueryRequest);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
namespace Physics
|
||||
{
|
||||
AzPhysics::SceneQueryHits RayCast(const AzPhysics::RayCastRequest& request)
|
||||
{
|
||||
return SceneQueryInternal<AzPhysics::RayCastRequest>(request);
|
||||
}
|
||||
|
||||
AzPhysics::SceneQueryHits ShapeCast(const AzPhysics::ShapeCastRequest& request)
|
||||
{
|
||||
return SceneQueryInternal<AzPhysics::ShapeCastRequest>(request);
|
||||
}
|
||||
|
||||
AzPhysics::SceneQueryHits Overlap(const AzPhysics::OverlapRequest& request)
|
||||
{
|
||||
return SceneQueryInternal<AzPhysics::OverlapRequest>(request);
|
||||
}
|
||||
} // namespace Physics
|
||||
} // namespace Multiplayer
|
||||
@@ -59,7 +59,7 @@ namespace Multiplayer
|
||||
AZ::Transform worldTm = GetEntity()->FindComponent<AzFramework::TransformComponent>()->GetWorldTM();
|
||||
auto preInsertionCallback =
|
||||
[worldTm = AZStd::move(worldTm), netEntityIndex = m_netEntityIndex, spawnableAssetId = m_networkSpawnableAsset.GetId()]
|
||||
(AzFramework::EntitySpawnTicket&, AzFramework::SpawnableEntityContainerView entities)
|
||||
(AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableEntityContainerView entities)
|
||||
{
|
||||
if (entities.size() == 1)
|
||||
{
|
||||
@@ -81,7 +81,8 @@ namespace Multiplayer
|
||||
};
|
||||
|
||||
m_netSpawnTicket = AzFramework::EntitySpawnTicket(m_networkSpawnableAsset);
|
||||
AzFramework::SpawnableEntitiesInterface::Get()->SpawnEntities(m_netSpawnTicket, {m_netEntityIndex}, preInsertionCallback);
|
||||
AzFramework::SpawnableEntitiesInterface::Get()->SpawnEntities(
|
||||
m_netSpawnTicket, AzFramework::SpawnablePriority_Default, { m_netEntityIndex }, preInsertionCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +90,7 @@ namespace Multiplayer
|
||||
{
|
||||
if(m_netSpawnTicket.IsValid())
|
||||
{
|
||||
AzFramework::SpawnableEntitiesInterface::Get()->DespawnAllEntities(m_netSpawnTicket);
|
||||
AzFramework::SpawnableEntitiesInterface::Get()->DespawnAllEntities(m_netSpawnTicket, AzFramework::SpawnablePriority_Default);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user