mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 17:51:24 +01:00
refactor: define globals
This commit is contained in:
parent
22903fcb71
commit
7c2c624417
26 changed files with 939 additions and 245 deletions
|
|
@ -1,5 +1,3 @@
|
|||
import {PRODUCTION} from "../constants";
|
||||
|
||||
export const DEBUG = Boolean(localStorage.getItem("debug"));
|
||||
export const INFO = DEBUG || !PRODUCTION;
|
||||
export const TIME = DEBUG || !PRODUCTION;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
export const PRODUCTION = location.hostname && location.hostname !== "localhost" && location.hostname !== "127.0.0.1";
|
||||
|
||||
// detect device
|
||||
export const MOBILE = window.innerWidth < 600 || window.navigator.userAgentData?.mobile;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,13 +2,18 @@
|
|||
// https://github.com/Azgaar/Fantasy-Map-Generator
|
||||
|
||||
import "./components";
|
||||
// @ts-expect-error js-module
|
||||
import {clearLegend} from "./modules/legend";
|
||||
// @ts-expect-error js-module
|
||||
import {Rulers} from "./modules/measurers";
|
||||
// @ts-expect-error js-module
|
||||
import {applyStoredOptions} from "./modules/ui/options";
|
||||
import {addGlobalListeners} from "./scripts/listeners";
|
||||
import {tip} from "./scripts/tooltips";
|
||||
import {byId} from "./utils/shorthands";
|
||||
import {checkForUpdates} from "./scripts/updater";
|
||||
import {getInputNumber} from "utils/nodeUtils";
|
||||
|
||||
checkForUpdates();
|
||||
addGlobalListeners();
|
||||
|
||||
window.fmg = {
|
||||
|
|
@ -23,10 +28,10 @@ options = {
|
|||
stateLabelsMode: "auto"
|
||||
};
|
||||
|
||||
populationRate = +byId("populationRateInput").value;
|
||||
distanceScale = +byId("distanceScaleInput").value;
|
||||
urbanization = +byId("urbanizationInput").value;
|
||||
urbanDensity = +byId("urbanDensityInput").value;
|
||||
populationRate = getInputNumber("populationRateInput");
|
||||
distanceScale = getInputNumber("distanceScaleInput");
|
||||
urbanization = getInputNumber("urbanizationInput");
|
||||
urbanDensity = getInputNumber("urbanDensityInput");
|
||||
statesNeutral = 1; // statesEditor growth parameter
|
||||
|
||||
applyStoredOptions();
|
||||
|
|
@ -36,8 +41,8 @@ biomesData = Biomes.getDefault();
|
|||
nameBases = Names.getNameBases(); // cultures-related data
|
||||
|
||||
// voronoi graph extension, cannot be changed after generation
|
||||
graphWidth = +byId("mapWidthInput").value;
|
||||
graphHeight = +byId("mapHeightInput").value;
|
||||
graphWidth = getInputNumber("mapWidthInput");
|
||||
graphHeight = getInputNumber("mapHeightInput");
|
||||
|
||||
// svg canvas resolution, can be changed
|
||||
svgWidth = graphWidth;
|
||||
|
|
@ -3,9 +3,11 @@
|
|||
|
||||
let grid = {}; // initial graph based on jittered square grid and data
|
||||
let pack = {}; // packed graph and data
|
||||
|
||||
let seed;
|
||||
let mapId;
|
||||
let mapHistory = [];
|
||||
|
||||
let elSelected;
|
||||
|
||||
let notes = [];
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {minmax, rn} from "utils/numberUtils";
|
|||
import {gauss, P, rand, rw} from "utils/probabilityUtils";
|
||||
import {byId, stored} from "utils/shorthands";
|
||||
import {regenerateMap} from "scripts/generation";
|
||||
import {fitScaleBar} from "modules/measurers";
|
||||
|
||||
$("#optionsContainer").draggable({handle: ".drag-trigger", snap: "svg", snapMode: "both"});
|
||||
$("#exitCustomization").draggable({handle: "div"});
|
||||
|
|
|
|||
|
|
@ -1,41 +1,40 @@
|
|||
// indexedDB support: ldb object
|
||||
|
||||
// @ts-ignore unimplemented historical interfaces
|
||||
const indexedDBfactory = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
|
||||
if (!indexedDBfactory) console.error("indexedDB not supported");
|
||||
|
||||
let database;
|
||||
let database: IDBDatabase | null = null;
|
||||
const databaseRequest = indexedDBfactory.open("d2", 1);
|
||||
|
||||
databaseRequest.onsuccess = function () {
|
||||
database = this.result;
|
||||
};
|
||||
|
||||
databaseRequest.onerror = function (e) {
|
||||
databaseRequest.onerror = e => {
|
||||
console.error("indexedDB request error", e);
|
||||
};
|
||||
|
||||
databaseRequest.onupgradeneeded = function (event) {
|
||||
databaseRequest.onupgradeneeded = () => {
|
||||
database = null;
|
||||
const store = databaseRequest.result.createObjectStore("s", {keyPath: "k"});
|
||||
store.transaction.oncomplete = function (e) {
|
||||
database = e.target.db;
|
||||
store.transaction.oncomplete = event => {
|
||||
database = (event.target as IDBTransaction)?.db;
|
||||
};
|
||||
};
|
||||
|
||||
function getValue(key, callback) {
|
||||
function getValue(key: string, callback: (value: unknown) => void) {
|
||||
if (!database) {
|
||||
setTimeout(() => getValue(key, callback), 100);
|
||||
return;
|
||||
}
|
||||
|
||||
database.transaction("s").objectStore("s").get(key).onsuccess = function (e) {
|
||||
const value = (e.target.result && e.target.result.v) || null;
|
||||
database.transaction("s").objectStore("s").get(key).onsuccess = event => {
|
||||
const target = event.target as IDBRequest<IDBDatabase>;
|
||||
const value = target.result || null;
|
||||
callback(value);
|
||||
};
|
||||
}
|
||||
|
||||
function setValue(key) {
|
||||
function setValue(key: string, value: unknown) {
|
||||
if (!database) {
|
||||
setTimeout(() => setValue(key, value), 100);
|
||||
return;
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
import {PRODUCTION} from "../constants";
|
||||
// @ts-ignore
|
||||
import {checkIfServerless} from "./loading";
|
||||
import {assignLockBehavior} from "./options/lock";
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
// @ts-nocheck global variables
|
||||
import {INFO} from "config/logging";
|
||||
import {heightmapTemplates} from "config/heightmap-templates";
|
||||
import {locked} from "scripts/options/lock";
|
||||
import {getInputValue} from "utils/nodeUtils";
|
||||
import {byId} from "utils/shorthands";
|
||||
|
||||
// show map stats on generation complete
|
||||
export function showStatistics() {
|
||||
|
|
@ -16,12 +16,12 @@ export function showStatistics() {
|
|||
Heightmap: ${heightmap} (${isRandomTemplate}${heightmapType})
|
||||
Points: ${grid.points.length}
|
||||
Cells: ${pack.cells.i.length}
|
||||
Map size: ${mapSizeOutput.value}%
|
||||
Map size: ${getInputValue("mapSizeOutput")}%
|
||||
States: ${pack.states.length - 1}
|
||||
Provinces: ${pack.provinces.length - 1}
|
||||
Burgs: ${pack.burgs.length - 1}
|
||||
Religions: ${pack.religions.length - 1}
|
||||
Culture set: ${culturesSet.selectedOptions[0].innerText}
|
||||
Culture set: ${(byId("culturesSet") as HTMLSelectElement)?.selectedOptions[0].innerText}
|
||||
Cultures: ${pack.cultures.length - 1}`;
|
||||
|
||||
mapId = Date.now(); // unique map id is it's creation date number
|
||||
|
|
|
|||
75
src/scripts/updater.ts
Normal file
75
src/scripts/updater.ts
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
import {byId} from "utils/shorthands";
|
||||
|
||||
console.info("Azgaar's Fantasy Map Generator", `v${APP_VERSION}`);
|
||||
|
||||
export function checkForUpdates() {
|
||||
const versionNumber = parseFloat(APP_VERSION);
|
||||
const storedVersion = parseFloat(localStorage.getItem("version") || "0");
|
||||
|
||||
const isOutdated = storedVersion !== versionNumber;
|
||||
if (isOutdated) clearCache();
|
||||
|
||||
const showUpdate = storedVersion < versionNumber;
|
||||
if (showUpdate) setTimeout(() => showUpdateWindow(storedVersion), 6000);
|
||||
}
|
||||
|
||||
const LATEST_CHANGES = [
|
||||
"Data Charts screen",
|
||||
"Сultures and religions can have multiple parents in hierarchy tree",
|
||||
"Heightmap selection screen",
|
||||
"Dialogs optimization for mobile",
|
||||
"New heightmap template: Fractious",
|
||||
"Template Editor: mask and invert tools",
|
||||
"Ability to install the App",
|
||||
"14 new default fonts",
|
||||
"Caching for faster startup"
|
||||
];
|
||||
|
||||
function showUpdateWindow(storedVersion: number) {
|
||||
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";
|
||||
|
||||
byId("alertMessage")!.innerHTML = /* html */ `
|
||||
The Fantasy Map Generator is updated up to version <strong>${APP_VERSION}</strong>. This version is compatible with <a href="${changelog}" target="_blank">previous versions</a>, loaded <i>.map</i> files will be auto-updated.
|
||||
${storedVersion ? "<span>Reload the page to fetch fresh code.</span>" : ""}
|
||||
|
||||
<ul>
|
||||
<strong>Latest changes:</strong>
|
||||
${LATEST_CHANGES.map(change => `<li>${change}</li>`).join("")}
|
||||
</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 Worlbuilding, report bugs and propose new features.</p>
|
||||
<span><i>Thanks for all supporters on <a href="${patreon}" target="_blank">Patreon</a>!</i></span>
|
||||
`;
|
||||
|
||||
const buttons: {Ok: noop; Reload?: noop} = {
|
||||
Ok: function () {
|
||||
$(this).dialog("close");
|
||||
if (storedVersion) localStorage.clear();
|
||||
localStorage.setItem("version", APP_VERSION);
|
||||
}
|
||||
};
|
||||
|
||||
if (storedVersion) {
|
||||
buttons.Reload = () => {
|
||||
localStorage.clear();
|
||||
localStorage.setItem("version", APP_VERSION);
|
||||
location.reload();
|
||||
};
|
||||
}
|
||||
|
||||
$("#alert").dialog({
|
||||
resizable: false,
|
||||
title: "Fantasy Map Generator update",
|
||||
width: "28em",
|
||||
position: {my: "center center-4em", at: "center", of: "svg"},
|
||||
buttons
|
||||
});
|
||||
}
|
||||
|
||||
async function clearCache() {
|
||||
const cacheNames = await caches.keys();
|
||||
Promise.all(cacheNames.map(cacheName => caches.delete(cacheName)));
|
||||
}
|
||||
10
src/types/biomes.d.ts
vendored
Normal file
10
src/types/biomes.d.ts
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
interface IBiomesData {
|
||||
i: number[];
|
||||
name: string[];
|
||||
color: Hex[];
|
||||
habitability: number[];
|
||||
cost: number[];
|
||||
icons: string[];
|
||||
iconsDensity: number[];
|
||||
biomesMartix: [Uint8Array, Uint8Array, Uint8Array, Uint8Array, Uint8Array];
|
||||
}
|
||||
2
src/types/common.d.ts
vendored
2
src/types/common.d.ts
vendored
|
|
@ -1,5 +1,7 @@
|
|||
type UnknownObject = {[key: string]: unknown};
|
||||
|
||||
type noop = () => void;
|
||||
|
||||
interface Dict<T> {
|
||||
[key: string]: T;
|
||||
}
|
||||
|
|
|
|||
2
src/types/env.d.ts
vendored
Normal file
2
src/types/env.d.ts
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
declare const APP_VERSION: string;
|
||||
declare const PRODUCTION: boolean;
|
||||
49
src/types/globals.d.ts
vendored
Normal file
49
src/types/globals.d.ts
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
declare const grid: IGrid;
|
||||
declare const pack: IPack;
|
||||
|
||||
declare let seed: string;
|
||||
declare let mapId: number;
|
||||
declare let mapHistory: IMapHistoryEntry[];
|
||||
|
||||
declare let elSelected: Selection<HTMLElement>;
|
||||
|
||||
declare let notes: INote[];
|
||||
declare let customization: number;
|
||||
|
||||
declare let rulers: Rulers;
|
||||
declare let biomesData: IBiomesData;
|
||||
declare let nameBases: INamebase[];
|
||||
|
||||
declare let graphWidth: number;
|
||||
declare let graphHeight: number;
|
||||
declare let svgWidth: number;
|
||||
declare let svgHeight: number;
|
||||
|
||||
declare let options: IOptions;
|
||||
|
||||
interface IOptions {
|
||||
pinNotes: boolean;
|
||||
showMFCGMap: boolean;
|
||||
winds: [number, number, number, number, number, number];
|
||||
stateLabelsMode: "auto" | "short" | "full";
|
||||
}
|
||||
|
||||
declare let populationRate: number;
|
||||
declare let urbanization: number;
|
||||
declare let distanceScale: number;
|
||||
declare let urbanDensity: number;
|
||||
declare let statesNeutral: number;
|
||||
|
||||
declare let scaleBar: Selection<HTMLElement>;
|
||||
declare let legend: Selection<HTMLElement>;
|
||||
|
||||
declare const defineSvg: (graphWidth: number, graphHeight: number) => void;
|
||||
|
||||
// old modules
|
||||
declare const Biomes: {
|
||||
getDefault: () => IBiomesData;
|
||||
};
|
||||
|
||||
declare const Names: {
|
||||
getNameBases: () => INamebase[];
|
||||
};
|
||||
7
src/types/grid.d.ts
vendored
Normal file
7
src/types/grid.d.ts
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
interface IGrid {
|
||||
points: TPoints;
|
||||
cells: {
|
||||
h: TypedArray;
|
||||
prec: number[];
|
||||
};
|
||||
}
|
||||
9
src/types/namebase.d.ts
vendored
Normal file
9
src/types/namebase.d.ts
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
interface INamebase {
|
||||
i: number;
|
||||
name: string;
|
||||
b: string; // comma-separated list of names
|
||||
d: string; // dublicating letters
|
||||
m: number; // words multiplication chance
|
||||
max: number; // recommended max name length
|
||||
min: number; // recommended min name length
|
||||
}
|
||||
5
src/types/note.d.ts
vendored
Normal file
5
src/types/note.d.ts
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
interface INote {
|
||||
id: number;
|
||||
name: string;
|
||||
legend: string;
|
||||
}
|
||||
7
src/types/overrides.d.ts
vendored
7
src/types/overrides.d.ts
vendored
|
|
@ -10,11 +10,8 @@ interface Window {
|
|||
[key: string]: boolean;
|
||||
};
|
||||
};
|
||||
pack: IPack;
|
||||
grig: IGrid;
|
||||
d3: typeof d3;
|
||||
graphHeight: number;
|
||||
graphWidth: number;
|
||||
$: typeof $;
|
||||
mapCoordinates: IMapCoordinates;
|
||||
}
|
||||
|
||||
|
|
@ -22,5 +19,3 @@ interface Node {
|
|||
on: (name: string, fn: EventListenerOrEventListenerObject, options?: AddEventListenerOptions) => void;
|
||||
off: (name: string, fn: EventListenerOrEventListenerObject) => void;
|
||||
}
|
||||
|
||||
type UnknownObject = {[key: string]: unknown};
|
||||
|
|
|
|||
23
src/types/pack.d.ts
vendored
Normal file
23
src/types/pack.d.ts
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
interface IPack {
|
||||
cells: {
|
||||
i: number[];
|
||||
g: number[];
|
||||
h: number[];
|
||||
pop: number[];
|
||||
burg: number[];
|
||||
};
|
||||
states: [];
|
||||
cultures: [];
|
||||
provinces: [];
|
||||
burgs: IBurg[];
|
||||
religions: [];
|
||||
}
|
||||
|
||||
interface IBurg {
|
||||
i: number;
|
||||
name: string;
|
||||
cell: number;
|
||||
x: number;
|
||||
y: number;
|
||||
population: number;
|
||||
}
|
||||
7
src/types/stores.d.ts
vendored
Normal file
7
src/types/stores.d.ts
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
interface IMapHistoryEntry {
|
||||
seed: string;
|
||||
width: number;
|
||||
height: number;
|
||||
template: string;
|
||||
created: number;
|
||||
}
|
||||
|
|
@ -21,12 +21,10 @@ interface ICreateTypesArrayFrom {
|
|||
export function createTypedArray(params: ICreateTypesArrayLength | ICreateTypesArrayFrom) {
|
||||
const typedArray = getTypedArray(params.maxValue);
|
||||
if ("from" in params) {
|
||||
typedArray.from(params.from);
|
||||
} else if ("length" in params) {
|
||||
return new typedArray(params.length);
|
||||
return typedArray.from(params.from);
|
||||
}
|
||||
|
||||
return typedArray;
|
||||
return new typedArray(params.length);
|
||||
}
|
||||
|
||||
function getTypedArray(maxValue: number) {
|
||||
|
|
|
|||
|
|
@ -55,9 +55,7 @@ export function convertTemperature(temp: number) {
|
|||
|
||||
// get user-friendly (real-world) height value from coordinates
|
||||
export function getFriendlyHeight([x, y]: [number, number]) {
|
||||
// @ts-expect-error pack is a global variable
|
||||
const packH = pack.cells.h[findCell(x, y)];
|
||||
// @ts-expect-error grid is a global variable
|
||||
const gridH = grid.cells.h[findGridCell(x, y, grid)];
|
||||
const h = packH < 20 ? gridH : packH;
|
||||
return getHeight(h);
|
||||
|
|
@ -92,7 +90,6 @@ function getFriendlyPrecipitation(prec: number) {
|
|||
|
||||
// get user-friendly (real-world) precipitation value from map data
|
||||
export function getCellIdPrecipitation(gridCellId: number) {
|
||||
// @ts-expect-error pack and grid are global variables
|
||||
const prec = grid.cells.prec[pack.cells.g[gridCellId]];
|
||||
return getFriendlyPrecipitation(prec);
|
||||
}
|
||||
|
|
@ -102,11 +99,8 @@ export function getCellIdPrecipitation(gridCellId: number) {
|
|||
// ***
|
||||
|
||||
export function getCellPopulation(cellId: number) {
|
||||
// @ts-expect-error pack and populationRate are global variables
|
||||
const rural = pack.cells.pop[cellId] * populationRate;
|
||||
// @ts-expect-error pack is a global variable
|
||||
const burg = pack.cells.burg[cellId];
|
||||
// @ts-expect-error pack and populationRate and urbanization are global variables
|
||||
const urban = burg ? pack.burgs[burg].population * populationRate * urbanization : 0;
|
||||
return [rural, urban];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,74 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
// version and caching control
|
||||
const version = "1.87.04"; // generator version, update each time
|
||||
|
||||
{
|
||||
document.title += " v" + version;
|
||||
const loadingScreenVersion = document.getElementById("version");
|
||||
if (loadingScreenVersion) loadingScreenVersion.innerHTML = version;
|
||||
|
||||
const versionNumber = parseFloat(version);
|
||||
const storedVersion = localStorage.getItem("version") ? parseFloat(localStorage.getItem("version")) : 0;
|
||||
|
||||
const isOutdated = storedVersion !== versionNumber;
|
||||
if (isOutdated) clearCache();
|
||||
|
||||
const showUpdate = storedVersion < versionNumber;
|
||||
if (showUpdate) 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 <i>.map</i> files will be auto-updated.
|
||||
${storedVersion ? "<span>Reload the page to fetch fresh code.</span>" : ""}
|
||||
|
||||
<ul>
|
||||
<strong>Latest changes:</strong>
|
||||
<li>Data Charts screen</li>
|
||||
<li>Сultures and religions can have multiple parents in hierarchy tree</li>
|
||||
<li>Heightmap selection screen</li>
|
||||
<li>Dialogs optimization for mobile</li>
|
||||
<li>New heightmap template: Fractious</li>
|
||||
<li>Template Editor: mask and invert tools</li>
|
||||
<li>Ability to install the App</li>
|
||||
<li>14 new default fonts</li>
|
||||
<li>Caching for faster startup</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 Worlbuilding, report bugs and propose new features.</p>
|
||||
<span><i>Thanks for all supporters on <a href="${patreon}" target="_blank">Patreon</a>!</i></span>`;
|
||||
|
||||
const buttons = {
|
||||
Ok: function () {
|
||||
$(this).dialog("close");
|
||||
if (storedVersion) localStorage.clear();
|
||||
localStorage.setItem("version", version);
|
||||
}
|
||||
};
|
||||
|
||||
if (storedVersion) {
|
||||
buttons.Reload = () => {
|
||||
localStorage.clear();
|
||||
localStorage.setItem("version", version);
|
||||
location.reload();
|
||||
};
|
||||
}
|
||||
|
||||
$("#alert").dialog({
|
||||
resizable: false,
|
||||
title: "Fantasy Map Generator update",
|
||||
width: "28em",
|
||||
position: {my: "center center-4em", at: "center", of: "svg"},
|
||||
buttons
|
||||
});
|
||||
}
|
||||
|
||||
async function clearCache() {
|
||||
const cacheNames = await caches.keys();
|
||||
Promise.all(cacheNames.map(cacheName => caches.delete(cacheName)));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue