milan2018_v3 #28

Closed
milan wants to merge 66 commits from milan2018_v3 into master
75 changed files with 855 additions and 5843 deletions

View file

@ -1,24 +0,0 @@
BASIC_MACHINES: lightweight automation mod for minetest
minetest 0.4.14+
(c) 2015-2016 rnd
textures by rnd, new textures by SaKeL (2016) and Jozet (2017)
MANUAL:
1.WIKI PAGES: https://github.com/ac-minetest/basic_machines/wiki
2.ingame help: right click mover/detector/keypad.. and click help button
---------------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------

View file

@ -1,354 +0,0 @@
-- modified and adapted from pipeworks mod by VanessaE
-- by rnd
-- disabled timers and on/off button, now autocrafter is only activated by signal
local autocrafterCache = {} -- caches some recipe data to avoid to call the slow function minetest.get_craft_result() every second
local craft_time = 1
local function count_index(invlist)
local index = {}
for _, stack in pairs(invlist) do
if not stack:is_empty() then
local stack_name = stack:get_name()
index[stack_name] = (index[stack_name] or 0) + stack:get_count()
end
end
return index
end
local function get_item_info(stack)
local name = stack:get_name()
local def = minetest.registered_items[name]
local description = def and def.description or "Unknown item"
return description, name
end
local function get_craft(pos, inventory, hash)
local hash = hash or minetest.hash_node_position(pos)
local craft = autocrafterCache[hash]
if not craft then
local recipe = inventory:get_list("recipe")
local output, decremented_input = minetest.get_craft_result({method = "normal", width = 3, items = recipe})
craft = {recipe = recipe, consumption=count_index(recipe), output = output, decremented_input = decremented_input}
autocrafterCache[hash] = craft
end
return craft
end
local function autocraft(inventory, craft)
if not craft then return false end
local output_item = craft.output.item
-- check if we have enough room in dst
if not inventory:room_for_item("dst", output_item) then return false end
local consumption = craft.consumption
local inv_index = count_index(inventory:get_list("src"))
-- check if we have enough material available
for itemname, number in pairs(consumption) do
if (not inv_index[itemname]) or inv_index[itemname] < number then return false end
end
-- consume material
for itemname, number in pairs(consumption) do
for i = 1, number do -- We have to do that since remove_item does not work if count > stack_max
inventory:remove_item("src", ItemStack(itemname))
end
end
-- craft the result into the dst inventory and add any "replacements" as well
inventory:add_item("dst", output_item)
for i = 1, 9 do
inventory:add_item("dst", craft.decremented_input.items[i])
end
return true
end
-- returns false to stop the timer, true to continue running
-- is started only from start_autocrafter(pos) after sanity checks and cached recipe
local function run_autocrafter(pos, elapsed)
local meta = minetest.get_meta(pos)
local inventory = meta:get_inventory()
local craft = get_craft(pos, inventory)
local output_item = craft.output.item
-- only use crafts that have an actual result
if output_item:is_empty() then
meta:set_string("infotext", "unconfigured Autocrafter: unknown recipe")
return false
end
for step = 1, math.floor(elapsed/craft_time) do
local continue = autocraft(inventory, craft)
if not continue then return false end
end
return true
end
local function start_crafter(pos) -- rnd we dont need timer anymore
-- local meta = minetest.get_meta(pos)
-- if meta:get_int("enabled") == 1 then
-- local timer = minetest.get_node_timer(pos)
-- if not timer:is_started() then
-- timer:start(craft_time)
-- end
-- end
end
local function after_inventory_change(pos)
start_crafter(pos)
end
-- note, that this function assumes allready being updated to virtual items
-- and doesn't handle recipes with stacksizes > 1
local function after_recipe_change(pos, inventory)
local meta = minetest.get_meta(pos)
-- if we emptied the grid, there's no point in keeping it running or cached
if inventory:is_empty("recipe") then
--minetest.get_node_timer(pos):stop()
autocrafterCache[minetest.hash_node_position(pos)] = nil
meta:set_string("infotext", "unconfigured Autocrafter")
return
end
local recipe_changed = false
local recipe = inventory:get_list("recipe")
local hash = minetest.hash_node_position(pos)
local craft = autocrafterCache[hash]
if craft then
-- check if it changed
local cached_recipe = craft.recipe
for i = 1, 9 do
if recipe[i]:get_name() ~= cached_recipe[i]:get_name() then
autocrafterCache[hash] = nil -- invalidate recipe
craft = nil
break
end
end
end
craft = craft or get_craft(pos, inventory, hash)
local output_item = craft.output.item
local description, name = get_item_info(output_item)
meta:set_string("infotext", string.format("'%s' Autocrafter (%s)", description, name))
inventory:set_stack("output", 1, output_item)
after_inventory_change(pos)
end
-- clean out unknown items and groups, which would be handled like unknown items in the crafting grid
-- if minetest supports query by group one day, this might replace them
-- with a canonical version instead
local function normalize(item_list)
for i = 1, #item_list do
local name = item_list[i]
if not minetest.registered_items[name] then
item_list[i] = ""
end
end
return item_list
end
local function on_output_change(pos, inventory, stack)
if not stack then
inventory:set_list("output", {})
inventory:set_list("recipe", {})
else
local input = minetest.get_craft_recipe(stack:get_name())
if not input.items or input.type ~= "normal" then return end
local items, width = normalize(input.items), input.width
local item_idx, width_idx = 1, 1
for i = 1, 9 do
if width_idx <= width then
inventory:set_stack("recipe", i, items[item_idx])
item_idx = item_idx + 1
else
inventory:set_stack("recipe", i, ItemStack(""))
end
width_idx = (width_idx < 3) and (width_idx + 1) or 1
end
-- we'll set the output slot in after_recipe_change to the actual result of the new recipe
end
after_recipe_change(pos, inventory)
end
-- returns false if we shouldn't bother attempting to start the timer again after this
local function update_meta(meta, enabled)
--local state = enabled and "on" or "off"
--meta:set_int("enabled", enabled and 1 or 0)
meta:set_string("formspec",
"size[8,11]"..
"list[context;recipe;0,0;3,3;]"..
"image[3,1;1,1;gui_hb_bg.png^[colorize:#141318:255]"..
"list[context;output;3,1;1,1;]"..
--"image_button[3,2;1,1;pipeworks_button_" .. state .. ".png;" .. state .. ";;;false;pipeworks_button_interm.png]" .. -- rnd disable button
"list[context;src;0,3.5;8,3;]"..
"list[context;dst;4,0;4,3;]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
default.get_hotbar_bg(0,7)..
"list[current_player;main;0,7;8,4;]"..
"listring[context;dst]"..
"listring[current_player;main]"..
"listring[context;src]"..
"listring[current_player;main]"..
"listring[context;recipe]"..
"listring[current_player;main]"
)
-- toggling the button doesn't quite call for running a recipe change check
-- so instead we run a minimal version for infotext setting only
-- this might be more written code, but actually executes less
local output = meta:get_inventory():get_stack("output", 1)
if output:is_empty() then -- doesn't matter if paused or not
meta:set_string("infotext", "unconfigured Autocrafter: Place items for recipe top left. To operate place required items in bottom space (src inventory) and activated with keypad signal. Obtain crafted item from top right (dst inventory).")
return false
end
local description, name = get_item_info(output)
local infotext = enabled and string.format("'%s' Autocrafter (%s)", description, name)
or string.format("paused '%s' Autocrafter", description)
meta:set_string("infotext", infotext)
return enabled
end
-- 1st version of the autocrafter had actual items in the crafting grid
-- the 2nd replaced these with virtual items, dropped the content on update and set "virtual_items" to string "1"
-- the third added an output inventory, changed the formspec and added a button for enabling/disabling
-- so we work out way backwards on this history and update each single case to the newest version
local function upgrade_autocrafter(pos, meta)
local meta = meta or minetest.get_meta(pos)
local inv = meta:get_inventory()
if inv:get_size("output") == 0 then -- we are version 2 or 1
inv:set_size("output", 1)
-- migrate the old autocrafters into an "enabled" state
update_meta(meta, true)
if meta:get_string("virtual_items") == "1" then -- we are version 2
-- we allready dropped stuff, so lets remove the metadatasetting (we are not being called again for this node)
meta:set_string("virtual_items", "")
else -- we are version 1
local recipe = inv:get_list("recipe")
if not recipe then return end
for idx, stack in ipairs(recipe) do
if not stack:is_empty() then
minetest.item_drop(stack, "", pos)
stack:set_count(1)
stack:set_wear(0)
inv:set_stack("recipe", idx, stack)
end
end
end
-- update the recipe, cache, and start the crafter
autocrafterCache[minetest.hash_node_position(pos)] = nil
after_recipe_change(pos, inv)
end
end
minetest.register_node("basic_machines:autocrafter", {
description = "Autocrafter",
drawtype = "normal",
tiles = {"pipeworks_autocrafter.png"},
groups = {cracky=3, mesecon_effector_on = 1},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
inv:set_size("src", 3*8)
inv:set_size("recipe", 3*3)
inv:set_size("dst", 4*3)
inv:set_size("output", 1)
update_meta(meta, false)
end,
on_receive_fields = function(pos, formname, fields, sender)
--if not pipeworks.may_configure(pos, sender) then return end
local meta = minetest.get_meta(pos)
if fields.on then
update_meta(meta, false)
--minetest.get_node_timer(pos):stop()
elseif fields.off then
if update_meta(meta, true) then
start_crafter(pos)
end
end
end,
can_dig = function(pos, player)
upgrade_autocrafter(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return (inv:is_empty("src") and inv:is_empty("dst"))
end,
after_place_node = function(pos, placer) -- rnd : set owner
local meta = minetest.get_meta(pos);
meta:set_string("owner", placer:get_player_name());
end,
--after_place_node = pipeworks.scan_for_tube_objects,
--after_dig_node = function(pos)
--pipeworks.scan_for_tube_objects(pos)
--end,
on_destruct = function(pos)
autocrafterCache[minetest.hash_node_position(pos)] = nil
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
--if not pipeworks.may_configure(pos, player) then return 0 end
local meta = minetest.get_meta(pos);if meta:get_string("owner")~=player:get_player_name() then return 0 end -- rnd
upgrade_autocrafter(pos)
local inv = minetest.get_meta(pos):get_inventory()
if listname == "recipe" then
stack:set_count(1)
inv:set_stack(listname, index, stack)
after_recipe_change(pos, inv)
return 0
elseif listname == "output" then
on_output_change(pos, inv, stack)
return 0
end
after_inventory_change(pos)
return stack:get_count()
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
--if not pipeworks.may_configure(pos, player) then
-- minetest.log("action", string.format("%s attempted to take from autocrafter at %s", player:get_player_name(), minetest.pos_to_string(pos)))
-- return 0
-- end
local meta = minetest.get_meta(pos);if meta:get_string("owner")~=player:get_player_name() then return 0 end -- rnd
upgrade_autocrafter(pos)
local inv = minetest.get_meta(pos):get_inventory()
if listname == "recipe" then
inv:set_stack(listname, index, ItemStack(""))
after_recipe_change(pos, inv)
return 0
elseif listname == "output" then
on_output_change(pos, inv, nil)
return 0
end
after_inventory_change(pos)
return stack:get_count()
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
return 0; -- no internal inventory moves!
end,
mesecons = {effector = { -- rnd: run machine when activated by signal
action_on = function (pos, node,ttl)
if type(ttl)~="number" then ttl = 1 end
if ttl<0 then return end -- machines_TTL prevents infinite recursion
run_autocrafter(pos, craft_time);
end
}
}
--on_timer = run_autocrafter -- rnd
})
-- minetest.register_craft( {
-- output = "basic_machines:autocrafter",
-- recipe = {
-- { "default:steel_ingot", "default:mese_crystal", "default:steel_ingot" },
-- { "default:diamondblock", "default:steel_ingot", "default:diamondblock" },
-- { "default:steel_ingot", "default:mese_crystal", "default:steel_ingot" }
-- },
-- })

View file

@ -1,669 +0,0 @@
-- BALL: energy ball that flies around, can bounce and activate stuff
-- rnd 2016:
-- TO DO: move mode: ball just rolling around on ground without hopping, also if inside slope it would "roll down", just increased velocity in slope direction
-- SETTINGS
basic_machines.ball = {};
basic_machines.ball.maxdamage = 10; -- player health 20
basic_machines.ball.bounce_materials = { -- to be used with bounce setting 2 in ball spawner: 1: bounce in x direction, 2: bounce in z direction, otherwise it bounces in y direction
["default:wood"]=1,
["xpanes:bar_2"]=1,
["xpanes:bar_10"]=1,
["darkage:iron_bars"]=1,
["default:glass"] = 2,
};
-- END OF SETTINGS
local ballcount = {};
local function round(x)
if x < 0 then
return -math.floor(-x+0.5);
else
return math.floor(x+0.5);
end
end
local ball_spawner_update_form = function (pos)
local meta = minetest.get_meta(pos);
local x0,y0,z0;
x0=meta:get_int("x0");y0=meta:get_int("y0");z0=meta:get_int("z0"); -- direction of velocity
local energy,bounce,g,puncheable, gravity,hp,hurt,solid;
local speed = meta:get_float("speed"); -- if positive sets initial ball speed
energy = meta:get_float("energy"); -- if positive activates, negative deactivates, 0 does nothing
bounce = meta:get_int("bounce"); -- if nonzero bounces when hit obstacle, 0 gets absorbed
gravity = meta:get_float("gravity"); -- gravity
hp = meta:get_float("hp");
hurt = meta:get_float("hurt");
puncheable = meta:get_int("puncheable"); -- if 1 can be punched by players in protection, if 2 can be punched by anyone
solid = meta:get_int("solid"); -- if 1 then entity is solid - cant be walked on
local texture = meta:get_string("texture") or "basic_machines_ball.png";
local visual = meta:get_string("visual") or "sprite";
local scale = meta:get_int("scale");
local form =
"size[4.25,4.75]" .. -- width, height
"field[0.25,0.5;1,1;x0;target;"..x0.."] field[1.25,0.5;1,1;y0;;"..y0.."] field[2.25,0.5;1,1;z0;;"..z0.."]"..
"field[3.25,0.5;1,1;speed;speed;"..speed.."]"..
--speed, jump, gravity,sneak
"field[0.25,1.5;1,1;energy;energy;"..energy.."]"..
"field[1.25,1.5;1,1;bounce;bounce;".. bounce.."]"..
"field[2.25,1.5;1,1;gravity;gravity;"..gravity.."]"..
"field[3.25,1.5;1,1;puncheable;puncheable;"..puncheable.."]"..
"field[3.25,2.5;1,1;solid;solid;"..solid.."]"..
"field[0.25,2.5;1,1;hp;hp;"..hp.."]".."field[1.25,2.5;1,1;hurt;hurt;"..hurt.."]"..
"field[0.25,3.5;4,1;texture;texture;"..minetest.formspec_escape(texture).."]"..
"field[0.25,4.5;1,1;scale;scale;"..scale.."]".."field[1.25,4.5;1,1;visual;visual;"..visual.."]"..
"button_exit[3.25,4.25;1,1;OK;OK]";
if meta:get_int("admin")==1 then
local lifetime = meta:get_int("lifetime");
if lifetime <= 0 then lifetime = 20 end
form = form .. "field[2.25,2.5;1,1;lifetime;lifetime;"..lifetime.."]"
end
meta:set_string("formspec",form);
end
minetest.register_entity("basic_machines:ball",{
timer = 0,
lifetime = 20, -- how long it exists before disappearing
energy = 0, -- if negative it will deactivate stuff, positive will activate, 0 wont do anything
puncheable = 1, -- can be punched by players in protection
bounce = 0, -- 0: absorbs in block, 1 = proper bounce=lag buggy, -- to do: 2 = line of sight bounce
gravity = 0,
speed = 5, -- velocity when punched
hurt = 0, -- how much damage it does to target entity, if 0 damage disabled
owner = "",
state = false,
origin = {x=0,y=0,z=0},
lastpos = {x=0,y=0,z=0}, -- last not-colliding position
hp_max = 100,
elasticity = 0.9, -- speed gets multiplied by this after bounce
visual="sprite",
visual_size={x=.6,y=.6},
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
physical=false,
--textures={"basic_machines_ball"},
on_activate = function(self, staticdata)
self.object:set_properties({textures={"basic_machines_ball.png"}})
self.object:set_properties({visual_size = {x=1, y=1}});
self.timer = 0;self.owner = "";
self.origin = self.object:getpos();
self.lifetime = 20;
end,
get_staticdata = function(self) -- this gets called before object put in world and before it hides
if not self.state then return nil end
self.object:remove();
return nil
end,
on_punch = function (self, puncher, time_from_last_punch, tool_capabilities, dir)
if self.puncheable == 0 then return end
if self.puncheable == 1 then -- only those in protection
local name = puncher:get_player_name();
local pos = self.object:getpos();
if minetest.is_protected(pos,name) then return end
end
--minetest.chat_send_all(minetest.pos_to_string(dir))
if time_from_last_punch<0.5 then return end
local v = self.speed or 1;
local velocity = dir;
velocity.x = velocity.x*v;velocity.y = velocity.y*v;velocity.z = velocity.z*v;
self.object:setvelocity(velocity)
end,
on_step = function(self, dtime)
self.timer=self.timer+dtime
if self.timer>self.lifetime then
local count = ballcount[self.owner] or 1; count=count-1; ballcount[self.owner] = count;
self.object:remove()
return
end
if not self.state then self.state = true end
local pos=self.object:getpos()
local origin = self.origin;
local r = 30;-- maximal distance when balls disappear
local dist = math.max(math.abs(pos.x-origin.x), math.abs(pos.y-origin.y), math.abs(pos.z-origin.z));
if dist>r then -- remove if it goes too far
local count = ballcount[self.owner] or 1; count=count-1; ballcount[self.owner] = count;
self.object:remove()
return
end
local nodename = minetest.get_node(pos).name;
local walkable = false;
if nodename ~= "air" then
walkable = minetest.registered_nodes[nodename].walkable;
if nodename == "basic_machines:ball_spawner" and dist>0.5 then walkable = true end -- ball can activate spawner, just not originating one
end
if not walkable then
self.lastpos = pos
if self.hurt~=0 then -- check for coliding nearby objects
local objects = minetest.get_objects_inside_radius(pos,2);
if #objects>1 then
for _, obj in pairs(objects) do
local p = obj:getpos();
local d = math.sqrt((p.x-pos.x)^2+(p.y-pos.y)^2+(p.z-pos.z)^2);
if d>0 then
--if minetest.is_protected(p,self.owner) then return end
if math.abs(p.x)<32 and math.abs(p.y)<32 and math.abs(p.z)<32 then return end -- no damage around spawn
if obj:is_player() then --player
if obj:get_player_name()==self.owner then break end -- dont hurt owner
local hp = obj:get_hp()
local newhp = hp-self.hurt;
if newhp<=0 and boneworld and boneworld.killxp then
local killxp = boneworld.killxp[self.owner];
if killxp then
boneworld.killxp[self.owner] = killxp + 0.01;
end
end
obj:set_hp(newhp)
else -- non player
local lua_entity = obj:get_luaentity();
if lua_entity and lua_entity.itemstring then
local entname = lua_entity.itemstring;
if entname == "robot" then
self.object:remove()
return;
end
end
local hp = obj:get_hp()
local newhp = hp-self.hurt;
minetest.chat_send_player(self.owner,"#ball: target hp " .. newhp)
if newhp<=0 then obj:remove() else obj:set_hp(newhp) end
end
local count = ballcount[self.owner] or 1; count=count-1; ballcount[self.owner] = count;
self.object:remove();
return
end
end
end
end
end
if walkable then -- we hit a node
--minetest.chat_send_all(" hit node at " .. minetest.pos_to_string(pos))
local node = minetest.get_node(pos);
local table = minetest.registered_nodes[node.name];
if table and table.mesecons and table.mesecons.effector then -- activate target
local energy = self.energy;
if energy~=0 then
if minetest.is_protected(pos,self.owner) then return end
end
local effector = table.mesecons.effector;
self.object:remove();
if energy>0 then
if not effector.action_on then return end
effector.action_on(pos,node,16);
elseif energy<0 then
if not effector.action_off then return end
effector.action_off(pos,node,16);
end
else -- bounce ( copyright rnd, 2016 )
local bounce = self.bounce;
if self.bounce == 0 then
local count = ballcount[self.owner] or 1; count=count-1; ballcount[self.owner] = count;
self.object:remove()
return end
local n = {x=0,y=0,z=0}; -- this will be bounce normal
local v = self.object:getvelocity();
local opos = {x=round(pos.x),y=round(pos.y), z=round(pos.z)}; -- obstacle
local bpos ={ x=(pos.x-opos.x),y=(pos.y-opos.y),z=(pos.z-opos.z)}; -- boundary position on cube, approximate
if bounce == 2 then -- uses special blocks for non buggy lag proof bouncing: by default it bounces in y direction
local bounce_direction = basic_machines.ball.bounce_materials[node.name] or 0;
if bounce_direction == 0 then
if v.y>=0 then n.y = -1 else n.y = 1 end
elseif bounce_direction == 1 then
if v.x>=0 then n.x = -1 else n.x = 1 end
n.y = 0;
elseif bounce_direction == 2 then
if v.z>=0 then n.z = -1 else n.z = 1 end
n.y = 0;
end
else -- algorithm to determine bounce direction - problem: with lag its impossible to determine reliable which node was hit and which face ..
if v.x<=0 then n.x = 1 else n.x = -1 end -- possible bounce directions
if v.y<=0 then n.y = 1 else n.y = -1 end
if v.z<=0 then n.z = 1 else n.z = -1 end
local dpos = {};
dpos.x = 0.5*n.x; dpos.y = 0; dpos.z = 0; -- calculate distance to bounding surface midpoints
local d1 = (bpos.x-dpos.x)^2 + (bpos.y)^2 + (bpos.z)^2;
dpos.x = 0; dpos.y = 0.5*n.y; dpos.z = 0;
local d2 = (bpos.x)^2 + (bpos.y-dpos.y)^2 + (bpos.z)^2;
dpos.x = 0; dpos.y = 0; dpos.z = 0.5*n.z;
local d3 = (bpos.x)^2 + (bpos.y)^2 + (bpos.z-dpos.z)^2;
local d = math.min(d1,d2,d3); -- we obtain bounce direction from minimal distance
if d1==d then --x
n.y=0;n.z=0
elseif d2==d then --y
n.x=0;n.z=0
elseif d3==d then --z
n.x=0;n.y=0
end
nodename=minetest.get_node({x=opos.x+n.x,y=opos.y+n.y,z=opos.z+n.z}).name -- verify normal
walkable = nodename ~= "air";
if walkable then -- problem, nonempty node - incorrect normal, fix it
if n.x ~=0 then -- x direction is wrong, try something else
n.x=0;
if v.y>=0 then n.y = -1 else n.y = 1 end -- try y
nodename=minetest.get_node({x=opos.x+n.x,y=opos.y+n.y,z=opos.z+n.z}).name -- verify normal
walkable = nodename ~= "air";
if walkable then -- still problem, only remaining is z
n.y=0;
if v.z>=0 then n.z = -1 else n.z = 1 end
nodename=minetest.get_node({x=opos.x+n.x,y=opos.y+n.y,z=opos.z+n.z}).name -- verify normal
walkable = nodename ~= "air";
if walkable then -- messed up, just remove the ball
self.object:remove()
return
end
end
end
end
end
local elasticity = self.elasticity;
-- bounce
if n.x~=0 then
v.x=-elasticity*v.x
elseif n.y~=0 then
v.y=-elasticity*v.y
elseif n.z~=0 then
v.z=-elasticity*v.z
end
local r = 0.2
bpos = {x=pos.x+n.x*r,y=pos.y+n.y*r,z=pos.z+n.z*r}; -- point placed a bit further away from box
self.object:setpos(bpos) -- place object at last known outside point
self.object:setvelocity(v);
minetest.sound_play("default_dig_cracky", {pos=pos,gain=1.0,max_hear_distance = 8,})
end
end
return
end,
})
minetest.register_node("basic_machines:ball_spawner", {
description = "Spawns energy ball one block above",
tiles = {"basic_machines_ball.png"},
groups = {cracky=3, mesecon_effector_on = 1},
drawtype = "allfaces",
paramtype = "light",
param1=1,
walkable = false,
alpha = 150,
sounds = default.node_sound_wood_defaults(),
after_place_node = function(pos, placer)
local meta = minetest.env:get_meta(pos)
meta:set_string("owner", placer:get_player_name());
local privs = minetest.get_player_privs(placer:get_player_name()); if privs.privs then meta:set_int("admin",1) end
if privs.machines then meta:set_int("machines",1) end
meta:set_float("hurt",0);
meta:set_string("texture", "basic_machines_ball.png");
meta:set_float("hp",100);
meta:set_float("speed",5); -- if positive sets initial ball speed
meta:set_float("energy",1); -- if positive activates, negative deactivates, 0 does nothing
meta:set_int("bounce",0); -- if nonzero bounces when hit obstacle, 0 gets absorbed
meta:set_float("gravity",0); -- gravity
meta:set_int("puncheable",0); -- if 0 not puncheable, if 1 can be punched by players in protection, if 2 can be punched by anyone
meta:set_int("scale",100);
meta:set_string("visual","sprite");
ball_spawner_update_form(pos);
end,
mesecons = {effector = {
action_on = function (pos, node,ttl)
if type(ttl)~="number" then ttl = 1 end
if ttl<0 then return end
local meta = minetest.get_meta(pos);
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
if meta:get_int("machines")~=1 then -- no machines priv, limit ball count
local owner = meta:get_string("owner");
local count = ballcount[owner];
if not count or count<0 then count = 0 end
if count>=2 then
if t1-t0>20 then count = 0
else return
end
end
count = count + 1;
ballcount[owner]=count;
--minetest.chat_send_all("count " .. count);
end
pos.x = round(pos.x);pos.y = round(pos.y);pos.z = round(pos.z);
local obj = minetest.add_entity({x=pos.x,y=pos.y,z=pos.z}, "basic_machines:ball");
local luaent = obj:get_luaentity();
local meta = minetest.get_meta(pos);
local speed,energy,bounce,gravity,puncheable,solid;
speed = meta:get_float("speed");
energy = meta:get_float("energy"); -- if positive activates, negative deactivates, 0 does nothing
bounce = meta:get_int("bounce"); -- if nonzero bounces when hit obstacle, 0 gets absorbed
gravity = meta:get_float("gravity"); -- gravity
puncheable = meta:get_int("puncheable"); -- if 1 can be punched by players in protection, if 2 can be punched by anyone
solid = meta:get_int("solid");
if energy<0 then
obj:set_properties({textures={"basic_machines_ball.png^[colorize:blue:120"}})
end
luaent.bounce = bounce;
luaent.energy = energy;
if gravity>0 then
obj:setacceleration({x=0,y=-gravity,z=0});
end
luaent.puncheable = puncheable;
luaent.owner = meta:get_string("owner");
luaent.hurt = meta:get_float("hurt");
if solid==1 then
luaent.physical = true
end
obj:set_hp( meta:get_float("hp") );
local x0,y0,z0;
if speed>0 then luaent.speed = speed end
x0=meta:get_int("x0");y0=meta:get_int("y0");z0=meta:get_int("z0"); -- direction of velocity
if speed~=0 and (x0~=0 or y0~=0 or z0~=0) then -- set velocity direction
local velocity = {x=x0,y=y0,z=z0};
local v = math.sqrt(velocity.x^2+velocity.y^2+velocity.z^2); if v == 0 then v = 1 end
v = v / speed;
velocity.x=velocity.x/v;velocity.y=velocity.y/v;velocity.z=velocity.z/v;
obj:setvelocity(velocity);
end
if meta:get_int("admin")==1 then
luaent.lifetime = meta:get_float("lifetime");
end
local visual = meta:get_string("visual")
obj:set_properties({visual=visual});
local texture = meta:get_string("texture");
if visual=="sprite" then
obj:set_properties({textures={texture}})
elseif visual == "cube" then
obj:set_properties({textures={texture,texture,texture,texture,texture,texture}})
end
local scale = meta:get_int("scale");if scale<=0 then scale = 1 else scale = scale/100 end
obj:set_properties({visual_size = {x=scale, y=scale}});
end,
action_off = function (pos, node,ttl)
if type(ttl)~="number" then ttl = 1 end
if ttl<0 then return end
pos.x = round(pos.x);pos.y = round(pos.y);pos.z = round(pos.z);
local obj = minetest.add_entity({x=pos.x,y=pos.y,z=pos.z}, "basic_machines:ball");
local luaent = obj:get_luaentity();
luaent.energy = -1;
obj:set_properties({textures={"basic_machines_ball.png^[colorize:blue:120"}})
end
}
},
on_receive_fields = function(pos, formname, fields, sender)
local name = sender:get_player_name();if minetest.is_protected(pos,name) then return end
if fields.OK then
local privs = minetest.get_player_privs(sender:get_player_name());
local meta = minetest.get_meta(pos);
local x0=0; local y0=0; local z0=0;
--minetest.chat_send_all("form at " .. dump(pos) .. " fields " .. dump(fields))
if fields.x0 then x0 = tonumber(fields.x0) or 0 end
if fields.y0 then y0 = tonumber(fields.y0) or 0 end
if fields.z0 then z0 = tonumber(fields.z0) or 0 end
if not privs.privs and (math.abs(x0)>10 or math.abs(y0)>10 or math.abs(z0) > 10) then return end
meta:set_int("x0",x0);meta:set_int("y0",y0);meta:set_int("z0",z0);
local speed,energy,bounce,gravity,puncheable,solid;
energy = meta:get_float("energy"); -- if positive activates, negative deactivates, 0 does nothing
bounce = meta:get_int("bounce"); -- if nonzero bounces when hit obstacle, 0 gets absorbed
gravity = meta:get_float("gravity"); -- gravity
puncheable = meta:get_int("puncheable"); -- if 1 can be punched by players in protection, if 2 can be punched by anyone
solid = meta:get_int("solid");
if fields.speed then
local speed = tonumber(fields.speed) or 0;
if (speed > 10 or speed < 0) and not privs.privs then return end
meta:set_float("speed", speed)
end
if fields.energy then
local energy = tonumber(fields.energy) or 1;
meta:set_float("energy", energy)
end
if fields.bounce then
local bounce = tonumber(fields.bounce) or 1;
meta:set_int("bounce",bounce)
end
if fields.gravity then
local gravity = tonumber(fields.gravity) or 1;
if (gravity<0 or gravity>30) and not privs.privs then return end
meta:set_float("gravity", gravity)
end
if fields.puncheable then
meta:set_int("puncheable", tonumber(fields.puncheable) or 0)
end
if fields.solid then
meta:set_int("solid", tonumber(fields.solid) or 0)
end
if fields.lifetime then
meta:set_int("lifetime", tonumber(fields.lifetime) or 0)
end
if fields.hurt then
meta:set_float("hurt", tonumber(fields.hurt) or 0)
end
if fields.hp then
meta:set_float("hp", math.abs(tonumber(fields.hp) or 0))
end
if fields.texture then
meta:set_string ("texture", fields.texture);
end
if fields.scale then
local scale = math.abs(tonumber(fields.scale) or 100);
if scale>1000 and not privs.privs then scale = 1000 end
meta:set_int("scale", scale)
end
if fields.visual then
local visual = fields.visual or "";
if visual~="sprite" and visual~="cube" then return end
meta:set_string ("visual", fields.visual);
end
ball_spawner_update_form(pos);
end
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local name = digger:get_player_name();
local inv = digger:get_inventory();
inv:remove_item("main", ItemStack("basic_machines:ball_spawner"));
local stack = ItemStack("basic_machines:ball_spell");
local meta = oldmetadata["fields"];
meta["formspec"]=nil;
stack:set_metadata(minetest.serialize(meta));
inv:add_item("main",stack);
end
})
local spelltime = {};
-- ball as magic spell user can cast
minetest.register_tool("basic_machines:ball_spell", {
description = "ball spawner",
inventory_image = "basic_machines_ball.png",
tool_capabilities = {
full_punch_interval = 2,
max_drop_level=0,
},
on_use = function(itemstack, user, pointed_thing)
local pos = user:getpos();pos.y=pos.y+1;
local meta = minetest.deserialize(itemstack:get_metadata());
if not meta then return end
local owner = meta["owner"] or "";
--if minetest.is_protected(pos,owner) then return end
local t0 = spelltime[owner] or 0;
local t1 = minetest.get_gametime();
if t1-t0<2 then return end -- too soon
spelltime[owner]=t1;
local obj = minetest.add_entity({x=pos.x,y=pos.y,z=pos.z}, "basic_machines:ball");
local luaent = obj:get_luaentity();
local speed,energy,bounce,gravity,puncheable;
speed = tonumber(meta["speed"]) or 0;
energy = tonumber(meta["energy"]) or 0; -- if positive activates, negative deactivates, 0 does nothing
bounce = tonumber(meta["bounce"]) or 0; -- if nonzero bounces when hit obstacle, 0 gets absorbed
gravity = tonumber(meta["gravity"]) or 0; -- gravity
puncheable = tonumber(meta["puncheable"]) or 0; -- if 1 can be punched by players in protection, if 2 can be punched by anyone
if energy<0 then
obj:set_properties({textures={"basic_machines_ball.png^[colorize:blue:120"}})
end
luaent.bounce = bounce;
luaent.energy = energy;
if gravity>0 then
obj:setacceleration({x=0,y=-gravity,z=0});
end
luaent.puncheable = puncheable;
luaent.owner = meta["owner"];
luaent.hurt = math.min(tonumber(meta["hurt"]),basic_machines.ball.maxdamage);
obj:set_hp( tonumber(meta["hp"]) );
local x0,y0,z0;
if speed>0 then luaent.speed = speed end
local v = user:get_look_dir();
v.x=v.x*speed;v.y=v.y*speed;v.z=v.z*speed;
obj:setvelocity(v);
if tonumber(meta["admin"])==1 then
luaent.lifetime = tonumber(meta["lifetime"]);
end
obj:set_properties({textures={meta["texture"]}})
end,
})
-- minetest.register_craft({
-- output = "basic_machines:ball_spawner",
-- recipe = {
-- {"basic_machines:power_cell"},
-- {"basic_machines:keypad"}
-- }
-- })

View file

@ -1,219 +0,0 @@
-- rnd 2016:
-- CONSTRUCTOR machine: used to make all other basic_machines
basic_machines.craft_recipes = {
["keypad"] = {item = "basic_machines:keypad", description = "Turns on/off lights and activates machines or opens doors", craft = {"default:wood","default:stick"}, tex = "keypad"},
["light"]={item = "basic_machines:light_on", description = "Light in darkness", craft = {"default:torch 4"}, tex = "light"},
["mover"]={item = "basic_machines:mover", description = "Can dig, harvest, plant, teleport or move items from/in inventories", craft = {"default:mese_crystal 6","default:stone 2", "basic_machines:keypad"}, tex = "basic_machine_mover_side"},
["detector"] = {item = "basic_machines:detector", description = "Detect and measure players, objects,blocks,light level", craft = {"default:mese_crystal 4","basic_machines:keypad"}, tex = "detector"},
["distributor"]= {item = "basic_machines:distributor", description = "Organize your circuits better", craft = {"default:steel_ingot","default:mese_crystal", "basic_machines:keypad"}, tex = "distributor"},
["clock_generator"]= {item = "basic_machines:clockgen", description = "For making circuits that run non stop", craft = {"default:diamondblock","basic_machines:keypad"}, tex = "basic_machine_clock_generator"},
["recycler"]= {item = "basic_machines:recycler", description = "Recycle old tools", craft = {"default:mese_crystal 8","default:diamondblock"}, tex = "recycler"},
["enviroment"] = {item = "basic_machines:enviro", description = "Change gravity and more", craft = {"basic_machines:generator 8","basic_machines:clockgen"}, tex = "enviro"},
["ball_spawner"]={item = "basic_machines:ball_spawner", description = "Spawn moving energy balls", craft = {"basic_machines:power_cell","basic_machines:keypad"}, tex = "basic_machines_ball"},
["battery"]={item = "basic_machines:battery_0", description = "Power for machines", craft = {"default:bronzeblock 2","default:mese","default:diamond"}, tex = "basic_machine_battery"},
["generator"]={item = "basic_machines:generator", description = "Generate power crystals", craft = {"default:diamondblock 5","basic_machines:battery 5","default:goldblock 5"}, tex = "basic_machine_generator"},
["autocrafter"] = {item = "basic_machines:autocrafter", description = "Automate crafting", craft = { "default:steel_ingot 5", "default:mese_crystal 2", "default:diamondblock 2"}, tex = "pipeworks_autocrafter"},
["grinder"] = {item = "basic_machines:grinder", description = "Makes dusts and grinds materials", craft = {"default:diamond 13","default:mese 4"}, tex = "grinder"},
["power_block"] = {item = "basic_machines:power_block 5", description = "Energy cell, contains 11 energy units", craft = {"basic_machines:power_rod"}, tex = "power_block"},
["power_cell"] = {item = "basic_machines:power_cell 5", description = "Energy cell, contains 1 energy unit", craft = {"basic_machines:power_block"}, tex = "power_cell"},
["coal_lump"] = {item = "default:coal_lump", description = "Coal lump, contains 1 energy unit", craft = {"basic_machines:power_cell 2"}, tex = "default_coal_lump"},
}
basic_machines.craft_recipe_order = { -- order in which nodes appear
"keypad","light","grinder","mover", "battery","generator","detector", "distributor", "clock_generator","recycler","autocrafter","ball_spawner", "enviroment", "power_block", "power_cell", "coal_lump",
}
local constructor_process = function(pos)
local meta = minetest.get_meta(pos);
local craft = basic_machines.craft_recipes[meta:get_string("craft")];
if not craft then return end
local item = craft.item;
local craftlist = craft.craft;
local inv = meta:get_inventory();
for _,v in pairs(craftlist) do
if not inv:contains_item("main", ItemStack(v)) then
meta:set_string("infotext", "#CRAFTING: you need " .. v .. " to craft " .. craft.item)
return
end
end
for _,v in pairs(craftlist) do
inv:remove_item("main", ItemStack(v));
end
inv:add_item("main", ItemStack(item));
end
local constructor_update_meta = function(pos)
local meta = minetest.get_meta(pos);
local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z
local craft = meta:get_string("craft");
local description = basic_machines.craft_recipes[craft];
local tex;
if description then
tex = description.tex;
local i = 0;
local itex;
local inv = meta:get_inventory(); -- set up craft list
for _,v in pairs(description.craft) do
i=i+1;
inv:set_stack("recipe", i, ItemStack(v))
end
for j = i+1,6 do
inv:set_stack("recipe", j, ItemStack(""))
end
description = description.description
else
description = ""
tex = ""
end
local textlist = " ";
local selected = meta:get_int("selected") or 1;
for _,v in ipairs(basic_machines.craft_recipe_order) do
textlist = textlist .. v .. ", ";
end
local form =
"size[8,10]"..
"textlist[0,0;3,1.5;craft;" .. textlist .. ";" .. selected .."]"..
"button[3.5,1;1.25,0.75;CRAFT;CRAFT]"..
"image[3.65,0;1,1;".. tex .. ".png]"..
"label[0,1.85;".. description .. "]"..
"list[context;recipe;5,0;3,2;]"..
"label[0,2.3;Put crafting materials here]"..
"list[context;main;0,2.7;8,3;]"..
--"list[context;dst;5,0;3,2;]"..
"label[0,5.5;player inventory]"..
"list[current_player;main;0,6;8,4;]"..
"listring[context;main]"..
"listring[current_player;main]";
meta:set_string("formspec", form);
end
minetest.register_node("basic_machines:constructor", {
description = "Constructor: used to make machines",
tiles = {"constructor.png"},
groups = {cracky=3, mesecon_effector_on = 1},
sounds = default.node_sound_wood_defaults(),
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos);
meta:set_string("infotext", "Constructor: To operate it insert materials, select item to make and click craft button.")
meta:set_string("owner", placer:get_player_name());
meta:set_string("craft","keypad")
meta:set_int("selected",1);
local inv = meta:get_inventory();inv:set_size("main", 24);--inv:set_size("dst",6);
inv:set_size("recipe",8);
end,
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if minetest.is_protected(pos, player:get_player_name()) and not privs.privs then return end -- only owner can interact with recycler
constructor_update_meta(pos);
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
if listname == "recipe" then return 0 end
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if meta:get_string("owner")~=player:get_player_name() and not privs.privs then return 0 end
return stack:get_count();
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
if listname == "recipe" then return 0 end
local privs = minetest.get_player_privs(player:get_player_name());
if minetest.is_protected(pos, player:get_player_name()) and not privs.privs then return 0 end
return stack:get_count();
end,
on_metadata_inventory_put = function(pos, listname, index, stack, player)
if listname == "recipe" then return 0 end
local privs = minetest.get_player_privs(player:get_player_name());
if minetest.is_protected(pos, player:get_player_name()) and not privs.privs then return 0 end
return stack:get_count();
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
return 0;
end,
mesecons = {effector = {
action_on = function (pos, node,ttl)
if type(ttl)~="number" then ttl = 1 end
if ttl<0 then return end -- machines_TTL prevents infinite recursion
constructor_process(pos);
end
}
},
on_receive_fields = function(pos, formname, fields, sender)
if minetest.is_protected(pos, sender:get_player_name()) then return end
local meta = minetest.get_meta(pos);
if fields.craft then
if string.sub(fields.craft,1,3)=="CHG" then
local sel = tonumber(string.sub(fields.craft,5)) or 1
meta:set_int("selected",sel);
local i = 0;
for _,v in ipairs(basic_machines.craft_recipe_order) do
i=i+1;
if i == sel then meta:set_string("craft",v); break; end
end
else
return
end
end
if fields.CRAFT then
constructor_process(pos);
end
constructor_update_meta(pos);
end,
})
minetest.register_craft({
output = "basic_machines:constructor",
recipe = {
{"default:steel_ingot","default:steel_ingot","default:steel_ingot"},
{"default:steel_ingot","default:copperblock","default:steel_ingot"},
{"default:steel_ingot","default:steel_ingot","default:steel_ingot"},
}
})

