better spawning
several robots per user off signal to spawner from mesecons/basic_machines removes robot
This commit is contained in:
parent
779f0ab40c
commit
ee7473dfac
69
commands.lua
69
commands.lua
@ -90,10 +90,10 @@ basic_robot.commands.dig = function(name,dir)
|
||||
local obj = basic_robot.data[name].obj;
|
||||
local pos = pos_in_dir(obj, dir)
|
||||
local luaent = obj:get_luaentity();
|
||||
if minetest.is_protected(pos,luaent.owner ) then return false end
|
||||
if minetest.is_protected(pos,luaent.owner) then return false end
|
||||
|
||||
local nodename = minetest.get_node(pos).name;
|
||||
if nodename == "air" then return false end
|
||||
if nodename == "air" or nodename=="ignore" then return false end
|
||||
|
||||
local spos = obj:get_luaentity().spawnpos;
|
||||
local inv = minetest.get_meta(spos):get_inventory();
|
||||
@ -177,6 +177,22 @@ basic_robot.commands.take_item = function(name,item, inventory,dir)
|
||||
return contains
|
||||
end
|
||||
|
||||
basic_robot.commands.check_inventory = function(name,itemname, inventory,dir)
|
||||
local obj = basic_robot.data[name].obj;
|
||||
local tpos;
|
||||
if dir~=0 then
|
||||
tpos = pos_in_dir(obj, dir); -- position of target block in front
|
||||
else
|
||||
tpos = obj:get_luaentity().spawnpos;
|
||||
end
|
||||
|
||||
local tinv = minetest.get_meta(tpos):get_inventory();
|
||||
local stack = ItemStack(itemname);
|
||||
if not inventory then inventory = "main"; end
|
||||
|
||||
return tinv:contains_item(inventory, stack);
|
||||
end
|
||||
|
||||
|
||||
basic_robot.no_teleport_table = {
|
||||
["itemframes:item"] = true,
|
||||
@ -187,7 +203,7 @@ basic_robot.no_teleport_table = {
|
||||
basic_robot.commands.pickup = function(r,name)
|
||||
|
||||
if r>8 then return false end
|
||||
|
||||
|
||||
local pos = basic_robot.data[name].obj:getpos();
|
||||
local spos = basic_robot.data[name].spawnpos; -- position of spawner block
|
||||
local meta = minetest.get_meta(spos);
|
||||
@ -195,8 +211,8 @@ basic_robot.commands.pickup = function(r,name)
|
||||
|
||||
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
|
||||
local detected_obj = lua_entity.name or ""
|
||||
if not obj:is_player() and lua_entity and lua_entity.itemstring then
|
||||
local detected_obj = lua_entity.itemstring or ""
|
||||
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)
|
||||
@ -245,11 +261,14 @@ basic_robot.commands.place = function(name,nodename, dir)
|
||||
inv:remove_item("main", ItemStack(nodename));
|
||||
|
||||
--DS
|
||||
local sounds = minetest.registered_nodes[nodename].sounds
|
||||
if sounds then
|
||||
local sound = sounds.place
|
||||
if sound then
|
||||
minetest.sound_play(sound,{object=obj, max_hear_distance = 10})
|
||||
local registered_node = minetest.registered_nodes[nodename];
|
||||
if registered_node then
|
||||
local sounds = registered_node.sounds
|
||||
if sounds then
|
||||
local sound = sounds.place
|
||||
if sound then
|
||||
minetest.sound_play(sound,{object=obj, max_hear_distance = 10})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -283,6 +302,29 @@ basic_robot.commands.attack = function(name, target) -- attack range 4, damage 5
|
||||
|
||||
end
|
||||
|
||||
basic_robot.commands.grab = function(name,target)
|
||||
|
||||
local reach = 4;
|
||||
|
||||
local tplayer = minetest.get_player_by_name(target);
|
||||
if not tplayer then return false end
|
||||
local obj = basic_robot.data[name].obj;
|
||||
local pos = obj:getpos();
|
||||
local tpos = tplayer:getpos();
|
||||
|
||||
if math.abs(pos.x-tpos.x)> reach or math.abs(pos.y-tpos.y)> reach or math.abs(pos.z-tpos.z)> reach then
|
||||
return false
|
||||
end
|
||||
|
||||
if tplayer:get_attach() then
|
||||
tplayer:set_detach()
|
||||
else
|
||||
tplayer:set_attach(obj, "", {x=0,y=5,z=0}, {x=0,y=0,z=0})
|
||||
end
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
basic_robot.commands.read_book = function (itemstack) -- itemstack should contain book
|
||||
local data = minetest.deserialize(itemstack:get_metadata())
|
||||
@ -293,14 +335,15 @@ basic_robot.commands.read_book = function (itemstack) -- itemstack should contai
|
||||
end
|
||||
end
|
||||
|
||||
basic_robot.commands.write_book = function(name,text) -- returns itemstack containing book
|
||||
basic_robot.commands.write_book = function(name,title,text) -- returns itemstack containing book
|
||||
|
||||
local lpp = 14;
|
||||
local new_stack = ItemStack("default:book_written")
|
||||
local data = {}
|
||||
|
||||
data.title = "program book"
|
||||
data.text = text
|
||||
if title == "" or not title then title = "program book "..minetest.get_gametime() end
|
||||
data.title = title
|
||||
data.text = text or ""
|
||||
data.text_len = #data.text
|
||||
data.page = 1
|
||||
data.page_max = math.ceil((#data.text:gsub("[^\n]", "") + 1) / lpp)
|
||||
|
523
init.lua
523
init.lua
@ -2,32 +2,37 @@
|
||||
|
||||
|
||||
basic_robot = {};
|
||||
basic_robot.call_limit = 32; -- how many execution calls per script execution allowed
|
||||
basic_robot.bad_inventory_blocks = {
|
||||
---- SETTINGS ------
|
||||
basic_robot.call_limit = 32; -- 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 execution, 0 = unlimited
|
||||
basic_robot.maxdig = 1; -- how many digs allowed per run, 0 = unlimited
|
||||
----------------------
|
||||
|
||||
|
||||
|
||||
basic_robot.version = "11/26a";
|
||||
|
||||
|
||||
basic_robot.data = {};
|
||||
basic_robot.data.listening = {}; -- which robots listen to chat
|
||||
basic_robot.version = "12/21a";
|
||||
|
||||
basic_robot.data = {}; -- stores all robot data
|
||||
--[[
|
||||
[name] = {sandbox= .., bytecode = ..., ram = ..., obj = robot object,spawnpos=...}
|
||||
[name] = { sandbox= .., bytecode = ..., ram = ..., obj = robot object,spawnpos=...}
|
||||
robot object = object of entity, used to manipulate movements and more
|
||||
--]]
|
||||
basic_robot.ids = {}; -- stores maxid for all players
|
||||
--[name] = {id = .., maxid = .. }, current id, how many robot ids player can use
|
||||
|
||||
|
||||
|
||||
basic_robot.data.listening = {}; -- which robots listen to chat
|
||||
dofile(minetest.get_modpath("basic_robot").."/commands.lua")
|
||||
|
||||
|
||||
|
||||
|
||||
-- SANDBOX for running lua code isolated and safely
|
||||
|
||||
function getSandboxEnv (name)
|
||||
|
||||
local commands = basic_robot.commands;
|
||||
local env =
|
||||
{
|
||||
@ -85,6 +90,15 @@ function getSandboxEnv (name)
|
||||
up = function(item, inventory) commands.take_item(name,item, inventory,5) end,
|
||||
|
||||
},
|
||||
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,5) end,
|
||||
up = function(itemname, inventory) return commands.check_inventory(name,itemname, inventory,6) end,
|
||||
self = function(itemname, inventory) return commands.check_inventory(name,itemname, inventory,0) end,
|
||||
},
|
||||
|
||||
pickup = function(r) -- pick up items around robot
|
||||
commands.pickup(r, name);
|
||||
@ -206,6 +220,8 @@ function getSandboxEnv (name)
|
||||
|
||||
attack = function(target) return basic_robot.commands.attack(name,target) end, -- attack player if nearby
|
||||
|
||||
grab = function(target) return basic_robot.commands.grab(name,target) end,
|
||||
|
||||
read_node = { -- returns node name
|
||||
left = function() return commands.read_node(name,1) end,
|
||||
right = function() return commands.read_node(name,2) end,
|
||||
@ -232,7 +248,8 @@ function getSandboxEnv (name)
|
||||
basic_robot.data[name].quiet_mode=true
|
||||
end
|
||||
else
|
||||
minetest.chat_send_player(name,"<robot ".. name .. "> " .. text)
|
||||
|
||||
minetest.chat_send_player(basic_robot.data[name].owner,"<robot ".. name .. "> " .. text)
|
||||
end
|
||||
end,
|
||||
|
||||
@ -240,8 +257,11 @@ function getSandboxEnv (name)
|
||||
book = {
|
||||
read = function(i)
|
||||
if i<=0 or i > 32 then return nil end
|
||||
local inv = minetest.get_meta(basic_robot.data[name].spawnpos):get_inventory();
|
||||
local itemstack = inv:get_stack("library", i);
|
||||
local pos = basic_robot.data[name].spawnpos; local meta = minetest.get_meta(pos);
|
||||
local libposstring = meta:get_string("libpos");
|
||||
local words = {}; for word in string.gmatch(libposstring,"%S+") do words[#words+1]=word end
|
||||
local libpos = {x=tonumber(words[1] or pos.x),y=tonumber(words[2] or pos.y),z=tonumber(words[3] or pos.z)};
|
||||
local inv = minetest.get_meta(libpos):get_inventory();local itemstack = inv:get_stack("library", i);
|
||||
if itemstack then
|
||||
return commands.read_book(itemstack);
|
||||
else
|
||||
@ -249,10 +269,10 @@ function getSandboxEnv (name)
|
||||
end
|
||||
end,
|
||||
|
||||
write = function(i,text)
|
||||
write = function(i,title,text)
|
||||
if i<=0 or i > 32 then return nil end
|
||||
local inv = minetest.get_meta(basic_robot.data[name].spawnpos):get_inventory();
|
||||
local stack = basic_robot.commands.write_book(name,text);
|
||||
local stack = basic_robot.commands.write_book(name,title,text);
|
||||
if stack then inv:set_stack("library", i, stack) end
|
||||
end
|
||||
},
|
||||
@ -291,6 +311,7 @@ function getSandboxEnv (name)
|
||||
byte = string.byte, char = string.char,
|
||||
find = string.find,
|
||||
format = string.format, gsub = string.gsub,
|
||||
gmatch = string.gmatch,
|
||||
len = string.len, lower = string.lower,
|
||||
upper = string.upper, rep = string.rep,
|
||||
reverse = string.reverse, sub = string.sub,
|
||||
@ -343,10 +364,20 @@ function getSandboxEnv (name)
|
||||
basic_robot.data[name].ccounter = _ccounter + 1;
|
||||
end,
|
||||
};
|
||||
env._G = env;
|
||||
|
||||
--special sandbox for admin
|
||||
local isadmin=basic_robot.data[name].isadmin
|
||||
|
||||
if not isadmin then
|
||||
env._G = env;
|
||||
else
|
||||
env._G=_G;
|
||||
end
|
||||
|
||||
return env
|
||||
end
|
||||
|
||||
-- code checker
|
||||
|
||||
local function check_code(code)
|
||||
|
||||
@ -390,6 +421,7 @@ local function is_inside_string(pos,script)
|
||||
return false;
|
||||
end
|
||||
|
||||
-- COMPILATION
|
||||
|
||||
local function CompileCode ( script )
|
||||
|
||||
@ -417,7 +449,7 @@ local function CompileCode ( script )
|
||||
--minetest.chat_send_all("while0");
|
||||
if not is_inside_string(i2,script) then
|
||||
local i21 = i2;
|
||||
i2=string.find(script, "do ", i2);
|
||||
i2=string.find(script, "do", i2);
|
||||
if i2 then
|
||||
script = script.sub(script,1, i2+1) .. insert_code .. script.sub(script, i2+2);
|
||||
i1=i21+6; -- after while
|
||||
@ -475,13 +507,16 @@ local function CompileCode ( script )
|
||||
return ScriptFunc, nil
|
||||
end
|
||||
|
||||
local function initSandbox ( name )
|
||||
local function initSandbox (name)
|
||||
basic_robot.data[name].sandbox = getSandboxEnv (name);
|
||||
end
|
||||
|
||||
local function setCode( name, script ) -- to run script: 1. initSandbox 2. setCode 3. runSandbox
|
||||
|
||||
local err;
|
||||
err = check_code(script);
|
||||
if not basic_robot.data[name].isadmin then
|
||||
err = check_code(script);
|
||||
end
|
||||
if err then return err end
|
||||
|
||||
local bytecode, err = CompileCode ( script );
|
||||
@ -494,48 +529,59 @@ basic_robot.commands.setCode=setCode; -- so we can use it
|
||||
|
||||
local function runSandbox( name)
|
||||
|
||||
local ScriptFunc = basic_robot.data[name].bytecode;
|
||||
local data = basic_robot.data[name]
|
||||
local ScriptFunc = data.bytecode;
|
||||
if not ScriptFunc then
|
||||
return "Bytecode missing."
|
||||
end
|
||||
|
||||
basic_robot.data[name].ccounter = 0;
|
||||
basic_robot.data[name].digcount = 1;
|
||||
data.ccounter = 0;
|
||||
data.digcount = 1;
|
||||
|
||||
setfenv( ScriptFunc, basic_robot.data[name].sandbox )
|
||||
setfenv( ScriptFunc, data.sandbox )
|
||||
|
||||
local Result, RuntimeError = pcall( ScriptFunc )
|
||||
if RuntimeError then
|
||||
return RuntimeError
|
||||
end
|
||||
local Result, RuntimeError = pcall( ScriptFunc )
|
||||
if RuntimeError then
|
||||
return RuntimeError
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
-- note: to see memory used by lua in kbytes: collectgarbage("count")
|
||||
|
||||
local function setupid(owner)
|
||||
local privs = minetest.get_player_privs(owner); if not privs then return end
|
||||
local maxid = 2;
|
||||
if privs.robot then maxid = 16 end -- max id's per user
|
||||
basic_robot.ids[owner] = {id = 1, maxid = maxid}; --active id for remove control
|
||||
end
|
||||
|
||||
|
||||
local robot_spawner_update_form = function (pos, mode)
|
||||
|
||||
if not pos then return end
|
||||
local meta = minetest.get_meta(pos);
|
||||
if not meta then return end
|
||||
local x0,y0,z0;
|
||||
x0=meta:get_int("x0");y0=meta:get_int("y0");z0=meta:get_int("z0"); -- direction of velocity
|
||||
local code = minetest.formspec_escape(meta:get_string("code"));
|
||||
local form;
|
||||
|
||||
if mode ~= 1 then
|
||||
local id = meta:get_int("id");
|
||||
|
||||
if mode ~= 1 then -- when placed
|
||||
|
||||
form =
|
||||
"size[9.5,6]" .. -- width, height
|
||||
"textarea[1.25,-0.25;8.75,7.6;code;;".. code.."]"..
|
||||
"button_exit[-0.25,-0.25;1.25,1;OK;SAVE]"..
|
||||
"button_exit[-0.25, 0.75;1.25,1;spawn;START]"..
|
||||
"button[-0.25, 1.75;1.25,1;despawn;STOP]"..
|
||||
"field[0.25,3.;1.,1;id;id;"..id.."]"..
|
||||
"button[-0.25, 3.6;1.25,1;inventory;storage]"..
|
||||
"button[-0.25, 4.6;1.25,1;library;library]"..
|
||||
"button[-0.25, 5.6;1.25,1;help;help]";
|
||||
else
|
||||
|
||||
else -- when robot clicked
|
||||
form =
|
||||
"size[9.5,6]" .. -- width, height
|
||||
"textarea[1.25,-0.25;8.75,7.6;code;;".. code.."]"..
|
||||
@ -544,6 +590,7 @@ local robot_spawner_update_form = function (pos, mode)
|
||||
"button[-0.25, 3.6;1.25,1;inventory;storage]"..
|
||||
"button[-0.25, 4.6;1.25,1;library;library]"..
|
||||
"button[-0.25, 5.6;1.25,1;help;help]";
|
||||
|
||||
end
|
||||
|
||||
if mode ==1 then return form end
|
||||
@ -551,23 +598,31 @@ local robot_spawner_update_form = function (pos, mode)
|
||||
|
||||
end
|
||||
|
||||
local function init_robot(self)
|
||||
local function init_robot(obj)
|
||||
|
||||
local self = obj:get_luaentity();
|
||||
local name = self.name; -- robot name
|
||||
basic_robot.data[name].obj = obj; --register object
|
||||
--init settings
|
||||
basic_robot.data.listening[name] = nil -- dont listen at beginning
|
||||
basic_robot.data[name].quiet_mode = false; -- can chat globally
|
||||
|
||||
basic_robot.data[self.owner].obj = self.object; -- BUG: some problems with functions using object later??
|
||||
basic_robot.data.listening[self.owner] = nil -- dont listen at beginning
|
||||
basic_robot.data[self.owner].quiet_mode = false;
|
||||
-- check if admin robot
|
||||
local privs = minetest.get_player_privs(self.owner);
|
||||
if privs then basic_robot.data[name].isadmin = privs.privs end
|
||||
|
||||
self.object:set_properties({infotext = "robot " .. self.owner});
|
||||
self.object:set_properties({nametag = "[" .. self.owner.."]",nametag_color = "LawnGreen"});
|
||||
self.object:set_armor_groups({fleshy=0})
|
||||
--robot appearance,armor...
|
||||
obj:set_properties({infotext = "robot " .. name});
|
||||
obj:set_properties({nametag = "[" .. name.."]",nametag_color = "LawnGreen"});
|
||||
obj:set_armor_groups({fleshy=0})
|
||||
|
||||
initSandbox ( self.owner )
|
||||
initSandbox ( name )
|
||||
end
|
||||
|
||||
minetest.register_entity("basic_robot:robot",{
|
||||
energy = 1,
|
||||
owner = "",
|
||||
name = "",
|
||||
hp_max = 10,
|
||||
code = "",
|
||||
timer = 0,
|
||||
@ -586,24 +641,27 @@ minetest.register_entity("basic_robot:robot",{
|
||||
physical=true,
|
||||
|
||||
on_activate = function(self, staticdata)
|
||||
|
||||
|
||||
-- reactivate robot
|
||||
if staticdata~="" then
|
||||
|
||||
self.owner = staticdata; -- remember its owner
|
||||
if not basic_robot.data[self.owner] then
|
||||
minetest.chat_send_player(self.owner, "#ROBOT INIT: error. spawn robot again.")
|
||||
self.name = staticdata; -- remember its name
|
||||
|
||||
local data = basic_robot.data[self.name];
|
||||
|
||||
if not data then
|
||||
--minetest.chat_send_all("#ROBOT INIT: error. spawn robot again.")
|
||||
self.object:remove();
|
||||
return;
|
||||
end
|
||||
|
||||
self.spawnpos = {x=basic_robot.data[self.owner].spawnpos.x,y=basic_robot.data[self.owner].spawnpos.y,z=basic_robot.data[self.owner].spawnpos.z};
|
||||
init_robot(self);
|
||||
self.owner = data.owner;
|
||||
self.spawnpos = {x=data.spawnpos.x,y=data.spawnpos.y,z=data.spawnpos.z};
|
||||
init_robot(self.object);
|
||||
self.running = 1;
|
||||
|
||||
local pos = basic_robot.data[self.owner].spawnpos;
|
||||
local meta = minetest.get_meta(pos);
|
||||
|
||||
local meta = minetest.get_meta(data.spawnpos);
|
||||
if meta then self.code = meta:get_string("code") end -- remember code
|
||||
if not self.code or self.code == "" then
|
||||
minetest.chat_send_player(self.owner, "#ROBOT INIT: no code found")
|
||||
@ -613,38 +671,15 @@ minetest.register_entity("basic_robot:robot",{
|
||||
return
|
||||
end
|
||||
|
||||
-- init robot TODO: rewrite for less buggy
|
||||
minetest.after(0, -- so that stuff with spawner is initialized before
|
||||
function()
|
||||
|
||||
if not self.spawnpos then self.object:remove() return end
|
||||
|
||||
if not basic_robot.data[self.owner] then
|
||||
basic_robot.data[self.owner] = {};
|
||||
end
|
||||
|
||||
basic_robot.data[self.owner].spawnpos = {x=self.spawnpos.x,y=self.spawnpos.y,z=self.spawnpos.z};
|
||||
init_robot(self); -- set properties, init sandbox
|
||||
|
||||
local err = setCode( self.owner, self.code ); -- compile code
|
||||
if err then
|
||||
minetest.chat_send_player(self.owner,"#ROBOT CODE COMPILATION ERROR : " .. err)
|
||||
self.running = 0; -- stop execution
|
||||
|
||||
self.object:remove();
|
||||
basic_robot.data[self.owner].obj = nil;
|
||||
return
|
||||
end
|
||||
|
||||
self.running = 1
|
||||
|
||||
end
|
||||
)
|
||||
-- lost robots
|
||||
--minetest.chat_send_all("D R " .. self.owner)
|
||||
|
||||
--if not self.spawnpos then self.object:remove() return end
|
||||
|
||||
end,
|
||||
|
||||
get_staticdata = function(self)
|
||||
return self.owner;
|
||||
return self.name;
|
||||
end,
|
||||
|
||||
on_punch = function (self, puncher, time_from_last_punch, tool_capabilities, dir)
|
||||
@ -652,32 +687,33 @@ minetest.register_entity("basic_robot:robot",{
|
||||
end,
|
||||
|
||||
on_step = function(self, dtime)
|
||||
|
||||
self.timer=self.timer+dtime
|
||||
if self.timer>self.timestep and self.running == 1 then
|
||||
self.timer = 0;
|
||||
local err = runSandbox(self.owner);
|
||||
local err = runSandbox(self.name);
|
||||
if err then
|
||||
minetest.chat_send_player(self.owner,"#ROBOT ERROR : " .. err)
|
||||
self.running = 0; -- stop execution
|
||||
|
||||
if string.find(err,"stack overflow") then -- remove stupid player privs and spawner, ban player ip
|
||||
local owner = self.owner;
|
||||
local pos = basic_robot.data[owner].spawnpos;
|
||||
local name = self.name;
|
||||
local pos = basic_robot.data[name].spawnpos;
|
||||
minetest.set_node(pos, {name = "air"});
|
||||
|
||||
local privs = core.get_player_privs(owner);privs.interact = false;
|
||||
local privs = core.get_player_privs(self.owner);privs.interact = false;
|
||||
|
||||
core.set_player_privs(owner, privs); minetest.auth_reload()
|
||||
minetest.ban_player(owner)
|
||||
core.set_player_privs(self.owner, privs); minetest.auth_reload()
|
||||
minetest.ban_player(self.owner)
|
||||
|
||||
end
|
||||
|
||||
local owner = self.owner;
|
||||
local pos = basic_robot.data[owner].spawnpos;
|
||||
local name = self.name;
|
||||
local pos = basic_robot.data[name].spawnpos;
|
||||
|
||||
if not basic_robot.data[owner] then return end
|
||||
if basic_robot.data[owner].obj then
|
||||
basic_robot.data[owner].obj = nil;
|
||||
if not basic_robot.data[name] then return end
|
||||
if basic_robot.data[name].obj then
|
||||
basic_robot.data[name].obj = nil;
|
||||
end
|
||||
|
||||
self.object:remove();
|
||||
@ -692,15 +728,18 @@ minetest.register_entity("basic_robot:robot",{
|
||||
local text = minetest.formspec_escape(self.code);
|
||||
local form = robot_spawner_update_form(self.spawnpos,1);
|
||||
|
||||
minetest.show_formspec(clicker:get_player_name(), "robot_worker_" .. self.owner, form);
|
||||
minetest.show_formspec(clicker:get_player_name(), "robot_worker_" .. self.name, form); -- yyy
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
|
||||
local spawn_robot = function(pos,node,ttl)
|
||||
if ttl<0 then return end
|
||||
|
||||
local meta = minetest.get_meta(pos);
|
||||
|
||||
--temperature based spam activate protect
|
||||
local t0 = meta:get_int("t");
|
||||
local t1 = minetest.get_gametime();
|
||||
local T = meta:get_int("T"); -- temperature
|
||||
@ -725,36 +764,104 @@ local spawn_robot = function(pos,node,ttl)
|
||||
-- spawn robot on top
|
||||
pos.y=pos.y+1;
|
||||
local owner = meta:get_string("owner")
|
||||
local id = meta:get_int("id");
|
||||
local name = owner..id;
|
||||
|
||||
-- if robot already exists do nothing
|
||||
if basic_robot.data[owner] and basic_robot.data[owner].obj then
|
||||
minetest.chat_send_player(owner,"#ROBOT: robot already active, removing")
|
||||
basic_robot.data[owner].obj:remove();
|
||||
basic_robot.data[owner].obj = nil;
|
||||
if basic_robot.data[name] and basic_robot.data[name].obj then
|
||||
minetest.chat_send_player(owner,"#ROBOT: ".. name .. " already active, removing ")
|
||||
basic_robot.data[name].obj:remove();
|
||||
basic_robot.data[name].obj = nil;
|
||||
end
|
||||
|
||||
local objects = minetest.get_objects_inside_radius(pos, 0.9);
|
||||
for _,obj in pairs(objects) do if not obj:is_player() then obj:remove() end end
|
||||
|
||||
local obj = minetest.add_entity(pos,"basic_robot:robot");
|
||||
local luaent = obj:get_luaentity();
|
||||
luaent.owner = meta:get_string("owner");
|
||||
|
||||
luaent.owner = owner;
|
||||
luaent.name = name;
|
||||
luaent.code = meta:get_string("code");
|
||||
luaent.spawnpos = {x=pos.x,y=pos.y-1,z=pos.z};
|
||||
-- note:
|
||||
|
||||
|
||||
local data = basic_robot.data[name];
|
||||
if not data then
|
||||
basic_robot.data[name] = {};
|
||||
data = basic_robot.data[name];
|
||||
end
|
||||
|
||||
data.owner = owner;
|
||||
data.spawnpos = {x=pos.x,y=pos.y-1,z=pos.z};
|
||||
|
||||
|
||||
init_robot(obj); -- set properties, init sandbox
|
||||
|
||||
local self = obj:get_luaentity();
|
||||
local err = setCode( self.name, self.code ); -- compile code
|
||||
if err then
|
||||
minetest.chat_send_player(self.owner,"#ROBOT CODE COMPILATION ERROR : " .. err)
|
||||
self.running = 0; -- stop execution
|
||||
|
||||
self.object:remove();
|
||||
basic_robot.data[self.name].obj = nil;
|
||||
return
|
||||
end
|
||||
|
||||
self.running = 1
|
||||
end
|
||||
|
||||
local despawn_robot = function(pos)
|
||||
|
||||
local meta = minetest.get_meta(pos);
|
||||
|
||||
--temperature based spam activate protect
|
||||
local t0 = meta:get_int("t");
|
||||
local t1 = minetest.get_gametime();
|
||||
local T = meta:get_int("T"); -- temperature
|
||||
|
||||
if t0>t1-2 then -- activated before natural time
|
||||
T=T+1;
|
||||
else
|
||||
if T>0 then
|
||||
T=T-1
|
||||
if t1-t0>5 then T = 0 end
|
||||
end
|
||||
end
|
||||
meta:set_int("T",T);
|
||||
meta:set_int("t",t1); -- update last activation time
|
||||
|
||||
if T > 2 then -- overheat
|
||||
minetest.sound_play("default_cool_lava",{pos = pos, max_hear_distance = 16, gain = 0.25})
|
||||
meta:set_string("infotext","overheat: temperature ".. T)
|
||||
return
|
||||
end
|
||||
|
||||
-- spawn position on top
|
||||
pos.y=pos.y+1;
|
||||
local owner = meta:get_string("owner")
|
||||
local id = meta:get_int("id");
|
||||
local name = owner..id;
|
||||
|
||||
-- if robot already exists remove it
|
||||
if basic_robot.data[name] and basic_robot.data[name].obj then
|
||||
minetest.chat_send_player(owner,"#ROBOT: ".. name .. " removed")
|
||||
basic_robot.data[name].obj:remove();
|
||||
basic_robot.data[name].obj = nil;
|
||||
end
|
||||
|
||||
local objects = minetest.get_objects_inside_radius(pos, 0.9);
|
||||
for _,obj in pairs(objects) do if not obj:is_player() then obj:remove() end end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--process forms from spawner
|
||||
local on_receive_robot_form = function(pos, formname, fields, sender)
|
||||
|
||||
local name = sender:get_player_name();
|
||||
if minetest.is_protected(pos,name) then return end
|
||||
|
||||
if fields.reset then
|
||||
local meta = minetest.get_meta(pos);
|
||||
meta:set_string("code","");
|
||||
robot_spawner_update_form(pos);
|
||||
return
|
||||
end
|
||||
|
||||
if fields.OK then
|
||||
|
||||
local meta = minetest.get_meta(pos);
|
||||
@ -763,6 +870,14 @@ local on_receive_robot_form = function(pos, formname, fields, sender)
|
||||
local code = fields.code or "";
|
||||
meta:set_string("code", code)
|
||||
end
|
||||
|
||||
if fields.id then
|
||||
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<1 or id>basic_robot.ids[owner].maxid then return end
|
||||
meta:set_int("id",id) -- set active id for spawner
|
||||
end
|
||||
|
||||
robot_spawner_update_form(pos);
|
||||
return
|
||||
@ -770,33 +885,35 @@ local on_receive_robot_form = function(pos, formname, fields, sender)
|
||||
|
||||
if fields.help then
|
||||
|
||||
local text = "BASIC LUA SYNTAX\n \nif x==1 then do_something else do_something_else end"..
|
||||
"\nfor i = 1, 5 do something end \nwhile i<6 do something; i=i+1; end\n"..
|
||||
local text = "BASIC LUA SYNTAX\n \nif x==1 then A else B end"..
|
||||
"\nfor i = 1, 5 do something end \nwhile i<6 do A; i=i+1; end\n"..
|
||||
"\narrays: myTable1 = {1,2,3}, myTable2 = {[\"entry1\"]=5, [\"entry2\"]=1}\n"..
|
||||
"access table entries with myTable1[1] or myTable2.entry1 or myTable2[\"entry1\"]\n \n"..
|
||||
"ROBOT COMMANDS\n \n"..
|
||||
"**MOVEMENT,DIGGING, PLACING, INVENTORY TAKE/INSERT\nmove.direction(), where direction is forward, backward, left,right, up, down)\n"..
|
||||
" **MOVEMENT,DIGGING, PLACING, INVENTORY TAKE/INSERT\nmove.direction(), where direction is forward, backward, left,right, up, down)\n"..
|
||||
"forward_down direction only works with dig, place and read_node\n"..
|
||||
"turn.left(), turn.right(), turn.angle(45)\n"..
|
||||
"dig.direction()\n place.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"..
|
||||
"check_inventory.direction(itemname, inventory) looks at node and returns false/true, direction can be self\n"..
|
||||
"pickup(r) picks up all items around robot in radius r<8\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"..
|
||||
"**BOOKS/CODE\nbook.read(i) returns contents of book at i-th position in library \nbook.write(i,text) writes book at i-th position\n"..
|
||||
" **BOOKS/CODE\nbook.read(i) returns contents of book at i-th position in library \nbook.write(i,title,text) writes book at i-th position at spawner library\n"..
|
||||
"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"..
|
||||
"attack(target) attempts to attack target player if nearby \n"..
|
||||
"grab(target) attempt to grab target player if nearby \n"..
|
||||
"player.getpos(name) return position of player, player.connected() returns list of players\n"..
|
||||
"**ROBOT\n"..
|
||||
" **ROBOT\n"..
|
||||
"say(\"hello\") will speak\n"..
|
||||
"self.listen(0/1) (de)attaches chat listener to robot\n"..
|
||||
"speaker, msg = self.listen_msg() retrieves last chat message if robot listens\n"..
|
||||
"self.send_mail(target,mail) sends mail to target robot\n"..
|
||||
"sender,mail = read_mail() reads mail, if any\n" ..
|
||||
"sender,mail = self.read_mail() reads mail, if any\n" ..
|
||||
"self.pos() returns table {x=pos.x,y=pos.y,z=pos.z}\n"..
|
||||
"self.spam(0/1) (dis)enable message repeat to all\n"..
|
||||
"self.remove() removes robot\n"..
|
||||
@ -828,11 +945,14 @@ local on_receive_robot_form = function(pos, formname, fields, sender)
|
||||
|
||||
local meta = minetest.get_meta(pos);
|
||||
local owner = meta:get_string("owner");
|
||||
local id = meta:get_int("id");
|
||||
local name = owner..id;
|
||||
|
||||
|
||||
if not basic_robot.data[owner] then return end
|
||||
if basic_robot.data[owner].obj then
|
||||
basic_robot.data[owner].obj:remove();
|
||||
basic_robot.data[owner].obj = nil;
|
||||
if not basic_robot.data[name] then return end
|
||||
if basic_robot.data[name].obj then
|
||||
basic_robot.data[name].obj:remove();
|
||||
basic_robot.data[name].obj = nil;
|
||||
end
|
||||
return
|
||||
end
|
||||
@ -842,29 +962,75 @@ local on_receive_robot_form = function(pos, formname, fields, sender)
|
||||
local form =
|
||||
"size[8,8]" .. -- width, height
|
||||
"list["..list_name..";main;0.,0;8,4;]"..
|
||||
"list[current_player;main;0,4.25;8,4;]";
|
||||
"list[current_player;main;0,4.25;8,4;]"..
|
||||
"listring[" .. list_name .. ";main]"..
|
||||
"listring[current_player;main]";
|
||||
minetest.show_formspec(sender:get_player_name(), "robot_inventory", form);
|
||||
end
|
||||
|
||||
if fields.library then
|
||||
|
||||
local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z ;
|
||||
local form =
|
||||
"size[8,8]" .. -- width, height
|
||||
"list["..list_name..";library;0.,0;8,4;]"..
|
||||
local list = "";
|
||||
local meta = minetest.get_meta(pos);
|
||||
|
||||
local owner = meta:get_string("owner");
|
||||
local id = meta:get_int("id");
|
||||
local name = owner..id;
|
||||
|
||||
local libposstring = meta:get_string("libpos");
|
||||
local words = {}; for word in string.gmatch(libposstring,"%S+") do words[#words+1]=word end
|
||||
local libpos = {x=tonumber(words[1] or pos.x),y=tonumber(words[2] or pos.y),z=tonumber(words[3] or pos.z)};
|
||||
local libform = "";
|
||||
|
||||
if libpos.x and libpos.y and libpos.z and not minetest.is_protected(libpos,owner) then
|
||||
libform = "list["..list_name..";library;4.25,0;4,4;]";
|
||||
else
|
||||
libform = "label[4.25,0;Library position is protected]";
|
||||
end
|
||||
|
||||
local libnodename = minetest.get_node(libpos).name;
|
||||
if libnodename~="basic_robot:spawner" then
|
||||
if libnodename == "ignore" then
|
||||
libform = "label[4.25,0;library target area is not loaded]"
|
||||
else
|
||||
libform = "label[4.25,0;there is no spawner at library coordinates]"
|
||||
end
|
||||
else
|
||||
local inv = minetest.get_meta(libpos):get_inventory();
|
||||
local text = "";
|
||||
for i=1,16 do
|
||||
local itemstack = inv:get_stack("library", i);
|
||||
local data = minetest.deserialize(itemstack:get_metadata())
|
||||
if data then
|
||||
text = string.sub(data.title or "",1,32);
|
||||
else
|
||||
text = "";
|
||||
end
|
||||
text = i..". " .. minetest.formspec_escape(text);
|
||||
list = list .. text .. ",";
|
||||
end
|
||||
end
|
||||
|
||||
--for word in string.gmatch(text, "(.-)\r?\n+") do list = list .. word .. ", " end -- matches lines
|
||||
local form = "size [8,8] textlist[0,0;4.,3.;books;" .. list .. "]"..
|
||||
"field[0.25,3.5;3.25,1;libpos;Position of spawner used as library;"..libposstring.."]"..
|
||||
"button_exit[3.25,3.2;1.,1;OK;SAVE]"..
|
||||
libform..
|
||||
"list[current_player;main;0,4.25;8,4;]";
|
||||
minetest.show_formspec(sender:get_player_name(), "robot_inventory", form);
|
||||
minetest.show_formspec(sender:get_player_name(), "robot_library_"..minetest.pos_to_string(pos), form);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- handle form when rightclicking robot entity
|
||||
-- handle form: when rightclicking robot entity, remote controller
|
||||
minetest.register_on_player_receive_fields(
|
||||
function(player, formname, fields)
|
||||
|
||||
local robot_formname = "robot_worker_";
|
||||
if string.find(formname,robot_formname) then
|
||||
local name = string.sub(formname, string.len(robot_formname)+1);
|
||||
local sender = minetest.get_player_by_name(name);
|
||||
local name = string.sub(formname, string.len(robot_formname)+1); -- robot name
|
||||
local sender = player:get_player_name(); --minetest.get_player_by_name(name);
|
||||
|
||||
if basic_robot.data[name] and basic_robot.data[name].spawnpos then
|
||||
local pos = basic_robot.data[name].spawnpos;
|
||||
@ -873,11 +1039,11 @@ minetest.register_on_player_receive_fields(
|
||||
local is_protected = minetest.is_protected(pos, player:get_player_name());
|
||||
if is_protected and not privs.privs then return 0 end
|
||||
|
||||
if not sender then
|
||||
-- if not sender then
|
||||
on_receive_robot_form(pos,formname, fields, player)
|
||||
else
|
||||
on_receive_robot_form(pos,formname, fields, sender)
|
||||
end
|
||||
-- else
|
||||
-- on_receive_robot_form(pos,formname, fields, sender)
|
||||
-- end
|
||||
|
||||
return
|
||||
end
|
||||
@ -885,20 +1051,24 @@ minetest.register_on_player_receive_fields(
|
||||
|
||||
local robot_formname = "robot_control_";
|
||||
if string.find(formname,robot_formname) then
|
||||
local name = string.sub(formname, string.len(robot_formname)+1);
|
||||
local sender = minetest.get_player_by_name(name); if not sender then return end
|
||||
local name = string.sub(formname, string.len(robot_formname)+1); -- robot name
|
||||
if fields.OK and fields.code then
|
||||
local item = sender:get_wielded_item(); --set_wielded_item(item)
|
||||
local item = player:get_wielded_item(); --set_wielded_item(item)
|
||||
item:set_metadata(fields.code);
|
||||
sender:set_wielded_item(item);
|
||||
player:set_wielded_item(item);
|
||||
if fields.id then
|
||||
local id = tonumber(fields.id) or 1;
|
||||
local owner = player:get_player_name();
|
||||
basic_robot.ids[owner].id = id -- set active id
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local robot_formname = "robot_manual_control_";
|
||||
if string.find(formname,robot_formname) then
|
||||
local name = string.sub(formname, string.len(robot_formname)+1);
|
||||
local sender = minetest.get_player_by_name(name); if not sender then return end
|
||||
local name = string.sub(formname, string.len(robot_formname)+1); -- robot name
|
||||
|
||||
local commands = basic_robot.commands;
|
||||
|
||||
if fields.turnleft then
|
||||
@ -927,6 +1097,36 @@ minetest.register_on_player_receive_fields(
|
||||
return
|
||||
end
|
||||
|
||||
local robot_formname = "robot_library_";
|
||||
if string.find(formname,robot_formname) then
|
||||
local spos = minetest.string_to_pos(string.sub(formname, string.len(robot_formname)+1));
|
||||
|
||||
if fields.books then
|
||||
if string.sub(fields.books,1,3)=="DCL" then
|
||||
local sel = tonumber(string.sub(fields.books,5)) or 1;
|
||||
local meta = minetest.get_meta(spos);
|
||||
local libposstring = meta:get_string("libpos");
|
||||
local words = {}; for word in string.gmatch(libposstring,"%S+") do words[#words+1]=word end
|
||||
local libpos = {x=tonumber(words[1] or spos.x),y=tonumber(words[2] or spos.y),z=tonumber(words[3] or spos.z)};
|
||||
local inv = minetest.get_meta(libpos):get_inventory();local itemstack = inv:get_stack("library", sel);
|
||||
if itemstack then
|
||||
local text = basic_robot.commands.read_book(itemstack) or "";
|
||||
local form = "size [8,8] textarea[0.,0;8.75,9.75;book;BOOK CONTENTS;" .. minetest.formspec_escape(text) .. "]"
|
||||
minetest.show_formspec(player:get_player_name(), "robot_book", form);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if fields.OK and fields.libpos then
|
||||
local sender = player:get_player_name(); --minetest.get_player_by_name(name);
|
||||
local meta = minetest.get_meta(spos);
|
||||
meta:set_string("libpos", fields.libpos);
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
)
|
||||
|
||||
@ -935,8 +1135,9 @@ minetest.register_on_chat_message(
|
||||
function(name, message)
|
||||
local listeners = basic_robot.data.listening;
|
||||
for pname,_ in pairs(listeners) do
|
||||
basic_robot.data[pname].listen_msg = message;
|
||||
basic_robot.data[pname].listen_speaker = name;
|
||||
local data = basic_robot.data[pname];
|
||||
data.listen_msg = message;
|
||||
data.listen_speaker = name;
|
||||
end
|
||||
end
|
||||
)
|
||||
@ -957,16 +1158,21 @@ minetest.register_node("basic_robot:spawner", {
|
||||
local privs = minetest.get_player_privs(placer:get_player_name()); if privs.privs then meta:set_int("admin",1) end
|
||||
|
||||
meta:set_string("code","");
|
||||
meta:set_int("id",1); -- initial robot id
|
||||
|
||||
meta:set_string("infotext", "robot spawner (owned by ".. placer:get_player_name() .. ")")
|
||||
meta:set_string("libpos",pos.x .. " " .. pos.y .. " " .. pos.z)
|
||||
|
||||
robot_spawner_update_form(pos);
|
||||
|
||||
local inv = meta:get_inventory(); -- spawner inventory
|
||||
inv:set_size("main",32);
|
||||
inv:set_size("library",32);
|
||||
inv:set_size("library",16); --4*4
|
||||
end,
|
||||
|
||||
mesecons = {effector = {
|
||||
action_on = spawn_robot
|
||||
action_on = spawn_robot,
|
||||
action_off = despawn_robot
|
||||
}
|
||||
},
|
||||
|
||||
@ -1030,44 +1236,53 @@ minetest.register_craftitem("basic_robot:control", {
|
||||
|
||||
on_secondary_use = function(itemstack, user, pointed_thing)
|
||||
|
||||
local name = user:get_player_name();
|
||||
local owner = user:get_player_name();
|
||||
local code = minetest.formspec_escape(itemstack:get_metadata());
|
||||
local ids = basic_robot.ids[owner]; if not ids then setupid(owner) end
|
||||
local id = basic_robot.ids[owner].id or 1; -- read active id for player
|
||||
local name = owner..id;
|
||||
local form =
|
||||
"size[9.5,1]" .. -- width, height
|
||||
"textarea[1.25,-0.25;8.75,3;code;;".. code.."]"..
|
||||
"button_exit[-0.25,-0.25;1.25,1;OK;SAVE]";
|
||||
minetest.show_formspec(name, "robot_control_" .. name, form);
|
||||
"size[9.5,1.25]" .. -- width, height
|
||||
"textarea[1.25,-0.25;8.75,2.25;code;;".. code.."]"..
|
||||
"button_exit[-0.25,-0.25;1.25,1;OK;SAVE]"..
|
||||
"field[0.25,1;1.,1;id;id;"..id.."]"
|
||||
minetest.show_formspec(owner, "robot_control_" .. name, form);
|
||||
return
|
||||
end,
|
||||
|
||||
on_use = function(itemstack, user, pointed_thing)
|
||||
|
||||
local name = user:get_player_name();
|
||||
local owner = user:get_player_name();
|
||||
local ids = basic_robot.ids[owner]; if not ids then setupid(owner) end
|
||||
local id = basic_robot.ids[owner].id or 1; -- read active id
|
||||
local name = owner .. id
|
||||
|
||||
if basic_robot.data[name] and basic_robot.data[name].sandbox then
|
||||
local data = basic_robot.data[name];
|
||||
|
||||
if data and data.sandbox then
|
||||
|
||||
else
|
||||
minetest.chat_send_player(name, "#remote control: your robot must be running");
|
||||
return
|
||||
end
|
||||
|
||||
local t0 = basic_robot.data[name].remoteuse or 0; -- prevent too fast remote use
|
||||
local t0 = data.remoteuse or 0; -- prevent too fast remote use
|
||||
local t1 = minetest.get_gametime();
|
||||
if t1-t0<1 then return end
|
||||
basic_robot.data[name].remoteuse = t1;
|
||||
data.remoteuse = t1;
|
||||
|
||||
|
||||
script = itemstack:get_metadata();
|
||||
if script == "" then
|
||||
--display control form
|
||||
minetest.show_formspec(name, "robot_manual_control_" .. name, get_manual_control_form(name));
|
||||
minetest.show_formspec(owner, "robot_manual_control_" .. name, get_manual_control_form(name));
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
local ScriptFunc, CompileError = loadstring( script )
|
||||
if CompileError then
|
||||
minetest.chat_send_player(name, "#remote control: compile error " .. CompileError )
|
||||
minetest.chat_send_player(owner, "#remote control: compile error " .. CompileError )
|
||||
return
|
||||
end
|
||||
|
||||
@ -1075,7 +1290,7 @@ minetest.register_craftitem("basic_robot:control", {
|
||||
|
||||
local Result, RuntimeError = pcall( ScriptFunc );
|
||||
if RuntimeError then
|
||||
minetest.chat_send_player(name, "#remote control: run error " .. RuntimeError )
|
||||
minetest.chat_send_player(owner, "#remote control: run error " .. RuntimeError )
|
||||
return
|
||||
end
|
||||
end,
|
||||
@ -1092,10 +1307,10 @@ minetest.register_entity(
|
||||
collisionbox = {-0.15,-0.15,-0.15, 0.15,0.15,0.15},
|
||||
visual ="sprite",
|
||||
visual_size = {x=0.5, y=0.5},
|
||||
textures = {"default_diamond_block.png"},
|
||||
textures = {"heart.png"},
|
||||
is_visible = true,
|
||||
oldvel = {x=0,y=0,z=0},
|
||||
owner = "",
|
||||
name = "", -- name of originating robot
|
||||
|
||||
--on_activate = function(self, staticdata)
|
||||
-- self.object:remove()
|
||||
@ -1108,8 +1323,9 @@ minetest.register_entity(
|
||||
on_step = function(self, dtime)
|
||||
local vel = self.object:getvelocity();
|
||||
if (self.oldvel.x~=0 and vel.x==0) or (self.oldvel.y~=0 and vel.y==0) or (self.oldvel.z~=0 and vel.z==0) then
|
||||
if basic_robot.data[self.owner] then
|
||||
basic_robot.data[self.owner].fire_pos = self.object:getpos();
|
||||
local data = basic_robot.data[self.name];
|
||||
if data then
|
||||
data.fire_pos = self.object:getpos();
|
||||
end
|
||||
self.object:remove()
|
||||
return
|
||||
@ -1134,4 +1350,7 @@ minetest.register_craft({
|
||||
{"default:mese_crystal", "default:mese_crystal","default:mese_crystal"},
|
||||
{"default:stone", "default:steel_ingot", "default:stone"}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
minetest.register_privilege("robot", "increased number of allowed active robots")
|
BIN
textures/control.png
Normal file
BIN
textures/control.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
Loading…
x
Reference in New Issue
Block a user