Skip to content
Open
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 60 additions & 1 deletion inventory.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,30 @@ local S = digilines.S

local pipeworks_enabled = minetest.get_modpath("pipeworks") ~= nil

-- Signals which will be sent in a single batch
local batched_signals = {}
-- Maximum interval from the previous signal to include the current one into batch (in seconds)
local interval_to_batch = 0.1
-- Maximum number of signals in batch
local max_signals_in_batch = 100

-- Sends the current batch message of a Digiline chest
-- pos: the position of the Digilines chest node
-- channel: the channel to which the message will be sent
local function send_and_clear_batch(pos, channel)
local pos_text = vector.to_string(pos)
if #batched_signals[pos_text] == 1 then
-- If there is only one signal is the batch, don't send it in a batch
digilines.receptor_send(pos, digilines.rules.default, next(batched_signals[pos_text]))
else
digilines.receptor_send(pos, digilines.rules.default, channel, {
action = "batch",
signals = batched_signals[pos_text]
})
end
batched_signals[pos_text] = nil
end

-- Sends a message onto the Digilines network.
-- pos: the position of the Digilines chest node.
-- action: the action string indicating what happened.
Expand All @@ -10,7 +34,9 @@ local pipeworks_enabled = minetest.get_modpath("pipeworks") ~= nil
-- to_slot: the slot number that is put into (optional).
-- side: which side of the chest the action occurred (optional).
local function send_message(pos, action, stack, from_slot, to_slot, side)
local channel = minetest.get_meta(pos):get_string("channel")
local meta = minetest.get_meta(pos)
local channel = meta:get_string("channel")

local msg = {
action = action,
stack = stack and stack:to_table(),
Expand All @@ -19,6 +45,27 @@ local function send_message(pos, action, stack, from_slot, to_slot, side)
-- Duplicate the vector in case the caller expects it not to change.
side = side and vector.new(side)
}

-- Check if we need to include the current signal into batch
-- Store "prev_time" in metadata as a string to avoid integer overflow
local prev_time = tonumber(meta:get_string("prev_time")) or 0
local cur_time = minetest.get_us_time()
meta:set_string("prev_time", tostring(cur_time))
if cur_time - prev_time < 1000000 * interval_to_batch then
local pos_text = vector.to_string(pos)
batched_signals[pos_text] = batched_signals[pos_text] or {}
table.insert(batched_signals[pos_text], msg)
local node_timer = minetest.get_node_timer(pos)
if #batched_signals[pos_text] >= max_signals_in_batch then
-- Send the batch immediately if it's full
node_timer:stop()
send_and_clear_batch(pos, channel)
else
node_timer:start(interval_to_batch)
end
return
end

digilines.receptor_send(pos, digilines.rules.default, channel, msg)
end

Expand Down Expand Up @@ -186,6 +233,9 @@ minetest.register_node("digilines:chest", {
local inv = meta:get_inventory()
inv:set_size("main", 8*4)
end,
on_destruct = function(pos)
batched_signals[vector.to_string(pos)] = nil
end,
after_place_node = tubescan,
after_dig_node = tubescan,
can_dig = function(pos)
Expand Down Expand Up @@ -321,6 +371,15 @@ minetest.register_node("digilines:chest", {
send_message(pos, "utake", stack, index)
check_empty(pos)
minetest.log("action", player:get_player_name().." takes stuff from chest at "..minetest.pos_to_string(pos))
end,
on_timer = function(pos, _)
-- Send all the batched signals when enough time since the last signal passed
if not batched_signals[vector.to_string(pos)] then
return
end
local channel = minetest.get_meta(pos):get_string("channel")
send_and_clear_batch(pos, channel)
return false
end
})

Expand Down