-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
master
rnd1 2017-02-06 11:03:30 +01:00
parent 211d007609
commit 873f32dfbf
3 changed files with 82 additions and 47 deletions

View File

@ -79,12 +79,14 @@ end
basic_robot.commands.dig = function(name,dir) basic_robot.commands.dig = function(name,dir)
local digcount = 0; local energy = 0;
if basic_robot.maxdig~=0 then if basic_robot.maxenergy~=0 then
digcount = basic_robot.data[name].digcount; energy = basic_robot.data[name].energy;
if digcount > basic_robot.maxdig then if energy > 0 then
basic_robot.data[name].digcount = digcount+1; basic_robot.data[name].energy = energy-1;
return false end else
return false
end
end end
local obj = basic_robot.data[name].obj; local obj = basic_robot.data[name].obj;
@ -113,7 +115,6 @@ basic_robot.commands.dig = function(name,dir)
end end
end end
basic_robot.data[name].digcount = digcount+1;
return true return true
end end
@ -177,7 +178,9 @@ basic_robot.commands.take_item = function(name,item, inventory,dir)
return true return true
end 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 obj = basic_robot.data[name].obj;
local tpos; local tpos;
if dir~=0 then if dir~=0 then
@ -187,6 +190,16 @@ basic_robot.commands.check_inventory = function(name,itemname, inventory,dir)
end end
local tinv = minetest.get_meta(tpos):get_inventory(); 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); local stack = ItemStack(itemname);
if not inventory then inventory = "main"; end if not inventory then inventory = "main"; end
@ -200,6 +213,8 @@ basic_robot.no_teleport_table = {
["basic_robot:robot"] = true ["basic_robot:robot"] = true
} }
-- BUG : doesnt return list!
basic_robot.commands.pickup = function(r,name) basic_robot.commands.pickup = function(r,name)
if r>8 then return false end 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 spos = basic_robot.data[name].spawnpos; -- position of spawner block
local meta = minetest.get_meta(spos); local meta = minetest.get_meta(spos);
local inv = minetest.get_meta(spos):get_inventory(); 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 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() local lua_entity = obj:get_luaentity()
if not obj:is_player() and lua_entity and lua_entity.itemstring then 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 if not basic_robot.no_teleport_table[detected_obj] then -- object on no teleport list
-- put item in chest -- put item in chest
local stack = ItemStack(lua_entity.itemstring) local stack = ItemStack(lua_entity.itemstring)
picklist[#picklist+1]=detected_obj;
if inv:room_for_item("main", stack) then if inv:room_for_item("main", stack) then
inv:add_item("main", stack); inv:add_item("main", stack);
end end
@ -223,8 +240,8 @@ basic_robot.commands.pickup = function(r,name)
end end
end end
end end
if not picklist[1] then return nil end
return true return picklist
end end
@ -393,7 +410,6 @@ basic_robot.give_drops = function(nodename, inv) -- gives apropriate drops when
inv:add_item("main",nodename); inv:add_item("main",nodename);
end end
end end
end end
@ -417,12 +433,12 @@ local render_text = function(text,linesize)
tex = "([combine:"..(linesize*width).."x"..(linesize*height)..tex..")"; tex = "([combine:"..(linesize*width).."x"..(linesize*height)..tex..")";
tex = background .. "^" .. tex; tex = background .. "^" .. tex;
return tex; return tex;
end end
text = "";
basic_robot.commands.display_text = function(obj,text,linesize,size) basic_robot.commands.display_text = function(obj,text,linesize,size)
if not linesize then linesize = 20 end if not linesize or linesize<1 then linesize = 20 end
if not size then size = 1 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 if string.len(text)>linesize*linesize then text = string.sub(text,1,linesize*linesize) end
local tex = render_text(text,linesize); local tex = render_text(text,linesize);
@ -433,12 +449,17 @@ basic_robot.commands.display_text = function(obj,text,linesize,size)
end end
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) basic_robot.commands.activate = function(name,mode, dir)
local obj = basic_robot.data[name].obj; local obj = basic_robot.data[name].obj;
local tpos = pos_in_dir(obj, dir); -- position of target block in front local tpos = pos_in_dir(obj, dir); -- position of target block in front
local node = minetest.get_node(tpos); 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]; local table = minetest.registered_nodes[node.name];
if table and table.mesecons and table.mesecons.effector then if table and table.mesecons and table.mesecons.effector then
else else