View file

@ -1,5 +0,0 @@
default
protector?
areas?
boneworld?
moreores?

View file

@ -1,382 +0,0 @@
-- ENVIRO block: change physics and skybox for players
-- note: nonadmin players are limited in changes ( cant change skybox and have limits on other allowed changes)
-- rnd 2016:
local enviro = {};
enviro.skyboxes = {
["default"]={type = "regular", tex = {}},
["space"]={type="skybox", tex={"sky_pos_y.png","sky_neg_y.png","sky_pos_z.png","sky_neg_z.png","sky_neg_x.png","sky_pos_x.png",}}, -- need textures installed!
["caves"]={type = "cavebox", tex = {"black.png","black.png","black.png","black.png","black.png","black.png",}},
};
local space_start = 1100;
local ENABLE_SPACE_EFFECTS = false -- enable damage outside protected areas
local enviro_update_form = function (pos)
local meta = minetest.get_meta(pos);
local x0,y0,z0;
x0=meta:get_int("x0");y0=meta:get_int("y0");z0=meta:get_int("z0");
local skybox = meta:get_string("skybox");
local skylist = "";
local sky_ind,j;
j=1;sky_ind = 3;
for i,_ in pairs(enviro.skyboxes) do
if i == skybox then sky_ind = j end
skylist = skylist .. i .. ",";
j=j+1;
end
local r = meta:get_int("r");
local speed,jump, g, sneak;
speed = meta:get_float("speed");jump = meta:get_float("jump");
g = meta:get_float("g"); sneak = meta:get_int("sneak");
local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z;
local form =
"size[8,8.5]".. -- width, height
"field[0.25,0.5;1,1;x0;target;"..x0.."] field[1.25,0.5;1,1;y0;;"..y0.."] field[2.25,0.5;1,1;z0;;"..z0.."]"..
"field[3.25,0.5;1,1;r;radius;"..r.."]"..
--speed, jump, gravity,sneak
"field[0.25,1.5;1,1;speed;speed;"..speed.."]"..
"field[1.25,1.5;1,1;jump;jump;"..jump.."]"..
"field[2.25,1.5;1,1;g;gravity;"..g.."]"..
"field[3.25,1.5;1,1;sneak;sneak;"..sneak.."]"..
"label[0.,3.0;Skybox selection]"..
"dropdown[0.,3.35;3,1;skybox;"..skylist..";"..sky_ind.."]"..
"button_exit[3.25,3.25;1,1;OK;OK]"..
"list["..list_name..";fuel;3.25,2.25;1,1;]"..
"list[current_player;main;0,4.5;8,4;]"..
"listring[current_player;main]"..
"listring["..list_name..";fuel]"..
"listring[current_player;main]"
meta:set_string("formspec",form)
end
-- enviroment changer
minetest.register_node("basic_machines:enviro", {
description = "Changes enviroment for players around target location",
tiles = {"enviro.png"},
drawtype = "allfaces",
paramtype = "light",
param1=1,
groups = {cracky=3, mesecon_effector_on = 1},
sounds = default.node_sound_wood_defaults(),
after_place_node = function(pos, placer)
local meta = minetest.env:get_meta(pos)
meta:set_string("infotext", "Right click to set it. Activate by signal.")
meta:set_string("owner", placer:get_player_name()); meta:set_int("public",1);
meta:set_int("x0",0);meta:set_int("y0",0);meta:set_int("z0",0); -- target
meta:set_int("r",5); meta:set_string("skybox","default");
meta:set_float("speed",1);
meta:set_float("jump",1);
meta:set_float("g",1);
meta:set_int("sneak",1);
meta:set_int("admin",0);
local name = placer:get_player_name();
meta:set_string("owner",name);
local privs = minetest.get_player_privs(name);
if privs.privs then meta:set_int("admin",1) end
if privs.machines then meta:set_int("machines",1) end
local inv = meta:get_inventory();
inv:set_size("fuel",1*1);
enviro_update_form(pos);
end,
mesecons = {effector = {
action_on = function (pos, node,ttl)
local meta = minetest.get_meta(pos);
local machines = meta:get_int("machines");
if not machines == 1 then meta:set_string("infotext","Error. You need machines privs.") return end
local admin = meta:get_int("admin");
local inv = meta:get_inventory(); local stack = ItemStack("default:diamond 1");
if inv:contains_item("fuel", stack) then
inv:remove_item("fuel", stack);
else
meta:set_string("infotext","Error. Insert diamond in fuel inventory")
return
end
local x0,y0,z0,r,skybox,speed,jump,g,sneak;
x0=meta:get_int("x0"); y0=meta:get_int("y0");z0=meta:get_int("z0"); -- target
r= meta:get_int("r",5); skybox=meta:get_string("skybox");
speed=meta:get_float("speed");jump= meta:get_float("jump");
g=meta:get_float("g");sneak=meta:get_int("sneak"); if sneak~=0 then sneak = true else sneak = false end
local players = minetest.get_connected_players();
for _,player in pairs(players) do
local pos1 = player:getpos();
local dist = math.sqrt((pos1.x-pos.x)^2 + (pos1.y-pos.y)^2 + (pos1.z-pos.z)^2 );
if dist<=r then
player:set_physics_override({speed=speed,jump=jump,gravity=g,sneak=sneak})
if admin == 1 then -- only admin can change skybox
local sky = enviro.skyboxes[skybox];
player:set_sky(0,sky["type"],sky["tex"]);
end
end
end
-- attempt to set acceleration to balls, if any around
local objects = minetest.get_objects_inside_radius(pos, r)
for _,obj in pairs(objects) do
if obj:get_luaentity() then
local obj_name = obj:get_luaentity().name or ""
if obj_name == "basic_machines:ball" then
obj:setacceleration({x=0,y=-g,z=0});
end
end
end
end
}
},
on_receive_fields = function(pos, formname, fields, sender)
local name = sender:get_player_name();if minetest.is_protected(pos,name) then return end
if fields.OK then
local privs = minetest.get_player_privs(sender:get_player_name());
local meta = minetest.get_meta(pos);
local x0=0; local y0=0; local z0=0;
--minetest.chat_send_all("form at " .. dump(pos) .. " fields " .. dump(fields))
if fields.x0 then x0 = tonumber(fields.x0) or 0 end
if fields.y0 then y0 = tonumber(fields.y0) or 0 end
if fields.z0 then z0 = tonumber(fields.z0) or 0 end
if not privs.privs and (math.abs(x0)>10 or math.abs(y0)>10 or math.abs(z0) > 10) then return end
meta:set_int("x0",x0);meta:set_int("y0",y0);meta:set_int("z0",z0);
if privs.privs then -- only admin can set sky
if fields.skybox then meta:set_string("skybox", fields.skybox) end
end
if fields.r then
local r = tonumber(fields.r) or 0;
if r > 10 and not privs.privs then return end
meta:set_int("r", r)
end
if fields.g then
local g = tonumber(fields.g) or 1;
if (g<0.1 or g>40) and not privs.privs then return end
meta:set_float("g", g)
end
if fields.speed then
local speed = tonumber(fields.speed) or 1;
if (speed>1 or speed < 0) and not privs.privs then return end
meta:set_float("speed", speed)
end
if fields.jump then
local jump = tonumber(fields.jump) or 1;
if (jump<0 or jump>2) and not privs.privs then return end
meta:set_float("jump", jump)
end
if fields.sneak then
meta:set_int("sneak", tonumber(fields.sneak) or 0)
end
enviro_update_form(pos);
end
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if meta:get_string("owner")~=player:get_player_name() and not privs.privs then return 0 end
return stack:get_count();
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if meta:get_string("owner")~=player:get_player_name() and not privs.privs then return 0 end
return stack:get_count();
end,
})
-- DEFAULT (SPAWN) PHYSICS VALUE/SKYBOX
local reset_player_physics = function(player)
if player then
player:set_physics_override({speed=1,jump=1,gravity=1}) -- value set for extreme test space spawn
local skybox = enviro.skyboxes["default"]; -- default skybox is "default"
player:set_sky(0,skybox["type"],skybox["tex"]);
end
end
-- globally available function
enviro_adjust_physics = function(player) -- adjust players physics/skybox 1 second after various events
minetest.after(1, function()
if player then
local pos = player:getpos(); if not pos then return end
if pos.y > space_start then -- is player in space or not?
player:set_physics_override({speed=1,jump=0.5,gravity=0.1}) -- value set for extreme test space spawn
local skybox = enviro.skyboxes["space"];
player:set_sky(0,skybox["type"],skybox["tex"]);
else
player:set_physics_override({speed=1,jump=1,gravity=1}) -- value set for extreme test space spawn
local skybox = enviro.skyboxes["default"];
player:set_sky(0,skybox["type"],skybox["tex"]);
end
end
end)
end
-- restore default values/skybox on respawn of player
minetest.register_on_respawnplayer(reset_player_physics)
-- when player joins, check where he is and adjust settings
minetest.register_on_joinplayer(enviro_adjust_physics)
-- SERVER GLOBAL SPACE CODE: uncomment to enable it
local round = math.floor;
local protector_position = function(pos)
local r = 20;
local ry = 2*r;
return {x=round(pos.x/r+0.5)*r,y=round(pos.y/ry+0.5)*ry,z=round(pos.z/r+0.5)*r};
end
local stimer = 0
local enviro_space = {};
minetest.register_globalstep(function(dtime)
stimer = stimer + dtime;
if stimer >= 5 then
stimer = 0;
local players = minetest.get_connected_players();
for _,player in pairs(players) do
local name = player:get_player_name();
local pos = player:getpos();
local inspace=0; if pos.y>space_start then inspace = 1 end
local inspace0=enviro_space[name];
if inspace~=inspace0 then -- only adjust player enviroment ONLY if change occured ( earth->space or space->earth !)
enviro_space[name] = inspace;
enviro_adjust_physics(player);
end
if ENABLE_SPACE_EFFECTS and inspace==1 then -- special space code
if pos.y<1500 and pos.y>1120 then
local hp = player:get_hp();
if hp>0 then
minetest.chat_send_player(name,"WARNING: you entered DEADLY RADIATION ZONE");
local privs = minetest.get_player_privs(name)
if not privs.kick then player:set_hp(hp-15) end
end
return
else
local ppos = protector_position(pos);
local populated = (minetest.get_node(ppos).name=="basic_protect:protector");
if populated then
if minetest.get_meta(ppos):get_int("space") == 1 then populated = false end
end
if not populated then -- do damage if player found not close to protectors
local hp = player:get_hp();
local privs = minetest.get_player_privs(name);
if hp>0 and not privs.kick then
player:set_hp(hp-10); -- dead in 20/10 = 2 events
minetest.chat_send_player(name,"WARNING: in space you must stay close to spawn or protected areas");
end
end
end
end
end
end
end)
-- END OF SPACE CODE
-- AIR EXPERIMENT
-- minetest.register_node("basic_machines:air", {
-- description = "enables breathing in space",
-- drawtype = "liquid",
-- tiles = {"default_water_source_animated.png"},
-- drawtype = "glasslike",
-- paramtype = "light",
-- alpha = 150,
-- sunlight_propagates = true, -- Sunlight shines through
-- walkable = false, -- Would make the player collide with the air node
-- pointable = false, -- You can't select the node
-- diggable = false, -- You can't dig the node
-- buildable_to = true,
-- drop = "",
-- groups = {not_in_creative_inventory=1},
-- after_place_node = function(pos, placer, itemstack, pointed_thing)
-- local r = 3;
-- for i = -r,r do
-- for j = -r,r do
-- for k = -r,r do
-- local p = {x=pos.x+i,y=pos.y+j,z=pos.z+k};
-- if minetest.get_node(p).name == "air" then
-- minetest.set_node(p,{name = "basic_machines:air"})
-- end
-- end
-- end
-- end
-- end
-- })
-- minetest.register_abm({
-- nodenames = {"basic_machines:air"},
-- neighbors = {"air"},
-- interval = 10,
-- chance = 1,
-- action = function(pos, node, active_object_count, active_object_count_wider)
-- minetest.set_node(pos,{name = "air"})
-- end
-- });
minetest.register_on_punchplayer( -- bring gravity closer to normal with each punch
function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage)
if player:get_physics_override() == nil then return end
local pos = player:getpos(); if pos.y>= space_start then return end
local gravity = player:get_physics_override().gravity;
if gravity<1 then
gravity = 1;
player:set_physics_override({gravity=gravity})
end
end
)
-- RECIPE: extremely expensive
-- minetest.register_craft({
-- output = "basic_machines:enviro",
-- recipe = {
-- {"basic_machines:generator", "basic_machines:clockgen","basic_machines:generator"},
-- {"basic_machines:generator", "basic_machines:generator","basic_machines:generator"},
-- {"basic_machines:generator", "basic_machines:generator", "basic_machines:generator"}
-- }
-- })

