From 1eb752536ce7e2aae4a8afa76077461f1d8bd431 Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 14 May 2026 00:51:47 -0700 Subject: [PATCH] Package Ground Zero investor demo --- .gitattributes | 1 + .gitignore | 1 + AGRARIAN_DEVELOPMENT_ROADMAP.md | 19 +- Config/DefaultEngine.ini | 5 +- Config/DefaultGame.ini | 26 ++- .../Maps/L_GroundZeroTerrain_Test.umap | 4 +- Content/Splash/Splash.bmp | 3 + Docs/Legal/InvestorDemoNotices.md | 27 +++ Scripts/PackageWindowsDevelopment.bat | 61 +++++++ Scripts/setup_ground_zero_demo_map.py | 166 ++++++++++++++++++ 10 files changed, 303 insertions(+), 10 deletions(-) create mode 100644 Content/Splash/Splash.bmp create mode 100644 Docs/Legal/InvestorDemoNotices.md create mode 100644 Scripts/PackageWindowsDevelopment.bat create mode 100644 Scripts/setup_ground_zero_demo_map.py diff --git a/.gitattributes b/.gitattributes index b39d47d..bdb591c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -6,6 +6,7 @@ *.wav filter=lfs diff=lfs merge=lfs -text *.mp3 filter=lfs diff=lfs merge=lfs -text *.png filter=lfs diff=lfs merge=lfs -text +*.bmp filter=lfs diff=lfs merge=lfs -text *.jpg filter=lfs diff=lfs merge=lfs -text *.jpeg filter=lfs diff=lfs merge=lfs -text *.tga filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore index 3c11ec1..aab5b18 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ Saved/ # Build outputs Build/ +Builds/ *.sln *.sln.DotSettings.user *.VC.db diff --git a/AGRARIAN_DEVELOPMENT_ROADMAP.md b/AGRARIAN_DEVELOPMENT_ROADMAP.md index acd63a9..aef6990 100644 --- a/AGRARIAN_DEVELOPMENT_ROADMAP.md +++ b/AGRARIAN_DEVELOPMENT_ROADMAP.md @@ -128,7 +128,7 @@ Goal: Prepare the project so all future development is controlled, recoverable, - [x] Decide local development platforms. - [x] Decide build machine strategy. - [x] Create repeatable local build instructions. -- [ ] Create repeatable packaged build instructions. +- [x] Create repeatable packaged build instructions. - [ ] Create repeatable dedicated server build instructions. - [~] Document required plugins. - [x] Disable unneeded plugins. @@ -145,6 +145,12 @@ Current tooling decisions: - Preferred interactive editor/gameplay connection: Parsec or similar real-GPU remote desktop, not RDP. - Dedicated server target: Linux for multiplayer hosting. - Windows compiler used by Unreal 5.7: VS 2022 Build Tools MSVC `14.44.35207`. +- Packaged Windows demo wrapper: `Scripts/PackageWindowsDevelopment.bat`. +- Current investor demo starts on the Ground Zero terrain map: `/Game/Agrarian/Maps/L_GroundZeroTerrain_Test`. +- Investor-demo release rule: whenever all tracked roadmap items for a version + milestone are complete, including minor versions like `.01` or `.6` and major + versions like `1`, build and smoke-test a fresh Windows packaged executable + for investor/demo review. ## 0.3 Design Documentation @@ -304,6 +310,9 @@ Completed in version .01: - [x] Converted extracted 1-meter DEM subset into an Unreal Landscape-ready R16 heightmap and import plan. - [x] Imported the Ground Zero R16 heightmap into `/Game/Agrarian/Maps/L_GroundZeroTerrain_Test`. - [x] Verified the Ground Zero terrain test map is centered and spans 1 km x 1 km in Unreal. +- [x] Set the packaged investor demo default map to Ground Zero. +- [x] Added first Agrarian Studio splash screen and investor demo legal notices. +- [x] Built a Windows Development packaged demo and smoke-tested launch into Ground Zero. Open version .01 tasks: @@ -331,6 +340,7 @@ Open version .01 tasks: - [x] Acquire or extract the final USGS 3DEP DEM/lidar source for the Ground Zero tile. - [x] Convert the extracted 1-meter DEM subset into an Unreal Landscape-ready heightmap and import plan. - [x] Import the Ground Zero R16 heightmap into an Unreal terrain test map. +- [x] Package a Windows Development investor demo that starts on the Ground Zero map. # Phase 1 - Foundational Survival MVP @@ -1218,7 +1228,7 @@ These tracks run across all phases and must not be left as afterthoughts. ## K. Build And Release Pipeline - [x] Define dev editor build process. -- [ ] Define internal test build process. +- [x] Define internal test build process. - [ ] Define closed alpha build process. - [ ] Define dedicated server packaging. - [ ] Define patch distribution. @@ -1228,9 +1238,10 @@ These tracks run across all phases and must not be left as afterthoughts. - [ ] Define release approval checklist. - [x] Add one-command Codex build wrapper for `AgrarianGameEditor`. - [x] Store editor build logs under `Saved/BuildLogs/BuildEditor-Windows.log`. -- [ ] Add one-command packaged client build wrapper. +- [x] Add one-command packaged client build wrapper. - [ ] Add one-command Linux dedicated server build wrapper. -- [ ] Add smoke-test command for build artifacts. +- [x] Define investor-demo build trigger at version milestone completion. +- [x] Add smoke-test command for build artifacts. ## L. Community And Marketing diff --git a/Config/DefaultEngine.ini b/Config/DefaultEngine.ini index 47ec6a8..acfe9cb 100644 --- a/Config/DefaultEngine.ini +++ b/Config/DefaultEngine.ini @@ -1,6 +1,6 @@ [/Script/EngineSettings.GameMapsSettings] -GameDefaultMap=/Game/ThirdPerson/Lvl_ThirdPerson.Lvl_ThirdPerson -EditorStartupMap=/Game/ThirdPerson/Lvl_ThirdPerson.Lvl_ThirdPerson +GameDefaultMap=/Game/Agrarian/Maps/L_GroundZeroTerrain_Test.L_GroundZeroTerrain_Test +EditorStartupMap=/Game/Agrarian/Maps/L_GroundZeroTerrain_Test.L_GroundZeroTerrain_Test GlobalDefaultGameMode=/Game/ThirdPerson/Blueprints/BP_ThirdPersonGameMode.BP_ThirdPersonGameMode_C [/Script/Engine.RendererSettings] @@ -255,4 +255,3 @@ bReportStats=False ConnectionType=USBOnly bUseManualIPAddress=False ManualIPAddress= - diff --git a/Config/DefaultGame.ini b/Config/DefaultGame.ini index d5c7bf1..db1d3f2 100644 --- a/Config/DefaultGame.ini +++ b/Config/DefaultGame.ini @@ -1,3 +1,27 @@ [/Script/EngineSettings.GeneralProjectSettings] ProjectID=1C37CF214211E5FA6177D497FE103AC4 -ProjectName=Third Person Game Template +ProjectName=Agrarian +ProjectDisplayedTitle=NSLOCTEXT("[/Script/EngineSettings]", "AgrarianProjectDisplayedTitle", "Agrarian") +ProjectDebugTitleInfo=NSLOCTEXT("[/Script/EngineSettings]", "AgrarianProjectDebugTitle", "Agrarian - Development Build") +Description=Persistent generational civilization survival prototype. +CompanyName=Agrarian Studio +CompanyDistinguishedName=Agrarian Studio +Homepage="https://agrarianstudio.com" +SupportContact=nathan@pacificao.com +CopyrightNotice=Copyright (c) 2026 Agrarian Studio. All rights reserved. +LicensingTerms=Investor demo build. Not for public distribution. +PrivacyPolicy=Internal prototype build; online services and telemetry policies are not final. + +[/Script/UnrealEd.ProjectPackagingSettings] +BuildConfiguration=PPBC_Development +ForDistribution=False +FullRebuild=False +UsePakFile=True +bCompressed=True +bShareMaterialShaderCode=True +bSharedMaterialNativeLibraries=True +IncludePrerequisites=True +IncludeAppLocalPrerequisites=False +Build=IfProjectHasCode ++MapsToCook=(FilePath="/Game/Agrarian/Maps/L_GroundZeroTerrain_Test") ++MapsToCook=(FilePath="/Game/ThirdPerson/Lvl_ThirdPerson") diff --git a/Content/Agrarian/Maps/L_GroundZeroTerrain_Test.umap b/Content/Agrarian/Maps/L_GroundZeroTerrain_Test.umap index d60b876..caecb85 100644 --- a/Content/Agrarian/Maps/L_GroundZeroTerrain_Test.umap +++ b/Content/Agrarian/Maps/L_GroundZeroTerrain_Test.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:025e52ded3ccf18fb16f8daf15ab1e189d0203d7c29db68d80612de25f5afec3 -size 7385323 +oid sha256:9eb6c3c9620f13c980d90fb955ce3a0758b35ca0a7c00331d0446bd342361e8a +size 7407234 diff --git a/Content/Splash/Splash.bmp b/Content/Splash/Splash.bmp new file mode 100644 index 0000000..8cf65f4 --- /dev/null +++ b/Content/Splash/Splash.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ec66e903e9833a54a352a90c05650930a0ecb2d0bd496709833d1071baae7ed +size 2764854 diff --git a/Docs/Legal/InvestorDemoNotices.md b/Docs/Legal/InvestorDemoNotices.md new file mode 100644 index 0000000..d926abe --- /dev/null +++ b/Docs/Legal/InvestorDemoNotices.md @@ -0,0 +1,27 @@ +# Agrarian Investor Demo Notices + +This file is a working legal/credits checklist for internal investor demo +builds. It is not a substitute for legal review before public release. + +## Product Notice + +Agrarian + +Copyright (c) 2026 Agrarian Studio. All rights reserved. + +Investor demo build. Not for public distribution. + +## Unreal Engine Notice + +Agrarian uses Unreal(R) Engine. Unreal(R) is a trademark or registered +trademark of Epic Games, Inc. in the United States of America and elsewhere. +Unreal(R) Engine, Copyright 1998 - 2026, Epic Games, Inc. All rights reserved. + +## Third-Party Notices + +Before public release, review every third-party asset, plugin, library, font, +sound, texture, and dataset used by the project and add required notices here. + +Current known project-specific source data: + +- USGS 3DEP 1-meter DEM source data for the Ground Zero terrain prototype. diff --git a/Scripts/PackageWindowsDevelopment.bat b/Scripts/PackageWindowsDevelopment.bat new file mode 100644 index 0000000..b8ecd8e --- /dev/null +++ b/Scripts/PackageWindowsDevelopment.bat @@ -0,0 +1,61 @@ +@echo off +setlocal + +set "PROJECT_DIR=%~dp0.." +set "PROJECT_FILE=%PROJECT_DIR%\AgrarianGame.uproject" +set "UE_ROOT=C:\Program Files\Epic Games\UE_5.7" +set "RUN_UAT=%UE_ROOT%\Engine\Build\BatchFiles\RunUAT.bat" +set "ARCHIVE_DIR=%PROJECT_DIR%\Builds\WindowsDevelopment" +set "LOG_DIR=%PROJECT_DIR%\Saved\BuildLogs" +set "LOG_FILE=%LOG_DIR%\PackageWindowsDevelopment.log" + +if not exist "%LOG_DIR%" mkdir "%LOG_DIR%" +if not exist "%ARCHIVE_DIR%" mkdir "%ARCHIVE_DIR%" + +if not exist "%RUN_UAT%" ( + echo Unreal Engine 5.7 RunUAT was not found at: + echo %RUN_UAT% + exit /b 1 +) + +if not exist "%PROJECT_FILE%" ( + echo Project file was not found at: + echo %PROJECT_FILE% + exit /b 1 +) + +echo Packaging Agrarian Windows Development build... +echo Archive: %ARCHIVE_DIR% +echo Log: %LOG_FILE% + +call "%RUN_UAT%" BuildCookRun ^ + -project="%PROJECT_FILE%" ^ + -noP4 ^ + -platform=Win64 ^ + -clientconfig=Development ^ + -build ^ + -cook ^ + -stage ^ + -pak ^ + -archive ^ + -archivedirectory="%ARCHIVE_DIR%" ^ + -map=/Game/Agrarian/Maps/L_GroundZeroTerrain_Test+/Game/ThirdPerson/Lvl_ThirdPerson ^ + -prereqs ^ + -utf8output ^ + -NoUBA > "%LOG_FILE%" 2>&1 + +set "PACKAGE_EXIT_CODE=%ERRORLEVEL%" +type "%LOG_FILE%" + +if not "%PACKAGE_EXIT_CODE%"=="0" ( + echo. + echo Package failed with exit code %PACKAGE_EXIT_CODE%. + echo Log file: %LOG_FILE% + exit /b %PACKAGE_EXIT_CODE% +) + +echo. +echo Package completed successfully. +echo Archive: %ARCHIVE_DIR% +echo. +exit /b 0 diff --git a/Scripts/setup_ground_zero_demo_map.py b/Scripts/setup_ground_zero_demo_map.py new file mode 100644 index 0000000..757568e --- /dev/null +++ b/Scripts/setup_ground_zero_demo_map.py @@ -0,0 +1,166 @@ +import struct +from pathlib import Path + +import unreal + + +MAP_PATH = "/Game/Agrarian/Maps/L_GroundZeroTerrain_Test" +PROJECT_ROOT = Path(r"Z:\AgrarianGameBulid") +TILE_ID = "gz_us_ca_pacifica_utm10n_e544_n4160" +HEIGHTMAP_PATH = PROJECT_ROOT / "Data" / "Terrain" / "Unreal" / TILE_ID / f"{TILE_ID}_unreal_1009.r16" +LANDSCAPE_SIZE = 1009 +XY_SCALE_CM = 100000.0 / (LANDSCAPE_SIZE - 1) +Z_SCALE_CM = 100.0 +LANDSCAPE_MIN_XY = -50000.0 + + +DEMO_ACTORS = [ + { + "label": "AGR_DemoPlayerStart", + "class": unreal.PlayerStart, + "location_xy": unreal.Vector(-18500.0, -6400.0, 0.0), + "z_offset": 220.0, + "rotation": unreal.Rotator(0.0, 72.0, 0.0), + }, + { + "label": "AGR_DemoWoodResource_01", + "class_path": "/Game/Agrarian/Blueprints/Resources/BP_WoodResourceNode", + "location_xy": unreal.Vector(-16800.0, -5400.0, 0.0), + "z_offset": 80.0, + "rotation": unreal.Rotator(0.0, 25.0, 0.0), + }, + { + "label": "AGR_DemoFiberResource_01", + "class_path": "/Game/Agrarian/Blueprints/Resources/BP_FiberResourceNode", + "location_xy": unreal.Vector(-15600.0, -7850.0, 0.0), + "z_offset": 80.0, + "rotation": unreal.Rotator(0.0, -15.0, 0.0), + }, + { + "label": "AGR_DemoCampfire_01", + "class_path": "/Game/Agrarian/Blueprints/Structures/BP_Campfire", + "location_xy": unreal.Vector(-13200.0, -6350.0, 0.0), + "z_offset": 90.0, + "rotation": unreal.Rotator(0.0, 0.0, 0.0), + }, + { + "label": "AGR_DemoPrimitiveShelter_01", + "class_path": "/Game/Agrarian/Blueprints/Structures/BP_PrimitiveShelter", + "location_xy": unreal.Vector(-11500.0, -7750.0, 0.0), + "z_offset": 120.0, + "rotation": unreal.Rotator(0.0, -30.0, 0.0), + }, + { + "label": "AGR_DemoRabbitWildlife_01", + "class_path": "/Game/Agrarian/Blueprints/Wildlife/BP_RabbitWildlife", + "location_xy": unreal.Vector(-19800.0, -8550.0, 0.0), + "z_offset": 120.0, + "rotation": unreal.Rotator(0.0, 135.0, 0.0), + }, + { + "label": "AGR_DemoSun", + "class": unreal.DirectionalLight, + "location_xy": unreal.Vector(-22000.0, -9000.0, 0.0), + "fixed_z": 35000.0, + "rotation": unreal.Rotator(-42.0, -35.0, 0.0), + }, + { + "label": "AGR_DemoSkyLight", + "class": unreal.SkyLight, + "location_xy": unreal.Vector(-18000.0, -7000.0, 0.0), + "fixed_z": 12000.0, + "rotation": unreal.Rotator(0.0, 0.0, 0.0), + }, + { + "label": "AGR_DemoFog", + "class": unreal.ExponentialHeightFog, + "location_xy": unreal.Vector(-18000.0, -7000.0, 0.0), + "fixed_z": 4000.0, + "rotation": unreal.Rotator(0.0, 0.0, 0.0), + }, +] + + +def get_actor_label(actor): + try: + return actor.get_actor_label() + except Exception: + return actor.get_name() + + +def set_actor_label(actor, label): + try: + actor.set_actor_label(label, mark_dirty=True) + except TypeError: + actor.set_actor_label(label) + + +def load_blueprint_class(path): + generated_class = unreal.EditorAssetLibrary.load_blueprint_class(path) + if not generated_class: + raise RuntimeError(f"Could not load Blueprint class: {path}") + return generated_class + + +def load_heightmap(): + raw = HEIGHTMAP_PATH.read_bytes() + expected_bytes = LANDSCAPE_SIZE * LANDSCAPE_SIZE * 2 + if len(raw) != expected_bytes: + raise RuntimeError(f"Unexpected heightmap size: {len(raw)} != {expected_bytes}") + return struct.unpack(f"<{LANDSCAPE_SIZE * LANDSCAPE_SIZE}H", raw) + + +def terrain_z_cm(height_values, x_cm, y_cm): + sample_x = max(0, min(LANDSCAPE_SIZE - 1, round((x_cm - LANDSCAPE_MIN_XY) / XY_SCALE_CM))) + sample_y = max(0, min(LANDSCAPE_SIZE - 1, round((y_cm - LANDSCAPE_MIN_XY) / XY_SCALE_CM))) + height_value = height_values[int(sample_y) * LANDSCAPE_SIZE + int(sample_x)] + elevation_m = (float(height_value) - 32768.0) * Z_SCALE_CM / (100.0 * 128.0) + return elevation_m * 100.0 + + +def remove_existing_demo_actors(labels): + for actor in unreal.EditorLevelLibrary.get_all_level_actors(): + if get_actor_label(actor) in labels: + unreal.EditorLevelLibrary.destroy_actor(actor) + + +def spawn_demo_actor(spec, height_values): + location_xy = spec["location_xy"] + z = spec.get("fixed_z") + if z is None: + z = terrain_z_cm(height_values, location_xy.x, location_xy.y) + spec.get("z_offset", 0.0) + + actor_class = spec.get("class") + if actor_class is None: + actor_class = load_blueprint_class(spec["class_path"]) + + actor = unreal.AgrarianEditorAutomationLibrary.spawn_actor_in_editor_world( + actor_class, + unreal.Vector(location_xy.x, location_xy.y, z), + spec["rotation"], + spec["label"], + ) + if not actor: + raise RuntimeError(f"Could not spawn {spec['label']}") + + set_actor_label(actor, spec["label"]) + unreal.log(f"Placed {spec['label']} at {actor.get_actor_location()}") + return actor + + +def main(): + if not unreal.EditorLevelLibrary.load_level(MAP_PATH): + raise RuntimeError(f"Could not load map: {MAP_PATH}") + + labels = {spec["label"] for spec in DEMO_ACTORS} + remove_existing_demo_actors(labels) + + height_values = load_heightmap() + for spec in DEMO_ACTORS: + spawn_demo_actor(spec, height_values) + + unreal.EditorLevelLibrary.save_current_level() + unreal.log("Ground Zero demo map setup complete.") + + +main()