Explorar o código

Merge pull request #391 from aws-lumberyard-dev/MPSGameLiftPackageExporter

Multiplayer Sample GameLift Exporter Script
Gene Walters %!s(int64=2) %!d(string=hai) anos
pai
achega
12d1f624b0

+ 22 - 44
MPSGameLift/Documentation/GameLift.md

@@ -12,58 +12,32 @@ This README covers optional setup, testing and running on [Amazon GameLift](http
     C:\> aws --version
     C:\> aws --version
     aws-cli/2.10.0 Python/3.11.2 Windows/10 exe/AMD64 prompt/off
     aws-cli/2.10.0 Python/3.11.2 Windows/10 exe/AMD64 prompt/off
     ```
     ```
-1. Enable the "AWSGameLift" and "MPSGameLift" gems
-
-    Option 1: Commandline
-    ```sh
-    <path-to-o3de-engine>\scripts\o3de.bat enable-gem -pp <path-to-multiplayer-sample> -gn MPSGameLift
-    ```
-    Option 2: Project Manager
-    1. Open Project Manager
-    2. Select the "Configure Gems" options for Multiplayer Sample
-    3. Enable "AWSGameLift" and "MPSGameLift" gems
-
-        ![Enable GameLift Gems](Media/enable_gamelift_gems.jpg)
-    4. Click "Save"
-
-
-    ---
-    **NOTE**
-
-    Due to [bug-15829](https://github.com/o3de/o3de/issues/15829) please also add "AWSGameLift" to project.json's _gem_names_ list.
-
-    ---
-    
-
-1. Build the server, game launchers, and asset bundler for MultiplayerSample
-
-    `cmake --build build\windows --target Editor MultiplayerSample.GameLauncher MultiplayerSample.ServerLauncher AssetBundler --config profile -- /m `
-
-1. Build all the assets
-
-    `cmake --build build\windows --target MultiplayerSample.Assets --config profile -- /m`
-
 1. Work in progress (WiP) step: Add your AWS region to Config/default_aws_resource_mappings.json (example: "Region": "us-west-2")
 1. Work in progress (WiP) step: Add your AWS region to Config/default_aws_resource_mappings.json (example: "Region": "us-west-2")
 
 
     a. Currently needed otherwise when the client initializes GameLift there will be an error about not having a region.
     a. Currently needed otherwise when the client initializes GameLift there will be an error about not having a region.
 
 
     b. This step will be removed once we properly parse the game-session data which contains the fleet-id, region-id, etc  
     b. This step will be removed once we properly parse the game-session data which contains the fleet-id, region-id, etc  
 
 
-## Build Server for Windows
-1. Build Monolithic Server
+1. Use Export Project to Compile Code and Build Assets
 
 
-    a. `cmake -B build\windows_mono -S . -G "Visual Studio 16" -DLY_MONOLITHIC_GAME=1 -DALLOW_SETTINGS_REGISTRY_DEVELOPMENT_OVERRIDES=0`
+    ```sh
+    <path-to-o3de-engine>\scripts\o3de.bat export-project -es <path-to-multiplayer-sample>\MPSGameLift\Scripts\export_gamelift_server_package.py --code --assets -ll INFO
+    ```
+    ---
+    **Important**
 
 
-    b. `cmake --build build\windows_mono --target MultiplayerSample.GameLauncher MultiplayerSample.ServerLauncher --config profile -- /m /nologo`
-1. Bundle Content
+    The export_gamelift_server_package script only works for projects built using engine source, and won't work with engine as an sdk. 
 
 
-    a. Open .\build\windows\bin\profile\AssetBundler.exe
+    ---
+    
+    ---
+    **Important**
 
 
-    b. Follow steps for "Create a bundle for game assets" and "Create a bundle for engine assets" and "Add bundles to the release game layout" here: https://www.o3de.org/docs/user-guide/packaging/asset-bundler/bundle-assets-for-release/
+    The export_gamelift_server_package script only works for projects built using engine source, and won't work with engine as an sdk. 
 
 
-The "default seed lists" choice should choose all but 4 seed lists to make the engine_pc.pak
-The other 4 seed lists should all get selected to make the game_pc.pak
+    ---
 It's important to make sure that the bootstrap.game.profile.setreg file has been added to one of the seed files. (also add debug if you want to support debug builds)
 It's important to make sure that the bootstrap.game.profile.setreg file has been added to one of the seed files. (also add debug if you want to support debug builds)
+
 1. Create the Launcher Zip file
 1. Create the Launcher Zip file
    Use the following .bat file or equivalent copy steps to create a directory with the launchers in it:
    Use the following .bat file or equivalent copy steps to create a directory with the launchers in it:
    Run from MultiplayerSample project root directory...
    Run from MultiplayerSample project root directory...
@@ -90,14 +64,14 @@ It's important to make sure that the bootstrap.game.profile.setreg file has been
 1. Test the profile pak server and game locally
 1. Test the profile pak server and game locally
     Run the server in headless mode using `rhi=null` and `NullRenderer` parameters; the server appears as a white screen in headless mode.
     Run the server in headless mode using `rhi=null` and `NullRenderer` parameters; the server appears as a white screen in headless mode.
     
     
-    `C:\GameLiftPackageWindows\MultiplayerSample.ServerLauncher.exe --rhi=null -NullRenderer -bg_ConnectToAssetProcessor=0 -sys_PakPriority=2 -sv_terminateOnPlayerExit=true --console-command-file=launch_server.cfg`
+    `C:\GameLiftPackageWindows\MultiplayerSample.ServerLauncher.exe --rhi=null -NullRenderer -bg_ConnectToAssetProcessor=0 -sys_PakPriority=2 --console-command-file=launch_server.cfg`
     
     
-    `C:\GameLiftPackageWindows\MultiplayerSample.GameLauncher.exe -bg_ConnectToAssetProcessor=0 -sys_PakPriority=2 --connect`
+    `<path-to-multiplayer-sample>\build\windows\bin\profile\MultiplayerSample.GameLauncher.exe -bg_ConnectToAssetProcessor=0 --connect`
 
 
     ---
     ---
     **NOTE**
     **NOTE**
 
 
-    Note: launch_server.cfg is required because there's a bug with multiplayer when calling --loadlevel in the command-line. See https://github.com/o3de/o3de/issues/15773.
+    Launch_server.cfg is required because there's a bug with multiplayer when calling --loadlevel in the command-line. See https://github.com/o3de/o3de/issues/15773.
 
 
     ---
     ---
 
 
@@ -150,9 +124,13 @@ Launch the game client with:
 ```sh
 ```sh
 aws gamelift create-player-session --region us-west-2 --game-session-id <GameSessionId> --player-id Player1
 aws gamelift create-player-session --region us-west-2 --game-session-id <GameSessionId> --player-id Player1
 ```
 ```
-Note: PlayerId passed into create-player-session shouldn't be the player id passed into these JSON block; keep these unique. 
+---
+**NOTE**
+PlayerId passed into create-player-session shouldn't be the player id passed into these JSON block; keep these unique. 
 Record PlayerSessionId and use this in the game immediately because it expires after 60 seconds. Example: psess-50311090-9283-4fb0-ad1a-94468e60fa16
 Record PlayerSessionId and use this in the game immediately because it expires after 60 seconds. Example: psess-50311090-9283-4fb0-ad1a-94468e60fa16
 
 
+---
+
 Paste in the game session and player session and click Connect. 
 Paste in the game session and player session and click Connect. 
 ```json
 ```json
 { "GameSessionId": "<GameSessionId>", "PlayerId": "player_id", "PlayerSessionId": "<PlayerSessionId>" }
 { "GameSessionId": "<GameSessionId>", "PlayerId": "player_id", "PlayerSessionId": "<PlayerSessionId>" }

+ 153 - 0
MPSGameLift/Scripts/export_gamelift_server_package.py

@@ -0,0 +1,153 @@
+#
+# 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
+#
+#
+"""
+Enables the project for AWS Gamelift and creates a Windows server package which can be uploaded to a GameLift.
+
+To use this script pass it into o3de.bat's export-project command: 
+<path-to-o3de-engine>\scripts\o3de.bat export-project -es <path-to-multiplayer-sample>\MPSGameLift\Scripts\export_gamelift_server_package.py -ll INFO
+"""
+
+import os
+import argparse
+
+import o3de.export_project as exp
+import o3de.enable_gem as enable_gem
+
+from o3de.export_project import process_command
+from o3de import manifest
+
+project_json_data = manifest.get_project_json_data(project_path=o3de_context.project_path)
+project_name = project_json_data.get('project_name')
+
+o3de_logger.info(f"Exporting AWS GameLift Server Package for {project_name}")
+
+# Parse arguments to either build code, assets, or both
+parser = argparse.ArgumentParser(
+                    prog='GameLift Server Package',
+                    description='Helps setup the project for AWS Gamelift and creates a Windows server package which can be uploaded to a GameLift.')
+
+parser.add_argument('--code', action='store_true', help='Build code')
+parser.add_argument('--assets', action='store_true', help='Build assets')
+parser.add_argument('-g', '--generator', choices=['Visual Studio 16', 'Visual Studio 17'], help='Which compiler do you want to use?')
+
+args = parser.parse_args(o3de_context.args)
+
+# Help user choose to build code, assets, or both if they didn't specify via command-line
+while not args.code and not args.assets:
+    user_input = input('No build command specified. Do you want to build code, assets, or both? (c/a/b). Quit(q): ')
+    if user_input.lower() == 'c':
+        args.code = True
+    elif user_input.lower() == 'a':
+        args.assets = True
+    elif user_input.lower() == 'b':
+        args.code = True
+        args.assets = True
+    elif user_input.lower() == 'q':
+        quit()
+
+# Help user choose their compiler if they didn't specify via command-line
+while not args.generator:
+    user_input = input('Select generator:\n 1. Visual Studio 16\n 2. Visual Studio 17.\n Quit(q)\n')
+    if user_input == '1':
+        args.generator = "Visual Studio 16"
+    if user_input == '2':
+        args.generator = "Visual Studio 17"
+    elif user_input.lower() == 'q':
+        quit()
+        
+build_folder = os.path.join(o3de_context.project_path, "build", "windows")
+
+# Build code
+if (args.code):
+    # Enable GameLift gems
+    o3de_logger.info(f"Enabling AWSGameLift and MPSGameLift gem")
+    if (enable_gem.enable_gem_in_project(gem_name="AWSGameLift", project_path=o3de_context.project_path) != 0):
+        quit()
+
+    if (enable_gem.enable_gem_in_project(gem_name="MPSGameLift", project_path=o3de_context.project_path) != 0):
+        quit()
+
+    # Build server launcher
+    os.makedirs(build_folder, exist_ok=True)
+    o3de_logger.info(f"Building {project_name}.ServerLauncher")
+
+    if (process_command(["cmake", "-B", build_folder, "-S", o3de_context.project_path, "-G", args.generator])):
+        quit()
+
+    if (process_command(["cmake", "--build", build_folder, "--target", f"{project_name}.ServerLauncher", "AssetProcessor", "AssetBundler", "AssetBundlerBatch", "--config", "profile", "--", "/m"]) != 0):
+        quit()
+        
+    # Build monolithic server launcher build
+    monolithic_build_folder = os.path.join(o3de_context.project_path, "build", "windows_mono")
+    os.makedirs(monolithic_build_folder, exist_ok=True)
+    if (process_command(["cmake", "-B", monolithic_build_folder, "-S", o3de_context.project_path, "-G", args.generator, "-DLY_MONOLITHIC_GAME=1", "-DALLOW_SETTINGS_REGISTRY_DEVELOPMENT_OVERRIDES=0"])):
+        quit()
+
+    if (process_command(["cmake", "--build", monolithic_build_folder, "--target", f"{project_name}.ServerLauncher", "--config", "profile", "--", "/m"])):
+        quit()
+
+# Build Assets
+if (args.assets):
+    # Process assets
+    if (process_command(["cmake", "--build", build_folder, "--target", f"{project_name}.Assets", "--config", "profile", "--", "/m"]) != 0):
+        quit()
+
+    if (process_command(["cmake", "--build", build_folder, "--target", "AssetBundler", "AssetBundlerBatch", "--config", "profile", "--", "/m"]) != 0):
+        quit()
+
+    # Create a game asset list by using the game seed list
+    platform = "pc"
+    asset_bundler_batch = os.path.join(build_folder, "bin", "profile", "AssetBundlerBatch.exe")
+    asset_list_directory = os.path.join(o3de_context.project_path, "AssetBundling", "AssetLists" )
+    seed_list_directory = os.path.join(o3de_context.project_path, "AssetBundling", "SeedLists" )
+    game_asset_list_path = os.path.join(asset_list_directory, f"game_{platform}.assetlist")
+    engine_asset_list_path = os.path.join(asset_list_directory, f"engine_{platform}.assetlist")
+
+    generate_asset_list_command = f"{asset_bundler_batch} assetLists --assetListFile {game_asset_list_path} --platform {platform} --allowOverwrites"
+    
+    # Add all the .seed files found inside <project>/AssetBundling/SeedLists
+    seed_file_extension = ".seed"
+    
+    seed_files = [os.path.join(seed_list_directory, f) for f in os.listdir(seed_list_directory) if f.endswith(seed_file_extension)]
+
+    if not seed_files:
+        o3de_logger.error(f"Building assets failed! Could not find any game seed files inside {seed_list_directory}")
+        quit()
+
+    for file in seed_files:
+        generate_asset_list_command += str(f" --seedListFile ")
+        generate_asset_list_command += str(os.path.join(seed_list_directory, file))
+
+    if (process_command(generate_asset_list_command.split()) != 0):
+        quit()
+
+
+    if (process_command([asset_bundler_batch, "assetLists", "--assetListFile", game_asset_list_path, "--platform", platform, "--allowOverwrites",
+                         "--seedListFile", os.path.join(seed_list_directory, "BasePopcornFxSeedList.seed"), 
+                         "--seedListFile", os.path.join(seed_list_directory, "GameSeedList.seed"), 
+                         "--seedListFile", os.path.join(seed_list_directory, "ProfileOnlySeedList.seed"), 
+                         "--seedListFile", os.path.join(seed_list_directory, "VFXSeedList.seed")]) != 0):
+        quit()
+
+    # Create a engine asset list by using the engine seed list
+    if (process_command([asset_bundler_batch, "assetLists", "--assetListFile", engine_asset_list_path, "--platform", platform, "--allowOverwrites",
+                         "--addDefaultSeedListFiles"]) != 0):
+        quit()
+
+    # Bundle game asset using game asset list
+    bundles_directory = os.path.join(o3de_context.project_path, "AssetBundling", "Bundles" )
+    if (process_command([asset_bundler_batch, "bundles", "--maxSize", "2048", "--platform", platform, "--allowOverwrites",
+                         "--outputBundlePath", os.path.join(bundles_directory, "game.pak"),
+                         "--assetListFile", game_asset_list_path]) != 0):
+        quit()
+
+    # Bundle engine asset using engine asset list
+    if (process_command([asset_bundler_batch, "bundles", "--maxSize", "2048", "--platform", platform, "--allowOverwrites",
+                         "--outputBundlePath", os.path.join(bundles_directory, "engine.pak"),
+                         "--assetListFile", engine_asset_list_path]) != 0):
+        quit()