1
depends.txt Normal file
View File

@ -0,0 +1 @@
default

View File

@ -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 basic_robot.bad_inventory_blocks = { -- disallow taking from these nodes inventories
["craft_guide:sign_wall"] = true, ["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 = { check_inventory = {
left = function(itemname, inventory) return commands.check_inventory(name,itemname, inventory,1) end, left = function(itemname, inventory,i) return commands.check_inventory(name,itemname, inventory,i,1) end,
right = function(itemname, inventory) return commands.check_inventory(name,itemname, inventory,2) end, right = function(itemname, inventory,i) return commands.check_inventory(name,itemname, inventory,i,2) end,
forward = function(itemname, inventory) return commands.check_inventory(name,itemname, inventory,3) end, forward = function(itemname, inventory,i) return commands.check_inventory(name,itemname, inventory,i,3) end,
backward = function(itemname, inventory) return commands.check_inventory(name,itemname, inventory,4) end, backward = function(itemname, inventory,i) return commands.check_inventory(name,itemname, inventory,i,4) end,
down = function(itemname, inventory) return commands.check_inventory(name,itemname, inventory,6) end, down = function(itemname, inventory,i) return commands.check_inventory(name,itemname, inventory,i,6) end,
up = function(itemname, inventory) return commands.check_inventory(name,itemname, inventory,5) end, up = function(itemname, inventory,i) return commands.check_inventory(name,itemname, inventory,i,5) end,
self = function(itemname, inventory) return commands.check_inventory(name,itemname, inventory,0) end, self = function(itemname, inventory,i) return commands.check_inventory(name,itemname, inventory,i,0) end,
}, },
activate = { activate = {
@ -111,7 +111,7 @@ function getSandboxEnv (name)
}, },
pickup = function(r) -- pick up items around robot pickup = function(r) -- pick up items around robot
commands.pickup(r, name); return commands.pickup(r, name);
end, end,
@ -228,10 +228,14 @@ function getSandboxEnv (name)
function(r) function(r)
if r>8 then return false end if r>8 then return false end
local objects = minetest.get_objects_inside_radius(basic_robot.data[name].obj:getpos(), r); local objects = minetest.get_objects_inside_radius(basic_robot.data[name].obj:getpos(), r);
local plist = {};
for _,obj in pairs(objects) do 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 end
return false if not plist[1] then return nil end
return plist
end, -- in radius around position end, -- in radius around position
player = { player = {
@ -240,6 +244,14 @@ function getSandboxEnv (name)
if player then return player:getpos() else return nil end if player then return player:getpos() else return nil end
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 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 basic_robot.data[name].quiet_mode=true
end end
else else
minetest.chat_send_player(basic_robot.data[name].owner,"<robot ".. name .. "> " .. text) minetest.chat_send_player(basic_robot.data[name].owner,"<robot ".. name .. "> " .. text)
end end
end, end,
@ -387,7 +398,6 @@ function getSandboxEnv (name)
pairs = pairs, pairs = pairs,
ipairs = ipairs, ipairs = ipairs,
error = error, error = error,
debug = debug,
--_ccounter = basic_robot.data[name].ccounter, -- counts how many executions of critical spots in script --_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; env._G = env;
else else
env._G=_G; env._G=_G;
debug = debug;
end end
return env return env
@ -578,7 +589,7 @@ local function runSandbox( name)
end end
data.ccounter = 0; data.ccounter = 0;
data.digcount = 1; data.energy = 1;
setfenv( ScriptFunc, data.sandbox ) setfenv( ScriptFunc, data.sandbox )
@ -810,22 +821,22 @@ local spawn_robot = function(pos,node,ttl)
local name = owner..id; 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; local codechange = false;
if meta:get_int("codechange") == 1 then if meta:get_int("codechange") == 1 then
meta:set_int("codechange",0); meta:set_int("codechange",0);
codechange = true; codechange = true;
end end
-- compile code & run it -- compile code & run it
local err; local err;
local data = basic_robot.data[name]; local data = basic_robot.data[name];
if codechange or (not data) then if codechange or (not data) then
basic_robot.data[name] = {}; data = basic_robot.data[name]; basic_robot.data[name] = {}; data = basic_robot.data[name];
meta:set_string("infotext",minetest.get_gametime().. " code changed ") meta:set_string("infotext",minetest.get_gametime().. " code changed ")
data.owner = owner;
if meta:get_int("admin") == 1 then data.isadmin = 1 end 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 --create virtual robot that reports position and other properties
local obj = {}; local obj = {};
function obj:getpos() return {x=pos.x,y=pos.y,z=pos.z} end 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 end
function obj:remove() end function obj:remove() end
basic_robot.data[name].obj = obj; data.obj = obj;
end end
end end
@ -867,7 +878,7 @@ local spawn_robot = function(pos,node,ttl)
if not data.sandbox then data.sandbox = getSandboxEnv (name) end if not data.sandbox then data.sandbox = getSandboxEnv (name) end
-- actual code run process -- actual code run process
data.ccounter = 0;data.digcount = 1; data.ccounter = 0;data.energy = 1;
setfenv(data.bytecode, data.sandbox ) setfenv(data.bytecode, data.sandbox )
@ -956,7 +967,7 @@ local despawn_robot = function(pos)
pos.y=pos.y+1; pos.y=pos.y+1;
local owner = meta:get_string("owner") local owner = meta:get_string("owner")
local id = meta:get_int("id"); 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; local name = owner..id;
-- if robot already exists remove it -- 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 id = math.floor(tonumber(fields.id) or 1);
local owner = meta:get_string("owner") local owner = meta:get_string("owner")
if not basic_robot.ids[owner] then setupid(owner) end 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); local privs = minetest.get_player_privs(name);
if not privs.privs then return end if not privs.privs then return end
end end
@ -1021,9 +1032,10 @@ local on_receive_robot_form = function(pos, formname, fields, sender)
"turn.left(), turn.right(), turn.angle(45)\n".. "turn.left(), turn.right(), turn.angle(45)\n"..
"dig.direction()\nplace.direction(\"default:dirt\")\nread_node.direction() tells you names of nodes\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".. "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".. "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".. "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".. "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".. "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.run(text) compiles and runs the code in sandbox\n"..
"code.set(text) replaces current bytecode of robot\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".. "find_nodes(\"default:dirt\",3) is true if node can be found at radius 3 around robot, otherwise false\n"..
"**PLAYERS\n".. " **PLAYERS\n"..
"find_player(3) finds player and returns his name in radius 3 around robot, if not returns false\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".. "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".. "player.getpos(name) return position of player, player.connected() returns list of players\n"..
" **ROBOT\n".. " **ROBOT\n"..
"say(\"hello\") will speak\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.pos() returns table {x=pos.x,y=pos.y,z=pos.z}\n"..
"self.name() returns robot name\n".. "self.name() returns robot name\n"..
"self.spam(0/1) (dis)enable message repeat to all\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.spawnpos() returns position of spawner block\n"..
"self.viewdir() returns vector of view for robot\n".. "self.viewdir() returns vector of view for robot\n"..
"self.fire(speed, pitch,gravity) fires a projectile from 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 id = meta:get_int("id");
local name = owner..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 not basic_robot.data[name] then return end
if basic_robot.data[name].obj then if basic_robot.data[name].obj then
@ -1219,15 +1232,15 @@ minetest.register_on_player_receive_fields(
elseif fields.right then elseif fields.right then
pcall(function () commands.move(name,2) end) pcall(function () commands.move(name,2) end)
elseif fields.dig then 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 elseif fields.up then
pcall(function () commands.move(name,5) end) pcall(function () commands.move(name,5) end)
elseif fields.down then elseif fields.down then
pcall(function () commands.move(name,6) end) pcall(function () commands.move(name,6) end)
elseif fields.digdown then 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 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 end
return return
end end