robot removed, will be released as extra mod
@ -1,466 +0,0 @@
|
|||||||
--[[
|
|
||||||
|
|
||||||
sl_robot
|
|
||||||
========
|
|
||||||
|
|
||||||
Copyright (C) 2018 Joachim Stolberg
|
|
||||||
|
|
||||||
LGPLv2.1+
|
|
||||||
See LICENSE.txt for more information
|
|
||||||
|
|
||||||
base.lua:
|
|
||||||
|
|
||||||
]]--
|
|
||||||
|
|
||||||
local FUEL_AMOUNT = 1000000
|
|
||||||
|
|
||||||
local sHELP = [[SaferLua Robot
|
|
||||||
|
|
||||||
The SaferLua Robot can be programmed in Lua by
|
|
||||||
means of this Robot Base.
|
|
||||||
The Robot needs Bio Fluel to operate.
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
local Cache = {}
|
|
||||||
|
|
||||||
local tCommands = {}
|
|
||||||
local tFunctions = {" Overview", " Data structures"}
|
|
||||||
local tHelpTexts = {[" Overview"] = sHELP, [" Data structures"] = safer_lua.DataStructHelp}
|
|
||||||
local sFunctionList = ""
|
|
||||||
local tFunctionIndex = {}
|
|
||||||
|
|
||||||
minetest.after(2, function()
|
|
||||||
sFunctionList = table.concat(tFunctions, ",")
|
|
||||||
for idx,key in ipairs(tFunctions) do
|
|
||||||
tFunctionIndex[key] = idx
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
local function output(pos, text)
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
text = meta:get_string("output") .. "\n" .. (text or "")
|
|
||||||
text = text:sub(-500,-1)
|
|
||||||
meta:set_string("output", text)
|
|
||||||
end
|
|
||||||
|
|
||||||
--
|
|
||||||
-- API functions for function/action registrations
|
|
||||||
--
|
|
||||||
function sl_robot.register_action(key, attr)
|
|
||||||
tCommands[key] = attr.cmnd
|
|
||||||
table.insert(tFunctions, " $"..key)
|
|
||||||
tHelpTexts[" $"..key] = attr.help
|
|
||||||
end
|
|
||||||
|
|
||||||
local function merge(dest, keys, values)
|
|
||||||
for idx,key in ipairs(keys) do
|
|
||||||
dest.env[key] = values[idx]
|
|
||||||
end
|
|
||||||
return dest
|
|
||||||
end
|
|
||||||
|
|
||||||
sl_robot.register_action("print", {
|
|
||||||
cmnd = function(self, text1, text2, text3)
|
|
||||||
local pos = self.meta.pos
|
|
||||||
text1 = tostring(text1 or "")
|
|
||||||
text2 = tostring(text2 or "")
|
|
||||||
text3 = tostring(text3 or "")
|
|
||||||
output(pos, text1..text2..text3)
|
|
||||||
end,
|
|
||||||
help = " $print(text,...)\n"..
|
|
||||||
" Send a text line to the output window.\n"..
|
|
||||||
" The function accepts up to 3 text strings\n"..
|
|
||||||
' e.g. $print("Hello ", name, " !")'
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
|
||||||
if minetest.is_protected(pos, player:get_player_name()) then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
if meta:get_int("state") == tubelib.RUNNING then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
local inv = meta:get_inventory()
|
|
||||||
if listname == "main" then
|
|
||||||
return stack:get_count()
|
|
||||||
elseif listname == "fuel" and stack:get_name() == "tubelib_addons1:biofuel" then
|
|
||||||
return stack:get_count()
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
|
|
||||||
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
|
|
||||||
if minetest.is_protected(pos, player:get_player_name()) then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
if meta:get_int("state") == tubelib.RUNNING then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
return stack:get_count()
|
|
||||||
end
|
|
||||||
|
|
||||||
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
|
||||||
if minetest.is_protected(pos, player:get_player_name()) then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
if meta:get_int("state") == tubelib.RUNNING then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
return count
|
|
||||||
end
|
|
||||||
|
|
||||||
local function formspec1(meta)
|
|
||||||
local running = meta:get_int("state") == tubelib.RUNNING
|
|
||||||
local cmnd = running and "stop;Stop" or "start;Start"
|
|
||||||
local init = meta:get_string("init")
|
|
||||||
local fuel = math.floor((meta:get_int("fuel") * 100.0) / FUEL_AMOUNT)
|
|
||||||
init = minetest.formspec_escape(init)
|
|
||||||
return "size[10,8]"..
|
|
||||||
default.gui_bg..
|
|
||||||
default.gui_bg_img..
|
|
||||||
default.gui_slots..
|
|
||||||
"tabheader[0,0;tab;Inv,init,loop,outp,notes,help;1;;true]"..
|
|
||||||
"label[5.3,0.5;1]label[6.3,0.5;2]label[7.3,0.5;3]label[8.3,0.5;4]"..
|
|
||||||
"list[context;main;5,1;4,2;]"..
|
|
||||||
"label[5.3,3;5]label[6.3,3;6]label[7.3,3;7]label[8.3,3;8]"..
|
|
||||||
"list[context;fuel;1,1.7;1,1;]"..
|
|
||||||
"item_image[1,1.7;1,1;tubelib_addons1:biofuel]"..
|
|
||||||
"image[2,1.7;1,1;default_furnace_fire_bg.png^[lowpart:"..
|
|
||||||
(fuel)..":default_furnace_fire_fg.png]"..
|
|
||||||
"list[current_player;main;1,4;8,4;]"..
|
|
||||||
"listring[context;main]"..
|
|
||||||
"listring[current_player;main]"
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
local function formspec2(meta)
|
|
||||||
local running = meta:get_int("state") == tubelib.RUNNING
|
|
||||||
local cmnd = running and "stop;Stop" or "start;Start"
|
|
||||||
local init = meta:get_string("init")
|
|
||||||
init = minetest.formspec_escape(init)
|
|
||||||
return "size[10,8]"..
|
|
||||||
default.gui_bg..
|
|
||||||
default.gui_bg_img..
|
|
||||||
default.gui_slots..
|
|
||||||
"tabheader[0,0;tab;Inv,init,loop,outp,notes,help;2;;true]"..
|
|
||||||
"textarea[0.3,0.2;10,8.3;init;function init();"..init.."]"..
|
|
||||||
"label[0,7.3;end]"..
|
|
||||||
"button_exit[4.4,7.5;1.8,1;cancel;Cancel]"..
|
|
||||||
"button[6.3,7.5;1.8,1;save;Save]"..
|
|
||||||
"button[8.2,7.5;1.8,1;"..cmnd.."]"
|
|
||||||
end
|
|
||||||
|
|
||||||
local function formspec3(meta)
|
|
||||||
local running = meta:get_int("state") == tubelib.RUNNING
|
|
||||||
local cmnd = running and "stop;Stop" or "start;Start"
|
|
||||||
local loop = meta:get_string("loop")
|
|
||||||
loop = minetest.formspec_escape(loop)
|
|
||||||
return "size[10,8]"..
|
|
||||||
default.gui_bg..
|
|
||||||
default.gui_bg_img..
|
|
||||||
default.gui_slots..
|
|
||||||
"tabheader[0,0;tab;Inv,init,loop,outp,notes,help;3;;true]"..
|
|
||||||
"textarea[0.3,0.2;10,8.3;loop;function loop(ticks, elapsed);"..loop.."]"..
|
|
||||||
"label[0,7.3;end]"..
|
|
||||||
"button_exit[4.4,7.5;1.8,1;cancel;Cancel]"..
|
|
||||||
"button[6.3,7.5;1.8,1;save;Save]"..
|
|
||||||
"button[8.2,7.5;1.8,1;"..cmnd.."]"
|
|
||||||
end
|
|
||||||
|
|
||||||
local function formspec4(meta)
|
|
||||||
local running = meta:get_int("state") == tubelib.RUNNING
|
|
||||||
local cmnd = running and "stop;Stop" or "start;Start"
|
|
||||||
local output = meta:get_string("output")
|
|
||||||
output = minetest.formspec_escape(output)
|
|
||||||
return "size[10,8]"..
|
|
||||||
default.gui_bg..
|
|
||||||
default.gui_bg_img..
|
|
||||||
default.gui_slots..
|
|
||||||
"tabheader[0,0;tab;Inv,init,loop,outp,notes,help;4;;true]"..
|
|
||||||
"textarea[0.3,0.2;10,8.3;help;Output:;"..output.."]"..
|
|
||||||
"button[4.4,7.5;1.8,1;clear;Clear]"..
|
|
||||||
"button[6.3,7.5;1.8,1;update;Update]"..
|
|
||||||
"button[8.2,7.5;1.8,1;"..cmnd.."]"
|
|
||||||
end
|
|
||||||
|
|
||||||
local function formspec5(meta)
|
|
||||||
local notes = meta:get_string("notes")
|
|
||||||
notes = minetest.formspec_escape(notes)
|
|
||||||
return "size[10,8]"..
|
|
||||||
default.gui_bg..
|
|
||||||
default.gui_bg_img..
|
|
||||||
default.gui_slots..
|
|
||||||
"tabheader[0,0;tab;Inv,init,loop,outp,notes,help;5;;true]"..
|
|
||||||
"textarea[0.3,0.2;10,8.3;notes;Notepad:;"..notes.."]"..
|
|
||||||
"button_exit[6.3,7.5;1.8,1;cancel;Cancel]"..
|
|
||||||
"button[8.2,7.5;1.8,1;save;Save]"
|
|
||||||
end
|
|
||||||
|
|
||||||
local function formspec6(items, pos, text)
|
|
||||||
text = minetest.formspec_escape(text)
|
|
||||||
return "size[10,8]"..
|
|
||||||
default.gui_bg..
|
|
||||||
default.gui_bg_img..
|
|
||||||
default.gui_slots..
|
|
||||||
"tabheader[0,0;tab;Inv,init,loop,outp,notes,help;6;;true]"..
|
|
||||||
"label[0,-0.2;Functions:]"..
|
|
||||||
"dropdown[0.3,0.2;10,8.3;functions;"..items..";"..pos.."]"..
|
|
||||||
"textarea[0.3,1.3;10,8;help;Help:;"..text.."]"
|
|
||||||
end
|
|
||||||
|
|
||||||
local function error(pos, err)
|
|
||||||
output(pos, err)
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
local number = meta:get_string("number")
|
|
||||||
meta:set_string("formspec", formspec4(meta))
|
|
||||||
meta:set_string("infotext", "Robot Base "..number..": error")
|
|
||||||
meta:set_int("state", tubelib.STOPPED)
|
|
||||||
minetest.get_node_timer(pos):stop()
|
|
||||||
local robot_pos = minetest.string_to_pos(meta:get_string("robot_pos"))
|
|
||||||
minetest.sound_play('sl_robot_error', {pos = robot_pos})
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- check the fuel level and return false if empty
|
|
||||||
local function check_fuel(pos, meta)
|
|
||||||
local fuel = meta:get_int("fuel")
|
|
||||||
if fuel <= 0 then
|
|
||||||
if tubelib.get_this_item(meta, "fuel", 1) == nil then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
fuel = FUEL_AMOUNT
|
|
||||||
end
|
|
||||||
meta:set_int("fuel", fuel)
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
local function reset_robot(pos, meta)
|
|
||||||
local robot_pos = minetest.string_to_pos(meta:get_string("robot_pos"))
|
|
||||||
minetest.log("action", "[robby] reset_robot "..meta:get_string("robot_pos"))
|
|
||||||
|
|
||||||
if robot_pos then
|
|
||||||
minetest.after(5, minetest.remove_node, table.copy(robot_pos))
|
|
||||||
end
|
|
||||||
|
|
||||||
local param2 = (minetest.get_node(pos).param2 + 1) % 4
|
|
||||||
robot_pos = sl_robot.new_pos(pos, param2, 1)
|
|
||||||
local pos_below = {x=robot_pos.x, y=robot_pos.y-1, z=robot_pos.z}
|
|
||||||
|
|
||||||
meta:set_string("robot_pos", minetest.pos_to_string(robot_pos))
|
|
||||||
meta:set_int("robot_param2", param2)
|
|
||||||
sl_robot.place_robot(robot_pos, pos_below, param2, nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function compile(pos, meta, number)
|
|
||||||
local init = meta:get_string("init")
|
|
||||||
local loop = meta:get_string("loop")
|
|
||||||
local owner = meta:get_string("owner")
|
|
||||||
local env = table.copy(tCommands)
|
|
||||||
reset_robot(pos, meta)
|
|
||||||
env.meta = {pos=pos, owner=owner, number=number, error=error}
|
|
||||||
local co, code = safer_lua.co_create(pos, init, loop, env, error)
|
|
||||||
|
|
||||||
if co then
|
|
||||||
Cache[number] = {code=code, co=co}
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local function start_robot(pos)
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
local number = meta:get_string("number")
|
|
||||||
|
|
||||||
meta:set_string("output", "<press update>")
|
|
||||||
|
|
||||||
if not check_fuel(pos, meta) then
|
|
||||||
local number = meta:get_string("number")
|
|
||||||
meta:set_string("infotext", "Robot Base "..number..": no fuel")
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
if compile(pos, meta, number) then
|
|
||||||
meta:set_int("state", tubelib.RUNNING)
|
|
||||||
meta:set_string("formspec", formspec4(meta))
|
|
||||||
minetest.get_node_timer(pos):start(1)
|
|
||||||
meta:set_string("infotext", "Robot Base "..number..": running")
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local function stop_robot(pos)
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
local number = meta:get_string("number")
|
|
||||||
local robot_pos = minetest.string_to_pos(meta:get_string("robot_pos"))
|
|
||||||
meta:set_int("state", tubelib.STOPPED)
|
|
||||||
minetest.get_node_timer(pos):stop()
|
|
||||||
meta:set_string("infotext", "Robot Base "..number..": stopped")
|
|
||||||
meta:set_string("formspec", formspec3(meta))
|
|
||||||
if Cache[number] then
|
|
||||||
local code = Cache[number].code
|
|
||||||
local env = getfenv(code)
|
|
||||||
sl_robot.remove_robot(robot_pos)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function call_loop(pos, meta, elapsed)
|
|
||||||
local t = minetest.get_us_time()
|
|
||||||
local number = meta:get_string("number")
|
|
||||||
if Cache[number] or compile(pos, meta, number) then
|
|
||||||
local cpu = meta:get_int("cpu") or 0
|
|
||||||
local code = Cache[number].code
|
|
||||||
local co = Cache[number].co
|
|
||||||
local res = safer_lua.co_resume(pos, co, code, error)
|
|
||||||
if res then
|
|
||||||
t = minetest.get_us_time() - t
|
|
||||||
cpu = math.floor(((cpu * 20) + t) / 21)
|
|
||||||
meta:set_int("cpu", cpu)
|
|
||||||
local robot_pos = meta:get_string("robot_pos")
|
|
||||||
meta:set_string("infotext", "Robot Base "..number..": running ("..cpu.."us) "..robot_pos)
|
|
||||||
meta:set_int("fuel", meta:get_int("fuel") - t)
|
|
||||||
end
|
|
||||||
return res
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local function on_timer(pos, elapsed)
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
|
|
||||||
--so some maintenance every 10 cycles
|
|
||||||
local ticks = (meta:get_int("ticks") or 0) + 1
|
|
||||||
meta:set_int("ticks", ticks)
|
|
||||||
if (ticks % 100) == 0 then
|
|
||||||
if not check_fuel(pos, meta) then
|
|
||||||
local number = meta:get_string("number")
|
|
||||||
meta:set_string("infotext", "Robot Base "..number..": no fuel")
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return call_loop(pos, meta, elapsed)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function on_receive_fields(pos, formname, fields, player)
|
|
||||||
if minetest.is_protected(pos, player:get_player_name()) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
|
|
||||||
--print(dump(fields))
|
|
||||||
if fields.cancel == nil then
|
|
||||||
if fields.init then
|
|
||||||
meta:set_string("init", fields.init)
|
|
||||||
meta:set_string("formspec", formspec2(meta))
|
|
||||||
elseif fields.loop then
|
|
||||||
meta:set_string("loop", fields.loop)
|
|
||||||
meta:set_string("formspec", formspec3(meta))
|
|
||||||
elseif fields.notes then
|
|
||||||
meta:set_string("notes", fields.notes)
|
|
||||||
meta:set_string("formspec", formspec5(meta))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if fields.update then
|
|
||||||
meta:set_string("formspec", formspec4(meta))
|
|
||||||
elseif fields.clear then
|
|
||||||
meta:set_string("output", "<press update>")
|
|
||||||
meta:set_string("formspec", formspec4(meta))
|
|
||||||
elseif fields.tab == "1" then
|
|
||||||
meta:set_string("formspec", formspec1(meta))
|
|
||||||
elseif fields.tab == "2" then
|
|
||||||
meta:set_string("formspec", formspec2(meta))
|
|
||||||
elseif fields.tab == "3" then
|
|
||||||
meta:set_string("formspec", formspec3(meta))
|
|
||||||
elseif fields.tab == "4" then
|
|
||||||
meta:set_string("formspec", formspec4(meta))
|
|
||||||
elseif fields.tab == "5" then
|
|
||||||
meta:set_string("formspec", formspec5(meta))
|
|
||||||
elseif fields.tab == "6" then
|
|
||||||
meta:set_string("formspec", formspec6(sFunctionList, 1, sHELP))
|
|
||||||
elseif fields.start == "Start" then
|
|
||||||
start_robot(pos)
|
|
||||||
minetest.log("action", player:get_player_name() ..
|
|
||||||
" starts the sl_robot at ".. minetest.pos_to_string(pos))
|
|
||||||
elseif fields.stop == "Stop" then
|
|
||||||
stop_robot(pos)
|
|
||||||
elseif fields.functions then
|
|
||||||
local key = fields.functions
|
|
||||||
local text = tHelpTexts[key] or ""
|
|
||||||
local pos = tFunctionIndex[key] or 1
|
|
||||||
meta:set_string("formspec", formspec6(sFunctionList, pos, text))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.register_node("sl_robot:base", {
|
|
||||||
description = "SaferLua Robot Base",
|
|
||||||
stack_max = 1,
|
|
||||||
tiles = {
|
|
||||||
-- up, down, right, left, back, front
|
|
||||||
'sl_robot_base_top.png',
|
|
||||||
'sl_robot_base_top.png',
|
|
||||||
'sl_robot_base_right.png',
|
|
||||||
'sl_robot_base_left.png',
|
|
||||||
'sl_robot_base_front.png',
|
|
||||||
'sl_robot_base_front.png',
|
|
||||||
},
|
|
||||||
|
|
||||||
on_construct = function(pos)
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
local inv = meta:get_inventory()
|
|
||||||
inv:set_size('main', 8)
|
|
||||||
inv:set_size('fuel', 1)
|
|
||||||
end,
|
|
||||||
|
|
||||||
after_place_node = function(pos, placer)
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
local number = tubelib.add_node(pos, "sl_robot:base")
|
|
||||||
meta:set_string("owner", placer:get_player_name())
|
|
||||||
meta:set_string("number", number)
|
|
||||||
meta:set_int("state", tubelib.STOPPED)
|
|
||||||
meta:set_string("init", "-- called only once")
|
|
||||||
meta:set_string("loop", "-- called cyclically")
|
|
||||||
meta:set_string("notes", "For your notes / snippets")
|
|
||||||
meta:set_string("formspec", formspec1(meta))
|
|
||||||
meta:set_string("infotext", "Robot Base "..number..": stopped")
|
|
||||||
end,
|
|
||||||
|
|
||||||
on_receive_fields = on_receive_fields,
|
|
||||||
|
|
||||||
on_dig = function(pos, node, puncher, pointed_thing)
|
|
||||||
if minetest.is_protected(pos, puncher:get_player_name()) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
if meta:get_int("state") == tubelib.RUNNING then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
minetest.node_dig(pos, node, puncher, pointed_thing)
|
|
||||||
tubelib.remove_node(pos)
|
|
||||||
end,
|
|
||||||
|
|
||||||
on_timer = on_timer,
|
|
||||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
|
||||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
|
||||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
|
||||||
|
|
||||||
paramtype = "light",
|
|
||||||
sunlight_propagates = true,
|
|
||||||
paramtype2 = "facedir",
|
|
||||||
is_ground_content = false,
|
|
||||||
groups = {cracky = 1},
|
|
||||||
sounds = default.node_sound_metal_defaults(),
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
--minetest.register_craft({
|
|
||||||
-- type = "shapeless",
|
|
||||||
-- output = "sl_robot:robot",
|
|
||||||
-- recipe = {"smartline:controller"}
|
|
||||||
--})
|
|
||||||
|
|
@ -1,226 +0,0 @@
|
|||||||
--[[
|
|
||||||
|
|
||||||
sl_robot
|
|
||||||
========
|
|
||||||
|
|
||||||
Copyright (C) 2018 Joachim Stolberg
|
|
||||||
|
|
||||||
LGPLv2.1+
|
|
||||||
See LICENSE.txt for more information
|
|
||||||
|
|
||||||
commands.lua:
|
|
||||||
|
|
||||||
Register all robot commands
|
|
||||||
|
|
||||||
]]--
|
|
||||||
|
|
||||||
-- constrict value to the given range
|
|
||||||
local function range(val, min, max)
|
|
||||||
val = tonumber(val)
|
|
||||||
if val < min then return min end
|
|
||||||
if val > max then return max end
|
|
||||||
return val
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
sl_robot.register_action("get_ms_time", {
|
|
||||||
cmnd = function(self)
|
|
||||||
return math.floor(minetest.get_us_time() / 1000)
|
|
||||||
end,
|
|
||||||
help = "$get_ms_time()\n"..
|
|
||||||
" returns time with millisecond precision."
|
|
||||||
})
|
|
||||||
|
|
||||||
sl_robot.register_action("forward", {
|
|
||||||
cmnd = function(self, steps)
|
|
||||||
steps = range(steps, 1, 100)
|
|
||||||
local idx = 1
|
|
||||||
while idx <= steps do
|
|
||||||
local meta = minetest.get_meta(self.meta.pos)
|
|
||||||
local robot_pos = minetest.string_to_pos(meta:get_string("robot_pos"))
|
|
||||||
local robot_param2 = meta:get_int("robot_param2")
|
|
||||||
local new_pos = sl_robot.move_robot(robot_pos, robot_param2, 1)
|
|
||||||
if new_pos then -- not blocked?
|
|
||||||
if new_pos.y == robot_pos.y then -- forward move?
|
|
||||||
idx = idx + 1
|
|
||||||
end
|
|
||||||
meta:set_string("robot_pos", minetest.pos_to_string(new_pos))
|
|
||||||
--minetest.log("action", "[robby] forward "..meta:get_string("robot_pos"))
|
|
||||||
end
|
|
||||||
coroutine.yield()
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
help = " go one (or more) steps forward\n"..
|
|
||||||
" Syntax: $forward(<steps>)\n"..
|
|
||||||
" Example: $forward(4)"
|
|
||||||
})
|
|
||||||
|
|
||||||
sl_robot.register_action("backward", {
|
|
||||||
cmnd = function(self, steps)
|
|
||||||
steps = range(steps, 1, 100)
|
|
||||||
local idx = 1
|
|
||||||
while idx <= steps do
|
|
||||||
local meta = minetest.get_meta(self.meta.pos)
|
|
||||||
local robot_pos = minetest.string_to_pos(meta:get_string("robot_pos"))
|
|
||||||
local robot_param2 = meta:get_int("robot_param2")
|
|
||||||
local new_pos = sl_robot.move_robot(robot_pos, robot_param2, -1)
|
|
||||||
if new_pos then -- not blocked?
|
|
||||||
if new_pos.y == robot_pos.y then -- forward move?
|
|
||||||
idx = idx + 1
|
|
||||||
end
|
|
||||||
meta:set_string("robot_pos", minetest.pos_to_string(new_pos))
|
|
||||||
--minetest.log("action", "[robby] forward "..meta:get_string("robot_pos"))
|
|
||||||
end
|
|
||||||
coroutine.yield()
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
help = " go one (or more) steps backward\n"..
|
|
||||||
" Syntax: $backward(<steps>)\n"..
|
|
||||||
" Example: $backward(4)"
|
|
||||||
})
|
|
||||||
|
|
||||||
sl_robot.register_action("left", {
|
|
||||||
cmnd = function(self)
|
|
||||||
local meta = minetest.get_meta(self.meta.pos)
|
|
||||||
local robot_pos = minetest.string_to_pos(meta:get_string("robot_pos"))
|
|
||||||
local robot_param2 = meta:get_int("robot_param2")
|
|
||||||
robot_param2 = sl_robot.turn_robot(robot_pos, robot_param2, "L")
|
|
||||||
meta:set_int("robot_param2", robot_param2)
|
|
||||||
--minetest.log("action", "[robby] left "..meta:get_string("robot_pos"))
|
|
||||||
coroutine.yield()
|
|
||||||
end,
|
|
||||||
help = " turn left\n"..
|
|
||||||
" Example: $left()"
|
|
||||||
})
|
|
||||||
|
|
||||||
sl_robot.register_action("right", {
|
|
||||||
cmnd = function(self)
|
|
||||||
local meta = minetest.get_meta(self.meta.pos)
|
|
||||||
local robot_pos = minetest.string_to_pos(meta:get_string("robot_pos"))
|
|
||||||
local robot_param2 = meta:get_int("robot_param2")
|
|
||||||
robot_param2 = sl_robot.turn_robot(robot_pos, robot_param2, "R")
|
|
||||||
meta:set_int("robot_param2", robot_param2)
|
|
||||||
--minetest.log("action", "[robby] right "..meta:get_string("robot_pos"))
|
|
||||||
coroutine.yield()
|
|
||||||
end,
|
|
||||||
help = " turn right\n"..
|
|
||||||
" Example: $right()"
|
|
||||||
})
|
|
||||||
|
|
||||||
sl_robot.register_action("up", {
|
|
||||||
cmnd = function(self)
|
|
||||||
local meta = minetest.get_meta(self.meta.pos)
|
|
||||||
local robot_pos = minetest.string_to_pos(meta:get_string("robot_pos"))
|
|
||||||
local robot_param2 = meta:get_int("robot_param2")
|
|
||||||
local new_pos
|
|
||||||
while true do
|
|
||||||
new_pos = sl_robot.robot_up(robot_pos, robot_param2)
|
|
||||||
if new_pos then break end
|
|
||||||
coroutine.yield()
|
|
||||||
end
|
|
||||||
meta:set_string("robot_pos", minetest.pos_to_string(new_pos))
|
|
||||||
--minetest.log("action", "[robby] up "..meta:get_string("robot_pos"))
|
|
||||||
coroutine.yield()
|
|
||||||
end,
|
|
||||||
help = " go one step up (2 steps max.)\n"..
|
|
||||||
" Example: $up()"
|
|
||||||
})
|
|
||||||
|
|
||||||
sl_robot.register_action("down", {
|
|
||||||
cmnd = function(self)
|
|
||||||
local meta = minetest.get_meta(self.meta.pos)
|
|
||||||
local robot_pos = minetest.string_to_pos(meta:get_string("robot_pos"))
|
|
||||||
local robot_param2 = meta:get_int("robot_param2")
|
|
||||||
local new_pos
|
|
||||||
while true do
|
|
||||||
new_pos = sl_robot.robot_down(robot_pos, robot_param2)
|
|
||||||
if new_pos then break end
|
|
||||||
coroutine.yield()
|
|
||||||
end
|
|
||||||
meta:set_string("robot_pos", minetest.pos_to_string(new_pos))
|
|
||||||
--minetest.log("action", "[robby] down "..meta:get_string("robot_pos"))
|
|
||||||
coroutine.yield()
|
|
||||||
end,
|
|
||||||
help = " go down again (2 steps max.)\n"..
|
|
||||||
" you have to go up before\n"..
|
|
||||||
" Example: $down()"
|
|
||||||
})
|
|
||||||
|
|
||||||
sl_robot.register_action("take", {
|
|
||||||
cmnd = function(self, num, slot)
|
|
||||||
num = range(num, 1, 99)
|
|
||||||
slot = range(slot, 1, 8)
|
|
||||||
local meta = minetest.get_meta(self.meta.pos)
|
|
||||||
local robot_pos = minetest.string_to_pos(meta:get_string("robot_pos"))
|
|
||||||
local robot_param2 = meta:get_int("robot_param2")
|
|
||||||
sl_robot.robot_take(self.meta.pos, robot_pos, robot_param2, self.meta.owner, num, slot)
|
|
||||||
minetest.log("action", "[robby] take "..meta:get_string("robot_pos"))
|
|
||||||
coroutine.yield()
|
|
||||||
end,
|
|
||||||
help = " take 'num' items from a chest or a node\n"..
|
|
||||||
" with an inventory in front of the robot\n"..
|
|
||||||
" and put the item into the own inventory,\n"..
|
|
||||||
" specified by 'slot'.\n"..
|
|
||||||
" Syntax: $take(num, slot)\n"..
|
|
||||||
" Example: $take(99, 1)"
|
|
||||||
})
|
|
||||||
|
|
||||||
sl_robot.register_action("add", {
|
|
||||||
cmnd = function(self, num, slot)
|
|
||||||
num = range(num, 1, 99)
|
|
||||||
slot = range(slot, 1, 8)
|
|
||||||
local meta = minetest.get_meta(self.meta.pos)
|
|
||||||
local robot_pos = minetest.string_to_pos(meta:get_string("robot_pos"))
|
|
||||||
local robot_param2 = meta:get_int("robot_param2")
|
|
||||||
sl_robot.robot_add(self.meta.pos, robot_pos, robot_param2, self.meta.owner, num, slot)
|
|
||||||
minetest.log("action", "[robby] add "..meta:get_string("robot_pos"))
|
|
||||||
coroutine.yield()
|
|
||||||
end,
|
|
||||||
help = " take 'num' items from the own inventory\n"..
|
|
||||||
" specified by 'slot' and add it to the nodes\n"..
|
|
||||||
" inventory in front of the robot.\n"..
|
|
||||||
" Syntax: $add(num, slot)\n"..
|
|
||||||
" Example: $add(99, 1)"
|
|
||||||
})
|
|
||||||
|
|
||||||
sl_robot.register_action("place", {
|
|
||||||
cmnd = function(self, slot, dir)
|
|
||||||
slot = range(slot, 1, 8)
|
|
||||||
local meta = minetest.get_meta(self.meta.pos)
|
|
||||||
local robot_pos = minetest.string_to_pos(meta:get_string("robot_pos"))
|
|
||||||
local robot_param2 = meta:get_int("robot_param2")
|
|
||||||
sl_robot.robot_place(self.meta.pos, robot_pos, robot_param2, self.meta.owner, dir, slot)
|
|
||||||
minetest.log("action", "[robby] place "..meta:get_string("robot_pos"))
|
|
||||||
coroutine.yield()
|
|
||||||
end,
|
|
||||||
help = " places an node in front of, above (up),\n"..
|
|
||||||
" or below (down) the robot. The node is taken\n"..
|
|
||||||
" from the own inventory, specified by 'slot'.\n"..
|
|
||||||
' Examples: $place(1) $place(1, "U"), $place(1, "D")'
|
|
||||||
})
|
|
||||||
|
|
||||||
sl_robot.register_action("dig", {
|
|
||||||
cmnd = function(self, slot, dir)
|
|
||||||
slot = range(slot, 1, 8)
|
|
||||||
local meta = minetest.get_meta(self.meta.pos)
|
|
||||||
local robot_pos = minetest.string_to_pos(meta:get_string("robot_pos"))
|
|
||||||
local robot_param2 = meta:get_int("robot_param2")
|
|
||||||
sl_robot.robot_dig(self.meta.pos, robot_pos, robot_param2, self.meta.owner, dir, slot)
|
|
||||||
minetest.log("action", "[robby] dig "..meta:get_string("robot_pos"))
|
|
||||||
coroutine.yield()
|
|
||||||
end,
|
|
||||||
help = " dig an node in front of, above (up),\n"..
|
|
||||||
" or below (down) the robot. The node is placed\n"..
|
|
||||||
" into the own inventory, specified by 'slot'.\n"..
|
|
||||||
' Examples: $dig(1) $dig(1, "U"), $dig(1, "D")'
|
|
||||||
})
|
|
||||||
|
|
||||||
sl_robot.register_action("stop", {
|
|
||||||
cmnd = function(self)
|
|
||||||
while true do
|
|
||||||
coroutine.yield()
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
help = "tbd"
|
|
||||||
})
|
|
@ -1,4 +0,0 @@
|
|||||||
default
|
|
||||||
tubelib
|
|
||||||
safer_lua
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
|||||||
SaferLua Robot - a simple robot to be programmed in LUA
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
|||||||
--[[
|
|
||||||
|
|
||||||
sl_robot
|
|
||||||
========
|
|
||||||
|
|
||||||
Copyright (C) 2018 Joachim Stolberg
|
|
||||||
|
|
||||||
LGPLv2.1+
|
|
||||||
See LICENSE.txt for more information
|
|
||||||
|
|
||||||
]]--
|
|
||||||
|
|
||||||
sl_robot = {}
|
|
||||||
|
|
||||||
--dofile(minetest.get_modpath("sl_robot") .. "/config.lua")
|
|
||||||
dofile(minetest.get_modpath("sl_robot") .. "/robot.lua")
|
|
||||||
dofile(minetest.get_modpath("sl_robot") .. "/base.lua")
|
|
||||||
dofile(minetest.get_modpath("sl_robot") .. "/commands.lua")
|
|
||||||
dofile(minetest.get_modpath("sl_robot") .. "/run_cmnd.lua")
|
|
@ -1 +0,0 @@
|
|||||||
name=sl_robot
|
|
@ -1,20 +0,0 @@
|
|||||||
SaferLua Robot [sl_robot]
|
|
||||||
=========================
|
|
||||||
|
|
||||||
## THIS IS WORK IN PROGRESS!
|
|
||||||
|
|
||||||
A tubelib compatible robot to be programmed in LUA
|
|
||||||
|
|
||||||
The mod uses SaferLua [safer_lua] as Lua sandbox for safe and secure code execution.
|
|
||||||
|
|
||||||
|
|
||||||
### License
|
|
||||||
Copyright (C) 2018 Joachim Stolberg
|
|
||||||
Code: Licensed under the GNU LGPL version 2.1 or later. See LICENSE.txt
|
|
||||||
|
|
||||||
|
|
||||||
### Dependencies
|
|
||||||
tubelib, safer_lua
|
|
||||||
|
|
||||||
### History
|
|
||||||
- 2018-07-06 v0.01 * first draft
|
|
@ -1,411 +0,0 @@
|
|||||||
--[[
|
|
||||||
|
|
||||||
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(),
|
|
||||||
})
|
|
||||||
|
|
@ -1,122 +0,0 @@
|
|||||||
--[[
|
|
||||||
|
|
||||||
sl_robot
|
|
||||||
========
|
|
||||||
|
|
||||||
Copyright (C) 2018 Joachim Stolberg
|
|
||||||
|
|
||||||
LGPLv2.1+
|
|
||||||
See LICENSE.txt for more information
|
|
||||||
|
|
||||||
run_cmnd.lua:
|
|
||||||
|
|
||||||
Register the run command
|
|
||||||
|
|
||||||
]]--
|
|
||||||
|
|
||||||
local function Reverse(arr)
|
|
||||||
local i, j = 1, #arr
|
|
||||||
|
|
||||||
while i < j do
|
|
||||||
arr[i], arr[j] = arr[j], arr[i]
|
|
||||||
|
|
||||||
i = i + 1
|
|
||||||
j = j - 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local switch = {
|
|
||||||
f = function(cmnd)
|
|
||||||
local num = (cmnd:byte(2) or 0x31) - 0x30
|
|
||||||
print("forward("..num..")")
|
|
||||||
end,
|
|
||||||
b = function(cmnd)
|
|
||||||
local num = (cmnd:byte(2) or 0x31) - 0x30
|
|
||||||
print("backward("..num..")")
|
|
||||||
end,
|
|
||||||
l = function(cmnd, reverse)
|
|
||||||
if reverse then
|
|
||||||
print("right()")
|
|
||||||
else
|
|
||||||
print("left()")
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
r = function(cmnd, reverse)
|
|
||||||
if reverse then
|
|
||||||
print("left()")
|
|
||||||
else
|
|
||||||
print("right()")
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
u = function(cmnd)
|
|
||||||
print("up()")
|
|
||||||
end,
|
|
||||||
d = function(cmnd)
|
|
||||||
print("down()")
|
|
||||||
end,
|
|
||||||
t = function(cmnd)
|
|
||||||
local num, slot
|
|
||||||
if cmnd:sub(2,2) == "s" then
|
|
||||||
num = 99
|
|
||||||
slot = (cmnd:byte(3) or 0x31) - 0x30
|
|
||||||
else
|
|
||||||
num = 1
|
|
||||||
slot = (cmnd:byte(2) or 0x31) - 0x30
|
|
||||||
end
|
|
||||||
print("take("..num..","..slot..")")
|
|
||||||
end,
|
|
||||||
a = function(cmnd)
|
|
||||||
local num, slot
|
|
||||||
if cmnd:sub(2,2) == "s" then
|
|
||||||
num = 99
|
|
||||||
slot = (cmnd:byte(3) or 0x31) - 0x30
|
|
||||||
else
|
|
||||||
num = 1
|
|
||||||
slot = (cmnd:byte(2) or 0x31) - 0x30
|
|
||||||
end
|
|
||||||
print("add("..num..","..slot..")")
|
|
||||||
end,
|
|
||||||
p = function(cmnd)
|
|
||||||
local num, slot
|
|
||||||
if cmnd:sub(2,2) == "u" then
|
|
||||||
slot = (cmnd:byte(3) or 0x31) - 0x30
|
|
||||||
print("place("..slot..",U)")
|
|
||||||
elseif cmnd:sub(2,2) == "d" then
|
|
||||||
slot = (cmnd:byte(3) or 0x31) - 0x30
|
|
||||||
print("place("..slot..",D)")
|
|
||||||
else
|
|
||||||
slot = (cmnd:byte(2) or 0x31) - 0x30
|
|
||||||
print("place("..slot..")")
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
e = function(cmnd)
|
|
||||||
print(cmnd.." is a invalid command")
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
local function run(task, reverse)
|
|
||||||
task = task:gsub("\n", " ")
|
|
||||||
task = task:gsub("\t", " ")
|
|
||||||
local cmnds = task:split(" ")
|
|
||||||
if reverse then
|
|
||||||
Reverse(cmnds)
|
|
||||||
end
|
|
||||||
for i,cmnd in ipairs(cmnds) do
|
|
||||||
(switch[cmnd:sub(1,1)] or switch["e"])(cmnd, reverse)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
sl_robot.register_action("run", {
|
|
||||||
cmnd = function(self, sCmndList, reverse)
|
|
||||||
sCmndList = sCmndList:gsub("\n", " ")
|
|
||||||
sCmndList = sCmndList:gsub("\t", " ")
|
|
||||||
local cmnds = sCmndList:split(" ")
|
|
||||||
if reverse then
|
|
||||||
Reverse(cmnds)
|
|
||||||
end
|
|
||||||
for i,cmnd in ipairs(cmnds) do
|
|
||||||
(switch[cmnd:sub(1,1)] or switch["e"])(cmnd, reverse)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
help = " "
|
|
||||||
})
|
|
Before Width: | Height: | Size: 292 B |
Before Width: | Height: | Size: 504 B |
Before Width: | Height: | Size: 524 B |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 547 B |
Before Width: | Height: | Size: 602 B |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 385 B |
Before Width: | Height: | Size: 273 B |
Before Width: | Height: | Size: 423 B |
Before Width: | Height: | Size: 380 B |
Before Width: | Height: | Size: 374 B |
Before Width: | Height: | Size: 281 B |
BIN
tubelib_addons2/textures/tubelib_addons2_invisiblelamp.png
Normal file
After Width: | Height: | Size: 150 B |
After Width: | Height: | Size: 328 B |