mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 23:04:52 +09:00
Remove inventoryImports plugin
Remove defunct and coding horror inventoryImports. The functionality provided in it should be added as an optional extra to subspace_storage.
This commit is contained in:
1 parent
24397b75cc
commit
e5e82ba2fb
10 files changed
-637
No files matched your search
@@ -1,46 +0,0 @@
|
||||
/**
|
||||
* Helper functions related to objects
|
||||
* @module lib/objectOps
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Deep clones an object, is actually just JSON.parse(JSON.stringify()) but looks cleaner.
|
||||
* @param {object} obj to clone
|
||||
* @returns {object} The cloned object.
|
||||
*
|
||||
* @example
|
||||
* a = {"thingy":"with a value"};
|
||||
* b = a;
|
||||
* a == b; // true
|
||||
* c = objectOps.deepclone(a);
|
||||
* a == c; // false
|
||||
*/
|
||||
module.exports.deepclone = function(obj){
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a string is valid JSON using try/catch. If passed an object it will always return true.
|
||||
* @param {string} string to verify
|
||||
* @returns {boolean} true if valid JSON.
|
||||
*
|
||||
* @example
|
||||
* objectOps.isJSON("99 bottles of beer"); // false
|
||||
* objectOps.isJSON("99"); // true
|
||||
* objectOps.isJSON({"thingy":"that is an object"}); // true
|
||||
* objectOps.isJSON(JSON.stringify({"thingy":"that is an object"})); // true
|
||||
*/
|
||||
module.exports.isJSON = function(string){
|
||||
let stringIsJson = false;
|
||||
let x;
|
||||
try {
|
||||
x = JSON.parse(string);
|
||||
} catch (e){
|
||||
return false;
|
||||
}
|
||||
if (typeof x === "object" || typeof string === "object"){
|
||||
stringIsJson = true;
|
||||
}
|
||||
return stringIsJson;
|
||||
};
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
|
||||
This clusterio plugin is tasked to read your inventory and logistic request slots
|
||||
it will then attempt to fulfill those requests using items provided by the master
|
||||
server. There *should* be an in game GUI to toggle this.
|
||||
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
// Name of package. For display somewhere I guess.
|
||||
name: "inventoryImports",
|
||||
version: "1.0.0",
|
||||
arguments: ["index.js"],
|
||||
description: "Clusterio plugin to fill character logistic slots with master imports",
|
||||
// We'll send everything in this file to your stdin. Beware.
|
||||
scriptOutputFileSubscription: "inventoryImports.txt",
|
||||
fileReadDelay: 100,
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
const needle = require("needle");
|
||||
const isJson = require("./isJson");
|
||||
const pluginConfig = require("./config");
|
||||
|
||||
const functions = require("./interfacingFunctions");
|
||||
|
||||
// poll inventories
|
||||
|
||||
class inventoryImports {
|
||||
constructor(slaveConfig, messageInterface){
|
||||
this.config = slaveConfig;
|
||||
this.messageInterface = messageInterface;
|
||||
messageInterface("/silent-command game.print('InventoryImports enabled')");
|
||||
setInterval(function(){
|
||||
// messageInterface("Polling inventories\n")
|
||||
messageInterface(functions.pollInventories(pluginConfig.scriptOutputFileSubscription));
|
||||
}, 10000);
|
||||
}
|
||||
scriptOutput(data){
|
||||
if(data !== null && isJson(data)){
|
||||
let inventory = JSON.parse(data);
|
||||
// process inventory of players and ask master for more stuff
|
||||
functions.handleInventory(inventory, this.config, this.messageInterface);
|
||||
}
|
||||
}
|
||||
}
|
||||
module.exports = inventoryImports;
|
||||
@@ -1,149 +0,0 @@
|
||||
const objectOps = require("@clusterio/lib/objectOps");
|
||||
const needle = require("needle");
|
||||
const pluginConfig = require("./config")
|
||||
const isJson = require("./isJson")
|
||||
|
||||
function handleInventory(json, config, callback){
|
||||
/*
|
||||
json is one of these two samples
|
||||
{"players":{"1":{"inventory":{"stone":12,"iron-ore":120,"raw-wood":10,"iron-plate":8,"steel-plate":480},"requestSlots":{}}}}
|
||||
{"exports":{"1":[{"name":"iron-ore","count":0},{"name":"steel-plate","count":0}]}}
|
||||
|
||||
we want to seperate players, parse their json and compare to request slots
|
||||
then ask master for the difference
|
||||
we must then prepare it all and inject it into players inventories with lua before
|
||||
the next json report arrives to avoid duplicating orders
|
||||
*/
|
||||
if(json && typeof json != "string" && typeof json == "object"){
|
||||
let exports = {};
|
||||
|
||||
// this is an inventory report, check whats missing and request from master
|
||||
// {"players":{"1":{"inventory":{"stone":12,"iron-ore":120,"raw-wood":10,"iron-plate":8,"steel-plate":480},"requestSlots":{}}}}
|
||||
if(json.players){
|
||||
let playerNames = Object.keys(json.players);
|
||||
for(let i = 0; i < playerNames.length; i++) {
|
||||
// haha, this turned into bit of a mess didn't it?
|
||||
let playerInv = json.players[playerNames[i]];
|
||||
// create a copy of player.requestSlots
|
||||
let toRequest = objectOps.deepclone(playerInv.requestSlots);
|
||||
let inventory = playerInv.inventory;
|
||||
let itemsToConfirm = Object.keys(toRequest).length;
|
||||
// create a place to store the object we have confirmed for importing
|
||||
let confirmedItems = {};
|
||||
let collectStacks = function(stack){
|
||||
itemsToConfirm--;
|
||||
if(stack){
|
||||
// because of the way we collect data in a keyed JSON object, this first part of the IF cannot happen.
|
||||
/* istanbul ignore next */
|
||||
if(confirmedItems[stack.name] && confirmedItems[stack.name] > 0){
|
||||
confirmedItems[stack.name] += stack.count;
|
||||
} else {
|
||||
confirmedItems[stack.name] = stack.count;
|
||||
}
|
||||
}
|
||||
if(itemsToConfirm == 0 && Object.keys(confirmedItems).length > 0){
|
||||
// return LUA
|
||||
callback(insertItemsFromObject(confirmedItems, playerNames[i]));
|
||||
}
|
||||
}
|
||||
// subtract items already in inventory
|
||||
Object.keys(playerInv.requestSlots).forEach(function(key){
|
||||
// if this item in inventory is also in a request slot, subtract invCount from requestCount
|
||||
if(inventory[key]){
|
||||
toRequest[key] -= inventory[key];
|
||||
}
|
||||
// if the difference is more than 0, request item from master
|
||||
if(toRequest[key] > 0){
|
||||
let request = {
|
||||
name:key,
|
||||
count:toRequest[key],
|
||||
}
|
||||
//console.log("Requesting: "+JSON.stringify(request));
|
||||
// request the difference from master
|
||||
function callback(err, response, body) {
|
||||
if (!err && response && response.body && (typeof response.body == "object" || isJson(response.body))) {
|
||||
// confirmed orders, already removed from master inventory
|
||||
//response.body.name: response.body.count
|
||||
if(typeof response.body == "string") response.body = JSON.parse(response.body);
|
||||
let stack = {name:response.body.name,count:Number(response.body.count)}
|
||||
collectStacks(stack);
|
||||
} else {
|
||||
collectStacks(false);
|
||||
}
|
||||
}
|
||||
needle.post(
|
||||
config.masterURL + '/api/remove',
|
||||
request,
|
||||
{json:true,headers: {'x-access-token': config.masterAuthToken}},
|
||||
callback
|
||||
);
|
||||
} else {
|
||||
collectStacks(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// {"exports":{"1":[{"name":"iron-ore","count":0},{"name":"steel-plate","count":0}]}}
|
||||
// this is a report of stuff we didn't have space for, send back to master
|
||||
if(json.exports){
|
||||
// loop over players (normally only one, but whatever)
|
||||
Object.keys(json.exports).forEach(function(playerName){
|
||||
// loop over simpleItemStacks to export
|
||||
let stackArray = json.exports[playerName];
|
||||
for(let i = 0; i < stackArray.length; i++){
|
||||
if(stackArray[i].count > 0){
|
||||
// console.log("Returning overflow: " + JSON.stringify(stackArray[i]));
|
||||
needle.post(
|
||||
config.masterURL + '/api/place',
|
||||
stackArray[i],
|
||||
{headers: {'x-access-token': config.masterAuthToken}},
|
||||
function (err, resp, body) {
|
||||
// console.log(body);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} else return false; // inventory is falsey or a string
|
||||
}
|
||||
function insertItemsFromObject(confirmedItems, playerName){
|
||||
// expeced input
|
||||
// {["iron-plate"]:100, coal:20}
|
||||
// make lua table
|
||||
// we gotta construct a string because I can't find any nice library for this
|
||||
if(playerName && confirmedItems){
|
||||
if(typeof playerName != "string") {
|
||||
throw new Error("playerName is: '"+typeof playerName+"' instead of string!");
|
||||
}
|
||||
let itemTable = "{";
|
||||
Object.keys(confirmedItems).forEach(function(name){
|
||||
let count = confirmedItems[name];
|
||||
if(count > 0){
|
||||
itemTable += '["'+name+'"]='+Math.floor(count)+',';
|
||||
}
|
||||
});
|
||||
itemTable += "}";
|
||||
let outputFile = pluginConfig.scriptOutputFileSubscription;
|
||||
// a="'+players[i]+'"
|
||||
// b='+itemTable+'
|
||||
return '/silent-command local a="'+playerName+'"local b='+itemTable+'local c={}if game.players[a]and game.players[a].connected then local d='+"'"+'{"exports":{"'+"'"+'..a..'+"'"+'":['+"'"+'local e=false;for f,g in pairs(b)do local h=game.players[a].insert{name=f,count=g}if e then d=d..'+"'"+','+"'"+'else e=true end;d=d..'+"'"+'{"name":"'+"'"+'..f..'+"'"+'","count":'+"'"+'..g-h..'+"'"+'}'+"'"+'end;d=d..'+"'"+']}}'+"'"+'game.write_file("'+outputFile+'",d,true,0)end';
|
||||
}
|
||||
}
|
||||
function pollInventories(outputFile){
|
||||
// console.log("/silent-command "+'local a=game.players["Danielv123"].get_inventory(defines.inventory.player_main).get_contents()local b=game.players["Danielv123"].get_quickbar().get_contents()local c={}local d="{inventory:{"for e,f in pairs(a)do d=d.."['+"'"+'"..e.."'+"'"+']:"..f..","end;for e,f in pairs(b)do d=d.."['+"'"+'"..e.."'+"'"+']:"..f..","end;d=d.."},requestSlots:{"for e,f in pairs(c)do d=d.."['+"'"+'"..e.."'+"'"+']:"..f..","end;d=d.."}}"game.write_file("'+pluginConfig.scriptOutputFileSubscription+'",d)');
|
||||
// console.log("Running inventory LUA")
|
||||
//console.log("/silent-command "+'local a=game.players["Danielv123"].get_inventory(defines.inventory.player_main).get_contents()local b=game.players["Danielv123"].get_quickbar().get_contents()local c={}for d=1,game.players["Danielv123"].force.character_logistic_slot_count do c[d]=game.players["Danielv123"].character.get_request_slot(d)end;local e="{inventory:{"for f,g in pairs(a)do e=e.."['+"'"+'"..f.."'+"'"+']:"..g..","end;for f,g in pairs(b)do e=e.."['+"'"+'"..f.."'+"'"+']:"..g..","end;e=e.."},requestSlots:{"for f,g in pairs(c)do e=e.."['+"'"+'"..g["name"].."'+"'"+']:"..g["count"]..", "end;e=e.."}}"game.write_file("'+pluginConfig.scriptOutputFileSubscription+'",e)')
|
||||
// console.log("/silent-command "+'local a="{"for b,c in pairs(game.players)do local d=game.players[b].get_inventory(defines.inventory.player_main).get_contents()local e=game.players[b].get_quickbar().get_contents()local f={}for g=1,game.players[b].force.character_logistic_slot_count do f[g]=game.players[b].character.get_request_slot(g)end;a=a..b..":{inventory:{"for h,i in pairs(d)do a=a.."['+"'"+'"..h.."'+"'"+']:"..i..","end;for h,i in pairs(e)do a=a.."['+"'"+'"..h.."'+"'"+']:"..i..","end;a=a.."},requestSlots:{"for h,i in pairs(f)do a=a.."['+"'"+'"..i["name"].."'+"'"+']:"..i["count"]..", "end;a=a.."}},"end;a=a.."}"game.write_file("'+pluginConfig.scriptOutputFileSubscription+'",a)')
|
||||
//return "/silent-command "+'local a="{"for b,c in pairs(game.players)do if c.connected then local d=game.players[b].get_inventory(defines.inventory.player_main).get_contents()local e=game.players[b].get_quickbar().get_contents()local f={}for g=1,game.players[b].force.character_logistic_slot_count do f[g]=game.players[b].character.get_request_slot(g)end;a=a..b..":{inventory:{"for h,i in pairs(d)do a=a.."['+"'"+'"..h.."'+"'"+']:"..i..","end;for h,i in pairs(e)do a=a.."['+"'"+'"..h.."'+"'"+']:"..i..","end;a=a.."},requestSlots:{"for h,i in pairs(f)do a=a.."['+"'"+'"..i["name"].."'+"'"+']:"..i["count"]..", "end;a=a.."}},"end end;a=a.."}"game.write_file("'+outputFile+'",a)'
|
||||
//return '/silent-command '+'local a='+"'"+'{"players":{'+"'"+'local b=false;for c,d in pairs(game.players)do if d.connected and d.character then if b then a=a..'+"'"+','+"'"+'else b=true end;local e=game.players[c].get_inventory(defines.inventory.player_main).get_contents()local f=game.players[c].get_quickbar().get_contents()local g={}local z={}for j,k in pairs(e)do if z[j] ~= nil then z[j] = z[j] + k else z[j] = k end end for j,k in pairs(f)do if z[j] ~= nil then z[j] = z[j] + k else z[j] = k end end for h=1,game.players[c].force.character_logistic_slot_count do g[h]=game.players[c].character.get_request_slot(h)end;a=a..'+"'"+'"'+"'"+'..c..'+"'"+'":{"inventory":{'+"'"+'local i=false;for j,k in pairs(z)do if i then a=a..'+"'"+','+"'"+'else i=true end;a=a..'+"'"+'"'+"'"+'..j..'+"'"+'":'+"'"+'..k end;a=a..'+"'"+'},"requestSlots":{'+"'"+'i=false;for j,k in pairs(g)do if i then a=a..'+"'"+','+"'"+'else i=true end;a=a..'+"'"+'"'+"'"+'..k['+"'"+'name'+"'"+']..'+"'"+'":'+"'"+'..k['+"'"+'count'+"'"+']end;a=a..'+"'"+'}}'+"'"+'end end;a=a.."}}"game.write_file("'+outputFile+'",a,true,0)'
|
||||
|
||||
// Warning: This command is not in sync with lua commands.lua
|
||||
return `/silent-command local a='{"players":{'local b=false;for c,d in pairs(game.players)do if d.connected and d.character then if b then a=a..','else b=true end;local e=game.players[c].get_inventory(defines.inventory.character_main).get_contents()local g={}for h=1,game.players[c].force.character_logistic_slot_count do g[h]=game.players[c].character.get_request_slot(h)end;a=a..'"'..c..'":{"inventory":{'local i=false;for j,k in pairs(e)do if i then a=a..','else i=true end;a=a..'"'..j..'":'..k end;a=a..'},"requestSlots":{'i=false;for j,k in pairs(g)do if i then a=a..','else i=true end;a=a..'"'..k['name']..'":'..k['count']end;a=a..'}}'end end;a=a.."}}"game.write_file("${outputFile}",a,true,0)`
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
handleInventory: handleInventory,
|
||||
pollInventories: pollInventories,
|
||||
insertItemsFromObject: insertItemsFromObject,
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
module.exports = function(x){
|
||||
if(x === false || x === true || x === null) return true; // === false is valid JSON, so is true and null
|
||||
var isNotJson = false
|
||||
try{
|
||||
JSON.parse(x);
|
||||
} catch (e) {
|
||||
isNotJson = true;
|
||||
}
|
||||
|
||||
return !isNotJson;
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
-- WARNING: The commands in this file is not in sync with interfacingFunctions.js
|
||||
-- Lua cheatsheet
|
||||
|
||||
/c game.write_file("test.txt",serpent.block(game.players["Danielv123"].get_quickbar().get_contents()))
|
||||
/c game.write_file("test.txt",serpent.block(game.players["Danielv123"].get_inventory(defines.inventory.character_main).get_contents()))
|
||||
|
||||
-- print JSON of entire inventory and request slots to file
|
||||
-- TODO: Get requester slot data as well
|
||||
|
||||
-- requester slot data is game.players.character.get_request_slot(slot)
|
||||
-- returns {name="copper-plate", count=47} or nil if nothing is set
|
||||
-- maybe game.players.character.item_requests? http://lua-api.factorio.com/latest/LuaEntity.html#LuaEntity.item_requests
|
||||
|
||||
/c
|
||||
local requests = {}
|
||||
for i = 1, game.player.force.character_logistic_slot_count do
|
||||
requests[i] = game.players["Danielv123"].character.get_request_slot(i)
|
||||
end
|
||||
|
||||
local o = "Requests: "
|
||||
for k,v in pairs(requests) do
|
||||
o = o..v["name"]..": "..v["count"]..", "
|
||||
end
|
||||
game.print(o)
|
||||
|
||||
-- sum up our inventory and request slots and print it as valid JSON
|
||||
-- turns out the valid part is important
|
||||
/c
|
||||
local o = '{"players":{'
|
||||
local notFirst = false
|
||||
for a,b in pairs(game.players) do
|
||||
if b.connected and b.character then
|
||||
if notFirst then
|
||||
o = o .. ','
|
||||
else
|
||||
notFirst = true
|
||||
end
|
||||
local inventory = game.players[a].get_inventory(defines.inventory.character_main).get_contents()
|
||||
local quickbar = game.players[a].get_quickbar().get_contents()
|
||||
--[[ Get contents of requester slots into a table ]]
|
||||
local requests = {}
|
||||
for i = 1, game.players[a].force.character_logistic_slot_count do
|
||||
requests[i] = game.players[a].character.get_request_slot(i)
|
||||
end
|
||||
|
||||
o = o..'"'..a..'":{"inventory":{'
|
||||
--[[ generate JSON table ]]
|
||||
local addComma = false
|
||||
for k,v in pairs(inventory) do
|
||||
if addComma then
|
||||
o = o..','
|
||||
else
|
||||
addComma = true
|
||||
end
|
||||
o = o..'"'..k..'":'..v
|
||||
end
|
||||
for k,v in pairs(quickbar) do
|
||||
if addComma then
|
||||
o = o..','
|
||||
else
|
||||
addComma = true
|
||||
end
|
||||
o = o..'"'..k..'":'..v
|
||||
end
|
||||
|
||||
o = o..'},"requestSlots":{'
|
||||
addComma = false
|
||||
for k,v in pairs(requests) do
|
||||
if addComma then
|
||||
o = o..','
|
||||
else
|
||||
addComma = true
|
||||
end
|
||||
o = o..'"'..v['name']..'":'..v['count']
|
||||
end
|
||||
o = o..'}}' --[[ We need a comma after these two if there is more than 1 player, handled up top by notFirst]]
|
||||
end
|
||||
end
|
||||
o = o.."}}"
|
||||
game.write_file("t.txt", o, true, 0)
|
||||
game.print(o)
|
||||
|
||||
--[[
|
||||
Example output
|
||||
{"players":{"1":{"inventory":{"stone":12,"iron-ore":120,"raw-wood":10,"iron-plate":8,"steel-plate":480},"requestSlots":{}}}}
|
||||
|
||||
Minification procedure:
|
||||
|
||||
Run through https://mothereff.in/lua-minifier
|
||||
Replace ' with '+"'"+'
|
||||
Prepend /silent-command
|
||||
remove game.print(o)
|
||||
replace "t.txt" with "'+outputFile+'"
|
||||
enclose in ''
|
||||
|
||||
]]
|
||||
|
||||
-- minified strings (newest on the top)
|
||||
local a='+"'"+'{"players":{'+"'"+'local b=false;for c,d in pairs(game.players)do if d.connected then if b then a=a..'+"'"+','+"'"+'else b=true end;local e=game.players[c].get_inventory(defines.inventory.character_main).get_contents()local f=game.players[c].get_quickbar().get_contents()local g={}for h=1,game.players[c].force.character_logistic_slot_count do g[h]=game.players[c].character.get_request_slot(h)end;a=a..'+"'"+'"'+"'"+'..c..'+"'"+'":{"inventory":{'+"'"+'local i=false;for j,k in pairs(e)do if i then a=a..'+"'"+','+"'"+'else i=true end;a=a..'+"'"+'"'+"'"+'..j..'+"'"+'":'+"'"+'..k end;for j,k in pairs(f)do if i then a=a..'+"'"+','+"'"+'else i=true end;a=a..'+"'"+'"'+"'"+'..j..'+"'"+'":'+"'"+'..k end;a=a..'+"'"+'},"requestSlots":{'+"'"+'i=false;for j,k in pairs(g)do if i then a=a..'+"'"+','+"'"+'else i=true end;a=a..'+"'"+'"'+"'"+'..k['+"'"+'name'+"'"+']..'+"'"+'":'+"'"+'..k['+"'"+'count'+"'"+']end;a=a..'+"'"+'}}'+"'"+'end end;a=a.."}}"game.write_file("'+outputFile+'",a,true,0)
|
||||
-- offline playes
|
||||
local a="{"for b,c in pairs(game.players)do if c.connected then local d=game.players[b].get_inventory(defines.inventory.character_main).get_contents()local e=game.players[b].get_quickbar().get_contents()local f={}for g=1,game.players[b].force.character_logistic_slot_count do f[g]=game.players[b].character.get_request_slot(g)end;a=a..b..":{inventory:{"for h,i in pairs(d)do a=a.."['+"'"+'"..h.."'+"'"+']:"..i..","end;for h,i in pairs(e)do a=a.."['+"'"+'"..h.."'+"'"+']:"..i..","end;a=a.."},requestSlots:{"for h,i in pairs(f)do a=a.."['+"'"+'"..i["name"].."'+"'"+']:"..i["count"]..", "end;a=a.."}},"end end;a=a.."}"game.print(a)
|
||||
-- multiple players
|
||||
local a="{"for b,c in pairs(game.players)do local d=game.players[b].get_inventory(defines.inventory.character_main).get_contents()local e=game.players[b].get_quickbar().get_contents()local f={}for g=1,game.players[b].force.character_logistic_slot_count do f[g]=game.players[b].character.get_request_slot(g)end;a=a..b..":{inventory:{"for h,i in pairs(d)do a=a.."['+"'"+'"..h.."'+"'"+']:"..i..","end;for h,i in pairs(e)do a=a.."['+"'"+'"..h.."'+"'"+']:"..i..","end;a=a.."},requestSlots:{"for h,i in pairs(f)do a=a.."['+"'"+'"..i["name"].."'+"'"+']:"..i["count"]..", "end;a=a.."}},"end;a=a.."}"game.print(a)
|
||||
local a=game.players["Danielv123"].get_inventory(defines.inventory.character_main).get_contents()local b=game.players["Danielv123"].get_quickbar().get_contents()local c={}for d=1,game.players["Danielv123"].force.character_logistic_slot_count do c[d]=game.players["Danielv123"].character.get_request_slot(d)end;local e="{inventory:{"for f,g in pairs(a)do e=e.."['+"'"+'"..f.."'+"'"+']:"..g..","end;for f,g in pairs(b)do e=e.."['+"'"+'"..f.."'+"'"+']:"..g..","end;e=e.."},requestSlots:{"for f,g in pairs(c)do e=e.."['+"'"+'"..g["name"].."'+"'"+']:"..g["count"]..", "end;e=e.."}}"game.print(e)
|
||||
local inventory = game.players["Danielv123"].get_inventory(defines.inventory.character_main).get_contents()local quickbar = game.players["Danielv123"].get_quickbar().get_contents()local requests = {}for i = 1, game.player.force.character_logistic_slot_count do requests[i] = game.players["Danielv123"].character.get_request_slot(i) end local o = "{inventory:{" for k,v in pairs(inventory) do o = o.."['+"'"+'"..k.."'+"'"+']:"..v.."," end for k,v in pairs(quickbar) do o = o.."['+"'"+'"..k.."'+"'"+']:"..v.."," end o = o.."},requestSlots:{" for k,v in pairs(requests) do o = o.."['+"'"+'"..v["name"].."'+"'"+']:"..v["count"]..", " end o = o.."}}" game.write_file("test.txt", o,true,0)
|
||||
|
||||
|
||||
-- insert items in players inventory and export leftovers
|
||||
-- name should be players[i]
|
||||
|
||||
/c
|
||||
local name = "1"
|
||||
local items = {["iron-ore"]=30, ["steel-plate"]=120}
|
||||
local items_failed = {}
|
||||
if(game.players[name] and game.players[name].connected) then
|
||||
for item,count in pairs(items) do
|
||||
local i = game.players[name].insert{name=item,count=count}
|
||||
if not items_failed[name] then
|
||||
items_failed[name] = {}
|
||||
end
|
||||
if items_failed[name][item] then
|
||||
items_failed[name][item] = items_failed[name][item] + count - i
|
||||
else
|
||||
items_failed[name][item] = count - i
|
||||
end
|
||||
end
|
||||
game.write_file("t.txt", serpent.line({["exports"]=items_failed}, {["comment"]=false, ["compact"]=true}),true,0)
|
||||
end
|
||||
|
||||
--[[
|
||||
Writes something like
|
||||
|
||||
{exports={["1"]={["iron-ore"]=0,["steel-plate"]=0}}}
|
||||
|
||||
converting to JS would be
|
||||
replace "[" and "]" with ""???
|
||||
replace "=" with ":"
|
||||
]]
|
||||
|
||||
--[[
|
||||
JSON edition
|
||||
|
||||
{"exports":{"1":[{"name":"iron-ore","count":0},{"name":"steel-plate","count":0}]}}
|
||||
|
||||
Should always return valid JSON
|
||||
]]
|
||||
/c
|
||||
local name = "1"
|
||||
local items = {["iron-ore"]=30, ["steel-plate"]=120}
|
||||
if(game.players[name] and game.players[name].connected) then
|
||||
local o = '{"exports":{"'..name..'":['
|
||||
local addComma = false
|
||||
for item,count in pairs(items) do
|
||||
local i = game.players[name].insert{name=item,count=count}
|
||||
if addComma then
|
||||
o = o..','
|
||||
else
|
||||
addComma = true
|
||||
end
|
||||
o = o .. '{"name":"'..item..'","count":'..count - i..'}'
|
||||
end
|
||||
o = o .. ']}}'
|
||||
game.write_file("t.txt", o,true,0)
|
||||
end
|
||||
|
||||
--[[
|
||||
Minification procedure:
|
||||
|
||||
Run through https://mothereff.in/lua-minifier
|
||||
Replace ' with '+"'"+'
|
||||
Prepend /silent-command
|
||||
replace "t.txt" with "'+outputFile+'"
|
||||
enclose in ''
|
||||
]]
|
||||
|
||||
|
||||
-- JSON outputFile
|
||||
local a="1"local b={["iron-ore"]=30,["steel-plate"]=120}local c={}if game.players[a]and game.players[a].connected then local d='+"'"+'{"exports":{"'+"'"+'..a..'+"'"+'":['+"'"+'local e=false;for f,g in pairs(b)do local h=game.players[a].insert{name=f,count=g}if e then d=d..'+"'"+','+"'"+'else e=true end;d=d..'+"'"+'{"name":"'+"'"+'..f..'+"'"+'","count":'+"'"+'..g-h..'+"'"+'}'+"'"+'end;d=d..'+"'"+']}}'+"'"+'game.write_file("'+outputFile+'",d,true,0)end
|
||||
-- output to serpented LUA table
|
||||
local a="Danielv123"local b={["iron-ore"]=30,["steel-plate"]=120}local c={}if game.players[a]and game.players[a].connected then for d,e in pairs(b)do local f=game.players[a].insert{name=d,count=e}if not c[a]then c[a]={}end;if c[a][d]then c[a][d]=c[a][d]+e-f else c[a][d]=e-f end end;game.write_file("'+outputFile+'",serpent.line(c,{["comment"]=false,["compact"]=true}),true,0)end
|
||||
|
||||
@@ -1,159 +0,0 @@
|
||||
const assert = require("assert");
|
||||
const child_process = require("child_process");
|
||||
const functions = require("../interfacingFunctions");
|
||||
const luamin = require("luamin");
|
||||
const isFactorioCommand = require("@clusterio/lib/isFactorioCommand");
|
||||
const nock = require("nock");
|
||||
|
||||
// sinon does weird prototype manipulation and so doen't need to be saved to anything.
|
||||
require("mocha-sinon");
|
||||
const sinon = require("sinon");
|
||||
|
||||
describe("inventoryImports/interfacingFunctions.js", function(){
|
||||
describe("handleInventory(inventory, config)", function(){
|
||||
let config = {
|
||||
masterURL:"http://localhost:8080",
|
||||
masterAuthToken:"",
|
||||
}
|
||||
it("returns false if given invalid input", function(){
|
||||
assert(functions.handleInventory("this is a string") === false, "when given strings it should return false and do nothing");
|
||||
});
|
||||
it("Sends post requests and outputs factorio commands", function(done){
|
||||
let inventory = {
|
||||
"players":{
|
||||
"Danielv123":{
|
||||
"inventory":{
|
||||
"stone":12,
|
||||
"iron-ore":120,
|
||||
"raw-wood":10,
|
||||
"iron-plate":8,
|
||||
"steel-plate":480
|
||||
},
|
||||
"requestSlots":{
|
||||
"iron-plate":100,
|
||||
"steel-plate":480,
|
||||
"raw-wood":20,
|
||||
"bullshit":0,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var scope = nock('http://localhost:8080')
|
||||
.post('/api/remove', function(body){
|
||||
// check that we are requesting the right things, () to convert to boolean
|
||||
// 92 because 100 requested and 8 already in inventory
|
||||
if(body.name == "iron-plate") assert(body.count == "92");
|
||||
// nock wants us to return true if this is the correct body and we should reply
|
||||
// if we return false we won't send a reply.
|
||||
return true;
|
||||
})
|
||||
// nock destroys the endpoints after being hit once, this changes the number of hits required for destruction
|
||||
.times(10)
|
||||
// respond with JSON object instead of url query parameters
|
||||
.reply(200,function(uri, req){
|
||||
return req
|
||||
},{
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
})
|
||||
// nock logging statement .log((data) => console.log(data));
|
||||
|
||||
functions.handleInventory(inventory, config, callback);
|
||||
function callback(x){
|
||||
assert(x.includes(92) && x.includes("iron-plate"), "it should have included the items it was going to import");
|
||||
assert(!x.includes("steel-plate"), "Inventory is already filled with steel so shouldn't be importing that");
|
||||
assert(isFactorioCommand(x), "it should have returned a valid factorio command");
|
||||
assert(x.includes('"Danielv123"'), "it should include the name of the player that will recieve the items");
|
||||
done();
|
||||
}
|
||||
});
|
||||
it("posts leftovers to master", function(done){
|
||||
let inventory2 = {
|
||||
"exports":{
|
||||
"1":[
|
||||
{"name":"iron-ore","count":1200},
|
||||
{"name":"steel-plate","count":1337},
|
||||
{"name":"copper-plate","count":0},
|
||||
]
|
||||
}
|
||||
}
|
||||
let timesRan = 0;
|
||||
let callback = function(){
|
||||
timesRan++
|
||||
assert(timesRan <= 2, "placed more than 2 items, unexpeceted test result");
|
||||
if(timesRan == 2){
|
||||
done();
|
||||
}
|
||||
}
|
||||
var scope = nock('http://localhost:8080')
|
||||
.post('/api/place', function(body){
|
||||
// check that we are requesting the right things
|
||||
assert(body.name != "copper-plate", "copper plate should not be placed because it is 0");
|
||||
assert(body.count > 0, "no need for placing 0 things");
|
||||
assert(Number(body.count) != NaN, "count should be a number");
|
||||
callback();
|
||||
return true;
|
||||
})
|
||||
// nock destroys the endpoints after being hit once, this changes the number of hits required for destruction
|
||||
.times(10)
|
||||
.reply(200,"affirmative")
|
||||
// if it tries using the nonexisting callback (argv 3) it will throw. It shoudln't.
|
||||
assert.doesNotThrow(function(){
|
||||
functions.handleInventory(inventory2, config);
|
||||
}, "this here threw for some reason, remove assert.doesNotThrow for easier debugging of this issue");
|
||||
});
|
||||
});
|
||||
describe("pollInventories(outputfile)", function(){
|
||||
it("Returns a big factorio command as string", function(){
|
||||
let x = functions.pollInventories("output.txt");
|
||||
assert(typeof x == "string", "pollInventories() should always return a string");
|
||||
assert(isFactorioCommand(x), "This is not a command factorio will accept, please prepend /c");
|
||||
assert(x.length > 20, "LUA string seems to short, this ain't good");
|
||||
});
|
||||
it("Returns valid LUA", function(){
|
||||
let x = functions.pollInventories("output.txt");
|
||||
|
||||
// remove string added to make factorio interpret as command
|
||||
x = x.replace("/silent-command ","").replace("/c ","");
|
||||
|
||||
let y = false;
|
||||
// luamin throws when it recieves something that is invalid LUA
|
||||
assert.doesNotThrow(function(){
|
||||
y = luamin.minify(x);
|
||||
}, "Invalid LUA supplied");
|
||||
assert(typeof y == "string", "luamin does not return string???");
|
||||
assert(y.length > 20, "Minified LUA too short, something is up");
|
||||
});
|
||||
});
|
||||
describe("insertItemsFromObject(object)", function(){
|
||||
let testObject = {"copper-plate":100, "iron-ore":1337}
|
||||
let playerName = "Danielv123"
|
||||
it("Returns undefined if any of the parameters are missing", function(){
|
||||
let x = functions.insertItemsFromObject();
|
||||
assert(x === undefined);
|
||||
|
||||
let y = functions.insertItemsFromObject(testObject);
|
||||
assert(y === undefined);
|
||||
|
||||
let z = functions.insertItemsFromObject(undefined, playerName);
|
||||
assert(z === undefined);
|
||||
});
|
||||
it("Throws if player name is not a string", function(){
|
||||
assert.throws(function(){
|
||||
let x = functions.insertItemsFromObject(testObject, testObject);
|
||||
}, Error("playerName is: 'object' instead of string!"));
|
||||
});
|
||||
it("Returns a big factorio command as string", function(){
|
||||
let x = functions.insertItemsFromObject(testObject, playerName);
|
||||
|
||||
assert(typeof x == "string", "LUA returned should be a string");
|
||||
assert(x.length > 20, "LUA strings are quite long");
|
||||
assert(isFactorioCommand(x), "This is not a command factorio will accept, please prepend /c");
|
||||
});
|
||||
it("The returned string is a valid factorio command", function(){
|
||||
let x = functions.insertItemsFromObject(testObject, playerName);
|
||||
|
||||
assert(isFactorioCommand(x) == true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,20 +0,0 @@
|
||||
const isJson = require("../isJson");
|
||||
const assert = require("assert");
|
||||
|
||||
describe("inventoryImports/isJson.js()", function(){
|
||||
it("checks if a thing is valid JSON", function(){
|
||||
assert(isJson("string") === false);
|
||||
assert(isJson("{js_object_notation='very false'}") === false);
|
||||
assert(isJson('{ "name":"John", "age":31, "city":"New York" }') === true, "This is valid JSON, lib disagrees");
|
||||
});
|
||||
it("recognizes that true and false are both valid JSON", function(){
|
||||
assert(isJson(true) === true);
|
||||
assert(isJson(false) === true);
|
||||
});
|
||||
it("Handles null as valid JSON (after spec)", function(){
|
||||
assert(isJson(null) === true);
|
||||
});
|
||||
it("Recognizes that JSON doesn't allow trailing commas (,)", function(){
|
||||
assert(isJson('["a", "b", ]') === false, "JSON should not allow trailing commas");
|
||||
});
|
||||
});
|
||||
@@ -1,4 +0,0 @@
|
||||
// These are libraries that does not have any units test, they are
|
||||
// required here in order to track coverage for them.
|
||||
|
||||
require('../index');
|
||||
@@ -1,22 +0,0 @@
|
||||
"use strict";
|
||||
var assert = require("assert");
|
||||
var libObjectOps = require("@clusterio/lib/object_ops");
|
||||
|
||||
describe("lib/object_ops", function(){
|
||||
describe("deepclone()", function(){
|
||||
it("deep clones javascript objects", function(){
|
||||
var obj1 = { hello: "world", cat: { legs: 4, name: "Kitty", colors: ["brown", "yellow", "purple"] }};
|
||||
var obj2 = {};
|
||||
obj2 = libObjectOps.deepclone(obj1);
|
||||
|
||||
obj1.cat.colors = "black";
|
||||
assert.equal(obj1.cat.colors, "black");
|
||||
assert.equal(obj2.cat.colors[1], "yellow");
|
||||
});
|
||||
it("throws on non JSON parameters", function(){
|
||||
assert.throws(function(){
|
||||
let y = libObjectOps.deepclone(libObjectOps.deepclone);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user