From b72b703dfcf789bc0e83ac47bf9dfe178a572f08 Mon Sep 17 00:00:00 2001 From: Joachim Stolberg Date: Fri, 17 Aug 2018 12:32:31 +0200 Subject: [PATCH] robot removed, will be released as extra mod --- sl_robot/base.lua | 466 ------------------ sl_robot/commands.lua | 226 --------- sl_robot/depends.txt | 4 - sl_robot/description.txt | 2 - sl_robot/init.lua | 19 - sl_robot/mod.conf | 1 - sl_robot/readme.md | 20 - sl_robot/robot.lua | 411 --------------- sl_robot/run_cmnd.lua | 122 ----- sl_robot/sounds/sl_robot_error.ogg | Bin 7585 -> 0 bytes sl_robot/sounds/sl_robot_go_away.ogg | Bin 8279 -> 0 bytes sl_robot/sounds/sl_robot_step.ogg | Bin 6201 -> 0 bytes sl_robot/textures/sl_robot_base.png | Bin 292 -> 0 bytes sl_robot/textures/sl_robot_base_front.png | Bin 504 -> 0 bytes sl_robot/textures/sl_robot_base_left.png | Bin 524 -> 0 bytes sl_robot/textures/sl_robot_base_lid.png | Bin 1627 -> 0 bytes sl_robot/textures/sl_robot_base_right.png | Bin 547 -> 0 bytes sl_robot/textures/sl_robot_base_top.png | Bin 602 -> 0 bytes sl_robot/textures/sl_robot_robot.png | Bin 1532 -> 0 bytes sl_robot/textures/sl_robot_robot_back.png | Bin 385 -> 0 bytes sl_robot/textures/sl_robot_robot_bottom.png | Bin 273 -> 0 bytes sl_robot/textures/sl_robot_robot_front.png | Bin 423 -> 0 bytes sl_robot/textures/sl_robot_robot_left.png | Bin 380 -> 0 bytes sl_robot/textures/sl_robot_robot_right.png | Bin 374 -> 0 bytes sl_robot/textures/sl_robot_robot_top.png | Bin 281 -> 0 bytes .../tubelib_addons2_invisiblelamp.png | Bin 0 -> 150 bytes ...ubelib_addons2_invisiblelamp_inventory.png | Bin 0 -> 328 bytes 27 files changed, 1271 deletions(-) delete mode 100644 sl_robot/base.lua delete mode 100644 sl_robot/commands.lua delete mode 100644 sl_robot/depends.txt delete mode 100644 sl_robot/description.txt delete mode 100644 sl_robot/init.lua delete mode 100644 sl_robot/mod.conf delete mode 100644 sl_robot/readme.md delete mode 100644 sl_robot/robot.lua delete mode 100644 sl_robot/run_cmnd.lua delete mode 100644 sl_robot/sounds/sl_robot_error.ogg delete mode 100644 sl_robot/sounds/sl_robot_go_away.ogg delete mode 100644 sl_robot/sounds/sl_robot_step.ogg delete mode 100644 sl_robot/textures/sl_robot_base.png delete mode 100644 sl_robot/textures/sl_robot_base_front.png delete mode 100644 sl_robot/textures/sl_robot_base_left.png delete mode 100644 sl_robot/textures/sl_robot_base_lid.png delete mode 100644 sl_robot/textures/sl_robot_base_right.png delete mode 100644 sl_robot/textures/sl_robot_base_top.png delete mode 100644 sl_robot/textures/sl_robot_robot.png delete mode 100644 sl_robot/textures/sl_robot_robot_back.png delete mode 100644 sl_robot/textures/sl_robot_robot_bottom.png delete mode 100644 sl_robot/textures/sl_robot_robot_front.png delete mode 100644 sl_robot/textures/sl_robot_robot_left.png delete mode 100644 sl_robot/textures/sl_robot_robot_right.png delete mode 100644 sl_robot/textures/sl_robot_robot_top.png create mode 100644 tubelib_addons2/textures/tubelib_addons2_invisiblelamp.png create mode 100644 tubelib_addons2/textures/tubelib_addons2_invisiblelamp_inventory.png diff --git a/sl_robot/base.lua b/sl_robot/base.lua deleted file mode 100644 index 25be4ca..0000000 --- a/sl_robot/base.lua +++ /dev/null @@ -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", "") - - 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", "") - 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"} ---}) - diff --git a/sl_robot/commands.lua b/sl_robot/commands.lua deleted file mode 100644 index 78dc94b..0000000 --- a/sl_robot/commands.lua +++ /dev/null @@ -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()\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()\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" -}) diff --git a/sl_robot/depends.txt b/sl_robot/depends.txt deleted file mode 100644 index bf0fc13..0000000 --- a/sl_robot/depends.txt +++ /dev/null @@ -1,4 +0,0 @@ -default -tubelib -safer_lua - diff --git a/sl_robot/description.txt b/sl_robot/description.txt deleted file mode 100644 index 05f8ab8..0000000 --- a/sl_robot/description.txt +++ /dev/null @@ -1,2 +0,0 @@ -SaferLua Robot - a simple robot to be programmed in LUA - diff --git a/sl_robot/init.lua b/sl_robot/init.lua deleted file mode 100644 index ecfe824..0000000 --- a/sl_robot/init.lua +++ /dev/null @@ -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") diff --git a/sl_robot/mod.conf b/sl_robot/mod.conf deleted file mode 100644 index afaee5f..0000000 --- a/sl_robot/mod.conf +++ /dev/null @@ -1 +0,0 @@ -name=sl_robot diff --git a/sl_robot/readme.md b/sl_robot/readme.md deleted file mode 100644 index 7f11fdb..0000000 --- a/sl_robot/readme.md +++ /dev/null @@ -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 diff --git a/sl_robot/robot.lua b/sl_robot/robot.lua deleted file mode 100644 index d8b4548..0000000 --- a/sl_robot/robot.lua +++ /dev/null @@ -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(), -}) - diff --git a/sl_robot/run_cmnd.lua b/sl_robot/run_cmnd.lua deleted file mode 100644 index a879cc0..0000000 --- a/sl_robot/run_cmnd.lua +++ /dev/null @@ -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 = " " -}) diff --git a/sl_robot/sounds/sl_robot_error.ogg b/sl_robot/sounds/sl_robot_error.ogg deleted file mode 100644 index 04fdd610a5024e23d7d6a1f4e76b9f4d45be97dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7585 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 diff --git a/sl_robot/sounds/sl_robot_step.ogg b/sl_robot/sounds/sl_robot_step.ogg deleted file mode 100644 index 0f426e5d4709bd78afeb395e4958e183f8cfedce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6201 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 ag%g>q_$@Z&1z&W?p}EG`ktGMOUt1nE3X$_ hQ~R?&Z9e-BhNZ2(DUs*H9e|E!@O1TaS?83{1OSIqYX$%S diff --git a/sl_robot/textures/sl_robot_base_front.png b/sl_robot/textures/sl_robot_base_front.png deleted file mode 100644 index 13a5d6fccb029aa233ea94a89685217c394f6592..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 504 zcmV!Nb7F!@|eO#?H{q($vw_*VEYA z*WlXO;oREX-rL^b-QDBm;N#!t;^5@w;^ye(>Fen2@9XyP@A32SBxvpA00001VoOIv z0Eh)0NB{r;32;bRa{vGf6951U69E94oEQKA00(qQO+^Rd2MQ7>2bNx7N&o->9!W$& zR5;7cQ_*gNFbuR%*O7H%NvK=bkn#V2xpP8jD?pX{w38slj^w+up$5>wFd7C`6_Lw@ z&)i#$n#MWTx&`eMaDiP2!Q%-r+BO z*2P`#GIQSI9Bj&@DwB3(Qk6+>%4Ab%GDA_hl9^1U(HKa#WKI)AnoJeKs27>31F^CX zRQG}AeTeZ(9>={HOgrQL2R^(S_k?`$!8T{h2jq(n2sV9~H_iL|Iz0G5E4;JzQhneZ uAGrDuo_$!Rx%#`aiqFGw10VBoIQ{_`MoMf4-~4v~0000!Nb7F!@|eO#?H{q($vw_*VEYA z*WlXO;oREX-rL^b-QDBm;N#!t;^5@w;^ye(>Fen2@9XyP@A32SBxvpA00001VoOIv z0Eh)0NB{r;32;bRa{vGf6951U69E94oEQKA00(qQO+^Rd2MQ7=Da{aZN&o->GD$>1 zR5;7ElZ$SHFbqX+87oO)JiH}K1GNADm$hS34H%lHX-7f<68UlDpkU%COu`sr3?X>$ zKHR(Pp(w1i#y&AC_&{gcOxNYNMtI|=YB9Ajz6dGDI7$ZZefs5G9S~~gT;rRt;GIBJ zksXG?I=Hl!mMHDGVZoNB?|Va-TaMhGx_Lo6386Vj&?a&Oca2=%d}nU=+dRb}E!Gzf zO7@c@aA5}?h%P~E=p`#rO3sH&KXIuD#8 z&BLJw;IAI?Jp7}FJP(H+@;u=8^RT@aI}h7?@x{XrQ(cwkZ+Kmn^85h5e@S4TeM^i0 O0000Xp}`SV8M4BI@ZbXBk3yZ3zO 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 iqkWt;zu8Oymq5zYdS z$YKTtZeb8+WSBKa0w~B{;_2(k{)nAJ(1gK_>0TO8NV3E=qQp5rH#aq}gu%HeHL)Z$ zMWH;iBtya7(>EZzkxv|`=%uHNV@Sl|w^I!H4jJ&c+OOztUlUi=_|9ieleR&T;JE{q z6C`fVys0;`v$=}+7-iCM>qBe7yb zl>B0@IQ`l0ixij@)+c5)B-L!NowJB*-uK-yhhz@%e5m1-4~@OPnJql@Ya9cE#%ZBd zTxo6J<<9NgZ705MMz*Bj!D@bnT5&;!hE+`+k5Ugg+Cxig_Bsfo9@Ne$qzfndeIq>` ztEO*mVyNjZK6Xm!$-TP|9^L!$P5b%FXTN?${r&&PA}%)`XcuFWx4R2N2dk_Hki%Kv z5n0T@z%2~Ij105pNB{-dOFVsD*&nfU2ytl7=6=us6p}1)jVN)>&&^HED`9XhN=+zopr0M9^4WdHyG diff --git a/sl_robot/textures/sl_robot_robot_front.png b/sl_robot/textures/sl_robot_robot_front.png deleted file mode 100644 index 9002d0fb411649c4f12e2fbe9f3eebb7a8e81161..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 423 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy2?0JKu8d3!d@Kq~Ofl+QZ0bDD z`3!~;+`Q)U+^VYLY$l9`>g+Cxig_Bsfo9@Ne$qzfndeIq>` ztEO*mVyNjZK6Xm!$-TP|9^L!$P5b%FXTN?${r&&PA}%)`XcuFWx4R2N2dk_Hki%Kv z5n0T@z%2~Ij105pNB{-dOFVsD*&nfU2(d8CW(qq46p}1)jVN)>&&^HED`9XhN=+#LW-5E<5r{KeV+w6y~v#OS4vW&C?D0&$ud{-4MIu{D<>e zUM##l3p5he^DcCG#G<*?HC8}?N!g-)ZN_`agL970*0;P}*f~+~5idh0hu{GTH--2~ z;)~9B89JTtDtjkVE#KGPr!5@FAi4IW(5Bjm%q#u!*&h$TdB!R6D9-oCX5EEAH#2y; L`njxgN@xNAg{P0m diff --git a/sl_robot/textures/sl_robot_robot_left.png b/sl_robot/textures/sl_robot_robot_left.png deleted file mode 100644 index 46ccd2e5901b98f55fd53ffc0ed82402070e331b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 380 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy2?0JKu8d3!d@Kq~Ofl+QZ0bDD z`3!~;+`Q)U+^VYLY$l9`>g+Cxig_Bsfo9@Ne$qzfndeIq>` ztEO*mVyNjZK6Xm!$-TP|9^L!$P5b%FXTN?${r&&PA}%)`XcuFWx4R2N2dk_Hki%Kv z5n0T@z%2~Ij105pNB{-dOFVsD*&nfU2=SQBN%V{b3Q3l@MwB?`=jNv7l`uFLr6!i7 zrYMwWmSiZnd-?{1H}Z)C71esWIEGl9K6>dcSAzl%Yr^|7(vDG%J#*V% zqW64x-i8U&d{)kk;alId?i~Mv(}wKI&ktriahvQQvhiRM&&K$KuE06^9bdmHcR0mO zX6U%dI%!3^u)_CnPSy$DQ5qZg7PxS3WAwhrveZBg+Cxig_Bsfo9@Ne$qzfndeIq>` ztEO*mVyNjZK6Xm!$-TP|9^L!$P5b%FXTN?${r&&PA}%)`XcuFWx4R2N2dk_Hki%Kv z5n0T@z%2~Ij105pNB{-dOFVsD*&nfU2=TI7t&#+}T(ZP9qQp5rH#aq}gu%HeHL)Z$ zMWH;iBtya7(>EZzkxv|`sNB=VF~s8Z(McP*4k+-r?6z!ea#qZ}@c;j5xtUv@EV**Y zuJEH=meVw@KB-5?Pg@_VddmK=*~t7*ZKAqQ&7}h#2HHot#3v+cii&(sE?&55*I`z{ z{S91`6gBjNiwg+Cxig_Bsfo9@Ne$qzfndeIq>` ztEO*mVyNjZK6Xm!$-TP|9^L!$P5b%FXTN?${r&&PA}%)`XcuFWx4R2N2dk_Hki%Kv z5n0T@z%2~Ij105pNB{-dOFVsD*&nfU2yq$j3X}=~3Q3l@MwB?`=jNv7l`uFLr6!i7 zrYMwWmSiZnd-?{1H}Z)C6-jxzIEGl9PM$E$z0sjT>wv+kgph+PnkKGdU~pnCW@K=& RF951y@O1TaS?83{1OP=fOzQvu diff --git a/tubelib_addons2/textures/tubelib_addons2_invisiblelamp.png b/tubelib_addons2/textures/tubelib_addons2_invisiblelamp.png new file mode 100644 index 0000000000000000000000000000000000000000..72f2dbd5ac2dccc1cc14c19cfe6b5fda519089d8 GIT binary patch literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;bAV5XE0A7ZWqS)qF_r}R1v5B2 zyO9RsBze2LFm$lWdH^|`1s;*b3=G`DAk4@xYmNj^kiEpy*OmPdhk&4gfQHKB@jRu?6^qxSl%6z`@C&ci@Q|P=v80 z$S;_|;n|He5GTpo-G!lpRn`N@;VkfoEM{Qf76xHPhFNnYfP(BLp1!W^k2nN`nay~Q zU1tFb?e=tW4AD4$_2NdsW&^vd z#+bd2lpp3lc&@@ZMKB`z!3sgio6fEe7K(njz!=icu(O(FhYeGX9AjF4#EKsq8aW$< zvIBOltxUSr>AF#1chmf*>mDqS