feat: data-oriented chunks optimization with tile registry
- Phase 1: Bit-packed standability (ChunkData with bitsets) - Phase 2: Reactive connectivity (dirty chunks) - Phase 3: Async terrain baking (AsyncComputeTaskPool) - Pathfinding weight system (rock=50 preferred, bedrock=150 avoided) - Movement speed affected by tile weight - External tiles.toml for hot-reloadable tile definitions - TileRegistry singleton for async-safe tile lookups - Fixed world_to_chunk to use CHUNK_SIZE_TILE (128) not CHUNK_SIZE (8) - Fixed infinite spawner with Local<bool> state guards - Fixed spawn coordinate grid alignment Note: Zigzag pathfinding bug introduced - needs investigation
This commit is contained in:
+110
-13
@@ -1,11 +1,11 @@
|
||||
use bevy::prelude::*;
|
||||
use bevy::tasks::AsyncComputeTaskPool;
|
||||
use bevy_platform::collections::HashMap;
|
||||
use bevy_platform::time::Instant;
|
||||
use noise::{NoiseFn, Perlin};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::{
|
||||
config::TileRegistry,
|
||||
constants::{SEED, TILE_SIZE},
|
||||
world::{
|
||||
tiles::{ChunkData, FloorTileData, TileMap, TerrainSpriteState, CurrentWorldSpriteState},
|
||||
@@ -70,6 +70,7 @@ fn generate_terrain_blob(chunk_pos: IVec2) -> TerrainBlob {
|
||||
let cave_noise = Perlin::new(SEED);
|
||||
let start_x = chunk_pos.x * CHUNK_SIZE;
|
||||
let start_y = chunk_pos.y * CHUNK_SIZE;
|
||||
let registry = TileRegistry::global();
|
||||
|
||||
let mut chunk_data = ChunkData::new(chunk_pos);
|
||||
let mut tile_updates: Vec<(IVec3, FloorTileData)> = Vec::new();
|
||||
@@ -105,51 +106,147 @@ fn generate_terrain_blob(chunk_pos: IVec2) -> TerrainBlob {
|
||||
z as f64 * 0.05,
|
||||
]);
|
||||
if cave_value < -0.75 {
|
||||
let tile = registry.floor("air");
|
||||
tile_spawns.push((position, FloorTilePrefab::air(position)));
|
||||
tile_updates.push((
|
||||
pos_ivec,
|
||||
FloorTileData::new(0, true, false, true, 0, [0; 8]),
|
||||
FloorTileData::new(
|
||||
tile.id,
|
||||
tile.can_stand_in,
|
||||
tile.can_stand_on,
|
||||
tile.transparent,
|
||||
tile.astar_weight,
|
||||
[0; 8],
|
||||
),
|
||||
));
|
||||
chunk_data.set_floor_tile(local_x, local_y, local_z, 0, true, false);
|
||||
chunk_data.set_floor_tile(
|
||||
local_x,
|
||||
local_y,
|
||||
local_z,
|
||||
tile.id,
|
||||
tile.can_stand_in,
|
||||
tile.can_stand_on,
|
||||
tile.astar_weight,
|
||||
);
|
||||
} else if cave_value < 0.8 {
|
||||
let tile = registry.floor("rock");
|
||||
tile_spawns.push((position, FloorTilePrefab::rock(position)));
|
||||
tile_updates.push((
|
||||
pos_ivec,
|
||||
FloorTileData::new(2, false, true, false, 50, [0; 8]),
|
||||
FloorTileData::new(
|
||||
tile.id,
|
||||
tile.can_stand_in,
|
||||
tile.can_stand_on,
|
||||
tile.transparent,
|
||||
tile.astar_weight,
|
||||
[0; 8],
|
||||
),
|
||||
));
|
||||
chunk_data.set_floor_tile(local_x, local_y, local_z, 2, false, true);
|
||||
chunk_data.set_floor_tile(
|
||||
local_x,
|
||||
local_y,
|
||||
local_z,
|
||||
tile.id,
|
||||
tile.can_stand_in,
|
||||
tile.can_stand_on,
|
||||
tile.astar_weight,
|
||||
);
|
||||
} else {
|
||||
let tile = registry.floor("dirt");
|
||||
tile_spawns.push((position, FloorTilePrefab::dirt(position)));
|
||||
tile_updates.push((
|
||||
pos_ivec,
|
||||
FloorTileData::new(1, false, true, false, 85, [0; 8]),
|
||||
FloorTileData::new(
|
||||
tile.id,
|
||||
tile.can_stand_in,
|
||||
tile.can_stand_on,
|
||||
tile.transparent,
|
||||
tile.astar_weight,
|
||||
[0; 8],
|
||||
),
|
||||
));
|
||||
chunk_data.set_floor_tile(local_x, local_y, local_z, 1, false, true);
|
||||
chunk_data.set_floor_tile(
|
||||
local_x,
|
||||
local_y,
|
||||
local_z,
|
||||
tile.id,
|
||||
tile.can_stand_in,
|
||||
tile.can_stand_on,
|
||||
tile.astar_weight,
|
||||
);
|
||||
}
|
||||
} else if noise_position.z > position.z {
|
||||
if surface_height <= position.z + TILE_SIZE {
|
||||
let tile = registry.floor("grass");
|
||||
tile_spawns.push((position, FloorTilePrefab::grass(position)));
|
||||
tile_updates.push((
|
||||
pos_ivec,
|
||||
FloorTileData::new(1, false, true, false, 100, [0; 8]),
|
||||
FloorTileData::new(
|
||||
tile.id,
|
||||
tile.can_stand_in,
|
||||
tile.can_stand_on,
|
||||
tile.transparent,
|
||||
tile.astar_weight,
|
||||
[0; 8],
|
||||
),
|
||||
));
|
||||
chunk_data.set_floor_tile(local_x, local_y, local_z, 1, false, true);
|
||||
chunk_data.set_floor_tile(
|
||||
local_x,
|
||||
local_y,
|
||||
local_z,
|
||||
tile.id,
|
||||
tile.can_stand_in,
|
||||
tile.can_stand_on,
|
||||
tile.astar_weight,
|
||||
);
|
||||
surface_positions.push((position, "grass".to_string()));
|
||||
} else {
|
||||
let tile = registry.floor("dirt");
|
||||
tile_spawns.push((position, FloorTilePrefab::dirt(position)));
|
||||
tile_updates.push((
|
||||
pos_ivec,
|
||||
FloorTileData::new(1, false, true, false, 85, [0; 8]),
|
||||
FloorTileData::new(
|
||||
tile.id,
|
||||
tile.can_stand_in,
|
||||
tile.can_stand_on,
|
||||
tile.transparent,
|
||||
tile.astar_weight,
|
||||
[0; 8],
|
||||
),
|
||||
));
|
||||
chunk_data.set_floor_tile(local_x, local_y, local_z, 1, false, true);
|
||||
chunk_data.set_floor_tile(
|
||||
local_x,
|
||||
local_y,
|
||||
local_z,
|
||||
tile.id,
|
||||
tile.can_stand_in,
|
||||
tile.can_stand_on,
|
||||
tile.astar_weight,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let tile = registry.floor("air");
|
||||
tile_spawns.push((position, FloorTilePrefab::air(position)));
|
||||
tile_updates.push((
|
||||
pos_ivec,
|
||||
FloorTileData::new(0, true, false, true, 0, [0; 8]),
|
||||
FloorTileData::new(
|
||||
tile.id,
|
||||
tile.can_stand_in,
|
||||
tile.can_stand_on,
|
||||
tile.transparent,
|
||||
tile.astar_weight,
|
||||
[0; 8],
|
||||
),
|
||||
));
|
||||
chunk_data.set_floor_tile(local_x, local_y, local_z, 0, true, false);
|
||||
chunk_data.set_floor_tile(
|
||||
local_x,
|
||||
local_y,
|
||||
local_z,
|
||||
tile.id,
|
||||
tile.can_stand_in,
|
||||
tile.can_stand_on,
|
||||
tile.astar_weight,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user