Add Transmit/Receive Combinators. Transmit combinators are Deciders which also output into txbuffer.txt. Receive Combinators are Constants which replay frames received from external sources via remote calls to receiveFrame and recieveMany.

This commit is contained in:
Thomas Deal committed 2016-10-01 21:20:18 -04:00
1 parent 4f8ad5eec6
commit f9d6d9e001
5 files changed
+267 -72

No files matched your search

+7 -1
View File
@@ -18,9 +18,15 @@ OUTPUT_TANK_NAME = "get-tank"
OUTPUT_TANK_PICTURE_PATH = nil
OUTPUT_TANK_ICON_PATH = nil
MAX_RX_BUFFER_SIZE = 40 -- slightly more than one second
RX_COMBINATOR_NAME = "get-combinator"
TX_COMBINATOR_NAME = "put-combinator"
OUTPUT_FILE = "output.txt"
ORDER_FILE = "orders.txt"
TX_BUFFER_FILE = "txbuffer.txt"
UPATE_RATE = 60
UPATE_RATE = 60
CIRCUIT_UPATE_RATE = 5
+156 -42
View File
@@ -43,12 +43,17 @@ function AddEntity(entity)
--add the chests to a lists if these chests so they can be interated over
global.outputTanks[HashPosition(entity.position)] = entity
entity.active = false
elseif entity.name == TX_COMBINATOR_NAME then
table.insert(global.txControls, entity.get_or_create_control_behavior())
elseif entity.name == RX_COMBINATOR_NAME then
table.insert(global.rxControls, entity.get_or_create_control_behavior())
entity.operable=false
end
end
function OnKilledEntity(event)
local entity = event.entity
if entity.type ~= "entity-ghost" then
if entity.type ~= "entity-ghost" then
--remove the entities from the tables as they are dead
if entity.name == INPUT_CHEST_NAME then
global.inputChests[HashPosition(entity.position)] = nil
@@ -85,23 +90,29 @@ end)
script.on_event(defines.events.on_tick, function(event)
global.inputChests = global.inputChests or {}
global.outputChests = global.outputChests or {}
global.inputTanks = global.inputTanks or {}
global.outputTanks = global.outputTanks or {}
global.outputList = global.outputList or {}
global.inputList = global.inputList or {}
global.rxControls = global.rxControls or {}
global.txControls = global.txControls or {}
-- TX Combinators must run every tick to catch single pulses
HandleTXCombinators()
local todo = game.tick % UPATE_RATE
local onlinePlayers = GetOnlinePlayerCount()
if global.previousPlayerCount == nil or global.previousPlayerCount ~= onlinePlayers then
Reset()
end
global.previousPlayerCount = onlinePlayers
if todo == 0 then
HandleInputChests()
elseif todo == 1 then
@@ -114,6 +125,14 @@ script.on_event(defines.events.on_tick, function(event)
ExportInputList()
elseif todo == 5 then
ExportOutputList()
end
local rxstate = game.tick % CIRCUIT_UPATE_RATE
-- RX Combinators are set and then cleared on sequential ticks to create pulses
if rxstate == 0 then
SetRXCombinators()
elseif rxstate == 1 then
ClearRXCombinators()
end
end)
@@ -131,12 +150,12 @@ function Reset()
global.outputList = {}
global.inputList = {}
global.itemStorage = {}
global.inputChests = {}
global.outputChests = {}
global.inputTanks = {}
global.outputTanks = {}
AddAllEntitiesOfName(INPUT_CHEST_NAME)
AddAllEntitiesOfName(OUTPUT_CHEST_NAME)
AddAllEntitiesOfName(INPUT_TANK_NAME)
@@ -171,7 +190,7 @@ function HandleInputTanks()
v.fluidbox[1] = fluid
end
end
end
function HandleOutputChests()
@@ -195,7 +214,7 @@ function HandleOutputChests()
--insert the missing items
local insertedItemsCount = chestInventory.insert(simpleItemStack)
local itemsNotInsertedCount = itemCountAllowedToInsert - insertedItemsCount
if itemsNotInsertedCount > 0 then
GiveItemsToStorage(requestItem.name, itemsNotInsertedCount)
end
@@ -214,16 +233,15 @@ function HandleOutputTanks()
local MAX_FLUID_AMOUNT = 1000
for k,v in pairs(global.outputTanks) do
--.recipe.products[1].name
if v.recipe ~= nil then
local fluidName = v.recipe.products[1].name
--either get the fluid or reset it to the requested fluid
local fluid = v.fluidbox[1] or {type = fluidName, amount = 0}
if fluid.type ~= fluidName then
fluid = {type = fluidName, amount = 0}
end
--if any fluid is missing then request the fluid
--from store and give either what it's missing or
--the rest of the liquid in the system
@@ -237,11 +255,11 @@ function HandleOutputTanks()
AddItemToOutputList(fluid.type, fluidToRequestAmount)
end
end
v.fluidbox[1] = fluid
end
v.fluidbox[1] = fluid
end
end
end
function AddItemToInputList(itemName, itemCount)
@@ -261,9 +279,9 @@ function ExportInputList()
end
global.inputList = {}
if #exportStrings > 0 then
--only write to file once as i/o is slow
--it's much faster to concatenate all the lines with table.concat
--it's much faster to concatenate all the lines with table.concat
--instead of doing it with the .. operator
game.write_file(OUTPUT_FILE, table.concat(exportStrings), true)
end
@@ -276,9 +294,9 @@ function ExportOutputList()
end
global.outputList = {}
if #exportStrings > 0 then
--only write to file once as i/o is slow
--it's much faster to concatenate all the lines with table.concat
--it's much faster to concatenate all the lines with table.concat
--instead of doing it with the .. operator
game.write_file(ORDER_FILE, table.concat(exportStrings), true)
end
@@ -296,7 +314,7 @@ function RequestItemsFromStorage(itemName, itemCount)
--requested then take the number of items there are left otherwise take the requested amount
local itemsTakenFromStorage = math.min(global.itemStorage[itemName], itemCount)
global.itemStorage[itemName] = global.itemStorage[itemName] - itemsTakenFromStorage
return itemsTakenFromStorage
end
@@ -311,10 +329,110 @@ end
function AddFrameToRXBuffer(frame)
-- Add a frame to the buffer. return remaining space in buffer
local validsignals = {
["virtual"] = game.virtual_signal_prototypes,
["fluid"] = game.fluid_prototypes,
["item"] = game.item_prototypes
}
global.rxBuffer = global.rxBuffer or {}
-- if buffer is full, drop frame
if #global.rxBuffer >= MAX_RX_BUFFER_SIZE then return 0 end
-- frame = {{count=42,name="signal-grey",type="virtual"},{...},...}
local signals = {}
local index = 1
for _,signal in pairs(frame) do
if validsignals[signal.type] and validsignals[signal.type][signal.name] then
signals[index] =
{
index=index,
count=signal.count,
signal={ name=signal.name, type=signal.type }
}
index = index + 1
--TODO: break if too many?
--TODO: error token on mismatched signals? maybe mismatch1-n signals?
end
end
if index > 1 then table.insert(global.rxBuffer,signals) end
return MAX_RX_BUFFER_SIZE - #global.rxBuffer
end
function HandleTXCombinators()
-- Check all TX Combinators, and if condition satisfied, add frame to transmit buffer
-- frame = {{count=42,name="signal-grey",type="virtual"},{...},...}
local signals = {["item"]={},["virtual"]={},["fluid"]={}}
for i,txControl in pairs(global.txControls) do
if txControl.valid then
local frame = txControl.signals_last_tick
if frame then
for _,signal in pairs(frame) do
signals[signal.signal.type][signal.signal.name]=
(signals[signal.signal.type][signal.signal.name] or 0) + signal.count
end
end
else
table.remove(global.txControls,i)
end
end
local frame = {}
for type,arr in pairs(signals) do
for name,count in pairs(arr) do
table.insert(frame,{count=count,name=name,type=type})
end
end
if #frame > 0 then
table.insert(frame,{count=game.tick,name="signal-srctick",type="virtual"})
game.write_file(TX_BUFFER_FILE, json:encode(frame).."\n", true)
-- Loopback for testing
--AddFrameToRXBuffer(frame)
end
end
function SetRXCombinators()
-- if the RX buffer is not empty, get a frame from it and output on all RX Combinators
if global.rxBuffer and #global.rxBuffer > 0 then
local frame = table.remove(global.rxBuffer)
for i,rxControl in pairs(global.rxControls) do
if rxControl.valid then
rxControl.parameters={parameters=frame}
rxControl.enabled=true
else
table.remove(global.rxControls,i)
end
end
end
end
function ClearRXCombinators()
-- Clear all RX Combinators.
-- This makes them emit pulses, which are easier to
-- detect than slowly changing continusous signals.
for i,rxControl in pairs(global.rxControls) do
if rxControl.valid then
rxControl.enabled=false
else
table.remove(global.rxControls,i)
end
end
end
--[[ Remote Thing ]]--
remote.add_interface("clusterio",
remote.add_interface("clusterio",
{
import = function(itemName, itemCount)
import = function(itemName, itemCount)
GiveItemsToStorage(itemName, itemCount)
end,
importMany = function(jsonString)
@@ -332,23 +450,19 @@ remote.add_interface("clusterio",
end
game.print(items)
end,
reset = Reset
reset = Reset,
receiveFrame = function(jsonframe)
local frame = json:decode(jsonframe)
-- frame = {tick=123456,frame={{count=42,name="signal-grey",type="virtual"},{...},...}}
return AddFrameToRXBuffer(frame)
end,
receiveMany = function(jsonframes)
local frames = json:decode(jsonframes)
local buffer
for _,frame in pairs(frames) do
buffer = AddFrameToRXBuffer(frame)
if buffer==0 then return 0 end
end
return buffer
end,
})
+97 -25
View File
@@ -18,10 +18,10 @@ function MakeLogisticEntity(entity, name, pictureFilename, pictureTablePath, ico
ChangePictureFilename(entity, pictureTablePath, pictureFilename)
--if no icon is defined then use the default one
entity.icon = iconPath or entity.icon
-- add the entity to a technology so it can be unlocked
--local wasAddedToTech = AddEntityToTech("construction-robotics", name)
data:extend(
{
-- add the entity
@@ -70,7 +70,7 @@ function AddEntityToTech(techName, name)
type = "unlock-recipe",
recipe = name
}
--if a new table for the effects is made then the effects has to be attached to the
--if a new table for the effects is made then the effects has to be attached to the
-- tech again because the table won't otherwise be owned by the tech
data.raw["technology"][techName].effects = effects
return true
@@ -86,22 +86,10 @@ MakeLogisticEntity(table.deepcopy(data.raw["container"]["iron-chest"]),
--make tanks
MakeLogisticEntity(table.deepcopy(data.raw["storage-tank"]["storage-tank"]), INPUT_TANK_NAME, INPUT_TANK_PICTURE_PATH, { "pictures", "picture", "sheet" }, INPUT_TANK_ICON_PATH)
--------------------------------------------------------
--[[This section is purely to create the output tank]]--
--------------------------------------------------------
local CRAFING_FLUID_CATEGORY_NAME = "crafting-fluids"
data:extend(
@@ -121,10 +109,10 @@ fluidCreator.fluid_boxes =
pipe_covers = pipecoverspictures(),
base_area = 250,
base_level = 1,
pipe_connections =
pipe_connections =
{
{
type="output", position = {0, 2}
{
type="output", position = {0, 2}
}
}
},
@@ -157,12 +145,96 @@ for k,v in pairs(data.raw.fluid) do
end
-- Virtual signals
data:extend{
{
type = "item-subgroup",
name = "virtual-signal-clusterio",
group = "signals",
order = "e"
},
{
type = "virtual-signal",
name = "signal-srctick",
icon = "__base__/graphics/icons/signal/signal_grey.png",
subgroup = "virtual-signal-clusterio",
order = "e[clusterio]-[1srctick]"
},
--[[{
type = "virtual-signal",
name = "signal-srcid",
icon = "__base__/graphics/icons/signal/signal_grey.png",
subgroup = "virtual-signal-clusterio",
order = "e[clusterio]-[2srcid]"
},]]
--[[{
type = "virtual-signal",
name = "signal-localid",
icon = "__base__/graphics/icons/signal/signal_grey.png",
subgroup = "virtual-signal-clusterio",
order = "e[clusterio]-[3localid]"
},]]
}
-- TX Combinator
local tx = table.deepcopy(data.raw["decider-combinator"]["decider-combinator"])
tx.name = TX_COMBINATOR_NAME
tx.minable.result = TX_COMBINATOR_NAME
data:extend{
tx,
{
type = "item",
name = TX_COMBINATOR_NAME,
icon = tx.icon,
flags = {"goes-to-quickbar"},
subgroup = "storage",
place_result=TX_COMBINATOR_NAME,
order = "a[items]-b["..TX_COMBINATOR_NAME.."]",
stack_size = 50,
},
{
type = "recipe",
name = TX_COMBINATOR_NAME,
enabled = true, -- TODO do this on a tech somewhere
ingredients =
{
{"decider-combinator", 1},
{"electronic-circuit", 3},
{"advanced-circuit", 1}
},
result = TX_COMBINATOR_NAME,
requester_paste_multiplier = 1
},
}
-- RX Combinator
local rx = table.deepcopy(data.raw["constant-combinator"]["constant-combinator"])
rx.name = RX_COMBINATOR_NAME
rx.minable.result = RX_COMBINATOR_NAME
rx.item_slot_count = 100
data:extend{
rx,
{
type = "item",
name = RX_COMBINATOR_NAME,
icon = rx.icon,
flags = {"goes-to-quickbar"},
subgroup = "storage",
place_result=RX_COMBINATOR_NAME,
order = "a[items]-b["..RX_COMBINATOR_NAME.."]",
stack_size = 50,
},
{
type = "recipe",
name = RX_COMBINATOR_NAME,
enabled = true, -- TODO do this on a tech somewhere
ingredients =
{
{"constant-combinator", 1},
{"electronic-circuit", 3},
{"advanced-circuit", 1}
},
result = RX_COMBINATOR_NAME,
requester_paste_multiplier = 1
},
}
+2 -2
View File
@@ -4,8 +4,8 @@
"title": "Clusterio",
"version": "0.0.2",
"date": "19-08-2016",
"author": "Danielv123 & Keyboardhack",
"author": "Danielv123 & Keyboardhack & justarandomgeek",
"dependencies": ["base >= 0.13"],
"factorio_version": "0.14",
"description": "Adds 2 chests to transfer items between saves and servers over the internet."
}
}
+5 -2
View File
@@ -3,10 +3,13 @@ put-chest=Put chest
get-chest=Get chest
put-tank=Put tank
get-tank=Get tank
put-combinator=Transmit combinator
get-combinator=Receive combinator
[item-name]
put-chest=Put chest
get-chest=Get chest
put-tank=Put tank
get-tank=Get tank
get-tank=Get tank
put-combinator=Transmit combinator
get-combinator=Receive combinator