mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-12 23:04:52 +09:00
Refactored chunkStore to use linvodb3, broke mapping (ofc)
This commit is contained in:
1 parent
cd2d00d224
commit
1b405b8701
3 files changed
+62
-104
No files matched your search
+33
-82
@@ -3,6 +3,10 @@ var mkdirpSync = require("mkdirp").sync;
|
||||
var fs = require("fs");
|
||||
var objectOps = require("./objectOps");
|
||||
|
||||
var LinvoDB = require("linvodb3");
|
||||
LinvoDB.dbPath = "./database/linvodb/";
|
||||
|
||||
|
||||
let allowLogging = true;
|
||||
let log = string => (allowLogging)? console.log(string):""
|
||||
|
||||
@@ -13,98 +17,51 @@ module.exports = class chunkStore {
|
||||
this.path = (path[path.length] == "/") ? path : path+"/";
|
||||
mkdirpSync(path+name);
|
||||
|
||||
this.entityWriteQueue = [];
|
||||
this.chunkWritesInProgress = {};
|
||||
this.entityWriteInProgress = false;
|
||||
}
|
||||
checkChunkWrite(x, y){
|
||||
if(!this.chunkWritesInProgress[x]) this.chunkWritesInProgress[x] = {};
|
||||
if(!this.chunkWritesInProgress[x][y]){
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
setChunkWrite(x,y, bool){
|
||||
if(!this.chunkWritesInProgress[x]) this.chunkWritesInProgress[x] = {};
|
||||
if(!this.chunkWritesInProgress[x][y]) this.chunkWritesInProgress[x][y] = bool;
|
||||
this.db = new LinvoDB(name, {}, {});
|
||||
}
|
||||
setEntity(x/**{number}*/, y/**{number}*/, newEntity/**{object}*/){
|
||||
return new Promise((resolve, reject) => {
|
||||
var localX = x > 0 ? Math.round(x % this.chunkSize) : Math.round(x % this.chunkSize)+64;
|
||||
x = Math.floor(Math.round(x)/this.chunkSize);
|
||||
var localY = y > 0 ? Math.round(y % this.chunkSize) : Math.round(y % this.chunkSize)+64;
|
||||
y = Math.floor(Math.round(y)/this.chunkSize);
|
||||
console.log("localX"+localX)
|
||||
console.log("localY"+localY)
|
||||
console.log(x+ " "+y)
|
||||
this.entityWriteQueue.push({x, y, localX, localY, newEntity});
|
||||
if(this.checkChunkWrite(x,y)){
|
||||
// we don't need to initiate another request for a chunk because there is one running already which should take care of it
|
||||
} else {
|
||||
this.setChunkWrite(x, y, true);
|
||||
this.getChunk(x,y).then(chunk => {
|
||||
log("Setting "+this.entityWriteQueue.length+" entities in chunk X: "+x+" Y: "+y);
|
||||
|
||||
// add each queued entity to the chunk
|
||||
this.entityWriteQueue.forEach(queuedEntity => {
|
||||
if(queuedEntity.x == x && queuedEntity.y == y){
|
||||
let localX = queuedEntity.localX;
|
||||
let localY = queuedEntity.localY;
|
||||
let newEntity = queuedEntity.newEntity;
|
||||
|
||||
if(!chunk.dataObject[localX]) chunk.dataObject[localX] = {};
|
||||
if(!chunk.dataObject[localX][localY]) chunk.dataObject[localX][localY] = {};
|
||||
|
||||
if(newEntity && typeof newEntity == "object"){
|
||||
log("Overwriting with new entity at "+localX+", "+localY);
|
||||
chunk.dataObject[localX][localY] = newEntity;
|
||||
} else {
|
||||
log("Deleting entry at "+localX+", "+localY);
|
||||
chunk.dataObject[localX][localY] = undefined;
|
||||
}
|
||||
}
|
||||
x = Math.floor(x);
|
||||
y = Math.floor(y);
|
||||
this.db.find({x, y}, (err, docs) => {
|
||||
if(typeof newEntity == "object"){
|
||||
if(err) reject(err);
|
||||
let entityDoc = {x, y, entity: newEntity};
|
||||
if(docs && docs[0] && docs[0]._id){
|
||||
entityDoc._id = docs[0]._id;
|
||||
}
|
||||
this.db.save(entityDoc, (err,docs) => {
|
||||
if(err) reject(err);
|
||||
resolve(docs);
|
||||
});
|
||||
// clear the now processed queue
|
||||
this.entityWriteQueue = this.entityWriteQueue.filter(entity => {
|
||||
if(entity.x != x && entity.y != y) return true
|
||||
} else {
|
||||
docs.forEach(doc => {
|
||||
doc.remove(()=>{
|
||||
// removed :)
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
// save the chunk and resolve the promise
|
||||
this.setChunk(x, y, chunk).then(()=>{
|
||||
log("Successfully saved chunk!");
|
||||
//this.entityWriteInProgress = false;
|
||||
this.setChunkWrite(x,y,false);
|
||||
resolve(chunk);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
setChunk(x, y, chunk){
|
||||
getEntity(x, y){
|
||||
return new Promise((resolve, reject) => {
|
||||
mkdirp(this.path+this.name+"/"+x).then(() => {
|
||||
fs.writeFile(this.path+this.name+"/"+x+"/"+y, JSON.stringify(chunk, null, 4), function(err){
|
||||
if(err) {
|
||||
reject(err);
|
||||
} else resolve();
|
||||
});
|
||||
this.db.find({x:Math.floor(x), y:Math.floor(y)}, (err, docs) => {
|
||||
if(err) reject(err);
|
||||
resolve(docs);
|
||||
});
|
||||
});
|
||||
}
|
||||
getChunk(x, y){
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
/*
|
||||
// make new chunk in case we can't find an existing one
|
||||
let chunk = {
|
||||
dataObject: {},
|
||||
position:{x,y}, // fancy ES6 feature that generates to {x:x, y:y}
|
||||
chunkSize:this.chunkSize,
|
||||
/*get: function(x, y){
|
||||
if(this.dataObject[Math.round(x)] && this.dataObject[Math.round(x)][Math.round(y)]){
|
||||
return this.dataObject[Math.round(x)][Math.round(y)];
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
},*/
|
||||
chunkSize:this.chunkSize
|
||||
};
|
||||
fs.readFile(this.path+this.name+"/"+x+"/"+y, (err, chunkFile) => {
|
||||
|
||||
@@ -115,13 +72,6 @@ module.exports = class chunkStore {
|
||||
if(objectOps.isJSON(chunkFile)) {
|
||||
log("returned from file")
|
||||
let chunk = JSON.parse(chunkFile);
|
||||
/*chunk.get = function(x, y){
|
||||
if(this.dataObject[Math.round(x)] && this.dataObject[Math.round(x)][Math.round(y)]){
|
||||
return this.dataObject[Math.round(x)][Math.round(y)];
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}*/
|
||||
resolve(chunk);
|
||||
} else {
|
||||
log("file failed")
|
||||
@@ -129,6 +79,7 @@ module.exports = class chunkStore {
|
||||
}
|
||||
}
|
||||
}); // add x and y values as well and we are done?
|
||||
*/
|
||||
});
|
||||
}
|
||||
}
|
||||
+23
-18
@@ -15,28 +15,33 @@ describe("chunkStore.js", () => {
|
||||
store = new chunkStore("910239"/* instanceID, use defaults for the rest */);
|
||||
assert.equal(store.name, "910239");
|
||||
});
|
||||
it("allows you to store the locations of entities in a chunk divided database", () => {
|
||||
return store.setEntity(inserterX, inserterY, {name:inserterName}).then(() => {
|
||||
it("allows you to store the locations of entities", done => {
|
||||
store.setEntity(inserterX, inserterY, {name:inserterName, otherData:"can be arbitrary"}).then(() => {
|
||||
done();
|
||||
// nothing to do here really
|
||||
});
|
||||
});
|
||||
it("returns items located in a chunk", (done) => {
|
||||
// We return the promise to mocha as it supports promises natively, works a lot better than calling done() manually.
|
||||
let x = 0;
|
||||
let y = -1
|
||||
store.getChunk(x,y).then(chunkData => {
|
||||
console.log(chunkData);
|
||||
assert.equal(typeof chunkData, "object");
|
||||
assert.equal(chunkData.dataObject[15][47].name, inserterName);
|
||||
assert.equal(chunkData.position.x, x);
|
||||
assert.equal(chunkData.position.y, y);
|
||||
done();
|
||||
});
|
||||
it("returns entities at positions you query for", done => {
|
||||
setTimeout(()=>{
|
||||
store.getEntity(inserterX, inserterY).then(entities => {
|
||||
entity = entities[0]
|
||||
// console.log(entity)
|
||||
assert.equal(entity.x, 14);
|
||||
assert.equal(entity.y, -18);
|
||||
assert.equal(entity.entity.name, "inserter");
|
||||
assert.equal(entity.entity.otherData, "can be arbitrary");
|
||||
done();
|
||||
});
|
||||
},500)
|
||||
});
|
||||
it("deletes entities when not provided with an object as 3rd arg", done => {
|
||||
store.setEntity(inserterX, inserterY).then((chunk)=>{
|
||||
assert(!chunk.dataObject(15, 47));
|
||||
done();
|
||||
store.setEntity(inserterX, inserterY).then(entity => {
|
||||
assert(entity === undefined);
|
||||
store.getEntity(inserterX, inserterY).then(entities => {
|
||||
// console.log(entities)
|
||||
assert.equal(entities.length, 0, "Why are we getting results, it should be empty?");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -36,7 +36,6 @@ class remoteMap {
|
||||
|
||||
data = data.split(" ");
|
||||
if(data && data[0] == undefined){
|
||||
// this position is now empty, delete whatever was there from DB
|
||||
console.log("empty: ");
|
||||
console.log(data);
|
||||
return
|
||||
@@ -46,12 +45,15 @@ class remoteMap {
|
||||
let yPos = data[2];
|
||||
if(xPos && yPos && name){
|
||||
if(name == "deleted"){
|
||||
this.chunkMap.setEntity(xPos, yPos, "delete this entity").then(data => {
|
||||
this.messageInterface("Deleted data "+data.position.x+", "+data.position.y);
|
||||
// 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));
|
||||
} else {
|
||||
// save this entity in the database
|
||||
this.chunkMap.setEntity(xPos, yPos, {name}).then(data => {
|
||||
this.messageInterface("Added "+name+" to data "+data.position.x+", "+data.position.y);
|
||||
data = data[0];
|
||||
this.messageInterface("Added "+name+" to data "+data.x+", "+data.y);
|
||||
}).catch((err)=>this.messageInterface(err));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user