mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-18 02:01:22 +01:00
Summary Ground burgs with sky ports keep land capabilities and land routes. Only truly flying burgs join the Sky Realm; turning off “flying” restores the ground state. Replace magic altitude 1000 with a DOM-configurable default. Guard state hover/pin logic for geometry-less Sky Realm to prevent console errors. Watabou link uses sky settings only for flying burgs. Details Land routing with sky ports: Change: include sky ports in land road/trail networks; exclude only flying burgs. Why: sky ports should not impose flying/land restrictions on a ground burg. File: modules/routes-generator.js Sky port toggle does not move state: Change: toggling skyPort no longer assigns the burg’s state to the Sky Realm or reassigns cell ownership. Why: sky port ≠ flying city; it’s just air connectivity. File: modules/ui/burg-editor.js Flying toggle and state restore: Change: enabling “flying” assigns the burg to the Sky Realm but does not overwrite the cell’s ground state; disabling “flying” restores the burg’s state to the underlying ground state (pack.cells.state[burg.cell]). Change: when relocating, assign Sky Realm only if the burg is placed over water; ground placements keep ground state. Why: fixes bug where reverting to ground left burg in Sky Realm and preserves ground sovereignty. File: modules/ui/burg-editor.js Default sky altitude via DOM (no more magic 1000): Change: add hidden input #burgDefaultSkyAltitude (default 1000 m) and read it everywhere altitude is defaulted (editor and “add burg on water” flow). Why: centralizes default, documents units, and makes it configurable without touching code. Files: index.html, modules/ui/burg-editor.js, modules/ui/burgs-overview.js Sky State creation robustness: Change: initialize a neutral diplomacy row for the new Sky State and extend existing states’ diplomacy arrays. Change: do not forcibly set the anchor cell ownership to Sky state when creating the Sky Realm. Why: prevents UI/editor crashes that assume diplomacy is rectangular; avoids accidental land transfer to Sky Realm. File: modules/ui/editors.js State hover/pin guards for Sky Realm: Change: skip fog/hover/highlight when the target state has no geometry (e.g., Sky Realm) or the path is missing. Why: fixes console errors in State hover and Pin feature. Files: modules/dynamic/editors/states-editor.js, modules/ui/diplomacy-editor.js, modules/ui/military-overview.js Watabou integration: Change: only treat burgs as “sky” for city links when flying is true (not when only skyPort is set). Why: ground burgs with sky ports should still have gates/roads/hubs/shanty, etc. File: modules/ui/editors.js User-visible Effects Ground cities can have sea port + sky port + roads/trails simultaneously. Toggling flying on shows altitude row; default altitude is read from the DOM. Toggling flying off restores the burg to its ground state affiliation. No more console errors when interacting with state hover/pin around the Sky Realm. Potential Impacts Land route generation may produce additional roads because sky-ported (but ground) burgs are now included. Diplomacy arrays gain a neutral column for the Sky Realm when first created (non-breaking, UI-aligned). Test Plan Set sky port on a ground burg: verify roads/trails remain; sea port and other features unaffected. Toggle flying on: burg state switches to Sky Realm; cell remains with ground state; altitude defaults from #burgDefaultSkyAltitude; air routes generate. Toggle flying off: burg state returns to the ground state; altitude row hides; routes regenerate. Hover/fog/pin states with the editors open: no errors with Sky Realm selected or hovered. Open Watabou (city generator) links: Ground + sky port: uses ground settings (gates/roads/hubs/shanty allowed). Flying: uses sky settings (no farms/gates/hub etc. as appropriate). Files Changed modules/routes-generator.js modules/ui/burg-editor.js modules/ui/burgs-overview.js modules/ui/editors.js modules/dynamic/editors/states-editor.js modules/ui/diplomacy-editor.js modules/ui/military-overview.js index.html
118 lines
4.8 KiB
JavaScript
118 lines
4.8 KiB
JavaScript
"use strict";
|
|
/**
|
|
* Version Control Guidelines
|
|
* --------------------------
|
|
* We use Semantic Versioning: major.minor.patch. Refer to https://semver.org
|
|
* Our .map file format is considered the public API.
|
|
*
|
|
* Update the version MANUALLY on each merge to main:
|
|
* 1. MAJOR version: Incompatible changes that break existing maps
|
|
* 2. MINOR version: Additions or changes that are backward-compatible but may require old .map files to be updated
|
|
* 3. PATCH version: Backward-compatible bug fixes and small features that do not affect the .map file format
|
|
*
|
|
* Example: 1.102.2 -> Major version 1, Minor version 102, Patch version 2
|
|
*/
|
|
|
|
const VERSION = "1.109.0";
|
|
if (parseMapVersion(VERSION) !== VERSION) alert("versioning.js: Invalid format or parsing function");
|
|
|
|
{
|
|
document.title += " v" + VERSION;
|
|
const loadingScreenVersion = document.getElementById("versionText");
|
|
if (loadingScreenVersion) loadingScreenVersion.innerText = `v${VERSION}`;
|
|
|
|
const storedVersion = localStorage.getItem("version");
|
|
if (compareVersions(storedVersion, VERSION, { major: true, minor: true, patch: false }).isOlder) {
|
|
setTimeout(showUpdateWindow, 6000);
|
|
}
|
|
|
|
function showUpdateWindow() {
|
|
const changelog = "https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Changelog";
|
|
const reddit = "https://www.reddit.com/r/FantasyMapGenerator";
|
|
const discord = "https://discordapp.com/invite/X7E84HU";
|
|
const patreon = "https://www.patreon.com/azgaar";
|
|
|
|
alertMessage.innerHTML = /* html */ `The Fantasy Map Generator is updated up to version <strong>${VERSION}</strong>. This version is compatible with <a href="${changelog}" target="_blank">previous versions</a>, loaded save files will be auto-updated.
|
|
${storedVersion ? "<span>Click on OK and then reload the page to fetch fresh code.</span>" : ""}
|
|
|
|
<ul>
|
|
<strong>Latest changes:</strong>
|
|
<li>Flying cities: Sky burgs join a dedicated locked Sky Realm</li>
|
|
<li>Air routes: curved, named connections rendered in new <code>#airroutes</code> layer</li>
|
|
<li>Burg Editor: Sky Port and Flying toggles, plus altitude control</li>
|
|
<li>Relocation: Flying burgs can be placed over water (Alt or Flying)</li>
|
|
<li>Heightmap reapply: Flying burgs are preserved even over water</li>
|
|
<li>Styling: separate <code>#burgIcons > #skyburgs</code> group for sky burg icons</li>
|
|
</ul>
|
|
|
|
<p>Join our <a href="${discord}" target="_blank">Discord server</a> and <a href="${reddit}" target="_blank">Reddit community</a> to ask questions, share maps, discuss the Generator and Worldbuilding, report bugs and propose new features.</p>
|
|
<span><i>Thanks for all supporters on <a href="${patreon}" target="_blank">Patreon</a>!</i></span>`;
|
|
|
|
$("#alert").dialog({
|
|
resizable: false,
|
|
title: "Fantasy Map Generator update",
|
|
width: "28em",
|
|
position: { my: "center center-4em", at: "center", of: "svg" },
|
|
buttons: {
|
|
"Clear cache": () => cleanupData(),
|
|
"Don't show again": function () {
|
|
$(this).dialog("close");
|
|
localStorage.setItem("version", VERSION);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
async function cleanupData() {
|
|
await clearCache();
|
|
localStorage.clear();
|
|
localStorage.setItem("version", VERSION);
|
|
localStorage.setItem("disable_click_arrow_tooltip", "true");
|
|
location.reload();
|
|
}
|
|
|
|
async function clearCache() {
|
|
const cacheNames = await caches.keys();
|
|
return Promise.all(cacheNames.map(cacheName => caches.delete(cacheName)));
|
|
}
|
|
|
|
function parseMapVersion(version) {
|
|
let [major, minor, patch] = version.split(".");
|
|
|
|
if (patch === undefined) {
|
|
// e.g. 1.732
|
|
minor = minor.slice(0, 2);
|
|
patch = minor.slice(2);
|
|
}
|
|
|
|
// e.g. 0.7b
|
|
major = parseInt(major) || 0;
|
|
minor = parseInt(minor) || 0;
|
|
patch = parseInt(patch) || 0;
|
|
|
|
return `${major}.${minor}.${patch}`;
|
|
}
|
|
|
|
function isValidVersion(versionString) {
|
|
if (!versionString) return false;
|
|
const [major, minor, patch] = versionString.split(".");
|
|
return !isNaN(major) && !isNaN(minor) && !isNaN(patch);
|
|
}
|
|
|
|
function compareVersions(version1, version2, options = { major: true, minor: true, patch: true }) {
|
|
if (!isValidVersion(version1) || !isValidVersion(version2)) return { isEqual: false, isNewer: false, isOlder: false };
|
|
|
|
let [major1, minor1, patch1] = version1.split(".").map(Number);
|
|
let [major2, minor2, patch2] = version2.split(".").map(Number);
|
|
|
|
if (!options.major) major1 = major2 = 0;
|
|
if (!options.minor) minor1 = minor2 = 0;
|
|
if (!options.patch) patch1 = patch2 = 0;
|
|
|
|
const isEqual = major1 === major2 && minor1 === minor2 && patch1 === patch2;
|
|
const isNewer = major1 > major2 || (major1 === major2 && (minor1 > minor2 || (minor1 === minor2 && patch1 > patch2)));
|
|
const isOlder = major1 < major2 || (major1 === major2 && (minor1 < minor2 || (minor1 === minor2 && patch1 < patch2)));
|
|
|
|
return { isEqual, isNewer, isOlder };
|
|
}
|