View file

@ -1,354 +0,0 @@
--todo: when grinding multiple items compare battery maxpower with number of items and attempt to grind as much as possible
-- rnd 2016:
-- this node works as technic grinder
-- There is a certain fuel cost to operate
-- recipe list: [in] ={fuel cost, out, quantity of material required for processing}
basic_machines.grinder_recipes = {
["default:stone"] = {2,"default:sand",1},
["default:desert_stone"] = {2,"default:desert_sand 4",1},
["default:cobble"] = {1,"default:gravel",1},
["default:gravel"] = {0.5,"default:dirt",1},
["default:dirt"] = {0.5,"default:clay_lump 4",1},
["es:aikerum_crystal"] ={16,"es:aikerum_dust 2",1}, -- added for es mod
["es:ruby_crystal"] = {16,"es:ruby_dust 2",1},
["es:emerald_crystal"] = {16,"es:emerald_dust 2",1},
["es:purpellium_lump"] = {16,"es:purpellium_dust 2",1},
["default:obsidian_shard"] = {199,"default:lava_source",1},
["gloopblocks:basalt"] = {1, "default:cobble",1}, -- enable coble farms with gloopblocks mod
["default:ice"] = {1, "default:snow 4",1},
["darkage:silt_lump"]={1,"darkage:chalk_powder",1},
};
-- es gems dust cooking
local es_gems = function()
local es_gems = {
{name = "emerald", cooktime = 1200},{name = "ruby", cooktime = 1500},{name = "purpellium", cooktime = 1800},
{name = "aikerum", cooktime = 2000}}
for _,v in pairs(es_gems) do
minetest.register_craft({
type = "cooking",
recipe = "es:"..v.name.."_dust",
output = "es:"..v.name .."_crystal",
cooktime = v.cooktime
})
end
end
minetest.after(0,es_gems);
local grinder_process = function(pos)
local node = minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z}).name;
local meta = minetest.get_meta(pos);local inv = meta:get_inventory();
-- PROCESS: check out inserted items
local stack = inv:get_stack("src",1);
if stack:is_empty() then return end; -- nothing to do
local src_item = stack:to_string();
local p=string.find(src_item," "); if p then src_item = string.sub(src_item,1,p-1) else p = 0 end -- take first word to determine what item was
local def = basic_machines.grinder_recipes[src_item];
if not def then
meta:set_string("infotext", "please insert valid materials"); return
end-- unknown node
if stack:get_count()< def[3] then
meta:set_string("infotext", "Recipe requires at least " .. def[3] .. " " .. src_item);
return
end
-- FUEL CHECK
local fuel = meta:get_float("fuel");
if fuel-def[1]<0 then -- we need new fuel, check chest below
local fuellist = inv:get_list("fuel")
if not fuellist then return end
local fueladd, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
local supply=0;
if fueladd.time == 0 then -- no fuel inserted, try look for outlet
-- No valid fuel in fuel list
supply = basic_machines.check_power({x=pos.x,y=pos.y-1,z=pos.z} , def[1]) or 0; -- tweaked so 1 coal = 1 energy
if supply>0 then
fueladd.time = supply -- same as 10 coal
else
meta:set_string("infotext", "Please insert fuel");
return;
end
else
if supply==0 then -- Take fuel from fuel list if no supply available
inv:set_stack("fuel",1,afterfuel.items[1])
fueladd.time=fueladd.time*0.1/4 -- thats 1 for coal
--minetest.chat_send_all("FUEL ADD TIME " .. fueladd.time)
end
end
if fueladd.time>0 then
fuel=fuel + fueladd.time
meta:set_float("fuel",fuel);
meta:set_string("infotext", "added fuel furnace burn time " .. fueladd.time .. ", fuel status " .. fuel);
end
if fuel-def[1]<0 then
meta:set_string("infotext", "need at least " .. def[1]-fuel .. " fuel to complete operation "); return
end
end
-- process items
-- TO DO: check if there is room for item yyy
local addstack = ItemStack(def[2]);
if inv:room_for_item("dst", addstack) then
inv:add_item("dst",addstack);
else return
end
--take 1 item from src inventory for each activation
stack=stack:take_item(1); inv:remove_item("src", stack)
minetest.sound_play("grinder", {pos=pos,gain=0.5,max_hear_distance = 16,})
fuel = fuel-def[1]; -- burn fuel
meta:set_float("fuel",fuel);
meta:set_string("infotext", "fuel " .. fuel);
end
local grinder_update_meta = function(pos)
local meta = minetest.get_meta(pos);
local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z
local form =
"size[8,8]".. -- width, height
--"size[6,10]".. -- width, height
"label[0,0;IN] label[1,0;OUT] label[0,2;FUEL] "..
"list["..list_name..";src;0.,0.5;1,1;]"..
"list["..list_name..";dst;1.,0.5;3,3;]"..
"list["..list_name..";fuel;0.,2.5;1,1;]"..
"list[current_player;main;0,4;8,4;]"..
"button[6.5,0.5;1,1;OK;OK]"..
"button[6.5,1.5;1,1;help;help]"..
"listring["..list_name..";dst]"..
"listring[current_player;main]"..
"listring["..list_name..";src]"..
"listring[current_player;main]"..
"listring["..list_name..";fuel]"..
"listring[current_player;main]"
meta:set_string("formspec", form)
end
minetest.register_node("basic_machines:grinder", {
description = "Grinder",
tiles = {"grinder.png"},
groups = {cracky=3, mesecon_effector_on = 1},
sounds = default.node_sound_wood_defaults(),
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos);
meta:set_string("infotext", "Grinder: To operate it insert fuel, then insert item to grind or use keypad to activate it.")
meta:set_string("owner", placer:get_player_name());
meta:set_float("fuel",0);
local inv = meta:get_inventory();inv:set_size("src", 1);inv:set_size("dst",9);inv:set_size("fuel",1);
end,
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if minetest.is_protected(pos, player:get_player_name()) and not privs.privs then return end -- only owner can interact with recycler
grinder_update_meta(pos);
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if meta:get_string("owner")~=player:get_player_name() and not privs.privs then return 0 end
return stack:get_count();
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if meta:get_string("owner")~=player:get_player_name() and not privs.privs then return 0 end
return stack:get_count();
end,
on_metadata_inventory_put = function(pos, listname, index, stack, player)
if listname =="dst" then return end
grinder_process(pos);
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
return 0;
end,
mesecons = {effector = {
action_on = function (pos, node,ttl)
if type(ttl)~="number" then ttl = 1 end
if ttl<0 then return end -- machines_TTL prevents infinite recursion
grinder_process(pos);
end
}
},
on_receive_fields = function(pos, formname, fields, sender)
if fields.quit then return end
local meta = minetest.get_meta(pos);
if fields.help then
--recipe list: [in] ={fuel cost, out, quantity of material required for processing}
--basic_machines.grinder_recipes
local text = "RECIPES\n\n";
for key,v in pairs(basic_machines.grinder_recipes) do
text = text .. "INPUT ".. key .. " " .. v[3] .. " OUTPUT " .. v[2] .. "\n"
end
local form = "size [6,7] textarea[0,0;6.5,8.5;grinderhelp;GRINDER RECIPES;".. text.."]"
minetest.show_formspec(sender:get_player_name(), "grinderhelp", form)
end
grinder_update_meta(pos);
end,
})
-- minetest.register_craft({
-- output = "basic_machines:grinder",
-- recipe = {
-- {"default:diamond","default:mese","default:diamond"},
-- {"default:mese","default:diamondblock","default:mese"},
-- {"default:diamond","default:mese","default:diamond"},
-- }
-- })
-- REGISTER DUSTS
local function register_dust(name,input_node_name,ingot,grindcost,cooktime,R,G,B)
if not R then R = "FF" end
if not G then G = "FF" end
if not B then B = "FF" end
local purity_table = {"33","66"};
for i = 1,#purity_table do
local purity = purity_table[i];
minetest.register_craftitem("basic_machines:"..name.."_dust_".. purity, {
description = name.. " dust purity " .. purity .. "%" ,
inventory_image = "basic_machines_dust.png^[colorize:#"..R..G..B..":180",
})
end
basic_machines.grinder_recipes[input_node_name] = {grindcost,"basic_machines:"..name.."_dust_".. purity_table[1].." 2",1} -- register grinder recipe
if ingot~="" then
for i = 1,#purity_table-1 do
minetest.register_craft({
type = "cooking",
recipe = "basic_machines:"..name.."_dust_".. purity_table[i],
output = "basic_machines:"..name.."_dust_".. purity_table[i+1],
cooktime = cooktime
})
end
minetest.register_craft({
type = "cooking",
recipe = "basic_machines:"..name.."_dust_".. purity_table[#purity_table],
groups = {not_in_creative_inventory=1},
output = ingot,
cooktime = cooktime
})
end
end
register_dust("iron","default:iron_lump","default:steel_ingot",4,8,"99","99","99")
register_dust("copper","default:copper_lump","default:copper_ingot",4,8,"C8","80","0D") --c8800d
register_dust("tin","default:tin_lump","default:tin_ingot",4,8,"9F","9F","9F")
register_dust("gold","default:gold_lump","default:gold_ingot",6,25,"FF","FF","00")
-- grinding ingots gives dust too
basic_machines.grinder_recipes["default:steel_ingot"] = {4,"basic_machines:iron_dust_33 2",1};
basic_machines.grinder_recipes["default:copper_ingot"] = {4,"basic_machines:copper_dust_33 2",1};
basic_machines.grinder_recipes["default:gold_ingot"] = {6,"basic_machines:gold_dust_33 2",1};
basic_machines.grinder_recipes["default:tin_ingot"] = {4,"basic_machines:tin_dust_33 2",1};
-- are moreores (tin, silver, mithril) present?
local table = minetest.registered_items["moreores:tin_lump"]; if table then
--register_dust("tin","moreores:tin_lump","moreores:tin_ingot",4,8,"FF","FF","FF")
register_dust("silver","moreores:silver_lump","moreores:silver_ingot",5,15,"BB","BB","BB")
register_dust("mithril","moreores:mithril_lump","moreores:mithril_ingot",16,750,"00","00","FF")
basic_machines.grinder_recipes["moreores:tin_ingot"] = {4,"basic_machines:tin_dust_33 2",1};
basic_machines.grinder_recipes["moreores:silver_ingot"] = {5,"basic_machines:silver_dust_33 2",1};
basic_machines.grinder_recipes["moreores:mithril_ingot"] = {16,"basic_machines:mithril_dust_33 2",1};
end
register_dust("mese","default:mese_crystal","default:mese_crystal",8,250,"CC","CC","00")
register_dust("diamond","default:diamond","default:diamond",16,500,"00","EE","FF") -- 0.3hr cooking time to make diamond!
-- darkage recipes and ice
minetest.register_craft({
type = "cooking",
recipe = "default:ice",
output = "default:water_flowing",
cooktime = 4
})
minetest.register_craft({
type = "cooking",
recipe = "default:stone",
output = "darkage:basalt",
cooktime = 60
})
minetest.register_craft({
type = "cooking",
recipe = "darkage:slate",
output = "darkage:schist",
cooktime = 20
})
-- dark age recipe: cook schist to get gneiss
minetest.register_craft({
type = "cooking",
recipe = "darkage:gneiss",
output = "darkage:marble",
cooktime = 20
})
minetest.register_craft({
output = "darkage:serpentine",
recipe = {
{"darkage:marble","default:cactus"}
}
})
minetest.register_craft({
output = "darkage:mud",
recipe = {
{"default:dirt","default:water_flowing"}
}
})

View file

@ -1,90 +0,0 @@
-- BASIC_MACHINES: lightweight automation mod for minetest
-- minetest 0.4.14
-- (c) 2015-2016 rnd
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
basic_machines = {};
dofile(minetest.get_modpath("basic_machines").."/mark.lua") -- used for markings, borrowed and adapted from worldedit mod
dofile(minetest.get_modpath("basic_machines").."/mover.lua") -- mover, detector, keypad, distributor
dofile(minetest.get_modpath("basic_machines").."/technic_power.lua") -- technic power for mover
dofile(minetest.get_modpath("basic_machines").."/recycler.lua") -- recycle old used tools
dofile(minetest.get_modpath("basic_machines").."/grinder.lua") -- grind materials into dusts
dofile(minetest.get_modpath("basic_machines").."/autocrafter.lua") -- borrowed and adapted from pipeworks mod
dofile(minetest.get_modpath("basic_machines").."/constructor.lua") -- enable crafting of all machines
dofile(minetest.get_modpath("basic_machines").."/protect.lua") -- enable interaction with players, adds local on protect/chat event handling
-- OPTIONAL ADDITIONAL STUFF ( comment to disable )
dofile(minetest.get_modpath("basic_machines").."/ball.lua") -- interactive flying ball, can activate blocks or be used as a weapon
dofile(minetest.get_modpath("basic_machines").."/enviro.lua") -- enviro blocks that can change surrounding enviroment physics, uncomment spawn/join code to change global physics, disabled by default
minetest.after(0, function()
dofile(minetest.get_modpath("basic_machines").."/mesecon_doors.lua") -- if you want open/close doors with signal, also steel doors are made impervious to dig through, removal by repeat punch
dofile(minetest.get_modpath("basic_machines").."/mesecon_lights.lua") -- adds ability for other light blocks to toggle light
end)
-- MACHINE PRIVILEGE
minetest.register_privilege("machines", {
description = "Player is expert basic_machine user: his machines work while not present on server, can spawn more than 2 balls at once",
})
-- machines fuel related recipes
-- CHARCOAL
minetest.register_craftitem("basic_machines:charcoal", {
description = "Wood charcoal",
inventory_image = "charcoal.png",
})
minetest.register_craft({
type = 'cooking',
recipe = "default:tree",
cooktime = 30,
output = "basic_machines:charcoal",
})
minetest.register_craft({
output = "default:coal_lump",
recipe = {
{"basic_machines:charcoal"},
{"basic_machines:charcoal"},
}
})
minetest.register_craft({
type = "fuel",
recipe = "basic_machines:charcoal",
-- note: to make it you need to use 1 tree block for fuel + 1 tree block, thats 2, caloric value 2*30=60
burntime = 40, -- coal lump has 40, tree block 30, coal block 370 (9*40=360!)
})
-- add since minetest doesnt have moreores tin ingot recipe
minetest.register_craft({
output = "default:tin_ingot",
recipe = {
{"moreores:tin_ingot"},
}
})
-- COMPATIBILITY
minetest.register_alias("basic_machines:battery", "basic_machines:battery_0")
print("[MOD] basic_machines " .. basic_machines.version .. " loaded.")

View file

@ -1,154 +0,0 @@
-- rnd: code borrowed from machines, mark.lua
-- need for marking
machines = {};
machines.pos1 = {};machines.pos11 = {}; machines.pos2 = {};
machines.marker1 = {}
machines.marker11 = {}
machines.marker2 = {}
machines.marker_region = {}
--marks machines region position 1
machines.mark_pos1 = function(name)
local pos1, pos2 = machines.pos1[name], machines.pos2[name]
if pos1 ~= nil then
--make area stay loaded
local manip = minetest.get_voxel_manip()
manip:read_from_map(pos1, pos1)
end
if not machines[name] then machines[name]={} end
machines[name].timer = 10;
if machines.marker1[name] ~= nil then --marker already exists
machines.marker1[name]:remove() --remove marker
machines.marker1[name] = nil
end
if pos1 ~= nil then
--add marker
machines.marker1[name] = minetest.add_entity(pos1, "machines:pos1")
if machines.marker1[name] ~= nil then
machines.marker1[name]:get_luaentity().name = name
end
end
end
--marks machines region position 1
machines.mark_pos11 = function(name)
local pos11 = machines.pos11[name];
if pos11 ~= nil then
--make area stay loaded
local manip = minetest.get_voxel_manip()
manip:read_from_map(pos11, pos11)
end
if not machines[name] then machines[name]={} end
machines[name].timer = 10;
if machines.marker11[name] ~= nil then --marker already exists
machines.marker11[name]:remove() --remove marker
machines.marker11[name] = nil
end
if pos11 ~= nil then
--add marker
machines.marker11[name] = minetest.add_entity(pos11, "machines:pos11")
if machines.marker11[name] ~= nil then
machines.marker11[name]:get_luaentity().name = name
end
end
end
--marks machines region position 2
machines.mark_pos2 = function(name)
local pos1, pos2 = machines.pos1[name], machines.pos2[name]
if pos2 ~= nil then
--make area stay loaded
local manip = minetest.get_voxel_manip()
manip:read_from_map(pos2, pos2)
end
if not machines[name] then machines[name]={} end
machines[name].timer = 10;
if machines.marker2[name] ~= nil then --marker already exists
machines.marker2[name]:remove() --remove marker
machines.marker2[name] = nil
end
if pos2 ~= nil then
--add marker
machines.marker2[name] = minetest.add_entity(pos2, "machines:pos2")
if machines.marker2[name] ~= nil then
machines.marker2[name]:get_luaentity().name = name
end
end
end
minetest.register_entity(":machines:pos1", {
initial_properties = {
visual = "cube",
visual_size = {x=1.1, y=1.1},
textures = {"machines_pos1.png", "machines_pos1.png",
"machines_pos1.png", "machines_pos1.png",
"machines_pos1.png", "machines_pos1.png"},
collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55},
physical = false,
},
on_step = function(self, dtime)
if not machines[self.name] then machines[self.name]={}; machines[self.name].timer = 10 end
machines[self.name].timer = machines[self.name].timer - dtime
if machines[self.name].timer<=0 or machines.marker1[self.name] == nil then
self.object:remove()
end
end,
on_punch = function(self, hitter)
self.object:remove()
machines.marker1[self.name] = nil
machines[self.name].timer = 10
end,
})
minetest.register_entity(":machines:pos11", {
initial_properties = {
visual = "cube",
visual_size = {x=1.1, y=1.1},
textures = {"machines_pos11.png", "machines_pos11.png",
"machines_pos11.png", "machines_pos11.png",
"machines_pos11.png", "machines_pos11.png"},
collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55},
physical = false,
},
on_step = function(self, dtime)
if not machines[self.name] then machines[self.name]={}; machines[self.name].timer = 10 end
machines[self.name].timer = machines[self.name].timer - dtime
if machines[self.name].timer<=0 or machines.marker11[self.name] == nil then
self.object:remove()
end
end,
on_punch = function(self, hitter)
self.object:remove()
machines.marker11[self.name] = nil
machines[self.name].timer = 10
end,
})
minetest.register_entity(":machines:pos2", {
initial_properties = {
visual = "cube",
visual_size = {x=1.1, y=1.1},
textures = {"machines_pos2.png", "machines_pos2.png",
"machines_pos2.png", "machines_pos2.png",
"machines_pos2.png", "machines_pos2.png"},
collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55},
physical = false,
},
on_step = function(self, dtime)
if not machines[self.name] then machines[self.name]={}; machines[self.name].timer = 10 end
if machines[self.name].timer<=0 or machines.marker2[self.name] == nil then
self.object:remove()
end
end,
})

