Implement production vertical slice foundation
This commit is contained in:
1 parent
9d4a89f355
commit
a18e82eb44
104 files changed
+10595
-268
No files matched your search
@@ -0,0 +1,75 @@
|
||||
class_name DiveTickRunner
|
||||
extends RefCounted
|
||||
|
||||
const VehicleTelemetry = preload("res://game/application/dive/vehicle_telemetry.gd")
|
||||
const DiveSession = preload("res://game/domain/dive/dive_session.gd")
|
||||
const DiveTick = preload("res://game/domain/dive/dive_tick.gd")
|
||||
const DiveTelemetrySample = preload("res://game/domain/dive/dive_telemetry_sample.gd")
|
||||
const CollisionObservation = preload("res://game/domain/dive/collision_observation.gd")
|
||||
const ToolPowerDemand = preload("res://game/domain/dive/tool_power_demand.gd")
|
||||
const EjectionIntent = preload("res://game/domain/dive/ejection_intent.gd")
|
||||
const ReturnRouteSample = preload("res://game/domain/dive/return_route_sample.gd")
|
||||
const DiveStep = preload("res://game/domain/dive/dive_step.gd")
|
||||
const DiveUpdate = preload("res://game/domain/dive/dive_update.gd")
|
||||
|
||||
var _session: DiveSession
|
||||
var _next_sequence := 0
|
||||
|
||||
|
||||
func _init(session: DiveSession) -> void:
|
||||
_session = session
|
||||
|
||||
|
||||
func next_sequence() -> int:
|
||||
return _next_sequence
|
||||
|
||||
|
||||
func initial_update() -> DiveUpdate:
|
||||
return DiveUpdate.initial(_session.current_snapshot())
|
||||
|
||||
|
||||
func advance(
|
||||
telemetry: VehicleTelemetry,
|
||||
elapsed_seconds: float,
|
||||
collisions: Array[CollisionObservation] = [],
|
||||
tool_power_demands: Array[ToolPowerDemand] = [],
|
||||
ejection_intent: EjectionIntent = null,
|
||||
return_route: ReturnRouteSample = null
|
||||
) -> DiveUpdate:
|
||||
if telemetry == null:
|
||||
return DiveUpdate.rejected(
|
||||
_next_sequence,
|
||||
"vehicle telemetry is missing",
|
||||
_session.current_snapshot()
|
||||
)
|
||||
var telemetry_error: String = telemetry.validation_error(
|
||||
_session.session_id,
|
||||
_next_sequence
|
||||
)
|
||||
if not telemetry_error.is_empty():
|
||||
return DiveUpdate.rejected(
|
||||
_next_sequence,
|
||||
telemetry_error,
|
||||
_session.current_snapshot()
|
||||
)
|
||||
|
||||
var tick := DiveTick.new(_session.session_id, _next_sequence, elapsed_seconds)
|
||||
var sample := DiveTelemetrySample.new(
|
||||
telemetry.depth_m,
|
||||
telemetry.longitudinal_effort,
|
||||
telemetry.steering_effort,
|
||||
telemetry.vertical_effort,
|
||||
telemetry.high_thrust_active
|
||||
)
|
||||
var step := DiveStep.new(
|
||||
tick,
|
||||
sample,
|
||||
collisions,
|
||||
tool_power_demands,
|
||||
ejection_intent,
|
||||
return_route
|
||||
)
|
||||
var update: DiveUpdate = _session.advance(step)
|
||||
if update.accepted:
|
||||
_next_sequence += 1
|
||||
return update
|
||||
@@ -0,0 +1,74 @@
|
||||
class_name VehicleTelemetry
|
||||
extends RefCounted
|
||||
|
||||
var session_id: StringName
|
||||
var sequence: int
|
||||
var world_position_m: Vector3
|
||||
var world_orientation: Quaternion
|
||||
var world_linear_velocity_mps: Vector3
|
||||
var local_angular_velocity_rps: Vector3
|
||||
var depth_m: float
|
||||
var longitudinal_effort: float
|
||||
var steering_effort: float
|
||||
var vertical_effort: float
|
||||
var high_thrust_active: bool
|
||||
|
||||
|
||||
func _init(
|
||||
p_session_id: StringName,
|
||||
p_sequence: int,
|
||||
p_world_position_m: Vector3,
|
||||
p_world_orientation: Quaternion,
|
||||
p_world_linear_velocity_mps: Vector3,
|
||||
p_local_angular_velocity_rps: Vector3,
|
||||
p_depth_m: float,
|
||||
p_longitudinal_effort: float,
|
||||
p_steering_effort: float,
|
||||
p_vertical_effort: float,
|
||||
p_high_thrust_active: bool
|
||||
) -> void:
|
||||
session_id = p_session_id
|
||||
sequence = p_sequence
|
||||
world_position_m = p_world_position_m
|
||||
world_orientation = p_world_orientation
|
||||
world_linear_velocity_mps = p_world_linear_velocity_mps
|
||||
local_angular_velocity_rps = p_local_angular_velocity_rps
|
||||
depth_m = p_depth_m
|
||||
longitudinal_effort = p_longitudinal_effort
|
||||
steering_effort = p_steering_effort
|
||||
vertical_effort = p_vertical_effort
|
||||
high_thrust_active = p_high_thrust_active
|
||||
|
||||
|
||||
func validation_error(expected_session_id: StringName, expected_sequence: int) -> String:
|
||||
if session_id != expected_session_id:
|
||||
return "telemetry session_id does not match"
|
||||
if sequence != expected_sequence:
|
||||
return "telemetry sequence does not match expected tick"
|
||||
if not _vector_is_finite(world_position_m):
|
||||
return "telemetry world position is not finite"
|
||||
if not _quaternion_is_finite(world_orientation):
|
||||
return "telemetry orientation is not finite"
|
||||
if not _vector_is_finite(world_linear_velocity_mps):
|
||||
return "telemetry linear velocity is not finite"
|
||||
if not _vector_is_finite(local_angular_velocity_rps):
|
||||
return "telemetry angular velocity is not finite"
|
||||
if not is_finite(depth_m) or depth_m < 0.0:
|
||||
return "telemetry depth must be finite and non-negative"
|
||||
for effort: float in [longitudinal_effort, steering_effort, vertical_effort]:
|
||||
if not is_finite(effort) or effort < -1.0 or effort > 1.0:
|
||||
return "telemetry efforts must be between -1 and 1"
|
||||
return ""
|
||||
|
||||
|
||||
func _vector_is_finite(value: Vector3) -> bool:
|
||||
return is_finite(value.x) and is_finite(value.y) and is_finite(value.z)
|
||||
|
||||
|
||||
func _quaternion_is_finite(value: Quaternion) -> bool:
|
||||
return (
|
||||
is_finite(value.x)
|
||||
and is_finite(value.y)
|
||||
and is_finite(value.z)
|
||||
and is_finite(value.w)
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
class_name InputBindingSnapshot
|
||||
extends RefCounted
|
||||
|
||||
var action_id: StringName
|
||||
var label: String
|
||||
var binding_text: String
|
||||
|
||||
|
||||
func _init(p_action_id: StringName, p_label: String, p_binding_text: String) -> void:
|
||||
action_id = p_action_id
|
||||
label = p_label
|
||||
binding_text = p_binding_text
|
||||
@@ -0,0 +1,22 @@
|
||||
class_name RebindResult
|
||||
extends RefCounted
|
||||
|
||||
var accepted: bool
|
||||
var action_id: StringName
|
||||
var binding_text: String
|
||||
var conflicting_action_id: StringName
|
||||
var message: String
|
||||
|
||||
|
||||
func _init(
|
||||
p_accepted: bool,
|
||||
p_action_id: StringName,
|
||||
p_binding_text: String = "",
|
||||
p_conflicting_action_id: StringName = &"",
|
||||
p_message: String = ""
|
||||
) -> void:
|
||||
accepted = p_accepted
|
||||
action_id = p_action_id
|
||||
binding_text = p_binding_text
|
||||
conflicting_action_id = p_conflicting_action_id
|
||||
message = p_message
|
||||
@@ -0,0 +1,8 @@
|
||||
class_name VehicleMotionPort
|
||||
extends RefCounted
|
||||
|
||||
const VehicleCommand = preload("res://game/application/vehicle/vehicle_command.gd")
|
||||
|
||||
|
||||
func apply_command(_command: VehicleCommand) -> void:
|
||||
pass
|
||||
@@ -0,0 +1,22 @@
|
||||
class_name CameraLookCommand
|
||||
extends RefCounted
|
||||
|
||||
var yaw_delta_radians: float
|
||||
var pitch_delta_radians: float
|
||||
var recenter_requested: bool
|
||||
|
||||
|
||||
func _init(
|
||||
p_yaw_delta_radians: float = 0.0,
|
||||
p_pitch_delta_radians: float = 0.0,
|
||||
p_recenter_requested: bool = false
|
||||
) -> void:
|
||||
yaw_delta_radians = p_yaw_delta_radians
|
||||
pitch_delta_radians = p_pitch_delta_radians
|
||||
recenter_requested = p_recenter_requested
|
||||
|
||||
|
||||
func validation_error() -> String:
|
||||
if not is_finite(yaw_delta_radians) or not is_finite(pitch_delta_radians):
|
||||
return "camera look deltas must be finite"
|
||||
return ""
|
||||
@@ -0,0 +1,32 @@
|
||||
class_name PilotUseCase
|
||||
extends RefCounted
|
||||
|
||||
const VehicleCommand = preload("res://game/application/vehicle/vehicle_command.gd")
|
||||
const VehicleCommandResult = preload(
|
||||
"res://game/application/vehicle/vehicle_command_result.gd"
|
||||
)
|
||||
const VehicleMotionPort = preload("res://game/application/interfaces/vehicle_motion_port.gd")
|
||||
|
||||
var _motion_port: VehicleMotionPort
|
||||
var _last_sequence := -1
|
||||
|
||||
|
||||
func _init(motion_port: VehicleMotionPort) -> void:
|
||||
_motion_port = motion_port
|
||||
|
||||
|
||||
func execute(command: VehicleCommand) -> VehicleCommandResult:
|
||||
if command == null:
|
||||
return VehicleCommandResult.new(false, -1, "vehicle command is missing")
|
||||
var error: String = command.validation_error()
|
||||
if not error.is_empty():
|
||||
return VehicleCommandResult.new(false, command.sequence, error)
|
||||
if command.sequence != _last_sequence + 1:
|
||||
return VehicleCommandResult.new(
|
||||
false,
|
||||
command.sequence,
|
||||
"vehicle command sequence is not consecutive"
|
||||
)
|
||||
_motion_port.apply_command(command)
|
||||
_last_sequence = command.sequence
|
||||
return VehicleCommandResult.new(true, command.sequence)
|
||||
@@ -0,0 +1,16 @@
|
||||
class_name VehicleCollisionSample
|
||||
extends RefCounted
|
||||
|
||||
var sample_id: StringName
|
||||
var sequence: int
|
||||
var normal_impact_speed_mps: float
|
||||
|
||||
|
||||
func _init(
|
||||
p_sample_id: StringName,
|
||||
p_sequence: int,
|
||||
p_normal_impact_speed_mps: float
|
||||
) -> void:
|
||||
sample_id = p_sample_id
|
||||
sequence = p_sequence
|
||||
normal_impact_speed_mps = p_normal_impact_speed_mps
|
||||
@@ -0,0 +1,35 @@
|
||||
class_name VehicleCommand
|
||||
extends RefCounted
|
||||
|
||||
var sequence: int
|
||||
var longitudinal: float
|
||||
var steering: float
|
||||
var vertical: float
|
||||
var high_thrust_active: bool
|
||||
|
||||
|
||||
func _init(
|
||||
p_sequence: int,
|
||||
p_longitudinal: float,
|
||||
p_steering: float,
|
||||
p_vertical: float,
|
||||
p_high_thrust_active: bool
|
||||
) -> void:
|
||||
sequence = p_sequence
|
||||
longitudinal = p_longitudinal
|
||||
steering = p_steering
|
||||
vertical = p_vertical
|
||||
high_thrust_active = p_high_thrust_active
|
||||
|
||||
|
||||
func validation_error() -> String:
|
||||
if sequence < 0:
|
||||
return "vehicle command sequence is negative"
|
||||
for value: float in [longitudinal, steering, vertical]:
|
||||
if not is_finite(value) or value < -1.0 or value > 1.0:
|
||||
return "vehicle command axes must be finite and normalized"
|
||||
return ""
|
||||
|
||||
|
||||
static func neutral(p_sequence: int) -> VehicleCommand:
|
||||
return new(p_sequence, 0.0, 0.0, 0.0, false)
|
||||
@@ -0,0 +1,12 @@
|
||||
class_name VehicleCommandResult
|
||||
extends RefCounted
|
||||
|
||||
var accepted: bool
|
||||
var sequence: int
|
||||
var rejection_reason: String
|
||||
|
||||
|
||||
func _init(p_accepted: bool, p_sequence: int, p_rejection_reason: String = "") -> void:
|
||||
accepted = p_accepted
|
||||
sequence = p_sequence
|
||||
rejection_reason = p_rejection_reason
|
||||
Reference in new issue
Block a user