mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-12 07:04:52 +09:00
131 lines
5.3 KiB
JavaScript
131 lines
5.3 KiB
JavaScript
const needle = require("needle");
|
|
const ioClient = require("socket.io-client");
|
|
|
|
const chunkStore = require("./chunkStore.js");
|
|
|
|
const moduleConfig = require("./config"); // not to be confused with clusterio config. This config is private to this plugin.
|
|
|
|
class remoteMap {
|
|
constructor(slaveConfig, messageInterface){
|
|
this.config = slaveConfig;
|
|
this.messageInterface = messageInterface;
|
|
|
|
// initialize chunk database
|
|
this.chunkMap = new chunkStore(this.config.unique, 64, "./database/chunkStore/");
|
|
this.chunkMap.onEntityChange(entity => {
|
|
// this.messageInterface("Entity changed: ")
|
|
// this.messageInterface(entity);
|
|
// check valid coordinates (dunno what could go wrong, but can never be too sure)
|
|
if(entity && entity.x !== undefined && !isNaN(Number(entity.x)) && entity.y !== undefined && !isNaN(Number(entity.y))){
|
|
this.socket.emit("sendEntity", entity);
|
|
}
|
|
});
|
|
|
|
// set up websocket communication and handle requests from web interface users (which are going through master)
|
|
// socket should be a global
|
|
this.socket = ioClient("http://"+this.config.masterIP+":"+this.config.masterPort);
|
|
this.socket.on("hello", data => {
|
|
this.socket.emit("registerSlaveMapper", {instanceID: this.config.unique});
|
|
setInterval(()=>{
|
|
this.socket.emit("heartbeat"); // send our heartbeat to prevent being assumed dead
|
|
},10000);
|
|
});
|
|
this.socket.on("getChunk", req => {
|
|
this.messageInterface("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 => {
|
|
// check for valid coordinates
|
|
if(req.x !== undefined && !isNaN(Number(req.x)) && req.y !== undefined && !isNaN(Number(req.y))){
|
|
this.chunkMap.getEntity(req.x, req.y).then(entities => {
|
|
if(entities && entities.length > 0){
|
|
entities.forEach(entity => {
|
|
this.socket.emit("sendEntity", entity);
|
|
});
|
|
}
|
|
});
|
|
} else {
|
|
this.messageInterface("socket.getEntity triggered called with invalid parameters");
|
|
}
|
|
});
|
|
// both placing and deleting entities via the web interface
|
|
this.socket.on("placeEntity", req => {
|
|
// game.player.surface.create_entity{name="small-ship-wreck", position={game.player.position.x-2, game.player.position.y+1}, direction=..., force=...}
|
|
this.messageInterface("placing "+JSON.stringify(req));
|
|
if(req.name && typeof req.name == "string" && req.position && !isNaN(Number(req.position.x)) && !isNaN(Number(req.position.y))){
|
|
if(req.name == "deleted"){ // {{'+req.position.x+','+req.position.y+'},{'+req.position.x+','+req.position.y+'}}
|
|
// delete entity from game world using LUA command
|
|
this.messageInterface('/silent-command local toDelete = game.surfaces[1].find_entities({{'+req.position.x+','+req.position.y+'},{'+(req.position.x+1)+','+(req.position.y+1)+'}}) for i, entity in pairs(toDelete) do entity.die() end');
|
|
// this position is now empty, delete whatever was there from DB
|
|
this.deleteEntity(req.position.x, req.position.y);
|
|
} else {
|
|
let command = '/silent-command game.surfaces[1].create_entity{name="'+req.name+'", position={'+Number(req.position.x)+', '+Number(req.position.y)+'}, force="neutral"'
|
|
if(req.direction) command += ', direction='+req.direction;
|
|
command += '}';
|
|
this.messageInterface(command); // execute command
|
|
|
|
// add entity to the chunkStore database because create_entity does not trigger any events
|
|
let name = req.name;
|
|
let entity = {name};
|
|
if(typeof req.direction == "string"){
|
|
entity.rot = req.direction;
|
|
}
|
|
this.addEntity(req.position.x, req.position.y, entity);
|
|
}
|
|
}
|
|
});
|
|
|
|
this.messageInterface("/silent-command game.print('"+moduleConfig.name+" version "+moduleConfig.version+" enabled')");
|
|
}
|
|
addEntity(x,y,entity){ // add entity to database
|
|
this.chunkMap.setEntity(Number(x), Number(y), entity).then(data => {
|
|
this.messageInterface("Added "+entity.name+" to data "+Number(x)+", "+Number(y));
|
|
}).catch((err)=>this.messageInterface(err));
|
|
}
|
|
deleteEntity(x,y){ // remove entity from database
|
|
// this position is now empty, delete whatever was there from DB
|
|
this.chunkMap.setEntity(x, y, "delete this entity").then(() => {
|
|
this.messageInterface("Deleted entity at "+x+", "+y);
|
|
}).catch((err)=>this.messageInterface(err));
|
|
}
|
|
scriptOutput(data){
|
|
if(data){
|
|
this.messageInterface(data);
|
|
// express-transport-belt,-35.5,-14.5,[...]
|
|
data = data.split(",");
|
|
if(data && data[0] == undefined){
|
|
this.messageInterface("empty: ");
|
|
this.messageInterface(data);
|
|
return
|
|
}
|
|
let name = data[0];
|
|
let xPos = data[1];
|
|
let yPos = data[2];
|
|
if(xPos && yPos && name){
|
|
if(name == "deleted"){
|
|
// this position is now empty, delete whatever was there from DB
|
|
this.deleteEntity(xPos, yPos);
|
|
} else {
|
|
let entity = {name};
|
|
for(let i = 3; i < data.length; i++){
|
|
if(data[i].includes("=")){
|
|
let kv = data[i].split("=");
|
|
entity[kv[0]] = kv[1];
|
|
}
|
|
}
|
|
// save this entity in the database
|
|
this.addEntity(xPos, yPos, entity);
|
|
/* this.chunkMap.setEntity(xPos, yPos, entity).then(data => {
|
|
this.messageInterface("Added "+name+" to data "+xPos+", "+yPos);
|
|
}).catch((err)=>this.messageInterface(err)); */
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
module.exports = remoteMap;
|