diff --git a/master.js b/master.js index 91cf10ce..9b713d98 100644 --- a/master.js +++ b/master.js @@ -618,7 +618,11 @@ class slaveMapper { this.socket = socket; this.socket.on("sendChunk", function(data){ - mapRequesters[data.requesterID].socket.emit("displayChunk", data) + mapRequesters[data.requesterID].socket.emit("displayChunk", data); + }); + // slaveMapper sent us an entity update, process + this.socket.on("sendEntity", function(entity){ + mapRequesters[entity.requesterID].socket.emit("displayEntity", entity); }); } } @@ -636,6 +640,13 @@ class mapRequester { slaveMappers[instanceID].socket.emit("getChunk", loc) } }); + this.socket.on("requestEntity", req => { + 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) + } + }); } } io.on('connection', function (socket) { diff --git a/lib/chunkStore.js b/sharedPlugins/remoteMap/chunkStore.js similarity index 78% rename from lib/chunkStore.js rename to sharedPlugins/remoteMap/chunkStore.js index 177e5d35..69cd9c63 100644 --- a/lib/chunkStore.js +++ b/sharedPlugins/remoteMap/chunkStore.js @@ -1,7 +1,9 @@ var mkdirp = require("mkdirp-promise"); var mkdirpSync = require("mkdirp").sync; var fs = require("fs"); -var objectOps = require("./objectOps"); +var events = require("events"); + +var objectOps = require("./../../lib/objectOps"); var LinvoDB = require("linvodb3"); LinvoDB.dbPath = "./database/linvodb/"; @@ -12,12 +14,16 @@ let log = string => (allowLogging)? console.log(string):"" module.exports = class chunkStore { constructor(name, chunkSize = 32, path = "./chunkStore/"){ + name = name.toString(); + if(!name || typeof name != "string") throw new Error("chunkstore requires a name string as first param") this.name = name; this.chunkSize = chunkSize; this.path = (path[path.length] == "/") ? path : path+"/"; mkdirpSync(path+name); this.db = new LinvoDB(name, {}, {}); + + this.eventEmitter = new events.EventEmitter(); } setEntity(x/**{number}*/, y/**{number}*/, newEntity/**{object}*/){ return new Promise((resolve, reject) => { @@ -33,14 +39,16 @@ module.exports = class chunkStore { this.db.save(entityDoc, (err,docs) => { if(err) reject(err); resolve(docs); + this.eventEmitter.emit("change", docs) }); } else { docs.forEach(doc => { doc.remove(()=>{ // removed :) - resolve(); }); }); + resolve(); + this.eventEmitter.emit("change", [{x,y}]); } }); }); @@ -50,9 +58,15 @@ module.exports = class chunkStore { this.db.find({x:Math.floor(x), y:Math.floor(y)}, (err, docs) => { if(err) reject(err); resolve(docs); + this.eventEmitter.emit("change", docs); }); }); } + onEntityChange(eventhandler/**function*/){ + if(typeof eventhandler == "function") { + this.eventEmitter.on("change", eventhandler); + } + } getChunk(x, y){ return new Promise((resolve, reject) => { diff --git a/lib/chunkStore.spec.js b/sharedPlugins/remoteMap/chunkStore.spec.js similarity index 97% rename from lib/chunkStore.spec.js rename to sharedPlugins/remoteMap/chunkStore.spec.js index c53fdc95..8317e421 100644 --- a/lib/chunkStore.spec.js +++ b/sharedPlugins/remoteMap/chunkStore.spec.js @@ -2,7 +2,7 @@ var assert = require("assert"); var chunkStore = require("./chunkStore.js"); -describe("chunkStore.js", () => { +describe("remoteMap/chunkStore.js", () => { // define some values for our test const inserterX = 14.5; // rounds to 15 const inserterY = -17.5; // rounds to -17, +64 would be 47 diff --git a/sharedPlugins/remoteMap/index.js b/sharedPlugins/remoteMap/index.js index 36d7e411..6244275c 100644 --- a/sharedPlugins/remoteMap/index.js +++ b/sharedPlugins/remoteMap/index.js @@ -1,7 +1,7 @@ const needle = require("needle"); const ioClient = require("socket.io-client"); -const chunkStore = require("./../../lib/chunkStore.js"); +const chunkStore = require("./chunkStore.js"); const moduleConfig = require("./config"); // not to be confused with clusterio config. This config is private to this plugin. @@ -10,7 +10,6 @@ class remoteMap { this.config = slaveConfig; this.messageInterface = messageInterface; - // initialize chunk database this.chunkMap = new chunkStore(this.config.unique, 64, "./database/chunkStore/"); @@ -21,17 +20,32 @@ class remoteMap { this.socket.emit("registerSlaveMapper", {instanceID: this.config.unique}); }); this.socket.on("getChunk", req => { - this.chunkMap.getChunk(req.x, req.y).then(chunk => { + console.log("getChunk is not supported!"); + /*this.chunkMap.getChunk(req.x, req.y).then(chunk => { chunk.requesterID = req.requesterID; this.socket.emit("sendChunk", chunk); - }); + });*/ + }); + this.socket.on("getEntity", req => { + if(req.requesterID && req.x && !isNaN(Number(req.x)) && req.y && !isNaN(Number(req.y))){ + this.chunkMap.getEntity(req.x, req.y).then(entities => { + if(entities && entities.length > 0){ + entities.forEach(entity => { + entity.requesterID = req.requesterID; + this.socket.emit("sendEntity", entity); + }); + } + }); + } else { + this.messageInterface("socket.getEntity triggered called with invalid parameters"); + } }); this.messageInterface("/silent-command game.print('"+moduleConfig.name+" version "+moduleConfig.version+" enabled')"); } scriptOutput(data){ if(data){ - this.messageInterface(data); + //this.messageInterface(data); // express-transport-belt -35.5 -14.5 data = data.split(" "); @@ -52,8 +66,7 @@ class remoteMap { } else { // save this entity in the database this.chunkMap.setEntity(xPos, yPos, {name}).then(data => { - data = data[0]; - this.messageInterface("Added "+name+" to data "+data.x+", "+data.y); + this.messageInterface("Added "+name+" to data "+xPos+", "+yPos); }).catch((err)=>this.messageInterface(err)); } } diff --git a/sharedPlugins/remoteMap/index.spec.js b/sharedPlugins/remoteMap/index.spec.js new file mode 100644 index 00000000..644df5a0 --- /dev/null +++ b/sharedPlugins/remoteMap/index.spec.js @@ -0,0 +1,9 @@ +var assert = require("assert"); + +var remoteMap = require("./index.js"); + +describe("remoteMap/index.js", () => { + it("exports a single class (or at least a function)", ()=>{ + assert.equal(typeof remoteMap, "function"); + }); +}); diff --git a/static/remoteMap.js b/static/remoteMap.js index 7c27daeb..307eefe7 100644 --- a/static/remoteMap.js +++ b/static/remoteMap.js @@ -4,8 +4,12 @@ socket.on('hello', function (data) { socket.emit("registerMapRequester", {instanceID: '1611985668'}); socket.on("displayChunk", function(chunk){ - console.log(chunk) - drawChunk(chunk, ctx) + console.log(chunk); + drawChunk(chunk, ctx); + }); + socket.on("displayEntity", function(entity){ + console.log("Displaying entity "+JSON.stringify(entity)); + drawEntity(entity, ctx); }); }); @@ -32,6 +36,47 @@ setTimeout(function(){ entityImages = {}; entityImages["express-transport-belt"] = new Image(); entityImages["express-transport-belt"].src = 'https://wiki.factorio.com/images/Express_transport_belt.png'; + +// map view position, top left corner (or another corner?) +playerPosition = { + x:0, + y:0, +} +function requestMapDraw(){ + let xLow = Math.floor(playerPosition.x % 16); + let yLow = Math.floor(playerPosition.y % 16); + + let xHigh = xLow+64; + let yHigh = yLow+64; + for(let x = xLow; x < xHigh; x++){ + for(let y = yLow; y < yHigh; y++){ + socket.emit("requestEntity", {x, y, instanceID: '1611985668'}); + } + } +} +function drawEntity(entity, ctx){ + if(entity.x && entity.y){ + if(entity.entity && entity.entity.name && typeof entity.entity.name == "string"){ + let name = entity.entity.name; + let xPos = (entity.x * 16) - playerPosition.x; + let yPos = (entity.y * 16) - playerPosition.y; + if(!entityImages[name]){ + // download the entityImages + entityImages[name] = new Image(); + entityImages[name].onload = function(){ + ctx.drawImage(entityImages[name], xPos, yPos, 16, 16); + console.log("Drawing "+name+" at X: "+xPos+", Y: "+yPos); + } + entityImages[name].src = getImageFromName(name); + } + + } else { + throw new Error(entity); + } + } else { + throw new Error("drawEntity on entity without x and y coordinates") + } +} function drawChunk(chunk, ctx){ Object.keys(chunk.dataObject).forEach(xValue => { let xRow = chunk.dataObject[xValue]; @@ -50,4 +95,4 @@ function drawChunk(chunk, ctx){ } }); }); -} \ No newline at end of file +}