Cleanup server launch, misc. MP consts, and register Editor Spawnable assets server side

main
puvvadar 5 years ago
parent 74ea093f71
commit 1915b97c16

@ -308,6 +308,8 @@ namespace AZ
Asset(AssetLoadBehavior loadBehavior = AssetLoadBehavior::Default); Asset(AssetLoadBehavior loadBehavior = AssetLoadBehavior::Default);
/// Create an asset from a valid asset data (created asset), might not be loaded or currently loading. /// Create an asset from a valid asset data (created asset), might not be loaded or currently loading.
Asset(AssetData* assetData, AssetLoadBehavior loadBehavior); Asset(AssetData* assetData, AssetLoadBehavior loadBehavior);
/// Create an asset from a valid asset data (created asset) and set the asset id for both, might not be loaded or currently loading.
Asset(const AZ::Data::AssetId& id, AssetData* assetData, AssetLoadBehavior loadBehavior);
/// Initialize asset pointer with id, type, and hint. No data construction will occur until QueueLoad is called. /// Initialize asset pointer with id, type, and hint. No data construction will occur until QueueLoad is called.
Asset(const AZ::Data::AssetId& id, const AZ::Data::AssetType& type, const AZStd::string& hint = AZStd::string()); Asset(const AZ::Data::AssetId& id, const AZ::Data::AssetType& type, const AZStd::string& hint = AZStd::string());
@ -788,6 +790,17 @@ namespace AZ
SetData(assetData); SetData(assetData);
} }
//=========================================================================
template<class T>
Asset<T>::Asset(const AssetId& id, AssetData* assetData, AssetLoadBehavior loadBehavior)
: m_assetId(id)
, m_assetType(azrtti_typeid<T>())
, m_loadBehavior(loadBehavior)
{
assetData->m_assetId = id;
SetData(assetData);
}
//========================================================================= //=========================================================================
template<class T> template<class T>
Asset<T>::Asset(const AssetId& id, const AZ::Data::AssetType& type, const AZStd::string& hint) Asset<T>::Asset(const AssetId& id, const AZ::Data::AssetType& type, const AZStd::string& hint)

@ -46,6 +46,8 @@ namespace AzToolsFramework
virtual Prefab::InstanceOptionalReference GetRootPrefabInstance() = 0; virtual Prefab::InstanceOptionalReference GetRootPrefabInstance() = 0;
//! Get all Assets generated by Prefab processing when entering Play-In Editor mode (Ctrl+G)
//! /return The vector of Assets generated by Prefab processing
virtual const AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& GetPlayInEditorAssetData() = 0; virtual const AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& GetPlayInEditorAssetData() = 0;
virtual bool LoadFromStream(AZ::IO::GenericStream& stream, AZStd::string_view filename) = 0; virtual bool LoadFromStream(AZ::IO::GenericStream& stream, AZStd::string_view filename) = 0;

