mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2026-02-04 17:41:23 +01:00
[Migration] NPM (#1266)
* chore: add npm + vite for progressive enhancement * fix: update Dockerfile to copy only the dist folder contents * fix: update Dockerfile to use multi-stage build for optimized production image * fix: correct nginx config file copy command in Dockerfile * chore: add netlify configuration for build and redirects * fix: add NODE_VERSION to environment in Netlify configuration * remove wrong dist folder * Update package.json Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * chore: split public and src * migrating all util files from js to ts * feat: Implement HeightmapGenerator and Voronoi module - Added HeightmapGenerator class for generating heightmaps with various tools (Hill, Pit, Range, Trough, Strait, etc.). - Introduced Voronoi class for creating Voronoi diagrams using Delaunator. - Updated index.html to include new modules. - Created index.ts to manage module imports. - Enhanced arrayUtils and graphUtils with type definitions and improved functionality. - Added utility functions for generating grids and calculating Voronoi cells. * chore: add GitHub Actions workflow for deploying to GitHub Pages * fix: update branch name in GitHub Actions workflow from 'main' to 'master' * chore: update package.json to specify Node.js engine version and remove unused launch.json * Initial plan * Update copilot guidelines to reflect NPM/Vite/TypeScript migration Co-authored-by: Azgaar <26469650+Azgaar@users.noreply.github.com> * Update src/modules/heightmap-generator.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/utils/graphUtils.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/modules/heightmap-generator.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * feat: Add TIME and ERROR variables to global scope in HeightmapGenerator * fix: Update base path in vite.config.ts for Netlify deployment * fix: Update Node.js version in Dockerfile to 24-alpine --------- Co-authored-by: Marc Emmanuel <marc.emmanuel@tado.com> Co-authored-by: Marc Emmanuel <marcwissler@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Azgaar <26469650+Azgaar@users.noreply.github.com>
This commit is contained in:
parent
0c26f0831f
commit
9e0eb03618
713 changed files with 5182 additions and 2161 deletions
|
|
@ -1,261 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
// functions to save the project to a file
|
||||
async function saveMap(method) {
|
||||
if (customization) return tip("Map cannot be saved in EDIT mode, please complete the edit and retry", false, "error");
|
||||
closeDialogs("#alert");
|
||||
|
||||
try {
|
||||
const mapData = prepareMapData();
|
||||
const filename = getFileName() + ".map";
|
||||
|
||||
saveToStorage(mapData, method === "storage"); // any method saves to indexedDB
|
||||
if (method === "machine") saveToMachine(mapData, filename);
|
||||
if (method === "dropbox") saveToDropbox(mapData, filename);
|
||||
} catch (error) {
|
||||
ERROR && console.error(error);
|
||||
alertMessage.innerHTML = /* html */ `An error is occured on map saving. If the issue persists, please copy the message below and report it on ${link(
|
||||
"https://github.com/Azgaar/Fantasy-Map-Generator/issues",
|
||||
"GitHub"
|
||||
)}. <p id="errorBox">${parseError(error)}</p>`;
|
||||
|
||||
$("#alert").dialog({
|
||||
resizable: false,
|
||||
title: "Saving error",
|
||||
width: "28em",
|
||||
buttons: {
|
||||
Retry: function () {
|
||||
$(this).dialog("close");
|
||||
saveMap(method);
|
||||
},
|
||||
Close: function () {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
},
|
||||
position: {my: "center", at: "center", of: "svg"}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function prepareMapData() {
|
||||
const date = new Date();
|
||||
const dateString = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
|
||||
const license = "File can be loaded in azgaar.github.io/Fantasy-Map-Generator";
|
||||
const params = [VERSION, license, dateString, seed, graphWidth, graphHeight, mapId].join("|");
|
||||
const settings = [
|
||||
distanceUnitInput.value,
|
||||
distanceScale,
|
||||
areaUnit.value,
|
||||
heightUnit.value,
|
||||
heightExponentInput.value,
|
||||
temperatureScale.value,
|
||||
"", // previously used for barSize.value
|
||||
"", // previously used for barLabel.value
|
||||
"", // previously used for barBackColor.value
|
||||
"", // previously used for barBackColor.value
|
||||
"", // previously used for barPosX.value
|
||||
"", // previously used for barPosY.value
|
||||
populationRate,
|
||||
urbanization,
|
||||
mapSizeOutput.value,
|
||||
latitudeOutput.value,
|
||||
"", // previously used for temperatureEquatorOutput.value
|
||||
"", // previously used for tempNorthOutput.value
|
||||
precOutput.value,
|
||||
JSON.stringify(options),
|
||||
mapName.value,
|
||||
+hideLabels.checked,
|
||||
stylePreset.value,
|
||||
+rescaleLabels.checked,
|
||||
urbanDensity,
|
||||
longitudeOutput.value,
|
||||
growthRate.value
|
||||
].join("|");
|
||||
const coords = JSON.stringify(mapCoordinates);
|
||||
const biomes = [biomesData.color, biomesData.habitability, biomesData.name].join("|");
|
||||
const notesData = JSON.stringify(notes);
|
||||
const rulersString = rulers.toString();
|
||||
const fonts = JSON.stringify(getUsedFonts(svg.node()));
|
||||
|
||||
// save svg
|
||||
const cloneEl = document.getElementById("map").cloneNode(true);
|
||||
|
||||
// reset transform values to default
|
||||
cloneEl.setAttribute("width", graphWidth);
|
||||
cloneEl.setAttribute("height", graphHeight);
|
||||
cloneEl.querySelector("#viewbox").removeAttribute("transform");
|
||||
|
||||
cloneEl.querySelector("#ruler").innerHTML = ""; // always remove rulers
|
||||
|
||||
const serializedSVG = new XMLSerializer().serializeToString(cloneEl);
|
||||
|
||||
const {spacing, cellsX, cellsY, boundary, points, features, cellsDesired} = grid;
|
||||
const gridGeneral = JSON.stringify({spacing, cellsX, cellsY, boundary, points, features, cellsDesired});
|
||||
const packFeatures = JSON.stringify(pack.features);
|
||||
const cultures = JSON.stringify(pack.cultures);
|
||||
const states = JSON.stringify(pack.states);
|
||||
const burgs = JSON.stringify(pack.burgs);
|
||||
const religions = JSON.stringify(pack.religions);
|
||||
const provinces = JSON.stringify(pack.provinces);
|
||||
const rivers = JSON.stringify(pack.rivers);
|
||||
const markers = JSON.stringify(pack.markers);
|
||||
const cellRoutes = JSON.stringify(pack.cells.routes);
|
||||
const routes = JSON.stringify(pack.routes);
|
||||
const zones = JSON.stringify(pack.zones);
|
||||
|
||||
// store name array only if not the same as default
|
||||
const defaultNB = Names.getNameBases();
|
||||
const namesData = nameBases
|
||||
.map((b, i) => {
|
||||
const names = defaultNB[i] && defaultNB[i].b === b.b ? "" : b.b;
|
||||
return `${b.name}|${b.min}|${b.max}|${b.d}|${b.m}|${names}`;
|
||||
})
|
||||
.join("/");
|
||||
|
||||
// round population to save space
|
||||
const pop = Array.from(pack.cells.pop).map(p => rn(p, 4));
|
||||
|
||||
// data format as below
|
||||
const mapData = [
|
||||
params,
|
||||
settings,
|
||||
coords,
|
||||
biomes,
|
||||
notesData,
|
||||
serializedSVG,
|
||||
gridGeneral,
|
||||
grid.cells.h,
|
||||
grid.cells.prec,
|
||||
grid.cells.f,
|
||||
grid.cells.t,
|
||||
grid.cells.temp,
|
||||
packFeatures,
|
||||
cultures,
|
||||
states,
|
||||
burgs,
|
||||
pack.cells.biome,
|
||||
pack.cells.burg,
|
||||
pack.cells.conf,
|
||||
pack.cells.culture,
|
||||
pack.cells.fl,
|
||||
pop,
|
||||
pack.cells.r,
|
||||
[], // deprecated pack.cells.road
|
||||
pack.cells.s,
|
||||
pack.cells.state,
|
||||
pack.cells.religion,
|
||||
pack.cells.province,
|
||||
[], // deprecated pack.cells.crossroad
|
||||
religions,
|
||||
provinces,
|
||||
namesData,
|
||||
rivers,
|
||||
rulersString,
|
||||
fonts,
|
||||
markers,
|
||||
cellRoutes,
|
||||
routes,
|
||||
zones
|
||||
].join("\r\n");
|
||||
return mapData;
|
||||
}
|
||||
|
||||
// save map file to indexedDB
|
||||
async function saveToStorage(mapData, showTip = false) {
|
||||
const blob = new Blob([mapData], {type: "text/plain"});
|
||||
await ldb.set("lastMap", blob);
|
||||
showTip && tip("Map is saved to the browser storage", false, "success");
|
||||
}
|
||||
|
||||
// download map file
|
||||
function saveToMachine(mapData, filename) {
|
||||
const blob = new Blob([mapData], {type: "text/plain"});
|
||||
const URL = window.URL.createObjectURL(blob);
|
||||
|
||||
const link = document.createElement("a");
|
||||
link.download = filename;
|
||||
link.href = URL;
|
||||
link.click();
|
||||
|
||||
tip('Map is saved to the "Downloads" folder (CTRL + J to open)', true, "success", 8000);
|
||||
window.URL.revokeObjectURL(URL);
|
||||
}
|
||||
|
||||
async function saveToDropbox(mapData, filename) {
|
||||
await Cloud.providers.dropbox.save(filename, mapData);
|
||||
tip("Map is saved to your Dropbox", true, "success", 8000);
|
||||
}
|
||||
|
||||
async function initiateAutosave() {
|
||||
const MINUTE = 60000; // munite in milliseconds
|
||||
let lastSavedAt = Date.now();
|
||||
|
||||
async function autosave() {
|
||||
const timeoutMinutes = byId("autosaveIntervalOutput").valueAsNumber;
|
||||
if (!timeoutMinutes) return;
|
||||
|
||||
const diffInMinutes = (Date.now() - lastSavedAt) / MINUTE;
|
||||
if (diffInMinutes < timeoutMinutes) return;
|
||||
if (customization) return tip("Autosave: map cannot be saved in edit mode", false, "warning", 2000);
|
||||
|
||||
try {
|
||||
tip("Autosave: saving map...", false, "warning", 3000);
|
||||
const mapData = prepareMapData();
|
||||
await saveToStorage(mapData);
|
||||
tip("Autosave: map is saved", false, "success", 2000);
|
||||
|
||||
lastSavedAt = Date.now();
|
||||
} catch (error) {
|
||||
ERROR && console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
setInterval(autosave, MINUTE / 2);
|
||||
}
|
||||
|
||||
// TODO: unused code
|
||||
async function compressData(uncompressedData) {
|
||||
const compressedStream = new Blob([uncompressedData]).stream().pipeThrough(new CompressionStream("gzip"));
|
||||
|
||||
let compressedData = [];
|
||||
for await (const chunk of compressedStream) {
|
||||
compressedData = compressedData.concat(Array.from(chunk));
|
||||
}
|
||||
|
||||
return new Uint8Array(compressedData);
|
||||
}
|
||||
|
||||
const saveReminder = function () {
|
||||
if (localStorage.getItem("noReminder")) return;
|
||||
const message = [
|
||||
"Please don't forget to save the project to desktop from time to time",
|
||||
"Please remember to save the map to your desktop",
|
||||
"Saving will ensure your data won't be lost in case of issues",
|
||||
"Safety is number one priority. Please save the map",
|
||||
"Don't forget to save your map on a regular basis!",
|
||||
"Just a gentle reminder for you to save the map",
|
||||
"Please don't forget to save your progress (saving to desktop is the best option)",
|
||||
"Don't want to get reminded about need to save? Press CTRL+Q"
|
||||
];
|
||||
const interval = 15 * 60 * 1000; // remind every 15 minutes
|
||||
|
||||
saveReminder.reminder = setInterval(() => {
|
||||
if (customization) return;
|
||||
tip(ra(message), true, "warn", 2500);
|
||||
}, interval);
|
||||
saveReminder.status = 1;
|
||||
};
|
||||
saveReminder();
|
||||
|
||||
function toggleSaveReminder() {
|
||||
if (saveReminder.status) {
|
||||
tip("Save reminder is turned off. Press CTRL+Q again to re-initiate", true, "warn", 2000);
|
||||
clearInterval(saveReminder.reminder);
|
||||
localStorage.setItem("noReminder", true);
|
||||
saveReminder.status = 0;
|
||||
} else {
|
||||
tip("Save reminder is turned on. Press CTRL+Q to turn off", true, "warn", 2000);
|
||||
localStorage.removeItem("noReminder");
|
||||
saveReminder();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue