mirror of
https://github.com/joe7575/techpack.git
synced 2025-01-14 01:21:40 +01:00
e8bad31a17
First draft of tubelib_addons3 (still WIP)
412 lines
12 KiB
Lua
412 lines
12 KiB
Lua
--[[
|
|
|
|
sl_robot
|
|
========
|
|
|
|
Copyright (C) 2018 Joachim Stolberg
|
|
|
|
LGPLv2.1+
|
|
See LICENSE.txt for more information
|
|
|
|
robot.lua:
|
|
|
|
]]--
|
|
|
|
local Face2Dir = {[0]=
|
|
{x=0, y=0, z=1},
|
|
{x=1, y=0, z=0},
|
|
{x=0, y=0, z=-1},
|
|
{x=-1, y=0, z=0},
|
|
{x=0, y=-1, z=0},
|
|
{x=0, y=1, z=0}
|
|
}
|
|
|
|
|
|
local Inventories = {
|
|
["tubelib:distributor"] = {take = "src", add = "src"},
|
|
["tubelib_addons1:harvester_base"] = {take = "main", add = "fuel"},
|
|
["tubelib_addons1:quarry"] = {take = "main", add = "fuel"},
|
|
["tubelib_addons1:quarry_active"] = {take = "main", add = "fuel"},
|
|
-- [""] = {take = "", add = ""},
|
|
-- [""] = {take = "", add = ""},
|
|
-- [""] = {take = "", add = ""},
|
|
}
|
|
|
|
local function inv_list_add(inv, name)
|
|
if Inventories[name] then
|
|
return inv:get_list(Inventories[name].add)
|
|
elseif inv:get_list("src") then
|
|
return inv:get_list("src")
|
|
elseif inv:get_list("main") then
|
|
return inv:get_list("main")
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local function inv_list_take(inv, name)
|
|
if Inventories[name] then
|
|
return inv:get_list(Inventories[name].take)
|
|
elseif inv:get_list("dst") then
|
|
return inv:get_list("dst")
|
|
elseif inv:get_list("main") then
|
|
return inv:get_list("main")
|
|
end
|
|
return nil
|
|
end
|
|
|
|
|
|
-- return the largest stack
|
|
local function peek(src_list)
|
|
local max_val = 0
|
|
local slot = nil
|
|
for idx,stack in ipairs(src_list) do
|
|
if stack:get_count() > max_val then
|
|
max_val = stack:get_count()
|
|
slot = idx
|
|
end
|
|
end
|
|
return slot
|
|
end
|
|
|
|
-- try to take the number of items from an inventory
|
|
local function take_num_items(src_list, num, dst_stack)
|
|
local slot = peek(src_list)
|
|
if slot then
|
|
local taken = src_list[slot]:take_item(num)
|
|
if dst_stack:item_fits(taken) then
|
|
dst_stack:add_item(taken)
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
function sl_robot.new_pos(pos, param2, step)
|
|
return vector.add(pos, vector.multiply(Face2Dir[param2], step))
|
|
end
|
|
|
|
-- use Voxel Manipulator to read the node
|
|
local function read_node_with_vm(pos)
|
|
local vm = VoxelManip()
|
|
local MinEdge, MaxEdge = vm:read_from_map(pos, pos)
|
|
local data = vm:get_data()
|
|
local area = VoxelArea:new({MinEdge = MinEdge, MaxEdge = MaxEdge})
|
|
return {
|
|
name = minetest.get_name_from_content_id(data[area:index(pos.x, pos.y, pos.z)])
|
|
}
|
|
end
|
|
|
|
-- check is posA == air-like and posB == solid and no player around
|
|
local function check_pos(posA, posB)
|
|
local nodeA = minetest.get_node_or_nil(posA) or read_node_with_vm(posA)
|
|
local nodeB = minetest.get_node_or_nil(posB) or read_node_with_vm(posB)
|
|
if not minetest.registered_nodes[nodeA.name].walkable and
|
|
minetest.registered_nodes[nodeB.name].walkable then
|
|
local objects = minetest.get_objects_inside_radius(posA, 1)
|
|
if #objects ~= 0 then
|
|
minetest.sound_play('sl_robot_go_away', {pos = posA})
|
|
return false
|
|
else
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function fake_player(name)
|
|
return {
|
|
get_player_name = function() return name end,
|
|
}
|
|
end
|
|
|
|
local function place_node(pos, owner, node_name, param2)
|
|
local under = {x=pos.x, y=pos.y-1, z=pos.z}
|
|
minetest.set_node(pos, {name=node_name, param2=param2})
|
|
local pointed_thing = {type="node", under=under, above=pos}
|
|
local itemstack = ItemStack(node_name)
|
|
pcall(minetest.after_place_node, pos, fake_player(owner), itemstack, pointed_thing)
|
|
end
|
|
|
|
local function remove_node(pos)
|
|
local node = minetest.get_node_or_nil(pos) or read_node_with_vm(pos)
|
|
if minetest.registered_nodes[node.name].after_dig_node then
|
|
return -- don't remove nodes with some intelligence
|
|
end
|
|
minetest.remove_node(pos)
|
|
return ItemStack(node.name)
|
|
end
|
|
|
|
|
|
function sl_robot.place_robot(pos1, pos2, param2, player_name)
|
|
if check_pos(pos1, pos2) then
|
|
minetest.set_node(pos1, {name = "sl_robot:robot", param2 = param2})
|
|
end
|
|
end
|
|
|
|
function sl_robot.remove_robot(pos)
|
|
local node = minetest.get_node_or_nil(pos) or read_node_with_vm(pos)
|
|
if node.name == "sl_robot:robot" then
|
|
minetest.remove_node(pos)
|
|
local pos1 = {x=pos.x, y=pos.y-1, z=pos.z}
|
|
node = minetest.get_node_or_nil(pos1) or read_node_with_vm(pos1)
|
|
if node.name == "sl_robot:robot_foot" or node.name == "sl_robot:robot_leg" then
|
|
minetest.remove_node(pos1)
|
|
pos1 = {x=pos.x, y=pos.y-2, z=pos.z}
|
|
node = minetest.get_node_or_nil(pos1) or read_node_with_vm(pos1)
|
|
if node.name == "sl_robot:robot_foot" then
|
|
minetest.remove_node(pos1)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Positions to check:
|
|
-- 3
|
|
-- [R]1
|
|
-- 4 2
|
|
-- 5
|
|
function sl_robot.move_robot(pos, param2, step)
|
|
local pos1 = sl_robot.new_pos(pos, param2, step)
|
|
local pos2 = {x=pos1.x, y=pos1.y-1, z=pos1.z}
|
|
local pos3 = {x=pos1.x, y=pos1.y+1, z=pos1.z}
|
|
local pos4 = {x=pos.x, y=pos.y-1, z=pos.z}
|
|
local pos5 = {x=pos.x, y=pos.y-2, z=pos.z}
|
|
local new_pos = nil
|
|
|
|
if check_pos(pos1, pos2) then -- one step forward
|
|
new_pos = pos1
|
|
elseif check_pos(pos3, pos1) then -- one step up
|
|
new_pos = {x=pos.x, y=pos.y+1, z=pos.z}
|
|
minetest.swap_node(pos, {name="sl_robot:robot_foot"})
|
|
minetest.set_node(new_pos, {name="sl_robot:robot", param2=param2})
|
|
minetest.sound_play('sl_robot_step', {pos = new_pos})
|
|
return new_pos
|
|
elseif check_pos(pos1, pos4) then -- one step forward
|
|
new_pos = pos1
|
|
elseif check_pos(pos4, pos5) then -- one step down
|
|
new_pos = pos4
|
|
else
|
|
return nil -- blocked
|
|
end
|
|
local node4 = minetest.get_node_or_nil(pos4) or read_node_with_vm(pos4)
|
|
if node4.name == "sl_robot:robot_foot" or node4.name == "sl_robot:robot_leg" then
|
|
minetest.remove_node(pos4)
|
|
local node5 = minetest.get_node_or_nil(pos5) or read_node_with_vm(pos5)
|
|
if node5.name == "sl_robot:robot_foot" then
|
|
minetest.remove_node(pos5)
|
|
end
|
|
end
|
|
minetest.remove_node(pos)
|
|
minetest.set_node(new_pos, {name="sl_robot:robot", param2=param2})
|
|
minetest.sound_play('sl_robot_step', {pos = new_pos})
|
|
return new_pos
|
|
end
|
|
|
|
function sl_robot.turn_robot(pos, param2, dir)
|
|
if dir == "R" then
|
|
param2 = (param2 + 1) % 4
|
|
else
|
|
param2 = (param2 + 3) % 4
|
|
end
|
|
minetest.swap_node(pos, {name="sl_robot:robot", param2=param2})
|
|
minetest.sound_play('sl_robot_step', {pos = pos, gain = 0.6})
|
|
return param2
|
|
end
|
|
|
|
-- Positions to check:
|
|
-- 1
|
|
-- [R]
|
|
-- 2
|
|
function sl_robot.robot_up(pos, param2)
|
|
local pos1 = {x=pos.x, y=pos.y+1, z=pos.z}
|
|
local pos2 = {x=pos.x, y=pos.y-1, z=pos.z}
|
|
if check_pos(pos1, pos2) then
|
|
local node = minetest.get_node_or_nil(pos2) or read_node_with_vm(pos2)
|
|
if node.name == "sl_robot:robot_foot" then
|
|
minetest.swap_node(pos, {name="sl_robot:robot_leg"})
|
|
else
|
|
minetest.swap_node(pos, {name="sl_robot:robot_foot"})
|
|
end
|
|
minetest.set_node(pos1, {name="sl_robot:robot", param2=param2})
|
|
minetest.sound_play('sl_robot_step', {pos = pos1})
|
|
return pos1
|
|
end
|
|
return nil
|
|
end
|
|
|
|
-- Positions to check:
|
|
-- [R]
|
|
-- 1
|
|
-- 2
|
|
-- 3
|
|
function sl_robot.robot_down(pos, param2)
|
|
local pos1 = {x=pos.x, y=pos.y-1, z=pos.z}
|
|
local pos2 = {x=pos.x, y=pos.y-2, z=pos.z}
|
|
local pos3 = {x=pos.x, y=pos.y-3, z=pos.z}
|
|
local node1 = minetest.get_node_or_nil(pos1) or read_node_with_vm(pos1)
|
|
if check_pos(pos1, pos2)
|
|
or (node1.name == "air" and check_pos(pos2, pos3))
|
|
or (node1.name == "sl_robot:robot_leg" or node1.name == "sl_robot:robot_foot") then
|
|
remove_node(pos)
|
|
minetest.set_node(pos1, {name="sl_robot:robot", param2=param2})
|
|
minetest.sound_play('sl_robot_step', {pos = pos1})
|
|
return pos1
|
|
end
|
|
return nil
|
|
end
|
|
|
|
-- take items from another inventory and put it into the own inventory slot
|
|
function sl_robot.robot_take(base_pos, robot_pos, param2, owner, num, slot)
|
|
local pos1 = sl_robot.new_pos(robot_pos, param2, 1)
|
|
if minetest.is_protected(pos1, owner) then
|
|
return
|
|
end
|
|
local node = minetest.get_node_or_nil(pos1) or read_node_with_vm(pos1)
|
|
local src_inv = minetest.get_inventory({type="node", pos=pos1})
|
|
local src_list = inv_list_take(src_inv, node.name)
|
|
local dst_inv = minetest.get_inventory({type="node", pos=base_pos})
|
|
local dst_list = dst_inv:get_list("main")
|
|
if src_list and take_num_items(src_list, num, dst_list[slot]) then
|
|
src_inv:set_list(listname, src_list)
|
|
dst_inv:set_list("main", dst_list)
|
|
end
|
|
end
|
|
|
|
function sl_robot.robot_add(base_pos, robot_pos, param2, owner, num, slot)
|
|
local pos1 = sl_robot.new_pos(robot_pos, param2, 1)
|
|
if minetest.is_protected(pos1, owner) then
|
|
return
|
|
end
|
|
local node = minetest.get_node_or_nil(pos1) or read_node_with_vm(pos1)
|
|
local dst_inv = minetest.get_inventory({type="node", pos=pos1})
|
|
local dst_list = inv_list_add(dst_inv, node.name)
|
|
local src_inv = minetest.get_inventory({type="node", pos=base_pos})
|
|
local src_list = src_inv:get_list("main")
|
|
if dst_list then
|
|
local taken = src_list[slot]:take_item(num)
|
|
if dst_inv:room_for_item(listname, taken) then
|
|
dst_inv:add_item(listname, taken)
|
|
src_inv:set_list("main", src_list)
|
|
end
|
|
end
|
|
end
|
|
|
|
function sl_robot.robot_place(base_pos, robot_pos, param2, owner, dir, slot)
|
|
local pos1
|
|
if dir == "U" then
|
|
pos1 = {x=robot_pos.x, y=robot_pos.y+1, z=robot_pos.z}
|
|
elseif dir == "D" then
|
|
pos1 = {x=robot_pos.x, y=robot_pos.y-1, z=robot_pos.z}
|
|
else
|
|
pos1 = sl_robot.new_pos(robot_pos, param2, 1)
|
|
end
|
|
if minetest.is_protected(pos1, owner) then
|
|
return
|
|
end
|
|
local src_inv = minetest.get_inventory({type="node", pos=base_pos})
|
|
local src_list = src_inv:get_list("main")
|
|
local taken = src_list[slot]:take_item(1)
|
|
if taken and taken:get_count() > 0 then
|
|
local node1 = minetest.get_node_or_nil(pos1) or read_node_with_vm(pos1)
|
|
if node1.name == "sl_robot:robot_leg" then
|
|
local pos2 = {x=pos1.x, y=pos1.y-1, z=pos1.z}
|
|
remove_node(pos2) -- remove foot
|
|
elseif node1.name == "sl_robot:robot_foot" then
|
|
remove_node(pos1)
|
|
elseif minetest.registered_nodes[node1.name].walkable then
|
|
return
|
|
end
|
|
place_node(pos1, owner, taken:get_name(), param2)
|
|
src_inv:set_list("main", src_list)
|
|
end
|
|
end
|
|
|
|
function sl_robot.robot_dig(base_pos, robot_pos, param2, owner, dir, slot)
|
|
local pos1
|
|
if dir == "U" then
|
|
pos1 = {x=robot_pos.x, y=robot_pos.y+1, z=robot_pos.z}
|
|
elseif dir == "D" then
|
|
pos1 = {x=robot_pos.x, y=robot_pos.y-1, z=robot_pos.z}
|
|
else
|
|
pos1 = sl_robot.new_pos(robot_pos, param2, 1)
|
|
end
|
|
if minetest.is_protected(pos1, owner) then
|
|
return
|
|
end
|
|
local item = remove_node(pos1)
|
|
if item then
|
|
local src_inv = minetest.get_inventory({type="node", pos=base_pos})
|
|
local src_list = src_inv:get_list("main")
|
|
src_list[slot]:add_item(item)
|
|
src_inv:set_list("main", src_list)
|
|
end
|
|
end
|
|
|
|
minetest.register_node("sl_robot:robot", {
|
|
description = "SaferLua Robot",
|
|
-- up, down, right, left, back, front
|
|
tiles = {
|
|
"sl_robot_robot_top.png",
|
|
"sl_robot_robot_bottom.png",
|
|
"sl_robot_robot_right.png",
|
|
"sl_robot_robot_left.png",
|
|
"sl_robot_robot_front.png",
|
|
"sl_robot_robot_back.png",
|
|
|
|
},
|
|
drawtype = "nodebox",
|
|
node_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
{ -5/16, 3/16, -5/16, 5/16, 8/16, 5/16},
|
|
{ -3/16, 2/16, -3/16, 3/16, 3/16, 3/16},
|
|
{ -6/16, -7/16, -6/16, 6/16, 2/16, 6/16},
|
|
{ -6/16, -8/16, -3/16, 6/16, -7/16, 3/16},
|
|
},
|
|
},
|
|
paramtype2 = "facedir",
|
|
paramtype = "light",
|
|
sunlight_propagates = true,
|
|
is_ground_content = false,
|
|
groups = {crumbly=0, not_in_creative_inventory = 1},
|
|
sounds = default.node_sound_metal_defaults(),
|
|
})
|
|
|
|
minetest.register_node("sl_robot:robot_leg", {
|
|
description = "SaferLua Robot",
|
|
tiles = {"sl_robot_robot.png^[transformR90]"},
|
|
drawtype = "nodebox",
|
|
node_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
{ -1/8, -4/8, -1/8, 1/8, 4/8, 1/8},
|
|
},
|
|
},
|
|
paramtype2 = "facedir",
|
|
paramtype = "light",
|
|
sunlight_propagates = true,
|
|
is_ground_content = false,
|
|
groups = {crumbly=0, not_in_creative_inventory = 1},
|
|
sounds = default.node_sound_metal_defaults(),
|
|
})
|
|
|
|
minetest.register_node("sl_robot:robot_foot", {
|
|
description = "SaferLua Robot",
|
|
tiles = {"sl_robot_robot.png^[transformR90]"},
|
|
drawtype = "nodebox",
|
|
node_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
{ -1/8, -4/8, -1/8, 1/8, 4/8, 1/8},
|
|
{ -2/8, -4/8, -2/8, 2/8, -3/8, 2/8},
|
|
},
|
|
},
|
|
paramtype2 = "facedir",
|
|
paramtype = "light",
|
|
sunlight_propagates = true,
|
|
is_ground_content = false,
|
|
groups = {crumbly=0, not_in_creative_inventory = 1},
|
|
sounds = default.node_sound_metal_defaults(),
|
|
})
|
|
|