View file

@ -1,102 +0,0 @@
-- make doors open/close with signal
local function door_signal_overwrite(name)
local table = minetest.registered_nodes[name]; if not table then return end
local table2 = {}
for i,v in pairs(table) do table2[i] = v end
-- 0.4.15: line 370 in doors defines thins
local door_on_rightclick = table2.on_rightclick;
-- this will make door toggle whenever its used
table2.mesecons = {effector = {
action_on = function (pos,node)
local meta = minetest.get_meta(pos);local name = meta:get_string("owner");
-- create virtual player
local clicker = {};
function clicker:get_wielded_item()
local item = {}
function item:get_name() return "" end
return item
end
function clicker:get_player_name() return name end; -- define method get_player_name() returning owner name so that we can call on_rightclick function in door
function clicker:is_player() return false end; -- method needed for mods that check this: like denaid areas mod
if door_on_rightclick then door_on_rightclick(pos, nil, clicker,ItemStack(""),{}) end -- safety if it doesnt exist
--minetest.swap_node(pos, {name = "protector:trapdoor", param1 = node.param1, param2 = node.param2}) -- more direct approach?, need to set param2 then too
end
}
};
minetest.register_node(":"..name, table2)
end
minetest.after(0,function()
door_signal_overwrite("doors:door_wood");door_signal_overwrite("doors:door_steel")
door_signal_overwrite("doors:door_wood_a");door_signal_overwrite("doors:door_wood_b");
door_signal_overwrite("doors:door_steel_a");door_signal_overwrite("doors:door_steel_b");
door_signal_overwrite("doors:door_glass_a");door_signal_overwrite("doors:door_glass_b");
door_signal_overwrite("doors:door_obsidian_glass_a");door_signal_overwrite("doors:door_obsidian_glass_b");
door_signal_overwrite("doors:trapdoor");door_signal_overwrite("doors:trapdoor_open");
door_signal_overwrite("doors:trapdoor_steel");door_signal_overwrite("doors:trapdoor_steel_open");
end
);
local function make_it_noclip(name)
local table = minetest.registered_nodes[name]; if not table then return end
local table2 = {}
for i,v in pairs(table) do
table2[i] = v
end
table2.walkable = false; -- cant be walked on
minetest.register_node(":"..name, table2)
end
minetest.after(0,function()
make_it_noclip("doors:trapdoor_open");
make_it_noclip("doors:trapdoor_steel_open");
end);
local function make_it_nondiggable_but_removable(name, dropname)
local table = minetest.registered_nodes[name]; if not table then return end
local table2 = {}
for i,v in pairs(table) do
table2[i] = v
end
table2.groups.level = 99; -- cant be digged, but it can be removed by owner or if not protected
table2.on_punch = function(pos, node, puncher, pointed_thing) -- remove node if owner repeatedly punches it 3x
local pname = puncher:get_player_name();
local meta = minetest.get_meta(pos);
local owner = meta:get_string("doors_owner")
if pname==owner or not minetest.is_protected(pos,pname) then -- can be dug by owner or if unprotected
local t0 = meta:get_int("punchtime");local count = meta:get_int("punchcount");
local t = minetest.get_gametime();
if t-t0<2 then count = (count +1 ) % 3 else count = 0 end
if count == 1 then
minetest.chat_send_player(pname, "#steel door: punch me one more time to remove me");
end
if count == 2 then -- remove steel door and drop it
minetest.set_node(pos, {name = "air"});
local stack = ItemStack(dropname);minetest.add_item(pos,stack)
end
meta:set_int("punchcount",count);meta:set_int("punchtime",t);
--minetest.chat_send_all("punch by "..name .. " count " .. count)
end
end
minetest.register_node(":"..name, table2)
end
minetest.after(0,function()
make_it_nondiggable_but_removable("doors:door_steel_a","doors:door_steel");
make_it_nondiggable_but_removable("doors:door_steel_b","doors:door_steel");
make_it_nondiggable_but_removable("doors:trapdoor_steel","doors:trapdoor_steel");
make_it_nondiggable_but_removable("doors:trapdoor_steel_open","doors:trapdoor_steel");
end);

