diff --git a/.gitignore b/.gitignore index d3285b41..c3f4099c 100644 --- a/.gitignore +++ b/.gitignore @@ -47,7 +47,6 @@ saves sharedPlugins/* !sharedPlugins/inventoryImports/ !sharedPlugins/UPSdisplay/ -!sharedPlugins/remoteMap/ !sharedPlugins/remoteCommands/ !sharedPlugins/researchSync/ !sharedPlugins/globalChat/ diff --git a/master.js b/master.js index c74e6934..4af91d1e 100644 --- a/master.js +++ b/master.js @@ -712,83 +712,11 @@ app.get("/api/getFactorioLocale", function(req,res){ }); }); -/* Websockets for remoteMap */ +/* Websockets for plugins */ var io = require("socket.io")({}); const ioMetrics = require("socket.io-prometheus"); ioMetrics(io); -var slaveMappers = {}; -class slaveMapper { - constructor(instanceID, socket) { - this.instanceID = instanceID; - this.socket = socket; - this.lastBeat = Date.now(); - - this.socket.on("heartbeat", () => { - prometheusWsUsageCounter.labels('heartbeat', this.instanceID).inc(); - // we aren't ready to die yet apparently - this.lastBeat = Date.now(); - }); - this.socket.on("sendChunk", function(data){ - prometheusWsUsageCounter.labels('sendChunk', this.instanceID).inc(); - mapRequesters[data.requesterID].socket.emit("displayChunk", data); - }); - // slaveMapper sent us an entity update, process - this.socket.on("sendEntity", entity => { - prometheusWsUsageCounter.labels('sendEntity', this.instanceID).inc(); - Object.keys(mapRequesters).forEach(requesterName => { - let requester = mapRequesters[requesterName]; - - if(requester.instanceID == this.instanceID){ - // this mapRequester is listening to this slaveMapper, so we send it updates - requester.socket.emit("displayEntity", entity); - } - }); - }); - } -} - - -var mapRequesters = {}; -class mapRequester { - constructor(requesterID, socket, instanceID){ - this.requesterID = requesterID; - this.socket = socket; - this.instanceID = instanceID; - this.lastBeat = Date.now(); - - this.socket.on("heartbeat", () => { - prometheusWsUsageCounter.labels('heartbeat', "other").inc(); - // we aren't ready to die yet apparently - this.lastBeat = Date.now(); - }); - this.socket.on("requestChunk", loc => { - prometheusWsUsageCounter.labels('requestChunk', "other").inc(); - loc.requesterID = this.requesterID; - let instanceID = loc.instanceID || this.instanceID; - if(slaveMappers[instanceID] && typeof loc.x == "number" && typeof loc.y == "number"){ - slaveMappers[instanceID].socket.emit("getChunk", loc); - } - }); - this.socket.on("requestEntity", req => { - prometheusWsUsageCounter.labels('requestEntity', "other").inc(); - req.requesterID = this.requesterID; - let instanceID = req.instanceID || this.instanceID; - if(slaveMappers[instanceID] && typeof req.x == "number" && typeof req.y == "number"){ - slaveMappers[instanceID].socket.emit("getEntity", req); - } - }); - this.socket.on("placeEntity", req => { - prometheusWsUsageCounter.labels('placeEntity', "other").inc(); - req.requesterID = this.requesterID; - let instanceID = req.instanceID || this.instanceID; - if(slaveMappers[instanceID]){ - slaveMappers[instanceID].socket.emit("placeEntity", req); - } - }); - } -} - /* Websockets for send and recieve combinators */ var wsSlaves = {}; @@ -852,8 +780,8 @@ class wsSlave { io.on('connection', function (socket) { // cleanup dead sockets from disconnected people let terminatedConnections = 0; - let currentConnections = Object.keys(mapRequesters).length + Object.keys(slaveMappers).length + Object.keys(wsSlaves).length; - [mapRequesters, slaveMappers, wsSlaves].forEach(list => { + let currentConnections = Object.keys(wsSlaves).length; + [wsSlaves].forEach(list => { Object.keys(list).forEach(connectionID => { let connection = list[connectionID]; if(connection.lastBeat < (Date.now() - 30000)){ @@ -867,21 +795,6 @@ io.on('connection', function (socket) { // tell our friend that we are listening setTimeout(()=>socket.emit('hello', { hello: 'world' }), 5000); - /* initial processing for remoteMap */ - socket.on('registerSlaveMapper', function (data) { - prometheusWsUsageCounter.labels('registerSlaveMapper', "other").inc(); - slaveMappers[data.instanceID] = new slaveMapper(data.instanceID, socket); - console.log("remoteMap | SOCKET registered map provider for "+data.instanceID); - }); - socket.on('registerMapRequester', function(data){ - // data {instanceID:""} - prometheusWsUsageCounter.labels('registerMapRequester', "other").inc(); - let requesterID = Math.random().toString(); - mapRequesters[requesterID] = new mapRequester(requesterID, socket, data.instanceID); - socket.emit("mapRequesterReady", true); - console.log("remoteMap | SOCKET registered map requester for "+data.instanceID); - }); - /* Websockets for send and recieve combinators */ socket.on("registerSlave", function(data) { prometheusWsUsageCounter.labels('registerSlave', "other").inc(); diff --git a/master.spec.js b/master.spec.js index a7fac60a..52620873 100644 --- a/master.spec.js +++ b/master.spec.js @@ -37,7 +37,7 @@ describe('Master server endpoint testing', function() { parallel("#GET static website data", function() { this.timeout(6000); - let paths = ["/", "/nodes", "/settings", "/nodeDetails", "/remoteMap"]; + let paths = ["/", "/nodes", "/settings", "/nodeDetails"]; for (let path of paths) { it(`sends some HTML when accessing ${path}`, () => getValidate(path)); } diff --git a/routes.js b/routes.js index 14f7a473..efd330b0 100644 --- a/routes.js +++ b/routes.js @@ -11,7 +11,4 @@ module.exports = function(app) { app.get("/nodeDetails", function(req, res) { res.render("nodeDetails"); }); - app.get("/remoteMap", function(req, res) { - res.render("remoteMap"); - }); }; \ No newline at end of file diff --git a/static/nodeDetails.js b/static/nodeDetails.js index d1044f45..90fc42db 100644 --- a/static/nodeDetails.js +++ b/static/nodeDetails.js @@ -131,18 +131,6 @@ function populateSlaveInfo(){ HTML += '"; HTML += '"; - // detect if remoteMap mod is installed, if it is we want to show the link for it - let hasRemoteMap = false; - slave.mods.forEach(mod => { - console.log(mod.modName); - if(mod.modName.includes("remoteMap")){ - hasRemoteMap = true; // we are still doing the logic on the outside, in case there are multiple instances of remoteMap installed.... - } - }); - if(hasRemoteMap){ - HTML += "Remote map"; - } - HTML += ""; // end of displayBody // list mods and other metadata diff --git a/static/nodes.html b/static/nodes.html index a34632eb..d026e9ae 100644 --- a/static/nodes.html +++ b/static/nodes.html @@ -14,13 +14,6 @@
<% - function findInArray(key, value, array){ - let indexes = []; - for(let i in array){ - if(array[i][key] && array[i][key].includes(value)) indexes.push(i); - } - return indexes; - } let html = "" for(let id in slaves){ let slave = slaves[id]; @@ -38,7 +31,6 @@
  • IP: ${slave.publicIP}:${slave.serverPort}
  • Host: ${slave.mac}
  • - ${findInArray("modName", "remoteMap", slave.mods).length ? "Remote map" : ""} ` for(let o in locals.masterPlugins){ let plug = locals.masterPlugins[o]; diff --git a/static/remoteMap.html b/static/remoteMap.html deleted file mode 100644 index b7eed423..00000000 --- a/static/remoteMap.html +++ /dev/null @@ -1,28 +0,0 @@ - - - <%- include("head.html") %> - - - - - - <%- include("nav.html") %> -
    -

    remoteMap

    -
    - - - -
    -
    - -
    -
    -

    Map size: (default 32)

    -

    Tile size: (default 8)

    -

    FPS:

    -

    Pause when window is deselected (saves CPU)

    -

    Movement speed: (default 0.2)

    -
    -
    - \ No newline at end of file diff --git a/static/remoteMap.js b/static/remoteMap.js deleted file mode 100644 index d966d908..00000000 --- a/static/remoteMap.js +++ /dev/null @@ -1,608 +0,0 @@ -/** - Javascript to download and render a map of a factorio world from an instance using websockets and canvas - - It is its responsibility to handle: - * Display settings - * Ordering of canvases - * Querying slaves through master for map info - * Drawing of sprites defined in external files to canvas - * Handling input for placing/removing items - * Transmitting item placements/removals through master - - That is way too much for one file, so to anyone reading this: - This file is horribly written and documented. - I am sorry. Drawing code is at the bottom, good luck. - - If you have questions and wish to contact me, my name - is Danielv123 on Github, Discord and esperNet #factorio -*/ -console.log(":)") -/// ES6 imports -// rules for how entities are drawn (sizes, offset etc) -import {entityDrawRules} from "lib/entityDrawRules.js"; -import {getParameterByName, drawImageWithRotation, isImageOk} from "lib/utility.js"; -import spritesheetJson from "./pictures/spritesheet.js"; -import {itemSelector} from "./remoteMap/itemSelection.js"; -var global = {}; - -var itemSelectorGUI = new itemSelector("#remoteMapItemSelector", [ - {name:"stone-furnace"}, - {name:"accumulator"}, - {name:"electric-furnace"}, - {name:"inserter"}, - {name:"express-transport-belt"}, -]); - -if(!localStorage.remoteMapConfig || localStorage.remoteMapConfig == "[object Object]"){ - localStorage.remoteMapConfig = JSON.stringify({ - mapSize: 32, - tileSize: 8, - movementSpeed: 0.2, - }); -} - -var remoteMapConfig = JSON.parse(localStorage.remoteMapConfig); - -// Handle config changes through UI buttons -(function(){ - let selectMapSize = document.querySelector("#mapSize"); - let selectTileSize = document.querySelector("#tileSize"); - if(selectMapSize && selectTileSize){ - selectMapSize.value = Number(remoteMapConfig.mapSize) || 32; - selectTileSize.value = Number(remoteMapConfig.tileSize) || 8; - - selectMapSize.onchange = function(){ - let config = JSON.parse(localStorage.remoteMapConfig); - config.mapSize = Number(selectMapSize.value); - localStorage.remoteMapConfig = JSON.stringify(config); - console.log("Config updated: "+localStorage.remoteMapConfig); - } - selectTileSize.onchange = function(){ - let config = JSON.parse(localStorage.remoteMapConfig); - config.tileSize = Number(selectTileSize.value); - localStorage.remoteMapConfig = JSON.stringify(config); - console.log("Config updated: "+localStorage.remoteMapConfig); - } - } - let pauseOnBlur = document.querySelector("#pauseOnBlur"); - if(pauseOnBlur){ - pauseOnBlur.checked = localStorage.remoteMapPauseOnBlur || true; - pauseOnBlur.onchange = function(){ - localStorage.remoteMapPauseOnBlur = pauseOnBlur.checked; - } - } - let movementSpeed = document.querySelector("#movementSpeed"); - if(movementSpeed){ - movementSpeed.value = Number(remoteMapConfig.movementSpeed) || 0.2; - movementSpeed.onchange = function(){ - let config = JSON.parse(localStorage.remoteMapConfig); - config.movementSpeed = Number(movementSpeed.value); - localStorage.remoteMapConfig = JSON.stringify(config); - console.log("Config updated: "+localStorage.remoteMapConfig); - - // also update config live - remoteMapConfig.movementSpeed = config.movementSpeed; - } - } -})(); - -var socket = io.connect(document.location.origin); -socket.on('hello', function (data) { - console.log(data); - socket.emit("registerMapRequester", {instanceID: getParameterByName("instanceID")}); - socket.on("mapRequesterReady", function(){ - setInterval(()=>{ - socket.emit("heartbeat"); // send our heartbeat to prevent being assumed dead - },10000); - // load important images then proceed with rendering (and loading more images) - global.spritesheet = new Image(); - global.spritesheet.onload = function(){ - global.grassBackground = new Image(); - global.grassBackground.onload = function(){ - requestMapDraw(); - } - global.grassBackground.src = "/pictures/grass-1.png"; - } - global.spritesheet.src = "/pictures/spritesheet.png"; - }); - - socket.on("displayChunk", function(chunk){ - console.log("displayChunk triggered but I can't draw chunks"); - }); - socket.on("displayEntity", function(entity){ - // console.log("Displaying entity "+JSON.stringify(entity)); - drawEntity(entity); - }); -}); - -function requestChunk(x,y){ - socket.emit('requestChunk', {x:x, y:y, instanceID: getParameterByName("instanceID")}); -} -(function(){ - let remoteMapLayers = document.querySelectorAll(".remoteMap"); - remoteMapLayers.forEach(layer => { - layer.addEventListener('contextmenu', event => event.preventDefault()); - layer.width = remoteMapConfig.tileSize * remoteMapConfig.mapSize; - layer.height = remoteMapConfig.tileSize * remoteMapConfig.mapSize; - }); - ["width", "height"].forEach(style => document.querySelector("#remoteMapContainer").style[style] = remoteMapConfig.tileSize * remoteMapConfig.mapSize + "px"); -})(); -const canvas = document.querySelector("#remoteMap"); -const ctx = canvas.getContext("2d"); -ctx.font = "30px Arial"; -ctx.fillText("Use WASD to navigate.",10,50); - -const selectionCanvas = document.querySelector("#remoteMapSelection"); -const selectionCtx = selectionCanvas.getContext("2d"); -selectionCtx.font = "30px Arial"; -selectionCtx.fillText("Selection layer",10,50); - -const backgroundCanvas = document.querySelector("#remoteMapBackground"); -const backgroundCtx = backgroundCanvas.getContext("2d"); -// map view position, top left corner (or another corner?) -window.playerPosition = { - x:0, - y:0, -} -window.cachePosition = { - x:0, - y:0, -}; -function requestMapDraw(){ - let xLow = Math.floor(cachePosition.x % remoteMapConfig.tileSize); - let yLow = Math.floor(cachePosition.y % remoteMapConfig.tileSize); - - let xHigh = xLow+remoteMapConfig.mapSize; - let yHigh = yLow+remoteMapConfig.mapSize; - for(let x = xLow; x < xHigh; x++){ - for(let y = yLow; y < yHigh; y++){ - socket.emit("requestEntity", {x, y, instanceID: getParameterByName("instanceID")}); - } - } -} - -document.addEventListener('keydown', keyDownHandler, false); -document.addEventListener('keyup', keyUpHandler, false); -var rightPressed = false; -var leftPressed = false; -var upPressed = false; -var downPressed = false; -function keyDownHandler(event) { - if(event.keyCode == 39 || event.keyCode == 68) { - rightPressed = true; - } - else if(event.keyCode == 37 || event.keyCode == 65) { - leftPressed = true; - } - if(event.keyCode == 40 || event.keyCode == 83) { - downPressed = true; - } - else if(event.keyCode == 38 || event.keyCode == 87) { - upPressed = true; - } -} -function keyUpHandler(event) { - if(event.keyCode == 39 || event.keyCode == 68) { - rightPressed = false; - } - else if(event.keyCode == 37 || event.keyCode == 65) { - leftPressed = false; - } - if(event.keyCode == 40 || event.keyCode == 83) { - downPressed = false; - } - else if(event.keyCode == 38 || event.keyCode == 87) { - upPressed = false; - } -} - -var entityCache = new Array(remoteMapConfig.mapSize); -// populate cache with arrays of arrays -for(let i = 0; i < remoteMapConfig.mapSize; i++){ - entityCache[i] = new Array(remoteMapConfig.mapSize); - for(let o = 0; o < remoteMapConfig.mapSize; o++){ - entityCache[i][o] = " "; - } -} -// cache navigation functions, for panning (walking, if you will) -const cache = { - walkDown: function walkUp(){ - cachePosition.y += remoteMapConfig.tileSize; - for(let i = 0; i < remoteMapConfig.mapSize; i++){ - entityCache[i].shift(); // remove leftmost entry - entityCache[i].push(" "); // add new entry on the right - // get data from slaveMapper - let x = cachePosition.x/remoteMapConfig.tileSize + i; - let y = cachePosition.y/remoteMapConfig.tileSize+remoteMapConfig.mapSize-1; - socket.emit("requestEntity", {x, y, instanceID: getParameterByName("instanceID")}); - } - }, - walkUp: function walkDown(){ - cachePosition.y -= remoteMapConfig.tileSize; - for(let i = 0; i < remoteMapConfig.mapSize; i++){ - entityCache[i].pop(); // remove rightmost entry - entityCache[i].unshift(" "); // add new entry on the left - // get data from slaveMapper - let x = cachePosition.x/remoteMapConfig.tileSize + i; - let y = cachePosition.y/remoteMapConfig.tileSize; - socket.emit("requestEntity", {x, y, instanceID: getParameterByName("instanceID")}); - } - }, - walkLeft: function walkLeft(){ - cachePosition.x += remoteMapConfig.tileSize; - entityCache.shift(); - entityCache.push(new Array(remoteMapConfig.mapSize)); - // get data from slaveMapper - // fill in a row on the right side of the screen, that is the bottom of the 1st level array - for(let i = 0; i < remoteMapConfig.mapSize; i++){ - let x = cachePosition.x/remoteMapConfig.tileSize + remoteMapConfig.mapSize - 1; - let y = cachePosition.y/remoteMapConfig.tileSize + i; - socket.emit("requestEntity", {x, y, instanceID: getParameterByName("instanceID")}); - } - }, - walkRight: function walkRight(){ - cachePosition.x -= remoteMapConfig.tileSize; - entityCache.pop(); - entityCache.unshift(new Array(remoteMapConfig.mapSize)); - // get data from slaveMapper - // fill a row on the left side of the screen, that is the top column - for(let i = 0; i < remoteMapConfig.mapSize; i++){ - let x = cachePosition.x/remoteMapConfig.tileSize; - let y = cachePosition.y/remoteMapConfig.tileSize + i; - socket.emit("requestEntity", {x, y, instanceID: getParameterByName("instanceID")}); - } - } -} -function drawFromCache(){ - clear(); - let startTime = Date.now() - entityCache.forEach(row => { - row.forEach(doc => { - if(doc && typeof doc == "object"){ - drawEntity(doc, true); - } - }); - }); -} -window.requestAnimationFrame(renderLoop); -var fpsTimings = { - lastFrame: Date.now(), - averageLength: 60, - sum:0, - counter: document.querySelector("#fpsCounter"), -} -var isPaused = false; -window.onblur = function() { - if(localStorage.remoteMapPauseOnBlur == "true"){ - isPaused = true; - console.log("paused"); - } -} -window.onfocus = function() { - if(isPaused){ - isPaused = false; - console.log("unpaused"); - window.requestAnimationFrame(renderLoop); - } -} -function getMousePos(canvas, evt) { - var rect = canvas.getBoundingClientRect(); - return { - x: evt.clientX - rect.left, - y: evt.clientY - rect.top - }; -} -window.mousePos = {}; -selectionCanvas.addEventListener('mousemove', function(evt) { - var mousePos = getMousePos(selectionCanvas, evt); - var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y; - window.mousePos.x = mousePos.x; - window.mousePos.y = mousePos.y; -}, false); -selectionCanvas.addEventListener("mousedown", function(evt) { - if(evt.which === 1) window.mousePos.clicked = true; - if(evt.which === 3) window.mousePos.rightClicked = true; - - // place item in world by sending it with websockets and shit - let tileSize = remoteMapConfig.tileSize; - let entity = { - name: itemSelectorGUI.getItem().name, - position:{ - x: Math.floor((playerPosition.x + window.mousePos.x) / tileSize), - y: Math.floor((playerPosition.y + window.mousePos.y) / tileSize), - }, - direction: itemSelectorGUI.getItem().direction.toString(), - }; - if(evt.which === 1){ // left click to place - console.log(JSON.stringify(entity)); - socket.emit("placeEntity", entity); - } else if(evt.which === 3){ // right click to delete - entity.name = "deleted"; - socket.emit("placeEntity", entity) - } - // console.log(entity); -}); -selectionCanvas.addEventListener("mouseup", function(evt) { - if(evt.which === 1) window.mousePos.clicked = false; - if(evt.which === 3) window.mousePos.rightClicked = false; -}); -function renderLoop(){ - // render game canvas - let newTimestamp = Date.now(); - fpsTimings.sum = fpsTimings.sum / fpsTimings.averageLength * (fpsTimings.averageLength - 1); - let timeSinceLastFrame; - fpsTimings.sum += timeSinceLastFrame = newTimestamp - fpsTimings.lastFrame; - fpsTimings.counter.value = (1000 / (fpsTimings.sum / fpsTimings.averageLength)).toPrecision(4); - fpsTimings.lastFrame = newTimestamp; - if(!isPaused){ - let moveSpeed = Number(remoteMapConfig.movementSpeed); - let movement = moveSpeed * timeSinceLastFrame; - // handle movement and requesting new entities - if(upPressed){ - console.log("w"); - playerPosition.y -= movement; - if(Math.abs((playerPosition.y-cachePosition.y)/remoteMapConfig.tileSize) > 1){ - for(let i = 0; i < Math.floor(Math.abs((playerPosition.y-cachePosition.y)/remoteMapConfig.tileSize)); i++){ - cache.walkUp(); - } - } - } - if(leftPressed){ - console.log("a"); - playerPosition.x -= movement; - if(Math.abs((playerPosition.x-cachePosition.x)/remoteMapConfig.tileSize) > 1){ - for(let i = 0; i < Math.floor(Math.abs((playerPosition.x-cachePosition.x)/remoteMapConfig.tileSize)); i++){ - cache.walkRight(); - }} - } - if(downPressed){ - console.log("s"); - playerPosition.y += movement; - if(Math.abs((playerPosition.y-cachePosition.y)/remoteMapConfig.tileSize) > 1){ - for(let i = 0; i < Math.floor(Math.abs((playerPosition.y-cachePosition.y)/remoteMapConfig.tileSize)); i++){ - cache.walkDown(); - }} - } - if(rightPressed){ - console.log("d"); - let oldPos = playerPosition.x; - playerPosition.x += movement; - if(Math.abs((playerPosition.x-cachePosition.x)/remoteMapConfig.tileSize) > 1){ - for(let i = 0; i < Math.floor(Math.abs((playerPosition.x-cachePosition.x)/remoteMapConfig.tileSize)); i++){ - cache.walkLeft(); - }} - } - // draw map - drawFromCache(); - // queue next tick - window.requestAnimationFrame(renderLoop); - } - - // render selection canvas - let mousePosition = window.mousePos; - if(mousePosition && mousePosition.x){ - // make a box around the mouse cursor - selectionCtx.beginPath(); - selectionCtx.lineWidth = remoteMapConfig.tileSize / 16; - selectionCtx.strokeStyle="yellow"; - if(mousePosition.clicked) selectionCtx.strokeStyle = "red"; - if(mousePosition.rightClicked) selectionCtx.strokeStyle = "blue"; - let tileSize = remoteMapConfig.tileSize - let halfTile = tileSize / 2; - let tilePosition = { // position in world coordinates (same as used by factorio) - x: Math.floor((playerPosition.x + mousePosition.x) / tileSize), - y: Math.floor((playerPosition.y + mousePosition.y) / tileSize), - } - // Long thing to correct for offset between playerPosition, cachePosition (tile grid) and mouse position and draw the box so it aligns with tiles. - selectionCtx.rect(tilePosition.x * tileSize - playerPosition.x, tilePosition.y * tileSize - playerPosition.y, tileSize, tileSize); - selectionCtx.stroke(); - } - - // render background canvas - let dw = 1024 / 32 * remoteMapConfig.tileSize; - let dh = 64 / 32 * remoteMapConfig.tileSize; - - // 0-dw and x < ?? + dw is to make sure we draw well outside the canvas on both sides to avoid ugly gfx - for(let x = 0-dw; x < remoteMapConfig.tileSize * remoteMapConfig.mapSize + dw; x += dw){ - for(let y = 0-dh; y < remoteMapConfig.tileSize * remoteMapConfig.mapSize + dh; y += dh){ - let dx = x - playerPosition.x % dw; - let dy = y - playerPosition.y % dh; - if(global.grassBackground && isImageOk(global.grassBackground)) backgroundCtx.drawImage(global.grassBackground, 0, 64, 1024, 64, dx, dy, dw, dh); - } - } -} -var entityImages = {}; // cache to store images and details about entities, populated by drawEntity(); -window.logEntCache = function(){console.log(entityCache)} -function drawEntity(entity, dontCache){ - if(entity.x !== undefined && entity.y !== undefined){ - if(!dontCache){ - // cache entity for later draws (like panning) - if(entity.x - cachePosition.x/remoteMapConfig.tileSize >= 0 && entity.x - cachePosition.x/remoteMapConfig.tileSize < remoteMapConfig.mapSize && entity.y - cachePosition.y/remoteMapConfig.tileSize >= 0 && entity.y - cachePosition.y/remoteMapConfig.tileSize < remoteMapConfig.mapSize){ - if(entity.entity){ - entityCache[entity.x - cachePosition.x/remoteMapConfig.tileSize][entity.y - cachePosition.y/remoteMapConfig.tileSize] = entity; - } else { - // delete this entity because we just heard the tile is empty and stuff - entityCache[entity.x - cachePosition.x/remoteMapConfig.tileSize][entity.y - cachePosition.y/remoteMapConfig.tileSize] = " "; - } - } - } - if(entity.entity && entity.entity.name && typeof entity.entity.name == "string"){ - let name = entity.entity.name; - if(!entityImages[name]){ - console.log("Downloading image "+name); - // download the entityImages and add stuff to queue - entityImages[name] = { - img: new Image(), - queue: [], - loaded: false, - }; - entityImages[name].draw = function(entity){ - if(this.loaded){ - let name = entity.entity.name; - let image, sprWidth, sprHeight, offLeft, offTop, size, offsetX, offsetY; - let flipX = false, flipY = false; - let rotation = 0; - // check hardcoded entity draw rules for specifics (otherwise draw icon as 1x1 entity with rotation if specified) - if(entityDrawRules[name] && (entityDrawRules[name].positionOffset || entityDrawRules[name].spritesheet)){ - let rules = entityDrawRules[name] - if(rules.positionOffset){ - offsetX = rules.positionOffset.x; - offsetY = rules.positionOffset.y; - } - if(rules.sizeInTiles){ - size = { - x: remoteMapConfig.tileSize * rules.sizeInTiles.x, - y: remoteMapConfig.tileSize * rules.sizeInTiles.y, - }; - } - if(rules.spritesheet && Array.isArray(rules.spritesheet)){ - let dir = Number(entity.entity.rot || 0); - // 2 animated sprites, we will need to flip it for rotations. - if(rules.spritesheet.length == 2){ - let spritesheetAnim = dir / 2 % 2; - let animationStage = Math.floor(Date.now()/16) % rules.spritesheet[spritesheetAnim].spritesheet.length; - - try{ - sprWidth = rules.spritesheet[spritesheetAnim].spritesheet[animationStage].frame.w; - sprHeight = rules.spritesheet[spritesheetAnim].spritesheet[animationStage].frame.h; - offLeft = rules.spritesheet[spritesheetAnim].spritesheet[animationStage].frame.x; - offTop = rules.spritesheet[spritesheetAnim].spritesheet[animationStage].frame.y; - } catch(e){ - // console.log(name) - // console.log(rules.spritesheet[spritesheetAnim].spritesheet) - } - image = global.spritesheet; - - // handle rotation (not handled by generic handler because we have to do flips and special stuff) - if(dir == 4){ - // rotation = (dir/2)*90 - // console.log("rotating") - flipY = true; - } else if(dir == 6){ - flipX = true; - // rotation = ((dir+2)/2)*90+180 // this formula is terrible, don't try to repair, there is no sense to it - } - - if(rules.spritesheet[spritesheetAnim].positionOffset){ - offsetX = rules.spritesheet[spritesheetAnim].positionOffset.x; - offsetY = rules.spritesheet[spritesheetAnim].positionOffset.y; - } - if(rules.spritesheet[spritesheetAnim].sizeInTiles){ - size = { - x: remoteMapConfig.tileSize * rules.spritesheet[spritesheetAnim].sizeInTiles.x, - y: remoteMapConfig.tileSize * rules.spritesheet[spritesheetAnim].sizeInTiles.y, - }; - } - } else { - // correct for whether we have 1, 4 or 8 directions - let spriteSheetRotIndex = dir / (8 / rules.spritesheet.length); - if(rules.spritesheet.length > 8) { - // apparently this entity has more than 8 directions. That isn't supported. - // therefore we can conclude that they are instead intended as animation frames. - // That is why we treat them as animation frames. - spriteSheetRotIndex = Math.floor(Date.now()/32) % rules.spritesheet.length; - } else if(rules.spritesheet[spriteSheetRotIndex].spritesheet.length){ - var animationStage = Math.floor(Date.now()/16) % rules.spritesheet[spriteSheetRotIndex].spritesheet.length; - var usesAnimation = true; - } else { - var usesAnimation = false; - } - - if(usesAnimation){ - try{ - sprWidth = rules.spritesheet[spriteSheetRotIndex].spritesheet[animationStage].frame.w; - sprHeight = rules.spritesheet[spriteSheetRotIndex].spritesheet[animationStage].frame.h; - offLeft = rules.spritesheet[spriteSheetRotIndex].spritesheet[animationStage].frame.x; - offTop = rules.spritesheet[spriteSheetRotIndex].spritesheet[animationStage].frame.y; - }catch(e){} // TODO throws error due to yellow belt rendering - } else { - sprWidth = rules.spritesheet[spriteSheetRotIndex].spritesheet.frame.w; - sprHeight = rules.spritesheet[spriteSheetRotIndex].spritesheet.frame.h; - offLeft = rules.spritesheet[spriteSheetRotIndex].spritesheet.frame.x; - offTop = rules.spritesheet[spriteSheetRotIndex].spritesheet.frame.y; - } - image = global.spritesheet; - - if(rules.spritesheet[spriteSheetRotIndex].positionOffset){ - offsetX = rules.spritesheet[spriteSheetRotIndex].positionOffset.x; - offsetY = rules.spritesheet[spriteSheetRotIndex].positionOffset.y; - } - if(rules.spritesheet[spriteSheetRotIndex].sizeInTiles){ - size = { - x: remoteMapConfig.tileSize * rules.spritesheet[spriteSheetRotIndex].sizeInTiles.x, - y: remoteMapConfig.tileSize * rules.spritesheet[spriteSheetRotIndex].sizeInTiles.y, - }; - } - if(rules.spritesheet[spriteSheetRotIndex].flip){ - let flip = rules.spritesheet[spriteSheetRotIndex].flip; - if(flip == "x") flipX = true; - if(flip == "y") flipY = true; - } - } - } else if(rules.spritesheet){ - sprWidth = rules.spritesheet.frame.w; - sprHeight = rules.spritesheet.frame.h; - offLeft = rules.spritesheet.frame.x; - offTop = rules.spritesheet.frame.y; - image = global.spritesheet; - } - } else { - offsetX = 0, offsetY = 0; - size = { - x:remoteMapConfig.tileSize, y: remoteMapConfig.tileSize, - }; - } - let xPos = ((entity.x + offsetX) * remoteMapConfig.tileSize) - playerPosition.x; - let yPos = ((entity.y + offsetY) * remoteMapConfig.tileSize) - playerPosition.y; - if(entity.entity.rot && !isNaN(Number(entity.entity.rot)) && !(entityDrawRules[name] && Array.isArray(entityDrawRules[name].spritesheet))){ - let rules = entityDrawRules[name]; - if(rules && rules.rotOffset){ - rotation = ((entity.entity.rot * 45) + entityDrawRules[name].rotOffset); - } else { - rotation = entity.entity.rot * 45; - } - } - if(!image) image = entityImages[name].img; - // if(name == "oil-refinery") console.log(offsetX) - drawImageWithRotation(ctx, image, xPos, yPos, size.x, size.y, rotation%360, sprWidth, sprHeight, offLeft, offTop, flipX, flipY); - //console.log("Drawing "+name+" at X: "+xPos+", Y: "+yPos+" with with rotation "+rotation); - } else { - // we are waiting for the image to load, push the task to our queue. It will be processed once the image loads. - this.queue.push(entity); - } - } - let imageLoaded = function(){ - // process queue and display - console.log("Image loaded!"); - entityImages[name].loaded = true; - entityImages[name].queue.forEach(entity => { - entityImages[name].draw(entity); - }); - entityImages[name].queue = []; - } - entityImages[name].queue.push(entity); - entityImages[name].img.onload = imageLoaded() - - if(entityDrawRules[name] && entityDrawRules[name].spritesheet){ - // imageLoaded(); - } else entityImages[name].img.src = getImageFromName(name); - } else { - // console.log("Already got image, drawing") - entityImages[name].draw(entity); - } - } else { - // we got an empty coordinate pair, that usually means this tile was occupied before but is empty now - console.log("Clearing at X: "+entity.x+", Y: "+entity.y); - ctx.clearRect((entity.x + playerPosition.x/remoteMapConfig.tileSize) * remoteMapConfig.tileSize, (entity.y + playerPosition.y/remoteMapConfig.tileSize) * remoteMapConfig.tileSize, remoteMapConfig.tileSize, remoteMapConfig.tileSize); - } - } else { - console.log(entity); - throw new Error("drawEntity on entity without x and y coordinates"); - } -} -function clear(){ - ctx.clearRect(0, 0, canvas.width, canvas.height); - selectionCtx.clearRect(0, 0, selectionCanvas.width, selectionCanvas.height); - backgroundCtx.clearRect(0, 0, backgroundCanvas.width, backgroundCanvas.height); -} -// setInterval(()=>console.log(entityDrawRules),5000); diff --git a/static/remoteMap/itemSelection.js b/static/remoteMap/itemSelection.js deleted file mode 100644 index f01a9adb..00000000 --- a/static/remoteMap/itemSelection.js +++ /dev/null @@ -1,85 +0,0 @@ -export class itemSelector { - constructor(containerSelector, entities){ - this.containerSelector = containerSelector; - this.container = document.querySelector(containerSelector); - if(!this.container) throw new Error("Could not find container "+container); - this.entities = entities; - this.direction = 0; - - // populate container - let cont = this.container; - let HTML = ""; - HTML += "
    "; - HTML += "

    Item selection

    "; - HTML += "
    "; - HTML += "
    "; - HTML += "Name: "; - HTML += ""; - HTML += "
    "; - // direction selector - HTML += "
    "; - HTML += "

    Direction:

    "; - HTML += "

    "+this.directionToCardinal(0)+"

    " - HTML += "

    Press R to rotate

    "; - HTML += "
    "; - - // write styles - let styles = { - ".header > h2":{ - color:"white", - }, - ".blackText":{ - color:"black", - }, - ".blackText > option":{ - color:"black", - } - } - - // turn style object into style tag - HTML += ""; - - // handle direction keyboard event - Mousetrap.bind('r', ()=>this.rotate()); - } - directionToCardinal(dir){ - if(dir == 0){ - return "north"; - } else if(dir == 1){ - return "north-east"; - } else if(dir == 2){ - return "east"; - } else if(dir == 3){ - return "south-east"; - } else if(dir == 4){ - return "south"; - } else if(dir == 5){ - return "south-west"; - } else if(dir == 6){ - return "west"; - } else if(dir == 7){ - return "north-west"; - } - } - rotate(){ - this.direction = (this.direction + 2) % 8; - // update display - document.querySelector("#directionDisplay").innerHTML = this.directionToCardinal(this.direction); - } - getItem(){ - let name = document.querySelector(this.containerSelector+" > .itemSelector > select").value; - let direction = this.direction; - return {name, direction}; - } -} \ No newline at end of file diff --git a/static/slaveDisplay.js b/static/slaveDisplay.js index f3015540..dbcc7e3e 100644 --- a/static/slaveDisplay.js +++ b/static/slaveDisplay.js @@ -17,20 +17,6 @@ setTimeout(function() { HTML += "

    " + slaveData[key].instanceName + "

    ID: " + slaveData[key].unique + "

    Last seen: "+seenDate+"

    Online players: "+slaveData[key].playerCount+"

    IP: "+slaveData[key].publicIP +":"+ slaveData[key].serverPort+"

    " HTML += "

    Host: "+slaveData[key].mac+"

    "; - // detect if remoteMap mod is installed, if it is we want to show the link for it - let hasRemoteMap = false; - if(slaveData[key].mods){ // not all instances have mods apparently - slaveData[key].mods.forEach(mod => { - console.log(mod.modName); - if(mod.modName.includes("remoteMap")){ - hasRemoteMap = true; // we are still doing the logic on the outside, in case there are multiple instances of remoteMap installed.... - } - }); - } - if(hasRemoteMap){ - HTML += "Remote map" - } - HTML += "

    Graph tools:

    "; HTML += ""; HTML += "";