WIP: use scenario template to build scenarios client-side

This commit is contained in:
2024-06-01 11:31:35 -07:00
parent 9a4fec27da
commit e8fae51b32
7 changed files with 300 additions and 2143 deletions

View File

@@ -40,16 +40,134 @@ const mapPlaceholder = document.querySelector('.map-placeholder'),
let mapResourceEl = document.querySelector('object');
async function requestScenario(url) {
return new Promise((res, rej) => {
const request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'document';
request.onload = function() {
if (request.status === 200) {
res(request.response);
} else {
rej(Error('Image didn\'t load successfully; error code:' + request.statusText));
}
};
request.onerror = function() {
rej(Error('There was a network error.'));
};
request.send();
});
}
const scenarioRequest = requestScenario(map);
function loadScenario(data) {
const current = document.querySelector('object');
const next = document.createElement('object');
next.setAttribute('type', 'image/svg+xml');
next.style.opacity = 0;
next.addEventListener('load', load);
mapPlaceholder.style.opacity = 1;
next.data = data;
mapPlaceholder.after(next);
current.remove();
// const current = document.querySelector('object');
// const next = document.createElement('object');
// next.setAttribute('type', 'image/svg+xml');
// next.style.opacity = 0;
// next.addEventListener('load', load);
// mapPlaceholder.style.opacity = 1;
// next.data = data;
// mapPlaceholder.after(next);
// current.remove();
buildScenario(requestScenario(data));
}
async function buildScenario(req) {
console.log('req', req);
const svg = scenarioTemplate.querySelector('svg').cloneNode(true);
document.querySelector('object').contentDocument.querySelector('svg').replaceWith(svg);
const startLocs = svg.querySelector('.start-locations');
const scenario = await req;
console.log(scenario);
const gb = svg.querySelector('.gameboard');
const grid = svg.querySelector('.grid');
const externalResourceEls = Array.from(scenario.querySelectorAll('use[href*=".svg"'));
const refs = externalResourceEls.reduce((acc, el) => {
const href = el.getAttributeNS(null, 'href');
const [filename] = href.match(/.+\.svg/);
const fragmentIdentifier = href.split('.svg').pop();
(acc[filename] ??= new Set()).add(fragmentIdentifier);
el.setAttributeNS(null, 'href', fragmentIdentifier);
return acc;
}, {});
await Promise.all(
Object.keys(refs).map(filename => requestScenario(`assets/images/${filename}`))
).then(result => {
const defs = svg.querySelector('defs');
Object.keys(refs).forEach((filename, index) => {
const external = result[index];
refs[filename].forEach(fragmentIdentifier => {
external
.querySelectorAll(`${fragmentIdentifier} use`)
.forEach(el => refs[filename].add(el.getAttributeNS(null, 'href')));
});
const refsQuery = [...refs[filename]].join(', ');
external.querySelectorAll(refsQuery).forEach(node => defs.append(node));
});
});
scenario.querySelectorAll('use.mapsheet').forEach(el => gb.prepend(el));
grid.before(scenario.querySelector('.start-locations'));
const scenarioGrid = scenario.querySelector('.grid');
console.log('scenarioGrid', scenarioGrid);
if (scenarioGrid) {
grid.replaceWith(svg.ownerDocument.importNode(scenarioGrid, true));
}
async function loadScript() {
return new Promise((resolve, reject) => {
const scriptEl = document.createElementNS("http://www.w3.org/2000/svg", 'script');
// const scriptEl = svg.ownerDocument.importNode(scenario.querySelector('script'));
scriptEl.onload = () => {
console.log('map.js loaded');
resolve();
};
scriptEl.onerror = () => {
reject(Error('Script failed to load.'));
};
const oldScript = scenario.querySelector('script');
if ('cols' in oldScript.dataset && 'rows' in oldScript.dataset) {
scriptEl.dataset.rows = oldScript.dataset.rows;
scriptEl.dataset.cols = oldScript.dataset.cols;
}
scriptEl.setAttributeNS(null, 'href', '../../map.js');
svg.append(scriptEl);
});
}
await loadScript();
// this.style.opacity = 1;
// mapPlaceholder.style.opacity = 0;
panzoom.start(svg);
gameboard.start(svg);
recordSheet.start(startLocs, gameboard.getUnits());
}
function updateTurnCounter() {
@@ -91,23 +209,82 @@ function roll(die) {
return numsAsWords[getRandomIntInclusive(0, numsAsWords.length - 1)];
}
function load() {
let scenarioTemplate;
async function load() {
const svg = this.contentDocument.querySelector('svg'),
startLocs = svg.querySelector('.start-locations')
// , scriptEl = this.contentDocument.querySelector('script')
;
scenarioTemplate = this.contentDocument.cloneNode(svg);
buildScenario(scenarioRequest);
// const scenario = await scenarioRequest;
// const gb = svg.querySelector('.gameboard');
// const grid = svg.querySelector('.grid');
// const useEls = svg.querySelectorAll('use[href*=".svg"]');
// const externalResourceEls = Array.from(scenario.querySelectorAll('use[href*=".svg"'));
// console.log(useEls);
// const refs = externalResourceEls.reduce((acc, el) => {
// const href = el.getAttributeNS(null, 'href');
// const [filename] = href.match(/.+\.svg/);
// const fragmentIdentifier = href.split('.svg').pop();
// [...new Set([...useEls].map(el => el.getAttributeNS(null, 'href').match(/^(.*?)\.svg/g).at(0)))].forEach(f => {
// const name = `../assets/images/${f}`;
// import(name);
// console.log(f);
// (acc[filename] ??= new Set()).add(fragmentIdentifier);
// el.setAttributeNS(null, 'href', fragmentIdentifier);
// return acc;
// }, {});
// await Promise.all(
// Object.keys(refs).map(filename => requestScenario(`assets/images/${filename}`))
// ).then(result => {
// const defs = svg.querySelector('defs');
// Object.keys(refs).forEach((filename, index) => {
// const external = result[index];
// refs[filename].forEach(fragmentIdentifier => {
// external
// .querySelectorAll(`${fragmentIdentifier} use`)
// .forEach(el => refs[filename].add(el.getAttributeNS(null, 'href')));
// });
// const refsQuery = [...refs[filename]].join(', ');
// external.querySelectorAll(refsQuery).forEach(node => defs.append(node));
// });
// });
// scenario.querySelectorAll('use.mapsheet').forEach(el => gb.prepend(el));
// grid.before(scenario.querySelector('.start-locations'));
// async function loadScript() {
// return new Promise((resolve, reject) => {
// const scriptEl = document.createElementNS("http://www.w3.org/2000/svg", 'script');
// // const scriptEl = svg.ownerDocument.importNode(scenario.querySelector('script'));
// scriptEl.onload = () => {
// console.log('map.js loaded');
// resolve();
// };
// scriptEl.onerror = () => {
// reject(Error('Script failed to load.'));
// };
// scriptEl.dataset.rows = scenario.querySelector('script').dataset.rows;
// scriptEl.dataset.cols = scenario.querySelector('script').dataset.cols;
// scriptEl.setAttributeNS(null, 'href', '../../map.js');
// svg.append(scriptEl);
// });
// }
// await loadScript();
this.style.opacity = 1;
mapPlaceholder.style.opacity = 0;
// URL.revokeObjectURL(this.data);
// const linkEl = document.createElement('link');
// linkEl.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');
// linkEl.setAttribute('rel', 'stylesheet');
@@ -116,25 +293,13 @@ function load() {
// linkEl.onload = function (e) {
// console.log('map.css loaded');
// if (scriptEl) {
// scriptEl.onload = function () {
// console.log('map.js loaded');
// };
// scriptEl.setAttribute('href', '../../map.js');
// }
// };
// svg.prepend(linkEl);
this.style.opacity = 1;
mapPlaceholder.style.opacity = 0;
URL.revokeObjectURL(this.data);
panzoom.start(svg);
gameboard.start(svg);
recordSheet.start(startLocs, gameboard.getUnits());
// panzoom.start(svg);
// gameboard.start(svg);
// recordSheet.start(startLocs, gameboard.getUnits());
}
document.querySelectorAll('.end-turn').forEach(el =>
@@ -199,7 +364,19 @@ document.querySelector('#upload-save').addEventListener('click', () => {
document.querySelector('input[type="file"]').addEventListener('change', e => {
const [file] = fileInputEl.files;
loadScenario(URL.createObjectURL(file))
let reader = new FileReader();
reader.onload = function () {
const parser = new DOMParser();
const doc = parser.parseFromString(reader.result, "image/svg+xml");
buildScenario(doc);
};
reader.readAsText(file);
// loadScenario(URL.createObjectURL(file));
});
document.querySelector('#roll-dice').addEventListener('click', () => {
@@ -221,8 +398,9 @@ mapSelectDialog
.changeMapOnConfirm(loadScenario);
mapResourceEl.addEventListener('load', load);
mapResourceEl.data = map;
mapResourceEl = null;
// mapResourceEl.data = map;
// mapResourceEl = null;
dice.forEach(el => {
el.classList.add(roll(d6));