@ -0,0 +1,32 @@
/*
* 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 <AzCore/EBus/Event.h>
#include <AzCore/Name/Name.h>
#include <AzCore/RTTI/TypeSafeIntegral.h>
#include <AzCore/std/string/fixed_string.h>
#include <AzNetworking/Serialization/ISerializer.h>
#include <AzNetworking/ConnectionLayer/ConnectionEnums.h>
namespace Multiplayer
{
static constexpr AZStd::string_view MPNetworkInterfaceName("MultiplayerNetworkInterface");
static constexpr AZStd::string_view MPEditorInterfaceName("MultiplayerEditorNetworkInterface");
static constexpr AZStd::string_view LocalHost("127.0.0.1");
static constexpr uint16_t DefaultServerPort = 30090;
static constexpr uint16_t DefaultServerEditorPort = 30091;
}

@ -11,26 +11,22 @@
*/ */
#include <Include/IMultiplayer.h> #include <Include/IMultiplayer.h>
#include <Include/MultiplayerConstants.h>
#include <Source/Editor/MultiplayerEditorConnection.h> #include <Source/Editor/MultiplayerEditorConnection.h>
#include <Source/AutoGen/AutoComponentTypes.h> #include <Source/AutoGen/AutoComponentTypes.h>
#include <AzNetworking/ConnectionLayer/IConnection.h> #include <AzNetworking/ConnectionLayer/IConnection.h>
#include <AzNetworking/Framework/INetworking.h> #include <AzNetworking/Framework/INetworking.h>
#include <AzCore/Serialization/SerializeContext.h> #include <AzCore/Asset/AssetManager.h>
#include <AzCore/Interface/Interface.h> #include <AzCore/Interface/Interface.h>
#include <AzCore/Utils/Utils.h> #include <AzCore/Utils/Utils.h>
#include <AzCore/Serialization/SerializeContext.h> #include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/Utils.h> #include <AzCore/Serialization/Utils.h>
#include <AzFramework/Spawnable/Spawnable.h>
namespace Multiplayer namespace Multiplayer
{ {
using namespace AzNetworking; using namespace AzNetworking;
static const AZStd::string_view s_networkInterfaceName("MultiplayerNetworkInterface");
static const AZStd::string_view s_networkEditorInterfaceName("MultiplayerEditorNetworkInterface");
static constexpr AZStd::string_view DefaultEditorIp = "127.0.0.1";
static constexpr uint16_t DefaultServerPort = 30090;
static constexpr uint16_t DefaultServerEditorPort = 30091;
static AZStd::vector<uint8_t> buffer; static AZStd::vector<uint8_t> buffer;
static AZ::IO::ByteContainerStream<AZStd::vector<uint8_t>> s_byteStream(&buffer); static AZ::IO::ByteContainerStream<AZStd::vector<uint8_t>> s_byteStream(&buffer);
@ -39,10 +35,16 @@ namespace Multiplayer
MultiplayerEditorConnection::MultiplayerEditorConnection() MultiplayerEditorConnection::MultiplayerEditorConnection()
{ {
m_networkEditorInterface = AZ::Interface<INetworking>::Get()->CreateNetworkInterface( m_networkEditorInterface = AZ::Interface<INetworking>::Get()->CreateNetworkInterface(
AZ::Name(s_networkEditorInterfaceName), ProtocolType::Tcp, TrustZone::ExternalClientToServer, *this); AZ::Name(MPEditorInterfaceName), ProtocolType::Tcp, TrustZone::ExternalClientToServer, *this);
if (editorsv_isDedicated) if (editorsv_isDedicated)
{ {
m_networkEditorInterface->Listen(DefaultServerEditorPort); uint16_t editorServerPort = DefaultServerEditorPort;
if (auto console = AZ::Interface<AZ::IConsole>::Get(); console)
{
console->GetCvarValue("editorsv_port", editorServerPort);
}
AZ_Assert(m_networkEditorInterface, "MP Editor Network Interface was unregistered before Editor Server could start listening.");
m_networkEditorInterface->Listen(editorServerPort);
} }
} }
@ -69,34 +71,56 @@ namespace Multiplayer
AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>> assetData; AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>> assetData;
while (s_byteStream.GetCurPos() < s_byteStream.GetLength()) while (s_byteStream.GetCurPos() < s_byteStream.GetLength())
{ {
AZ::Data::AssetId assetId;
AZ::Data::AssetLoadBehavior assetLoadBehavior; AZ::Data::AssetLoadBehavior assetLoadBehavior;
uint32_t hintSize;
AZStd::string assetHint;
s_byteStream.Read(sizeof(AZ::Data::AssetId), reinterpret_cast<void*>(&assetId));
s_byteStream.Read(sizeof(AZ::Data::AssetLoadBehavior), reinterpret_cast<void*>(&assetLoadBehavior)); s_byteStream.Read(sizeof(AZ::Data::AssetLoadBehavior), reinterpret_cast<void*>(&assetLoadBehavior));
s_byteStream.Read(sizeof(uint32_t), reinterpret_cast<void*>(&hintSize));
assetHint.resize(hintSize);
s_byteStream.Read(hintSize, assetHint.data());
size_t assetSize = s_byteStream.GetCurPos();
AZ::Data::AssetData* assetDatum = AZ::Utils::LoadObjectFromStream<AZ::Data::AssetData>(s_byteStream, nullptr);
assetSize = s_byteStream.GetCurPos() - assetSize;
AZ::Data::Asset<AZ::Data::AssetData> asset = AZ::Data::Asset<AZ::Data::AssetData>(assetId, assetDatum, assetLoadBehavior);
asset.SetHint(assetHint);
AZ::Data::AssetInfo assetInfo;
assetInfo.m_assetId = asset.GetId();
assetInfo.m_assetType = asset.GetType();
assetInfo.m_relativePath = asset.GetHint();
assetInfo.m_sizeBytes = assetSize;
AZ::Data::AssetData* assetDatum = AZ::Utils::LoadObjectFromStream<AZ::Data::AssetData>(s_byteStream, nullptr);
AZ::Data::Asset<AZ::Data::AssetData> asset = AZ::Data::Asset<AZ::Data::AssetData>(assetDatum, assetLoadBehavior);
/*
// Register Asset to AssetManager // Register Asset to AssetManager
*/ AZ::Data::AssetManager::Instance().AssignAssetData(asset);
AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::RegisterAsset, asset.GetId(), assetInfo);
assetData.push_back(asset);
assetData.push_back(asset);
} }
// Now that we've deserialized, clear the byte stream // Now that we've deserialized, clear the byte stream
s_byteStream.Seek(0, AZ::IO::GenericStream::SeekMode::ST_SEEK_BEGIN); s_byteStream.Seek(0, AZ::IO::GenericStream::SeekMode::ST_SEEK_BEGIN);
s_byteStream.Truncate(); s_byteStream.Truncate();
/* // Load the level via the root spawnable tha was registered
// Hand-off our resultant assets AZ::CVarFixedString loadLevelString = "LoadLevel Root.spawnable";
*/ AZ::Interface<AZ::IConsole>::Get()->PerformCommand(loadLevelString.c_str());
AZLOG_INFO("Editor Server completed asset receive, responding to Editor..."); AZLOG_INFO("Editor Server completed asset receive, responding to Editor...");
if (connection->SendReliablePacket(MultiplayerEditorPackets::EditorServerReady())) if (connection->SendReliablePacket(MultiplayerEditorPackets::EditorServerReady()))
{ {
// Setup the normal multiplayer connection // Setup the normal multiplayer connection
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(MultiplayerAgentType::DedicatedServer); AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(MultiplayerAgentType::DedicatedServer);
INetworkInterface* networkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(s_networkInterfaceName)); INetworkInterface* networkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(MPNetworkInterfaceName));
networkInterface->Listen(DefaultServerPort);
uint16_t serverPort = DefaultServerPort;
if (auto console = AZ::Interface<AZ::IConsole>::Get(); console)
{
console->GetCvarValue("sv_port", serverPort);
}
networkInterface->Listen(serverPort);
return true; return true;
} }
@ -121,11 +145,22 @@ namespace Multiplayer
// Receiving this packet means Editor sync is done, disconnect // Receiving this packet means Editor sync is done, disconnect
connection->Disconnect(AzNetworking::DisconnectReason::TerminatedByClient, AzNetworking::TerminationEndpoint::Local); connection->Disconnect(AzNetworking::DisconnectReason::TerminatedByClient, AzNetworking::TerminationEndpoint::Local);
// Connect the Editor to the local server for Multiplayer simulation if (auto console = AZ::Interface<AZ::IConsole>::Get(); console)
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(MultiplayerAgentType::Client); {
INetworkInterface* networkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(s_networkInterfaceName)); AZ::CVarFixedString remoteAddress;
const IpAddress ipAddress(DefaultEditorIp.data(), DefaultServerEditorPort, networkInterface->GetType()); uint16_t remotePort;
networkInterface->Connect(ipAddress); if (console->GetCvarValue("editorsv_serveraddr", remoteAddress) != AZ::GetValueResult::ConsoleVarNotFound &&
console->GetCvarValue("editorsv_port", remotePort) != AZ::GetValueResult::ConsoleVarNotFound)
{
// Connect the Editor to the editor server for Multiplayer simulation
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(MultiplayerAgentType::Client);
INetworkInterface* networkInterface =
AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(MPNetworkInterfaceName));
const IpAddress ipAddress(remoteAddress.c_str(), remotePort, networkInterface->GetType());
networkInterface->Connect(ipAddress);
}
}
} }
return true; return true;
} }