View file

@ -1,50 +0,0 @@
-- make other light blocks work with mesecon signals - can toggle on/off
local function enable_toggle_light(name)
local table = minetest.registered_nodes[name]; if not table then return end
local table2 = {}
for i,v in pairs(table) do
table2[i] = v
end
if table2.mesecons then return end -- we dont want to overwrite existing stuff!
local offname = "basic_machines:"..string.gsub(name, ":", "_").. "_OFF";
table2.mesecons = {effector = { -- action to toggle light off
action_off = function (pos,node,ttl)
minetest.swap_node(pos,{name = offname});
end
}
};
minetest.register_node(":"..name, table2) -- redefine item
-- STRANGE BUG1: if you dont make new table table3 and reuse table2 definition original node (definition one line above) is changed by below code too!???
-- STRANGE BUG2: if you dont make new table3.. original node automatically changes to OFF node when placed ????
local table3 = {}
for i,v in pairs(table) do
table3[i] = v
end
table3.light_source = 0; -- off block has light off
table3.mesecons = {effector = {
action_on = function (pos,node,ttl)
minetest.swap_node(pos,{name = name});
end
}
};
-- REGISTER OFF BLOCK
minetest.register_node(":"..offname, table3);
end
enable_toggle_light("xdecor:wooden_lightbox");
enable_toggle_light("xdecor:iron_lightbox");
enable_toggle_light("moreblocks:slab_meselamp_1");
enable_toggle_light("moreblocks:slab_super_glow_glass");
enable_toggle_light("darkage:lamp");

File diff suppressed because it is too large Load diff

View file

@ -1,54 +0,0 @@
-- adds event handler for attempt to dig in protected area
-- tries to activate specially configured nearby distributor at points with coordinates of form 20i, registers dig attempts in radius 10 around
-- distributor must have first target filter set to 0 ( disabled ) to handle dig events
local old_is_protected = minetest.is_protected
local round = math.floor;
local machines_TTL=5
function minetest.is_protected(pos, digger)
local is_protected = old_is_protected(pos, digger);
if is_protected then -- only if protected
local r = 20;local p = {x=round(pos.x/r+0.5)*r,y=round(pos.y/r+0.5)*r+1,z=round(pos.z/r+0.5)*r}
if minetest.get_node(p).name == "basic_machines:distributor" then -- attempt to activate distributor at special grid location: coordinates of the form 10+20*i
local meta = minetest.get_meta(p);
if meta:get_int("active1") == 0 then -- first output is disabled, indicating ready to be used as event handler
if meta:get_int("x1") ~= 0 then -- trigger protection event
meta:set_string("infotext",digger); -- record diggers name onto distributor
local table = minetest.registered_nodes["basic_machines:distributor"];
local effector=table.mesecons.effector;
local node = nil;
effector.action_on(p,node,machines_TTL);
end
end
end
end
return is_protected;
end
minetest.register_on_chat_message(function(name, message)
local player = minetest.get_player_by_name(name);
if not player then return end
local pos = player:getpos();
local r = 20;local p = {x=round(pos.x/r+0.5)*r,y=round(pos.y/r+0.5)*r+1,z=round(pos.z/r+0.5)*r}
--minetest.chat_send_all(minetest.pos_to_string(p))
if minetest.get_node(p).name == "basic_machines:distributor" then -- attempt to activate distributor at special grid location: coordinates of the form 20*i
local meta = minetest.get_meta(p);
if meta:get_int("active1") == 0 then -- first output is disabled, indicating ready to be used as event handler
local y1 = meta:get_int("y1");
if y1 ~= 0 then -- chat event, positive relays message, negative drops it
meta:set_string("infotext",message); -- record diggers message
local table = minetest.registered_nodes["basic_machines:distributor"];
local effector=table.mesecons.effector;
local node = nil;
effector.action_on(p,node,machines_TTL);
if y1<0 then return true
end
end
end
end
end
)

View file

