Kaynağa Gözat

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

Multiplayer Sample GameLift Exporter Script
Gene Walters 2 yıl önce
ebeveyn
işleme
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
     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")
 
     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  
 
-## 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)
+
 1. Create the Launcher Zip file
    Use the following .bat file or equivalent copy steps to create a directory with the launchers in it:
    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
     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: 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
 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
 
+---
+
 Paste in the game session and player session and click Connect. 
 ```json
 { "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()