Reintroduce multiple maps: per-map chunk directories + map_t name/mapSetMap
Move chunk assets from a single flat assetsraw/chunks (and assets/chunks) into per-map assetsraw/maps/<map>/chunks (assets/maps/<map>/chunks), so terrain mesh/model output no longer collides across maps sharing chunk coordinates. map_t gains a name[MAP_NAME_MAX] field plus mapSetMap()/ mapIsLoaded() (checks name[0] == '\0') in place of the old bool loaded flag; mapInit() now just resets state and mapSetMap() does the chunk grid load. Updated the chunk asset tool and the map editor's dev server/client to match.
This commit is contained in:
1 parent
b3623c84a5
commit
db42bca44b
32 files changed
+123
-45
No files matched your search
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"mesh": "meshes/chunks/chunk_-1_0_0_0.dmf",
|
"mesh": "maps/overworld/meshes/chunks/chunk_-1_0_0_0.dmf",
|
||||||
"color": [
|
"color": [
|
||||||
255,
|
255,
|
||||||
255,
|
255,
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"mesh": "meshes/chunks/chunk_0_0_0_0.dmf",
|
"mesh": "maps/overworld/meshes/chunks/chunk_0_0_0_0.dmf",
|
||||||
"color": [
|
"color": [
|
||||||
255,
|
255,
|
||||||
255,
|
255,
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"mesh": "meshes/chunks/chunk_0_1_0_0.dmf",
|
"mesh": "maps/overworld/meshes/chunks/chunk_0_1_0_0.dmf",
|
||||||
"color": [
|
"color": [
|
||||||
255,
|
255,
|
||||||
255,
|
255,
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"mesh": "meshes/chunks/chunk_1_0_0_0.dmf",
|
"mesh": "maps/overworld/meshes/chunks/chunk_1_0_0_0.dmf",
|
||||||
"color": [
|
"color": [
|
||||||
255,
|
255,
|
||||||
255,
|
255,
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"mesh": "meshes/chunks/chunk_1_1_0_0.dmf",
|
"mesh": "maps/overworld/meshes/chunks/chunk_1_1_0_0.dmf",
|
||||||
"color": [
|
"color": [
|
||||||
255,
|
255,
|
||||||
255,
|
255,
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"mesh": "meshes/chunks/chunk_2_0_0_0.dmf",
|
"mesh": "maps/overworld/meshes/chunks/chunk_2_0_0_0.dmf",
|
||||||
"color": [
|
"color": [
|
||||||
255,
|
255,
|
||||||
255,
|
255,
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@@ -345,12 +345,14 @@
|
|||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MAP_NAME = "overworld";
|
||||||
|
|
||||||
function chunkPaths(x, y, z) {
|
function chunkPaths(x, y, z) {
|
||||||
return {
|
return {
|
||||||
raw: `assetsraw/chunks/chunk_${x}_${y}_${z}.json`,
|
raw: `assetsraw/maps/${MAP_NAME}/chunks/chunk_${x}_${y}_${z}.json`,
|
||||||
dcf: `assets/chunks/${x}_${y}_${z}.dcf`,
|
dcf: `assets/maps/${MAP_NAME}/chunks/${x}_${y}_${z}.dcf`,
|
||||||
terrainDmf: `assets/meshes/chunks/chunk_${x}_${y}_${z}_0.dmf`,
|
terrainDmf: `assets/maps/${MAP_NAME}/meshes/chunks/chunk_${x}_${y}_${z}_0.dmf`,
|
||||||
terrainModel: `assets/models/chunks/chunk_${x}_${y}_${z}_0.json`,
|
terrainModel: `assets/maps/${MAP_NAME}/models/chunks/chunk_${x}_${y}_${z}_0.json`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -767,7 +769,7 @@
|
|||||||
async function buildChunkBrowseList() {
|
async function buildChunkBrowseList() {
|
||||||
const list = document.getElementById("chunkBrowseList");
|
const list = document.getElementById("chunkBrowseList");
|
||||||
list.innerHTML = "";
|
list.innerHTML = "";
|
||||||
const res = await apiLs("assetsraw/chunks");
|
const res = await apiLs(`assetsraw/maps/${MAP_NAME}/chunks`);
|
||||||
for(const entry of res.entries || []) {
|
for(const entry of res.entries || []) {
|
||||||
const m = entry.name.match(/^chunk_(-?\d+)_(-?\d+)_(-?\d+)\.json$/);
|
const m = entry.name.match(/^chunk_(-?\d+)_(-?\d+)_(-?\d+)\.json$/);
|
||||||
if(!m) continue;
|
if(!m) continue;
|
||||||
|
|||||||
@@ -209,7 +209,10 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
self.send_json({"error": "invalid chunk coordinates"}, 400)
|
self.send_json({"error": "invalid chunk coordinates"}, 400)
|
||||||
return
|
return
|
||||||
|
|
||||||
json_path = PROJECT_ROOT / "assetsraw" / "chunks" / f"chunk_{x}_{y}_{z}.json"
|
json_path = (
|
||||||
|
PROJECT_ROOT / "assetsraw" / "maps" / "overworld" / "chunks"
|
||||||
|
/ f"chunk_{x}_{y}_{z}.json"
|
||||||
|
)
|
||||||
if not json_path.is_file():
|
if not json_path.is_file():
|
||||||
self.send_json({"error": "chunk json not found"}, 404)
|
self.send_json({"error": "chunk json not found"}, 404)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -28,7 +28,25 @@ void mapChunkLoadingSlotClear(chunk_t *chunk) {
|
|||||||
|
|
||||||
errorret_t mapInit() {
|
errorret_t mapInit() {
|
||||||
memoryZero(&MAP, sizeof(map_t));
|
memoryZero(&MAP, sizeof(map_t));
|
||||||
MAP.loaded = true;
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t mapIsLoaded() {
|
||||||
|
return MAP.name[0] != '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t mapSetMap(const char_t *map) {
|
||||||
|
assertNotNull(map, "mapSetMap: map name cannot be NULL");
|
||||||
|
assertStrLenMax(map, MAP_NAME_MAX, "Map name too long");
|
||||||
|
|
||||||
|
if(mapIsLoaded()) {
|
||||||
|
for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) {
|
||||||
|
mapChunkUnload(&MAP.chunks[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memoryZero(&MAP, sizeof(map_t));
|
||||||
|
stringCopy(MAP.name, map, MAP_NAME_MAX);
|
||||||
|
|
||||||
chunkindex_t i = 0;
|
chunkindex_t i = 0;
|
||||||
for(chunkunit_t z = 0; z < MAP_CHUNK_DEPTH; z++) {
|
for(chunkunit_t z = 0; z < MAP_CHUNK_DEPTH; z++) {
|
||||||
@@ -47,10 +65,6 @@ errorret_t mapInit() {
|
|||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t mapIsLoaded() {
|
|
||||||
return MAP.loaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
errorret_t mapPositionSet(const chunkpos_t newPos) {
|
errorret_t mapPositionSet(const chunkpos_t newPos) {
|
||||||
if(!mapIsLoaded()) errorThrow("No map loaded");
|
if(!mapIsLoaded()) errorThrow("No map loaded");
|
||||||
if(chunkPositionIsEqual(newPos, MAP.chunkPosition)) errorOk();
|
if(chunkPositionIsEqual(newPos, MAP.chunkPosition)) errorOk();
|
||||||
@@ -132,6 +146,7 @@ errorret_t mapDispose() {
|
|||||||
for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) {
|
for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) {
|
||||||
mapChunkUnload(&MAP.chunks[i]);
|
mapChunkUnload(&MAP.chunks[i]);
|
||||||
}
|
}
|
||||||
|
MAP.name[0] = '\0';
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,10 +218,11 @@ errorret_t mapChunkLoad(chunk_t *chunk) {
|
|||||||
|
|
||||||
chunk->meshCount = 0;
|
chunk->meshCount = 0;
|
||||||
|
|
||||||
char_t name[64];
|
char_t name[MAP_FILE_PATH_MAX];
|
||||||
stringFormat(
|
stringFormat(
|
||||||
name, sizeof(name),
|
name, sizeof(name),
|
||||||
"chunks/%d_%d_%d.dcf",
|
"maps/%s/chunks/%d_%d_%d.dcf",
|
||||||
|
MAP.name,
|
||||||
(int32_t)chunk->position.x,
|
(int32_t)chunk->position.x,
|
||||||
(int32_t)chunk->position.y,
|
(int32_t)chunk->position.y,
|
||||||
(int32_t)chunk->position.z
|
(int32_t)chunk->position.z
|
||||||
@@ -241,10 +257,11 @@ void mapChunkLoadNext() {
|
|||||||
MAP.loadQueueCount--;
|
MAP.loadQueueCount--;
|
||||||
MAP.loadingChunks[slot] = chunk;
|
MAP.loadingChunks[slot] = chunk;
|
||||||
|
|
||||||
char_t name[64];
|
char_t name[MAP_FILE_PATH_MAX];
|
||||||
stringFormat(
|
stringFormat(
|
||||||
name, sizeof(name),
|
name, sizeof(name),
|
||||||
"chunks/%d_%d_%d.dcf",
|
"maps/%s/chunks/%d_%d_%d.dcf",
|
||||||
|
MAP.name,
|
||||||
(int32_t)chunk->position.x,
|
(int32_t)chunk->position.x,
|
||||||
(int32_t)chunk->position.y,
|
(int32_t)chunk->position.y,
|
||||||
(int32_t)chunk->position.z
|
(int32_t)chunk->position.z
|
||||||
|
|||||||
@@ -12,12 +12,18 @@
|
|||||||
|
|
||||||
#define MAP_FILE_PATH_MAX 128
|
#define MAP_FILE_PATH_MAX 128
|
||||||
|
|
||||||
|
// Buffer size for a map's name, including the null terminator - so map
|
||||||
|
// names are at most 9 characters.
|
||||||
|
#define MAP_NAME_MAX 10
|
||||||
|
|
||||||
// Number of chunks that may be mid-load (asset locked & awaiting onLoaded/
|
// Number of chunks that may be mid-load (asset locked & awaiting onLoaded/
|
||||||
// onError) at the same time - everything past this waits in loadQueue.
|
// onError) at the same time - everything past this waits in loadQueue.
|
||||||
#define MAP_CHUNK_LOAD_CONCURRENCY 2
|
#define MAP_CHUNK_LOAD_CONCURRENCY 2
|
||||||
|
|
||||||
typedef struct map_s {
|
typedef struct map_s {
|
||||||
bool_t loaded;
|
// Name of the currently loaded map, or an empty string if none is
|
||||||
|
// loaded (see mapIsLoaded).
|
||||||
|
char_t name[MAP_NAME_MAX];
|
||||||
|
|
||||||
chunk_t chunks[MAP_CHUNK_COUNT];
|
chunk_t chunks[MAP_CHUNK_COUNT];
|
||||||
chunk_t *chunkOrder[MAP_CHUNK_COUNT];
|
chunk_t *chunkOrder[MAP_CHUNK_COUNT];
|
||||||
@@ -31,7 +37,8 @@ typedef struct map_s {
|
|||||||
extern map_t MAP;
|
extern map_t MAP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the map.
|
* Initializes the map subsystem. No map is loaded until mapSetMap is
|
||||||
|
* called.
|
||||||
*
|
*
|
||||||
* @return An error code.
|
* @return An error code.
|
||||||
*/
|
*/
|
||||||
@@ -44,6 +51,16 @@ errorret_t mapInit();
|
|||||||
*/
|
*/
|
||||||
bool_t mapIsLoaded();
|
bool_t mapIsLoaded();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the active map by name, unloading the previously loaded map (if
|
||||||
|
* any) first, then starts loading the new map's chunks around chunk
|
||||||
|
* position (0, 0, 0).
|
||||||
|
*
|
||||||
|
* @param map The map's name, at most MAP_NAME_MAX - 1 characters.
|
||||||
|
* @return An error code.
|
||||||
|
*/
|
||||||
|
errorret_t mapSetMap(const char_t *map);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the map.
|
* Updates the map.
|
||||||
*
|
*
|
||||||
|
|||||||
+1
-2
@@ -32,9 +32,8 @@ errorret_t rpgInit(void) {
|
|||||||
errorChain(mapInit());
|
errorChain(mapInit());
|
||||||
rpgCameraInit();
|
rpgCameraInit();
|
||||||
|
|
||||||
|
|
||||||
// Init test world
|
// Init test world
|
||||||
errorChain(mapPositionSet((chunkpos_t){ 0, 0, 0 }));
|
errorChain(mapSetMap("overworld"));
|
||||||
|
|
||||||
// The player is the one entity that isn't sourced from map/chunk data -
|
// The player is the one entity that isn't sourced from map/chunk data -
|
||||||
// every other entity (NPCs, items) and map area comes from the loaded
|
// every other entity (NPCs, items) and map area comes from the loaded
|
||||||
|
|||||||
@@ -9,12 +9,13 @@
|
|||||||
#include "rpg/overworld/map.h"
|
#include "rpg/overworld/map.h"
|
||||||
#include "rpg/overworld/tile.h"
|
#include "rpg/overworld/tile.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
|
||||||
void entityTestFixtureReset(void) {
|
void entityTestFixtureReset(void) {
|
||||||
memoryZero(ENTITIES, sizeof(ENTITIES));
|
memoryZero(ENTITIES, sizeof(ENTITIES));
|
||||||
|
|
||||||
memoryZero(&MAP, sizeof(map_t));
|
memoryZero(&MAP, sizeof(map_t));
|
||||||
MAP.loaded = true;
|
stringCopy(MAP.name, "test", MAP_NAME_MAX);
|
||||||
MAP.chunkPosition = (chunkpos_t){ 0, 0, 0 };
|
MAP.chunkPosition = (chunkpos_t){ 0, 0, 0 };
|
||||||
|
|
||||||
chunk_t *chunk = &MAP.chunks[0];
|
chunk_t *chunk = &MAP.chunks[0];
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
Generates DCF + companion DMF files from raw chunk JSON files, or upgrades
|
Generates DCF + companion DMF files from raw chunk JSON files, or upgrades
|
||||||
legacy DCF files (version 1 or 2) to the current version.
|
legacy DCF files (version 1 or 2) to the current version.
|
||||||
|
|
||||||
JSON input (assetsraw/chunks/chunk_X_Y_Z.json):
|
JSON input (assetsraw/maps/<map>/chunks/chunk_X_Y_Z.json):
|
||||||
{
|
{
|
||||||
"tiles": [
|
"tiles": [
|
||||||
{ "pos": [x, y, z], "type": <tile_shape_int>, "tile": <uv_tile_int> }
|
{ "pos": [x, y, z], "type": <tile_shape_int>, "tile": <uv_tile_int> }
|
||||||
@@ -35,6 +35,9 @@ JSON input (assetsraw/chunks/chunk_X_Y_Z.json):
|
|||||||
Mesh files are located by searching under assets/meshes/ and referenced by
|
Mesh files are located by searching under assets/meshes/ and referenced by
|
||||||
path from the assets root in the DCF.
|
path from the assets root in the DCF.
|
||||||
|
|
||||||
|
<map> is the map's name, up to 9 characters (MAP_NAME_MAX in
|
||||||
|
src/dusk/rpg/overworld/map.h reserves 1 byte for the null terminator).
|
||||||
|
|
||||||
"entities" spawns things into the world when this chunk loads. A "global"
|
"entities" spawns things into the world when this chunk loads. A "global"
|
||||||
entity is spawned via mapSpawnEntity() - globalId indexes
|
entity is spawned via mapSpawnEntity() - globalId indexes
|
||||||
ENTITY_GLOBAL_LIST (src/dusk/rpg/entity/global/entitygloballist.h) and is
|
ENTITY_GLOBAL_LIST (src/dusk/rpg/entity/global/entitygloballist.h) and is
|
||||||
@@ -53,7 +56,8 @@ JSON input (assetsraw/chunks/chunk_X_Y_Z.json):
|
|||||||
trigger is bitwise MAP_TRIGGER_STEP(1)|ENTER(2)|EXIT(4).
|
trigger is bitwise MAP_TRIGGER_STEP(1)|ENTER(2)|EXIT(4).
|
||||||
|
|
||||||
Output DCF is derived automatically:
|
Output DCF is derived automatically:
|
||||||
assetsraw/chunks/chunk_X_Y_Z.json -> assets/chunks/X_Y_Z.dcf
|
assetsraw/maps/<map>/chunks/chunk_X_Y_Z.json
|
||||||
|
-> assets/maps/<map>/chunks/X_Y_Z.dcf
|
||||||
|
|
||||||
Version 5 DCF format (after 8-byte header):
|
Version 5 DCF format (after 8-byte header):
|
||||||
tile_t tiles[CHUNK_WIDTH * CHUNK_HEIGHT] (one per x/y column)
|
tile_t tiles[CHUNK_WIDTH * CHUNK_HEIGHT] (one per x/y column)
|
||||||
@@ -85,7 +89,7 @@ DMF format:
|
|||||||
Each vertex: uv[2] + pos[3] = 5 x float32 LE = 20 bytes
|
Each vertex: uv[2] + pos[3] = 5 x float32 LE = 20 bytes
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
python3 -m tools.asset.chunk # process all assetsraw/chunks/*.json
|
python3 -m tools.asset.chunk # process all assetsraw/maps/*/chunks/*.json
|
||||||
python3 -m tools.asset.chunk <file.json> # process one JSON file
|
python3 -m tools.asset.chunk <file.json> # process one JSON file
|
||||||
python3 -m tools.asset.chunk <file.dcf> # upgrade legacy (v1/v2) DCF in-place
|
python3 -m tools.asset.chunk <file.dcf> # upgrade legacy (v1/v2) DCF in-place
|
||||||
"""
|
"""
|
||||||
@@ -118,6 +122,10 @@ CHUNK_MESH_NAME_MAX = 64
|
|||||||
CHUNK_ENTITY_SPAWN_COUNT_MAX = 8
|
CHUNK_ENTITY_SPAWN_COUNT_MAX = 8
|
||||||
CHUNK_AREA_COUNT_MAX = 4
|
CHUNK_AREA_COUNT_MAX = 4
|
||||||
|
|
||||||
|
# Matches MAP_NAME_MAX in src/dusk/rpg/overworld/map.h (buffer size,
|
||||||
|
# including the null terminator - so map names are at most 9 characters).
|
||||||
|
MAP_NAME_MAX = 10
|
||||||
|
|
||||||
ENTITY_SPAWN_KIND_GLOBAL = 0
|
ENTITY_SPAWN_KIND_GLOBAL = 0
|
||||||
ENTITY_SPAWN_KIND_ITEM = 1
|
ENTITY_SPAWN_KIND_ITEM = 1
|
||||||
|
|
||||||
@@ -188,8 +196,29 @@ def write_model_json(path, mesh_rel, texture_rel, color):
|
|||||||
print(f' Wrote model JSON {path}')
|
print(f' Wrote model JSON {path}')
|
||||||
|
|
||||||
|
|
||||||
|
def chunk_map_name(json_path):
|
||||||
|
"""assetsraw/maps/<map>/chunks/chunk_X_Y_Z.json -> <map>
|
||||||
|
|
||||||
|
Raises ValueError if json_path isn't under that structure, or if <map>
|
||||||
|
is longer than MAP_NAME_MAX - 1 characters."""
|
||||||
|
rel = os.path.relpath(os.path.abspath(json_path), ASSETSRAW_DIR)
|
||||||
|
parts = rel.split(os.sep)
|
||||||
|
if len(parts) != 4 or parts[0] != 'maps' or parts[2] != 'chunks':
|
||||||
|
raise ValueError(
|
||||||
|
f"Chunk JSON must live at assetsraw/maps/<map>/chunks/*.json, got: "
|
||||||
|
f"{json_path}"
|
||||||
|
)
|
||||||
|
map_name = parts[1]
|
||||||
|
if len(map_name) > MAP_NAME_MAX - 1:
|
||||||
|
raise ValueError(
|
||||||
|
f"Map name too long (> {MAP_NAME_MAX - 1} characters): {map_name}"
|
||||||
|
)
|
||||||
|
return map_name
|
||||||
|
|
||||||
|
|
||||||
def derive_dcf_path(json_path):
|
def derive_dcf_path(json_path):
|
||||||
"""assetsraw/chunks/chunk_X_Y_Z.json -> assets/chunks/X_Y_Z.dcf"""
|
"""assetsraw/maps/<map>/chunks/chunk_X_Y_Z.json
|
||||||
|
-> assets/maps/<map>/chunks/X_Y_Z.dcf"""
|
||||||
base = os.path.splitext(os.path.basename(json_path))[0]
|
base = os.path.splitext(os.path.basename(json_path))[0]
|
||||||
if base.startswith('chunk_'):
|
if base.startswith('chunk_'):
|
||||||
base = base[len('chunk_'):]
|
base = base[len('chunk_'):]
|
||||||
@@ -351,6 +380,8 @@ def build_terrain_verts(tiles_bytes):
|
|||||||
|
|
||||||
|
|
||||||
def from_json(json_path, dcf_path):
|
def from_json(json_path, dcf_path):
|
||||||
|
map_name = chunk_map_name(json_path)
|
||||||
|
|
||||||
with open(json_path) as f:
|
with open(json_path) as f:
|
||||||
data = json.load(f)
|
data = json.load(f)
|
||||||
|
|
||||||
@@ -377,15 +408,17 @@ def from_json(json_path, dcf_path):
|
|||||||
|
|
||||||
dcf_base = os.path.splitext(os.path.basename(dcf_path))[0]
|
dcf_base = os.path.splitext(os.path.basename(dcf_path))[0]
|
||||||
|
|
||||||
# Terrain mesh + model (only written if non-empty)
|
# Terrain mesh + model (only written if non-empty). Namespaced under the
|
||||||
terrain_dir = os.path.join(ASSETS_DIR, 'meshes', 'chunks')
|
# owning map so two maps can each have a chunk at the same (x, y, z)
|
||||||
models_dir = os.path.join(ASSETS_DIR, 'models', 'chunks')
|
# without their generated terrain assets colliding.
|
||||||
|
terrain_dir = os.path.join(ASSETS_DIR, 'maps', map_name, 'meshes', 'chunks')
|
||||||
|
models_dir = os.path.join(ASSETS_DIR, 'maps', map_name, 'models', 'chunks')
|
||||||
os.makedirs(terrain_dir, exist_ok=True)
|
os.makedirs(terrain_dir, exist_ok=True)
|
||||||
os.makedirs(models_dir, exist_ok=True)
|
os.makedirs(models_dir, exist_ok=True)
|
||||||
if terrain_verts:
|
if terrain_verts:
|
||||||
dmf_name = f'chunk_{dcf_base}_0.dmf'
|
dmf_name = f'chunk_{dcf_base}_0.dmf'
|
||||||
write_dmf(os.path.join(terrain_dir, dmf_name), terrain_verts)
|
write_dmf(os.path.join(terrain_dir, dmf_name), terrain_verts)
|
||||||
mesh_rel = f'meshes/chunks/{dmf_name}'
|
mesh_rel = f'maps/{map_name}/meshes/chunks/{dmf_name}'
|
||||||
json_name = f'chunk_{dcf_base}_0.json'
|
json_name = f'chunk_{dcf_base}_0.json'
|
||||||
write_model_json(
|
write_model_json(
|
||||||
os.path.join(models_dir, json_name),
|
os.path.join(models_dir, json_name),
|
||||||
@@ -393,7 +426,7 @@ def from_json(json_path, dcf_path):
|
|||||||
'tiles.png',
|
'tiles.png',
|
||||||
[255, 255, 255, 255]
|
[255, 255, 255, 255]
|
||||||
)
|
)
|
||||||
model_names.append(f'models/chunks/{json_name}')
|
model_names.append(f'maps/{map_name}/models/chunks/{json_name}')
|
||||||
mesh_offsets.append((0.0, 0.0, 0.0))
|
mesh_offsets.append((0.0, 0.0, 0.0))
|
||||||
|
|
||||||
# External mesh references -> look up matching model JSON
|
# External mesh references -> look up matching model JSON
|
||||||
@@ -555,22 +588,27 @@ def main():
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'path', nargs='?',
|
'path', nargs='?',
|
||||||
help='Chunk JSON file to process, or legacy DCF file to upgrade. '
|
help='Chunk JSON file to process, or legacy DCF file to upgrade. '
|
||||||
'If omitted, processes all assetsraw/chunks/*.json'
|
'If omitted, processes all assetsraw/maps/*/chunks/*.json'
|
||||||
)
|
)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if args.path is None:
|
if args.path is None:
|
||||||
chunks_dir = os.path.join(ASSETSRAW_DIR, 'chunks')
|
maps_dir = os.path.join(ASSETSRAW_DIR, 'maps')
|
||||||
if not os.path.isdir(chunks_dir):
|
if not os.path.isdir(maps_dir):
|
||||||
print(f"No directory found: {chunks_dir}")
|
print(f"No directory found: {maps_dir}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
json_files = sorted(
|
json_files = []
|
||||||
os.path.join(chunks_dir, f)
|
for map_name in sorted(os.listdir(maps_dir)):
|
||||||
for f in os.listdir(chunks_dir)
|
chunks_dir = os.path.join(maps_dir, map_name, 'chunks')
|
||||||
if f.endswith('.json')
|
if not os.path.isdir(chunks_dir):
|
||||||
)
|
continue
|
||||||
|
json_files.extend(sorted(
|
||||||
|
os.path.join(chunks_dir, f)
|
||||||
|
for f in os.listdir(chunks_dir)
|
||||||
|
if f.endswith('.json')
|
||||||
|
))
|
||||||
if not json_files:
|
if not json_files:
|
||||||
print(f"No JSON files found in {chunks_dir}")
|
print(f"No JSON files found under {maps_dir}")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
for p in json_files:
|
for p in json_files:
|
||||||
process_json(p)
|
process_json(p)
|
||||||
|
|||||||
Reference in new issue
Block a user