Adding elevation
All checks were successful
Deploy Promiscuity Auth API / deploy (push) Successful in 48s
Deploy Promiscuity Character API / deploy (push) Successful in 1m0s
Deploy Promiscuity Inventory API / deploy (push) Successful in 47s
Deploy Promiscuity Locations API / deploy (push) Successful in 1m0s
k8s smoke test / test (push) Successful in 9s
All checks were successful
Deploy Promiscuity Auth API / deploy (push) Successful in 48s
Deploy Promiscuity Character API / deploy (push) Successful in 1m0s
Deploy Promiscuity Inventory API / deploy (push) Successful in 47s
Deploy Promiscuity Locations API / deploy (push) Successful in 1m0s
k8s smoke test / test (push) Successful in 9s
This commit is contained in:
parent
c5e692c051
commit
f90de8a98b
@ -8,8 +8,9 @@ const SETTINGS_SCENE := "res://scenes/UI/Settings.tscn"
|
||||
const CHARACTER_SLOT_COUNT := 6
|
||||
|
||||
@export var tile_size := 8.0
|
||||
@export var block_height := 1.0
|
||||
@export_range(1, 8, 1) var tile_radius := 3
|
||||
@export var block_height := 1.0
|
||||
@export var elevation_step_height := 0.5
|
||||
@export_range(1, 8, 1) var tile_radius := 3
|
||||
@export var tracked_node_path: NodePath
|
||||
@export var player_spawn_height := 2.0
|
||||
@export var border_color: Color = Color(0.05, 0.05, 0.05, 1.0)
|
||||
@ -129,14 +130,14 @@ func _world_to_coord(world_pos: Vector3) -> Vector2i:
|
||||
)
|
||||
|
||||
|
||||
func _coord_to_world(coord: Vector2i) -> Vector3:
|
||||
return Vector3(coord.x * tile_size, block_height * 0.5, coord.y * tile_size)
|
||||
|
||||
|
||||
func _coord_to_world(coord: Vector2i) -> Vector3:
|
||||
return Vector3(coord.x * tile_size, _get_tile_center_y(coord), coord.y * tile_size)
|
||||
|
||||
|
||||
func _move_player_to_coord(coord: Vector2i) -> void:
|
||||
if _player == null:
|
||||
return
|
||||
_player.global_position = Vector3(coord.x * tile_size, player_spawn_height, coord.y * tile_size)
|
||||
_player.global_position = Vector3(coord.x * tile_size, _get_tile_surface_y(coord) + player_spawn_height, coord.y * tile_size)
|
||||
_player.linear_velocity = Vector3.ZERO
|
||||
_player.angular_velocity = Vector3.ZERO
|
||||
|
||||
@ -302,11 +303,12 @@ func _spawn_tile(coord: Vector2i, location_data: Dictionary) -> void:
|
||||
_tile_nodes[coord] = tile_root
|
||||
|
||||
|
||||
func _update_tile(coord: Vector2i, location_data: Dictionary) -> void:
|
||||
var tile_root := _tile_nodes.get(coord) as Node3D
|
||||
if tile_root == null:
|
||||
return
|
||||
|
||||
func _update_tile(coord: Vector2i, location_data: Dictionary) -> void:
|
||||
var tile_root := _tile_nodes.get(coord) as Node3D
|
||||
if tile_root == null:
|
||||
return
|
||||
tile_root.position = _coord_to_world(coord)
|
||||
|
||||
if show_tile_labels:
|
||||
var label := tile_root.get_node_or_null("LocationNameLabel") as Label3D
|
||||
if label:
|
||||
@ -480,6 +482,19 @@ func _build_floor_inventory_label(floor_items: Array) -> String:
|
||||
return label
|
||||
|
||||
|
||||
func _get_tile_elevation(coord: Vector2i) -> int:
|
||||
var location_data := _get_location_data(coord)
|
||||
return int(location_data.get("elevation", 0))
|
||||
|
||||
|
||||
func _get_tile_center_y(coord: Vector2i) -> float:
|
||||
return (_get_tile_elevation(coord) * elevation_step_height) + (block_height * 0.5)
|
||||
|
||||
|
||||
func _get_tile_surface_y(coord: Vector2i) -> float:
|
||||
return (_get_tile_elevation(coord) * elevation_step_height) + block_height
|
||||
|
||||
|
||||
func _update_inventory_location_label() -> void:
|
||||
if _inventory_location_label == null:
|
||||
return
|
||||
@ -812,6 +827,7 @@ func _ensure_selected_location_exists(coord: Vector2i) -> void:
|
||||
"id": "",
|
||||
"name": _selected_location_name(coord),
|
||||
"biomeKey": "plains",
|
||||
"elevation": 0,
|
||||
"locationObject": {},
|
||||
"floorItems": []
|
||||
}
|
||||
@ -889,6 +905,7 @@ func _load_existing_locations() -> void:
|
||||
"id": String(location.get("id", "")).strip_edges(),
|
||||
"name": location_name,
|
||||
"biomeKey": String(location.get("biomeKey", "plains")).strip_edges(),
|
||||
"elevation": int(location.get("elevation", 0)),
|
||||
"locationObject": _parse_location_object(location.get("locationObject", {})),
|
||||
"floorItems": _parse_floor_inventory_items(location.get("floorItems", []))
|
||||
}
|
||||
|
||||
@ -19,6 +19,9 @@ public class VisibleLocation
|
||||
[BsonElement("biomeKey")]
|
||||
public string BiomeKey { get; set; } = "plains";
|
||||
|
||||
[BsonElement("elevation")]
|
||||
public int Elevation { get; set; }
|
||||
|
||||
[BsonElement("locationObject")]
|
||||
public VisibleLocationObject? LocationObject { get; set; }
|
||||
|
||||
|
||||
@ -18,6 +18,9 @@ public class Location
|
||||
[BsonElement("biomeKey")]
|
||||
public string BiomeKey { get; set; } = "plains";
|
||||
|
||||
[BsonElement("elevation")]
|
||||
public int Elevation { get; set; }
|
||||
|
||||
[BsonElement("resources")]
|
||||
public List<LocationResource> Resources { get; set; } = [];
|
||||
|
||||
|
||||
@ -10,6 +10,8 @@ public class VisibleLocationResponse
|
||||
|
||||
public string BiomeKey { get; set; } = "plains";
|
||||
|
||||
public int Elevation { get; set; }
|
||||
|
||||
public VisibleLocationObjectResponse? LocationObject { get; set; }
|
||||
|
||||
public List<FloorInventoryItemResponse> FloorItems { get; set; } = [];
|
||||
|
||||
@ -38,7 +38,7 @@ public class LocationStore
|
||||
"$jsonSchema", new BsonDocument
|
||||
{
|
||||
{ "bsonType", "object" },
|
||||
{ "required", new BsonArray { "name", "coord", "biomeKey", "createdUtc" } },
|
||||
{ "required", new BsonArray { "name", "coord", "biomeKey", "elevation", "createdUtc" } },
|
||||
{
|
||||
"properties", new BsonDocument
|
||||
{
|
||||
@ -58,6 +58,7 @@ public class LocationStore
|
||||
}
|
||||
},
|
||||
{ "biomeKey", new BsonDocument { { "bsonType", "string" } } },
|
||||
{ "elevation", new BsonDocument { { "bsonType", "int" } } },
|
||||
{
|
||||
"resources", new BsonDocument
|
||||
{
|
||||
@ -348,6 +349,7 @@ public class LocationStore
|
||||
Name = "Origin",
|
||||
Coord = new Coord { X = 0, Y = 0 },
|
||||
BiomeKey = originBiomeKey,
|
||||
Elevation = 0,
|
||||
LocationObject = CreateLocationObjectForBiome(biomeDefinitions, originBiomeKey, 0, 0),
|
||||
LocationObjectResolved = true,
|
||||
CreatedUtc = DateTime.UtcNow
|
||||
@ -423,6 +425,7 @@ public class LocationStore
|
||||
}
|
||||
|
||||
var biomeKey = await DetermineBiomeKeyAsync(x, y, biomeDefinitions);
|
||||
var elevation = await DetermineElevationAsync(x, y, biomeKey);
|
||||
var locationObject = CreateLocationObjectForBiome(biomeDefinitions, biomeKey, x, y);
|
||||
BsonValue locationObjectValue = locationObject is null ? BsonNull.Value : locationObject.ToBsonDocument();
|
||||
var update = Builders<BsonDocument>.Update
|
||||
@ -430,6 +433,7 @@ public class LocationStore
|
||||
.SetOnInsert("name", DefaultLocationName(x, y))
|
||||
.SetOnInsert("coord", new BsonDocument { { "x", x }, { "y", y } })
|
||||
.SetOnInsert("biomeKey", biomeKey)
|
||||
.SetOnInsert("elevation", elevation)
|
||||
.SetOnInsert("locationObject", locationObjectValue)
|
||||
.SetOnInsert("locationObjectResolved", true)
|
||||
.SetOnInsert("createdUtc", DateTime.UtcNow);
|
||||
@ -447,13 +451,16 @@ public class LocationStore
|
||||
|
||||
private async Task<Location> EnsureLocationMetadataAsync(Location location)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(location.BiomeKey) && location.LocationObjectResolved)
|
||||
var locationId = location.Id ?? string.Empty;
|
||||
var hasElevation = !string.IsNullOrWhiteSpace(locationId) && await HasStoredElevationAsync(locationId);
|
||||
if (!string.IsNullOrWhiteSpace(location.BiomeKey) && location.LocationObjectResolved && hasElevation)
|
||||
return location;
|
||||
|
||||
var biomeDefinitions = await LoadBiomeDefinitionsAsync();
|
||||
var biomeKey = location.BiomeKey;
|
||||
if (string.IsNullOrWhiteSpace(biomeKey))
|
||||
biomeKey = await DetermineBiomeKeyAsync(location.Coord.X, location.Coord.Y, biomeDefinitions);
|
||||
var elevation = hasElevation ? location.Elevation : await DetermineElevationAsync(location.Coord.X, location.Coord.Y, biomeKey);
|
||||
|
||||
var migratedObject = TryMigrateLegacyResources(location) ?? CreateLocationObjectForBiome(biomeDefinitions, biomeKey, location.Coord.X, location.Coord.Y);
|
||||
var filter = Builders<Location>.Filter.And(
|
||||
@ -461,10 +468,12 @@ public class LocationStore
|
||||
);
|
||||
var update = Builders<Location>.Update
|
||||
.Set(l => l.BiomeKey, biomeKey)
|
||||
.Set(l => l.Elevation, elevation)
|
||||
.Set(l => l.LocationObjectResolved, true)
|
||||
.Set(l => l.LocationObject, migratedObject);
|
||||
await _col.UpdateOneAsync(filter, update);
|
||||
location.BiomeKey = biomeKey;
|
||||
location.Elevation = elevation;
|
||||
location.LocationObject = migratedObject;
|
||||
location.LocationObjectResolved = true;
|
||||
return location;
|
||||
@ -478,6 +487,7 @@ public class LocationStore
|
||||
Name = location.Name,
|
||||
Coord = new Coord { X = location.Coord.X, Y = location.Coord.Y },
|
||||
BiomeKey = location.BiomeKey,
|
||||
Elevation = location.Elevation,
|
||||
LocationObject = MapVisibleLocationObject(location.LocationObject)
|
||||
};
|
||||
}
|
||||
@ -571,6 +581,23 @@ public class LocationStore
|
||||
return bestBiome;
|
||||
}
|
||||
|
||||
private async Task<int> DetermineElevationAsync(int x, int y, string biomeKey)
|
||||
{
|
||||
if (x == 0 && y == 0)
|
||||
return 0;
|
||||
|
||||
var baseElevation = DetermineBaseElevation(x, y, biomeKey);
|
||||
var neighbors = await LoadNeighborElevationsAsync(x, y);
|
||||
if (neighbors.Count == 0)
|
||||
return baseElevation;
|
||||
|
||||
var averageNeighbor = (int)Math.Round(neighbors.Average());
|
||||
var blended = (int)Math.Round((baseElevation + averageNeighbor) / 2.0);
|
||||
var minNeighbor = neighbors.Min();
|
||||
var maxNeighbor = neighbors.Max();
|
||||
return Math.Clamp(blended, minNeighbor - 1, maxNeighbor + 1);
|
||||
}
|
||||
|
||||
private static LocationObject? CreateLocationObjectForBiome(IReadOnlyList<BiomeDefinition> biomeDefinitions, string biomeKey, int x, int y)
|
||||
{
|
||||
var biome = biomeDefinitions.FirstOrDefault(definition => definition.BiomeKey == biomeKey)
|
||||
@ -655,6 +682,32 @@ public class LocationStore
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private async Task<List<int>> LoadNeighborElevationsAsync(int x, int y)
|
||||
{
|
||||
var coords = new[] { (x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1) };
|
||||
var filters = coords.Select(coord =>
|
||||
Builders<BsonDocument>.Filter.And(
|
||||
Builders<BsonDocument>.Filter.Eq("coord.x", coord.Item1),
|
||||
Builders<BsonDocument>.Filter.Eq("coord.y", coord.Item2)))
|
||||
.ToList();
|
||||
var filter = Builders<BsonDocument>.Filter.Or(filters);
|
||||
var neighbors = await _rawCol.Find(filter).ToListAsync();
|
||||
|
||||
return neighbors
|
||||
.Where(doc => doc.Contains("elevation") && doc["elevation"].IsInt32)
|
||||
.Select(doc => doc["elevation"].AsInt32)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private async Task<bool> HasStoredElevationAsync(string locationId)
|
||||
{
|
||||
var filter = Builders<BsonDocument>.Filter.And(
|
||||
Builders<BsonDocument>.Filter.Eq("_id", ObjectId.Parse(locationId)),
|
||||
Builders<BsonDocument>.Filter.Exists("elevation", true)
|
||||
);
|
||||
return await _rawCol.Find(filter).AnyAsync();
|
||||
}
|
||||
|
||||
private List<BiomeDefinition> LoadBiomeDefinitions()
|
||||
{
|
||||
return _biomeDefinitions.Find(Builders<BiomeDefinition>.Filter.Empty)
|
||||
@ -689,6 +742,22 @@ public class LocationStore
|
||||
return "plains";
|
||||
}
|
||||
|
||||
private static int DetermineBaseElevation(int x, int y, string biomeKey)
|
||||
{
|
||||
var macro = StableNoise(x, y, 404);
|
||||
var micro = StableNoise(x, y, 505);
|
||||
|
||||
return biomeKey switch
|
||||
{
|
||||
"wetlands" => (int)Math.Round((macro * 2.0) - 1.0),
|
||||
"plains" => (int)Math.Round((macro * 3.0) - 1.0),
|
||||
"forest" => (int)Math.Round((macro * 4.0) - 1.5),
|
||||
"desert" => (int)Math.Round((macro * 3.0) - 1.0 + ((micro - 0.5) * 0.75)),
|
||||
"rocky" => (int)Math.Round((macro * 5.0) - 1.0 + ((micro - 0.5) * 1.25)),
|
||||
_ => (int)Math.Round((macro * 3.0) - 1.0)
|
||||
};
|
||||
}
|
||||
|
||||
private static double StableNoise(int x, int y, int salt)
|
||||
{
|
||||
var value = Math.Sin((x * 12.9898) + (y * 78.233) + ((1729 + salt) * 0.1597)) * 43758.5453;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user