Improve VPS delivery and simplify editor history
This commit is contained in:
parent
0074f0e10c
commit
17c64e1fbe
6 changed files with 283 additions and 595 deletions
64
server.js
64
server.js
|
|
@ -1,4 +1,5 @@
|
|||
import express from "express";
|
||||
import compression from "compression";
|
||||
import { spawn } from "child_process";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
|
@ -999,8 +1000,25 @@ function createDefaultColorCatalogEntries() {
|
|||
});
|
||||
}
|
||||
|
||||
app.use(compression({ threshold: 1024 }));
|
||||
app.use(express.json({ limit: "10mb" }));
|
||||
app.use(express.static(path.join(__dirname, "dist")));
|
||||
app.use(express.static(path.join(__dirname, "dist"), {
|
||||
etag: true,
|
||||
setHeaders(res, filePath) {
|
||||
const normalizedPath = String(filePath || "").replace(/\\/g, "/");
|
||||
if (normalizedPath.includes("/dist/assets/")) {
|
||||
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
|
||||
return;
|
||||
}
|
||||
if (/\.(png|svg|jpg|jpeg|webp|gif|ico)$/i.test(normalizedPath)) {
|
||||
res.setHeader("Cache-Control", "public, max-age=604800");
|
||||
return;
|
||||
}
|
||||
if (/\.html$/i.test(normalizedPath)) {
|
||||
res.setHeader("Cache-Control", "no-cache");
|
||||
}
|
||||
},
|
||||
}));
|
||||
|
||||
function resolveContent(type) {
|
||||
const entry = contentMap[type];
|
||||
|
|
@ -1325,6 +1343,33 @@ function listWorldChunkFiles(worldId) {
|
|||
.sort((a, b) => a.localeCompare(b));
|
||||
}
|
||||
|
||||
function buildWorldChunkOverviewSurfaceRows(chunkPayload, fallbackWidth, fallbackHeight) {
|
||||
const width = Math.max(1, Number(chunkPayload?.width) || Number(fallbackWidth) || DEFAULT_WORLD_CHUNK_SIZE);
|
||||
const height = Math.max(1, Number(chunkPayload?.height) || Number(fallbackHeight) || DEFAULT_WORLD_CHUNK_SIZE);
|
||||
const sortedRoomLayers = Array.isArray(chunkPayload?.roomLayers)
|
||||
? chunkPayload.roomLayers
|
||||
.slice()
|
||||
.sort((left, right) => (Number(left?.layer) || 0) - (Number(right?.layer) || 0))
|
||||
: [];
|
||||
return Array.from({ length: height }, (_entry, rowIndex) => {
|
||||
let row = "";
|
||||
for (let columnIndex = 0; columnIndex < width; columnIndex += 1) {
|
||||
let resolvedSymbol = ".";
|
||||
sortedRoomLayers.forEach((layer) => {
|
||||
const layerNumber = Number(layer?.layer) || 0;
|
||||
const fillChar = layerNumber === 0 ? "." : " ";
|
||||
const sourceRow = Array.isArray(layer?.rows) ? String(layer.rows[rowIndex] || "") : "";
|
||||
const symbol = String(sourceRow.charAt(columnIndex) || fillChar).charAt(0) || fillChar;
|
||||
if (symbol !== "." && symbol !== " ") {
|
||||
resolvedSymbol = symbol;
|
||||
}
|
||||
});
|
||||
row += resolvedSymbol;
|
||||
}
|
||||
return row;
|
||||
});
|
||||
}
|
||||
|
||||
function countSymbolOccurrencesInRows(rows, targetSymbol) {
|
||||
const normalizedTarget = String(targetSymbol || "").charAt(0);
|
||||
if (!normalizedTarget) {
|
||||
|
|
@ -3505,6 +3550,19 @@ app.get("/api/world/:worldId/overview", (req, res) => {
|
|||
const chunks = chunkCoords
|
||||
.map((coord) => readWorldChunkPayload(worldId, coord.chunkX, coord.chunkY, { createIfMissing: false }))
|
||||
.filter(Boolean);
|
||||
const overviewChunks = chunks.map((chunk) => {
|
||||
const width = Math.max(1, Number(chunk.width) || Number(worldDefinition.chunkWidth) || DEFAULT_WORLD_CHUNK_SIZE);
|
||||
const height = Math.max(1, Number(chunk.height) || Number(worldDefinition.chunkHeight) || DEFAULT_WORLD_CHUNK_SIZE);
|
||||
return {
|
||||
chunkX: Math.floor(Number(chunk.chunkX) || 0),
|
||||
chunkY: Math.floor(Number(chunk.chunkY) || 0),
|
||||
width,
|
||||
height,
|
||||
backgroundTileId: String(chunk.backgroundTileId || "").trim(),
|
||||
surfaceRows: buildWorldChunkOverviewSurfaceRows(chunk, width, height),
|
||||
instanceCount: Array.isArray(chunk.instances) ? chunk.instances.length : 0,
|
||||
};
|
||||
});
|
||||
const chunkWidth = Math.max(1, Number(worldDefinition.chunkWidth) || DEFAULT_WORLD_CHUNK_SIZE);
|
||||
const chunkHeight = Math.max(1, Number(worldDefinition.chunkHeight) || DEFAULT_WORLD_CHUNK_SIZE);
|
||||
const minChunkX = chunks.length > 0 ? Math.min(...chunks.map((chunk) => Math.floor(Number(chunk.chunkX) || 0))) : 0;
|
||||
|
|
@ -3524,8 +3582,8 @@ app.get("/api/world/:worldId/overview", (req, res) => {
|
|||
maxTileX: ((maxChunkX + 1) * chunkWidth) - 1,
|
||||
maxTileY: ((maxChunkY + 1) * chunkHeight) - 1,
|
||||
},
|
||||
chunkCount: chunks.length,
|
||||
chunks,
|
||||
chunkCount: overviewChunks.length,
|
||||
chunks: overviewChunks,
|
||||
});
|
||||
} catch (err) {
|
||||
res.status(500).json({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue