v0.04 support for 'node_io' added, chest added, further commands added
parent
17f5564155
commit
3792590ea0
11
README.md
11
README.md
|
@ -29,9 +29,10 @@ The state of the actuator is saved with the pairing and restored by the signal.
|
|||
An actuator can receive signals from many sensors. A sensor can only be connected to an actuator. However, if several actuators are to be controlled by one sensor, a signal extender block must be used. This connects to a sensor when it is placed next to the sensor. This extender can then be paired with another actuator.
|
||||
|
||||
Sensors are:
|
||||
- Bot Sensor: sends a signal when the robot passes by
|
||||
- Node Sensor: sends a signal when it detects a change (tree, cactus, flower, etc.) in front of the sensor (over 3 positions)
|
||||
- Crop Sendor: Sends a signal when, for example, the wheat is fully grown
|
||||
- Bot Sensor: Sends a signal when the robot passes by
|
||||
- Node Sensor: Sends a signal when it detects a change (tree, cactus, flower, etc.) in front of the sensor (over 3 positions)
|
||||
- Crop Sensor: Sends a signal when, for example, the wheat is fully grown
|
||||
- Bot Chest: Sends a signal depending on the chest state. Possible states are "empty", "not empty", "almost full". The state to be sent is defined while pairing.
|
||||
|
||||
Actuators are:
|
||||
- Control Unit: Can place up to 4 signs and steer the bot e.g. in different directions.
|
||||
|
@ -72,10 +73,12 @@ For all Inventory commands applies: If the inventory stack specified by <slot> i
|
|||
place_left <slot> <lvl> - Set block to the left
|
||||
place_right <slot> <lvl> - set block to the right
|
||||
place_below <slot> - set block under the robot
|
||||
place_above <slot> - set block above the robot
|
||||
dig_front <slot> <lvl> - remove block in front of the robot
|
||||
dig_left <slot> <lvl> - remove block on the left
|
||||
dig_right <slot> <lvl> - remove block on the right
|
||||
dig_below <slot> - dig block under the robot
|
||||
dig_above <slot> - dig block above the robot
|
||||
place_sign <slot> - set sign
|
||||
place_sign_behind <slot> - put a sign behind the bot
|
||||
dig_sign <slot> - remove the sign
|
||||
|
@ -104,4 +107,4 @@ optional: farming redo
|
|||
- 2019-03-23 v0.01 * first draft
|
||||
- 2019-04-06 v0.02 * completely reworked
|
||||
- 2019-04-08 v0.03 * 'plant_sapling', 'place_below', 'dig_below' added, many bugs fixed
|
||||
|
||||
- 2019-04-11 v0.04 * support for 'node_io' added, chest added, further commands added
|
||||
|
|
|
@ -105,11 +105,14 @@ end
|
|||
|
||||
local function node_timer(pos, elapsed)
|
||||
local mem = tubelib2.get_mem(pos)
|
||||
local res
|
||||
--local t = minetest.get_us_time()
|
||||
local res = signs_bot.run_next_command(pos, mem)
|
||||
if mem.running then
|
||||
res = signs_bot.run_next_command(pos, mem)
|
||||
end
|
||||
--t = minetest.get_us_time() - t
|
||||
--print("node_timer", t)
|
||||
return res
|
||||
return res and mem.running
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
--[[
|
||||
|
||||
Signs Bot
|
||||
=========
|
||||
|
||||
Copyright (C) 2019 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Signs Bot Chest
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
|
||||
-- Load support for intllib.
|
||||
local MP = minetest.get_modpath("signs_bot")
|
||||
local I,_ = dofile(MP.."/intllib.lua")
|
||||
|
||||
local function get_inv_state(pos)
|
||||
local inv = minetest.get_inventory({type="node", pos=pos})
|
||||
if inv:is_empty("main") then
|
||||
return "empty"
|
||||
else
|
||||
local list = inv:get_list("main")
|
||||
for _, item in ipairs(list) do
|
||||
if item:is_empty() then
|
||||
return "not empty"
|
||||
end
|
||||
end
|
||||
end
|
||||
return "almost full"
|
||||
end
|
||||
|
||||
local function check_state(pos)
|
||||
local state = M(pos):get_string("state")
|
||||
if state == get_inv_state(pos) then
|
||||
signs_bot.send_signal(pos)
|
||||
signs_bot.lib.activate_extender_nodes(pos, true)
|
||||
end
|
||||
end
|
||||
|
||||
local function update_infotext(pos, dest_pos, cmnd)
|
||||
local meta = M(pos)
|
||||
local state = get_inv_state(pos)
|
||||
meta:set_string("infotext", I("Bot Chest: Sends signal to ")..S(dest_pos).." / "..cmnd..", if "..state)
|
||||
meta:set_string("state", state)
|
||||
|
||||
end
|
||||
|
||||
local function formspec()
|
||||
return "size[9,8]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;main;0.5,0;8,4;]"..
|
||||
"list[current_player;main;0.5,4.3;8,4;]"..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
|
||||
minetest.register_node("signs_bot:chest", {
|
||||
description = I("Signs Bot Chest"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
'signs_bot_chest_top.png',
|
||||
'signs_bot_chest_top.png',
|
||||
'signs_bot_chest_side.png',
|
||||
'signs_bot_chest_side.png',
|
||||
'signs_bot_chest_side.png',
|
||||
'signs_bot_chest_front.png',
|
||||
},
|
||||
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size('main', 32)
|
||||
end,
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local mem = tubelib2.init_mem(pos)
|
||||
mem.running = false
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("owner", placer:get_player_name())
|
||||
meta:set_string("formspec", formspec(pos, mem))
|
||||
meta:set_string("infotext", "Bot Chest: Not connected")
|
||||
end,
|
||||
|
||||
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end,
|
||||
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end,
|
||||
on_metadata_inventory_move = function(pos, from_list, from_index, to_list)
|
||||
check_state(pos)
|
||||
end,
|
||||
on_metadata_inventory_put = function(pos, listname)
|
||||
check_state(pos)
|
||||
end,
|
||||
on_metadata_inventory_take = function(pos, listname)
|
||||
check_state(pos)
|
||||
end,
|
||||
|
||||
node_io_can_put_item = function(pos, node, side) return true end,
|
||||
node_io_room_for_item = function(pos, node, side, itemstack, count)
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
if not inv then return 0 end
|
||||
return node_io.room_for_item_in_inventory(inv, "main", itemstack, count)
|
||||
end,
|
||||
node_io_put_item = function(pos, node, side, putter, itemstack)
|
||||
local owner = M(pos):get_string("owner")
|
||||
if owner == putter:get_player_name() then
|
||||
local left_over = node_io.put_item_in_inventory(pos, node, "main", putter, itemstack)
|
||||
check_state(pos)
|
||||
return left_over
|
||||
end
|
||||
end,
|
||||
node_io_can_take_item = function(pos, node, side) return true end,
|
||||
node_io_get_item_size = function(pos, node, side)
|
||||
return node_io.get_inventory_size(pos, "main")
|
||||
end,
|
||||
node_io_get_item_name = function(pos, node, side, index)
|
||||
return node_io.get_inventory_name(pos, "main", index)
|
||||
end,
|
||||
node_io_get_item_stack = function(pos, node, side, index)
|
||||
return node_io.get_inventory_stack(pos, "main", index)
|
||||
end,
|
||||
node_io_take_item = function(pos, node, side, taker, want_item, want_count)
|
||||
local owner = M(pos):get_string("owner")
|
||||
if owner == taker:get_player_name() then
|
||||
local left_over = node_io.take_item_from_inventory(pos, node, "main", taker, want_item, want_count)
|
||||
check_state(pos)
|
||||
return left_over
|
||||
end
|
||||
end,
|
||||
|
||||
update_infotext = update_infotext,
|
||||
on_rotate = screwdriver.disallow,
|
||||
paramtype2 = "facedir",
|
||||
is_ground_content = false,
|
||||
groups = {cracky = 1, sign_bot_sensor = 1},
|
||||
sounds = default.node_sound_metal_defaults(),
|
||||
})
|
128
cmd_item.lua
128
cmd_item.lua
|
@ -24,96 +24,38 @@ local I,_ = dofile(MP.."/intllib.lua")
|
|||
local lib = signs_bot.lib
|
||||
|
||||
|
||||
--
|
||||
-- Inventory helper functions
|
||||
--
|
||||
|
||||
local function get_other_inv(pos, take, is_fuel)
|
||||
local inv = minetest.get_inventory({type="node", pos=pos})
|
||||
if is_fuel and inv:get_list("fuel") then
|
||||
return inv, "fuel"
|
||||
elseif take and inv:get_list("dst") then
|
||||
return inv, "dst"
|
||||
elseif inv:get_list("src") then
|
||||
return inv, "src"
|
||||
elseif inv:get_list("main") then
|
||||
return inv, "main"
|
||||
end
|
||||
end
|
||||
|
||||
local function get_own_inv(pos, take)
|
||||
return minetest.get_inventory({type="node", pos=pos}), "main"
|
||||
end
|
||||
|
||||
-- Get the given number of items from the inv. The position within the list
|
||||
-- is random so that different item stacks will be considered.
|
||||
-- Returns nil if ItemList is empty.
|
||||
local function get_items(inv, listname, num)
|
||||
if inv:is_empty(listname) then
|
||||
return nil
|
||||
end
|
||||
local size = inv:get_size(listname)
|
||||
local startpos = math.random(1, size)
|
||||
for idx = startpos, startpos+size do
|
||||
idx = (idx % size) + 1
|
||||
local items = inv:get_stack(listname, idx)
|
||||
if items:get_count() > 0 then
|
||||
local taken = items:take_item(num)
|
||||
inv:set_stack(listname, idx, items)
|
||||
return taken
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Put the given stack into the given ItemList.
|
||||
-- Function returns false if ItemList is full.
|
||||
local function put_items(inv, listname, stack)
|
||||
if inv:room_for_item(listname, stack) then
|
||||
inv:add_item(listname, stack)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--
|
||||
-- Move from/to inventories
|
||||
--
|
||||
-- From chest to robot
|
||||
function signs_bot.robot_take(base_pos, robot_pos, param2, num, slot)
|
||||
local pos1 = lib.next_pos(robot_pos, param2)
|
||||
if lib.not_protected(base_pos, pos1) then
|
||||
local me = M(base_pos):get_string("owner")
|
||||
local you = M(pos1):get_string("owner")
|
||||
if you == "" or me == you then
|
||||
--minetest.global_exists("node_io")
|
||||
local src_inv, src_list = get_other_inv(pos1, true)
|
||||
local dst_inv, dst_list = get_own_inv(base_pos)
|
||||
local taken = get_items(src_inv, src_list, num)
|
||||
if taken then
|
||||
if not lib.put_inv_items(dst_inv, dst_list, slot, taken) then
|
||||
lib.drop_items(robot_pos, taken)
|
||||
end
|
||||
end
|
||||
function signs_bot.robot_take(base_pos, robot_pos, param2, want_count, slot)
|
||||
local target_pos = lib.next_pos(robot_pos, param2)
|
||||
local side = node_io.get_target_side(robot_pos, target_pos)
|
||||
local node = lib.get_node_lvm(target_pos)
|
||||
local owner = M(base_pos):get_string("owner")
|
||||
local fake_player = lib.fake_player(owner)
|
||||
local taken = node_io.take_item(target_pos, node, side, fake_player, nil, want_count)
|
||||
if taken then
|
||||
local dst_inv = minetest.get_inventory({type="node", pos=base_pos})
|
||||
if not lib.put_inv_items(dst_inv, "main", slot, taken) then
|
||||
lib.drop_items(robot_pos, taken)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- From robot to chest
|
||||
function signs_bot.robot_add(base_pos, robot_pos, param2, num, slot, is_fuel)
|
||||
local pos1 = lib.next_pos(robot_pos, param2)
|
||||
if lib.not_protected(base_pos, pos1) and not lib.is_air_like(pos1) then
|
||||
local me = M(base_pos):get_string("owner")
|
||||
local you = M(pos1):get_string("owner")
|
||||
if you == "" or me == you then
|
||||
local src_inv, src_list = get_own_inv(base_pos)
|
||||
local dst_inv, dst_list = get_other_inv(pos1, false, is_fuel)
|
||||
local taken = lib.get_inv_items(src_inv, src_list, slot, num)
|
||||
if taken then
|
||||
if not put_items(dst_inv, dst_list, taken) then
|
||||
lib.drop_items(robot_pos, taken)
|
||||
end
|
||||
end
|
||||
function signs_bot.robot_add(base_pos, robot_pos, param2, num, slot)
|
||||
local target_pos = lib.next_pos(robot_pos, param2)
|
||||
local side = node_io.get_target_side(robot_pos, target_pos)
|
||||
local src_inv = minetest.get_inventory({type="node", pos=base_pos})
|
||||
local taken = lib.get_inv_items(src_inv, "main", slot, num)
|
||||
if taken then
|
||||
local node = lib.get_node_lvm(target_pos)
|
||||
local owner = M(base_pos):get_string("owner")
|
||||
local fake_player = lib.fake_player(owner)
|
||||
local left_over = node_io.put_item(target_pos, node, side, fake_player, taken)
|
||||
if left_over:get_count() > 0 then
|
||||
lib.drop_items(robot_pos, left_over)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -166,30 +108,6 @@ signs_bot.register_botcommand("add_item", {
|
|||
end,
|
||||
})
|
||||
|
||||
signs_bot.register_botcommand("add_fuel", {
|
||||
mod = "item",
|
||||
params = "<num> <slot>",
|
||||
description = I("Add <num> fuel items to a furnace like node\ntaken from the item inventory.\n"..
|
||||
"<slot> is the inventory slot (1..8)"),
|
||||
check = function(num, slot)
|
||||
num = tonumber(num or 1)
|
||||
if not num or num < 1 or num > 99 then
|
||||
return false
|
||||
end
|
||||
slot = tonumber(slot or 1)
|
||||
if not slot or slot < 1 or slot > 8 then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end,
|
||||
cmnd = function(base_pos, mem, num, slot)
|
||||
num = tonumber(num or 1)
|
||||
slot = tonumber(slot or 1)
|
||||
signs_bot.robot_add(base_pos, mem.robot_pos, mem.robot_param2, num, slot)
|
||||
return lib.DONE
|
||||
end,
|
||||
})
|
||||
|
||||
signs_bot.register_botcommand("pickup_items", {
|
||||
mod = "item",
|
||||
params = "<slot>",
|
||||
|
|
|
@ -162,6 +162,36 @@ signs_bot.register_botcommand("place_below", {
|
|||
end,
|
||||
})
|
||||
|
||||
local function place_item_above(base_pos, robot_pos, param2, slot)
|
||||
local pos1 = {x=robot_pos.x,y=robot_pos.y+1,z=robot_pos.z}
|
||||
if lib.not_protected(base_pos, pos1) and lib.is_air_like(pos1) then
|
||||
local src_inv, src_list = get_own_inv(base_pos)
|
||||
local taken = lib.get_inv_items(src_inv, src_list, slot, 1)
|
||||
if taken then
|
||||
local name = taken:get_name()
|
||||
local def = minetest.registered_nodes[name]
|
||||
if not def then return end
|
||||
minetest.set_node(pos1, {name=name, param2=param2})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
signs_bot.register_botcommand("place_above", {
|
||||
mod = "place",
|
||||
params = "<slot>",
|
||||
description = I("Place a block above the robot.\n"..
|
||||
"<slot> is the inventory slot (1..8)"),
|
||||
check = function(slot)
|
||||
slot = tonumber(slot or 1)
|
||||
return slot and slot > 0 and slot < 9
|
||||
end,
|
||||
cmnd = function(base_pos, mem, slot)
|
||||
slot = tonumber(slot or 1)
|
||||
place_item_above(base_pos, mem.robot_pos, mem.robot_param2, slot)
|
||||
return lib.DONE
|
||||
end,
|
||||
})
|
||||
|
||||
local function dig_item(base_pos, robot_pos, param2, slot, route, level)
|
||||
local pos1 = lib.dest_pos(robot_pos, param2, route)
|
||||
pos1.y = pos1.y + level
|
||||
|
@ -264,6 +294,32 @@ signs_bot.register_botcommand("dig_below", {
|
|||
end,
|
||||
})
|
||||
|
||||
local function dig_item_above(base_pos, robot_pos, param2, slot)
|
||||
local pos1 = {x=robot_pos.x,y=robot_pos.y+1,z=robot_pos.z}
|
||||
local node = lib.get_node_lvm(pos1)
|
||||
if lib.not_protected(base_pos, pos1) and lib.is_simple_node(node) then
|
||||
local dst_inv, dst_list = get_own_inv(base_pos)
|
||||
if lib.put_inv_items(dst_inv, dst_list, slot, ItemStack(node.name)) then
|
||||
minetest.remove_node(pos1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
signs_bot.register_botcommand("dig_above", {
|
||||
mod = "place",
|
||||
params = "<slot>",
|
||||
description = I("Dig the block above the robot.\n"..
|
||||
"<slot> is the inventory slot (1..8)"),
|
||||
check = function(slot)
|
||||
slot = tonumber(slot or 1)
|
||||
return slot and slot > 0 and slot < 9
|
||||
end,
|
||||
cmnd = function(base_pos, mem, slot)
|
||||
slot = tonumber(slot or 1)
|
||||
dig_item_above(base_pos, mem.robot_pos, mem.robot_param2, slot, 1)
|
||||
return lib.DONE
|
||||
end,
|
||||
})
|
||||
|
||||
local function rotate_item(base_pos, robot_pos, param2, route, level, steps)
|
||||
local pos1 = lib.dest_pos(robot_pos, param2, route)
|
||||
|
|
|
@ -2,3 +2,4 @@ default
|
|||
farming
|
||||
basic_materials
|
||||
tubelib2
|
||||
node_io
|
||||
|
|
1
init.lua
1
init.lua
|
@ -39,5 +39,6 @@ dofile(MP.."/nodes.lua")
|
|||
dofile(MP.."/bot_sensor.lua")
|
||||
dofile(MP.."/node_sensor.lua")
|
||||
dofile(MP.."/crop_sensor.lua")
|
||||
dofile(MP.."/chest.lua")
|
||||
|
||||
dofile(MP.."/tool.lua")
|
||||
|
|
6
lib.lua
6
lib.lua
|
@ -261,4 +261,10 @@ function signs_bot.lib.trim_text(text)
|
|||
return table.concat(tbl, "\n")
|
||||
end
|
||||
|
||||
function signs_bot.lib.fake_player(name)
|
||||
return {
|
||||
get_player_name = function() return name end,
|
||||
is_player = function() return false end,
|
||||
}
|
||||
end
|
||||
|
||||
|
|
2
mod.conf
2
mod.conf
|
@ -1,3 +1,3 @@
|
|||
name=signs_bot
|
||||
depends = default,farming,basic_materials,tubelib2
|
||||
depends = default,farming,basic_materials,tubelib2,node_io
|
||||
description = A robot controlled by signs
|
Binary file not shown.
After Width: | Height: | Size: 396 B |
Binary file not shown.
After Width: | Height: | Size: 318 B |
Binary file not shown.
After Width: | Height: | Size: 344 B |
Loading…
Reference in New Issue