@ -12,6 +12,7 @@
#include <Include/IMultiplayer.h> #include <Include/IMultiplayer.h>
#include <Include/IMultiplayerTools.h> #include <Include/IMultiplayerTools.h>
#include <Include/MultiplayerConstants.h>
#include <Source/AutoGen/Multiplayer.AutoPackets.h> #include <Source/AutoGen/Multiplayer.AutoPackets.h>
#include <Source/MultiplayerSystemComponent.h> #include <Source/MultiplayerSystemComponent.h>
#include <Source/Editor/MultiplayerEditorSystemComponent.h> #include <Source/Editor/MultiplayerEditorSystemComponent.h>
@ -26,16 +27,16 @@
namespace Multiplayer namespace Multiplayer
{ {
static const AZStd::string_view s_networkEditorInterfaceName("MultiplayerEditorNetworkInterface");
using namespace AzNetworking; using namespace AzNetworking;
AZ_CVAR(bool, editorsv_enabled, true, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, AZ_CVAR(bool, editorsv_enabled, true, nullptr, AZ::ConsoleFunctorFlags::DontReplicate,
"Whether Editor launching a local server to connect to is supported"); "Whether Editor launching a local server to connect to is supported");
AZ_CVAR(bool, editorsv_launch, false, nullptr, AZ::ConsoleFunctorFlags::DontReplicate,
"Whether Editor should launch a server when the server address is localhost");
AZ_CVAR(AZ::CVarFixedString, editorsv_process, "", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, AZ_CVAR(AZ::CVarFixedString, editorsv_process, "", nullptr, AZ::ConsoleFunctorFlags::DontReplicate,
"The server executable that should be run. Empty to use the current project's ServerLauncher"); "The server executable that should be run. Empty to use the current project's ServerLauncher");
AZ_CVAR(AZ::CVarFixedString, editorsv_serveraddr, "127.0.0.1", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The address of the server to connect to"); AZ_CVAR(AZ::CVarFixedString, editorsv_serveraddr, LocalHost.data(), nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The address of the server to connect to");
AZ_CVAR(uint16_t, editorsv_port, 30091, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The port that the multiplayer editor gem will bind to for traffic"); AZ_CVAR(uint16_t, editorsv_port, DefaultServerEditorPort, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The port that the multiplayer editor gem will bind to for traffic");
void MultiplayerEditorSystemComponent::Reflect(AZ::ReflectContext* context) void MultiplayerEditorSystemComponent::Reflect(AZ::ReflectContext* context)
{ {
@ -105,7 +106,7 @@ namespace Multiplayer
m_serverProcess->TerminateProcess(0); m_serverProcess->TerminateProcess(0);
m_serverProcess = nullptr; m_serverProcess = nullptr;
} }
INetworkInterface* editorNetworkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(s_networkEditorInterfaceName)); INetworkInterface* editorNetworkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(MPEditorInterfaceName));
if (editorNetworkInterface) if (editorNetworkInterface)
{ {
editorNetworkInterface->Disconnect(m_editorConnId, AzNetworking::DisconnectReason::TerminatedByClient); editorNetworkInterface->Disconnect(m_editorConnId, AzNetworking::DisconnectReason::TerminatedByClient);
@ -114,6 +115,46 @@ namespace Multiplayer
} }
} }
void LaunchEditorServer(AzFramework::ProcessWatcher* outProcess)
{
// Assemble the server's path
AZ::CVarFixedString serverProcess = editorsv_process;
if (serverProcess.empty())
{
// If enabled but no process name is supplied, try this project's ServerLauncher
serverProcess = AZ::Utils::GetProjectName() + ".ServerLauncher";
}
AZ::IO::FixedMaxPathString serverPath = AZ::Utils::GetExecutableDirectory();
if (!serverProcess.contains(AZ_TRAIT_OS_PATH_SEPARATOR))
{
// If only the process name is specified, append that as well
serverPath.append(AZ_TRAIT_OS_PATH_SEPARATOR + serverProcess);
}
else
{
// If any path was already specified, then simply assign
serverPath = serverProcess;
}
if (!serverProcess.ends_with(AZ_TRAIT_OS_EXECUTABLE_EXTENSION))
{
// Add this platform's exe extension if it's not specified
serverPath.append(AZ_TRAIT_OS_EXECUTABLE_EXTENSION);
}
// Start the configured server if it's available
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
processLaunchInfo.m_commandlineParameters = AZStd::string::format("\"%s\" --editorsv_isDedicated true", serverPath.c_str());
processLaunchInfo.m_showWindow = true;
processLaunchInfo.m_processPriority = AzFramework::ProcessPriority::PROCESSPRIORITY_NORMAL;
// Launch the Server and give it a few seconds to boot up
outProcess = AzFramework::ProcessWatcher::LaunchProcess(
processLaunchInfo, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_NONE);
AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(15000));
}
void MultiplayerEditorSystemComponent::OnGameEntitiesStarted() void MultiplayerEditorSystemComponent::OnGameEntitiesStarted()
{ {
auto prefabEditorEntityOwnershipInterface = AZ::Interface<AzToolsFramework::PrefabEditorEntityOwnershipInterface>::Get(); auto prefabEditorEntityOwnershipInterface = AZ::Interface<AzToolsFramework::PrefabEditorEntityOwnershipInterface>::Get();
@ -134,55 +175,38 @@ namespace Multiplayer
// Serialize Asset information and AssetData into a potentially large buffer // Serialize Asset information and AssetData into a potentially large buffer
for (auto asset : assetData) for (auto asset : assetData)
{ {
AZ::Data::AssetId assetId = asset.GetId();
AZ::Data::AssetLoadBehavior assetLoadBehavior = asset.GetAutoLoadBehavior(); AZ::Data::AssetLoadBehavior assetLoadBehavior = asset.GetAutoLoadBehavior();
AZStd::string assetHint = asset.GetHint();
uint32_t hintSize = aznumeric_cast<uint32_t>(assetHint.size());
byteStream.Write(sizeof(AZ::Data::AssetId), reinterpret_cast<void*>(&assetId));
byteStream.Write(sizeof(AZ::Data::AssetLoadBehavior), reinterpret_cast<void*>(&assetLoadBehavior)); byteStream.Write(sizeof(AZ::Data::AssetLoadBehavior), reinterpret_cast<void*>(&assetLoadBehavior));
byteStream.Write(sizeof(uint32_t), reinterpret_cast<void*>(&hintSize));
byteStream.Write(assetHint.size(), assetHint.data());
AZ::Utils::SaveObjectToStream(byteStream, AZ::DataStream::ST_BINARY, asset.GetData(), asset.GetData()->GetType()); AZ::Utils::SaveObjectToStream(byteStream, AZ::DataStream::ST_BINARY, asset.GetData(), asset.GetData()->GetType());
} }
// Assemble the server's path const AZ::CVarFixedString remoteAddress = editorsv_serveraddr;
AZ::CVarFixedString serverProcess = editorsv_process; if (editorsv_launch && LocalHost.compare(remoteAddress.c_str()) == 0)
if (serverProcess.empty())
{ {
// If enabled but no process name is supplied, try this project's ServerLauncher LaunchEditorServer(m_serverProcess);
serverProcess = AZ::Utils::GetProjectName() + ".ServerLauncher";
} }
AZ::IO::FixedMaxPathString serverPath = AZ::Utils::GetExecutableDirectory(); // Now that the server has launched, attempt to connect the NetworkInterface
if (!serverProcess.contains(AZ_TRAIT_OS_PATH_SEPARATOR)) INetworkInterface* editorNetworkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(MPEditorInterfaceName));
{ AZ_Assert(editorNetworkInterface, "MP Editor Network Interface was unregistered before Editor could connect.");
// If only the process name is specified, append that as well m_editorConnId = editorNetworkInterface->Connect(
serverPath.append(AZ_TRAIT_OS_PATH_SEPARATOR + serverProcess); AzNetworking::IpAddress(remoteAddress.c_str(), editorsv_port, AzNetworking::ProtocolType::Tcp));
}
else
{
// If any path was already specified, then simply assign
serverPath = serverProcess;
}
if (!serverProcess.ends_with(AZ_TRAIT_OS_EXECUTABLE_EXTENSION)) if (m_editorConnId == AzNetworking::InvalidConnectionId)
{ {
// Add this platform's exe extension if it's not specified AZ_Warning(
serverPath.append(AZ_TRAIT_OS_EXECUTABLE_EXTENSION); "MultiplayerEditor", false,
"Could not connect to server targeted by Editor. If using a local server, check that it's built and editorsv_launch is true.");
return;
} }
// Start the configured server if it's available
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
processLaunchInfo.m_commandlineParameters = AZStd::string::format("\"%s\" --editorsv_isDedicated true", serverPath.c_str());
processLaunchInfo.m_showWindow = true;
processLaunchInfo.m_processPriority = AzFramework::ProcessPriority::PROCESSPRIORITY_NORMAL;
// Launch the Server and give it a few seconds to boot up
m_serverProcess = AzFramework::ProcessWatcher::LaunchProcess(
processLaunchInfo, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_NONE);
AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(15000));
// Now that the server has launched, attempt to connect the NetworkInterface
const AZ::CVarFixedString remoteAddress = editorsv_serveraddr;
INetworkInterface* editorNetworkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(s_networkEditorInterfaceName));
m_editorConnId = editorNetworkInterface->Connect(
AzNetworking::IpAddress(remoteAddress.c_str(), editorsv_port, AzNetworking::ProtocolType::Tcp));
// Read the buffer into EditorServerInit packets until we've flushed the whole thing // Read the buffer into EditorServerInit packets until we've flushed the whole thing
byteStream.Seek(0, AZ::IO::GenericStream::SeekMode::ST_SEEK_BEGIN); byteStream.Seek(0, AZ::IO::GenericStream::SeekMode::ST_SEEK_BEGIN);

