-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)
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

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
["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,"<robot ".. name .. "> " .. 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