@ -1,244 +0,0 @@
-- rnd 2015:
-- this node works as a reverse of crafting process with a 25% loss of items (aka recycling). You can select which recipe to use when recycling.
-- There is a fuel cost to recycle
-- prevent unrealistic recyclings
local no_recycle_list = {
["default:steel_ingot"]=1,["default:copper_ingot"]=1,["default:bronze_ingot"]=1,["default:gold_ingot"]=1,
["dye:white"]=1,["dye:grey"]=1,["dye:dark_grey"]=1,["dye:black"]=1,
["dye:violet"]=1,["dye:blue"]=1,["dye:cyan"]=1,["dye:dark_green"]=1,
["dye:green"]=1,["dye:yellow"]=1,["dye:brown"]=1,["dye:orange"]=1,
["dye:red"]=1,["dye:magenta"]=1,["dye:pink"]=1,
}
local recycler_process = function(pos)
local node = minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z}).name;
local meta = minetest.get_meta(pos);local inv = meta:get_inventory();
-- FUEL CHECK
local fuel = meta:get_float("fuel");
if fuel-1<0 then -- we need new fuel, check chest below
local fuellist = inv:get_list("fuel")
if not fuellist then return end
local fueladd, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
local supply=0;
if fueladd.time == 0 then -- no fuel inserted, try look for outlet
-- No valid fuel in fuel list
supply = basic_machines.check_power({x=pos.x,y=pos.y-1,z=pos.z},1) or 0;
if supply>0 then
fueladd.time = 40*supply -- same as 10 coal
else
meta:set_string("infotext", "Please insert fuel.");
return;
end
else
if supply==0 then -- Take fuel from fuel list if no supply available
inv:set_stack("fuel", 1, afterfuel.items[1])
fueladd.time = fueladd.time*0.1; -- thats 4 for coal
end
end
if fueladd.time>0 then
fuel=fuel + fueladd.time
meta:set_float("fuel",fuel);
meta:set_string("infotext", "added fuel furnace burn time " .. fueladd.time .. ", fuel status " .. fuel);
end
if fuel-1<0 then return end
end
-- RECYCLING: check out inserted items
local stack = inv:get_stack("src",1);
if stack:is_empty() then return end; -- nothing to do
local src_item = stack:to_string();
local p=string.find(src_item," "); if p then src_item = string.sub(src_item,1,p-1) end -- take first word to determine what item was
-- look if we already handled this item
local known_recipe=true;
if src_item~=meta:get_string("node") then-- did we already handle this? if yes read from cache
meta:set_string("node",src_item);
meta:set_string("itemlist","{}");
meta:set_int("reqcount",0);
known_recipe=false;
end
local itemlist, reqcount;
reqcount = 1; -- needed count of materials for recycle to work
if not known_recipe then
if no_recycle_list[src_item] then meta:set_string("node","") return end -- dont allow recycling of forbidden items
local recipe = minetest.get_all_craft_recipes( src_item );
local recipe_id = tonumber(meta:get_int("recipe")) or 1;
if not recipe then
return
else
itemlist = recipe[recipe_id];
if not itemlist then meta:set_string("node","") return end;
itemlist=itemlist.items;
end
local output = recipe[recipe_id].output or "";
if string.find(output," ") then
local par = string.find(output," ");
--if (tonumber(string.sub(output, par)) or 0)>1 then itemlist = {} end
if par then
reqcount = tonumber(string.sub(output, par)) or 1;
end
end
meta:set_string("itemlist",minetest.serialize(itemlist)); -- read cached itemlist
meta:set_int("reqcount",reqcount);
else
itemlist=minetest.deserialize(meta:get_string("itemlist")) or {};
reqcount = meta:get_int("reqcount") or 1;
end
if stack:get_count()<reqcount then
meta:set_string("infotext", "at least " .. reqcount .. " of " .. src_item .. " is needed ");
return
end
--empty dst inventory before proceeding
-- local size = inv:get_size("dst");
-- for i=1,size do
-- inv:set_stack("dst", i, ItemStack(""));
-- end
--take 1 item from src inventory for each activation
stack=stack:take_item(reqcount); inv:remove_item("src", stack)
for _, v in pairs(itemlist) do
if math.random(1, 4)<=3 then -- probability 3/4 = 75%
if not string.find(v,"group") then -- dont add if item described with group
local par = string.find(v,"\"") or 0;
if inv:room_for_item("dst", ItemStack(v)) then -- can item be put in
inv:add_item("dst",ItemStack(v));
else return
end
end
end
end
minetest.sound_play("recycler", {pos=pos,gain=0.5,max_hear_distance = 16,})
fuel = fuel-1; -- burn fuel on succesful operation
meta:set_float("fuel",fuel); meta:set_string("infotext", "fuel status " .. fuel .. ", recycling " .. meta:get_string("node"));
end
local recycler_update_meta = function(pos)
local meta = minetest.get_meta(pos)
local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z
local form =
"size[8,8]".. -- width, height
--"size[6,10]".. -- width, height
"label[0,0;IN] label[1,0;OUT] label[0,2;FUEL] "..
"list["..list_name..";src;0.,0.5;1,1;]"..
"list["..list_name..";dst;1.,0.5;3,3;]"..
"list["..list_name..";fuel;0.,2.5;1,1;]"..
"list[current_player;main;0,4;8,4;]"..
"field[4.5,0.75;2,1;recipe;select recipe: ;"..(meta:get_int("recipe")).."]"..
"button[6.5,0.5;1,1;OK;OK]"..
"listring["..list_name..";dst]"..
"listring[current_player;main]"..
"listring["..list_name..";src]"..
"listring[current_player;main]"..
"listring["..list_name..";fuel]"..
"listring[current_player;main]"
--"field[0.25,4.5;2,1;mode;mode;"..mode.."]"
meta:set_string("formspec", form)
end
minetest.register_node("basic_machines:recycler", {
description = "Recycler - use to get some ingredients back from crafted things",
tiles = {"recycler.png"},
groups = {cracky=3, mesecon_effector_on = 1},
sounds = default.node_sound_wood_defaults(),
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos);
meta:set_string("infotext", "Recycler: put one item in it (src) and obtain 75% of raw materials (dst). To operate it insert fuel, then insert item to recycle or use keypad to activate it.")
meta:set_string("owner", placer:get_player_name());
meta:set_int("recipe",1);
meta:set_float("fuel",0);
local inv = meta:get_inventory();inv:set_size("src", 1);inv:set_size("dst",9);inv:set_size("fuel",1);
end,
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if minetest.is_protected(pos, player:get_player_name()) and not privs.privs then return end -- only owner can interact with recycler
recycler_update_meta(pos);
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if meta:get_string("owner")~=player:get_player_name() and not privs.privs then return 0 end
return stack:get_count();
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if meta:get_string("owner")~=player:get_player_name() and not privs.privs then return 0 end
return stack:get_count();
end,
on_metadata_inventory_put = function(pos, listname, index, stack, player)
if listname =="dst" then return end
recycler_process(pos);
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
return 0;
end,
mesecons = {effector = {
action_on = function (pos, node,ttl)
if type(ttl)~="number" then ttl = 1 end
if ttl<0 then return end -- machines_TTL prevents infinite recursion
recycler_process(pos);
end
}
},
on_receive_fields = function(pos, formname, fields, sender)
if minetest.is_protected(pos, sender:get_player_name()) then return end
if fields.quit then return end
local meta = minetest.get_meta(pos);
local recipe=1;
if fields.recipe then
recipe = tonumber(fields.recipe) or 1;
else return;
end
meta:set_int("recipe",recipe);
meta:set_string("node",""); -- this will force to reread recipe on next use
recycler_update_meta(pos);
end,
})
-- minetest.register_craft({
-- output = "basic_machines:recycler",
-- recipe = {
-- {"default:mese_crystal","default:mese_crystal","default:mese_crystal"},
-- {"default:mese_crystal","default:diamondblock","default:mese_crystal"},
-- {"default:mese_crystal","default:mese_crystal","default:mese_crystal"},
-- }
-- })

Binary file not shown.

Binary file not shown.

View file

@ -1,517 +0,0 @@
local machines_timer=5
local machines_minstep = 1
-- BATTERY
local battery_update_meta = function(pos)
local meta = minetest.get_meta(pos)
local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z
local capacity = meta:get_float("capacity")
local maxpower = meta:get_float("maxpower")
local energy = math.ceil(10*meta:get_float("energy"))/10
local form =
"size[8,6.5]".. -- width, height
"label[0,0;FUEL] ".."label[6,0;UPGRADE] "..
"label[0.,1.5;UPGRADE: diamond/mese block for power/capacity]"..
"label[0.,1.75;UPGRADE: maxpower ".. maxpower .. " / CAPACITY " .. meta:get_int("capacity") .. "]"..
"list["..list_name..";fuel;0.,0.5;1,1;]".. "list["..list_name..";upgrade;6.,0.5;2,2;]" ..
"list[current_player;main;0,2.5;8,4;]"..
"button[4.5,0.35;1.5,1;OK;REFRESH]"..
"listring["..list_name..";upgrade]"..
"listring[current_player;main]"..
"listring["..list_name..";fuel]"..
"listring[current_player;main]"
meta:set_string("formspec", form)
end
--[power crystal name] = energy provided
basic_machines.energy_crystals = {
["basic_machines:power_cell"]=1,
["basic_machines:power_block"]=11,
["basic_machines:power_rod"]=100,
}
battery_recharge = function(pos)
local meta = minetest.get_meta(pos);
local energy = meta:get_float("energy");
local capacity = meta:get_float("capacity");
local inv = meta:get_inventory();
local stack = inv:get_stack("fuel", 1); local item = stack:get_name();
local crystal = false;
local add_energy=0;
add_energy = basic_machines.energy_crystals[item] or 0;
if add_energy>0 then
if pos.y>1500 then add_energy=2*add_energy end -- in space recharge is more efficient
crystal = true;
if add_energy<=capacity then
stack:take_item(1);
inv:set_stack("fuel", 1, stack)
else
meta:set_string("infotext", "recharge problem: capacity " .. capacity .. ", needed " .. energy+add_energy)
return energy
end
else -- try do determine caloric value of fuel inside battery
local fuellist = inv:get_list("fuel");if not fuellist then return energy end
local fueladd, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
if fueladd.time > 0 then
add_energy = fueladd.time/40;
if energy+add_energy<=capacity then
inv:set_stack("fuel", 1, afterfuel.items[1]);
end
end
end
if add_energy>0 then
energy=energy+add_energy
if energy<0 then energy = 0 end
if energy>capacity then energy = capacity end -- excess energy is wasted
meta:set_float("energy",energy);
meta:set_string("infotext", "(R) energy: " .. math.ceil(energy*10)/10 .. " / ".. capacity);
minetest.sound_play("electric_zap", {pos=pos,gain=0.05,max_hear_distance = 8,})
end
local full_coef = math.floor(energy/capacity*3); if full_coef > 2 then full_coef = 2 end
minetest.swap_node(pos,{name = "basic_machines:battery_".. full_coef}) -- graphic energy
return energy; -- new battery energy level
end
battery_upgrade = function(pos)
local meta = minetest.get_meta(pos);
local inv = meta:get_inventory();
local count1,count2;count1=0;count2=0;
local stack,item,count;
for i=1,4 do
stack = inv:get_stack("upgrade", i);item = stack:get_name();count= stack:get_count();
if item == "default:mese" then
count1=count1+count
elseif item == "default:diamondblock" then
count2=count2+count
end
end
--if count1<count2 then count =count1 else count=count2 end
if pos.y>1500 then count1 = 2*count1; count2=2*count2 end -- space increases efficiency
meta:set_int("upgrade",count2); -- diamond for power
-- adjust capacity
--yyy
local capacity = 3+3*count1; -- mese for capacity
local maxpower = 1+count2*2; -- old 99 upgrade -> 200 power
capacity = math.ceil(capacity*10)/10;
local energy = 0;
meta:set_float("capacity",capacity)
meta:set_float("maxpower",maxpower)
meta:set_float("energy",0)
meta:set_string("infotext", "energy: " .. math.ceil(energy*10)/10 .. " / ".. capacity);
end
local machines_activate_furnace = minetest.registered_nodes["default:furnace"].on_metadata_inventory_put; -- this function will activate furnace
minetest.register_node("basic_machines:battery_0", {
description = "battery - stores energy, generates energy from fuel, can power nearby machines, or accelerate/run furnace above it. Its upgradeable.",
tiles = {"basic_machine_outlet.png","basic_machine_side.png","basic_machine_battery_0.png"},
groups = {cracky=3, mesecon_effector_on = 1},
sounds = default.node_sound_wood_defaults(),
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos);
meta:set_string("infotext","battery - stores energy, generates energy from fuel, can power nearby machines, or accelerate/run furnace above it when activated by keypad");
meta:set_string("owner",placer:get_player_name());
local inv = meta:get_inventory();inv:set_size("fuel", 1*1); -- place to put crystals
inv:set_size("upgrade", 2*2);
meta:set_int("upgrade",0); -- upgrade level determines energy storage capacity and max energy output
meta:set_float("capacity",3);meta:set_float("maxpower",1);
meta:set_float("energy",0);
end,
mesecons = {effector = {
action_on = function (pos, node,ttl)
if type(ttl)~="number" then ttl = 1 end
if ttl<0 then return end -- machines_TTL prevents infinite recursion
local meta = minetest.get_meta(pos);
local energy = meta:get_float("energy");
local capacity = meta:get_float("capacity");
local full_coef = math.floor(energy/capacity*3);
-- try to power furnace on top of it
if energy>=1 then -- need at least 1 energy
pos.y=pos.y+1; local node = minetest.get_node(pos).name;
if node== "default:furnace" or node=="default:furnace_active" then
local fmeta = minetest.get_meta(pos);
local fuel_totaltime = fmeta:get_float("fuel_totaltime") or 0;
local fuel_time = fmeta:get_float("fuel_time") or 0;
local t0 = meta:get_int("ftime"); -- furnace time
local t1 = minetest.get_gametime();
if t1-t0<machines_minstep then -- to prevent too quick furnace acceleration, punishment is cooking reset
fmeta:set_float("src_time",0); return
end
meta:set_int("ftime",t1);
local upgrade = meta:get_int("upgrade");upgrade=upgrade*0.1;
--if fuel_time>4 then -- accelerated cooking
local src_time = fmeta:get_float("src_time") or 0
energy = energy - 0.25*upgrade; -- use energy to accelerate burning
if fuel_time>40 or fuel_totaltime == 0 or node=="default:furnace" then -- to add burn time: must burn for at least 40 secs or furnace out of fuel
fmeta:set_float("fuel_totaltime",60);fmeta:set_float("fuel_time",0) -- add 60 second burn time to furnace
energy=energy-0.5; -- use up energy to add fuel
-- make furnace start if not already started
if node~="default:furnace_active" and machines_activate_furnace then machines_activate_furnace(pos) end
-- update energy display
end
if energy<0 then
energy = 0
else -- only accelerate if we had enough energy, note: upgrade*0.1*0.25<power_rod is limit upgrade, so upgrade = 40*100 = 4000
fmeta:set_float("src_time",src_time+machines_timer*upgrade); -- accelerated smelt: with 99 upgrade battery furnace works 11x faster
end
meta:set_float("energy",energy);
meta:set_string("infotext", "energy: " .. math.ceil(energy*10)/10 .. " / ".. capacity);
if energy>=1 then -- no need to recharge yet, will still work next time
local full_coef_new = math.floor(energy/capacity*3); if full_coef_new>2 then full_coef_new = 2 end
pos.y = pos.y-1;
if full_coef_new ~= full_coef then minetest.swap_node(pos,{name = "basic_machines:battery_".. full_coef_new}) end
return
else
local infotext = meta:get_string("infotext");
local new_infotext = "furnace needs at least 1 energy";
if new_infotext~=infotext then -- dont update unnecesarilly
meta:set_string("infotext", new_infotext);
pos.y=pos.y-1; -- so that it points to battery again!
end
end
else
pos.y=pos.y-1;
end
end
-- try to recharge by converting inserted fuel/power cells into energy
if energy<capacity then -- not full, try to recharge
battery_recharge(pos);
return
end
local full_coef_new = math.floor(energy/capacity*3); if full_coef_new>2 then full_coef_new = 2 end
if full_coef_new ~= full_coef then minetest.swap_node(pos,{name = "basic_machines:battery_".. full_coef_new}) end
end
}},
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if minetest.is_protected(pos,player:get_player_name()) and not privs.privs then return end -- only owner can interact with recycler
battery_update_meta(pos);
end,
on_receive_fields = function(pos, formname, fields, sender)
if fields.quit then return end
local meta = minetest.get_meta(pos);
battery_update_meta(pos);
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if minetest.is_protected(pos,player:get_player_name()) and not privs.privs then return 0 end
return stack:get_count();
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if minetest.is_protected(pos,player:get_player_name()) and not privs.privs then return 0 end
return stack:get_count();
end,
on_metadata_inventory_put = function(pos, listname, index, stack, player)
if listname=="fuel" then
battery_recharge(pos);
battery_update_meta(pos);
elseif listname == "upgrade" then
battery_upgrade(pos);
battery_update_meta(pos);
end
return stack:get_count();
end,
on_metadata_inventory_take = function(pos, listname, index, stack, player)
if listname == "upgrade" then
battery_upgrade(pos);
battery_update_meta(pos);
end
return stack:get_count();
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
return 0;
end,
can_dig = function(pos)
local meta = minetest.get_meta(pos);
if meta:get_int("upgrade")~=0 then return false else return true end
end
})
-- GENERATOR
local generator_update_meta = function(pos)
local meta = minetest.get_meta(pos);
local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z
local form =
"size[8,6.5]" .. -- width, height
"label[0,0;POWER CRYSTALS] ".."label[6,0;UPGRADE] "..
"label[1,1;UPGRADE LEVEL ".. meta:get_int("upgrade").." (generator)]"..
"list["..list_name..";fuel;0.,0.5;1,1;]"..
"list["..list_name..";upgrade;6.,0.5;2,1;]"..
"list[current_player;main;0,2.5;8,4;]"..
"button[4.5,1.5;1.5,1;OK;REFRESH]"..
"button[6,1.5;1.5,1;help;help]"..
"listring["..list_name..";fuel]"..
"listring[current_player;main]"..
"listring["..list_name..";upgrade]"..
"listring[current_player;main]"
meta:set_string("formspec", form)
end
generator_upgrade = function(pos)
local meta = minetest.get_meta(pos);
local inv = meta:get_inventory();
local stack,item,count;
count = 0
for i=1,2 do
stack = inv:get_stack("upgrade", i);item = stack:get_name();
if item == "basic_machines:generator" then
count= count + stack:get_count();
end
end
meta:set_int("upgrade",count);
end
minetest.register_node("basic_machines:generator", {
description = "Generator - very expensive, generates power crystals that provide power. Its upgradeable.",
tiles = {"basic_machine_generator.png"},
groups = {cracky=3, mesecon_effector_on = 1},
sounds = default.node_sound_wood_defaults(),
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos);
meta:set_string("infotext","generator - generates power crystals that provide power. Upgrade with up to 99 gold/diamond blocks.");
meta:set_string("owner",placer:get_player_name());
local inv = meta:get_inventory();
inv:set_size("fuel", 1*1); -- here generated power crystals are placed
inv:set_size("upgrade", 2*1);
meta:set_int("upgrade",0); -- upgrade level determines quality of produced crystals
end,
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if minetest.is_protected(pos,player:get_player_name()) and not privs.privs then return end -- only owner can interact with recycler
generator_update_meta(pos);
end,
on_receive_fields = function(pos, formname, fields, sender)
if fields.quit then return end
if fields.help then
local text = "Generator slowly produces power crystals. Those can be used to recharge batteries and come in 3 flavors:\n\n low level (0-4), medium level (5-19) and high level (20+). Upgrading the generator (upgrade with generators) will increase the rate at which the crystals are produced.\n\nYou can automate the process of battery recharging by using mover in inventory mode, taking from inventory \"fuel\"";
local form = "size [6,7] textarea[0,0;6.5,8.5;help;GENERATOR HELP;".. text.."]"
minetest.show_formspec(sender:get_player_name(), "basic_machines:help_mover", form)
return
end
local meta = minetest.get_meta(pos);
generator_update_meta(pos);
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if minetest.is_protected(pos,player:get_player_name()) and not privs.privs then return 0 end
return stack:get_count();
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if minetest.is_protected(pos,player:get_player_name()) and not privs.privs then return 0 end
return stack:get_count();
end,
on_metadata_inventory_put = function(pos, listname, index, stack, player)
if listname == "upgrade" then
generator_upgrade(pos);
generator_update_meta(pos);
end
return stack:get_count();
end,
on_metadata_inventory_take = function(pos, listname, index, stack, player)
if listname == "upgrade" then
generator_upgrade(pos);
generator_update_meta(pos);
end
return stack:get_count();
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
return 0;
end,
can_dig = function(pos)
local meta = minetest.get_meta(pos);
if meta:get_int("upgrade")~=0 then return false else return true end
end
})
minetest.register_abm({
nodenames = {"basic_machines:generator"},
neighbors = {""},
interval = 19,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
local meta = minetest.get_meta(pos);
local upgrade = meta:get_int("upgrade");
local inv = meta:get_inventory();
local stack = inv:get_stack("fuel", 1);
local crystal, text;
if upgrade >= 20 then
crystal = "basic_machines:power_rod " .. math.floor(1+(upgrade-20)*9/178)
text = "high upgrade: power rod";
elseif upgrade >=5 then
crystal ="basic_machines:power_block " .. math.floor(1+(upgrade-5)*9/15);
text = "medium upgrade: power block";
else
crystal ="basic_machines:power_cell " .. math.floor(1+2*upgrade);
text = "low upgrade: power cell";
end
local morecrystal = ItemStack(crystal)
stack:add_item(morecrystal);
inv:set_stack("fuel", 1, stack)
meta:set_string("infotext",text)
end
})
-- API for power distribution
function basic_machines.check_power(pos, power_draw) -- mover checks power source - battery
--minetest.chat_send_all(" battery: check_power " .. minetest.pos_to_string(pos) .. " " .. power_draw)
local batname = "basic_machines:battery";
if not string.find(minetest.get_node(pos).name,batname) then
return -1 -- battery not found!
end
local meta = minetest.get_meta(pos);
local energy = meta:get_float("energy");
local capacity = meta:get_float("capacity");
local maxpower = meta:get_float("maxpower");
local full_coef = math.floor(energy/capacity*3); -- 0,1,2
if power_draw>maxpower then
meta:set_string("infotext", "Power draw required : " .. power_draw .. " maximum power output " .. maxpower .. ". Please upgrade battery")
return 0;
end
if power_draw>energy then
energy = battery_recharge(pos); -- try recharge battery and continue operation immidiately
if not energy then return 0 end
end
energy = energy-power_draw;
if energy<0 then
meta:set_string("infotext", "used fuel provides too little power for current power draw ".. power_draw);
return 0
end -- recharge wasnt enough, needs to be repeated manually, return 0 power available
meta:set_float("energy", energy);
-- update energy display
meta:set_string("infotext", "energy: " .. math.ceil(energy*10)/10 .. " / ".. capacity);
local full_coef_new = math.floor(energy/capacity*3); if full_coef_new>2 then full_coef_new = 2 end
if full_coef_new ~= full_coef then minetest.swap_node(pos,{name = "basic_machines:battery_".. full_coef_new}) end -- graphic energy level display
return power_draw;
end
------------------------
-- CRAFTS
------------------------
-- minetest.register_craft({
-- output = "basic_machines:battery",
-- recipe = {
-- {"","default:steel_ingot",""},
-- {"default:steel_ingot","default:mese","default:steel_ingot"},
-- {"","default:diamond",""},
-- }
-- })
-- minetest.register_craft({
-- output = "basic_machines:generator",
-- recipe = {
-- {"","",""},
-- {"default:diamondblock","basic_machines:battery","default:diamondblock"},
-- {"default:diamondblock","default:diamondblock","default:diamondblock"}
-- }
-- })
minetest.register_craftitem("basic_machines:power_cell", {
description = "Power cell - provides 1 power",
inventory_image = "power_cell.png",
stack_max = 25
})
minetest.register_craftitem("basic_machines:power_block", {
description = "Power block - provides 11 power",
inventory_image = "power_block.png",
stack_max = 25
})
minetest.register_craftitem("basic_machines:power_rod", {
description = "Power rod - provides 100 power",
inventory_image = "power_rod.png",
stack_max = 25
})
-- various battery levels: 0,1,2 (2 >= 66%, 1 >= 33%,0>=0%)
local batdef = {};
for k,v in pairs(minetest.registered_nodes["basic_machines:battery_0"]) do batdef[k] = v end
for i = 1,2 do
batdef.tiles[3] = "basic_machine_battery_" .. i ..".png"
minetest.register_node("basic_machines:battery_"..i, batdef)
end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 238 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 325 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 315 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 316 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 B

