mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 23:04:52 +09:00
remoteMap placing and removing entities
This commit is contained in:
1 parent
4b286f7b08
commit
f5eef7c1bb
7 files changed
+166
-20
No files matched your search
@@ -659,14 +659,21 @@ class mapRequester {
|
||||
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)
|
||||
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)
|
||||
slaveMappers[instanceID].socket.emit("getEntity", req);
|
||||
}
|
||||
});
|
||||
this.socket.on("placeEntity", req => {
|
||||
req.requesterID = this.requesterID;
|
||||
let instanceID = req.instanceID || this.instanceID;
|
||||
if(slaveMappers[instanceID]){
|
||||
slaveMappers[instanceID].socket.emit("placeEntity", req);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -51,9 +51,45 @@ class remoteMap {
|
||||
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=...}
|
||||
console.log("placing "+JSON.stringify(req));
|
||||
if(req.name && typeof req.name == "string" && req.position && Number(req.position.x) && Number(req.position.y)){
|
||||
if(req.name == "deleted"){ // {{'+req.position.x+','+req.position.y+'},{'+req.position.x+','+req.position.y+'}}
|
||||
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(req.direction){
|
||||
entity.direction = 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 data "+x+", "+y);
|
||||
}).catch((err)=>this.messageInterface(err));
|
||||
}
|
||||
scriptOutput(data){
|
||||
if(data){
|
||||
this.messageInterface(data);
|
||||
@@ -70,9 +106,7 @@ class remoteMap {
|
||||
if(xPos && yPos && name){
|
||||
if(name == "deleted"){
|
||||
// this position is now empty, delete whatever was there from DB
|
||||
this.chunkMap.setEntity(xPos, yPos, "delete this entity").then(() => {
|
||||
this.messageInterface("Deleted data "+xPos+", "+yPos);
|
||||
}).catch((err)=>this.messageInterface(err));
|
||||
this.deleteEntity(xPos, yPos);
|
||||
} else {
|
||||
let entity = {name};
|
||||
for(let i = 3; i < data.length; i++){
|
||||
@@ -82,9 +116,10 @@ class remoteMap {
|
||||
}
|
||||
}
|
||||
// save this entity in the database
|
||||
this.chunkMap.setEntity(xPos, yPos, entity).then(data => {
|
||||
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));
|
||||
}).catch((err)=>this.messageInterface(err)); */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ export var entityDrawRules = {
|
||||
},
|
||||
positionOffset: {
|
||||
x:-0.8,
|
||||
y:-1.5,
|
||||
y:-1.7,
|
||||
},
|
||||
},
|
||||
"centrifuge": {
|
||||
@@ -67,7 +67,7 @@ for(let i = 1; i <= 3; i++){
|
||||
},
|
||||
positionOffset: {
|
||||
x:-1.4,
|
||||
y:-0.9,
|
||||
y:-1.2,
|
||||
},
|
||||
}
|
||||
// template3x3entity;
|
||||
@@ -125,7 +125,7 @@ for(let i = 1; i <= 3; i++){
|
||||
x:1.2,y:1.6,
|
||||
},
|
||||
positionOffset: {
|
||||
x:0,y:0,
|
||||
x:0,y:-0.2,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
<%- include("sidebar.html") %>
|
||||
<div id="body">
|
||||
<h2>remoteMap</h2>
|
||||
<div id="remoteMapContainer">
|
||||
<canvas class="remoteMap" id="remoteMap" width="32" height="32" style="border:1px solid #000000;position:absolute;"></canvas>
|
||||
<canvas class="remoteMap" id="remoteMapSelection" width="32" height="32" style="border:1px solid #000000;position:absolute;"></canvas>
|
||||
<div id="remoteMapContainer" style="float:left">
|
||||
<canvas class="remoteMap" id="remoteMap" width="512" height="512" style="border:1px solid #000000;position:absolute;"></canvas>
|
||||
<canvas class="remoteMap" id="remoteMapSelection" width="512" height="512" style="border:1px solid #000000;position:absolute;"></canvas>
|
||||
</div>
|
||||
<div id="remoteMapItemSelector">
|
||||
<div id="remoteMapItemSelector" style="float:left">
|
||||
<!-- Generated by script, don't edit -->
|
||||
</div>
|
||||
<div id="remoteMapSettings">
|
||||
<div id="remoteMapSettings" style="float:left">
|
||||
<p>Map size: <input type="number" id="mapSize" style="color:black;"> (default 32)</p>
|
||||
<p>Tile size: <input type="number" id="tileSize" style="color:black;"> (default 8)</p>
|
||||
<p>FPS: <input type="number" id="fpsCounter" style="color:black;"></p>
|
||||
|
||||
+56
-5
@@ -1,14 +1,34 @@
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
|
||||
console.log(":)")
|
||||
/// ES6 imports
|
||||
// rules for how entities are drawn (sizes, offset etc)
|
||||
import {entityDrawRules} from "./lib/entityDrawRules.js";
|
||||
import {getParameterByName, drawImageWithRotation} 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"}
|
||||
]);
|
||||
|
||||
if(!localStorage.remoteMapConfig || localStorage.remoteMapConfig == "[object Object]"){
|
||||
localStorage.remoteMapConfig = JSON.stringify({
|
||||
mapSize: 32,
|
||||
@@ -92,6 +112,7 @@ function requestChunk(x,y){
|
||||
(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;
|
||||
});
|
||||
@@ -259,12 +280,37 @@ function getMousePos(canvas, evt) {
|
||||
y: evt.clientY - rect.top
|
||||
};
|
||||
}
|
||||
window.mousePos;
|
||||
window.mousePos = {};
|
||||
selectionCanvas.addEventListener('mousemove', function(evt) {
|
||||
var mousePos = getMousePos(selectionCanvas, evt);
|
||||
var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
|
||||
window.mousePos = mousePos;
|
||||
window.mousePos.x = mousePos.x;
|
||||
window.mousePos.y = mousePos.y;
|
||||
}, false);
|
||||
selectionCanvas.addEventListener("mousedown", function(evt) {
|
||||
if(evt.which === 1) window.mousePos.clicked = 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),
|
||||
},
|
||||
};
|
||||
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;
|
||||
});
|
||||
function renderLoop(){
|
||||
// render game canvas
|
||||
let newTimestamp = Date.now();
|
||||
@@ -319,15 +365,20 @@ function renderLoop(){
|
||||
|
||||
// render selection canvas
|
||||
let mousePosition = window.mousePos;
|
||||
if(mousePosition){
|
||||
if(mousePosition && mousePosition.x){
|
||||
// make a box around the mouse cursor
|
||||
selectionCtx.beginPath();
|
||||
selectionCtx.lineWidth = remoteMapConfig.tileSize / 8;
|
||||
selectionCtx.strokeStyle="yellow";
|
||||
if(mousePosition.clicked) selectionCtx.strokeStyle = "red";
|
||||
let tileSize = remoteMapConfig.tileSize
|
||||
let halfTile = tileSize / 2;
|
||||
let tilePosition = {
|
||||
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(mousePosition.x - mousePosition.x % tileSize + playerPosition.x % tileSize, mousePosition.y - mousePosition.y % tileSize - playerPosition.y % tileSize, tileSize, tileSize);
|
||||
selectionCtx.rect(mousePosition.x - mousePosition.x % tileSize - playerPosition.x % tileSize, mousePosition.y - mousePosition.y % tileSize - playerPosition.y % tileSize, tileSize, tileSize);
|
||||
selectionCtx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
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;
|
||||
|
||||
// populate container
|
||||
let cont = this.container;
|
||||
let HTML = "";
|
||||
HTML += "<div class='header'>";
|
||||
HTML += "<h2>Item selection</h2>";
|
||||
HTML += "</div>";
|
||||
HTML += "<div class='itemSelector'>";
|
||||
HTML += "<span>Name: </span>";
|
||||
HTML += "<select class='blackText'>";
|
||||
this.entities.forEach(entity => HTML += "<option value='"+entity.name+"'>"+entity.name+"</option>");
|
||||
HTML += "</select>";
|
||||
HTML += "</div>";
|
||||
|
||||
// write styles
|
||||
let styles = {
|
||||
".header > h2":{
|
||||
color:"white",
|
||||
},
|
||||
".blackText":{
|
||||
color:"black",
|
||||
},
|
||||
".blackText > option":{
|
||||
color:"black",
|
||||
}
|
||||
}
|
||||
|
||||
// turn style object into style tag
|
||||
HTML += "<style>";
|
||||
for(let style in styles){
|
||||
HTML += containerSelector+" "+style+"{";
|
||||
for(let styleName in styles[style]){
|
||||
let styleValue = styles[style][styleName];
|
||||
HTML += styleName+":"+styleValue+";";
|
||||
}
|
||||
HTML += "}";
|
||||
}
|
||||
cont.innerHTML += HTML + "</style>";
|
||||
}
|
||||
getItem(){
|
||||
let name = document.querySelector(this.containerSelector+" > .itemSelector > select").value;
|
||||
return {name};
|
||||
}
|
||||
}
|
||||
@@ -271,4 +271,7 @@ input:checked + .slider:before {
|
||||
-webkit-transform: translateX(26px);
|
||||
-ms-transform: translateX(26px);
|
||||
transform: translateX(26px);
|
||||
}
|
||||
canvas {
|
||||
-webkit-transform:translateZ(0)
|
||||
}
|
||||
Reference in new issue
Block a user