@ -10,6 +10,7 @@
* *
*/ */
#include <Include/MultiplayerConstants.h>
#include <Source/MultiplayerSystemComponent.h> #include <Source/MultiplayerSystemComponent.h>
#include <Source/Components/MultiplayerComponent.h> #include <Source/Components/MultiplayerComponent.h>
#include <Source/AutoGen/AutoComponentTypes.h> #include <Source/AutoGen/AutoComponentTypes.h>
@ -59,13 +60,8 @@ namespace Multiplayer
{ {
using namespace AzNetworking; using namespace AzNetworking;
static const AZStd::string_view s_networkInterfaceName("MultiplayerNetworkInterface");
static const AZStd::string_view s_networkEditorInterfaceName("MultiplayerEditorNetworkInterface");
static constexpr uint16_t DefaultServerPort = 30090;
static constexpr uint16_t DefaultServerEditorPort = 30091;
AZ_CVAR(uint16_t, cl_clientport, 0, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The port to bind to for game traffic when connecting to a remote host, a value of 0 will select any available port"); AZ_CVAR(uint16_t, cl_clientport, 0, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The port to bind to for game traffic when connecting to a remote host, a value of 0 will select any available port");
AZ_CVAR(AZ::CVarFixedString, cl_serveraddr, "127.0.0.1", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The address of the remote server or host to connect to"); AZ_CVAR(AZ::CVarFixedString, cl_serveraddr, LocalHost.data(), nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The address of the remote server or host to connect to");
AZ_CVAR(AZ::CVarFixedString, cl_serverpassword, "", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Optional server password"); AZ_CVAR(AZ::CVarFixedString, cl_serverpassword, "", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Optional server password");
AZ_CVAR(uint16_t, cl_serverport, DefaultServerPort, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The port of the remote host to connect to for game traffic"); AZ_CVAR(uint16_t, cl_serverport, DefaultServerPort, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The port of the remote host to connect to for game traffic");
AZ_CVAR(uint16_t, sv_port, DefaultServerPort, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The port that this multiplayer gem will bind to for game traffic"); AZ_CVAR(uint16_t, sv_port, DefaultServerPort, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The port that this multiplayer gem will bind to for game traffic");
@ -116,7 +112,7 @@ namespace Multiplayer
void MultiplayerSystemComponent::Activate() void MultiplayerSystemComponent::Activate()
{ {
AZ::TickBus::Handler::BusConnect(); AZ::TickBus::Handler::BusConnect();
m_networkInterface = AZ::Interface<INetworking>::Get()->CreateNetworkInterface(AZ::Name(s_networkInterfaceName), sv_protocol, TrustZone::ExternalClientToServer, *this); m_networkInterface = AZ::Interface<INetworking>::Get()->CreateNetworkInterface(AZ::Name(MPNetworkInterfaceName), sv_protocol, TrustZone::ExternalClientToServer, *this);
m_consoleCommandHandler.Connect(AZ::Interface<AZ::IConsole>::Get()->GetConsoleCommandInvokedEvent()); m_consoleCommandHandler.Connect(AZ::Interface<AZ::IConsole>::Get()->GetConsoleCommandInvokedEvent());
AZ::Interface<IMultiplayer>::Register(this); AZ::Interface<IMultiplayer>::Register(this);
@ -635,7 +631,7 @@ namespace Multiplayer
{ {
Multiplayer::MultiplayerAgentType serverType = sv_isDedicated ? MultiplayerAgentType::DedicatedServer : MultiplayerAgentType::ClientServer; Multiplayer::MultiplayerAgentType serverType = sv_isDedicated ? MultiplayerAgentType::DedicatedServer : MultiplayerAgentType::ClientServer;
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(serverType); AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(serverType);
INetworkInterface* networkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(s_networkInterfaceName)); INetworkInterface* networkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(MPNetworkInterfaceName));
networkInterface->Listen(sv_port); networkInterface->Listen(sv_port);
} }
AZ_CONSOLEFREEFUNC(host, AZ::ConsoleFunctorFlags::DontReplicate, "Opens a multiplayer connection as a host for other clients to connect to"); AZ_CONSOLEFREEFUNC(host, AZ::ConsoleFunctorFlags::DontReplicate, "Opens a multiplayer connection as a host for other clients to connect to");
@ -643,7 +639,7 @@ namespace Multiplayer
void connect([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments) void connect([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
{ {
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(MultiplayerAgentType::Client); AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(MultiplayerAgentType::Client);
INetworkInterface* networkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(s_networkInterfaceName)); INetworkInterface* networkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(MPNetworkInterfaceName));
if (arguments.size() < 1) if (arguments.size() < 1)
{ {
@ -673,7 +669,7 @@ namespace Multiplayer
void disconnect([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments) void disconnect([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
{ {
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(MultiplayerAgentType::Uninitialized); AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(MultiplayerAgentType::Uninitialized);
INetworkInterface* networkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(s_networkInterfaceName)); INetworkInterface* networkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(MPNetworkInterfaceName));
auto visitor = [](IConnection& connection) { connection.Disconnect(DisconnectReason::TerminatedByUser, TerminationEndpoint::Local); }; auto visitor = [](IConnection& connection) { connection.Disconnect(DisconnectReason::TerminatedByUser, TerminationEndpoint::Local); };
networkInterface->GetConnectionSet().VisitConnections(visitor); networkInterface->GetConnectionSet().VisitConnections(visitor);
} }

@ -31,11 +31,16 @@ namespace Multiplayer
void NetworkPrefabProcessor::Process(PrefabProcessorContext& context) void NetworkPrefabProcessor::Process(PrefabProcessorContext& context)
{ {
IMultiplayerTools* mpTools = AZ::Interface<IMultiplayerTools>::Get(); IMultiplayerTools* mpTools = AZ::Interface<IMultiplayerTools>::Get();
mpTools->SetDidProcessNetworkPrefabs(false); if (mpTools)
{
mpTools->SetDidProcessNetworkPrefabs(false);
}
context.ListPrefabs([&context](AZStd::string_view prefabName, PrefabDom& prefab) { context.ListPrefabs([&context](AZStd::string_view prefabName, PrefabDom& prefab) {
ProcessPrefab(context, prefabName, prefab); ProcessPrefab(context, prefabName, prefab);
}); });
if (context.GetProcessedObjects().size() > 0)
if (mpTools && context.GetProcessedObjects().size() > 0)
{ {
mpTools->SetDidProcessNetworkPrefabs(true); mpTools->SetDidProcessNetworkPrefabs(true);
} }

@ -17,6 +17,7 @@ set(FILES
Include/INetworkEntityManager.h Include/INetworkEntityManager.h
Include/INetworkTime.h Include/INetworkTime.h
Include/IReplicationWindow.h Include/IReplicationWindow.h
Include/MultiplayerConstants.h
Include/MultiplayerStats.cpp Include/MultiplayerStats.cpp
Include/MultiplayerStats.h Include/MultiplayerStats.h
Include/MultiplayerTypes.h Include/MultiplayerTypes.h

Loading…
Cancel
Save