updated basic_robots

master
TMcSquared 2018-03-31 07:32:13 -05:00
parent 27d0570f40
commit c84f016e42
8 changed files with 239 additions and 81 deletions

View File

@ -49,7 +49,7 @@ local function pos_in_dir(obj, dir) -- position after we move in specified direc
elseif dir == 13 then -- forward_up
pos.y=pos.y+1
elseif dir == 14 then -- backward_up
yaw = yaw + pi; pos.y=pos.y-1
yaw = yaw + pi; pos.y=pos.y+1
end
if dir ~= 5 and dir ~= 6 then
@ -277,35 +277,35 @@ basic_robot.no_teleport_table = {
}
--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
--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);
--local inv = minetest.get_meta(spos):get_inventory();
--local picklist = {};
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);
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
--local detected_obj = lua_entity.itemstring or ""
--if not basic_robot.no_teleport_table[detected_obj] then -- object on no teleport list
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.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)
--picklist[#picklist+1]=detected_obj;
--if inv:room_for_item("main", stack) then
--inv:add_item("main", stack);
--obj:setpos({x=0,y=0,z=0}) -- no dupe
--end
--obj:remove();
--end
--end
--end
--if not picklist[1] then return nil end
--return picklist
--end
local stack = ItemStack(lua_entity.itemstring)
picklist[#picklist+1]=detected_obj;
if inv:room_for_item("main", stack) then
inv:add_item("main", stack);
obj:setpos({x=0,y=0,z=0}) -- no dupe
end
obj:remove();
end
end
end
if not picklist[1] then return nil end
return picklist
end
basic_robot.commands.read_node = function(name,dir)
@ -571,7 +571,7 @@ local register_robot_button = function(R,G,B,type)
on_punch = function(pos, node, player)
local name = player:get_player_name(); if name==nil then return end
local round = math.floor;
local r = 32; local ry = 2*r; -- note: this is skyblock adjusted
local r = basic_robot.radius; local ry = 2*r; -- note: this is skyblock adjusted
local ppos = {x=round(pos.x/r+0.5)*r,y=round(pos.y/ry+0.5)*ry+1,z=round(pos.z/r+0.5)*r}; -- just on top of basic_protect:protector!
local meta = minetest.get_meta(ppos);
local name = meta:get_string("name");
@ -595,7 +595,7 @@ minetest.register_node("basic_robot:button"..number,
on_punch = function(pos, node, player)
local name = player:get_player_name(); if name==nil then return end
local round = math.floor;
local r = 32; local ry = 2*r;
local r = basic_robot.radius; local ry = 2*r;
local ppos = {x=round(pos.x/r+0.5)*r,y=round(pos.y/ry+0.5)*ry+1,z=round(pos.z/r+0.5)*r};
local meta = minetest.get_meta(ppos);
local name = meta:get_string("name");
@ -618,7 +618,7 @@ minetest.register_node("basic_robot:button_"..number,
on_punch = function(pos, node, player)
local name = player:get_player_name(); if name==nil then return end
local round = math.floor;
local r = 32; local ry = 2*r;
local r = basic_robot.radius; local ry = 2*r;
local ppos = {x=round(pos.x/r+0.5)*r,y=round(pos.y/ry+0.5)*ry+1,z=round(pos.z/r+0.5)*r};
local meta = minetest.get_meta(ppos);
local name = meta:get_string("name");
@ -640,7 +640,7 @@ minetest.register_node("basic_robot:button_"..number,
on_punch = function(pos, node, player)
local name = player:get_player_name(); if name==nil then return end
local round = math.floor;
local r = 32; local ry = 2*r;
local r = basic_robot.radius; local ry = 2*r;
local ppos = {x=round(pos.x/r+0.5)*r,y=round(pos.y/ry+0.5)*ry+1,z=round(pos.z/r+0.5)*r};
local meta = minetest.get_meta(ppos);
local name = meta:get_string("name");
@ -675,6 +675,9 @@ register_robot_button_custom(281,"puzzle_NOT")
register_robot_button_custom(282,"puzzle_delayer")
register_robot_button_custom(283,"puzzle_platform")
register_robot_button_custom(284,"puzzle_giver")
register_robot_button_custom(285,"puzzle_checker")
-- interactive button for robot: place robot on top of protector to intercept events
@ -1184,7 +1187,7 @@ basic_robot.commands.crypto = {encrypt = encrypt, decrypt = decrypt, scramble =
local is_same_block = function(pos1,pos2)
local round = math.floor;
local r = 32; local ry = 2*r; -- note: this is skyblock adjusted
local r = basic_robot.radius; local ry = 2*r; -- note: this is skyblock adjusted
local ppos1 = {round(pos1.x/r+0.5)*r,round(pos1.y/ry+0.5)*ry,round(pos1.z/r+0.5)*r};
local ppos2 = {round(pos2.x/r+0.5)*r,round(pos2.y/ry+0.5)*ry,round(pos2.z/r+0.5)*r};
return ppos1[1]==ppos2[1] and ppos1[2]==ppos2[2] and ppos1[3] == ppos2[3]
@ -1351,3 +1354,116 @@ basic_robot.commands.puzzle = {
return true
end,
}
-- VIRTUAL PLAYER --
local Vplayer = {};
function Vplayer:new(name) -- constructor
if not basic_robot.data[name].obj then return end -- only make it for existing robot
if basic_robot.virtual_players[name] then return end -- already exists
local o = {}
setmetatable(o, self)
self.__index = self
o.obj = basic_robot.data[name].obj;
o.data = basic_robot.data[name];
local spawnpos = o.data.spawnpos;
local meta = minetest.get_meta(spawnpos); if not meta then return end
o.inv = meta:get_inventory();
basic_robot.virtual_players[name] = o;
end
-- functions
function Vplayer:getpos() return self.obj:getpos() end
function Vplayer:remove() end
function Vplayer:setpos() end
function Vplayer:move_to() end
function Vplayer:punch() end
function Vplayer:rightlick() end
function Vplayer:get_hp() return 20 end
function Vplayer:set_hp() return 20 end
function Vplayer:get_inventory() return self.inv end
function Vplayer:get_wield_list() return "main" end
function Vplayer:get_wield_index() return 1 end
function Vplayer:get_wielded_item() return self.inv:get_stack("main", 1) end
function Vplayer:set_wielded_item() end
function Vplayer:set_armor_groups() end
function Vplayer:get_armor_groups() return {fleshy = 100} end
function Vplayer:set_animation() end
function Vplayer:get_animation() end
function Vplayer:set_attach() end
function Vplayer:get_attach() end
function Vplayer:set_detach() end
function Vplayer:set_bone_position() end
function Vplayer:get_bone_position() end
function Vplayer:set_properties() end
function Vplayer:get_properties() end
function Vplayer:is_player() return true end
function Vplayer:get_nametag_attributes() end
function Vplayer:set_nametag_attributes() end
function Vplayer:set_velocity() end
function Vplayer:get_velocity() end
function Vplayer:set_acceleration() end
function Vplayer:get_acceleration() end
function Vplayer:set_yaw() end
function Vplayer:get_yaw() end
function Vplayer:set_texture_mod() end
function Vplayer:get_luaentity() end
function Vplayer:get_player_name() return self.data.name end
function Vplayer:get_player_velocity() return {x=0,y=0,z=0} end
function Vplayer:get_look_dir() return {x=1,y=0,z=0} end
function Vplayer:get_look_vertical() return 0 end
function Vplayer:get_look_horizontal() return 0 end
function Vplayer:set_look_vertical() end
function Vplayer:set_look_horizontal() end
function Vplayer:get_breath() return 1 end
function Vplayer:set_breath() end
function Vplayer:set_attribute() end
function Vplayer:get_attribute() end
function Vplayer:set_inventory_formspec() end
function Vplayer:get_inventory_formspec() return "" end
function Vplayer:get_player_control() return {} end
function Vplayer:get_player_control_bits() return 0 end
function Vplayer:set_physics_override() end
function Vplayer:get_physics_override() return {} end
function Vplayer:hud_add() end
function Vplayer:hud_remove() end
function Vplayer:hud_change() end
function Vplayer:hud_get() end
function Vplayer:hud_set_flags() end
function Vplayer:hud_get_flags() return {} end
function Vplayer:hud_set_hotbar_itemcount() end
function Vplayer:hud_get_hotbar_itemcount() return 0 end
function Vplayer:hud_set_hotbar_image() end
function Vplayer:hud_get_hotbar_image() return "" end
function Vplayer:hud_set_hotbar_selected_image() end
function Vplayer:hud_get_hotbar_selected_image() return "" end
function Vplayer:set_sky() end
function Vplayer:get_sky() end
function Vplayer:set_clouds() end
function Vplayer:get_clouds() end
function Vplayer:override_day_night_ratio() end
function Vplayer:get_day_night_ratio() end
function Vplayer:set_local_animation() end
function Vplayer:get_local_animation() end
function Vplayer:set_eye_offset() end
function Vplayer:get_eye_offset() end
-- code for act borrowed from: https://github.com/minetest-mods/pipeworks/blob/fa4817136c8d1e62dafd6ab694821cba255b5206/wielder.lua, line 372

View File

@ -4,11 +4,12 @@
basic_robot = {};
---- SETTINGS ------
basic_robot.call_limit = 48; -- how many execution calls per script run allowed
basic_robot.entry_count = 2 -- how many robot ordinary player can have
basic_robot.entry_count = 2 -- how many robots ordinary player can have
basic_robot.advanced_count = 16 -- how many robots player with robot privs can have
basic_robot.radius = 32; -- divide whole world into blocks of this size - used for managing events like keyboard punches
basic_robot.password = "password"; -- IMPORTANT: change it before running mod, password used for authentifications
basic_robot.bad_inventory_blocks = { -- disallow taking from these nodes inventories
basic_robot.bad_inventory_blocks = { -- disallow taking from these nodes inventories to prevent player abuses
["craft_guide:sign_wall"] = true,
}
basic_robot.maxoperations = 2; -- how many operations (dig, generate energy,..) available per run, 0 = unlimited
@ -17,15 +18,17 @@ basic_robot.dig_require_energy = true; -- does robot require energy to dig?
basic_robot.http_api = minetest.request_http_api();
basic_robot.version = "2017/10 /07a";
basic_robot.version = "2018/02/06a";
basic_robot.data = {}; -- stores all robot data
basic_robot.data = {}; -- stores all robot related data
--[[
[name] = { sandbox= .., bytecode = ..., ram = ..., obj = robot object,spawnpos=...}
[name] = { sandbox= .., bytecode = ..., ram = ..., obj = robot object, spawnpos= ..., authlevel = ...}
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.ids = {}; -- stores maxid for each player
--[name] = {id = .., maxid = .. }, current id for robot controller, how many robot ids player can use
basic_robot.virtual_players = {}; -- this way robot can interact with the world as "player" TODO
basic_robot.data.listening = {}; -- which robots listen to chat
dofile(minetest.get_modpath("basic_robot").."/commands.lua")
@ -38,6 +41,8 @@ local check_code, preprocess_code,is_inside_string;
function getSandboxEnv (name)
local authlevel = basic_robot.data[name].authlevel or 0;
local commands = basic_robot.commands;
local directions = {left = 1, right = 2, forward = 3, backward = 4, up = 5, down = 6,
left_down = 7, right_down = 8, forward_down = 9, backward_down = 10,
@ -114,17 +119,6 @@ function getSandboxEnv (name)
return sender,mail
end,
read_form = function()
local fields = basic_robot.data[name].read_form;
local sender = basic_robot.data[name].form_sender;
basic_robot.data[name].read_form = nil;
basic_robot.data[name].form_sender = nil;
return sender,fields
end,
show_form = function(playername, form)
commands.show_form(name, playername, form)
end,
send_mail = function(target,mail)
if not basic_robot.data[target] then return false end
@ -157,7 +151,7 @@ function getSandboxEnv (name)
end
end,
fire = function(speed, pitch,gravity, is_entity) -- experimental: fires an projectile
fire = function(speed, pitch,gravity, texture, is_entity) -- experimental: fires an projectile
local obj = basic_robot.data[name].obj;
local pos = obj:getpos();
local yaw = obj:getyaw();
@ -171,7 +165,7 @@ function getSandboxEnv (name)
expirationtime = 10,
velocity = {x=speed*math.cos(yaw)*math.cos(pitch), y=speed*math.sin(pitch),z=speed*math.sin(yaw)*math.cos(pitch)},
size = 5,
texture = "default_apple.png",
texture = texture or "default_apple.png",
acceleration = {x=0,y=-gravity,z=0},
collisiondetection = true,
collision_removal = true,
@ -346,7 +340,7 @@ function getSandboxEnv (name)
end,
run = function(script)
if basic_robot.data[name].isadmin ~= 1 then
if basic_robot.data[name].authlevel < 3 then
local err = check_code(script);
script = preprocess_code(script);
if err then
@ -485,10 +479,23 @@ function getSandboxEnv (name)
env.write_text[dir] = function(text) return commands.write_text(name, dir_id,text) end
end
-- set up sandbox for puzzle
if authlevel>=1 then -- robot privs
env.self.read_form = function()
local fields = basic_robot.data[name].read_form;
local sender = basic_robot.data[name].form_sender;
basic_robot.data[name].read_form = nil;
basic_robot.data[name].form_sender = nil;
return sender,fields
end
env.self.show_form = function(playername, form)
commands.show_form(name, playername, form)
end
end
local ispuzzle = basic_robot.data[name].ispuzzle; -- need puzzle privs
if ispuzzle == 1 then
-- set up sandbox for puzzle
if authlevel>=2 then -- puzzle privs
basic_robot.data[name].puzzle = {};
local data = basic_robot.data[name];
local pdata = data.puzzle;
@ -516,13 +523,11 @@ function getSandboxEnv (name)
pdata = pdata,
ItemStack = ItemStack,
}
end
--special sandbox for admin
local isadmin=basic_robot.data[name].isadmin
if isadmin~=1 then
if authlevel<3 then -- is admin?
env._G = env;
else
env.minetest = minetest;
@ -675,7 +680,7 @@ end
local function setCode( name, script ) -- to run script: 1. initSandbox 2. setCode 3. runSandbox
local err;
if basic_robot.data[name].isadmin~=1 then
if basic_robot.data[name].authlevel<3 then -- not admin
err = check_code(script);
script = preprocess_code(script);
end
@ -806,9 +811,7 @@ local function init_robot(obj)
basic_robot.data[name].quiet_mode = false; -- can chat globally
-- check if admin robot
if self.isadmin then basic_robot.data[name].isadmin = 1 end
-- can we do puzzles?
if self.ispuzzle then basic_robot.data[name].ispuzzle = 1 end
basic_robot.data[name].authlevel = self.authlevel or 0
--robot appearance,armor...
obj:set_properties({infotext = "robot " .. name});
@ -833,7 +836,7 @@ minetest.register_entity("basic_robot:robot",{
--textures={"character.png"},
visual="cube",
textures={"arrow.png","basic_machine_side.png","face.png","basic_machine_side.png","basic_machine_side.png","basic_machine_side.png"},
textures={"topface.png","legs.png","face.png","face-back.png","left-hand.png","right-hand.png"},
visual_size={x=1,y=1},
running = 0, -- does it run code or is it idle?
@ -856,6 +859,8 @@ minetest.register_entity("basic_robot:robot",{
end
self.owner = data.owner;
self.authlevel = data.authlevel;
self.spawnpos = {x=data.spawnpos.x,y=data.spawnpos.y,z=data.spawnpos.z};
init_robot(self.object);
self.running = 1;
@ -985,7 +990,13 @@ local spawn_robot = function(pos,node,ttl)
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
data.authlevel = meta:get_int("authlevel")
local sec_hash = minetest.get_password_hash("",data.authlevel.. owner .. basic_robot.password)
if meta:get_string("sec_hash")~= sec_hash then
minetest.chat_send_player(owner,"#ROBOT: " .. name .. " is using fake auth level. dig and place again.")
return
end
if not data.obj then
--create virtual robot that reports position and other properties
@ -1007,8 +1018,8 @@ local spawn_robot = function(pos,node,ttl)
if not data.bytecode then
local script = meta:get_string("code");
if data.isadmin~=1 then
if data.authlevel<3 then -- not admin
err = check_code(script);
script = preprocess_code(script);
end
@ -1059,8 +1070,14 @@ local spawn_robot = function(pos,node,ttl)
luaent.name = name;
luaent.code = meta:get_string("code");
luaent.spawnpos = {x=pos.x,y=pos.y-1,z=pos.z};
if meta:get_int("admin") == 1 then luaent.isadmin = 1 end
if meta:get_int("puzzle") == 1 then luaent.ispuzzle = 1 end
luaent.authlevel = meta:get_int("authlevel")
local sec_hash = minetest.get_password_hash("",luaent.authlevel.. owner .. basic_robot.password)
if meta:get_string("sec_hash")~= sec_hash then
minetest.chat_send_player(owner,"#ROBOT: " .. name .. " is using fake auth level. dig and place again.")
obj:remove();
return
end
local data = basic_robot.data[name];
if data == nil then
@ -1253,6 +1270,9 @@ local on_receive_robot_form = function(pos, formname, fields, sender)
if fields.code then
local code = fields.code or "";
if string.len(code) > 64000 then
minetest.chat_send_all("#ROBOT: " .. name .. " is spamming with long text.") return
end
if meta:get_int("admin") == 1 then
local privs = minetest.get_player_privs(name); -- only admin can edit admin robot code
@ -1346,7 +1366,7 @@ local on_receive_robot_form = function(pos, formname, fields, sender)
" self.reset() resets robot position\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"..
" self.fire(speed, pitch,gravity, texture, is_entity) fires a projectile from robot\n"..
" self.fire_pos() returns last hit position\n"..
" self.label(text) changes robot label\n"..
" self.display_text(text,linesize,size) displays text instead of robot face, if no size return tex\n"..
@ -1520,6 +1540,9 @@ minetest.register_on_player_receive_fields(
local name = string.sub(formname, string.len(robot_formname)+1); -- robot name
if fields.OK and fields.code then
local item = player:get_wielded_item(); --set_wielded_item(item)
if string.len(fields.code) > 1000 then
minetest.chat_send_player(player,"#ROBOT: text too long") return
end
item:set_metadata(fields.code);
player:set_wielded_item(item);
if fields.id then
@ -1661,6 +1684,9 @@ minetest.register_on_player_receive_fields(
local data = itemstack:get_meta():to_table().fields -- 0.4.16, old minetest.deserialize(itemstack:get_metadata())
if not data then data = {} end
local text = fields.book or "";
if string.len(text) > 64000 then
minetest.chat_send_all("#ROBOT: " .. sender .. " is spamming with long text.") return
end
data.text = text or ""
data.title = fields.title or ""
data.text_len = #data.text
@ -1720,10 +1746,24 @@ minetest.register_node("basic_robot:spawner", {
alpha = 150,
after_place_node = function(pos, placer)
local meta = minetest.env:get_meta(pos)
meta:set_string("owner", placer:get_player_name());
local owner = placer:get_player_name();
meta:set_string("owner", owner);
local privs = minetest.get_player_privs(placer:get_player_name());
if privs.privs then meta:set_int("admin",1) end
if privs.puzzle then meta:set_int("puzzle",1) end
local authlevel = 0;
if privs.privs then -- set auth level depending on privs
authlevel = 3
elseif privs.puzzle then
authlevel = 2
elseif privs.robot then
authlevel = 1
else
authlevel = 0
end
meta:set_int("authlevel",authlevel)
local sec_hash = minetest.get_password_hash("",authlevel .. owner .. basic_robot.password) -- 'digitally sign' authlevel using password
meta:set_string("sec_hash", sec_hash);
meta:set_string("code","");
meta:set_int("id",1); -- initial robot id
@ -1827,9 +1867,9 @@ minetest.register_craftitem("basic_robot:control", {
local owner = user:get_player_name();
local script = itemstack:get_metadata();
if script == "@" then -- remote control as a tool - notify robot in current block of pointed position
if script == "@" then -- remote control as a tool - notify robot in current block of pointed position, using keyboard event type 0
local round = math.floor;
local r = 32; local ry = 2*r; -- note: this is skyblock adjusted
local r = basic_robot.radius; local ry = 2*r; -- note: this is skyblock adjusted
local pos = pointed_thing.under
if not pos then return end
local ppos = {x=round(pos.x/r+0.5)*r,y=round(pos.y/ry+0.5)*ry+1,z=round(pos.z/r+0.5)*r}; -- just on top of basic_protect:protector!
@ -1850,7 +1890,7 @@ minetest.register_craftitem("basic_robot:control", {
if data and data.sandbox then
else
minetest.chat_send_player(name, "#remote control: your robot must be running");
minetest.chat_send_player(owner, "#remote control: your robot must be running");
return
end
@ -1859,7 +1899,7 @@ minetest.register_craftitem("basic_robot:control", {
if t1-t0<1 then return end
data.remoteuse = t1;
if data.isadmin == 1 then
if data.authlevel >= 3 then
local privs = minetest.get_player_privs(owner); -- only admin can run admin robot
if not privs.privs then
return
@ -1872,7 +1912,7 @@ minetest.register_craftitem("basic_robot:control", {
return
end
if not data.isadmin then
if data.authlevel<3 then
if check_code(script)~=nil then return end
end
@ -1967,3 +2007,5 @@ minetest.register_craft({
minetest.register_privilege("robot", "increased number of allowed active robots")
minetest.register_privilege("puzzle", "allow player to use puzzle. namespace in robots")
print('[MOD]'.. " basic_robot " .. basic_robot.version .. " loaded.")

View File

@ -1,7 +1,7 @@
-- SOKOBAN GAME, by rnd, robots port
if not sokoban then
sokoban = {};
local players = find_player(4);
local players = find_player(5);
if not players then error("sokoban: no player near") end
name = players[1];
@ -37,7 +37,7 @@
if lvl == nil then return end
if lvl <0 or lvl >89 then return end
local file = _G.io.open(minetest.get_modpath("basic_robot").."/scripts/sokoban.txt","r")
local file = _G.io.open(minetest.get_modpath("basic_robot").."\\scripts\\sokoban.txt","r")
if not file then return end
local str = ""; local s; local p = {x=pos.x,y=pos.y,z=pos.z}; local i,j;i=0;
local lvl_found = false

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 676 B

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 795 B

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 732 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B