View file

@ -71,7 +71,7 @@ minetest.register_node("digilines:chest", {
return return
end end
if fields.channel ~= nil then if fields.channel ~= nil then
minetest.get_meta(pos):set_string("channel",fields.channel) minetest.get_meta(pos):set_string("channel", fields.channel)
end end
end, end,
digiline = { digiline = {
@ -81,70 +81,32 @@ minetest.register_node("digilines:chest", {
} }
}, },
tube = { tube = {
insert_object = function(pos, node, stack, direction)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return inv:add_item("main", stack)
end,
can_insert = function(pos, node, stack, direction)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return inv:room_for_item("main", stack)
end,
connect_sides = {left=1, right=1, back=1, front=1, bottom=1, top=1}, connect_sides = {left=1, right=1, back=1, front=1, bottom=1, top=1},
connects = function(i,param2)
return not pipeworks.connects.facingFront(i,param2)
end,
input_inventory = "main", input_inventory = "main",
can_insert = function(pos, _, stack)
return can_insert(pos, stack)
end,
insert_object = function(pos, _, stack)
local inv = minetest.get_meta(pos):get_inventory()
local leftover = inv:add_item("main", stack)
local count = leftover:get_count()
if count == 0 then
local derpstack = stack:get_name()..' 1'
if not inv:room_for_item("main", derpstack) then
-- when you can't put a single more of whatever you just put,
-- you'll get a put for it, then a full
sendMessage(pos,"full "..maybeString(stack)..' '..tostring(count))
end
else
-- this happens when the chest has received two stacks in a row and
-- filled up exactly with the first one.
-- You get a put for the first stack, a put for the second
-- and then a overflow with the first in stack and the second in leftover
-- and NO full?
sendMessage(pos,"overflow "..maybeString(stack)..' '..tostring(count))
end
return leftover
end,
}, },
allow_metadata_inventory_put = function(pos, _, _, stack)
if not can_insert(pos, stack) then
sendMessage(pos,"uoverflow "..maybeString(stack))
end
return stack:get_count()
end,
on_metadata_inventory_move = function(pos, _, _, _, _, _, player) on_metadata_inventory_move = function(pos, _, _, _, _, _, player)
minetest.log("action", player:get_player_name().." moves stuff in chest at "..minetest.pos_to_string(pos)) minetest.log("action", player:get_player_name().." moves stuff in chest at "..minetest.pos_to_string(pos))
end, end,
on_metadata_inventory_put = function(pos, _, _, stack, player) on_metadata_inventory_put = function(pos, _, _, stack, player)
local channel = minetest.get_meta(pos):get_string("channel") local channel = minetest.get_meta(pos):get_string("channel")
local send = function(msg) sendMessage(pos, "uput "..maybeString(stack), channel)
sendMessage(pos,msg,channel)
end
-- direction is only for furnaces
-- as the item has already been put, can_insert should return false if the chest is now full.
local derpstack = stack:get_name()..' 1'
if can_insert(pos,derpstack) then
send("uput "..maybeString(stack))
else
send("ufull "..maybeString(stack))
end
minetest.log("action", player:get_player_name().." puts stuff into chest at "..minetest.pos_to_string(pos)) minetest.log("action", player:get_player_name().." puts stuff into chest at "..minetest.pos_to_string(pos))
end, end,
on_metadata_inventory_take = function(pos, listname, _, stack, player) on_metadata_inventory_take = function(pos, listname, _, stack, player)
local meta = minetest.get_meta(pos) local channel = minetest.get_meta(pos):get_string("channel")
local channel = meta:get_string("channel") sendMessage(pos, "utake "..maybeString(stack), channel)
local inv = meta:get_inventory()
if inv:is_empty(listname) then
sendMessage(pos, "empty", channel)
end
sendMessage(pos,"utake "..maybeString(stack))
minetest.log("action", player:get_player_name().." takes stuff from chest at "..minetest.pos_to_string(pos)) minetest.log("action", player:get_player_name().." takes stuff from chest at "..minetest.pos_to_string(pos))
end end,
}) })
minetest.register_craft({ minetest.register_craft({

View file

@ -141,7 +141,7 @@ local function commandblock_action_on(pos, node)
end end
local commands = resolve_commands(meta:get_string("commands"), pos) local commands = resolve_commands(meta:get_string("commands"), pos)
for _, command in pairs(commands:split("\n")) do for _, command in pairs(commands:split("\n/")) do
local pos = command:find(" ") local pos = command:find(" ")
local cmd, param = command, "" local cmd, param = command, ""
if pos then if pos then

View file

@ -70,6 +70,7 @@ function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky)
while #frontiers > 0 do while #frontiers > 0 do
local np = frontiers[1] local np = frontiers[1]
local nn = minetest.get_node(np) local nn = minetest.get_node(np)
if nn.name == "ignore" then return nil end
if not node_replaceable(nn.name) then if not node_replaceable(nn.name) then
table.insert(nodes, {node = nn, pos = np}) table.insert(nodes, {node = nn, pos = np})
@ -90,6 +91,7 @@ function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky)
for _, r in ipairs(mesecon.rules.alldirs) do for _, r in ipairs(mesecon.rules.alldirs) do
local adjpos = vector.add(np, r) local adjpos = vector.add(np, r)
local adjnode = minetest.get_node(adjpos) local adjnode = minetest.get_node(adjpos)
if adjnode.name == "ignore" then return nil end
if minetest.registered_nodes[adjnode.name] if minetest.registered_nodes[adjnode.name]
and minetest.registered_nodes[adjnode.name].mvps_sticky then and minetest.registered_nodes[adjnode.name].mvps_sticky then
local sticksto = minetest.registered_nodes[adjnode.name] local sticksto = minetest.registered_nodes[adjnode.name]
@ -155,7 +157,7 @@ function mesecon.mvps_push_or_pull(pos, stackdir, movedir, maximum, all_pull_sti
if not nodes then return end if not nodes then return end
-- determine if one of the nodes blocks the push / pull -- determine if one of the nodes blocks the push / pull
for id, n in ipairs(nodes) do for id, n in ipairs(nodes) do
if mesecon.is_mvps_stopper(n.node, movedir, nodes, id) then if mesecon.is_mvps_stopper(n.node, movedir, nodes, id) or minetest.is_protected(n.pos, "mvps") then
return return
end end
end end

View file

@ -17,3 +17,12 @@ minetest.register_node("mesecons_stickyblocks:sticky_block_all", {
end, end,
sounds = default.node_sound_wood_defaults(), sounds = default.node_sound_wood_defaults(),
}) })
minetest.register_craft({
output = "mesecons_stickyblocks:sticky_block_all",
recipe = {
{"mesecons_materials:glue", "mesecons_materials:glue", "mesecons_materials:glue"},
{"mesecons_materials:glue", "mesecons_materials:glue", "mesecons_materials:glue"},
{"mesecons_materials:glue", "mesecons_materials:glue", "mesecons_materials:glue"},
}
})

23
teleport_potion/README.md Normal file
View file

@ -0,0 +1,23 @@
Teleport Potion
This minetest mod adds both a teleportation potion and pad to the game
https://forum.minetest.net/viewtopic.php?f=9&t=9234
Change log:
- 1.1 - Using 0.4.16+ code changes, can only teleport players now
- 1.0 - Added changes by maybe_dragon to bookmark teleport destination before using pads and potions
- 0.9 - Update to newer functions, requires Minetest 0.4.16 to work.
- 0.8 - Teleport pads now have arrows showing direction player will face after use
- 0.7 - Can now enter descriptions for teleport pads e.g. (0,12,0,Home)
- 0.6 - Tweaked and tidied code, added map_generation_limit's
- 0.5 - Added throwable potions
- 0.4 - Code tidy and particle effects added
- 0.3 - Added Teleport Pad
- 0.2 - Bug fixes
- 0.1 - Added SFX
- 0.0 - Initial release
Lucky Blocks: 4

View file

@ -0,0 +1,3 @@
default
intllib?
lucky_block?

View file

@ -0,0 +1 @@
Adds craftable teleport potions (throwable) and teleport pads.

503
teleport_potion/init.lua Normal file
View file

@ -0,0 +1,503 @@
--= Teleport Potion mod by TenPlus1
-- Create teleport potion or pad, place then right-click to enter coords
-- and step onto pad or walk into the blue portal light, portal closes after
-- 10 seconds, pad remains, potions are throwable... SFX are license Free...
-- Load support for intllib.
local MP = minetest.get_modpath(minetest.get_current_modname())
local S, NS = dofile(MP.."/intllib.lua")
-- max teleport distance
local dist = tonumber(minetest.settings:get("map_generation_limit") or 31000)
-- creative check
local creative_mode_cache = minetest.settings:get_bool("creative_mode")
local function is_creative(name)
return creative_mode_cache or minetest.check_player_privs(name, {creative = true})
end
local check_coordinates = function(str)
if not str or str == "" then
return nil
end
-- get coords from string
local x, y, z = string.match(str, "^(-?%d+),(-?%d+),(-?%d+)$")
-- check coords
if x == nil or string.len(x) > 6
or y == nil or string.len(y) > 6
or z == nil or string.len(z) > 6 then
return nil
end
-- convert string coords to numbers
x = tonumber(x)
y = tonumber(y)
z = tonumber(z)
-- are coords in map range ?
if x > dist or x < -dist
or y > dist or y < -dist
or z > dist or z < -dist then
return nil
end
-- return ok coords
return {x = x, y = y, z = z}
end
-- particle effects
local function tp_effect(pos)
minetest.add_particlespawner({
amount = 20,
time = 0.25,
minpos = pos,
maxpos = pos,
minvel = {x = -2, y = 1, z = -2},
maxvel = {x = 2, y = 2, z = 2},
minacc = {x = 0, y = -2, z = 0},
maxacc = {x = 0, y = -4, z = 0},
minexptime = 0.1,
maxexptime = 1,
minsize = 0.5,
maxsize = 1.5,
texture = "particle.png",
glow = 15,
})
end
local teleport_destinations = {}
local function set_teleport_destination(playername, dest)
teleport_destinations[playername] = dest
tp_effect(dest)
minetest.sound_play("portal_open", {
pos = dest,
gain = 1.0,
max_hear_distance = 10
})
end
--------------------------------------------------------------------------------
--- Teleport portal
--------------------------------------------------------------------------------
minetest.register_node("teleport_potion:portal", {
drawtype = "plantlike",
tiles = {
{name="portal.png",
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 1.0
}
}
},
light_source = 13,
walkable = false,
paramtype = "light",
pointable = false,
buildable_to = true,
waving = 1,
sunlight_propagates = true,
damage_per_second = 1, -- walking into portal hurts player
-- start timer when portal appears
on_construct = function(pos)
minetest.get_node_timer(pos):start(10)
end,
-- remove portal after 10 seconds
on_timer = function(pos)
minetest.sound_play("portal_close", {
pos = pos,
gain = 1.0,
max_hear_distance = 10
})
minetest.remove_node(pos)
end,
on_blast = function() end,
drop = {},
})
-- Throwable potion
local function throw_potion(itemstack, player)
local playerpos = player:get_pos()
local obj = minetest.add_entity({
x = playerpos.x,
y = playerpos.y + 1.5,
z = playerpos.z
}, "teleport_potion:potion_entity")
local dir = player:get_look_dir()
local velocity = 20
obj:set_velocity({
x = dir.x * velocity,
y = dir.y * velocity,
z = dir.z * velocity
})
obj:set_acceleration({
x = dir.x * -3,
y = -9.5,
z = dir.z * -3
})
obj:set_yaw(player:get_look_horizontal())
obj:get_luaentity().player = player
end
local potion_entity = {
physical = true,
visual = "sprite",
visual_size = {x = 1.0, y = 1.0},
textures = {"potion.png"},
collisionbox = {0,0,0,0,0,0},
lastpos = {},
player = "",
}
potion_entity.on_step = function(self, dtime)
if not self.player then
self.object:remove()
return
end
local pos = self.object:get_pos()
if self.lastpos.x ~= nil then
local vel = self.object:get_velocity()
-- only when potion hits something physical
if vel.x == 0
or vel.y == 0
or vel.z == 0 then
if self.player ~= "" then
-- round up coords to fix glitching through doors
self.lastpos = vector.round(self.lastpos)
self.player:set_pos(self.lastpos)
minetest.sound_play("portal_close", {
pos = self.lastpos,
gain = 1.0,
max_hear_distance = 5
})
tp_effect(self.lastpos)
end
self.object:remove()
return
end
end
self.lastpos = pos
end
minetest.register_entity("teleport_potion:potion_entity", potion_entity)
--------------------------------------------------------------------------------
--- Teleport potion
--------------------------------------------------------------------------------
minetest.register_node("teleport_potion:potion", {
tiles = {"pad.png"},
drawtype = "signlike",
paramtype = "light",
paramtype2 = "wallmounted",
walkable = false,
sunlight_propagates = true,
description = S("Teleport Potion (use to set destination; place to open portal)"),
inventory_image = "potion.png",
wield_image = "potion.png",
groups = {dig_immediate = 3, vessel = 1},
selection_box = {type = "wallmounted"},
on_use = function(itemstack, user, pointed_thing)
if pointed_thing.type == "node" then
set_teleport_destination(user:get_player_name(), pointed_thing.above)
else
throw_potion(itemstack, user)
if not is_creative(user:get_player_name()) then
itemstack:take_item()
return itemstack
end
end
end,
after_place_node = function(pos, placer, itemstack, pointed_thing)
local name = placer:get_player_name()
local dest = teleport_destinations[name]
if dest then
minetest.set_node(pos, {name = "teleport_potion:portal"})
local meta = minetest.get_meta(pos)
-- Set portal destination
meta:set_int("x", dest.x)
meta:set_int("y", dest.y)
meta:set_int("z", dest.z)
-- Portal open effect and sound
tp_effect(pos)
minetest.sound_play("portal_open", {
pos = pos,
gain = 1.0,
max_hear_distance = 10
})
else
minetest.chat_send_player(name, S("Potion failed!"))
minetest.remove_node(pos)
minetest.add_item(pos, "teleport_potion:potion")
end
end,
})
-- teleport potion recipe
minetest.register_craft({
output = "teleport_potion:potion",
recipe = {
{"", "default:diamond", ""},
{"default:diamond", "vessels:glass_bottle", "default:diamond"},
{"", "default:diamond", ""},
},
})
--------------------------------------------------------------------------------
--- Teleport pad
--------------------------------------------------------------------------------
local teleport_formspec_context = {}
minetest.register_node("teleport_potion:pad", {
tiles = {"padd.png", "padd.png^[transformFY"},
drawtype = "nodebox",
paramtype = "light",
paramtype2 = "facedir",
legacy_wallmounted = true,
walkable = true,
sunlight_propagates = true,
description = S("Teleport Pad (use to set destination; place to open portal)"),
inventory_image = "padd.png",
wield_image = "padd.png",
light_source = 5,
groups = {snappy = 3},
node_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -6/16, 0.5}
},
selection_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -6/16, 0.5}
},
-- Save pointed nodes coordinates as destination for further portals
on_use = function(itemstack, user, pointed_thing)
if pointed_thing.type == "node" then
set_teleport_destination(user:get_player_name(), pointed_thing.above)
end
end,
-- Initialize teleport to saved location or the current position
after_place_node = function(pos, placer, itemstack, pointed_thing)
local meta = minetest.get_meta(pos)
local name = placer:get_player_name()
local dest = teleport_destinations[name]
if not dest then
dest = pos
end
-- Set coords
meta:set_int("x", dest.x)
meta:set_int("y", dest.y)
meta:set_int("z", dest.z)
meta:set_string("infotext", S("Pad Active (@1,@2,@3)",
dest.x, dest.y, dest.z))
minetest.sound_play("portal_open", {
pos = pos,
gain = 1.0,
max_hear_distance = 10
})
end,
-- Show formspec depending on the players privileges.
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
local name = clicker:get_player_name()
if minetest.is_protected(pos, name) then
minetest.record_protection_violation(pos, name)
return
end
local meta = minetest.get_meta(pos)
local coords = {
x = meta:get_int("x"),
y = meta:get_int("y"),
z = meta:get_int("z")
}
local coords = coords.x .. "," .. coords.y .. "," .. coords.z
local desc = meta:get_string("desc")
formspec = "field[desc;" .. S("Description") .. ";"
.. minetest.formspec_escape(desc) .. "]"
-- Only allow privileged players to change coordinates
if minetest.check_player_privs(name, "teleport") then
formspec = formspec ..
"field[coords;" .. S("Teleport coordinates") .. ";" .. coords .. "]"
end
teleport_formspec_context[name] = {
pos = pos,
coords = coords,
desc = desc,
}
minetest.show_formspec(name, "teleport_potion:set_destination", formspec)
end,
})
-- Check and set coordinates
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "teleport_potion:set_destination" then
return false
end
local name = player:get_player_name()
local context = teleport_formspec_context[name]
if not context then return false end
teleport_formspec_context[name] = nil
local meta = minetest.get_meta(context.pos)
-- Coordinates were changed
if fields.coords and fields.coords ~= context.coords then
local coords = check_coordinates(fields.coords)
if coords then
meta:set_int("x", coords.x)
meta:set_int("y", coords.y)
meta:set_int("z", coords.z)
else
minetest.chat_send_player(name, S("Teleport Pad coordinates failed!"))
end
end
-- Update infotext
if fields.desc and fields.desc ~= "" then
meta:set_string("desc", fields.desc)
meta:set_string("infotext", S("Teleport to @1", fields.desc))
else
local coords = minetest.string_to_pos("(" .. context.coords .. ")")
meta:set_string("infotext", S("Pad Active (@1,@2,@3)",
coords.x, coords.y, coords.z))
end
return true
end)
-- teleport pad recipe
minetest.register_craft({
output = "teleport_potion:pad",
recipe = {
{"teleport_potion:potion", "default:glass", "teleport_potion:potion"},
{"default:glass", "default:mese", "default:glass"},
{"teleport_potion:potion", "default:glass", "teleport_potion:potion"}
}
})
-- check portal & pad, teleport any entities on top
minetest.register_abm({
label = "Potion/Pad teleportation",
nodenames = {"teleport_potion:portal", "teleport_potion:pad"},
interval = 2,
chance = 1,
catch_up = false,
action = function(pos, node, active_object_count, active_object_count_wider)
-- check objects inside pad/portal
local objs = minetest.get_objects_inside_radius(pos, 1)
if #objs == 0 then
return
end
-- get coords from pad/portal
local meta = minetest.get_meta(pos)
if not meta then return end -- errorcheck
local target_coords = {
x = meta:get_int("x"),
y = meta:get_int("y"),
z = meta:get_int("z")
}
for n = 1, #objs do
if objs[n]:is_player() then
-- play sound on portal end
minetest.sound_play("portal_close", {
pos = pos,
gain = 1.0,
max_hear_distance = 5
})
-- move player
objs[n]:set_pos(target_coords)
-- paricle effects on arrival
tp_effect(target_coords)
-- play sound on destination end
minetest.sound_play("portal_close", {
pos = target_coords,
gain = 1.0,
max_hear_distance = 5
})
-- rotate player to look in pad placement direction
local rot = node.param2
local yaw = 0
if rot == 0 or rot == 20 then
yaw = 0 -- north
elseif rot == 2 or rot == 22 then
yaw = 3.14 -- south
elseif rot == 1 or rot == 23 then
yaw = 4.71 -- west
elseif rot == 3 or rot == 21 then
yaw = 1.57 -- east
end
objs[n]:set_look_yaw(yaw)
end
end
end
})
-- add lucky blocks
-- Teleport Potion mod
if minetest.get_modpath("lucky_block") then
lucky_block:add_blocks({
{"dro", {"teleport_potion:potion"}, 2},
{"tel"},
{"dro", {"teleport_potion:pad"}, 1},
{"lig"},
})
end
print ("[MOD] Teleport Potion loaded")

