159 lines
4.4 KiB
TypeScript
159 lines
4.4 KiB
TypeScript
import type { JsonObject } from "./editorCore";
|
|
|
|
export const WORLD_INDEX_SCHEMA_VERSION = 1;
|
|
export const WORLD_SCHEMA_VERSION = 1;
|
|
export const WORLD_CHUNK_SCHEMA_VERSION = 1;
|
|
export const WORLD_BOOKMARKS_SCHEMA_VERSION = 1;
|
|
export const DEFAULT_WORLD_CHUNK_SIZE = 32;
|
|
export const DEFAULT_WORLD_TILE_SIZE = 32;
|
|
|
|
export type WorldIndexEntry = {
|
|
id: string;
|
|
name: string;
|
|
worldDir: string;
|
|
};
|
|
|
|
export type WorldIndexPayload = {
|
|
schemaVersion: number;
|
|
worlds: WorldIndexEntry[];
|
|
};
|
|
|
|
export type WorldBookmark = {
|
|
id: string;
|
|
label: string;
|
|
x: number;
|
|
y: number;
|
|
};
|
|
|
|
export type WorldBookmarksPayload = {
|
|
schemaVersion: number;
|
|
worldId: string;
|
|
bookmarks: WorldBookmark[];
|
|
};
|
|
|
|
export type WorldDefinition = {
|
|
schemaVersion: number;
|
|
id: string;
|
|
name: string;
|
|
chunkWidth: number;
|
|
chunkHeight: number;
|
|
tileSize: number;
|
|
defaultBackgroundTileId: string;
|
|
spawn: { x: number; y: number };
|
|
editor?: {
|
|
defaultZoom?: number;
|
|
gridVisible?: boolean;
|
|
};
|
|
};
|
|
|
|
export type WorldChunkLayer = {
|
|
layer: number;
|
|
name?: string;
|
|
rows: string[];
|
|
instanceIds: string[];
|
|
};
|
|
|
|
export type WorldHeightPatch = {
|
|
id: string;
|
|
name?: string;
|
|
z: number;
|
|
x: number;
|
|
y: number;
|
|
rows: string[];
|
|
};
|
|
|
|
export type WorldChunkInstance = {
|
|
id: string;
|
|
templateId?: string;
|
|
layer: number;
|
|
x: number;
|
|
y: number;
|
|
record: JsonObject;
|
|
};
|
|
|
|
export type WorldChunk = {
|
|
schemaVersion: number;
|
|
worldId: string;
|
|
chunkX: number;
|
|
chunkY: number;
|
|
width: number;
|
|
height: number;
|
|
backgroundTileId: string;
|
|
roomLayers: WorldChunkLayer[];
|
|
heightLayers: WorldHeightPatch[];
|
|
instances: WorldChunkInstance[];
|
|
};
|
|
|
|
export function normalizeChunkDimension(value: unknown, fallback = DEFAULT_WORLD_CHUNK_SIZE): number {
|
|
return Math.max(1, Math.floor(Number(value) || fallback));
|
|
}
|
|
|
|
export function buildChunkKey(chunkX: number, chunkY: number): string {
|
|
return `${Math.floor(chunkX)}:${Math.floor(chunkY)}`;
|
|
}
|
|
|
|
export function buildChunkFileName(chunkX: number, chunkY: number): string {
|
|
return `${Math.floor(chunkX)}_${Math.floor(chunkY)}.json`;
|
|
}
|
|
|
|
export function worldToChunkCoord(worldCoord: number, chunkSize: number): number {
|
|
const safeChunkSize = Math.max(1, Math.floor(Number(chunkSize) || DEFAULT_WORLD_CHUNK_SIZE));
|
|
return Math.floor(Number(worldCoord) / safeChunkSize);
|
|
}
|
|
|
|
export function worldToLocalCoord(worldCoord: number, chunkSize: number): number {
|
|
const safeChunkSize = Math.max(1, Math.floor(Number(chunkSize) || DEFAULT_WORLD_CHUNK_SIZE));
|
|
const chunkCoord = worldToChunkCoord(worldCoord, safeChunkSize);
|
|
return Math.floor(Number(worldCoord) - (chunkCoord * safeChunkSize));
|
|
}
|
|
|
|
export function localToWorldCoord(chunkCoord: number, localCoord: number, chunkSize: number): number {
|
|
const safeChunkSize = Math.max(1, Math.floor(Number(chunkSize) || DEFAULT_WORLD_CHUNK_SIZE));
|
|
return (Math.floor(Number(chunkCoord) || 0) * safeChunkSize) + Math.floor(Number(localCoord) || 0);
|
|
}
|
|
|
|
export function resolveWorldChunkAddress(worldX: number, worldY: number, chunkWidth: number, chunkHeight: number) {
|
|
const safeChunkWidth = normalizeChunkDimension(chunkWidth);
|
|
const safeChunkHeight = normalizeChunkDimension(chunkHeight);
|
|
const chunkX = worldToChunkCoord(worldX, safeChunkWidth);
|
|
const chunkY = worldToChunkCoord(worldY, safeChunkHeight);
|
|
const localX = worldToLocalCoord(worldX, safeChunkWidth);
|
|
const localY = worldToLocalCoord(worldY, safeChunkHeight);
|
|
return {
|
|
chunkX,
|
|
chunkY,
|
|
localX,
|
|
localY,
|
|
chunkKey: buildChunkKey(chunkX, chunkY),
|
|
fileName: buildChunkFileName(chunkX, chunkY),
|
|
};
|
|
}
|
|
|
|
export function createEmptyChunk(worldId: string, chunkX: number, chunkY: number, backgroundTileId = "", chunkWidth = DEFAULT_WORLD_CHUNK_SIZE, chunkHeight = DEFAULT_WORLD_CHUNK_SIZE): WorldChunk {
|
|
const width = normalizeChunkDimension(chunkWidth);
|
|
const height = normalizeChunkDimension(chunkHeight);
|
|
return {
|
|
schemaVersion: WORLD_CHUNK_SCHEMA_VERSION,
|
|
worldId: String(worldId || "").trim(),
|
|
chunkX: Math.floor(Number(chunkX) || 0),
|
|
chunkY: Math.floor(Number(chunkY) || 0),
|
|
width,
|
|
height,
|
|
backgroundTileId: String(backgroundTileId || "").trim(),
|
|
roomLayers: [
|
|
{
|
|
layer: 0,
|
|
rows: Array.from({ length: height }, () => ".".repeat(width)),
|
|
instanceIds: [],
|
|
},
|
|
{
|
|
layer: 1,
|
|
rows: Array.from({ length: height }, () => " ".repeat(width)),
|
|
instanceIds: [],
|
|
},
|
|
],
|
|
heightLayers: [],
|
|
instances: [],
|
|
};
|
|
}
|
|
|