mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
dropbox - import changes from alpha
This commit is contained in:
parent
7865497cd2
commit
c783301de9
7 changed files with 208 additions and 129 deletions
|
|
@ -12,6 +12,18 @@ function quickLoad() {
|
|||
});
|
||||
}
|
||||
|
||||
function loadFromDropbox() {
|
||||
const options = {
|
||||
success: function (files) {
|
||||
const url = files[0].link;
|
||||
loadMapFromURL(url);
|
||||
},
|
||||
linkType: "direct",
|
||||
extensions: [".map"]
|
||||
};
|
||||
Dropbox.choose(options);
|
||||
}
|
||||
|
||||
function loadMapPrompt(blob) {
|
||||
const workingTime = (Date.now() - last(mapHistory).created) / 60000; // minutes
|
||||
if (workingTime < 5) {
|
||||
|
|
@ -46,6 +58,37 @@ function loadMapPrompt(blob) {
|
|||
}
|
||||
}
|
||||
|
||||
function loadMapFromURL(maplink, random) {
|
||||
const URL = decodeURIComponent(maplink);
|
||||
|
||||
fetch(URL, {method: "GET", mode: "cors"})
|
||||
.then(response => {
|
||||
if (response.ok) return response.blob();
|
||||
throw new Error("Cannot load map from URL");
|
||||
})
|
||||
.then(blob => uploadMap(blob))
|
||||
.catch(error => {
|
||||
showUploadErrorMessage(error.message, URL, random);
|
||||
if (random) generateMapOnLoad();
|
||||
});
|
||||
}
|
||||
|
||||
function showUploadErrorMessage(error, URL, random) {
|
||||
ERROR && console.error(error);
|
||||
alertMessage.innerHTML = `Cannot load map from the ${link(URL, "link provided")}.
|
||||
${random ? `A new random map is generated. ` : ""}
|
||||
Please ensure the linked file is reachable and CORS is allowed on server side`;
|
||||
$("#alert").dialog({
|
||||
title: "Loading error",
|
||||
width: "32em",
|
||||
buttons: {
|
||||
OK: function () {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function uploadMap(file, callback) {
|
||||
uploadMap.timeStart = performance.now();
|
||||
|
||||
|
|
@ -54,14 +97,12 @@ function uploadMap(file, callback) {
|
|||
if (callback) callback();
|
||||
document.getElementById("coas").innerHTML = ""; // remove auto-generated emblems
|
||||
|
||||
const dataLoaded = fileLoadedEvent.target.result;
|
||||
const result = fileLoadedEvent.target.result;
|
||||
const dataLoaded = last(result) === "=" ? decodeURIComponent(atob(result)) : result; // map can be encoded base64
|
||||
const data = dataLoaded.split("\r\n");
|
||||
|
||||
const mapVersion = data[0].split("|")[0] || data[0];
|
||||
if (mapVersion === version) {
|
||||
parseLoadedData(data);
|
||||
return;
|
||||
}
|
||||
if (mapVersion === version) return parseLoadedData(data);
|
||||
|
||||
const archive = link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Changelog", "archived version");
|
||||
const parsed = parseFloat(mapVersion);
|
||||
|
|
|
|||
135
modules/save.js
135
modules/save.js
|
|
@ -367,68 +367,65 @@ function inlineStyle(clone) {
|
|||
|
||||
// prepare map data for saving
|
||||
function getMapData() {
|
||||
TIME && console.time("createMapDataBlob");
|
||||
TIME && console.time("createMapData");
|
||||
|
||||
return new Promise(resolve => {
|
||||
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, distanceScaleInput.value, areaUnit.value, heightUnit.value, heightExponentInput.value, temperatureScale.value, barSizeInput.value, barLabel.value, barBackOpacity.value, barBackColor.value, barPosX.value, barPosY.value, populationRate, urbanization, mapSizeOutput.value, latitudeOutput.value, temperatureEquatorOutput.value, temperaturePoleOutput.value, precOutput.value, JSON.stringify(options), mapName.value, +hideLabels.checked, stylePreset.value, +rescaleLabels.checked].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 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, distanceScaleInput.value, areaUnit.value, heightUnit.value, heightExponentInput.value, temperatureScale.value, barSizeInput.value, barLabel.value, barBackOpacity.value, barBackColor.value, barPosX.value, barPosY.value, populationRate, urbanization, mapSizeOutput.value, latitudeOutput.value, temperatureEquatorOutput.value, temperaturePoleOutput.value, precOutput.value, JSON.stringify(options), mapName.value, +hideLabels.checked, stylePreset.value, +rescaleLabels.checked].join("|");
|
||||
const coords = JSON.stringify(mapCoordinates);
|
||||
const biomes = [biomesData.color, biomesData.habitability, biomesData.name].join("|");
|
||||
const notesData = JSON.stringify(notes);
|
||||
const rulersString = rulers.toString();
|
||||
|
||||
// clone svg
|
||||
const cloneEl = document.getElementById("map").cloneNode(true);
|
||||
// save svg
|
||||
const cloneEl = document.getElementById("map").cloneNode(true);
|
||||
|
||||
// set transform values to default
|
||||
cloneEl.setAttribute("width", graphWidth);
|
||||
cloneEl.setAttribute("height", graphHeight);
|
||||
cloneEl.querySelector("#viewbox").removeAttribute("transform");
|
||||
// reset transform values to default
|
||||
cloneEl.setAttribute("width", graphWidth);
|
||||
cloneEl.setAttribute("height", graphHeight);
|
||||
cloneEl.querySelector("#viewbox").removeAttribute("transform");
|
||||
|
||||
// always remove rulers
|
||||
cloneEl.querySelector("#ruler").innerHTML = "";
|
||||
cloneEl.querySelector("#ruler").innerHTML = ""; // always remove rulers
|
||||
|
||||
const svg_xml = new XMLSerializer().serializeToString(cloneEl);
|
||||
const serializedSVG = new XMLSerializer().serializeToString(cloneEl);
|
||||
|
||||
const gridGeneral = JSON.stringify({spacing: grid.spacing, cellsX: grid.cellsX, cellsY: grid.cellsY, boundary: grid.boundary, points: grid.points, features: grid.features});
|
||||
const features = 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 {spacing, cellsX, cellsY, boundary, points, features} = grid;
|
||||
const gridGeneral = JSON.stringify({spacing, cellsX, cellsY, boundary, points, features});
|
||||
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);
|
||||
|
||||
// store name array only if it is 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("/");
|
||||
// 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 resources
|
||||
const pop = Array.from(pack.cells.pop).map(p => rn(p, 4));
|
||||
// round population to save space
|
||||
const pop = Array.from(pack.cells.pop).map(p => rn(p, 4));
|
||||
|
||||
// data format as below
|
||||
const data = [params, settings, coords, biomes, notesData, svg_xml, gridGeneral, grid.cells.h, grid.cells.prec, grid.cells.f, grid.cells.t, grid.cells.temp, features, cultures, states, burgs, pack.cells.biome, pack.cells.burg, pack.cells.conf, pack.cells.culture, pack.cells.fl, pop, pack.cells.r, pack.cells.road, pack.cells.s, pack.cells.state, pack.cells.religion, pack.cells.province, pack.cells.crossroad, religions, provinces, namesData, rivers, rulersString].join("\r\n");
|
||||
const blob = new Blob([data], {type: "text/plain"});
|
||||
|
||||
TIME && console.timeEnd("createMapDataBlob");
|
||||
resolve(blob);
|
||||
});
|
||||
// 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, pack.cells.road, pack.cells.s, pack.cells.state, pack.cells.religion, pack.cells.province, pack.cells.crossroad, religions, provinces, namesData, rivers, rulersString].join("\r\n");
|
||||
TIME && console.timeEnd("createMapData");
|
||||
return mapData;
|
||||
}
|
||||
|
||||
// Download .map file
|
||||
async function saveMap() {
|
||||
function dowloadMap() {
|
||||
if (customization) return tip("Map cannot be saved when edit mode is active, please exit the mode and retry", false, "error");
|
||||
closeDialogs("#alert");
|
||||
|
||||
const blob = await getMapData();
|
||||
const mapData = getMapData();
|
||||
const blob = new Blob([mapData], {type: "text/plain"});
|
||||
const URL = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement("a");
|
||||
link.download = getFileName() + ".map";
|
||||
|
|
@ -438,6 +435,44 @@ async function saveMap() {
|
|||
window.URL.revokeObjectURL(URL);
|
||||
}
|
||||
|
||||
function saveToDropbox() {
|
||||
if (customization) return tip("Map cannot be saved when edit mode is active, please exit the mode and retry", false, "error");
|
||||
closeDialogs("#alert");
|
||||
|
||||
const mapData = getMapData();
|
||||
const URL = "data:text/plain; base64," + btoa(encodeURIComponent(mapData));
|
||||
const filename = getFileName() + ".map";
|
||||
const options = {
|
||||
success: () => tip("Map is saved to your Dropbox", true, "success", 8000),
|
||||
error: function (errorMessage) {
|
||||
tip("Cannot save .map to your Dropbox", true, "error", 8000);
|
||||
console.error(errorMessage);
|
||||
}
|
||||
};
|
||||
Dropbox.save(URL, filename, options);
|
||||
}
|
||||
|
||||
function createSharableDropboxLink() {
|
||||
const sharableLink = document.getElementById("sharableLink");
|
||||
const sharableLinkContainer = document.getElementById("sharableLinkContainer");
|
||||
|
||||
const options = {
|
||||
success: function (files) {
|
||||
const url = files[0].link;
|
||||
const fmg = window.location.href.split("?")[0];
|
||||
const link = `${fmg}/?maplink=${url}`;
|
||||
const shortLink = link.slice(0, 50) + "...";
|
||||
|
||||
sharableLinkContainer.style.display = "block";
|
||||
sharableLink.innerText = shortLink;
|
||||
sharableLink.setAttribute("href", link);
|
||||
},
|
||||
linkType: "direct",
|
||||
extensions: [".map"]
|
||||
};
|
||||
Dropbox.choose(options);
|
||||
}
|
||||
|
||||
function saveGeoJSON_Cells() {
|
||||
const json = {type: "FeatureCollection", features: []};
|
||||
const cells = pack.cells;
|
||||
|
|
@ -556,9 +591,11 @@ function getRiverPoints(node) {
|
|||
return points;
|
||||
}
|
||||
|
||||
async function quickSave() {
|
||||
function quickSave() {
|
||||
if (customization) return tip("Map cannot be saved when edit mode is active, please exit the mode and retry", false, "error");
|
||||
const blob = await getMapData();
|
||||
|
||||
const mapData = getMapData();
|
||||
const blob = new Blob([mapData], {type: "text/plain"});
|
||||
if (blob) ldb.set("lastMap", blob); // auto-save map
|
||||
tip("Map is saved to browser memory. Please also save as .map file to secure progress", true, "success", 2000);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ function editHeightmap() {
|
|||
<p><i>Erase</i> mode also allows you Convert an Image into a heightmap or use Template Editor.</p>
|
||||
<p>You can <i>keep</i> the data, but you won't be able to change the coastline.</p>
|
||||
<p>Try <i>risk</i> mode to change the coastline and keep the data. The data will be restored as much as possible, but it can cause unpredictable errors.</p>
|
||||
<p>Please <span class="pseudoLink" onclick=saveMap(); editHeightmap();>save the map</span> before editing the heightmap!</p>
|
||||
<p>Please <span class="pseudoLink" onclick=dowloadMap(); editHeightmap();>save the map</span> before editing the heightmap!</p>
|
||||
<p>Check out ${link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Heightmap-customization", "wiki")} for guidance.</p>`;
|
||||
|
||||
$("#alert").dialog({
|
||||
|
|
|
|||
|
|
@ -621,6 +621,7 @@ document.getElementById("sticked").addEventListener("click", function (event) {
|
|||
const id = event.target.id;
|
||||
if (id === "newMapButton") regeneratePrompt();
|
||||
else if (id === "saveButton") showSavePane();
|
||||
else if (id === "exportButton") showExportPane();
|
||||
else if (id === "loadButton") showLoadPane();
|
||||
else if (id === "zoomReset") resetZoom(1000);
|
||||
});
|
||||
|
|
@ -654,12 +655,13 @@ function regeneratePrompt() {
|
|||
}
|
||||
|
||||
function showSavePane() {
|
||||
document.getElementById("showLabels").checked = !hideLabels.checked;
|
||||
const sharableLinkContainer = document.getElementById("sharableLinkContainer");
|
||||
sharableLinkContainer.style.display = "none";
|
||||
|
||||
$("#saveMapData").dialog({
|
||||
title: "Save map",
|
||||
resizable: false,
|
||||
width: "30em",
|
||||
width: "27em",
|
||||
position: {my: "center", at: "center", of: "svg"},
|
||||
buttons: {
|
||||
Close: function () {
|
||||
|
|
@ -669,21 +671,21 @@ function showSavePane() {
|
|||
});
|
||||
}
|
||||
|
||||
// download map data as GeoJSON
|
||||
function saveGeoJSON() {
|
||||
alertMessage.innerHTML = `You can export map data in GeoJSON format used in GIS tools such as QGIS.
|
||||
Check out ${link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/GIS-data-export", "wiki-page")} for guidance`;
|
||||
function copyLinkToClickboard() {
|
||||
const shrableLink = document.getElementById("sharableLink");
|
||||
const link = shrableLink.getAttribute("href");
|
||||
navigator.clipboard.writeText(link).then(() => tip("Link is copied to the clipboard", true, "success", 8000));
|
||||
}
|
||||
|
||||
$("#alert").dialog({
|
||||
title: "GIS data export",
|
||||
function showExportPane() {
|
||||
document.getElementById("showLabels").checked = !hideLabels.checked;
|
||||
|
||||
$("#exportMapData").dialog({
|
||||
title: "Export map data",
|
||||
resizable: false,
|
||||
width: "35em",
|
||||
width: "26em",
|
||||
position: {my: "center", at: "center", of: "svg"},
|
||||
buttons: {
|
||||
Cells: saveGeoJSON_Cells,
|
||||
Routes: saveGeoJSON_Routes,
|
||||
Rivers: saveGeoJSON_Rivers,
|
||||
Markers: saveGeoJSON_Markers,
|
||||
Close: function () {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
|
|
@ -695,7 +697,7 @@ function showLoadPane() {
|
|||
$("#loadMapData").dialog({
|
||||
title: "Load map",
|
||||
resizable: false,
|
||||
width: "17em",
|
||||
width: "22em",
|
||||
position: {my: "center", at: "center", of: "svg"},
|
||||
buttons: {
|
||||
Close: function () {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue