From 873f32dfbf38b112abbc8a72d042b8437211316f Mon Sep 17 00:00:00 2001 From: rnd1 Date: Mon, 6 Feb 2017 11:03:30 +0100 Subject: [PATCH] -bug fixes -robot now has "energy", each round of execute gives 1 energy up to max 1. to dig stuff, 1 energy is expended -find_player, pickup, player.connected now all return list or nil -check_inventory can look at i-th item in inventory and return its name --- commands.lua | 55 +++++++++++++++++++++++++++------------ depends.txt | 1 + init.lua | 73 +++++++++++++++++++++++++++++++--------------------- 3 files changed, 82 insertions(+), 47 deletions(-) create mode 100644 depends.txt diff --git a/commands.lua b/commands.lua index 8647324..84115d4 100644 --- a/commands.lua +++ b/commands.lua @@ -79,12 +79,14 @@ end basic_robot.commands.dig = function(name,dir) - local digcount = 0; - if basic_robot.maxdig~=0 then - digcount = basic_robot.data[name].digcount; - if digcount > basic_robot.maxdig then - basic_robot.data[name].digcount = digcount+1; - return false end + local energy = 0; + if basic_robot.maxenergy~=0 then + energy = basic_robot.data[name].energy; + if energy > 0 then + basic_robot.data[name].energy = energy-1; + else + return false + end end local obj = basic_robot.data[name].obj; @@ -113,7 +115,6 @@ basic_robot.commands.dig = function(name,dir) end end - basic_robot.data[name].digcount = digcount+1; return true end @@ -177,7 +178,9 @@ basic_robot.commands.take_item = function(name,item, inventory,dir) return true end -basic_robot.commands.check_inventory = function(name,itemname, inventory,dir) +-- check_inventory(item, inventory, position) +--if position>0 then it returns name of item at that position +basic_robot.commands.check_inventory = function(name,itemname, inventory, position, dir) local obj = basic_robot.data[name].obj; local tpos; if dir~=0 then @@ -187,6 +190,16 @@ basic_robot.commands.check_inventory = function(name,itemname, inventory,dir) end local tinv = minetest.get_meta(tpos):get_inventory(); + + if not position then position = -1 end + if position>0 then + return tinv:get_stack(inventory, position):to_string() + end + + if itemname == "" then + return tinv:is_empty(inventory) + end + local stack = ItemStack(itemname); if not inventory then inventory = "main"; end @@ -200,6 +213,8 @@ basic_robot.no_teleport_table = { ["basic_robot:robot"] = true } +-- BUG : doesnt return list! + basic_robot.commands.pickup = function(r,name) if r>8 then return false end @@ -208,7 +223,8 @@ basic_robot.commands.pickup = function(r,name) local spos = basic_robot.data[name].spawnpos; -- position of spawner block local meta = minetest.get_meta(spos); local inv = minetest.get_meta(spos):get_inventory(); - + local picklist = {}; + for _,obj in pairs(minetest.get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, r)) do local lua_entity = obj:get_luaentity() if not obj:is_player() and lua_entity and lua_entity.itemstring then @@ -216,6 +232,7 @@ basic_robot.commands.pickup = function(r,name) if not basic_robot.no_teleport_table[detected_obj] then -- object on no teleport list -- put item in chest local stack = ItemStack(lua_entity.itemstring) + picklist[#picklist+1]=detected_obj; if inv:room_for_item("main", stack) then inv:add_item("main", stack); end @@ -223,8 +240,8 @@ basic_robot.commands.pickup = function(r,name) end end end - - return true + if not picklist[1] then return nil end + return picklist end @@ -393,7 +410,6 @@ basic_robot.give_drops = function(nodename, inv) -- gives apropriate drops when inv:add_item("main",nodename); end end - end @@ -417,12 +433,12 @@ local render_text = function(text,linesize) tex = "([combine:"..(linesize*width).."x"..(linesize*height)..tex..")"; tex = background .. "^" .. tex; return tex; - end - text = ""; +end + basic_robot.commands.display_text = function(obj,text,linesize,size) - if not linesize then linesize = 20 end - if not size then size = 1 end + if not linesize or linesize<1 then linesize = 20 end + if not size or size<=0 then size = 1 end if string.len(text)>linesize*linesize then text = string.sub(text,1,linesize*linesize) end local tex = render_text(text,linesize); @@ -433,12 +449,17 @@ basic_robot.commands.display_text = function(obj,text,linesize,size) end end - +local robot_activate_furnace = minetest.registered_nodes["default:furnace"].on_metadata_inventory_put; -- this function will activate furnace basic_robot.commands.activate = function(name,mode, dir) local obj = basic_robot.data[name].obj; local tpos = pos_in_dir(obj, dir); -- position of target block in front local node = minetest.get_node(tpos); + if node.name == "default:furnace" or node.name == "default:furnace_active" then + if mode>0 then robot_activate_furnace(tpos) end + return + end + local table = minetest.registered_nodes[node.name]; if table and table.mesecons and table.mesecons.effector then else diff --git a/depends.txt b/depends.txt new file mode 100644 index 0000000..331d858 --- /dev/null +++ b/depends.txt @@ -0,0 +1 @@ +default \ No newline at end of file diff --git a/init.lua b/init.lua index a20666c..afa65d0 100644 --- a/init.lua +++ b/init.lua @@ -8,7 +8,7 @@ basic_robot.call_limit = 48; -- how many execution calls per script run allowed basic_robot.bad_inventory_blocks = { -- disallow taking from these nodes inventories ["craft_guide:sign_wall"] = true, } -basic_robot.maxdig = 1; -- how many digs allowed per run, 0 = unlimited +basic_robot.maxenergy = 1; -- how much energy available per run, 0 = unlimited ---------------------- @@ -91,13 +91,13 @@ function getSandboxEnv (name) }, check_inventory = { - left = function(itemname, inventory) return commands.check_inventory(name,itemname, inventory,1) end, - right = function(itemname, inventory) return commands.check_inventory(name,itemname, inventory,2) end, - forward = function(itemname, inventory) return commands.check_inventory(name,itemname, inventory,3) end, - backward = function(itemname, inventory) return commands.check_inventory(name,itemname, inventory,4) end, - down = function(itemname, inventory) return commands.check_inventory(name,itemname, inventory,6) end, - up = function(itemname, inventory) return commands.check_inventory(name,itemname, inventory,5) end, - self = function(itemname, inventory) return commands.check_inventory(name,itemname, inventory,0) end, + left = function(itemname, inventory,i) return commands.check_inventory(name,itemname, inventory,i,1) end, + right = function(itemname, inventory,i) return commands.check_inventory(name,itemname, inventory,i,2) end, + forward = function(itemname, inventory,i) return commands.check_inventory(name,itemname, inventory,i,3) end, + backward = function(itemname, inventory,i) return commands.check_inventory(name,itemname, inventory,i,4) end, + down = function(itemname, inventory,i) return commands.check_inventory(name,itemname, inventory,i,6) end, + up = function(itemname, inventory,i) return commands.check_inventory(name,itemname, inventory,i,5) end, + self = function(itemname, inventory,i) return commands.check_inventory(name,itemname, inventory,i,0) end, }, activate = { @@ -111,7 +111,7 @@ function getSandboxEnv (name) }, pickup = function(r) -- pick up items around robot - commands.pickup(r, name); + return commands.pickup(r, name); end, @@ -228,10 +228,14 @@ function getSandboxEnv (name) function(r) if r>8 then return false end local objects = minetest.get_objects_inside_radius(basic_robot.data[name].obj:getpos(), r); + local plist = {}; for _,obj in pairs(objects) do - if obj:is_player() then return obj:get_player_name() end + if obj:is_player() then + plist[#plist+1]=obj:get_player_name(); + end end - return false + if not plist[1] then return nil end + return plist end, -- in radius around position player = { @@ -240,6 +244,14 @@ function getSandboxEnv (name) if player then return player:getpos() else return nil end end, + connected = function() + local players = minetest.get_connected_players(); + local plist = {} + for _,player in pairs(players) do + plist[#plist+1]=player:get_player_name() + end + if not plist[1] then return nil else return plist end + end }, attack = function(target) return basic_robot.commands.attack(name,target) end, -- attack player if nearby @@ -281,7 +293,6 @@ function getSandboxEnv (name) basic_robot.data[name].quiet_mode=true end else - minetest.chat_send_player(basic_robot.data[name].owner," " .. text) end end, @@ -387,7 +398,6 @@ function getSandboxEnv (name) pairs = pairs, ipairs = ipairs, error = error, - debug = debug, --_ccounter = basic_robot.data[name].ccounter, -- counts how many executions of critical spots in script @@ -408,6 +418,7 @@ function getSandboxEnv (name) env._G = env; else env._G=_G; + debug = debug; end return env @@ -578,7 +589,7 @@ local function runSandbox( name) end data.ccounter = 0; - data.digcount = 1; + data.energy = 1; setfenv( ScriptFunc, data.sandbox ) @@ -810,22 +821,22 @@ local spawn_robot = function(pos,node,ttl) local name = owner..id; - if id == 0 then -- just compile code and run it, no robot spawn + if id <= 0 then -- just compile code and run it, no robot spawn local codechange = false; if meta:get_int("codechange") == 1 then meta:set_int("codechange",0); codechange = true; end -- compile code & run it - local err; local data = basic_robot.data[name]; if codechange or (not data) then basic_robot.data[name] = {}; data = basic_robot.data[name]; meta:set_string("infotext",minetest.get_gametime().. " code changed ") + data.owner = owner; if meta:get_int("admin") == 1 then data.isadmin = 1 end - if not basic_robot.data[name].obj then + if not data.obj then --create virtual robot that reports position and other properties local obj = {}; function obj:getpos() return {x=pos.x,y=pos.y,z=pos.z} end @@ -838,7 +849,7 @@ local spawn_robot = function(pos,node,ttl) end function obj:remove() end - basic_robot.data[name].obj = obj; + data.obj = obj; end end @@ -867,7 +878,7 @@ local spawn_robot = function(pos,node,ttl) if not data.sandbox then data.sandbox = getSandboxEnv (name) end -- actual code run process - data.ccounter = 0;data.digcount = 1; + data.ccounter = 0;data.energy = 1; setfenv(data.bytecode, data.sandbox ) @@ -956,7 +967,7 @@ local despawn_robot = function(pos) pos.y=pos.y+1; local owner = meta:get_string("owner") local id = meta:get_int("id"); - if id == 0 then meta:set_int("codechange",1) return end + if id <= 0 then meta:set_int("codechange",1) return end local name = owner..id; -- if robot already exists remove it @@ -997,7 +1008,7 @@ local on_receive_robot_form = function(pos, formname, fields, sender) local id = math.floor(tonumber(fields.id) or 1); local owner = meta:get_string("owner") if not basic_robot.ids[owner] then setupid(owner) end - if id<0 or id>basic_robot.ids[owner].maxid then + if id<-1000 and id>basic_robot.ids[owner].maxid then local privs = minetest.get_player_privs(name); if not privs.privs then return end end @@ -1021,9 +1032,10 @@ local on_receive_robot_form = function(pos, formname, fields, sender) "turn.left(), turn.right(), turn.angle(45)\n".. "dig.direction()\nplace.direction(\"default:dirt\")\nread_node.direction() tells you names of nodes\n".. "insert.direction(item, inventory) inserts item from robot inventory to target inventory\n".. - "check_inventory.direction(itemname, inventory) looks at node and returns false/true, direction can be self\n".. + "check_inventory.direction(itemname, inventory,index) looks at node and returns false/true, direction can be self,\n".. + " if index>0 it returns itemname\n".. "activate.direction(mode) activates target block\n".. - "pickup(r) picks up all items around robot in radius r<8\n".. + "pickup(r) picks up all items around robot in radius r<8 and returns list or nil\n".. "take.direction(item, inventory) takes item from target inventory into robot inventory\n".. "read_text.direction(stringname) reads text of signs, chests and other blocks, optional stringname for other meta\n".. "write_text.direction(text) writes text to target block as infotext\n".. @@ -1031,10 +1043,10 @@ local on_receive_robot_form = function(pos, formname, fields, sender) "code.run(text) compiles and runs the code in sandbox\n".. "code.set(text) replaces current bytecode of robot\n".. "find_nodes(\"default:dirt\",3) is true if node can be found at radius 3 around robot, otherwise false\n".. - "**PLAYERS\n".. - "find_player(3) finds player and returns his name in radius 3 around robot, if not returns false\n".. + " **PLAYERS\n".. + "find_player(3) finds players in radius 3 around robot and returns list, if none returns nil\n".. "attack(target) attempts to attack target player if nearby \n".. - "grab(target) attempt to grab target player if nearby \n".. + "grab(target) attempt to grab target player if nearby and returns true if succesful \n".. "player.getpos(name) return position of player, player.connected() returns list of players\n".. " **ROBOT\n".. "say(\"hello\") will speak\n".. @@ -1045,7 +1057,7 @@ local on_receive_robot_form = function(pos, formname, fields, sender) "self.pos() returns table {x=pos.x,y=pos.y,z=pos.z}\n".. "self.name() returns robot name\n".. "self.spam(0/1) (dis)enable message repeat to all\n".. - "self.remove() removes robot\n".. + "self.remove() removes robot object\n".. "self.spawnpos() returns position of spawner block\n".. "self.viewdir() returns vector of view for robot\n".. "self.fire(speed, pitch,gravity) fires a projectile from robot\n".. @@ -1083,6 +1095,7 @@ local on_receive_robot_form = function(pos, formname, fields, sender) local id = meta:get_int("id"); local name = owner..id; + if id<=0 then meta:set_int("codechange",1) end if not basic_robot.data[name] then return end if basic_robot.data[name].obj then @@ -1219,15 +1232,15 @@ minetest.register_on_player_receive_fields( elseif fields.right then pcall(function () commands.move(name,2) end) elseif fields.dig then - pcall(function () basic_robot.data[name].digcount = 1; commands.dig(name,3) end) + pcall(function () basic_robot.data[name].energy = 1; commands.dig(name,3) end) elseif fields.up then pcall(function () commands.move(name,5) end) elseif fields.down then pcall(function () commands.move(name,6) end) elseif fields.digdown then - pcall(function () basic_robot.data[name].digcount = 1; commands.dig(name,6) end) + pcall(function () basic_robot.data[name].energy = 1; commands.dig(name,6) end) elseif fields.digup then - pcall(function () basic_robot.data[name].digcount = 1; commands.dig(name,5) end) + pcall(function () basic_robot.data[name].energy = 1; commands.dig(name,5) end) end return end