index : btroops | |
Virtual board game-aid for BattleTroops, an infantry combat simulator wargame published by FASA in 1989. |
aboutsummaryrefslogtreecommitdiff |
diff options
author | Catalin Mititiuc <webdevcat@proton.me> | 2024-06-01 11:31:35 -0700 |
---|---|---|
committer | Catalin Mititiuc <webdevcat@proton.me> | 2024-06-01 11:31:58 -0700 |
commit | e8fae51b32b6ebc4ec4e16338467b7fcc41edd11 (patch) | |
tree | baf01092df986019346c4cc606cce2584577eed5 /src/index.js | |
parent | 9a4fec27daed58272c71e163df7df216a4252127 (diff) |
WIP: use scenario template to build scenarios client-side
Diffstat (limited to 'src/index.js')
-rw-r--r-- | src/index.js | 246 |
1 files changed, 212 insertions, 34 deletions
diff --git a/src/index.js b/src/index.js index 992366a..e638910 100644 --- a/src/index.js +++ b/src/index.js @@ -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 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'); - // const useEls = svg.querySelectorAll('use[href*=".svg"]'); + // Object.keys(refs).forEach((filename, index) => { + // const external = result[index]; - // console.log(useEls); + // refs[filename].forEach(fragmentIdentifier => { + // external + // .querySelectorAll(`${fragmentIdentifier} use`) + // .forEach(el => refs[filename].add(el.getAttributeNS(null, 'href'))); + // }); - // [...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); + // 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)); |