v0.04 support for 'node_io' added, chest added, further commands added

master
Joachim Stolberg 2019-04-11 22:28:42 +02:00
parent 17f5564155
commit 3792590ea0
12 changed files with 254 additions and 112 deletions

View File

@ -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

View File

@ -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)

154
chest.lua Normal file
View File

@ -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(),
})

View File

@ -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)
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
if not lib.put_inv_items(dst_inv, dst_list, slot, 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
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)
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
if not put_items(dst_inv, dst_list, taken) then
lib.drop_items(robot_pos, taken)
end
end
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>",

View File

@ -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)

View File

@ -2,3 +2,4 @@ default
farming
basic_materials
tubelib2
node_io

View File

@ -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")

View File

@ -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

View File

@ -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