milan2018_v2 #25
|
@ -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/>.
|
|
||||||
----------------------------------------------------------------------
|
|
|
@ -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" }
|
|
||||||
-- },
|
|
||||||
-- })
|
|
|
@ -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"}
|
|
||||||
-- }
|
|
||||||
-- })
|
|
|
@ -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"},
|
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
|
@ -1,5 +0,0 @@
|
||||||
default
|
|
||||||
protector?
|
|
||||||
areas?
|
|
||||||
boneworld?
|
|
||||||
moreores?
|
|
|
@ -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"}
|
|
||||||
-- }
|
|
||||||
-- })
|
|
|
@ -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"}
|
|
||||||
}
|
|
||||||
})
|
|
|
@ -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.")
|
|
|
@ -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,
|
|
||||||
})
|
|
|
@ -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);
|
|
|
@ -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");
|
|
|
@ -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
|
|
||||||
)
|
|
|
@ -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"},
|
|
||||||
|
|
||||||
-- }
|
|
||||||
-- })
|
|
|
@ -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
|
|
Before Width: | Height: | Size: 242 B |
Before Width: | Height: | Size: 393 B |
Before Width: | Height: | Size: 398 B |
Before Width: | Height: | Size: 242 B |
Before Width: | Height: | Size: 274 B |
Before Width: | Height: | Size: 240 B |
Before Width: | Height: | Size: 239 B |
Before Width: | Height: | Size: 348 B |
Before Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 292 B |
Before Width: | Height: | Size: 119 B |
Before Width: | Height: | Size: 219 B |
Before Width: | Height: | Size: 239 B |
Before Width: | Height: | Size: 258 B |
Before Width: | Height: | Size: 253 B |
Before Width: | Height: | Size: 238 B |
Before Width: | Height: | Size: 302 B |
Before Width: | Height: | Size: 325 B |
Before Width: | Height: | Size: 315 B |
Before Width: | Height: | Size: 218 B |
Before Width: | Height: | Size: 214 B |
Before Width: | Height: | Size: 123 B |
Before Width: | Height: | Size: 123 B |
Before Width: | Height: | Size: 134 B |
Before Width: | Height: | Size: 316 B |
Before Width: | Height: | Size: 133 B |
Before Width: | Height: | Size: 133 B |
Before Width: | Height: | Size: 133 B |
Before Width: | Height: | Size: 234 B |
|
@ -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({
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
@ -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
|
3
teleport_potion/depends.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
default
|
||||||
|
intllib?
|
||||||
|
lucky_block?
|
1
teleport_potion/description.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Adds craftable teleport potions (throwable) and teleport pads.
|
503
teleport_potion/init.lua
Normal 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")
|
45
teleport_potion/intllib.lua
Normal 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
|
21
teleport_potion/license.txt
Normal 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.
|
59
teleport_potion/locale/de.po
Normal 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!"
|
55
teleport_potion/locale/fr.po
Normal 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 !"
|
54
teleport_potion/locale/template.pot
Normal 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
|
@ -0,0 +1 @@
|
||||||
|
name = teleport_potion
|
BIN
teleport_potion/screenshot.png
Normal file
After Width: | Height: | Size: 8.5 KiB |
BIN
teleport_potion/sounds/portal_close.ogg
Normal file
BIN
teleport_potion/sounds/portal_open.ogg
Normal file
BIN
teleport_potion/textures/pad.png
Normal file
After Width: | Height: | Size: 334 B |
BIN
teleport_potion/textures/padd.png
Normal file
After Width: | Height: | Size: 201 B |
BIN
teleport_potion/textures/particle.png
Normal file
After Width: | Height: | Size: 173 B |
BIN
teleport_potion/textures/portal.png
Normal file
After Width: | Height: | Size: 458 B |
BIN
teleport_potion/textures/potion.png
Normal file
After Width: | Height: | Size: 171 B |
|
@ -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)
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
||||||
|
|