diff --git a/AutomatedTesting/Gem/Code/CMakeLists.txt b/AutomatedTesting/Gem/Code/CMakeLists.txt
index 6f55cc2764..8808507765 100644
--- a/AutomatedTesting/Gem/Code/CMakeLists.txt
+++ b/AutomatedTesting/Gem/Code/CMakeLists.txt
@@ -14,15 +14,25 @@ ly_add_target(
FILES_CMAKE
automatedtesting_files.cmake
${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
+ automatedtesting_autogen_files.cmake
INCLUDE_DIRECTORIES
PRIVATE
Source
PUBLIC
Include
BUILD_DEPENDENCIES
+ PUBLIC
+ AZ::AzNetworking
+ Gem::Multiplayer
PRIVATE
AZ::AzCore
Gem::Atom_AtomBridge.Static
+ Gem::Multiplayer.Static
+ AUTOGEN_RULES
+ *.AutoComponent.xml,AutoComponent_Header.jinja,$path/$fileprefix.AutoComponent.h
+ *.AutoComponent.xml,AutoComponent_Source.jinja,$path/$fileprefix.AutoComponent.cpp
+ *.AutoComponent.xml,AutoComponentTypes_Header.jinja,$path/AutoComponentTypes.h
+ *.AutoComponent.xml,AutoComponentTypes_Source.jinja,$path/AutoComponentTypes.cpp
)
# if enabled, AutomatedTesting is used by all kinds of applications
diff --git a/AutomatedTesting/Gem/Code/Source/AutoGen/NetworkTestPlayerComponent.AutoComponent.xml b/AutomatedTesting/Gem/Code/Source/AutoGen/NetworkTestPlayerComponent.AutoComponent.xml
new file mode 100644
index 0000000000..12c222add6
--- /dev/null
+++ b/AutomatedTesting/Gem/Code/Source/AutoGen/NetworkTestPlayerComponent.AutoComponent.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/AutomatedTesting/Gem/Code/Source/AutomatedTestingModule.cpp b/AutomatedTesting/Gem/Code/Source/AutomatedTestingModule.cpp
index 7ed37e89ca..b5be8410ef 100644
--- a/AutomatedTesting/Gem/Code/Source/AutomatedTestingModule.cpp
+++ b/AutomatedTesting/Gem/Code/Source/AutomatedTestingModule.cpp
@@ -8,6 +8,7 @@
#include
#include
+#include
#include
@@ -27,6 +28,8 @@ namespace AutomatedTesting
m_descriptors.insert(m_descriptors.end(), {
AutomatedTestingSystemComponent::CreateDescriptor(),
});
+
+ CreateComponentDescriptors(m_descriptors); //< Register multiplayer components
}
/**
diff --git a/AutomatedTesting/Gem/Code/Source/AutomatedTestingSystemComponent.cpp b/AutomatedTesting/Gem/Code/Source/AutomatedTestingSystemComponent.cpp
index 3b373b1f65..a77f62caf2 100644
--- a/AutomatedTesting/Gem/Code/Source/AutomatedTestingSystemComponent.cpp
+++ b/AutomatedTesting/Gem/Code/Source/AutomatedTestingSystemComponent.cpp
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
#include
@@ -60,6 +61,7 @@ namespace AutomatedTesting
void AutomatedTestingSystemComponent::Activate()
{
AutomatedTestingRequestBus::Handler::BusConnect();
+ RegisterMultiplayerComponents(); //< Register AutomatedTesting's multiplayer components to assign NetComponentIds
}
void AutomatedTestingSystemComponent::Deactivate()
diff --git a/AutomatedTesting/Gem/Code/automatedtesting_autogen_files.cmake b/AutomatedTesting/Gem/Code/automatedtesting_autogen_files.cmake
new file mode 100644
index 0000000000..b3c6fcaa0b
--- /dev/null
+++ b/AutomatedTesting/Gem/Code/automatedtesting_autogen_files.cmake
@@ -0,0 +1,14 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
+#
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+set(FILES
+ ${LY_ROOT_FOLDER}/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Common.jinja
+ ${LY_ROOT_FOLDER}/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Header.jinja
+ ${LY_ROOT_FOLDER}/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponent_Source.jinja
+ ${LY_ROOT_FOLDER}/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponentTypes_Header.jinja
+ ${LY_ROOT_FOLDER}/Gems/Multiplayer/Code/Include/Multiplayer/AutoGen/AutoComponentTypes_Source.jinja
+)
diff --git a/AutomatedTesting/Gem/Code/automatedtesting_files.cmake b/AutomatedTesting/Gem/Code/automatedtesting_files.cmake
index 6bf2bf72d9..eb619104a4 100644
--- a/AutomatedTesting/Gem/Code/automatedtesting_files.cmake
+++ b/AutomatedTesting/Gem/Code/automatedtesting_files.cmake
@@ -11,4 +11,5 @@ set(FILES
Source/AutomatedTestingModule.cpp
Source/AutomatedTestingSystemComponent.cpp
Source/AutomatedTestingSystemComponent.h
+ Source/AutoGen/NetworkTestPlayerComponent.AutoComponent.xml
)
diff --git a/AutomatedTesting/Gem/Code/enabled_gems.cmake b/AutomatedTesting/Gem/Code/enabled_gems.cmake
index f653a54505..e6a4d6ca37 100644
--- a/AutomatedTesting/Gem/Code/enabled_gems.cmake
+++ b/AutomatedTesting/Gem/Code/enabled_gems.cmake
@@ -55,4 +55,5 @@ set(ENABLED_GEMS
PrefabBuilder
AudioSystem
Profiler
+ Multiplayer
)
diff --git a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt
index fd3222ba83..bec49185bd 100644
--- a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt
+++ b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt
@@ -59,5 +59,8 @@ add_subdirectory(smoke)
## AWS ##
add_subdirectory(AWS)
+## Multiplayer ##
+add_subdirectory(Multiplayer)
+
## Integration tests for editor testing framework ##
add_subdirectory(editor_test_testing)
diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py
index 1b094b1cfa..481d73274f 100644
--- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py
+++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py
@@ -14,7 +14,10 @@ from typing import Callable, Tuple
import azlmbr
import azlmbr.legacy.general as general
+import azlmbr.multiplayer as multiplayer
import azlmbr.debug
+import ly_test_tools.environment.waiter as waiter
+import ly_test_tools.environment.process_utils as process_utils
class FailFast(Exception):
@@ -66,6 +69,56 @@ class TestHelper:
TestHelper.wait_for_condition(lambda : general.is_in_game_mode(), 1.0)
Report.critical_result(msgtuple_success_fail, general.is_in_game_mode())
+ @staticmethod
+ def multiplayer_enter_game_mode(msgtuple_success_fail : Tuple[str, str], sv_default_player_spawn_asset : str):
+ # type: (tuple) -> None
+ """
+ :param msgtuple_success_fail: The tuple with the expected/unexpected messages for entering game mode.
+ :param sv_default_player_spawn_asset: The path to the network player prefab that will be automatically spawned upon entering gamemode. The engine default is "prefabs/player.network.spawnable"
+
+ :return: None
+ """
+
+ # looks for an expected line in a list of tracers lines
+ # lines: the tracer list of lines to search. options are section_tracer.warnings, section_tracer.errors, section_tracer.asserts, section_tracer.prints
+ # return: true if the line is found, otherwise false
+ def find_expected_line(expected_line, lines):
+ found_lines = [printInfo.message.strip() for printInfo in lines]
+ return expected_line in found_lines
+
+ def wait_for_critical_expected_line(expected_line, lines, time_out):
+ TestHelper.wait_for_condition(lambda : find_expected_line(expected_line, lines), time_out)
+ Report.critical_result(("Found expected line: " + expected_line, "Failed to find expected line: " + expected_line), find_expected_line(expected_line, lines))
+
+ def wait_for_critical_unexpected_line(unexpected_line, lines, time_out):
+ TestHelper.wait_for_condition(lambda : find_expected_line(unexpected_line, lines), time_out)
+ Report.critical_result(("Unexpected line not found: " + unexpected_line, "Unexpected line found: " + unexpected_line), not find_expected_line(unexpected_line, lines))
+
+
+ Report.info("Entering game mode")
+ if sv_default_player_spawn_asset :
+ general.set_cvar("sv_defaultPlayerSpawnAsset", sv_default_player_spawn_asset)
+
+ with Tracer() as section_tracer:
+ # enter game-mode.
+ # game-mode in multiplayer will also launch ServerLauncher.exe and connect to the editor
+ multiplayer.PythonEditorFuncs_enter_game_mode()
+
+ # make sure the server launcher binary exists
+ wait_for_critical_unexpected_line("LaunchEditorServer failed! The ServerLauncher binary is missing!", section_tracer.errors, 0.5)
+
+ # make sure the server launcher is running
+ waiter.wait_for(lambda: process_utils.process_exists("AutomatedTesting.ServerLauncher", ignore_extensions=True), timeout=5.0, exc=AssertionError("AutomatedTesting.ServerLauncher has NOT launched!"), interval=1.0)
+
+ # make sure the editor connects to the editor-server and sends the level data packet
+ wait_for_critical_expected_line("Editor is sending the editor-server the level data packet.", section_tracer.prints, 5.0)
+
+ # make sure the editor finally connects to the editor-server network simulation
+ wait_for_critical_expected_line("Editor-server ready. Editor has successfully connected to the editor-server's network simulation.", section_tracer.prints, 5.0)
+
+ TestHelper.wait_for_condition(lambda : multiplayer.PythonEditorFuncs_is_in_game_mode(), 5.0)
+ Report.critical_result(msgtuple_success_fail, multiplayer.PythonEditorFuncs_is_in_game_mode())
+
@staticmethod
def exit_game_mode(msgtuple_success_fail : Tuple[str, str]):
# type: (tuple) -> None
diff --git a/AutomatedTesting/Gem/PythonTests/Multiplayer/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/Multiplayer/CMakeLists.txt
new file mode 100644
index 0000000000..5e74d1e93b
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/Multiplayer/CMakeLists.txt
@@ -0,0 +1,23 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+#
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
+ ly_add_pytest(
+ NAME AutomatedTesting::MultiplayerTests_Main
+ TEST_SUITE main
+ TEST_SERIAL
+ PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Main.py
+ RUNTIME_DEPENDENCIES
+ Legacy::Editor
+ AZ::AssetProcessor
+ AutomatedTesting.Assets
+ AutomatedTesting.ServerLauncher
+ COMPONENT
+ Multiplayer
+ )
+endif()
diff --git a/AutomatedTesting/Gem/PythonTests/Multiplayer/TestSuite_Main.py b/AutomatedTesting/Gem/PythonTests/Multiplayer/TestSuite_Main.py
new file mode 100644
index 0000000000..9cecaa7fe8
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/Multiplayer/TestSuite_Main.py
@@ -0,0 +1,33 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+
+"""
+
+# This suite consists of all test cases that are under development and have not been verified yet.
+# Once they are verified, please move them to TestSuite_Active.py
+
+import pytest
+import os
+import sys
+
+
+sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../automatedtesting_shared')
+
+from base import TestAutomationBase
+
+@pytest.mark.parametrize("project", ["AutomatedTesting"])
+@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
+class TestAutomation(TestAutomationBase):
+ def _run_prefab_test(self, request, workspace, editor, test_module, batch_mode=True, autotest_mode=True):
+ self._run_test(request, workspace, editor, test_module,
+ extra_cmdline_args=["--regset=/Amazon/Preferences/EnablePrefabSystem=true"],
+ batch_mode=batch_mode,
+ autotest_mode=autotest_mode)
+
+ def test_Multiplayer_AutoComponent_NetworkInput(self, request, workspace, editor, launcher_platform):
+ from .tests import Multiplayer_AutoComponent_NetworkInput as test_module
+ self._run_prefab_test(request, workspace, editor, test_module)
+
diff --git a/AutomatedTesting/Gem/PythonTests/Multiplayer/__init__.py b/AutomatedTesting/Gem/PythonTests/Multiplayer/__init__.py
new file mode 100644
index 0000000000..f5193b300e
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/Multiplayer/__init__.py
@@ -0,0 +1,6 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+"""
diff --git a/AutomatedTesting/Gem/PythonTests/Multiplayer/tests/Multiplayer_AutoComponent_NetworkInput.py b/AutomatedTesting/Gem/PythonTests/Multiplayer/tests/Multiplayer_AutoComponent_NetworkInput.py
new file mode 100644
index 0000000000..7b56213313
--- /dev/null
+++ b/AutomatedTesting/Gem/PythonTests/Multiplayer/tests/Multiplayer_AutoComponent_NetworkInput.py
@@ -0,0 +1,115 @@
+"""
+Copyright (c) Contributors to the Open 3D Engine Project.
+For complete copyright and license terms please see the LICENSE at the root of this distribution.
+
+SPDX-License-Identifier: Apache-2.0 OR MIT
+"""
+
+
+# Test Case Title : Check that network input can be created, received by the authority, and processed
+
+
+# fmt: off
+class Tests():
+ enter_game_mode = ("Entered game mode", "Failed to enter game mode")
+ exit_game_mode = ("Exited game mode", "Couldn't exit game mode")
+ find_network_player = ("Found network player", "Couldn't find network player")
+ found_lines = ("Expected log lines were found", "Expected log lines were not found")
+ found_unexpected_lines = ("Unexpected log lines were not found", "Unexpected log lines were found")
+# fmt: on
+
+
+def Multiplayer_AutoComponent_NetworkInput():
+ r"""
+ Summary:
+ Runs a test to make sure that network input can be sent from the autonomous player, received by the authority, and processed
+
+ Level Description:
+ - Dynamic
+ 1. Although the level is empty, when the server and editor connect the server will spawn and replicate the player network prefab.
+ a. The player network prefab has a NetworkTestPlayerComponent.AutoComponent and a script canvas attached which will listen for the CreateInput and ProcessInput events.
+ Print logs occur upon triggering the CreateInput and ProcessInput events along with their values; we are testing to make sure the expected events are values are recieved.
+ - Static
+ 1. This is an empty level. All the logic occurs on the Player.network.spawnable (see the above Dynamic description)
+
+
+ Expected Outcome:
+ We should see editor logs stating that network input has been created and processed.
+ However, if the script receives unexpected values for the Process event we will see print logs for bad data as well.
+
+ :return:
+ """
+ import azlmbr.legacy.general as general
+ from editor_python_test_tools.utils import Report
+ from editor_python_test_tools.utils import Tracer
+
+ from editor_python_test_tools.utils import TestHelper as helper
+ from ly_remote_console.remote_console_commands import RemoteConsole as RemoteConsole
+
+
+ def find_expected_line(expected_line):
+ found_lines = [printInfo.message.strip() for printInfo in section_tracer.prints]
+ return expected_line in found_lines
+
+ def find_unexpected_line(expected_line):
+ return not find_expected_line(expected_line)
+
+ unexpected_lines = [
+ 'AutoComponent_NetworkInput received bad fwdback!',
+ 'AutoComponent_NetworkInput received bad leftright!',
+
+ ]
+ expected_lines = [
+ 'AutoComponent_NetworkInput ProcessInput called!',
+ 'AutoComponent_NetworkInput CreateInput called!',
+ ]
+
+ expected_lines_server = [
+ '(Script) - AutoComponent_NetworkInput ProcessInput called!',
+ ]
+
+ level_name = "AutoComponent_NetworkInput"
+ player_prefab_name = "Player"
+ player_prefab_path = f"levels/multiplayer/{level_name}/{player_prefab_name}.network.spawnable"
+
+ helper.init_idle()
+
+
+ # 1) Open Level
+ helper.open_level("Multiplayer", level_name)
+
+ with Tracer() as section_tracer:
+ # 2) Enter game mode
+ helper.multiplayer_enter_game_mode(Tests.enter_game_mode, player_prefab_path.lower())
+
+ # 3) Make sure the network player was spawned
+ player_id = general.find_game_entity(player_prefab_name)
+ Report.critical_result(Tests.find_network_player, player_id.IsValid())
+
+ # 4) Check the editor logs for expected and unexpected log output
+ EXPECTEDLINE_WAIT_TIME_SECONDS = 1.0
+ for expected_line in expected_lines :
+ helper.wait_for_condition(lambda: find_expected_line(expected_line), EXPECTEDLINE_WAIT_TIME_SECONDS)
+ Report.result(Tests.found_lines, find_expected_line(expected_line))
+
+ general.idle_wait_frames(1)
+ for unexpected_line in unexpected_lines :
+ Report.result(Tests.found_unexpected_lines, find_unexpected_line(unexpected_line))
+
+ # 5) Check the ServerLauncher logs for expected log output
+ # Since the editor has started a server launcher, the RemoteConsole with the default port=4600 will automatically be able to read the server logs
+ server_console = RemoteConsole()
+ server_console.start()
+ for line in expected_lines_server:
+ assert server_console.expect_log_line(line, EXPECTEDLINE_WAIT_TIME_SECONDS), f"Expected line not found: {line}"
+ server_console.stop()
+
+
+ # Exit game mode
+ helper.exit_game_mode(Tests.exit_game_mode)
+
+
+
+if __name__ == "__main__":
+ from editor_python_test_tools.utils import Report
+ Report.start_test(Multiplayer_AutoComponent_NetworkInput)
diff --git a/AutomatedTesting/Levels/Multiplayer/AutoComponent_NetworkInput/AutoComponent_NetworkInput.prefab b/AutomatedTesting/Levels/Multiplayer/AutoComponent_NetworkInput/AutoComponent_NetworkInput.prefab
new file mode 100644
index 0000000000..78c88144fd
--- /dev/null
+++ b/AutomatedTesting/Levels/Multiplayer/AutoComponent_NetworkInput/AutoComponent_NetworkInput.prefab
@@ -0,0 +1,525 @@
+{
+ "ContainerEntity": {
+ "Id": "Entity_[1146574390643]",
+ "Name": "Level",
+ "Components": {
+ "Component_[10641544592923449938]": {
+ "$type": "EditorInspectorComponent",
+ "Id": 10641544592923449938
+ },
+ "Component_[12039882709170782873]": {
+ "$type": "EditorOnlyEntityComponent",
+ "Id": 12039882709170782873
+ },
+ "Component_[12265484671603697631]": {
+ "$type": "EditorPendingCompositionComponent",
+ "Id": 12265484671603697631
+ },
+ "Component_[14126657869720434043]": {
+ "$type": "EditorEntitySortComponent",
+ "Id": 14126657869720434043
+ },
+ "Component_[15230859088967841193]": {
+ "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+ "Id": 15230859088967841193,
+ "Parent Entity": ""
+ },
+ "Component_[16239496886950819870]": {
+ "$type": "EditorDisabledCompositionComponent",
+ "Id": 16239496886950819870
+ },
+ "Component_[5688118765544765547]": {
+ "$type": "EditorEntityIconComponent",
+ "Id": 5688118765544765547
+ },
+ "Component_[6545738857812235305]": {
+ "$type": "SelectionComponent",
+ "Id": 6545738857812235305
+ },
+ "Component_[7247035804068349658]": {
+ "$type": "EditorPrefabComponent",
+ "Id": 7247035804068349658
+ },
+ "Component_[9307224322037797205]": {
+ "$type": "EditorLockComponent",
+ "Id": 9307224322037797205
+ },
+ "Component_[9562516168917670048]": {
+ "$type": "EditorVisibilityComponent",
+ "Id": 9562516168917670048
+ }
+ }
+ },
+ "Entities": {
+ "Entity_[1155164325235]": {
+ "Id": "Entity_[1155164325235]",
+ "Name": "Sun",
+ "Components": {
+ "Component_[10440557478882592717]": {
+ "$type": "SelectionComponent",
+ "Id": 10440557478882592717
+ },
+ "Component_[13620450453324765907]": {
+ "$type": "EditorLockComponent",
+ "Id": 13620450453324765907
+ },
+ "Component_[2134313378593666258]": {
+ "$type": "EditorInspectorComponent",
+ "Id": 2134313378593666258
+ },
+ "Component_[234010807770404186]": {
+ "$type": "EditorVisibilityComponent",
+ "Id": 234010807770404186
+ },
+ "Component_[2970359110423865725]": {
+ "$type": "EditorEntityIconComponent",
+ "Id": 2970359110423865725
+ },
+ "Component_[3722854130373041803]": {
+ "$type": "EditorOnlyEntityComponent",
+ "Id": 3722854130373041803
+ },
+ "Component_[5992533738676323195]": {
+ "$type": "EditorDisabledCompositionComponent",
+ "Id": 5992533738676323195
+ },
+ "Component_[7378860763541895402]": {
+ "$type": "AZ::Render::EditorDirectionalLightComponent",
+ "Id": 7378860763541895402,
+ "Controller": {
+ "Configuration": {
+ "Intensity": 1.0,
+ "CameraEntityId": "",
+ "ShadowFilterMethod": 1
+ }
+ }
+ },
+ "Component_[7892834440890947578]": {
+ "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+ "Id": 7892834440890947578,
+ "Parent Entity": "Entity_[1176639161715]",
+ "Transform Data": {
+ "Translate": [
+ 0.0,
+ 0.0,
+ 13.487043380737305
+ ],
+ "Rotate": [
+ -76.13099670410156,
+ -0.847000002861023,
+ -15.8100004196167
+ ]
+ }
+ },
+ "Component_[8599729549570828259]": {
+ "$type": "EditorEntitySortComponent",
+ "Id": 8599729549570828259
+ },
+ "Component_[952797371922080273]": {
+ "$type": "EditorPendingCompositionComponent",
+ "Id": 952797371922080273
+ }
+ }
+ },
+ "Entity_[1159459292531]": {
+ "Id": "Entity_[1159459292531]",
+ "Name": "Ground",
+ "Components": {
+ "Component_[11701138785793981042]": {
+ "$type": "SelectionComponent",
+ "Id": 11701138785793981042
+ },
+ "Component_[12260880513256986252]": {
+ "$type": "EditorEntityIconComponent",
+ "Id": 12260880513256986252
+ },
+ "Component_[13711420870643673468]": {
+ "$type": "EditorDisabledCompositionComponent",
+ "Id": 13711420870643673468
+ },
+ "Component_[138002849734991713]": {
+ "$type": "EditorOnlyEntityComponent",
+ "Id": 138002849734991713
+ },
+ "Component_[16578565737331764849]": {
+ "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+ "Id": 16578565737331764849,
+ "Parent Entity": "Entity_[1176639161715]"
+ },
+ "Component_[16919232076966545697]": {
+ "$type": "EditorInspectorComponent",
+ "Id": 16919232076966545697
+ },
+ "Component_[5182430712893438093]": {
+ "$type": "EditorMaterialComponent",
+ "Id": 5182430712893438093,
+ "materialSlots": [
+ {
+ "id": {
+ "materialSlotStableId": 803645540
+ }
+ },
+ {
+ "id": {
+ "materialSlotStableId": 803645540
+ }
+ }
+ ],
+ "materialSlotsByLod": [
+ [
+ {
+ "id": {
+ "lodIndex": 0,
+ "materialSlotStableId": 803645540
+ }
+ }
+ ],
+ [
+ {
+ "id": {
+ "lodIndex": 0,
+ "materialSlotStableId": 803645540
+ }
+ }
+ ]
+ ]
+ },
+ "Component_[5675108321710651991]": {
+ "$type": "AZ::Render::EditorMeshComponent",
+ "Id": 5675108321710651991,
+ "Controller": {
+ "Configuration": {
+ "ModelAsset": {
+ "assetId": {
+ "guid": "{0CD745C0-6AA8-569A-A68A-73A3270986C4}",
+ "subId": 277889906
+ },
+ "assetHint": "objects/groudplane/groundplane_512x512m.azmodel"
+ }
+ }
+ }
+ },
+ "Component_[5681893399601237518]": {
+ "$type": "EditorEntitySortComponent",
+ "Id": 5681893399601237518
+ },
+ "Component_[592692962543397545]": {
+ "$type": "EditorPendingCompositionComponent",
+ "Id": 592692962543397545
+ },
+ "Component_[7090012899106946164]": {
+ "$type": "EditorLockComponent",
+ "Id": 7090012899106946164
+ },
+ "Component_[9410832619875640998]": {
+ "$type": "EditorVisibilityComponent",
+ "Id": 9410832619875640998
+ }
+ }
+ },
+ "Entity_[1163754259827]": {
+ "Id": "Entity_[1163754259827]",
+ "Name": "Camera",
+ "Components": {
+ "Component_[11895140916889160460]": {
+ "$type": "EditorEntityIconComponent",
+ "Id": 11895140916889160460
+ },
+ "Component_[16880285896855930892]": {
+ "$type": "{CA11DA46-29FF-4083-B5F6-E02C3A8C3A3D} EditorCameraComponent",
+ "Id": 16880285896855930892,
+ "Controller": {
+ "Configuration": {
+ "Field of View": 55.0,
+ "EditorEntityId": 12554887233631987164
+ }
+ }
+ },
+ "Component_[17187464423780271193]": {
+ "$type": "EditorLockComponent",
+ "Id": 17187464423780271193
+ },
+ "Component_[17495696818315413311]": {
+ "$type": "EditorEntitySortComponent",
+ "Id": 17495696818315413311
+ },
+ "Component_[18086214374043522055]": {
+ "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+ "Id": 18086214374043522055,
+ "Parent Entity": "Entity_[1176639161715]",
+ "Transform Data": {
+ "Translate": [
+ -2.3000001907348633,
+ -3.9368600845336914,
+ 1.0
+ ],
+ "Rotate": [
+ -2.050307512283325,
+ 1.9552897214889526,
+ -43.623355865478516
+ ]
+ }
+ },
+ "Component_[18387556550380114975]": {
+ "$type": "SelectionComponent",
+ "Id": 18387556550380114975
+ },
+ "Component_[2654521436129313160]": {
+ "$type": "EditorVisibilityComponent",
+ "Id": 2654521436129313160
+ },
+ "Component_[5265045084611556958]": {
+ "$type": "EditorDisabledCompositionComponent",
+ "Id": 5265045084611556958
+ },
+ "Component_[7169798125182238623]": {
+ "$type": "EditorPendingCompositionComponent",
+ "Id": 7169798125182238623
+ },
+ "Component_[7255796294953281766]": {
+ "$type": "GenericComponentWrapper",
+ "Id": 7255796294953281766,
+ "m_template": {
+ "$type": "FlyCameraInputComponent"
+ }
+ },
+ "Component_[8866210352157164042]": {
+ "$type": "EditorInspectorComponent",
+ "Id": 8866210352157164042
+ },
+ "Component_[9129253381063760879]": {
+ "$type": "EditorOnlyEntityComponent",
+ "Id": 9129253381063760879
+ }
+ }
+ },
+ "Entity_[1168049227123]": {
+ "Id": "Entity_[1168049227123]",
+ "Name": "Grid",
+ "Components": {
+ "Component_[11443347433215807130]": {
+ "$type": "EditorEntityIconComponent",
+ "Id": 11443347433215807130
+ },
+ "Component_[11779275529534764488]": {
+ "$type": "SelectionComponent",
+ "Id": 11779275529534764488
+ },
+ "Component_[14249419413039427459]": {
+ "$type": "EditorInspectorComponent",
+ "Id": 14249419413039427459
+ },
+ "Component_[15448581635946161318]": {
+ "$type": "AZ::Render::EditorGridComponent",
+ "Id": 15448581635946161318,
+ "Controller": {
+ "Configuration": {
+ "primarySpacing": 4.0,
+ "primaryColor": [
+ 0.501960813999176,
+ 0.501960813999176,
+ 0.501960813999176
+ ],
+ "secondarySpacing": 0.5,
+ "secondaryColor": [
+ 0.250980406999588,
+ 0.250980406999588,
+ 0.250980406999588
+ ]
+ }
+ }
+ },
+ "Component_[1843303322527297409]": {
+ "$type": "EditorDisabledCompositionComponent",
+ "Id": 1843303322527297409
+ },
+ "Component_[380249072065273654]": {
+ "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+ "Id": 380249072065273654,
+ "Parent Entity": "Entity_[1176639161715]"
+ },
+ "Component_[7476660583684339787]": {
+ "$type": "EditorPendingCompositionComponent",
+ "Id": 7476660583684339787
+ },
+ "Component_[7557626501215118375]": {
+ "$type": "EditorEntitySortComponent",
+ "Id": 7557626501215118375
+ },
+ "Component_[7984048488947365511]": {
+ "$type": "EditorVisibilityComponent",
+ "Id": 7984048488947365511
+ },
+ "Component_[8118181039276487398]": {
+ "$type": "EditorOnlyEntityComponent",
+ "Id": 8118181039276487398
+ },
+ "Component_[9189909764215270515]": {
+ "$type": "EditorLockComponent",
+ "Id": 9189909764215270515
+ }
+ }
+ },
+ "Entity_[1176639161715]": {
+ "Id": "Entity_[1176639161715]",
+ "Name": "Atom Default Environment",
+ "Components": {
+ "Component_[10757302973393310045]": {
+ "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+ "Id": 10757302973393310045,
+ "Parent Entity": "Entity_[1146574390643]"
+ },
+ "Component_[14505817420424255464]": {
+ "$type": "EditorInspectorComponent",
+ "Id": 14505817420424255464,
+ "ComponentOrderEntryArray": [
+ {
+ "ComponentId": 10757302973393310045
+ }
+ ]
+ },
+ "Component_[14988041764659020032]": {
+ "$type": "EditorLockComponent",
+ "Id": 14988041764659020032
+ },
+ "Component_[15808690248755038124]": {
+ "$type": "SelectionComponent",
+ "Id": 15808690248755038124
+ },
+ "Component_[15900837685796817138]": {
+ "$type": "EditorVisibilityComponent",
+ "Id": 15900837685796817138
+ },
+ "Component_[3298767348226484884]": {
+ "$type": "EditorOnlyEntityComponent",
+ "Id": 3298767348226484884
+ },
+ "Component_[4076975109609220594]": {
+ "$type": "EditorPendingCompositionComponent",
+ "Id": 4076975109609220594
+ },
+ "Component_[5679760548946028854]": {
+ "$type": "EditorDisabledCompositionComponent",
+ "Id": 5679760548946028854
+ },
+ "Component_[5855590796136709437]": {
+ "$type": "EditorEntitySortComponent",
+ "Id": 5855590796136709437,
+ "ChildEntityOrderEntryArray": [
+ {
+ "EntityId": "Entity_[1155164325235]"
+ },
+ {
+ "EntityId": "Entity_[1180934129011]",
+ "SortIndex": 1
+ },
+ {
+ "EntityId": "",
+ "SortIndex": 2
+ },
+ {
+ "EntityId": "Entity_[1168049227123]",
+ "SortIndex": 3
+ },
+ {
+ "EntityId": "Entity_[1163754259827]",
+ "SortIndex": 4
+ },
+ {
+ "EntityId": "Entity_[1159459292531]",
+ "SortIndex": 5
+ }
+ ]
+ },
+ "Component_[9277695270015777859]": {
+ "$type": "EditorEntityIconComponent",
+ "Id": 9277695270015777859
+ }
+ }
+ },
+ "Entity_[1180934129011]": {
+ "Id": "Entity_[1180934129011]",
+ "Name": "Global Sky",
+ "Components": {
+ "Component_[11231930600558681245]": {
+ "$type": "AZ::Render::EditorHDRiSkyboxComponent",
+ "Id": 11231930600558681245,
+ "Controller": {
+ "Configuration": {
+ "CubemapAsset": {
+ "assetId": {
+ "guid": "{215E47FD-D181-5832-B1AB-91673ABF6399}",
+ "subId": 1000
+ },
+ "assetHint": "lightingpresets/highcontrast/goegap_4k_skyboxcm.exr.streamingimage"
+ }
+ }
+ }
+ },
+ "Component_[11980494120202836095]": {
+ "$type": "SelectionComponent",
+ "Id": 11980494120202836095
+ },
+ "Component_[1428633914413949476]": {
+ "$type": "EditorLockComponent",
+ "Id": 1428633914413949476
+ },
+ "Component_[14936200426671614999]": {
+ "$type": "AZ::Render::EditorImageBasedLightComponent",
+ "Id": 14936200426671614999,
+ "Controller": {
+ "Configuration": {
+ "diffuseImageAsset": {
+ "assetId": {
+ "guid": "{3FD09945-D0F2-55C8-B9AF-B2FD421FE3BE}",
+ "subId": 3000
+ },
+ "assetHint": "lightingpresets/highcontrast/goegap_4k_iblglobalcm_ibldiffuse.exr.streamingimage"
+ },
+ "specularImageAsset": {
+ "assetId": {
+ "guid": "{3FD09945-D0F2-55C8-B9AF-B2FD421FE3BE}",
+ "subId": 2000
+ },
+ "assetHint": "lightingpresets/highcontrast/goegap_4k_iblglobalcm_iblspecular.exr.streamingimage"
+ }
+ }
+ }
+ },
+ "Component_[14994774102579326069]": {
+ "$type": "EditorDisabledCompositionComponent",
+ "Id": 14994774102579326069
+ },
+ "Component_[15417479889044493340]": {
+ "$type": "EditorPendingCompositionComponent",
+ "Id": 15417479889044493340
+ },
+ "Component_[15826613364991382688]": {
+ "$type": "EditorEntitySortComponent",
+ "Id": 15826613364991382688
+ },
+ "Component_[1665003113283562343]": {
+ "$type": "EditorOnlyEntityComponent",
+ "Id": 1665003113283562343
+ },
+ "Component_[3704934735944502280]": {
+ "$type": "EditorEntityIconComponent",
+ "Id": 3704934735944502280
+ },
+ "Component_[5698542331457326479]": {
+ "$type": "EditorVisibilityComponent",
+ "Id": 5698542331457326479
+ },
+ "Component_[6644513399057217122]": {
+ "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+ "Id": 6644513399057217122,
+ "Parent Entity": "Entity_[1176639161715]"
+ },
+ "Component_[931091830724002070]": {
+ "$type": "EditorInspectorComponent",
+ "Id": 931091830724002070
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/AutomatedTesting/Levels/Multiplayer/AutoComponent_NetworkInput/AutoComponent_NetworkInput.scriptcanvas b/AutomatedTesting/Levels/Multiplayer/AutoComponent_NetworkInput/AutoComponent_NetworkInput.scriptcanvas
new file mode 100644
index 0000000000..2f8a434108
--- /dev/null
+++ b/AutomatedTesting/Levels/Multiplayer/AutoComponent_NetworkInput/AutoComponent_NetworkInput.scriptcanvas
@@ -0,0 +1,1827 @@
+{
+ "Type": "JsonSerialization",
+ "Version": 1,
+ "ClassName": "ScriptCanvasData",
+ "ClassData": {
+ "m_scriptCanvas": {
+ "Id": {
+ "id": 20239954977260
+ },
+ "Name": "AutoComponent_NetworkInput",
+ "Components": {
+ "Component_[14059414856740480991]": {
+ "$type": "EditorGraphVariableManagerComponent",
+ "Id": 14059414856740480991,
+ "m_variableData": {
+ "m_nameVariableMap": [
+ {
+ "Key": {
+ "m_id": "{720D213F-AA7A-48B0-ABBB-A3756C528CF9}"
+ },
+ "Value": {
+ "Datum": {
+ "scriptCanvasType": {
+ "m_type": 3
+ },
+ "isNullPointer": false,
+ "$type": "double",
+ "value": 0.25
+ },
+ "VariableId": {
+ "m_id": "{720D213F-AA7A-48B0-ABBB-A3756C528CF9}"
+ },
+ "VariableName": "leftright"
+ }
+ },
+ {
+ "Key": {
+ "m_id": "{B2E338E9-2ACB-42FC-B0BE-EDA14A8A86AD}"
+ },
+ "Value": {
+ "Datum": {
+ "scriptCanvasType": {
+ "m_type": 3
+ },
+ "isNullPointer": false,
+ "$type": "double",
+ "value": 1.0
+ },
+ "VariableId": {
+ "m_id": "{B2E338E9-2ACB-42FC-B0BE-EDA14A8A86AD}"
+ },
+ "VariableName": "fwdback"
+ }
+ },
+ {
+ "Key": {
+ "m_id": "{D843B13F-B3C7-4619-8092-7164EB1D7888}"
+ },
+ "Value": {
+ "Datum": {
+ "scriptCanvasType": {
+ "m_type": 3
+ },
+ "isNullPointer": false,
+ "$type": "double",
+ "value": 20.0
+ },
+ "VariableId": {
+ "m_id": "{D843B13F-B3C7-4619-8092-7164EB1D7888}"
+ },
+ "VariableName": "VELOCITY"
+ }
+ }
+ ]
+ }
+ },
+ "Component_[642525765775040231]": {
+ "$type": "{4D755CA9-AB92-462C-B24F-0B3376F19967} Graph",
+ "Id": 642525765775040231,
+ "m_graphData": {
+ "m_nodes": [
+ {
+ "Id": {
+ "id": 20265724781036
+ },
+ "Name": "SC-Node(NotEqualTo)",
+ "Components": {
+ "Component_[12036973200504716538]": {
+ "$type": "NotEqualTo",
+ "Id": 12036973200504716538,
+ "Slots": [
+ {
+ "id": {
+ "m_id": "{6D0EF497-7C52-432B-9301-7BAB26F4F5A5}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Result",
+ "DisplayDataType": {
+ "m_type": 0
+ },
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 2
+ },
+ "DataType": 1
+ },
+ {
+ "id": {
+ "m_id": "{AE7E453C-15DE-47D2-954A-05C3895B7AC6}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "In",
+ "toolTip": "Signal to perform the evaluation when desired.",
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{AC364E17-A9A1-42DB-A29D-7B2D666E4287}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "True",
+ "toolTip": "Signaled if the result of the operation is true.",
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{0754AC37-61A6-42A7-B4EC-D35D18D27960}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "False",
+ "toolTip": "Signaled if the result of the operation is false.",
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{57EBC15B-452E-49B3-8BD3-4FBBB07F1F14}"
+ },
+ "DynamicTypeOverride": 3,
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Value A",
+ "DisplayDataType": {
+ "m_type": 3
+ },
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 2
+ },
+ "DynamicGroup": {
+ "Value": 3545012108
+ },
+ "DataType": 1
+ },
+ {
+ "id": {
+ "m_id": "{21864AEE-7954-4F68-82C6-573C175724EF}"
+ },
+ "DynamicTypeOverride": 3,
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Value B",
+ "DisplayDataType": {
+ "m_type": 3
+ },
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 2
+ },
+ "DynamicGroup": {
+ "Value": 3545012108
+ },
+ "DataType": 1,
+ "IsReference": true,
+ "VariableReference": {
+ "m_id": "{720D213F-AA7A-48B0-ABBB-A3756C528CF9}"
+ }
+ }
+ ],
+ "Datums": [
+ {
+ "scriptCanvasType": {
+ "m_type": 3
+ },
+ "isNullPointer": false,
+ "$type": "double",
+ "value": 0.0,
+ "label": "Value A"
+ },
+ {
+ "scriptCanvasType": {
+ "m_type": 3
+ },
+ "isNullPointer": false,
+ "$type": "double",
+ "value": 0.0,
+ "label": "Value B"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 20257134846444
+ },
+ "Name": "SC-Node(NotEqualTo)",
+ "Components": {
+ "Component_[12036973200504716538]": {
+ "$type": "NotEqualTo",
+ "Id": 12036973200504716538,
+ "Slots": [
+ {
+ "id": {
+ "m_id": "{6D0EF497-7C52-432B-9301-7BAB26F4F5A5}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Result",
+ "DisplayDataType": {
+ "m_type": 0
+ },
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 2
+ },
+ "DataType": 1
+ },
+ {
+ "id": {
+ "m_id": "{AE7E453C-15DE-47D2-954A-05C3895B7AC6}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "In",
+ "toolTip": "Signal to perform the evaluation when desired.",
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{AC364E17-A9A1-42DB-A29D-7B2D666E4287}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "True",
+ "toolTip": "Signaled if the result of the operation is true.",
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{0754AC37-61A6-42A7-B4EC-D35D18D27960}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "False",
+ "toolTip": "Signaled if the result of the operation is false.",
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{57EBC15B-452E-49B3-8BD3-4FBBB07F1F14}"
+ },
+ "DynamicTypeOverride": 3,
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Value A",
+ "DisplayDataType": {
+ "m_type": 3
+ },
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 2
+ },
+ "DynamicGroup": {
+ "Value": 3545012108
+ },
+ "DataType": 1
+ },
+ {
+ "id": {
+ "m_id": "{21864AEE-7954-4F68-82C6-573C175724EF}"
+ },
+ "DynamicTypeOverride": 3,
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Value B",
+ "DisplayDataType": {
+ "m_type": 3
+ },
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 2
+ },
+ "DynamicGroup": {
+ "Value": 3545012108
+ },
+ "DataType": 1,
+ "IsReference": true,
+ "VariableReference": {
+ "m_id": "{B2E338E9-2ACB-42FC-B0BE-EDA14A8A86AD}"
+ }
+ }
+ ],
+ "Datums": [
+ {
+ "scriptCanvasType": {
+ "m_type": 3
+ },
+ "isNullPointer": false,
+ "$type": "double",
+ "value": 0.0,
+ "label": "Value A"
+ },
+ {
+ "scriptCanvasType": {
+ "m_type": 3
+ },
+ "isNullPointer": false,
+ "$type": "double",
+ "value": 0.0,
+ "label": "Value B"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 20278609682924
+ },
+ "Name": "SC-Node(Print)",
+ "Components": {
+ "Component_[12996217042650310160]": {
+ "$type": "Print",
+ "Id": 12996217042650310160,
+ "Slots": [
+ {
+ "id": {
+ "m_id": "{D994D58A-DBF1-4929-B779-F0D2CBAD2F0D}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "In",
+ "toolTip": "Input signal",
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{233C15BC-0186-4A7F-B272-6B2C020DE57A}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Out",
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 1
+ }
+ }
+ ],
+ "m_format": "AutoComponent_NetworkInput ProcessInput called!",
+ "m_unresolvedString": [
+ "AutoComponent_NetworkInput ProcessInput called!"
+ ]
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 20244249944556
+ },
+ "Name": "SC-Node(CreateFromValues)",
+ "Components": {
+ "Component_[16858161274259468878]": {
+ "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method",
+ "Id": 16858161274259468878,
+ "Slots": [
+ {
+ "id": {
+ "m_id": "{7CF3B6C0-FE59-4E16-ABC6-E7CC8AFA8EF3}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "fwdBack",
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 2
+ },
+ "DataType": 1,
+ "IsReference": true,
+ "VariableReference": {
+ "m_id": "{B2E338E9-2ACB-42FC-B0BE-EDA14A8A86AD}"
+ }
+ },
+ {
+ "id": {
+ "m_id": "{02473A8A-A0F0-4E73-8999-0B16D17E8E2A}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "leftRight",
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 2
+ },
+ "DataType": 1,
+ "IsReference": true,
+ "VariableReference": {
+ "m_id": "{720D213F-AA7A-48B0-ABBB-A3756C528CF9}"
+ }
+ },
+ {
+ "id": {
+ "m_id": "{514CDDAA-290F-4758-B28F-4003E719E635}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "In",
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{E3A94716-C880-4D6D-ADD6-34D019161ED1}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Out",
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{90E52F81-54E0-4C63-9881-B661FB5D87D1}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Result: NetworkTestPlayerComponentNetworkInput",
+ "DisplayDataType": {
+ "m_type": 4,
+ "m_azType": "{12A1776B-61F6-4E5F-356A-AD718A62051F}"
+ },
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 2
+ },
+ "DataType": 1
+ }
+ ],
+ "Datums": [
+ {
+ "scriptCanvasType": {
+ "m_type": 3
+ },
+ "isNullPointer": false,
+ "$type": "double",
+ "value": 0.0,
+ "label": "fwdBack"
+ },
+ {
+ "scriptCanvasType": {
+ "m_type": 3
+ },
+ "isNullPointer": false,
+ "$type": "double",
+ "value": 0.0,
+ "label": "leftRight"
+ }
+ ],
+ "methodType": 2,
+ "methodName": "CreateFromValues",
+ "className": "NetworkTestPlayerComponentNetworkInput",
+ "resultSlotIDs": [
+ {}
+ ],
+ "inputSlots": [
+ {
+ "m_id": "{7CF3B6C0-FE59-4E16-ABC6-E7CC8AFA8EF3}"
+ },
+ {
+ "m_id": "{02473A8A-A0F0-4E73-8999-0B16D17E8E2A}"
+ }
+ ],
+ "prettyClassName": "NetworkTestPlayerComponentNetworkInput"
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 20252839879148
+ },
+ "Name": "EBusEventHandler",
+ "Components": {
+ "Component_[1734984895901771768]": {
+ "$type": "EBusEventHandler",
+ "Id": 1734984895901771768,
+ "Slots": [
+ {
+ "id": {
+ "m_id": "{41899533-66B3-423F-8BE2-A624A1FB6FCB}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Connect",
+ "toolTip": "Connect this event handler to the specified entity.",
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{65C09819-1B00-4BA8-B6E0-8DD6D8B44A36}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Disconnect",
+ "toolTip": "Disconnect this event handler.",
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{B7437693-34D0-4BDE-8516-2CADB9F509BF}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "OnConnected",
+ "toolTip": "Signaled when a connection has taken place.",
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{BCE36ED4-0899-4403-826A-FE89BE033A0A}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "OnDisconnected",
+ "toolTip": "Signaled when this event handler is disconnected.",
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{796993F4-685D-4A85-A0CA-032E3466FB57}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "OnFailure",
+ "toolTip": "Signaled when it is not possible to connect this handler.",
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{680E9668-87B4-4FF2-AA24-EB8F11352A49}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Source",
+ "toolTip": "ID used to connect on a specific Event address (Type: EntityId)",
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 2
+ },
+ "DataType": 1
+ },
+ {
+ "id": {
+ "m_id": "{ADF9B366-8324-4C1E-B601-C059DA70FDDE}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Result: NetworkTestPlayerComponentNetworkInput",
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 2
+ },
+ "DataType": 1
+ },
+ {
+ "id": {
+ "m_id": "{3301102C-AD42-48A0-8764-D2D4D31E0C75}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Number",
+ "DisplayDataType": {
+ "m_type": 3
+ },
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 2
+ },
+ "DataType": 1
+ },
+ {
+ "id": {
+ "m_id": "{B831AC60-7641-4B74-9829-26A3576B4766}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "ExecutionSlot:CreateInput",
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 1
+ },
+ "IsLatent": true
+ },
+ {
+ "id": {
+ "m_id": "{8F69FA2E-28D8-4DF1-A4B5-AEF3985095C5}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "NetworkTestPlayerComponentNetworkInput",
+ "DisplayDataType": {
+ "m_type": 4,
+ "m_azType": "{12A1776B-61F6-4E5F-356A-AD718A62051F}"
+ },
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 2
+ },
+ "DataType": 1
+ },
+ {
+ "id": {
+ "m_id": "{BE3E3F84-E91C-4F6C-B148-E13BF01B5FBC}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Number",
+ "DisplayDataType": {
+ "m_type": 3
+ },
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 2
+ },
+ "DataType": 1
+ },
+ {
+ "id": {
+ "m_id": "{4C8F2908-12B0-4C35-8468-31D3D4DF36AA}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "ExecutionSlot:ProcessInput",
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 1
+ },
+ "IsLatent": true
+ }
+ ],
+ "Datums": [
+ {
+ "scriptCanvasType": {
+ "m_type": 1
+ },
+ "isNullPointer": false,
+ "$type": "EntityId",
+ "value": {
+ "id": 2901262558
+ },
+ "label": "Source"
+ },
+ {
+ "scriptCanvasType": {
+ "m_type": 4,
+ "m_azType": "{12A1776B-61F6-4E5F-356A-AD718A62051F}"
+ },
+ "isNullPointer": false,
+ "$type": "NetworkTestPlayerComponentNetworkInput",
+ "label": "Result: NetworkTestPlayerComponentNetworkInput"
+ }
+ ],
+ "m_eventMap": [
+ {
+ "Key": {
+ "Value": 78438309
+ },
+ "Value": {
+ "m_eventName": "CreateInput",
+ "m_eventId": {
+ "Value": 78438309
+ },
+ "m_eventSlotId": {
+ "m_id": "{B831AC60-7641-4B74-9829-26A3576B4766}"
+ },
+ "m_resultSlotId": {
+ "m_id": "{ADF9B366-8324-4C1E-B601-C059DA70FDDE}"
+ },
+ "m_parameterSlotIds": [
+ {
+ "m_id": "{3301102C-AD42-48A0-8764-D2D4D31E0C75}"
+ }
+ ],
+ "m_numExpectedArguments": 1
+ }
+ },
+ {
+ "Key": {
+ "Value": 1793364217
+ },
+ "Value": {
+ "m_eventName": "ProcessInput",
+ "m_eventId": {
+ "Value": 1793364217
+ },
+ "m_eventSlotId": {
+ "m_id": "{4C8F2908-12B0-4C35-8468-31D3D4DF36AA}"
+ },
+ "m_parameterSlotIds": [
+ {
+ "m_id": "{8F69FA2E-28D8-4DF1-A4B5-AEF3985095C5}"
+ },
+ {
+ "m_id": "{BE3E3F84-E91C-4F6C-B148-E13BF01B5FBC}"
+ }
+ ],
+ "m_numExpectedArguments": 2
+ }
+ }
+ ],
+ "m_ebusName": "NetworkTestPlayerComponentBusHandler",
+ "m_busId": {
+ "Value": 3690077280
+ }
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 20248544911852
+ },
+ "Name": "SC-Node(ExtractProperty)",
+ "Components": {
+ "Component_[2395597035843331661]": {
+ "$type": "ExtractProperty",
+ "Id": 2395597035843331661,
+ "Slots": [
+ {
+ "id": {
+ "m_id": "{C80C50EE-F216-4F44-B107-6B35354AFD52}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "In",
+ "toolTip": "When signaled assigns property values using the supplied source input",
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{C69C098D-D667-4DC7-85E5-AFD119727D94}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Out",
+ "toolTip": "Signaled after all property haves have been pushed to the output slots",
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{D387C800-352B-4B01-8765-4F4B40DF45CB}"
+ },
+ "DynamicTypeOverride": 1,
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Source",
+ "toolTip": "The value on which to extract properties from.",
+ "DisplayDataType": {
+ "m_type": 4,
+ "m_azType": "{12A1776B-61F6-4E5F-356A-AD718A62051F}"
+ },
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 2
+ },
+ "DataType": 1
+ },
+ {
+ "id": {
+ "m_id": "{0C03D491-DE25-46C2-BF09-14769FA49FDB}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "FwdBack: Number",
+ "DisplayDataType": {
+ "m_type": 3
+ },
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 2
+ },
+ "DataType": 1
+ },
+ {
+ "id": {
+ "m_id": "{4C13F9EF-60BF-4AD1-8FA9-66F46455411C}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "LeftRight: Number",
+ "DisplayDataType": {
+ "m_type": 3
+ },
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 2
+ },
+ "DataType": 1
+ }
+ ],
+ "Datums": [
+ {
+ "scriptCanvasType": {
+ "m_type": 4,
+ "m_azType": "{12A1776B-61F6-4E5F-356A-AD718A62051F}"
+ },
+ "isNullPointer": false,
+ "$type": "NetworkTestPlayerComponentNetworkInput",
+ "label": "Source"
+ }
+ ],
+ "m_dataType": {
+ "m_type": 4,
+ "m_azType": "{12A1776B-61F6-4E5F-356A-AD718A62051F}"
+ },
+ "m_propertyAccounts": [
+ {
+ "m_propertySlotId": {
+ "m_id": "{0C03D491-DE25-46C2-BF09-14769FA49FDB}"
+ },
+ "m_propertyType": {
+ "m_type": 3
+ },
+ "m_propertyName": "FwdBack"
+ },
+ {
+ "m_propertySlotId": {
+ "m_id": "{4C13F9EF-60BF-4AD1-8FA9-66F46455411C}"
+ },
+ "m_propertyType": {
+ "m_type": 3
+ },
+ "m_propertyName": "LeftRight"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 20270019748332
+ },
+ "Name": "SC-Node(Print)",
+ "Components": {
+ "Component_[7568030783460446634]": {
+ "$type": "Print",
+ "Id": 7568030783460446634,
+ "Slots": [
+ {
+ "id": {
+ "m_id": "{733AA75D-022C-45E9-9D0F-3EF9A1633ADC}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "In",
+ "toolTip": "Input signal",
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{2E77B0FC-DE56-4D78-9A59-152B7A0666F3}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Out",
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 1
+ }
+ }
+ ],
+ "m_format": "AutoComponent_NetworkInput received bad fwdback!",
+ "m_unresolvedString": [
+ "AutoComponent_NetworkInput received bad fwdback!"
+ ]
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 20274314715628
+ },
+ "Name": "SC-Node(Print)",
+ "Components": {
+ "Component_[7568030783460446634]": {
+ "$type": "Print",
+ "Id": 7568030783460446634,
+ "Slots": [
+ {
+ "id": {
+ "m_id": "{733AA75D-022C-45E9-9D0F-3EF9A1633ADC}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "In",
+ "toolTip": "Input signal",
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{2E77B0FC-DE56-4D78-9A59-152B7A0666F3}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Out",
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 1
+ }
+ }
+ ],
+ "m_format": "AutoComponent_NetworkInput received bad leftright!",
+ "m_unresolvedString": [
+ "AutoComponent_NetworkInput received bad leftright!"
+ ]
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 20261429813740
+ },
+ "Name": "SC-Node(Print)",
+ "Components": {
+ "Component_[8131385522131771125]": {
+ "$type": "Print",
+ "Id": 8131385522131771125,
+ "Slots": [
+ {
+ "id": {
+ "m_id": "{2B6DB3BC-AA87-4280-B4C3-42C1EE17CBA3}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "In",
+ "toolTip": "Input signal",
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{68F1C47B-3127-4CBA-AC9B-5B9B736C70AD}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Out",
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 1
+ }
+ }
+ ],
+ "m_format": "AutoComponent_NetworkInput CreateInput called!",
+ "m_unresolvedString": [
+ "AutoComponent_NetworkInput CreateInput called!"
+ ]
+ }
+ }
+ }
+ ],
+ "m_connections": [
+ {
+ "Id": {
+ "id": 20282904650220
+ },
+ "Name": "srcEndpoint=(NetworkTestPlayerComponentBusHandler Handler: ExecutionSlot:CreateInput), destEndpoint=(Print: In)",
+ "Components": {
+ "Component_[3586317167340048684]": {
+ "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+ "Id": 3586317167340048684,
+ "sourceEndpoint": {
+ "nodeId": {
+ "id": 20252839879148
+ },
+ "slotId": {
+ "m_id": "{B831AC60-7641-4B74-9829-26A3576B4766}"
+ }
+ },
+ "targetEndpoint": {
+ "nodeId": {
+ "id": 20261429813740
+ },
+ "slotId": {
+ "m_id": "{2B6DB3BC-AA87-4280-B4C3-42C1EE17CBA3}"
+ }
+ }
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 20287199617516
+ },
+ "Name": "srcEndpoint=(NetworkTestPlayerComponentBusHandler Handler: ExecutionSlot:CreateInput), destEndpoint=(CreateFromValues: In)",
+ "Components": {
+ "Component_[15956251897822268937]": {
+ "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+ "Id": 15956251897822268937,
+ "sourceEndpoint": {
+ "nodeId": {
+ "id": 20252839879148
+ },
+ "slotId": {
+ "m_id": "{B831AC60-7641-4B74-9829-26A3576B4766}"
+ }
+ },
+ "targetEndpoint": {
+ "nodeId": {
+ "id": 20244249944556
+ },
+ "slotId": {
+ "m_id": "{514CDDAA-290F-4758-B28F-4003E719E635}"
+ }
+ }
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 20291494584812
+ },
+ "Name": "srcEndpoint=(CreateFromValues: Result: NetworkTestPlayerComponentNetworkInput), destEndpoint=(NetworkTestPlayerComponentBusHandler Handler: Result: NetworkTestPlayerComponentNetworkInput)",
+ "Components": {
+ "Component_[3864080489501353126]": {
+ "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+ "Id": 3864080489501353126,
+ "sourceEndpoint": {
+ "nodeId": {
+ "id": 20244249944556
+ },
+ "slotId": {
+ "m_id": "{90E52F81-54E0-4C63-9881-B661FB5D87D1}"
+ }
+ },
+ "targetEndpoint": {
+ "nodeId": {
+ "id": 20252839879148
+ },
+ "slotId": {
+ "m_id": "{ADF9B366-8324-4C1E-B601-C059DA70FDDE}"
+ }
+ }
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 20295789552108
+ },
+ "Name": "srcEndpoint=(NetworkTestPlayerComponentBusHandler Handler: ExecutionSlot:ProcessInput), destEndpoint=(Print: In)",
+ "Components": {
+ "Component_[8628095809445337119]": {
+ "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+ "Id": 8628095809445337119,
+ "sourceEndpoint": {
+ "nodeId": {
+ "id": 20252839879148
+ },
+ "slotId": {
+ "m_id": "{4C8F2908-12B0-4C35-8468-31D3D4DF36AA}"
+ }
+ },
+ "targetEndpoint": {
+ "nodeId": {
+ "id": 20278609682924
+ },
+ "slotId": {
+ "m_id": "{D994D58A-DBF1-4929-B779-F0D2CBAD2F0D}"
+ }
+ }
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 20300084519404
+ },
+ "Name": "srcEndpoint=(NetworkTestPlayerComponentBusHandler Handler: ExecutionSlot:ProcessInput), destEndpoint=(Extract Properties: In)",
+ "Components": {
+ "Component_[10621112306443381493]": {
+ "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+ "Id": 10621112306443381493,
+ "sourceEndpoint": {
+ "nodeId": {
+ "id": 20252839879148
+ },
+ "slotId": {
+ "m_id": "{4C8F2908-12B0-4C35-8468-31D3D4DF36AA}"
+ }
+ },
+ "targetEndpoint": {
+ "nodeId": {
+ "id": 20248544911852
+ },
+ "slotId": {
+ "m_id": "{C80C50EE-F216-4F44-B107-6B35354AFD52}"
+ }
+ }
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 20304379486700
+ },
+ "Name": "srcEndpoint=(NetworkTestPlayerComponentBusHandler Handler: NetworkTestPlayerComponentNetworkInput), destEndpoint=(Extract Properties: Source)",
+ "Components": {
+ "Component_[14013500888143163469]": {
+ "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+ "Id": 14013500888143163469,
+ "sourceEndpoint": {
+ "nodeId": {
+ "id": 20252839879148
+ },
+ "slotId": {
+ "m_id": "{8F69FA2E-28D8-4DF1-A4B5-AEF3985095C5}"
+ }
+ },
+ "targetEndpoint": {
+ "nodeId": {
+ "id": 20248544911852
+ },
+ "slotId": {
+ "m_id": "{D387C800-352B-4B01-8765-4F4B40DF45CB}"
+ }
+ }
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 20308674453996
+ },
+ "Name": "srcEndpoint=(Extract Properties: Out), destEndpoint=(Not Equal To (!=): In)",
+ "Components": {
+ "Component_[14597948098713219792]": {
+ "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+ "Id": 14597948098713219792,
+ "sourceEndpoint": {
+ "nodeId": {
+ "id": 20248544911852
+ },
+ "slotId": {
+ "m_id": "{C69C098D-D667-4DC7-85E5-AFD119727D94}"
+ }
+ },
+ "targetEndpoint": {
+ "nodeId": {
+ "id": 20257134846444
+ },
+ "slotId": {
+ "m_id": "{AE7E453C-15DE-47D2-954A-05C3895B7AC6}"
+ }
+ }
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 20312969421292
+ },
+ "Name": "srcEndpoint=(Extract Properties: FwdBack: Number), destEndpoint=(Not Equal To (!=): Value A)",
+ "Components": {
+ "Component_[14915522756837814768]": {
+ "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+ "Id": 14915522756837814768,
+ "sourceEndpoint": {
+ "nodeId": {
+ "id": 20248544911852
+ },
+ "slotId": {
+ "m_id": "{0C03D491-DE25-46C2-BF09-14769FA49FDB}"
+ }
+ },
+ "targetEndpoint": {
+ "nodeId": {
+ "id": 20257134846444
+ },
+ "slotId": {
+ "m_id": "{57EBC15B-452E-49B3-8BD3-4FBBB07F1F14}"
+ }
+ }
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 20317264388588
+ },
+ "Name": "srcEndpoint=(Extract Properties: Out), destEndpoint=(Not Equal To (!=): In)",
+ "Components": {
+ "Component_[6510282773353837676]": {
+ "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+ "Id": 6510282773353837676,
+ "sourceEndpoint": {
+ "nodeId": {
+ "id": 20248544911852
+ },
+ "slotId": {
+ "m_id": "{C69C098D-D667-4DC7-85E5-AFD119727D94}"
+ }
+ },
+ "targetEndpoint": {
+ "nodeId": {
+ "id": 20265724781036
+ },
+ "slotId": {
+ "m_id": "{AE7E453C-15DE-47D2-954A-05C3895B7AC6}"
+ }
+ }
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 20321559355884
+ },
+ "Name": "srcEndpoint=(Extract Properties: LeftRight: Number), destEndpoint=(Not Equal To (!=): Value A)",
+ "Components": {
+ "Component_[16150645152204311425]": {
+ "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+ "Id": 16150645152204311425,
+ "sourceEndpoint": {
+ "nodeId": {
+ "id": 20248544911852
+ },
+ "slotId": {
+ "m_id": "{4C13F9EF-60BF-4AD1-8FA9-66F46455411C}"
+ }
+ },
+ "targetEndpoint": {
+ "nodeId": {
+ "id": 20265724781036
+ },
+ "slotId": {
+ "m_id": "{57EBC15B-452E-49B3-8BD3-4FBBB07F1F14}"
+ }
+ }
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 20325854323180
+ },
+ "Name": "srcEndpoint=(Not Equal To (!=): True), destEndpoint=(Print: In)",
+ "Components": {
+ "Component_[3322355580364572639]": {
+ "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+ "Id": 3322355580364572639,
+ "sourceEndpoint": {
+ "nodeId": {
+ "id": 20257134846444
+ },
+ "slotId": {
+ "m_id": "{AC364E17-A9A1-42DB-A29D-7B2D666E4287}"
+ }
+ },
+ "targetEndpoint": {
+ "nodeId": {
+ "id": 20270019748332
+ },
+ "slotId": {
+ "m_id": "{733AA75D-022C-45E9-9D0F-3EF9A1633ADC}"
+ }
+ }
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 20330149290476
+ },
+ "Name": "srcEndpoint=(Not Equal To (!=): True), destEndpoint=(Print: In)",
+ "Components": {
+ "Component_[1975626970668030308]": {
+ "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+ "Id": 1975626970668030308,
+ "sourceEndpoint": {
+ "nodeId": {
+ "id": 20265724781036
+ },
+ "slotId": {
+ "m_id": "{AC364E17-A9A1-42DB-A29D-7B2D666E4287}"
+ }
+ },
+ "targetEndpoint": {
+ "nodeId": {
+ "id": 20274314715628
+ },
+ "slotId": {
+ "m_id": "{733AA75D-022C-45E9-9D0F-3EF9A1633ADC}"
+ }
+ }
+ }
+ }
+ }
+ ]
+ },
+ "m_assetType": "{3E2AC8CD-713F-453E-967F-29517F331784}",
+ "versionData": {
+ "_grammarVersion": 1,
+ "_runtimeVersion": 1,
+ "_fileVersion": 1
+ },
+ "m_variableCounter": 2,
+ "GraphCanvasData": [
+ {
+ "Key": {
+ "id": 20239954977260
+ },
+ "Value": {
+ "ComponentData": {
+ "{5F84B500-8C45-40D1-8EFC-A5306B241444}": {
+ "$type": "SceneComponentSaveData",
+ "ViewParams": {
+ "Scale": 1.0097068678919363,
+ "AnchorX": 1086.4539794921875,
+ "AnchorY": 198.07728576660156
+ }
+ }
+ }
+ }
+ },
+ {
+ "Key": {
+ "id": 20244249944556
+ },
+ "Value": {
+ "ComponentData": {
+ "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": {
+ "$type": "NodeSaveData"
+ },
+ "{328FF15C-C302-458F-A43D-E1794DE0904E}": {
+ "$type": "GeneralNodeTitleComponentSaveData",
+ "PaletteOverride": "MethodNodeTitlePalette"
+ },
+ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
+ "$type": "GeometrySaveData",
+ "Position": [
+ 740.0,
+ 100.0
+ ]
+ },
+ "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
+ "$type": "StylingComponentSaveData",
+ "SubStyle": ".method"
+ },
+ "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
+ "$type": "PersistentIdComponentSaveData",
+ "PersistentId": "{7A7C96CB-4B5A-48DD-A0AD-0094A113549B}"
+ }
+ }
+ }
+ },
+ {
+ "Key": {
+ "id": 20248544911852
+ },
+ "Value": {
+ "ComponentData": {
+ "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": {
+ "$type": "NodeSaveData"
+ },
+ "{328FF15C-C302-458F-A43D-E1794DE0904E}": {
+ "$type": "GeneralNodeTitleComponentSaveData",
+ "PaletteOverride": "DefaultNodeTitlePalette"
+ },
+ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
+ "$type": "GeometrySaveData",
+ "Position": [
+ 740.0,
+ 320.0
+ ]
+ },
+ "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
+ "$type": "StylingComponentSaveData"
+ },
+ "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
+ "$type": "PersistentIdComponentSaveData",
+ "PersistentId": "{ED8F0B6C-0811-4FB7-AEE8-B71DB87FABF0}"
+ }
+ }
+ }
+ },
+ {
+ "Key": {
+ "id": 20252839879148
+ },
+ "Value": {
+ "ComponentData": {
+ "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": {
+ "$type": "NodeSaveData"
+ },
+ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
+ "$type": "GeometrySaveData",
+ "Position": [
+ 160.0,
+ 100.0
+ ]
+ },
+ "{9E81C95F-89C0-4476-8E82-63CCC4E52E04}": {
+ "$type": "EBusHandlerNodeDescriptorSaveData",
+ "EventIds": [
+ {
+ "Value": 78438309
+ },
+ {
+ "Value": 1793364217
+ }
+ ]
+ },
+ "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
+ "$type": "StylingComponentSaveData"
+ },
+ "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
+ "$type": "PersistentIdComponentSaveData",
+ "PersistentId": "{BB97BA3E-F2AB-4078-9BB3-2A0F31DC771C}"
+ }
+ }
+ }
+ },
+ {
+ "Key": {
+ "id": 20257134846444
+ },
+ "Value": {
+ "ComponentData": {
+ "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": {
+ "$type": "NodeSaveData"
+ },
+ "{328FF15C-C302-458F-A43D-E1794DE0904E}": {
+ "$type": "GeneralNodeTitleComponentSaveData",
+ "PaletteOverride": "MathNodeTitlePalette"
+ },
+ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
+ "$type": "GeometrySaveData",
+ "Position": [
+ 1040.0,
+ 320.0
+ ]
+ },
+ "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
+ "$type": "StylingComponentSaveData"
+ },
+ "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
+ "$type": "PersistentIdComponentSaveData",
+ "PersistentId": "{71AB4748-41F4-4FEA-874C-F54037236F31}"
+ }
+ }
+ }
+ },
+ {
+ "Key": {
+ "id": 20261429813740
+ },
+ "Value": {
+ "ComponentData": {
+ "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": {
+ "$type": "NodeSaveData"
+ },
+ "{328FF15C-C302-458F-A43D-E1794DE0904E}": {
+ "$type": "GeneralNodeTitleComponentSaveData",
+ "PaletteOverride": "StringNodeTitlePalette"
+ },
+ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
+ "$type": "GeometrySaveData",
+ "Position": [
+ 740.0,
+ -100.0
+ ]
+ },
+ "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
+ "$type": "StylingComponentSaveData"
+ },
+ "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
+ "$type": "PersistentIdComponentSaveData",
+ "PersistentId": "{26E363EE-F35A-4096-88EF-DF907A809894}"
+ }
+ }
+ }
+ },
+ {
+ "Key": {
+ "id": 20265724781036
+ },
+ "Value": {
+ "ComponentData": {
+ "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": {
+ "$type": "NodeSaveData"
+ },
+ "{328FF15C-C302-458F-A43D-E1794DE0904E}": {
+ "$type": "GeneralNodeTitleComponentSaveData",
+ "PaletteOverride": "MathNodeTitlePalette"
+ },
+ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
+ "$type": "GeometrySaveData",
+ "Position": [
+ 1040.0,
+ 520.0
+ ]
+ },
+ "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
+ "$type": "StylingComponentSaveData"
+ },
+ "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
+ "$type": "PersistentIdComponentSaveData",
+ "PersistentId": "{F64E211C-8DDD-4223-9235-8DB802A017CB}"
+ }
+ }
+ }
+ },
+ {
+ "Key": {
+ "id": 20270019748332
+ },
+ "Value": {
+ "ComponentData": {
+ "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": {
+ "$type": "NodeSaveData"
+ },
+ "{328FF15C-C302-458F-A43D-E1794DE0904E}": {
+ "$type": "GeneralNodeTitleComponentSaveData",
+ "PaletteOverride": "StringNodeTitlePalette"
+ },
+ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
+ "$type": "GeometrySaveData",
+ "Position": [
+ 1480.0,
+ 320.0
+ ]
+ },
+ "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
+ "$type": "StylingComponentSaveData"
+ },
+ "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
+ "$type": "PersistentIdComponentSaveData",
+ "PersistentId": "{9161B9FA-8493-479D-BE35-10D92644D5C0}"
+ }
+ }
+ }
+ },
+ {
+ "Key": {
+ "id": 20274314715628
+ },
+ "Value": {
+ "ComponentData": {
+ "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": {
+ "$type": "NodeSaveData"
+ },
+ "{328FF15C-C302-458F-A43D-E1794DE0904E}": {
+ "$type": "GeneralNodeTitleComponentSaveData",
+ "PaletteOverride": "StringNodeTitlePalette"
+ },
+ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
+ "$type": "GeometrySaveData",
+ "Position": [
+ 1480.0,
+ 520.0
+ ]
+ },
+ "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
+ "$type": "StylingComponentSaveData"
+ },
+ "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
+ "$type": "PersistentIdComponentSaveData",
+ "PersistentId": "{1AF129A6-751C-4FC0-805E-65AC2D4B6D3D}"
+ }
+ }
+ }
+ },
+ {
+ "Key": {
+ "id": 20278609682924
+ },
+ "Value": {
+ "ComponentData": {
+ "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": {
+ "$type": "NodeSaveData"
+ },
+ "{328FF15C-C302-458F-A43D-E1794DE0904E}": {
+ "$type": "GeneralNodeTitleComponentSaveData",
+ "PaletteOverride": "StringNodeTitlePalette"
+ },
+ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
+ "$type": "GeometrySaveData",
+ "Position": [
+ 740.0,
+ 740.0
+ ]
+ },
+ "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
+ "$type": "StylingComponentSaveData"
+ },
+ "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
+ "$type": "PersistentIdComponentSaveData",
+ "PersistentId": "{F7407B9B-C302-4B50-BFB0-D1208DF1D5AC}"
+ }
+ }
+ }
+ }
+ ],
+ "StatisticsHelper": {
+ "InstanceCounter": [
+ {
+ "Key": 5842116704436214676,
+ "Value": 1
+ },
+ {
+ "Key": 5842116706017748280,
+ "Value": 1
+ },
+ {
+ "Key": 7441100700879769985,
+ "Value": 2
+ },
+ {
+ "Key": 10684225535275896474,
+ "Value": 4
+ },
+ {
+ "Key": 10715014621082578046,
+ "Value": 1
+ },
+ {
+ "Key": 14285852892804039565,
+ "Value": 1
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/AutomatedTesting/Levels/Multiplayer/AutoComponent_NetworkInput/Player.prefab b/AutomatedTesting/Levels/Multiplayer/AutoComponent_NetworkInput/Player.prefab
new file mode 100644
index 0000000000..72fce2d291
--- /dev/null
+++ b/AutomatedTesting/Levels/Multiplayer/AutoComponent_NetworkInput/Player.prefab
@@ -0,0 +1,196 @@
+{
+ "ContainerEntity": {
+ "Id": "ContainerEntity",
+ "Name": "Player",
+ "Components": {
+ "Component_[10591405285626521927]": {
+ "$type": "EditorLockComponent",
+ "Id": 10591405285626521927
+ },
+ "Component_[10962884071806037909]": {
+ "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+ "Id": 10962884071806037909,
+ "Parent Entity": ""
+ },
+ "Component_[14883697413991420474]": {
+ "$type": "EditorOnlyEntityComponent",
+ "Id": 14883697413991420474
+ },
+ "Component_[1497622121956209837]": {
+ "$type": "EditorVisibilityComponent",
+ "Id": 1497622121956209837
+ },
+ "Component_[16429314387772079347]": {
+ "$type": "EditorEntityIconComponent",
+ "Id": 16429314387772079347
+ },
+ "Component_[16665294301093657382]": {
+ "$type": "EditorDisabledCompositionComponent",
+ "Id": 16665294301093657382
+ },
+ "Component_[1706666252612720326]": {
+ "$type": "EditorInspectorComponent",
+ "Id": 1706666252612720326
+ },
+ "Component_[4216896820422195198]": {
+ "$type": "EditorPendingCompositionComponent",
+ "Id": 4216896820422195198
+ },
+ "Component_[4540089401187370610]": {
+ "$type": "EditorPrefabComponent",
+ "Id": 4540089401187370610
+ },
+ "Component_[6378576046601184103]": {
+ "$type": "EditorEntitySortComponent",
+ "Id": 6378576046601184103
+ },
+ "Component_[7745420981568587180]": {
+ "$type": "SelectionComponent",
+ "Id": 7745420981568587180
+ }
+ }
+ },
+ "Entities": {
+ "Entity_[1028733630164]": {
+ "Id": "Entity_[1028733630164]",
+ "Name": "Player",
+ "Components": {
+ "Component_[12294726333564087591]": {
+ "$type": "SelectionComponent",
+ "Id": 12294726333564087591
+ },
+ "Component_[13587084088242540786]": {
+ "$type": "EditorInspectorComponent",
+ "Id": 13587084088242540786,
+ "ComponentOrderEntryArray": [
+ {
+ "ComponentId": 6819443882832501114
+ },
+ {
+ "ComponentId": 5577505593558922067,
+ "SortIndex": 1
+ },
+ {
+ "ComponentId": 2069554278758260821,
+ "SortIndex": 2
+ },
+ {
+ "ComponentId": 16508969730014660362,
+ "SortIndex": 3
+ },
+ {
+ "ComponentId": 8125406152674415588,
+ "SortIndex": 4
+ },
+ {
+ "ComponentId": 4337571454344109612,
+ "SortIndex": 5
+ },
+ {
+ "ComponentId": 16457408099527309065,
+ "SortIndex": 6
+ }
+ ]
+ },
+ "Component_[14335168881008289852]": {
+ "$type": "EditorEntitySortComponent",
+ "Id": 14335168881008289852
+ },
+ "Component_[16308902899170829847]": {
+ "$type": "EditorVisibilityComponent",
+ "Id": 16308902899170829847
+ },
+ "Component_[16457408099527309065]": {
+ "$type": "GenericComponentWrapper",
+ "Id": 16457408099527309065,
+ "m_template": {
+ "$type": "Multiplayer::NetworkTransformComponent"
+ }
+ },
+ "Component_[16508969730014660362]": {
+ "$type": "GenericComponentWrapper",
+ "Id": 16508969730014660362,
+ "m_template": {
+ "$type": "AutomatedTesting::NetworkTestPlayerComponent"
+ }
+ },
+ "Component_[16541569566865026527]": {
+ "$type": "EditorOnlyEntityComponent",
+ "Id": 16541569566865026527
+ },
+ "Component_[2002761223483048905]": {
+ "$type": "EditorPendingCompositionComponent",
+ "Id": 2002761223483048905
+ },
+ "Component_[2069554278758260821]": {
+ "$type": "EditorScriptCanvasComponent",
+ "Id": 2069554278758260821,
+ "m_name": "AutoComponent_NetworkInput",
+ "m_assetHolder": {
+ "m_asset": {
+ "assetId": {
+ "guid": "{D079F53D-CCAA-5C98-8E0C-B485B7821747}"
+ },
+ "assetHint": "levels/multiplayer/autocomponent_networkinput/autocomponent_networkinput.scriptcanvas"
+ }
+ },
+ "runtimeDataIsValid": true,
+ "runtimeDataOverrides": {
+ "source": {
+ "assetId": {
+ "guid": "{D079F53D-CCAA-5C98-8E0C-B485B7821747}"
+ },
+ "assetHint": "levels/multiplayer/autocomponent_networkinput/autocomponent_networkinput.scriptcanvas"
+ }
+ }
+ },
+ "Component_[4337571454344109612]": {
+ "$type": "GenericComponentWrapper",
+ "Id": 4337571454344109612,
+ "m_template": {
+ "$type": "NetBindComponent"
+ }
+ },
+ "Component_[477591477979440744]": {
+ "$type": "EditorLockComponent",
+ "Id": 477591477979440744
+ },
+ "Component_[5577505593558922067]": {
+ "$type": "AZ::Render::EditorMeshComponent",
+ "Id": 5577505593558922067,
+ "Controller": {
+ "Configuration": {
+ "ModelAsset": {
+ "assetId": {
+ "guid": "{6DE0E9A8-A1C7-5D0F-9407-4E627C1F223C}",
+ "subId": 284780167
+ },
+ "assetHint": "models/sphere.azmodel"
+ }
+ }
+ }
+ },
+ "Component_[5828214869455694702]": {
+ "$type": "EditorDisabledCompositionComponent",
+ "Id": 5828214869455694702
+ },
+ "Component_[6819443882832501114]": {
+ "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+ "Id": 6819443882832501114,
+ "Parent Entity": "ContainerEntity"
+ },
+ "Component_[8125406152674415588]": {
+ "$type": "GenericComponentWrapper",
+ "Id": 8125406152674415588,
+ "m_template": {
+ "$type": "Multiplayer::LocalPredictionPlayerInputComponent"
+ }
+ },
+ "Component_[8838623765985560328]": {
+ "$type": "EditorEntityIconComponent",
+ "Id": 8838623765985560328
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/AutomatedTesting/Levels/Multiplayer/AutoComponent_NetworkInput/tags.txt b/AutomatedTesting/Levels/Multiplayer/AutoComponent_NetworkInput/tags.txt
new file mode 100644
index 0000000000..0d6c1880e7
--- /dev/null
+++ b/AutomatedTesting/Levels/Multiplayer/AutoComponent_NetworkInput/tags.txt
@@ -0,0 +1,12 @@
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0
+0,0,0,0,0,0
diff --git a/Gems/LyShine/Code/CMakeLists.txt b/Gems/LyShine/Code/CMakeLists.txt
index f8c2ebfd07..77aaa681e0 100644
--- a/Gems/LyShine/Code/CMakeLists.txt
+++ b/Gems/LyShine/Code/CMakeLists.txt
@@ -52,8 +52,9 @@ ly_add_target(
Gem::TextureAtlas
)
-# by default, load the above "Gem::LyShine" module in Client applications:
+# by default, load the above "Gem::LyShine" module in Client and Server applications:
ly_create_alias(NAME LyShine.Clients NAMESPACE Gem TARGETS Gem::LyShine)
+ly_create_alias(NAME LyShine.Servers NAMESPACE Gem TARGETS Gem::LyShine)
if (PAL_TRAIT_BUILD_HOST_TOOLS)
ly_add_target(
diff --git a/Gems/Multiplayer/Code/CMakeLists.txt b/Gems/Multiplayer/Code/CMakeLists.txt
index b971e6a2ce..559fa23553 100644
--- a/Gems/Multiplayer/Code/CMakeLists.txt
+++ b/Gems/Multiplayer/Code/CMakeLists.txt
@@ -149,6 +149,8 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS)
AZ::AzFramework
AZ::AzNetworking
AZ::AzToolsFramework
+ Gem::Atom_RPI.Public
+ Gem::Atom_RHI.Reflect
Gem::Multiplayer.Static
Gem::Multiplayer.Builders
)
diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Editor/MultiplayerPythonEditorEventsBus.h b/Gems/Multiplayer/Code/Include/Multiplayer/Editor/MultiplayerPythonEditorEventsBus.h
new file mode 100644
index 0000000000..82b63d94f0
--- /dev/null
+++ b/Gems/Multiplayer/Code/Include/Multiplayer/Editor/MultiplayerPythonEditorEventsBus.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+#pragma once
+
+#include
+
+namespace Multiplayer
+{
+ /**
+ * This bus can be used to send commands to the editor.
+ */
+ class MultiplayerEditorLayerPythonRequests
+ : public AZ::ComponentBus
+ {
+ public:
+ /*
+ * Enters the editor game mode and launches/connects to the server launcher.
+ */
+ virtual void EnterGameMode() = 0;
+
+ /*
+ * Queries if the Editor is in game mode, the editor-server has finished connecting, and the default network player has spawned.
+ */
+ virtual bool IsInGameMode() = 0;
+ };
+ using MultiplayerEditorLayerPythonRequestBus = AZ::EBus;
+}
diff --git a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.cpp b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.cpp
index d2b0ca7095..3c3c4f0664 100644
--- a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.cpp
+++ b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.cpp
@@ -26,6 +26,7 @@ namespace Multiplayer
using namespace AzNetworking;
AZ_CVAR(bool, editorsv_isDedicated, false, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Whether to init as a server expecting data from an Editor. Do not modify unless you're sure of what you're doing.");
+ AZ_CVAR(uint16_t, editorsv_port, DefaultServerEditorPort, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The port that the multiplayer editor gem will bind to for traffic.");
MultiplayerEditorConnection::MultiplayerEditorConnection()
: m_byteStream(&m_buffer)
@@ -33,33 +34,37 @@ namespace Multiplayer
m_networkEditorInterface = AZ::Interface::Get()->CreateNetworkInterface(
AZ::Name(MpEditorInterfaceName), ProtocolType::Tcp, TrustZone::ExternalClientToServer, *this);
m_networkEditorInterface->SetTimeoutMs(AZ::TimeMs{ 0 }); // Disable timeouts on this network interface
- if (editorsv_isDedicated)
+ ActivateDedicatedEditorServer();
+ }
+
+ void MultiplayerEditorConnection::ActivateDedicatedEditorServer() const
+ {
+ if (m_isActivated || !editorsv_isDedicated)
{
- uint16_t editorsv_port = DefaultServerEditorPort;
- const auto console = AZ::Interface::Get();
- if (console->GetCvarValue("editorsv_port", editorsv_port) != AZ::GetValueResult::Success)
- {
- AZ_Assert( false,
- "MultiplayerEditorConnection failed! Could not find the editorsv_port cvar; we may not be able to connect to the editor's port! Please update this code to use a valid cvar!")
- }
+ return;
+ }
+ m_isActivated = true;
+
+ AZ_Assert(m_networkEditorInterface, "MP Editor Network Interface was unregistered before Editor Server could start listening.")
- AZ_Assert(m_networkEditorInterface, "MP Editor Network Interface was unregistered before Editor Server could start listening.")
+ // Check if there's already an Editor out there waiting to connect
+ const ConnectionId editorServerToEditorConnectionId =
+ m_networkEditorInterface->Connect(IpAddress(LocalHost.data(), editorsv_port, ProtocolType::Tcp));
- // Check if there's already an Editor out there waiting to connect
- const ConnectionId editorServerToEditorConnectionId = m_networkEditorInterface->Connect(IpAddress(LocalHost.data(), editorsv_port, ProtocolType::Tcp));
-
- // If there wasn't an Editor waiting for this server to start, then assume this is an editor-server launched by hand... listen and wait for the editor to request a connection
- if (editorServerToEditorConnectionId == InvalidConnectionId)
- {
- m_networkEditorInterface->Listen(editorsv_port);
- }
- else
- {
- m_networkEditorInterface->SendReliablePacket(editorServerToEditorConnectionId, MultiplayerEditorPackets::EditorServerReadyForLevelData());
- }
+ // If there wasn't an Editor waiting for this server to start, then assume this is an editor-server launched by hand... listen
+ // and wait for the editor to request a connection
+ if (editorServerToEditorConnectionId == InvalidConnectionId)
+ {
+ m_networkEditorInterface->Listen(editorsv_port);
+ AZ_Printf("MultiplayerEditorConnection", "Editor-server activation did not find an editor in game-mode willing to connect; we'll instead wait and listen for an editor trying to connect to us.")
+ }
+ else
+ {
+ m_networkEditorInterface->SendReliablePacket(editorServerToEditorConnectionId, MultiplayerEditorPackets::EditorServerReadyForLevelData());
+ AZ_Printf("MultiplayerEditorConnection", "Editor-server activation has found and connected to the editor.")
}
}
-
+
bool MultiplayerEditorConnection::HandleRequest
(
[[maybe_unused]] AzNetworking::IConnection* connection,
@@ -136,7 +141,7 @@ namespace Multiplayer
networkInterface->Listen(sv_port);
- AZLOG_INFO("Editor Server completed asset receive, responding to Editor...");
+ AZLOG_INFO("Editor Server completed receiving the editor's level assets, responding to Editor...");
return connection->SendReliablePacket(MultiplayerEditorPackets::EditorServerReady());
}
@@ -180,8 +185,14 @@ namespace Multiplayer
}
// Connect the Editor to the editor server for Multiplayer simulation
- AZ::Interface::Get()->Connect(editorsv_serveraddr.c_str(), sv_port);
-
+ if (AZ::Interface::Get()->Connect(editorsv_serveraddr.c_str(), sv_port))
+ {
+ AZ_Printf("MultiplayerEditorConnection", "Editor-server ready. Editor has successfully connected to the editor-server's network simulation.")
+ }
+ else
+ {
+ AZ_Warning("MultiplayerEditorConnection", false, "MultiplayerEditorConnection::HandleRequest for EditorServerReady failed! Connecting to the editor-server's network simulation failed.")
+ }
return true;
}
diff --git a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.h b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.h
index 3828d751f0..f6510896fe 100644
--- a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.h
+++ b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.h
@@ -45,9 +45,11 @@ namespace Multiplayer
//! @}
private:
+ void ActivateDedicatedEditorServer() const;
AzNetworking::INetworkInterface* m_networkEditorInterface = nullptr;
AZStd::vector m_buffer;
AZ::IO::ByteContainerStream> m_byteStream;
+ mutable bool m_isActivated = false;
};
}
diff --git a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorGem.cpp b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorGem.cpp
index 65d1f43a64..c922a8683f 100644
--- a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorGem.cpp
+++ b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorGem.cpp
@@ -25,6 +25,7 @@ namespace Multiplayer
m_descriptors.end(),
{
MultiplayerEditorSystemComponent::CreateDescriptor(),
+ PythonEditorFuncs::CreateDescriptor()
});
}
diff --git a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp
index 2651981bce..11aca101b3 100644
--- a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp
+++ b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp
@@ -12,6 +12,7 @@
#include
#include
+#include
#include
#include
@@ -23,6 +24,7 @@
#include
#include
#include
+#include
namespace Multiplayer
{
@@ -35,8 +37,47 @@ namespace Multiplayer
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");
AZ_CVAR(AZ::CVarFixedString, editorsv_serveraddr, AZ::CVarFixedString(LocalHost), nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The address of the server to connect to");
- AZ_CVAR(uint16_t, editorsv_port, DefaultServerEditorPort, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The port that the multiplayer editor gem will bind to for traffic");
+ AZ_CVAR(AZ::CVarFixedString, editorsv_rhi_override, "", nullptr, AZ::ConsoleFunctorFlags::DontReplicate,
+ "Override the default rendering hardware interface (rhi) when launching the Editor server. For example, you may be running an Editor using 'dx12', but want to launch a headless server using 'null'. If empty the server will launch using the same rhi as the Editor.");
+ AZ_CVAR_EXTERNED(uint16_t, editorsv_port);
+
+ //////////////////////////////////////////////////////////////////////////
+ void PyEnterGameMode()
+ {
+ editorsv_enabled = true;
+ editorsv_launch = true;
+ AzToolsFramework::EditorLayerPythonRequestBus::Broadcast(&AzToolsFramework::EditorLayerPythonRequestBus::Events::EnterGameMode);
+ }
+ bool PyIsInGameMode()
+ {
+ // If the network entity manager is tracking at least 1 entity then the editor has connected and the autonomous player exists and is being replicated.
+ if (const INetworkEntityManager* networkEntityManager = AZ::Interface::Get())
+ {
+ return networkEntityManager->GetEntityCount() > 0;
+ }
+
+ AZ_Warning("MultiplayerEditorSystemComponent", false, "PyIsInGameMode returning false; NetworkEntityManager has not been created yet.")
+ return false;
+ }
+
+ void PythonEditorFuncs::Reflect(AZ::ReflectContext* context)
+ {
+ if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context))
+ {
+ // This will create static python methods in the 'azlmbr.multiplayer' module
+ // Note: The methods will be prefixed with the class name, PythonEditorFuncs
+ // Example Hydra Python: azlmbr.multiplayer.PythonEditorFuncs_enter_game_mode()
+ behaviorContext->Class()
+ ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
+ ->Attribute(AZ::Script::Attributes::Module, "multiplayer")
+ ->Method("enter_game_mode", PyEnterGameMode, nullptr, "Enters the editor game mode and launches/connects to the server launcher.")
+ ->Method("is_in_game_mode", PyIsInGameMode, nullptr, "Queries if it's in the game mode and the server has finished connecting and the default network player has spawned.")
+ ;
+
+ }
+ }
+
void MultiplayerEditorSystemComponent::Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serializeContext = azrtti_cast(context))
@@ -44,6 +85,18 @@ namespace Multiplayer
serializeContext->Class()
->Version(1);
}
+
+ // Reflect Python Editor Functions
+ if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context))
+ {
+ // This will add the MultiplayerPythonEditorBus into the 'azlmbr.multiplayer' module
+ behaviorContext->EBus("MultiplayerPythonEditorBus")
+ ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
+ ->Attribute(AZ::Script::Attributes::Module, "multiplayer")
+ ->Event("EnterGameMode", &MultiplayerEditorLayerPythonRequestBus::Events::EnterGameMode)
+ ->Event("IsInGameMode", &MultiplayerEditorLayerPythonRequestBus::Events::IsInGameMode)
+ ;
+ }
}
void MultiplayerEditorSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
@@ -147,11 +200,21 @@ namespace Multiplayer
// Start the configured server if it's available
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
+
+ // Open the server launcher using the same rhi as the editor (or launch with the override rhi)
+ AZ::Name server_rhi = AZ::RPI::RPISystemInterface::Get()->GetRenderApiName();
+ if (!static_cast(editorsv_rhi_override).empty())
+ {
+ server_rhi = static_cast(editorsv_rhi_override);
+ }
+
processLaunchInfo.m_commandlineParameters = AZStd::string::format(
- R"("%s" --project-path "%s" --editorsv_isDedicated true --sv_defaultPlayerSpawnAsset "%s")",
+ R"("%s" --project-path "%s" --editorsv_isDedicated true --sv_defaultPlayerSpawnAsset "%s" --rhi "%s")",
serverPath.c_str(),
AZ::Utils::GetProjectPath().c_str(),
- static_cast(sv_defaultPlayerSpawnAsset).c_str());
+ static_cast(sv_defaultPlayerSpawnAsset).c_str(),
+ server_rhi.GetCStr()
+ );
processLaunchInfo.m_showWindow = true;
processLaunchInfo.m_processPriority = AzFramework::ProcessPriority::PROCESSPRIORITY_NORMAL;
@@ -159,6 +222,10 @@ namespace Multiplayer
AzFramework::ProcessWatcher* outProcess = AzFramework::ProcessWatcher::LaunchProcess(
processLaunchInfo, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_NONE);
+ AZ_Error(
+ "MultiplayerEditor", processLaunchInfo.m_launchResult != AzFramework::ProcessLauncher::ProcessLaunchResult::PLR_MissingFile,
+ "LaunchEditorServer failed! The ServerLauncher binary is missing! (%s) Please build server launcher.", serverPath.c_str())
+
return outProcess;
}
@@ -231,7 +298,7 @@ namespace Multiplayer
"Editor multiplayer game-mode failed! Could not connect to an editor-server. editorsv_launch is false so we're assuming you're running your own editor-server at editorsv_serveraddr(%s) on editorsv_port(%i). "
"Either set editorsv_launch=true so the editor launches an editor-server for you, or launch your own editor-server by hand before entering game-mode. Remember editor-servers must use editorsv_isDedicated=true.",
remoteAddress.c_str(),
- static_cast < uint16_t>(editorsv_port))
+ static_cast(editorsv_port))
return;
}
@@ -261,6 +328,8 @@ namespace Multiplayer
return;
}
+ AZ_Printf("MultiplayerEditor", "Editor is sending the editor-server the level data packet.")
+
const AZStd::vector>& assetData = prefabEditorEntityOwnershipInterface->GetPlayInEditorAssetData();
AZStd::vector buffer;
@@ -311,4 +380,13 @@ namespace Multiplayer
}
}
+ void MultiplayerEditorSystemComponent::EnterGameMode()
+ {
+ PyEnterGameMode();
+ }
+
+ bool MultiplayerEditorSystemComponent::IsInGameMode()
+ {
+ return PyIsInGameMode();
+ }
}
diff --git a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.h b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.h
index a008afc873..77b41a5dc4 100644
--- a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.h
+++ b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.h
@@ -10,6 +10,7 @@
#include
#include
+#include
#include
#include
@@ -29,9 +30,24 @@ namespace AzNetworking
namespace Multiplayer
{
+ //! A component to reflect scriptable commands for the Editor
+ class PythonEditorFuncs : public AZ::Component
+ {
+ public:
+ AZ_COMPONENT(PythonEditorFuncs, "{22AEEA59-94E6-4033-B67D-7C8FBB84DF0D}")
+
+ SANDBOX_API static void Reflect(AZ::ReflectContext* context);
+
+ // AZ::Component ...
+ void Activate() override {}
+ void Deactivate() override {}
+ };
+
+
//! Multiplayer system component wraps the bridging logic between the game and transport layer.
class MultiplayerEditorSystemComponent final
: public AZ::Component
+ , public MultiplayerEditorLayerPythonRequestBus::Handler
, private AzFramework::GameEntityContextEventBus::Handler
, private AzToolsFramework::EditorEvents::Bus::Handler
, private IEditorNotifyListener
@@ -62,6 +78,12 @@ namespace Multiplayer
void NotifyRegisterViews() override;
//! @}
+ //! MultiplayerEditorLayerPythonRequestBus::Handler overrides.
+ //! @{
+ void EnterGameMode() override;
+ bool IsInGameMode() override;
+ //! @}
+
private:
//! EditorEvents::Handler overrides
//! @{
diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp
index fdd7602f71..6df5e4611f 100644
--- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp
+++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp
@@ -719,11 +719,6 @@ namespace Multiplayer
void MultiplayerSystemComponent::OnConnect(AzNetworking::IConnection* connection)
{
- MultiplayerAgentDatum datum;
- datum.m_id = connection->GetConnectionId();
- datum.m_isInvited = false;
- datum.m_agentType = MultiplayerAgentType::Client;
-
AZStd::string providerTicket;
if (connection->GetConnectionRole() == ConnectionRole::Connector)
{
@@ -737,7 +732,12 @@ namespace Multiplayer
}
else
{
- AZLOG_INFO("New incoming connection from remote address: %s", connection->GetRemoteAddress().GetString().c_str());
+ AZLOG_INFO("New incoming connection from remote address: %s", connection->GetRemoteAddress().GetString().c_str())
+
+ MultiplayerAgentDatum datum;
+ datum.m_id = connection->GetConnectionId();
+ datum.m_isInvited = false;
+ datum.m_agentType = MultiplayerAgentType::Client;
m_connectionAcquiredEvent.Signal(datum);
}
@@ -771,15 +771,14 @@ namespace Multiplayer
AZLOG_INFO("%s from remote address %s due to %s", endpointString, connection->GetRemoteAddress().GetString().c_str(), reasonString.c_str());
// The client is disconnecting
- if (GetAgentType() == MultiplayerAgentType::Client)
+ if (m_agentType == MultiplayerAgentType::Client)
{
AZ_Assert(connection->GetConnectionRole() == ConnectionRole::Connector, "Client connection role should only ever be Connector");
m_clientDisconnectedEvent.Signal();
}
-
- // Signal to session management that a user has left the server
- if (m_agentType == MultiplayerAgentType::DedicatedServer || m_agentType == MultiplayerAgentType::ClientServer)
+ else if (m_agentType == MultiplayerAgentType::DedicatedServer || m_agentType == MultiplayerAgentType::ClientServer)
{
+ // Signal to session management that a user has left the server
if (AZ::Interface::Get() != nullptr &&
connection->GetConnectionRole() == ConnectionRole::Acceptor)
{
@@ -1130,7 +1129,10 @@ namespace Multiplayer
return m_networkEntityManager.GetNetworkEntityTracker()->Get(node->second);
}
- PrefabEntityId playerPrefabEntityId(AZ::Name(static_cast(sv_defaultPlayerSpawnAsset).c_str()));
+ // make sure the player prefab path is lowercase (how it's stored in the cache folder)
+ auto sv_defaultPlayerSpawnAssetLowerCase = static_cast(sv_defaultPlayerSpawnAsset);
+ AZStd::to_lower(sv_defaultPlayerSpawnAssetLowerCase.begin(), sv_defaultPlayerSpawnAssetLowerCase.end());
+ PrefabEntityId playerPrefabEntityId(AZ::Name(static_cast(sv_defaultPlayerSpawnAssetLowerCase).c_str()));
INetworkEntityManager::EntityList entityList = m_networkEntityManager.CreateEntitiesImmediate(playerPrefabEntityId, NetEntityRole::Authority, AZ::Transform::CreateIdentity(), Multiplayer::AutoActivate::DoNotActivate);
for (NetworkEntityHandle subEntity : entityList)
diff --git a/Gems/Multiplayer/Code/multiplayer_editor_shared_files.cmake b/Gems/Multiplayer/Code/multiplayer_editor_shared_files.cmake
index 693485143f..cadd908caa 100644
--- a/Gems/Multiplayer/Code/multiplayer_editor_shared_files.cmake
+++ b/Gems/Multiplayer/Code/multiplayer_editor_shared_files.cmake
@@ -13,4 +13,5 @@ set(FILES
Source/Editor/MultiplayerEditorGem.h
Source/Editor/MultiplayerEditorSystemComponent.cpp
Source/Editor/MultiplayerEditorSystemComponent.h
+ Include/Multiplayer/Editor/MultiplayerPythonEditorEventsBus.h
)