Add developer travel command

This commit is contained in:
2026-05-16 13:46:34 -07:00
parent 65bcdf639e
commit e4364554de
5 changed files with 125 additions and 1 deletions
+5 -1
View File
@@ -474,7 +474,11 @@ Target deliverable: A small group can join a server, spawn into one biome, gathe
`AAgrarianMapBoundaryVolume`, placed `AGR_GroundZeroMapBoundary` around the `AAgrarianMapBoundaryVolume`, placed `AGR_GroundZeroMapBoundary` around the
loaded 1 km Ground Zero tile, clamps server-authoritative player pawns back loaded 1 km Ground Zero tile, clamps server-authoritative player pawns back
inside the tile with padding, and exposes a warning-zone hook for later UI. inside the tile with padding, and exposes a warning-zone hook for later UI.
- [ ] Add developer travel command. - [x] Add developer travel command. Added server-authoritative
`AgrarianTravel X Y Z` and `AgrarianTravelHome` exec commands on the Agrarian
player controller, teleports the controlled pawn to explicit coordinates or
the validated Ground Zero safe-spawn fallback, stops active movement after
travel, and verifies the command wiring.
## 0.1.E Inventory System ## 0.1.E Inventory System
+8
View File
@@ -180,6 +180,14 @@ tile with a small padding rather than allowing players to walk into missing
neighbor terrain. The actor exposes a warning distance hook so later UI can neighbor terrain. The actor exposes a warning distance hook so later UI can
present an in-world or HUD notice before a clamp occurs. present an in-world or HUD notice before a clamp occurs.
Developer testing supports server-authoritative developer travel through
`AgrarianTravel X Y Z` on `AAgrarianGamePlayerController`. The command teleports
the controlled pawn to explicit Unreal world coordinates, stops any current
character movement, and reports the destination to the issuing player.
`AgrarianTravelHome` returns the player to the validated Ground Zero safe-spawn
fallback near `AGR_DemoPlayerStart`, above sea level and above terrain by the
same safe offset used by the map setup pass.
First-pass sky and lighting use `AAgrarianSkyLightingController`. The controller First-pass sky and lighting use `AAgrarianSkyLightingController`. The controller
owns movable sun, skylight, and exponential-height-fog components and reads the owns movable sun, skylight, and exponential-height-fog components and reads the
replicated `AAgrarianGameState` time, active tile sunrise/sunset, weather state, replicated `AAgrarianGameState` time, active tile sunrise/sunset, weather state,
@@ -0,0 +1,54 @@
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
FILES = {
"AgrarianGamePlayerController.h": ROOT / "Source" / "AgrarianGame" / "AgrarianGamePlayerController.h",
"AgrarianGamePlayerController.cpp": ROOT / "Source" / "AgrarianGame" / "AgrarianGamePlayerController.cpp",
"TechnicalDesignDocument.md": ROOT / "Docs" / "TechnicalDesignDocument.md",
"AGRARIAN_DEVELOPMENT_ROADMAP.md": ROOT / "AGRARIAN_DEVELOPMENT_ROADMAP.md",
}
EXPECTED = {
"AgrarianGamePlayerController.h": [
"void AgrarianTravel(float X, float Y, float Z);",
"void AgrarianTravelHome();",
"void ServerAgrarianTravel(FVector Destination);",
],
"AgrarianGamePlayerController.cpp": [
"GroundZeroDeveloperTravelHomeLocation(-22000.0f, -3500.0f, 1148.0f)",
"void AAgrarianGamePlayerController::AgrarianTravel(float X, float Y, float Z)",
"void AAgrarianGamePlayerController::AgrarianTravelHome()",
"ServerAgrarianTravel(FVector(X, Y, Z));",
"void AAgrarianGamePlayerController::ServerAgrarianTravel_Implementation(FVector Destination)",
"ControlledPawn->TeleportTo(Destination, ControlledPawn->GetActorRotation(), false, true);",
"Movement->StopMovementImmediately();",
"Destination.ContainsNaN()",
],
"TechnicalDesignDocument.md": [
"`AgrarianTravel X Y Z`",
"`AgrarianTravelHome`",
"server-authoritative developer travel",
],
"AGRARIAN_DEVELOPMENT_ROADMAP.md": [
"[x] Add developer travel command.",
],
}
def main():
missing = []
for label, path in FILES.items():
text = path.read_text(encoding="utf-8")
for snippet in EXPECTED[label]:
if snippet not in text:
missing.append(f"{label}: {snippet}")
if missing:
raise RuntimeError("Developer travel command verification failed: " + "; ".join(missing))
print("Agrarian developer travel command verification complete.")
if __name__ == "__main__":
main()
@@ -9,11 +9,18 @@
#include "AgrarianSurvivalComponent.h" #include "AgrarianSurvivalComponent.h"
#include "EnhancedInputSubsystems.h" #include "EnhancedInputSubsystems.h"
#include "Engine/LocalPlayer.h" #include "Engine/LocalPlayer.h"
#include "GameFramework/Character.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "InputMappingContext.h" #include "InputMappingContext.h"
#include "Blueprint/UserWidget.h" #include "Blueprint/UserWidget.h"
#include "AgrarianGame.h" #include "AgrarianGame.h"
#include "Widgets/Input/SVirtualJoystick.h" #include "Widgets/Input/SVirtualJoystick.h"
namespace
{
const FVector GroundZeroDeveloperTravelHomeLocation(-22000.0f, -3500.0f, 1148.0f);
}
void AAgrarianGamePlayerController::BeginPlay() void AAgrarianGamePlayerController::BeginPlay()
{ {
Super::BeginPlay(); Super::BeginPlay();
@@ -120,6 +127,16 @@ void AAgrarianGamePlayerController::AgrarianHeal()
ServerAgrarianHeal(); ServerAgrarianHeal();
} }
void AAgrarianGamePlayerController::AgrarianTravel(float X, float Y, float Z)
{
ServerAgrarianTravel(FVector(X, Y, Z));
}
void AAgrarianGamePlayerController::AgrarianTravelHome()
{
ServerAgrarianTravel(GroundZeroDeveloperTravelHomeLocation);
}
void AAgrarianGamePlayerController::ServerAgrarianGrantItem_Implementation(FName ItemId, int32 Quantity) void AAgrarianGamePlayerController::ServerAgrarianGrantItem_Implementation(FName ItemId, int32 Quantity)
{ {
AAgrarianGameCharacter* AgrarianCharacter = GetPawn<AAgrarianGameCharacter>(); AAgrarianGameCharacter* AgrarianCharacter = GetPawn<AAgrarianGameCharacter>();
@@ -196,3 +213,35 @@ void AAgrarianGamePlayerController::ServerAgrarianHeal_Implementation()
SurvivalComponent->AddWarmth(37.0f - SurvivalComponent->Survival.BodyTemperature); SurvivalComponent->AddWarmth(37.0f - SurvivalComponent->Survival.BodyTemperature);
ClientMessage(TEXT("Agrarian survival restored.")); ClientMessage(TEXT("Agrarian survival restored."));
} }
void AAgrarianGamePlayerController::ServerAgrarianTravel_Implementation(FVector Destination)
{
APawn* ControlledPawn = GetPawn();
if (!ControlledPawn)
{
ClientMessage(TEXT("No controlled pawn found for developer travel."));
return;
}
if (!Destination.ContainsNaN())
{
ControlledPawn->TeleportTo(Destination, ControlledPawn->GetActorRotation(), false, true);
if (ACharacter* ControlledCharacter = Cast<ACharacter>(ControlledPawn))
{
if (UCharacterMovementComponent* Movement = ControlledCharacter->GetCharacterMovement())
{
Movement->StopMovementImmediately();
}
}
ClientMessage(FString::Printf(
TEXT("Developer travel complete: X %.1f Y %.1f Z %.1f"),
Destination.X,
Destination.Y,
Destination.Z));
}
else
{
ClientMessage(TEXT("Developer travel failed: invalid destination."));
}
}
@@ -66,6 +66,12 @@ public:
UFUNCTION(Exec) UFUNCTION(Exec)
void AgrarianHeal(); void AgrarianHeal();
UFUNCTION(Exec)
void AgrarianTravel(float X, float Y, float Z);
UFUNCTION(Exec)
void AgrarianTravelHome();
protected: protected:
UFUNCTION(Server, Reliable) UFUNCTION(Server, Reliable)
void ServerAgrarianGrantItem(FName ItemId, int32 Quantity); void ServerAgrarianGrantItem(FName ItemId, int32 Quantity);
@@ -78,4 +84,7 @@ protected:
UFUNCTION(Server, Reliable) UFUNCTION(Server, Reliable)
void ServerAgrarianHeal(); void ServerAgrarianHeal();
UFUNCTION(Server, Reliable)
void ServerAgrarianTravel(FVector Destination);
}; };