View file

@ -0,0 +1,45 @@
-- Fallback functions for when `intllib` is not installed.
-- Code released under Unlicense <http://unlicense.org>.
-- Get the latest version of this file at:
-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua
local function format(str, ...)
local args = { ... }
local function repl(escape, open, num, close)
if escape == "" then
local replacement = tostring(args[tonumber(num)])
if open == "" then
replacement = replacement..close
end
return replacement
else
return "@"..open..num..close
end
end
return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl))
end
local gettext, ngettext
if minetest.get_modpath("intllib") then
if intllib.make_gettext_pair then
-- New method using gettext.
gettext, ngettext = intllib.make_gettext_pair()
else
-- Old method using text files.
gettext = intllib.Getter()
end
end
-- Fill in missing functions.
gettext = gettext or function(msgid, ...)
return format(msgid, ...)
end
ngettext = ngettext or function(msgid, msgid_plural, n, ...)
return format(n==1 and msgid or msgid_plural, ...)
end
return gettext, ngettext

View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 TenPlus1
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -0,0 +1,59 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-05-14 08:37+0200\n"
"PO-Revision-Date: 2016-05-27 08:38+0200\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.12\n"
"Last-Translator: Xanthin\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Language: de\n"
#: init.lua
msgid "Teleport Potion (place and right-click to enchant location)"
msgstr ""
"Teleportationstrank (platzieren und rechtsklicken,\n"
"um Standort zu verzaubern)"
#: init.lua
msgid "Enter teleport coords (e.g. 200,20,-200)"
msgstr "Koordinaten eingeben (z.B. 200,20,-200)"
#: init.lua
msgid "Right-click to enchant teleport location"
msgstr "Rechtsklick um Teleportationsort zu verzaubern"
#: init.lua
msgid "Potion failed!"
msgstr "Trank misslungen!"
#: init.lua
msgid "Teleport Pad (place and right-click to enchant location)"
msgstr ""
"Teleportationsfeld (platzieren und rechtsklicken,\n"
"um Standort zu verzaubern)"
#: init.lua
msgid "Enter teleport coords (e.g. 200,20,-200,Home)"
msgstr "Koordinaten eingeben (z.B. 200,20,-200,Haus)"
#: init.lua
msgid "Teleport to @1"
msgstr "Teleportiere nach @1"
#: init.lua
msgid "Pad Active (@1,@2,@3)"
msgstr "Feld aktiv (@1,@2,@3)"
#: init.lua
msgid "Teleport Pad coordinates failed!"
msgstr "Teleportationsfeldkoordinaten fehlgeschlagen!"

View file

@ -0,0 +1,55 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-05-14 08:35+0200\n"
"PO-Revision-Date: 2017-05-14 08:37+0200\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.12\n"
"Last-Translator: Peppy <peppy@twang-factory.com>\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"Language: fr\n"
#: init.lua
msgid "Teleport Potion (place and right-click to enchant location)"
msgstr "Potion de téléportation (poser puis clic-droit pour enchanter l'emplacement)"
#: init.lua
msgid "Enter teleport coords (e.g. 200,20,-200)"
msgstr "Saisissez les coordonnées de téléportation (ex : 200,20,-200)"
#: init.lua
msgid "Right-click to enchant teleport location"
msgstr "Clic-droit pour enchanter l'emplacement de téléportation"
#: init.lua
msgid "Potion failed!"
msgstr "La potion n'a pas fonctionné !"
#: init.lua
msgid "Teleport Pad (place and right-click to enchant location)"
msgstr "Pad de téléportation (poser puis clic-droit pour enchanter l'emplacement)"
#: init.lua
msgid "Enter teleport coords (e.g. 200,20,-200,Home)"
msgstr "Saisissez les coordonnées de téléportation (ex : 200,20,-200,Maison)"
#: init.lua
msgid "Teleport to @1"
msgstr "Téléportation vers @1"
#: init.lua
msgid "Pad Active (@1,@2,@3)"
msgstr "Pad activé (@1,@,2,@3)"
#: init.lua
msgid "Teleport Pad coordinates failed!"
msgstr "Les coordonnées du pad sont inchangées !"

View file

@ -0,0 +1,54 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-05-14 08:34+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: init.lua
msgid "Teleport Potion (place and right-click to enchant location)"
msgstr ""
#: init.lua
msgid "Enter teleport coords (e.g. 200,20,-200)"
msgstr ""
#: init.lua
msgid "Right-click to enchant teleport location"
msgstr ""
#: init.lua
msgid "Potion failed!"
msgstr ""
#: init.lua
msgid "Teleport Pad (place and right-click to enchant location)"
msgstr ""
#: init.lua
msgid "Enter teleport coords (e.g. 200,20,-200,Home)"
msgstr ""
#: init.lua
msgid "Teleport to @1"
msgstr ""
#: init.lua
msgid "Pad Active (@1,@2,@3)"
msgstr ""
#: init.lua
msgid "Teleport Pad coordinates failed!"
msgstr ""

1
teleport_potion/mod.conf Normal file
View file

@ -0,0 +1 @@
name = teleport_potion

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

View file

@ -31,6 +31,7 @@ local ferment = {
{"wine:blue_agave", "wine:glass_tequila"}, {"wine:blue_agave", "wine:glass_tequila"},
{"farming:wheat", "wine:glass_wheat_beer"}, {"farming:wheat", "wine:glass_wheat_beer"},
{"farming:rice", "wine:glass_sake"}, {"farming:rice", "wine:glass_sake"},
{"xdecor:honey", "wine:glass_mead"},
} }
function wine:add_item(list) function wine:add_item(list)

View file

@ -1,52 +1,59 @@
--- Lua code execution functions. --- Lua code execution functions.
-- @module worldedit.code -- @module worldedit.code
--- Executes `code` as a Lua chunk in the global namespace. --- Executes `code` as a Lua chunk in the global namespace.
-- @return An error message if the code fails, or nil on success. -- @return An error message if the code fails, or nil on success.
function worldedit.lua(code) function worldedit.lua(code)
local func, err = loadstring(code) local func, err = loadstring(code)
if not func then -- Syntax error if not func then -- Syntax error
return err return err
end end
local good, err = pcall(func) local good, err = pcall(func)
if not good then -- Runtime error if not good then -- Runtime error
return err return err
end end
return nil return nil
end end
--- Executes `code` as a Lua chunk in the global namespace with the variable --- Executes `code` as a Lua chunk in the global namespace with the variable
-- pos available, for each node in a region defined by positions `pos1` and -- pos available, for each node in a region defined by positions `pos1` and
-- `pos2`. -- `pos2`.
-- @return An error message if the code fails, or nil on success. -- @return An error message if the code fails, or nil on success.
function worldedit.luatransform(pos1, pos2, code) function worldedit.luatransform(pos1, pos2, code)
pos1, pos2 = worldedit.sort_pos(pos1, pos2) pos1, pos2 = worldedit.sort_pos(pos1, pos2)
local factory, err = loadstring("return function(pos) " .. code .. " end") local factory, err = loadstring("return function(pos) " .. code .. " end")
if not factory then -- Syntax error if not factory then -- Syntax error
return err return err
end end
local func = factory() local func = factory()
worldedit.keep_loaded(pos1, pos2) worldedit.keep_loaded(pos1, pos2)
local pos = {x=pos1.x, y=0, z=0} local pos = {x=pos1.x, y=0, z=0}
while pos.x <= pos2.x do while pos.x <= pos2.x do
pos.y = pos1.y pos.y = pos1.y
while pos.y <= pos2.y do while pos.y <= pos2.y do
pos.z = pos1.z pos.z = pos1.z
while pos.z <= pos2.z do while pos.z <= pos2.z do
local good, err = pcall(func, pos) local good, err = pcall(func, pos)
if not good then -- Runtime error if not good then -- Runtime error
return err return err
end end
pos.z = pos.z + 1 pos.z = pos.z + 1
end end
pos.y = pos.y + 1 pos.y = pos.y + 1
end end
pos.x = pos.x + 1 pos.x = pos.x + 1
end end
return nil return nil
end end
local input = io.open(minetest.get_worldpath().."/init.lua", "r")
if input then
local code = input:read("*a")
input:close()
worldedit.lua(code)
end

View file

@ -242,6 +242,7 @@ xdecor.register("workbench", {
for _, d in pairs(workbench.defs) do for _, d in pairs(workbench.defs) do
for i=1, #nodes do for i=1, #nodes do
pcall(function()
local node = nodes[i] local node = nodes[i]
local def = registered_nodes[node] local def = registered_nodes[node]
@ -286,6 +287,7 @@ for i=1, #nodes do
on_place = minetest.rotate_node on_place = minetest.rotate_node
}) })
end end
end)
end end
end end