use submodules

add mods
master
HybridDog 2014-05-28 23:19:13 +02:00
parent 45e8cd33e3
commit 755a61a2a3
117 changed files with 5 additions and 4314 deletions

1
mods/carts Submodule

@ -0,0 +1 @@
Subproject commit 10c455793d430e9177b9d5226a76f8525faef007

View File

@ -1,22 +0,0 @@
Minetest 0.4 mod: carts
=======================
by PilzAdam
License of source code:
-----------------------
WTFPL
License of media (textures, sounds and models):
-----------------------------------------------
CC-0
Authors of media files:
-----------------------
kddekadenz:
cart_bottom.png
cart_side.png
cart_top.png
Zeg9:
cart.x
cart.png

View File

@ -1 +0,0 @@
default

View File

@ -1,56 +0,0 @@
--
-- Helper functions
--
cart_func = {}
function cart_func:get_sign(z)
if z == 0 then
return 0
else
return z/math.abs(z)
end
end
-- Returns the velocity as a unit vector
-- The smaller part of the vector will be turned to 0
function cart_func:velocity_to_dir(v)
if math.abs(v.x) > math.abs(v.z) then
return {x=cart_func:get_sign(v.x), y=cart_func:get_sign(v.y), z=0}
else
return {x=0, y=cart_func:get_sign(v.y), z=cart_func:get_sign(v.z)}
end
end
function cart_func:is_rail(p)
local nn = minetest.env:get_node(p).name
return minetest.get_item_group(nn, "rail") ~= 0
end
function cart_func:is_int(z)
z = math.abs(z)
return math.abs(math.floor(z+0.5)-z) <= 0.1
end
cart_func.v3 = {}
function cart_func.v3:add(v1, v2)
return {x=v1.x+v2.x, y=v1.y+v2.y, z=v1.z+v2.z}
end
function cart_func.v3:copy(v)
return {x=v.x, y=v.y, z=v.z}
end
function cart_func.v3:round(v)
return {
x = math.floor(v.x+0.5),
y = math.floor(v.y+0.5),
z = math.floor(v.z+0.5),
}
end
function cart_func.v3:equal(v1, v2)
return v1.x == v2.x and v1.y == v2.y and v1.z == v2.z
end

View File

@ -1,475 +0,0 @@
dofile(minetest.get_modpath("carts").."/functions.lua")
--
-- Cart entity
--
local cart = {
physical = false,
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
visual = "mesh",
mesh = "cart.x",
visual_size = {x=1, y=1},
textures = {"cart.png"},
driver = nil,
velocity = {x=0, y=0, z=0},
old_pos = nil,
old_velocity = nil,
MAX_V = 15, -- Limit of the velocity
}
function cart:on_rightclick(clicker)
if not clicker or not clicker:is_player() then
return
end
if self.driver and clicker == self.driver then
self.driver = nil
clicker:set_detach()
elseif not self.driver then
self.driver = clicker
clicker:set_attach(self.object, "", {x=0,y=5,z=0}, {x=0,y=0,z=0})
end
end
function cart:on_activate(staticdata, dtime_s)
self.object:set_armor_groups({immortal=1})
if staticdata then
local tmp = minetest.deserialize(staticdata)
if tmp then
self.velocity = tmp.velocity
end
end
self.old_pos = self.object:getpos()
self.old_velocity = self.velocity
end
function cart:get_staticdata()
return minetest.serialize({
velocity = self.velocity,
})
end
-- Remove the cart if holding a tool or accelerate it
function cart:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
if not puncher or not puncher:is_player() then
return
end
if puncher:get_player_control().sneak then
self.object:remove()
puncher:get_inventory():add_item("main", "carts:cart")
return
end
if puncher == self.driver then
return
end
local d = cart_func:velocity_to_dir(direction)
local s = self.velocity
if time_from_last_punch > tool_capabilities.full_punch_interval then
time_from_last_punch = tool_capabilities.full_punch_interval
end
local f = 4*(time_from_last_punch/tool_capabilities.full_punch_interval)
local v = {x=s.x+d.x*f, y=s.y, z=s.z+d.z*f}
if math.abs(v.x) < 6 and math.abs(v.z) < 6 then
self.velocity = v
else
if math.abs(self.velocity.x) < 6 and math.abs(v.x) >= 6 then
self.velocity.x = 6*cart_func:get_sign(self.velocity.x)
end
if math.abs(self.velocity.z) < 6 and math.abs(v.z) >= 6 then
self.velocity.z = 6*cart_func:get_sign(self.velocity.z)
end
end
end
-- Returns the direction as a unit vector
function cart:get_rail_direction(pos, dir)
local d = cart_func.v3:copy(dir)
-- Check front
d.y = 0
local p = cart_func.v3:add(cart_func.v3:copy(pos), d)
if cart_func:is_rail(p) then
return d
end
-- Check downhill
d.y = -1
p = cart_func.v3:add(cart_func.v3:copy(pos), d)
if cart_func:is_rail(p) then
return d
end
-- Check uphill
d.y = 1
p = cart_func.v3:add(cart_func.v3:copy(pos), d)
if cart_func:is_rail(p) then
return d
end
d.y = 0
-- Check left and right
local view_dir
local other_dir
local a
if d.x == 0 and d.z ~= 0 then
view_dir = "z"
other_dir = "x"
if d.z < 0 then
a = {1, -1}
else
a = {-1, 1}
end
elseif d.z == 0 and d.x ~= 0 then
view_dir = "x"
other_dir = "z"
if d.x > 0 then
a = {1, -1}
else
a = {-1, 1}
end
else
return {x=0, y=0, z=0}
end
d[view_dir] = 0
d[other_dir] = a[1]
p = cart_func.v3:add(cart_func.v3:copy(pos), d)
if cart_func:is_rail(p) then
return d
end
d.y = -1
p = cart_func.v3:add(cart_func.v3:copy(pos), d)
if cart_func:is_rail(p) then
return d
end
d.y = 0
d[other_dir] = a[2]
p = cart_func.v3:add(cart_func.v3:copy(pos), d)
if cart_func:is_rail(p) then
return d
end
d.y = -1
p = cart_func.v3:add(cart_func.v3:copy(pos), d)
if cart_func:is_rail(p) then
return d
end
d.y = 0
return {x=0, y=0, z=0}
end
function cart:calc_rail_direction(pos, vel)
local velocity = cart_func.v3:copy(vel)
local p = cart_func.v3:copy(pos)
if cart_func:is_int(p.x) and cart_func:is_int(p.z) then
local dir = cart_func:velocity_to_dir(velocity)
local dir_old = cart_func.v3:copy(dir)
dir = self:get_rail_direction(cart_func.v3:round(p), dir)
local v = math.max(math.abs(velocity.x), math.abs(velocity.z))
velocity = {
x = v * dir.x,
y = v * dir.y,
z = v * dir.z,
}
if cart_func.v3:equal(velocity, {x=0, y=0, z=0}) then
-- First try this HACK
-- Move the cart on the rail if above or under it
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=1, z=0})) and vel.y >= 0 then
p = cart_func.v3:add(p, {x=0, y=1, z=0})
return self:calc_rail_direction(p, vel)
end
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=-1, z=0})) and vel.y <= 0 then
p = cart_func.v3:add(p, {x=0, y=-1, z=0})
return self:calc_rail_direction(p, vel)
end
-- Now the HACK gets really dirty
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=2, z=0})) and vel.y >= 0 then
p = cart_func.v3:add(p, {x=0, y=1, z=0})
return self:calc_rail_direction(p, vel)
end
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=-2, z=0})) and vel.y <= 0 then
p = cart_func.v3:add(p, {x=0, y=-1, z=0})
return self:calc_rail_direction(p, vel)
end
return {x=0, y=0, z=0}, p
end
if not cart_func.v3:equal(dir, dir_old) then
return velocity, cart_func.v3:round(p)
end
end
return velocity, p
end
function cart:on_step(dtime)
local pos = self.object:getpos()
local dir = cart_func:velocity_to_dir(self.velocity)
-- Stop the cart if the velocity is nearly 0
-- Only if on a flat railway
if dir.y == 0 then
if math.abs(self.velocity.x) < 0.1 and math.abs(self.velocity.z) < 0.1 then
self.velocity = {x=0, y=0, z=0}
self.object:setvelocity(self.velocity)
self.old_velocity = self.velocity
self.old_pos = self.object:getpos()
return
end
end
--
-- Set the new moving direction
--
-- Recalcualte the rails that are passed since the last server step
local old_dir = cart_func:velocity_to_dir(self.old_velocity)
if old_dir.x ~= 0 then
local sign = cart_func:get_sign(pos.x-self.old_pos.x)
while true do
if sign ~= cart_func:get_sign(pos.x-self.old_pos.x) or pos.x == self.old_pos.x then
break
end
self.old_pos.x = self.old_pos.x + cart_func:get_sign(pos.x-self.old_pos.x)*0.1
self.old_pos.y = self.old_pos.y + cart_func:get_sign(pos.x-self.old_pos.x)*0.1*old_dir.y
self.old_velocity, self.old_pos = self:calc_rail_direction(self.old_pos, self.old_velocity)
old_dir = cart_func:velocity_to_dir(self.old_velocity)
if not cart_func.v3:equal(cart_func:velocity_to_dir(self.old_velocity), dir) then
self.velocity = self.old_velocity
pos = self.old_pos
self.object:setpos(self.old_pos)
break
end
end
elseif old_dir.z ~= 0 then
local sign = cart_func:get_sign(pos.z-self.old_pos.z)
while true do
if sign ~= cart_func:get_sign(pos.z-self.old_pos.z) or pos.z == self.old_pos.z then
break
end
self.old_pos.z = self.old_pos.z + cart_func:get_sign(pos.z-self.old_pos.z)*0.1
self.old_pos.y = self.old_pos.y + cart_func:get_sign(pos.z-self.old_pos.z)*0.1*old_dir.y
self.old_velocity, self.old_pos = self:calc_rail_direction(self.old_pos, self.old_velocity)
old_dir = cart_func:velocity_to_dir(self.old_velocity)
if not cart_func.v3:equal(cart_func:velocity_to_dir(self.old_velocity), dir) then
self.velocity = self.old_velocity
pos = self.old_pos
self.object:setpos(self.old_pos)
break
end
end
end
-- Calculate the new step
self.velocity, pos = self:calc_rail_direction(pos, self.velocity)
self.object:setpos(pos)
dir = cart_func:velocity_to_dir(self.velocity)
-- Accelerate or decelerate the cart according to the pitch and acceleration of the rail node
local a = tonumber(minetest.env:get_meta(pos):get_string("cart_acceleration"))
if not a then
a = 0
end
if self.velocity.y < 0 then
self.velocity = {
x = self.velocity.x + (a+0.13)*cart_func:get_sign(self.velocity.x),
y = self.velocity.y + (a+0.13)*cart_func:get_sign(self.velocity.y),
z = self.velocity.z + (a+0.13)*cart_func:get_sign(self.velocity.z),
}
elseif self.velocity.y > 0 then
self.velocity = {
x = self.velocity.x + (a-0.1)*cart_func:get_sign(self.velocity.x),
y = self.velocity.y + (a-0.1)*cart_func:get_sign(self.velocity.y),
z = self.velocity.z + (a-0.1)*cart_func:get_sign(self.velocity.z),
}
else
self.velocity = {
x = self.velocity.x + (a-0.03)*cart_func:get_sign(self.velocity.x),
y = self.velocity.y + (a-0.03)*cart_func:get_sign(self.velocity.y),
z = self.velocity.z + (a-0.03)*cart_func:get_sign(self.velocity.z),
}
-- Place the cart exactly on top of the rail
if cart_func:is_rail(cart_func.v3:round(pos)) then
self.object:setpos({x=pos.x, y=math.floor(pos.y+0.5), z=pos.z})
pos = self.object:getpos()
end
end
-- Dont switch moving direction
-- Only if on flat railway
if dir.y == 0 then
if cart_func:get_sign(dir.x) ~= cart_func:get_sign(self.velocity.x) then
self.velocity.x = 0
end
if cart_func:get_sign(dir.y) ~= cart_func:get_sign(self.velocity.y) then
self.velocity.y = 0
end
if cart_func:get_sign(dir.z) ~= cart_func:get_sign(self.velocity.z) then
self.velocity.z = 0
end
end
-- Allow only one moving direction (multiply the other one with 0)
dir = cart_func:velocity_to_dir(self.velocity)
self.velocity = {
x = math.abs(self.velocity.x) * dir.x,
y = self.velocity.y,
z = math.abs(self.velocity.z) * dir.z,
}
-- Move cart exactly on the rail
if dir.x ~= 0 and not cart_func:is_int(pos.z) then
pos.z = math.floor(0.5+pos.z)
self.object:setpos(pos)
elseif dir.z ~= 0 and not cart_func:is_int(pos.x) then
pos.x = math.floor(0.5+pos.x)
self.object:setpos(pos)
end
-- Limit the velocity
if math.abs(self.velocity.x) > self.MAX_V then
self.velocity.x = self.MAX_V*cart_func:get_sign(self.velocity.x)
end
if math.abs(self.velocity.y) > self.MAX_V then
self.velocity.y = self.MAX_V*cart_func:get_sign(self.velocity.y)
end
if math.abs(self.velocity.z) > self.MAX_V then
self.velocity.z = self.MAX_V*cart_func:get_sign(self.velocity.z)
end
self.object:setvelocity(self.velocity)
self.old_pos = self.object:getpos()
self.old_velocity = cart_func.v3:copy(self.velocity)
if dir.x < 0 then
self.object:setyaw(math.pi/2)
elseif dir.x > 0 then
self.object:setyaw(3*math.pi/2)
elseif dir.z < 0 then
self.object:setyaw(math.pi)
elseif dir.z > 0 then
self.object:setyaw(0)
end
if dir.y == -1 then
self.object:set_animation({x=1, y=1}, 1, 0)
elseif dir.y == 1 then
self.object:set_animation({x=2, y=2}, 1, 0)
else
self.object:set_animation({x=0, y=0}, 1, 0)
end
end
minetest.register_entity("carts:cart", cart)
minetest.register_craftitem("carts:cart", {
description = "Minecart",
inventory_image = minetest.inventorycube("cart_top.png", "cart_side.png", "cart_side.png"),
wield_image = "cart_side.png",
on_place = function(itemstack, placer, pointed_thing)
if not pointed_thing.type == "node" then
return
end
if cart_func:is_rail(pointed_thing.under) then
minetest.env:add_entity(pointed_thing.under, "carts:cart")
itemstack:take_item()
return itemstack
elseif cart_func:is_rail(pointed_thing.above) then
minetest.env:add_entity(pointed_thing.above, "carts:cart")
itemstack:take_item()
return itemstack
end
end,
})
minetest.register_craft({
output = "carts:cart",
recipe = {
{"", "", ""},
{"default:steel_ingot", "", "default:steel_ingot"},
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
},
})
--
-- Mesecon support
--
minetest.register_node(":default:rail", {
description = "Rail",
drawtype = "raillike",
tiles = {"default_rail.png", "default_rail_curved.png", "default_rail_t_junction.png", "default_rail_crossing.png"},
inventory_image = "default_rail.png",
wield_image = "default_rail.png",
paramtype = "light",
is_ground_content = true,
walkable = false,
selection_box = {
type = "fixed",
-- but how to specify the dimensions for curved and sideways rails?
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
},
groups = {bendy=2,snappy=1,dig_immediate=2,attached_node=1,rail=1},
mesecons = {
effector = {
action_on = function(pos, node)
minetest.env:get_meta(pos):set_string("cart_acceleration", "0.5")
-- Start the cart
for _,obj in ipairs(minetest.env:get_objects_inside_radius(pos, 1)) do
if obj:get_luaentity() and obj:get_luaentity().name == "carts:cart" then
local self = obj:get_luaentity()
if cart_func.v3:equal(self.velocity, {x=0, y=0, z=0}) then
for _,y in ipairs({0,-1,1}) do
for _,z in ipairs({1,-1}) do
if cart_func.v3:equal(self:get_rail_direction(obj:getpos(), {x=0, y=y, z=z}), {x=0, y=y, z=z}) then
self.velocity = {
x = 0,
y = 0.2*y,
z = 0.2*z,
}
self.old_velocity = self.velocity
return
end
end
for _,x in ipairs({1,-1}) do
if cart_func.v3:equal(self:get_rail_direction(obj:getpos(), {x=x, y=y, z=0}), {x=x, y=y, z=0}) then
self.velocity = {
x = 0.2*x,
y = 0.2*y,
z = 0,
}
self.old_velocity = self.velocity
return
end
end
end
end
end
end
end,
action_off = function(pos, node)
minetest.env:get_meta(pos):set_string("cart_acceleration", "0")
end,
},
},
})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 422 B

View File

@ -1,339 +0,0 @@
xof 0303txt 0032
Frame Root {
FrameTransformMatrix {
1.000000, 0.000000, 0.000000, 0.000000,
0.000000, 0.000000, 1.000000, 0.000000,
0.000000, 1.000000,-0.000000, 0.000000,
0.000000, 0.000000, 0.000000, 1.000000;;
}
Frame Cube {
FrameTransformMatrix {
5.000000, 0.000000,-0.000000, 0.000000,
-0.000000, 3.535534, 3.535534, 0.000000,
0.000000,-3.535534, 3.535534, 0.000000,
0.000000,-3.000000, 3.000000, 1.000000;;
}
Mesh { //Cube_001 Mesh
72;
-1.000000; 1.000000;-1.000000;,
-1.000000;-1.000000;-1.000000;,
1.000000;-1.000000;-1.000000;,
1.000000; 1.000000;-1.000000;,
-0.833334;-1.000000; 1.000000;,
-1.000000;-1.000000; 1.000000;,
-1.000000;-0.833333; 1.000000;,
-0.833334;-0.833333; 1.000000;,
-1.000000;-1.000000;-1.000000;,
-1.000000;-1.000000; 1.000000;,
0.999999;-1.000001; 1.000000;,
1.000000;-1.000000;-1.000000;,
0.999999;-1.000001; 1.000000;,
0.833332;-1.000000; 1.000000;,
0.833333;-0.833334; 1.000000;,
1.000000;-0.833334; 1.000000;,
0.833332;-1.000000; 1.000000;,
-0.833334;-1.000000; 1.000000;,
-0.833334;-0.833333; 1.000000;,
0.833333;-0.833334; 1.000000;,
1.000000; 0.833333; 1.000000;,
0.833334; 0.833333; 1.000000;,
0.833334; 1.000000; 1.000000;,
1.000000; 0.999999; 1.000000;,
1.000000;-0.833334; 1.000000;,
0.833333;-0.833334; 1.000000;,
0.833334; 0.833333; 1.000000;,
1.000000; 0.833333; 1.000000;,
0.833334; 0.833333; 1.000000;,
-0.833333; 0.833333; 1.000000;,
-0.833333; 1.000000; 1.000000;,
0.833334; 1.000000; 1.000000;,
0.833334; 0.833333;-0.800000;,
-0.833333; 0.833333;-0.800000;,
-0.833333; 0.833333; 1.000000;,
0.833334; 0.833333; 1.000000;,
-0.833333; 0.833333; 1.000000;,
-1.000000; 0.833333; 1.000000;,
-1.000000; 1.000000; 1.000000;,
-0.833333; 1.000000; 1.000000;,
-0.833334;-0.833333; 1.000000;,
-1.000000;-0.833333; 1.000000;,
-1.000000; 0.833333; 1.000000;,
-0.833333; 0.833333; 1.000000;,
0.833333;-0.833334;-0.800000;,
-0.833334;-0.833333;-0.800000;,
-0.833333; 0.833333;-0.800000;,
0.833334; 0.833333;-0.800000;,
-0.833333; 0.833333;-0.800000;,
-0.833334;-0.833333;-0.800000;,
-0.833334;-0.833333; 1.000000;,
-0.833333; 0.833333; 1.000000;,
-0.833334;-0.833333;-0.800000;,
0.833333;-0.833334;-0.800000;,
0.833333;-0.833334; 1.000000;,
-0.833334;-0.833333; 1.000000;,
0.833333;-0.833334;-0.800000;,
0.833334; 0.833333;-0.800000;,
0.833334; 0.833333; 1.000000;,
0.833333;-0.833334; 1.000000;,
-1.000000; 1.000000;-1.000000;,
-1.000000; 1.000000; 1.000000;,
-1.000000;-1.000000; 1.000000;,
-1.000000;-1.000000;-1.000000;,
-1.000000; 1.000000; 1.000000;,
-1.000000; 1.000000;-1.000000;,
1.000000; 1.000000;-1.000000;,
1.000000; 0.999999; 1.000000;,
1.000000;-1.000000;-1.000000;,
0.999999;-1.000001; 1.000000;,
1.000000; 0.999999; 1.000000;,
1.000000; 1.000000;-1.000000;;
18;
4;0;1;2;3;,
4;4;5;6;7;,
4;8;9;10;11;,
4;12;13;14;15;,
4;16;17;18;19;,
4;20;21;22;23;,
4;24;25;26;27;,
4;28;29;30;31;,
4;32;33;34;35;,
4;36;37;38;39;,
4;40;41;42;43;,
4;44;45;46;47;,
4;48;49;50;51;,
4;52;53;54;55;,
4;56;57;58;59;,
4;60;61;62;63;,
4;64;65;66;67;,
4;68;69;70;71;;
MeshNormals { //Cube_001 Normals
72;
0.000000; 0.000000;-1.000000;,
0.000000; 0.000000;-1.000000;,
0.000000; 0.000000;-1.000000;,
0.000000; 0.000000;-1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
-0.000000;-1.000000;-0.000000;,
-0.000000;-1.000000;-0.000000;,
-0.000000;-1.000000;-0.000000;,
-0.000000;-1.000000;-0.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
-0.000000;-1.000000; 0.000000;,
-0.000000;-1.000000; 0.000000;,
-0.000000;-1.000000; 0.000000;,
-0.000000;-1.000000; 0.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
0.000000;-0.000000; 1.000000;,
1.000000;-0.000000; 0.000000;,
1.000000;-0.000000; 0.000000;,
1.000000;-0.000000; 0.000000;,
1.000000;-0.000000; 0.000000;,
0.000000; 1.000000; 0.000000;,
0.000000; 1.000000; 0.000000;,
0.000000; 1.000000; 0.000000;,
0.000000; 1.000000; 0.000000;,
-1.000000; 0.000000; 0.000000;,
-1.000000; 0.000000; 0.000000;,
-1.000000; 0.000000; 0.000000;,
-1.000000; 0.000000; 0.000000;,
-1.000000; 0.000000;-0.000000;,
-1.000000; 0.000000;-0.000000;,
-1.000000; 0.000000;-0.000000;,
-1.000000; 0.000000;-0.000000;,
0.000000; 1.000000; 0.000000;,
0.000000; 1.000000; 0.000000;,
0.000000; 1.000000; 0.000000;,
0.000000; 1.000000; 0.000000;,
1.000000;-0.000000; 0.000000;,
1.000000;-0.000000; 0.000000;,
1.000000;-0.000000; 0.000000;,
1.000000;-0.000000; 0.000000;;
18;
4;0;1;2;3;,
4;4;5;6;7;,
4;8;9;10;11;,
4;12;13;14;15;,
4;16;17;18;19;,
4;20;21;22;23;,
4;24;25;26;27;,
4;28;29;30;31;,
4;32;33;34;35;,
4;36;37;38;39;,
4;40;41;42;43;,
4;44;45;46;47;,
4;48;49;50;51;,
4;52;53;54;55;,
4;56;57;58;59;,
4;60;61;62;63;,
4;64;65;66;67;,
4;68;69;70;71;;
} //End of Cube_001 Normals
MeshMaterialList { //Cube_001 Material List
1;
18;
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0;;
Material Material {
0.640000; 0.640000; 0.640000; 1.000000;;
96.078431;
0.500000; 0.500000; 0.500000;;
0.000000; 0.000000; 0.000000;;
TextureFilename {"cart.png";}
}
} //End of Cube_001 Material List
MeshTextureCoords { //Cube_001 UV Coordinates
72;
0.000000; 0.500000;,
0.500000; 0.500000;,
0.500000; 1.000000;,
0.000000; 1.000000;,
0.031250; 0.500000;,
-0.000000; 0.500000;,
-0.000000; 0.468750;,
0.031250; 0.468750;,
0.500000; 0.500000;,
0.500000; 0.000000;,
1.000000; 0.000000;,
1.000000; 0.500000;,
0.468750; 0.468750;,
0.500000; 0.468750;,
0.500000; 0.500000;,
0.468750; 0.500000;,
0.031250; 0.468750;,
0.468750; 0.468750;,
0.468750; 0.500000;,
0.031250; 0.500000;,
0.468750; 0.000000;,
0.500000; 0.000000;,
0.500000; 0.031250;,
0.468750; 0.031250;,
0.468750; 0.031250;,
0.500000; 0.031250;,
0.500000; 0.468750;,
0.468750; 0.468750;,
0.468750; 0.031250;,
0.031250; 0.031250;,
0.031250; 0.000000;,
0.468750; 0.000000;,
1.000000; 0.500000;,
0.500000; 0.500000;,
0.500000; 0.000000;,
1.000000; 0.000000;,
0.031250; 0.031250;,
0.000000; 0.031250;,
0.000000; 0.000000;,
0.031250; 0.000000;,
0.031250; 0.468750;,
-0.000000; 0.468750;,
0.000000; 0.031250;,
0.031250; 0.031250;,
0.000000; 0.500000;,
0.500000; 0.500000;,
0.500000; 1.000000;,
0.000000; 1.000000;,
1.000000; 0.500000;,
0.500000; 0.500000;,
0.500000; 0.000000;,
1.000000; 0.000000;,
1.000000; 0.500000;,
0.500000; 0.500000;,
0.500000; 0.000000;,
1.000000; 0.000000;,
1.000000; 0.500000;,
0.500000; 0.500000;,
0.500000; 0.000000;,
1.000000; 0.000000;,
0.500000; 0.500000;,
0.500000; 0.000000;,
1.000000; 0.000000;,
1.000000; 0.500000;,
1.000000; 0.000000;,
1.000000; 0.500000;,
0.500000; 0.500000;,
0.500000; 0.000000;,
0.500000; 0.500000;,
0.500000; 0.000000;,
1.000000; 0.000000;,
1.000000; 0.500000;;
} //End of Cube_001 UV Coordinates
} //End of Cube_001 Mesh
} //End of Cube
} //End of Root Frame
AnimationSet {
Animation {
{Cube}
AnimationKey { //Position
2;
4;
0;3; 0.000000, 0.000000, 0.000000;;,
1;3; 0.000000, 3.000000, 3.000000;;,
2;3; 0.000000,-3.000000, 3.000000;;,
3;3; 0.000000,-3.000000, 3.000000;;;
}
AnimationKey { //Rotation
0;
4;
0;4; -1.000000, 0.000000, 0.000000, 0.000000;;,
1;4; -0.923880,-0.382683,-0.000000, 0.000000;;,
2;4; -0.923880, 0.382683, 0.000000, 0.000000;;,
3;4; -0.923880, 0.382683, 0.000000, 0.000000;;;
}
AnimationKey { //Scale
1;
4;
0;3; 5.000000, 5.000000, 5.000000;;,
1;3; 5.000000, 5.000000, 5.000000;;,
2;3; 5.000000, 5.000000, 5.000000;;,
3;3; 5.000000, 5.000000, 5.000000;;;
}
}
} //End of AnimationSet

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 524 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 533 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 548 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 584 B

1
mods/conifers Submodule

@ -0,0 +1 @@
Subproject commit 40a7bb9aaa7b1c97ebb15081bc8fb20aea2a1d34

View File

@ -1,16 +0,0 @@
--------------------------------------------------------------------------------
--
-- CONIFERS MOD
-- For Minetest
-- Created by Cisoun (cysoun[at]gmail.com).
--
-- This mod adds some conifers randomly at a certain altitude.
-- There are two types of conifers: regular and narrow.
-- You can define the altitude at which they spawn and their structure and
-- choose if you want to keep normal trees above this altitude.
--
--------------------------------------------------------------------------------
TODO:
— add a TODO list

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

View File

@ -1 +0,0 @@
default

View File

@ -1,524 +0,0 @@
--------------------------------------------------------------------------------
--
-- CONIFERS MOD 0.3
-- For Minetest-c55
-- Created by Cisoun (cysoun[at]gmail.com).
--
-- This mod adds some conifers randomly at a certain altitude.
-- There are two types of conifers: regular and narrow.
-- You can define the altitude at which they spawn and their structure and
-- choose if you want to keep normal trees above this altitude.
--
--------------------------------------------------------------------------------
-- Structure definitions.
local TRUNK_MINHEIGHT = 7
local TRUNK_MAXHEIGHT = 25
local LEAVES_MINHEIGHT = 2
local LEAVES_MAXHEIGHT = 6
local LEAVES_MAXRADIUS = 5
local LEAVES_NARROWRADIUS = 3 -- For narrow typed conifers.
local CONIFERS_DISTANCE = 4
local CONIFERS_ALTITUDE = 30
local REMOVE_TREES = false -- Remove trees above CONIFERS_ALTITUDE?
local SAPLING_CHANCE = 100 -- 1/x chances to grow a sapling.
local INTERVAL = 1800
-- End of structure definitions.
conifers = {}
--------------------------------------------------------------------------------
--
-- Definitions
--
--------------------------------------------------------------------------------
--
-- Node definitions
--
minetest.register_node("conifers:trunk", {
description = "Conifer trunk",
tile_images = {
"conifers_trunktop.png",
"conifers_trunktop.png",
"conifers_trunk.png",
"conifers_trunk.png",
"conifers_trunk.png",
"conifers_trunk.png"
},
--inventory_image = minetest.inventorycube(
--"conifers_trunktop.png",
--"conifers_trunk.png",
--"conifers_trunk.png"
--),
paramtype = "facedir_simple",
material = minetest.digprop_woodlike(1.0),
is_ground_content = true,
groups = {
tree = 1,
snappy = 2,
choppy = 2,
oddly_breakable_by_hand = 1,
flammable = 2
},
sounds = default.node_sound_wood_defaults()
})
minetest.register_node("conifers:trunk_reversed", {
description = "Conifer reversed trunk",
tile_images = {
"conifers_trunk_reversed.png",
"conifers_trunk_reversed.png",
"conifers_trunktop.png",
"conifers_trunktop.png",
"conifers_trunk_reversed.png",
"conifers_trunk_reversed.png"
},
--inventory_image = minetest.inventorycube(
--"conifers_trunk.png",
--"conifers_trunktop.png",
--"conifers_trunk.png"
--),
paramtype = "facedir_simple",
material = minetest.digprop_woodlike(1.0),
legacy_facedir_simple = true,
is_ground_content = true,
groups = {
tree = 1,
snappy = 2,
choppy = 2,
oddly_breakable_by_hand = 1,
flammable = 2
},
sounds = default.node_sound_wood_defaults()
})
minetest.register_node("conifers:leaves", {
description = "Conifer leaves",
drawtype = "allfaces_optional",
visual_scale = 1.3,
tile_images = { "conifers_leaves.png" },
--inventory_image = "conifers_leaves.png",
paramtype = "light",
groups = {
snappy = 3,
leafdecay = 3,
flammable = 2
},
drop = {
max_items = 1,
items = {
{
-- player will get sapling with 1/20 chance
items = {'conifers:sapling'},
rarity = 20,
},
{
-- player will get leaves only if he get no saplings,
-- this is because max_items is 1
items = {'conifers:leaves'},
}
}
},
sounds = default.node_sound_leaves_defaults()
})
minetest.register_node("conifers:leaves_special", {
description = "Bright conifer leaves",
drawtype = "allfaces_optional",
visual_scale = 1.3,
tile_images = { "conifers_leaves_special.png" },
--inventory_image = "conifers_leaves_special.png",
paramtype = "light",
groups = {
snappy = 3,
leafdecay = 3,
flammable = 2
},
drop = {
max_items = 1,
items = {
{
-- player will get sapling with 1/20 chance
items = {'conifers:sapling'},
rarity = 20,
},
{
-- player will get leaves only if he get no saplings,
-- this is because max_items is 1
items = {'conifers:leaves'},
}
}
},
sounds = default.node_sound_leaves_defaults()
})
minetest.register_node("conifers:sapling", {
description = "Conifer sapling",
drawtype = "plantlike",
visual_scale = 1.0,
tile_images = {"conifers_sapling.png"},
inventory_image = "conifers_sapling.png",
wield_image = "conifers_sapling.png",
paramtype = "light",
walkable = false,
groups = {
snappy = 2,
dig_immediate = 3,
flammable = 2
},
sounds = default.node_sound_defaults(),
})
--
-- Craft definitions
--
minetest.register_craft({
output = 'node "conifers:trunk_reversed" 2',
recipe = {
{'node "conifers:trunk"', 'node "conifers:trunk"'},
}
})
minetest.register_craft({
output = 'node "conifers:trunk" 2',
recipe = {
{'node "conifers:trunk_reversed"'},
{'node "conifers:trunk_reversed"'}
}
})
minetest.register_craft({
output = 'default:wood 4',
recipe = {
{'conifers:trunk'}
}
})
minetest.register_craft({
output = 'default:wood 4',
recipe = {
{'conifers:trunk_reversed'}
}
})
--
-- ABM definitions
--
-- Spawn random conifers.
minetest.register_abm({
nodenames = "default:dirt_with_grass",
interval = INTERVAL,
chance = 1,
action = function(pos, node, _, _)
if minetest.env:get_node({x = pos.x, y = pos.y + 1, z = pos.z}).name == "air"
and pos.y >= CONIFERS_ALTITUDE
and conifers:is_node_in_cube({"conifers:trunk"}, pos, CONIFERS_DISTANCE) == false
then
if math.random(0,1000) == 5 then
conifers:make_conifer({x = pos.x, y = pos.y + 1, z = pos.z}, math.random(0, 1))
end
end
end
})
-- Saplings.
minetest.register_abm({
nodenames = "conifers:sapling",
interval = INTERVAL,
chance = SAPLING_CHANCE,
action = function(pos, node, _, _)
if minetest.env:get_node({x = pos.x, y = pos.y + 1, z = pos.z}).name == "air" then
conifers:make_conifer({x = pos.x, y = pos.y, z = pos.z}, math.random(0, 1))
end
end
})
-- Should we remove all the trees above the conifers altitude?
if REMOVE_TREES == true then
minetest.register_abm({
nodenames = {
"default:tree",
"default:leaves"
},
interval = INTERVAL/100,
chance = 1,
action = function(pos, node, _, _)
if minetest.env:get_node({x = pos.x, y = pos.y + 1, z = pos.z}).name == "air"
and pos.y >= CONIFERS_ALTITUDE
then
minetest.env:add_node(pos , {name = "air"})
end
end
})
end
--------------------------------------------------------------------------------
--
-- Functions
--
--------------------------------------------------------------------------------
--
-- table_contains(t, v)
--
-- Taken from the Flowers mod by erlehmann.
--
function conifers:table_contains(t, v)
for _, i in ipairs(t) do
if (i == v) then
return true
end
end
return false
end
--
-- is_node_in_cube(nodenames, node_pos, radius)
--
-- Taken from the Flowers mod by erlehmann.
--
function conifers:is_node_in_cube(nodenames, node_pos, radius)
for x = node_pos.x - radius, node_pos.x + radius do
for y = node_pos.y - math.floor(radius / 2), node_pos.y + math.floor(radius / 2) do
for z = node_pos.z - radius, node_pos.z + radius do
n = minetest.env:get_node_or_nil({x = x, y = y, z = z})
if (n == nil)
or (n.name == 'ignore')
or (conifers:table_contains(nodenames, n.name) == true) then
return true
end
end
end
end
return false
end
--
-- are_leaves_surrounded(position)
--
-- Return a boolean value set to 'true' if a leaves block is surrounded
-- by something else than
-- - air
-- - leaves
-- - special leaves
--
-- If a leaves block is surrounded by the blocks above,
-- it can be placed.
-- Otherwise, it will replace blocks we want to keep.
--
function conifers:are_leaves_surrounded(pos)
--
-- Check if a leaves block does not interfer with something else than the air or another leaves block.
--
local node1 = minetest.env:get_node({x = pos.x + 1, y = pos.y, z = pos.z}).name
local node2 = minetest.env:get_node({x = pos.x - 1, y = pos.y, z = pos.z}).name
local node3 = minetest.env:get_node({x = pos.x, y = pos.y, z = pos.z + 1}).name
local node4 = minetest.env:get_node({x = pos.x, y = pos.y, z = pos.z - 1}).name
local replacable_nodes = {
"air",
"conifers:leaves",
"conifers:leaves_special"
}
-- Let's check if the neighboring node is a replacable node.
if (conifers:table_contains(replacable_nodes, node1) == true)
and (conifers:table_contains(replacable_nodes, node2) == true)
and (conifers:table_contains(replacable_nodes, node3) == true)
and (conifers:table_contains(replacable_nodes, node4) == true)
then
return false
else
return true
end
end
--
-- add_leaves_block(position, type of leaves, near trunk?)
--
-- Put a simple leaves block.
-- Leaves must be positioned near a trunk or surrounded by air.
-- Types of leaves are:
-- 0: dark leaves
-- 1: bright leaves (special)
--
function conifers:add_leaves_block(pos, special, near_trunk)
if conifers:are_leaves_surrounded(pos) == false or near_trunk == true then
if special == 0 then
minetest.env:add_node(pos , { name = "conifers:leaves" })
else
minetest.env:add_node(pos , { name = "conifers:leaves_special" })
end
end
end
--
-- make_leaves(middle point, min radius, max radius, type of leaves)
--
-- Make a circle of leaves with a center given by 'middle point'.
-- Types of leaves are:
-- 0: dark leaves
-- 1: bright leaves (special)
--
function conifers:make_leaves(c, radius_min, radius_max, special)
--
-- Using the midpoint circle algorithm from Bresenham we can trace a circle of leaves.
--
for r = radius_min, radius_max do
local m_x = 0
local m_z = r
local m_m = 5 - 4 * r
while m_x <= m_z do
if radius_max > 1 then
if r == 1 then
-- Add a square of leaves (fixing holes near the trunk).
-- [ ] [ ]
-- [#]
-- [ ] [ ]
conifers:add_leaves_block({x = -1 + c.x, y = c.y, z = 1 + c.z}, special)
conifers:add_leaves_block({x = 1 + c.x, y = c.y, z = 1 + c.z}, special)
conifers:add_leaves_block({x = -1 + c.x, y = c.y, z = -1 + c.z}, special)
conifers:add_leaves_block({x = 1 + c.x, y = c.y, z = -1 + c.z}, special)
-- [ ]
-- [ ][#][ ]
-- [ ]
conifers:add_leaves_block({x = c.x, y = c.y, z = -1 + c.z}, special, true)
conifers:add_leaves_block({x = c.x, y = c.y, z = 1 + c.z}, special, true)
conifers:add_leaves_block({x = -1 + c.x, y = c.y, z = c.z}, special, true)
conifers:add_leaves_block({x = 1 + c.x, y = c.y, z = c.z}, special, true)
else
conifers:add_leaves_block({x = m_x + c.x, y = c.y, z = m_z + c.z}, special)
conifers:add_leaves_block({x = m_z + c.x, y = c.y, z = m_x + c.z}, special)
conifers:add_leaves_block({x = -m_x + c.x, y = c.y, z = m_z + c.z}, special)
conifers:add_leaves_block({x = -m_z + c.x, y = c.y, z = m_x + c.z}, special)
conifers:add_leaves_block({x = m_x + c.x, y = c.y, z = -m_z + c.z}, special)
conifers:add_leaves_block({x = m_z + c.x, y = c.y, z = -m_x + c.z}, special)
conifers:add_leaves_block({x = -m_x + c.x, y = c.y, z = -m_z + c.z}, special)
conifers:add_leaves_block({x = -m_z + c.x, y = c.y, z = -m_x + c.z}, special)
end
else
-- Put a small circle of leaves around the trunk.
-- [ ]
-- [ ][#][ ]
-- [ ]
conifers:add_leaves_block({x = c.x, y = c.y, z = -1 + c.z}, special, true)
conifers:add_leaves_block({x = c.x, y = c.y, z = 1 + c.z}, special, true)
conifers:add_leaves_block({x = -1 + c.x, y = c.y, z = c.z}, special, true)
conifers:add_leaves_block({x = 1 + c.x, y = c.y, z = c.z}, special, true)
end
-- Stuff...
if m_m > 0 then
m_z = m_z - 1
m_m = m_m - 8 * m_z
end
m_x = m_x + 1
m_m = m_m + 8 * m_x + 4
end
end
end
--
-- make_conifer(position, type)
--
-- Make a conifer at a given position.
-- Types are:
-- 0: regular pine
-- 1: narrow pine
--
function conifers:make_conifer(pos, conifer_type)
-- Check if we can gros a conifer at this place.
if minetest.env:get_node({x = pos.x, y = pos.y - 1, z = pos.z}).name ~= "default:dirt_with_grass"
and (minetest.env:get_node({x = pos.x, y = pos.y, z = pos.z}).name ~= "air"
or minetest.env:get_node({x = pos.x, y = pos.y, z = pos.z}).name ~= "conifers:sapling"
)
then
return false
--else
--if minetest.env:get_node({x = pos.x, y = pos.y, z = pos.z}).name == "conifers:sapling" then
--minetest.env:add_node(pos , {name = "air"})
--end
end
local height = math.random(TRUNK_MINHEIGHT, TRUNK_MAXHEIGHT) -- Random height of the conifer.
local leaves_height = math.random(LEAVES_MINHEIGHT, LEAVES_MAXHEIGHT) -- Level from where the leaves grow.
local current_block = {} -- Duh...
local leaves_radius = 1
local leaves_max_radius = 2
local special = math.random(0, 1)
-- Let's check if we can grow a tree here.
-- That means, we must have a column of 'height' high which contains
-- only air.
for j = 1, height - 1 do -- Start from 1 so we can grow a sapling.
if minetest.env:get_node({x = pos.x, y = pos.y + j, z = pos.z}).name ~= "air" then
-- Abort
return false
end
end
-- Create the trunk and add the leaves.
for i = 0, height - 1 do
current_block = {
x = pos.x,
y = pos.y + i,
z = pos.z
}
-- Put a trunk block.
minetest.env:add_node(current_block , {name = "conifers:trunk"})
-- Put some leaves.
if i >= leaves_height then
-- Put some leaves.
conifers:make_leaves({x = pos.x, y = pos.y + leaves_height + (height - 1) - i, z = pos.z}, 1, leaves_radius, special)
--
-- TYPE OF CONIFER
--
if conifer_type == 1 then -- Regular type
-- Prepare the next circle of leaves.
leaves_radius = leaves_radius + 1
-- Check if the current radius is the maximum radius at this level.
if leaves_radius > leaves_max_radius then
leaves_radius = 1
leaves_max_radius = leaves_max_radius + 1
-- Does it exceeds the maximum radius?
if leaves_max_radius > LEAVES_MAXRADIUS then
leaves_max_radius = LEAVES_MAXRADIUS
end
end
else -- Narrow type
if i % 2 == 0 then
leaves_radius = LEAVES_NARROWRADIUS - math.random(0, 1)
else
leaves_radius = math.floor(LEAVES_NARROWRADIUS / 2)
end
end
end
end
-- Put a top leaves block.
current_block.y = current_block.y + 1
conifers:add_leaves_block(current_block, special)
-- Blahblahblah
print ('[conifers] A conifer has grown at (' .. pos.x .. ',' .. pos.y .. ',' .. pos.z .. ') with a height of ' .. (height))
return true
end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

View File

@ -1,510 +0,0 @@
--------------------------------------------------------------------------------
--
-- CONIFERS MOD
-- For Minetest
-- Created by Cisoun (cysoun[at]gmail.com).
--
-- This mod adds some conifers randomly at a certain altitude.
-- There are two types of conifers: regular and narrow.
-- You can define the altitude at which they spawn and their structure and
-- choose if you want to keep normal trees above this altitude.
--
--------------------------------------------------------------------------------
-- Structure definitions.
local TRUNK_MINHEIGHT = 7
local TRUNK_MAXHEIGHT = 25
local LEAVES_MINHEIGHT = 2
local LEAVES_MAXHEIGHT = 6
local LEAVES_MAXRADIUS = 5
local LEAVES_NARROWRADIUS = 3 -- For narrow typed conifers.
local CONIFERS_DISTANCE = 4
local CONIFERS_ALTITUDE = 30
local REMOVE_TREES = false -- Remove trees above CONIFERS_ALTITUDE?
local SAPLING_CHANCE = 100 -- 1/x chances to grow a sapling.
local INTERVAL = 3600
-- End of structure definitions.
conifers = {}
--------------------------------------------------------------------------------
--
-- Definitions
--
--------------------------------------------------------------------------------
--
-- Node definitions
--
minetest.register_node("conifers:trunk", {
description = "Conifer trunk",
tile_images = {
"conifers_trunktop.png",
"conifers_trunktop.png",
"conifers_trunk.png",
},
--inventory_image = minetest.inventorycube(
--"conifers_trunktop.png",
--"conifers_trunk.png",
--"conifers_trunk.png"
--),
paramtype = "facedir_simple",
material = minetest.digprop_woodlike(1.0),
groups = {
tree = 1,
snappy = 2,
choppy = 2,
oddly_breakable_by_hand = 1,
flammable = 2
},
sounds = default.node_sound_wood_defaults()
})
local tex_reversed_trunk = "conifers_trunk.png^[transformR90"
minetest.register_node("conifers:trunk_reversed", {
description = "Conifer reversed trunk",
tile_images = {
tex_reversed_trunk,
tex_reversed_trunk,
"conifers_trunktop.png",
"conifers_trunktop.png",
tex_reversed_trunk,
},
--inventory_image = minetest.inventorycube(
--"conifers_trunk.png",
--"conifers_trunktop.png",
--"conifers_trunk.png"
--),
paramtype = "facedir_simple",
material = minetest.digprop_woodlike(1.0),
legacy_facedir_simple = true,
groups = {
tree = 1,
snappy = 2,
choppy = 2,
oddly_breakable_by_hand = 1,
flammable = 2
},
sounds = default.node_sound_wood_defaults()
})
minetest.register_node("conifers:leaves", {
description = "Conifer leaves",
drawtype = "allfaces_optional",
visual_scale = 1.3,
tile_images = { "conifers_leaves.png" },
--inventory_image = "conifers_leaves.png",
paramtype = "light",
groups = {
snappy = 3,
--leafdecay = 3,
flammable = 2
},
drop = {
max_items = 1,
items = {
{
-- player will get sapling with 1/20 chance
items = {'conifers:sapling'},
rarity = 20,
},
{
-- player will get leaves only if he get no saplings,
-- this is because max_items is 1
items = {'conifers:leaves'},
}
}
},
sounds = default.node_sound_leaves_defaults()
})
minetest.register_node("conifers:leaves_special", {
description = "Bright conifer leaves",
drawtype = "allfaces_optional",
visual_scale = 1.3,
tile_images = { "conifers_leaves_special.png" },
--inventory_image = "conifers_leaves_special.png",
paramtype = "light",
groups = {
snappy = 3,
--leafdecay = 3,
flammable = 2
},
drop = {
max_items = 1,
items = {
{
-- player will get sapling with 1/20 chance
items = {'conifers:sapling'},
rarity = 20,
},
{
-- player will get leaves only if he get no saplings,
-- this is because max_items is 1
items = {'conifers:leaves'},
}
}
},
sounds = default.node_sound_leaves_defaults()
})
minetest.register_node("conifers:sapling", {
description = "Conifer sapling",
drawtype = "plantlike",
tile_images = {"conifers_sapling.png"},
inventory_image = "conifers_sapling.png",
wield_image = "conifers_sapling.png",
paramtype = "light",
walkable = false,
groups = {
snappy = 2,
dig_immediate = 3,
flammable = 2
},
sounds = default.node_sound_defaults(),
})
--
-- Craft definitions
--
minetest.register_craft({
output = "conifers:trunk_reversed 2",
recipe = {
{"conifers:trunk", "conifers:trunk"},
}
})
minetest.register_craft({
output = "conifers:trunk 2",
recipe = {
{"conifers:trunk_reversed"},
{"conifers:trunk_reversed"}
}
})
minetest.register_craft({
output = 'default:wood 4',
recipe = {
{'conifers:trunk'}
}
})
minetest.register_craft({
output = 'default:wood 4',
recipe = {
{'conifers:trunk_reversed'}
}
})
--
-- ABM definitions
--
-- Spawn random conifers.
minetest.register_abm({
nodenames = "default:dirt_with_grass",
interval = INTERVAL,
chance = 200.2,
action = function(pos, node)
local p = {x=pos.x, y=pos.y+1, z=pos.z}
if minetest.get_node(p).name == "air"
and pos.y >= CONIFERS_ALTITUDE
and (not conifers:is_node_in_cube({"conifers:trunk"}, pos, CONIFERS_DISTANCE)) then
conifers:make_conifer(p, math.random(0, 1))
end
end
})
-- Saplings.
minetest.register_abm({
nodenames = "conifers:sapling",
interval = INTERVAL,
chance = SAPLING_CHANCE,
action = function(pos, node)
if minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z}).name == "air" then
conifers:make_conifer(pos, math.random(0, 1))
end
end
})
-- Should we remove all the trees above the conifers altitude?
if REMOVE_TREES == true then
minetest.register_abm({
nodenames = {
"default:tree",
"default:leaves"
},
interval = INTERVAL/100,
chance = 1,
action = function(pos, node)
if minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z}).name == "air"
and pos.y >= CONIFERS_ALTITUDE then
minetest.add_node(pos , {name = "air"})
end
end
})
end
--------------------------------------------------------------------------------
--
-- Functions
--
--------------------------------------------------------------------------------
--
-- table_contains(t, v)
--
-- Taken from the Flowers mod by erlehmann.
--
function conifers:table_contains(t, v)
for _,i in ipairs(t) do
if i == v then
return true
end
end
return false
end
--
-- is_node_in_cube(nodenames, node_pos, radius)
--
-- Taken from the Flowers mod by erlehmann.
--
function conifers:is_node_in_cube(nodenames, pos, size)
local hs = math.floor(size / 2)
for x = pos.x-size, pos.x+size do
for y = pos.y-hs, pos.y+hs do
for z = pos.z-size, pos.z+size do
n = minetest.get_node_or_nil({x=x, y=y, z=z})
if n == nil
or n.name == 'ignore'
or conifers:table_contains(nodenames, n.name) then
return true
end
end
end
end
return false
end
--
-- are_leaves_surrounded(position)
--
-- Return a boolean value set to 'true' if a leaves block is surrounded
-- by something else than
-- - air
-- - leaves
-- - special leaves
--
-- If a leaves block is surrounded by the blocks above,
-- it can be placed.
-- Otherwise, it will replace blocks we want to keep.
--
function conifers:are_leaves_surrounded(pos)
--
-- Check if a leaves block does not interfer with something else than the air or another leaves block.
--
local replacable_nodes = {
"air",
"conifers:leaves",
"conifers:leaves_special"
}
-- Let's check if the neighboring node is a replacable node.
for i = -1,1,2 do
if not (conifers:table_contains(replacable_nodes, minetest.get_node({x=pos.x+i, y=pos.y, z=pos.z}).name)
or conifers:table_contains(replacable_nodes, minetest.get_node({x=pos.x, y=pos.y, z=pos.z+i}).name)
) then
return true
end
end
return false
end
--
-- add_leaves_block(position, type of leaves, near trunk?)
--
-- Put a simple leaves block.
-- Leaves must be positioned near a trunk or surrounded by air.
-- Types of leaves are:
-- 0: dark leaves
-- 1: bright leaves (special)
--
function conifers:add_leaves_block(pos, special, near_trunk)
if (not conifers:are_leaves_surrounded(pos))
or near_trunk then
if special == 0 then
minetest.add_node(pos , { name = "conifers:leaves" })
else
minetest.add_node(pos , { name = "conifers:leaves_special" })
end
end
end
--
-- make_leaves(middle point, min radius, max radius, type of leaves)
--
-- Make a circle of leaves with a center given by 'middle point'.
-- Types of leaves are:
-- 0: dark leaves
-- 1: bright leaves (special)
--
function conifers:make_leaves(c, radius_min, radius_max, special)
--
-- Using the midpoint circle algorithm from Bresenham we can trace a circle of leaves.
--
for r = radius_min, radius_max do
local m_x = 0
local m_z = r
local m_m = 5 - 4 * r
while m_x <= m_z do
if radius_max > 1 then
if r == 1 then
-- Add a square of leaves (fixing holes near the trunk).
-- [ ] [ ]
-- [#]
-- [ ] [ ]
conifers:add_leaves_block({x = -1 + c.x, y = c.y, z = 1 + c.z}, special)
conifers:add_leaves_block({x = 1 + c.x, y = c.y, z = 1 + c.z}, special)
conifers:add_leaves_block({x = -1 + c.x, y = c.y, z = -1 + c.z}, special)
conifers:add_leaves_block({x = 1 + c.x, y = c.y, z = -1 + c.z}, special)
-- [ ]
-- [ ][#][ ]
-- [ ]
conifers:add_leaves_block({x = c.x, y = c.y, z = -1 + c.z}, special, true)
conifers:add_leaves_block({x = c.x, y = c.y, z = 1 + c.z}, special, true)
conifers:add_leaves_block({x = -1 + c.x, y = c.y, z = c.z}, special, true)
conifers:add_leaves_block({x = 1 + c.x, y = c.y, z = c.z}, special, true)
else
conifers:add_leaves_block({x = m_x + c.x, y = c.y, z = m_z + c.z}, special)
conifers:add_leaves_block({x = m_z + c.x, y = c.y, z = m_x + c.z}, special)
conifers:add_leaves_block({x = -m_x + c.x, y = c.y, z = m_z + c.z}, special)
conifers:add_leaves_block({x = -m_z + c.x, y = c.y, z = m_x + c.z}, special)
conifers:add_leaves_block({x = m_x + c.x, y = c.y, z = -m_z + c.z}, special)
conifers:add_leaves_block({x = m_z + c.x, y = c.y, z = -m_x + c.z}, special)
conifers:add_leaves_block({x = -m_x + c.x, y = c.y, z = -m_z + c.z}, special)
conifers:add_leaves_block({x = -m_z + c.x, y = c.y, z = -m_x + c.z}, special)
end
else
-- Put a small circle of leaves around the trunk.
-- [ ]
-- [ ][#][ ]
-- [ ]
conifers:add_leaves_block({x = c.x, y = c.y, z = -1 + c.z}, special, true)
conifers:add_leaves_block({x = c.x, y = c.y, z = 1 + c.z}, special, true)
conifers:add_leaves_block({x = -1 + c.x, y = c.y, z = c.z}, special, true)
conifers:add_leaves_block({x = 1 + c.x, y = c.y, z = c.z}, special, true)
end
-- Stuff...
if m_m > 0 then
m_z = m_z - 1
m_m = m_m - 8 * m_z
end
m_x = m_x + 1
m_m = m_m + 8 * m_x + 4
end
end
end
--
-- make_conifer(position, type)
--
-- Make a conifer at a given position.
-- Types are:
-- 0: regular pine
-- 1: narrow pine
--
function conifers:make_conifer(pos, conifer_type)
-- Check if we can gros a conifer at this place.
local node = minetest.get_node(pos).name
if minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name ~= "default:dirt_with_grass"
and (node ~= "air"
or node ~= "conifers:sapling"
) then
return false
--else
--if minetest.get_node({x = pos.x, y = pos.y, z = pos.z}).name == "conifers:sapling" then
--minetest.add_node(pos , {name = "air"})
--end
end
local height = math.random(TRUNK_MINHEIGHT, TRUNK_MAXHEIGHT) -- Random height of the conifer.
-- Let's check if we can grow a tree here.
-- That means, we must have a column of 'height' high which contains
-- only air.
for j = 1, height - 1 do -- Start from 1 so we can grow a sapling.
if minetest.get_node({x=pos.x, y=pos.y+j, z=pos.z}).name ~= "air" then
-- Abort
return false
end
end
local t1 = os.clock()
local leaves_height = math.random(LEAVES_MINHEIGHT, LEAVES_MAXHEIGHT) -- Level from where the leaves grow.
local current_block = {} -- Duh...
local leaves_radius = 1
local leaves_max_radius = 2
local special = math.random(0, 1)
-- Create the trunk and add the leaves.
for i = 0, height - 1 do
current_block = {x=pos.x, y=pos.y+i, z=pos.z}
-- Put a trunk block.
minetest.add_node(current_block , {name = "conifers:trunk"})
-- Put some leaves.
if i >= leaves_height then
-- Put some leaves.
conifers:make_leaves({x=pos.x, y=pos.y+leaves_height+height-1-i, z=pos.z}, 1, leaves_radius, special)
--
-- TYPE OF CONIFER
--
if conifer_type == 1 then -- Regular type
-- Prepare the next circle of leaves.
leaves_radius = leaves_radius+1
-- Check if the current radius is the maximum radius at this level.
if leaves_radius > leaves_max_radius then
leaves_radius = 1
leaves_max_radius = leaves_max_radius+1
-- Does it exceeds the maximum radius?
if leaves_max_radius > LEAVES_MAXRADIUS then
leaves_max_radius = LEAVES_MAXRADIUS
end
end
else -- Narrow type
if i % 2 == 0 then
leaves_radius = LEAVES_NARROWRADIUS-math.random(0,1)
else
leaves_radius = math.floor(LEAVES_NARROWRADIUS/2)
end
end
end
end
-- Put a top leaves block.
current_block.y = current_block.y+1
conifers:add_leaves_block(current_block, special)
-- Blahblahblah
print (string.format('[conifers] A conifer has grown at ('..pos.x..','..pos.y..','..pos.z..') with a height of '..height..' after ca. %.2fs', os.clock() - t1))
return true
end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 699 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 768 B

1
mods/hydro Submodule

@ -0,0 +1 @@
Subproject commit cf0252fe2233ee345b7364def9de1044c6fec42c

View File

@ -1,4 +0,0 @@
## Generic ignorable patterns and files
*~
.*.swp
debug.txt

View File

@ -1 +0,0 @@
default

View File

@ -1,425 +0,0 @@
local HYDRO_GROW_INTERVAL = 100
local PLANTS = {
tomato = {name='tomato', description="Tomato", growtype='growtall'},
peas = {name='peas', description="Peas", growtype='growtall'},
habanero = {name='habanero', description="Habanero", growtype='growtall'},
grapes = {name='grapes', description="Grapes", growtype='permaculture'},
coffee = {name='coffee', description="Coffee", growtype='permaculture'},
roses = {name='roses', description="Roses", growtype='growtall',give_on_harvest='hydro:rosebush'}
}
minetest.register_node("hydro:wine", {
description = 'Wine Bottle',
drawtype = "plantlike",
tile_images = {"hydro_wine.png"},
inventory_image = "hydro_wine.png",
wield_image = "hydro_wine.png",
use_texture_alpha = true,
paramtype = "light",
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,flammable=3},
sounds = default.node_sound_wood_defaults(),
walkable = false,
on_use = minetest.item_eat(1)
})
minetest.register_node("hydro:coffeecup", {
description = 'Coffee Cup',
drawtype = "plantlike",
tile_images = {"hydro_coffeecup.png"},
inventory_image = "hydro_coffeecup.png",
wield_image = "hydro_coffeecup.png",
use_texture_alpha = true,
paramtype = "light",
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,flammable=3},
sounds = default.node_sound_wood_defaults(),
walkable = false,
on_use = minetest.item_eat(2)
})
minetest.register_node("hydro:growlamp", {
description = "Growlamp",
drawtype = 'nodebox',
node_box = {
type = "fixed",
fixed = {
{-1/16, -7/16, -1/16, 1/16, 8/16, 1/16},
{-2/16, 3/16, -2/16, 2/16, 6/16, 2/16},
{-3/16, -6/16, -2/16, 3/16, 3/16, 2/16},
{-2/16, -6/16, -3/16, 2/16, 3/16, 3/16},
}
},
tile_images = {"hydro_growlamp_top.png", "hydro_growlamp_bottom.png", "hydro_growlamp_side.png"},
--inventory_image = "hydro_growlamp_side.png",
paramtype = "light",
light_propagates = true,
sunlight_propagates = true,
light_source = 15,
groups = {snappy=2,cracky=3,oddly_breakable_by_hand=3},
sounds = default.node_sound_glass_defaults(),
node_placement_prediction = "hydro:coffeecup",
})
minetest.on_place = minetest.on_place or function(name, func)
local previous_on_place = minetest.registered_nodes[name].on_place
minetest.override_item(name, {
on_place = function(itemstack, placer, pointed_thing)
if func(itemstack, placer, pointed_thing) then
return previous_on_place(itemstack, placer, pointed_thing)
end
end
})
end
minetest.on_place("hydro:growlamp", function(itemstack, placer, pointed_thing)
if not pointed_thing then
return
end
local pos = minetest.get_pointed_thing_position(pointed_thing, true)
if not pos then
return
end
local nd_above = minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z}).name
local nd_above_info = minetest.registered_nodes[nd_above]
if nd_above == "air"
or nd_above == "hydro:growlamp"
or not nd_above_info.walkable
or nd_above_info.buildable_to then
return
end
return true
end)
minetest.register_node("hydro:promix", {
description = "Promix",
tile_images = {"hydro_promix.png"},
groups = {crumbly=3},
sounds = default.node_sound_dirt_defaults(),
})
minetest.register_node("hydro:roastedcoffee", {
description = "Roasted Coffee",
tile_images = {"hydro_roastedcoffee.png"},
inventory_image = minetest.inventorycube("hydro_roastedcoffee.png"),
groups = {snappy=2,cracky=3,oddly_breakable_by_hand=3},
sounds = default.node_sound_stone_defaults(),
})
minetest.register_node("hydro:rosebush", {
description = "Rose Bush",
drawtype = "allfaces_optional",
visual_scale = 1.3,
tile_images = {"hydro_rosebush.png"},
paramtype = "light",
groups = {snappy=3, flammable=2},
sounds = default.node_sound_leaves_defaults(),
})
local get_plantname = {} -- plants index by nodenames (tomato1, tomato2, seeds_tomato, etc..)
local get_plantbynumber = {} -- plants index by number (for random select)
local get_wildplants = {} -- wildplant nodenames (pop control)
for _,plant in pairs(PLANTS) do
-- define nodes
local wild_plant = "hydro:wild_"..plant.name
minetest.register_node(wild_plant, {
description = "Wild "..plant.description.." Plant",
drawtype = "plantlike",
visual_scale = 1.0,
tile_images = {"hydro_wildplant.png"},
paramtype = "light",
walkable = false,
groups = {snappy=3,flammable=3},
sounds = default.node_sound_leaves_defaults(),
drop = 'hydro:seeds_'..plant.name..' 4',
selection_box = {
type = "fixed",
fixed = {-1/3, -1/2, -1/3, 1/3, 1/6, 1/3},
},
})
minetest.register_node("hydro:seeds_"..plant.name, {
description = plant.description.." Seeds",
drawtype = "signlike",
tile_images = {"hydro_seeds.png"},
inventory_image = "hydro_seeds.png",
wield_image = "hydro_seeds.png",
paramtype = "light",
paramtype2 = "wallmounted",
is_ground_content = true,
walkable = false,
climbable = false,
selection_box = {
type = "wallmounted",
--wall_top = = <default>
--wall_bottom = = <default>
--wall_side = = <default>
},
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=3},
legacy_wallmounted = true,
sounds = default.node_sound_wood_defaults(),
})
minetest.register_node('hydro:seedlings_'..plant.name, {
drawtype = 'plantlike',
visual_scale = 1.0,
tile_images = { 'hydro_seedlings.png' },
inventory_image = 'hydro_seedlings.png',
sunlight_propagates = true,
paramtype = 'light',
walkable = false,
furnace_burntime = 1,
groups = { snappy = 3 },
sounds = default.node_sound_leaves_defaults(),
drop = '',
})
minetest.register_node('hydro:sproutlings_' .. plant.name, {
drawtype = 'plantlike',
visual_scale = 1.0,
tile_images = { 'hydro_sproutlings.png' },
inventory_image = 'hydro_sproutlings.png',
sunlight_propagates = true,
paramtype = 'light',
walkable = false,
furnace_burntime = 1,
groups = { snappy = 3 },
sounds = default.node_sound_leaves_defaults(),
drop = '',
})
minetest.register_node('hydro:'..plant.name..'1', {
description = plant.description..' Plant (Young)',
drawtype = 'plantlike',
visual_scale = 1.0,
tile_images = { 'hydro_'..plant.name..'1.png' },
inventory_image = 'hydro_'..plant.name..'1.png',
sunlight_propagates = true,
paramtype = 'light',
walkable = false,
furnace_burntime = 1,
groups = { snappy = 3 },
sounds = default.node_sound_leaves_defaults(),
drop = '',
})
minetest.register_node('hydro:'..plant.name..'2', {
description = plant.description..' Plant (Youngish)',
drawtype = 'plantlike',
visual_scale = 1.0,
tile_images = { 'hydro_'..plant.name..'2.png' },
inventory_image = 'hydro_'..plant.name..'2.png',
sunlight_propagates = true,
paramtype = 'light',
walkable = false,
furnace_burntime = 1,
groups = { snappy = 3 },
sounds = default.node_sound_leaves_defaults(),
drop = '',
})
minetest.register_node('hydro:'..plant.name..'3', {
description = plant.description..' Plant (Fruitings)',
drawtype = 'plantlike',
visual_scale = 1.0,
tile_images = { 'hydro_'..plant.name..'3.png' },
inventory_image = 'hydro_'..plant.name..'3.png',
sunlight_propagates = true,
paramtype = 'light',
walkable = false,
furnace_burntime = 1,
groups = { snappy = 3 },
sounds = default.node_sound_leaves_defaults(),
drop = '',
})
local harvest = 'hydro:'..plant.name
if plant.give_on_harvest then
harvest = plant.give_on_harvest
end
local after_dig_node
if plant.growtype == 'permaculture' then
plant.growtype = 'growshort'
after_dig_node = function(pos)
minetest.add_node(pos, {name='hydro:'..plant.name..'1'})
end
end
minetest.register_node('hydro:'..plant.name..'4', {
description = plant.description..' Plant (Ripe)',
drawtype = 'plantlike',
visual_scale = 1.0,
tile_images = { 'hydro_'..plant.name..'4.png' },
inventory_image = 'hydro_'..plant.name..'4.png',
sunlight_propagates = true,
paramtype = 'light',
walkable = false,
furnace_burntime = 1,
groups = { snappy = 3 },
sounds = default.node_sound_leaves_defaults(),
after_dig_node = after_dig_node,
drop = {
items = {
{ items = {'hydro:seeds_'..plant.name..' 4'},
rarity = 4,
},
{
items = {harvest..' 2'},
}
}
},
})
if not plant.give_on_harvest then
minetest.register_node("hydro:"..plant.name, {
description = plant.name,
drawtype = "plantlike",
visual_scale = 1.0,
tile_images = {"hydro_"..plant.name..".png"},
inventory_image = "hydro_"..plant.name..".png",
paramtype = "light",
sunlight_propagates = true,
walkable = false,
groups = {fleshy=3,dig_immediate=3,flammable=2},
on_use = minetest.item_eat(4),
sounds = default.node_sound_defaults(),
})
end
table.insert(get_wildplants, wild_plant)
table.insert(get_plantbynumber, plant.name)
get_plantname["hydro:"..plant.name.."4"] = plant.name
get_plantname["hydro:"..plant.name.."3"] = plant.name
get_plantname["hydro:"..plant.name.."2"] = plant.name
get_plantname["hydro:"..plant.name.."1"] = plant.name
get_plantname['hydro:sproutlings_'..plant.name] = plant.name
get_plantname['hydro:seedlings_'..plant.name] = plant.name
get_plantname['hydro:seeds_'..plant.name] = plant.name
end
-- GROW (TALL) FUNCTION
local function grow_plant(plantname, nodename, pos, tall)
local name, above
if nodename == 'hydro:'..plantname..'3' then
name = plantname.."4"
above = true
elseif nodename == 'hydro:'..plantname..'2' then
name = plantname.."3"
above = true
elseif nodename == 'hydro:'..plantname..'1' then
name = plantname.."2"
above = true
elseif nodename =='hydro:sproutlings_'..plantname then
name = plantname.."1"
elseif nodename == 'hydro:seedlings_'..plantname then
name = "sproutlings_"..plantname
elseif nodename == 'hydro:seeds_'..plantname then
name = "seedlings_"..plantname
else
return
end
minetest.add_node(pos, {name="hydro:"..name})
if above
and tall then
minetest.add_node({x=pos.x, y=pos.y+1, z=pos.z}, {name="hydro:"..name})
end
end
-- WILD PLANTS/SEEDS GENERATING
local function get_random(pos, seed)
return PseudoRandom(math.abs(pos.x+pos.y*3+pos.z*5)+seed)
end
minetest.register_abm({
nodenames = { "default:dirt_with_grass" },
interval = 600,
chance = 80,
action = function(p, node)
local pr = get_random(p, 17)
if pr:next(1,20) ~= 1 then
return
end
p.y = p.y+1
local is_air = minetest.get_node_or_nil(p)
if is_air
and is_air.name == 'air' then
local count = table.getn(get_plantbynumber)
local random_plant = math.random(1, count)
local nodename = "hydro:wild_"..get_plantbynumber[random_plant]
if nodename ~= "hydro:wild_rubberplant" then
minetest.add_node(p, {name=nodename})
end
end
end
})
-- GROWING
minetest.register_abm({
nodenames = { "hydro:growlamp" },
interval = HYDRO_GROW_INTERVAL,
chance = 1,
action = function(pos, node)
if minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z}).name == "air"
or minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name ~= "air" then
return
end
for i = -1,1 do
for j = -1,1 do
local p = {x=pos.x+j, y=pos.y, z=pos.z+i}
local water = minetest.get_node({x=p.x, y=p.y-5, z=p.z}).name
if (water == 'default:water_source' or water == 'default:water_flowing')
and minetest.get_node({x=p.x, y=p.y-4, z=p.z}).name == 'hydro:promix' then
local grow = minetest.get_node({x=p.x, y=p.y-3, z=p.z}).name
local curplant = get_plantname[grow]
if curplant then
local growtype = PLANTS[curplant].growtype
local tall
if growtype == 'growtall' then
tall = true
end
grow_plant(curplant, grow, {x=p.x, y=p.y-3, z=p.z}, tall)
end
end
end
end
end
})
--Crafting
minetest.register_craft({
output = 'hydro:growlamp',
recipe = {
{'default:glass', 'default:torch','default:glass'},
{'default:glass', 'default:torch','default:glass'},
{'default:glass', 'default:torch','default:glass'},
}
})
minetest.register_craft({
output = 'hydro:promix 6',
recipe = {
{'', 'default:clay_lump',''},
{'default:dirt', 'default:dirt', 'default:dirt'},
{'default:dirt', 'default:dirt', 'default:dirt'},
}
})
minetest.register_craft({
output = 'hydro:wine',
recipe = {
{'default:glass', 'hydro:grapes','default:glass'},
{'default:glass', 'hydro:grapes','default:glass'},
{'default:glass', 'hydro:grapes','default:glass'},
}
})
minetest.register_craft({
output = "hydro:coffeecup",
recipe = {
{'','',''},
{'default:clay_lump','hydro:roastedcoffee','default:clay_lump'},
{'','default:clay_lump',''},
}
})
minetest.register_craft({
type = "cooking",
output = "hydro:roastedcoffee",
recipe = "hydro:coffee",
})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 797 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 429 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 383 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 480 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 533 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 475 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 533 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 687 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 540 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 396 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 489 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 696 B

1
mods/locks Submodule

@ -0,0 +1 @@
Subproject commit 06fb90c1198a9e89c8281b52d7e9291819c2dd1e

View File

@ -1,36 +0,0 @@
This Mod for Minetest adds objects that can be locked and shared.
It is written so that other objects/mods can easily use the functions provided here.
Comes with modified chest, sign and xyz' xdoor2 as sample objects.
New: Furnaces added.
For the (unmodified) xdoors2, see http://minetest.net/forum/viewtopic.php?id=2757. Chest and sign take their textures out of default.
The textures (lock, key and keychain) have been provided by Addi. Please consult textures/licence.txt.
The code of the lock mod has been written by Sokomine.
A player may open/use a shared locked object if he/she is/has...
- the owner
- diglocks priv (may dig up shared locked objects)
- openlocks priv (object may only be used - i.e. take something out of a chest, open a door - not digged up!)
- has been added by the owner with the /add playername command
- member of a playergroup that has been added with /add :playergroupname command (provided the playergroups mod is installed)
- typed in the correct password that the owner did set with /set thisisthepassword
Adds lock, key and keychain.
- lock: craftitem to create shared locked objects (chests, signs, doors)
- key: needed to open your own shared locked objects (a keychain is ok as well)
- keychain: needed to open the shared locked objects of other players
The tools do not have to be wielded. They just have to be in the players' inventory.
Keys and keychains are not specific to a selected lock. They fit all locks - provided the player may open/use the object.
Thus it is sufficient to carry around only one keychain to open all shared locked objects the player has access to.
If you do not want any of the objects chest, sign and/or door, just remove the corresponding lines from the init.lua:
dofile(minetest.get_modpath("locks").."/shared_locked_chest.lua");
dofile(minetest.get_modpath("locks").."/shared_locked_sign_wall.lua");
dofile(minetest.get_modpath("locks").."/shared_locked_xdoors2.lua");
dofile(minetest.get_modpath("locks").."/shared_locked_furnace.lua");
I hope this mod will be helpful.
Sokomine

View File

@ -1,2 +0,0 @@
default
pipeworks?

View File

@ -1,611 +0,0 @@
--[[
Shared locked objects (Mod for MineTest)
Allows to restrict usage of blocks to a certain player or a group of
players.
Copyright (C) 2013 Sokomine
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/>.
--]]
-- Version 1.20
-- Changelog:
-- 08.05.2014 * Changed animation of shared locked furnace (removed pipeworks overlay on front, changed to new animation type)
-- 10.01.2013 * Added command to toggle for pipeworks output
-- * Added pipeworks support for chests and furnace.
-- 17.12.2013 * aborting input with ESC is possible again
-- 01.09.2013 * fixed bug in input sanitization
-- 31.08.2013 * changed receipe for key to avoid crafting conflickt with screwdriver
-- 10.07.2013 * removed a potential bug (now uses string:gmatch)
-- * added shared locked furnaces
locks = {};
minetest.register_privilege("openlocks", { description = "allows to open/use all locked objects", give_to_singleplayer = false});
minetest.register_privilege("diglocks", { description = "allows to open/use and dig up all locked objects", give_to_singleplayer = false});
locks.pipeworks_enabled = false;
if( minetest.get_modpath("pipeworks") ~= nil ) then
locks.pipeworks_enabled = true;
end
-- initializes a lock (that is: prepare the metadata so that it can store data)
-- default_formspec is the formspec that will be used on right click; the input field for the commands has to exist
-- Call this in on_construct in register_node. Excample:
-- on_construct = function(pos)
-- locks:lock_init( pos, "" );
-- end;
function locks:lock_init( pos, default_formspec )
if( pos == nil ) then
print( "Error: [locks] lock_init: pos is nil");
return;
end
local meta = minetest.env:get_meta(pos);
if( meta == nil ) then
print( "Error: [locks] lock_init: unable to get meta data");
return;
end
-- this will be changed after the node is placed
meta:set_string("infotext", "Locked object");
-- prepare the field for the owner
meta:set_string("owner", "");
-- this is the list of players/groups that may unlock the lock even if they are not the owner
meta:set_string("allowed_users","");
-- objects can be unlocked by passwords as well (if it is set)
meta:set_string("password","");
-- the last player who entered the right password (to save space this is not a list)
meta:set_string("pw_user","");
-- this formspec is presented on right-click for every user
meta:set_string("formspec", default_formspec);
-- by default, do not send output to pipework tubes
meta:set_int( "allow_pipeworks", 0 );
end
-- returns the information stored in the metadata strings (like owner etc.)
function locks:get_lockdata( pos )
if( pos == nil ) then
return;
end
local meta = minetest.env:get_meta(pos);
if( meta == nil) then
return;
end
return{ infotext = (meta:get_string( "infotext" ) or ""),
owner = (meta:get_string( "owner" ) or ""),
allowed_users = (meta:get_string( "allowed_users" ) or ""),
password = (meta:get_string( "password" ) or ""),
pw_user = (meta:get_string( "w_user" ) or ""),
formspec = (meta:get_string( "formspec" ) or "")
};
end
-- sets all the metadata the look needs (used e.g. in doors)
function locks:set_lockdata( pos, data )
if( pos == nil ) then
return;
end
local meta = minetest.env:get_meta(pos);
if( meta == nil) then
return;
end
meta:set_string("infotext", (data.infotext or ""));
meta:set_string("owner", (data.owner or ""));
meta:set_string("allowed_users",(data.allowed_users or ""));
meta:set_string("password", (data.password or ""));
meta:set_string("pw_user", (data.pw_user or ""));
meta:set_string("formspec", (data.formspec or ""));
end
-- Set the owner of the locked object.
-- Call this in after_place_node in register_node. Example:
-- after_place_node = function(pos, placer)
-- locks:lock_set_owner( pos, placer, "Shared locked object" );
-- end,
function locks:lock_set_owner( pos, player_or_name, description )
if( pos == nil or player_or_name == nil ) then
print( "Error: [locks] Missing/wrong parameters to lock_set_owner");
return false;
end
local meta = minetest.env:get_meta(pos);
if( meta == nil ) then
print( "Error: [locks] lock_set_owner: unable to get meta data");
return;
end
-- accepts a name or a player object
if( type( player_or_name )~="string") then
player_or_name = player_or_name:get_player_name();
end
meta:set_string("owner", player_or_name or "");
-- add the name of the owner to the description
meta:set_string("infotext", ( description or "Shared lockecd object" ).." (owned by "..meta:get_string("owner")..")");
end
-- The locked object can only be digged by the owner OR by people with the diglocks priv
-- Call this in can_dig in register_node. Example:
-- can_dig = function(pos,player)
-- return locks:lock_allow_dig( pos, player );
-- end
function locks:lock_allow_dig( pos, player )
if( pos == nil or player == nil ) then
print( "Error: [locks] Missing/wrong parameters to lock_allow_dig");
return false;
end
local meta = minetest.env:get_meta(pos);
local lock_owner = meta:get_string("owner");
-- locks who lost their owner can be opened/digged by anyone
if( meta == nil or lock_owner == nil or lock_owner == "") then
return true;
end
-- the owner can dig up his own locked objects
if( player:get_player_name() == meta:get_string("owner")) then
return true;
end
-- players with diglocks priv can dig up locked objects as well
if( minetest.check_player_privs(player:get_player_name(), {diglocks=true})) then
return true;
end
return false; -- fallback
end
-- The locked object can only be used (i.e. opened, stuff taken out, changed, ... - depends on object) if this
-- function returns true. Call it wherever appropriate (usually in on_punch in register_node). Example:
-- on_punch = function(pos,player)
-- if( !locks:lock_allow_use( pos, player ) then
-- print( "Sorry, you have no access here.");
-- else
-- do_what_this_object_is_good_for( pos, puncher );
-- end
-- end
function locks:lock_allow_use( pos, player )
if( pos == nil or player == nil ) then
print( "Error: [locks] Missing/wrong parameters to lock_allow_use");
return false;
end
local name = player:get_player_name();
local meta = minetest.env:get_meta(pos);
-- pipeworks sends a special username
if( name == ':pipeworks' ) then
if( meta:get_int( 'allow_pipeworks' ) == 1 ) then
return true;
else
return false;
end
end
-- the player has to have a key or a keychain to open his own shared locked objects
if( name == meta:get_string("owner")) then
if( not( player:get_inventory():contains_item("main","locks:keychain 1"))
and not( player:get_inventory():contains_item("main","locks:key 1"))) then
minetest.chat_send_player( name, "You do not have a key or a keychain. Without that you can't use your shared locked objects!");
return false;
end
-- the player has to have a keychain to open shared locked objects of other players
else
if( not( player:get_inventory():contains_item("main","locks:keychain 1"))) then
minetest.chat_send_player(name, "You do not have a keychain. Without that you can't open shared locked objects of other players!");
return false;
end
end
-- if the user would even be allowed to dig this node up, using the node is allowed as well
if( locks:lock_allow_dig( pos, player )) then
return true;
end
if( meta == nil ) then
minetest.chat_send_player( name, "Error: Could not access metadata of this shared locked object.");
return false;
end
-- players with openlocks priv can open locked objects
if( minetest.check_player_privs(name, {openlocks=true})) then
return true;
end
-- the player might be specificly allowed to use this object through allowed_users
local liste = meta:get_string("allowed_users"):split( "," );
for i in ipairs( liste ) do
if( liste[i] == name ) then
return true;
end
-- the player might member of a playergroup that is allowed to use this object
if( liste[i]:sub(1,1) == ":"
and playergroups ~= nil
and playergroups:is_group_member( meta:get_string("owner"), liste[i]:sub(2), name )) then
return true;
end
end
-- the player may have entered the right password
if( name == meta:get_string("pw_user")) then
return true;
end
-- the lock may have a password set. If this is the case then ask the user for it
if( meta:get_string( "password" ) and meta:get_string( "password" ) ~= "" ) then
minetest.chat_send_player(name, "Access denied. Right-click and enter password first!");
return false;
end
return false; -- fallback
end
-- Method for the lock to get password and configuration data
-- Call in on_receive_fields in register_node. Example:
-- on_receive_fields = function(pos, formname, fields, sender)
-- locks:lock_handle_input( pos, formname, fields, sender );
-- end,
function locks:lock_handle_input( pos, formname, fields, player )
if( pos == nil or player == nil ) then
print( "Error: [locks] Missing/wrong parameters to lock_handle_input");
return false;
end
local meta = minetest.env:get_meta(pos);
if( meta == nil ) then
print( "Error: [locks] lock_handle_input: unable to get meta data");
return;
end
-- is this input the lock is supposed to handle?
if( not( fields.locks_sent_lock_command )
or (fields.quit and (fields.quit==true or fields.quit=='true'))
-- or not( fields.locks_sent_input )
or fields.locks_sent_lock_command == "" ) then
return;
end
name = player:get_player_name();
if( fields.locks_sent_lock_command == "/help" ) then
if( name == meta:get_string( "owner" )) then
minetest.chat_send_player(name, "The following commands are available to you, the owner of this object, only:\n"..
" /help Shows this help text.\n"..
" /add <name> Player <name> can now unlock this object with any key.\n"..
" /del <name> Player <name> can no longer use this object.\n"..
" /list Shows a list of players who can use this object.\n"..
" /set <password> Sets a password. Everyone who types that in can use the object.\n"..
" /pipeworks Toggles permission for pipeworks to take inventory out of the shared locked object.\n");
else if( locks:lock_allow_use( pos, player )) then
minetest.chat_send_player(name, "This locked object is owned by "..tostring( meta:get_string( "owner" ))..".\n"..
"You do have access to it.\n");
else if( meta:get_string( "password" ) ~= "" ) then
minetest.chat_send_player(name, "This locked object is owned by "..tostring( meta:get_string( "owner" ))..".\n"..
"Enter the correct password to gain access.\n");
else
minetest.chat_send_player(name, "This locked object is owned by "..tostring( meta:get_string( "owner" ))..".\n"..
"There is no password set. You can only gain access if the owner grants it to you.");
end end end -- lua is not the most intuitive language here....
return;
end -- of /help
-- sanitize player input
if( fields.locks_sent_lock_command:match("[^%a%d%s_%- /%:]")) then
minetest.chat_send_player(name, "Input contains unsupported characters. Allowed: a-z, A-Z, 0-9, _, -, :.");
return;
end
if( #fields.locks_sent_lock_command > 60) then
minetest.chat_send_player(name, "Input too long. Only up to 80 characters supported.");
return;
end
-- other players can only try to input the correct password
if( name ~= meta:get_string( "owner" )) then
-- no need to bother with trying other PWs if none is set...
if( meta:get_string("password")=="" ) then
minetest.chat_send_player(name, "There is no password set. Access denied.");
return;
end
-- the player may have entered the right password already
if( name == meta:get_string("pw_user")) then
-- nothing to do - the player entered the right pw alredy
minetest.chat_send_player(name, "You have entered the right password already. Access granted.");
return;
end
if( fields.locks_sent_lock_command ~= meta:get_string("password")) then
minetest.chat_send_player(name, "Wrong password. Access denied.");
return;
end
-- store the last user (this one) who entered the right pw
meta:set_string( "pw_user", name );
minetest.chat_send_player(name, "Password confirmed. Access granted.");
return;
end
local txt = "";
if( fields.locks_sent_lock_command == "/list" ) then
if( meta:get_string("allowed_users")=="" ) then
txt = "No other users are allowed to use this object (except those with global privs like moderators/admins).";
else
txt = "You granted the following users/groups of users access to this object:\n";
local liste = meta:get_string("allowed_users"):split( "," );
for i in ipairs( liste ) do
txt = txt.." "..tostring(liste[i]);
end
end
if( meta:get_string( "password" ) == "" ) then
txt = txt.."\nThere is no password set. That means no one can get access through a password.";
else
txt = txt.."\nThe password for this lock is: \""..tostring( meta:get_string( "password" ).."\"");
end
if( not( minetest.get_modpath("pipeworks") )) then
txt = txt.."\nThe pipeworks mod is not installed. Install it if you wish support for tubes.";
elseif( meta:get_int( "allow_pipeworks" ) == 1 ) then
txt = txt.."\nTubes from pipeworks may be used to extract items out of/add items to this shared locked object.";
else
txt = txt.."\nInput from tubes is accepted, but output to them is denied (default).";
end
minetest.chat_send_player(name, txt );
return;
end -- of /list
-- toggle tube output on/off
if( fields.locks_sent_lock_command == "/pipeworks" ) then
if( meta:get_int('allow_pipeworks') == 1 ) then
meta:set_int('allow_pipeworks', 0 );
minetest.chat_send_player( name, 'Output to pipework tubes is now DISABLED (input is still acceped).');
return;
else
meta:set_int('allow_pipeworks', 1 );
minetest.chat_send_player( name, 'Output to pipework tubes is now ENABLED. Connected tubes may insert and remove items.');
return;
end
end
-- -- all other commands take exactly one parameter
local help = fields.locks_sent_lock_command:split( " " );
print( tostring( help[1] ));
print( tostring( help[2] ));
-- set/change a password
if( help[1]=="/set" ) then
-- if empty password then delete it
if( help[2]==nil ) then
help[2] = "";
end
minetest.chat_send_player(name, "Old password: \""..tostring( meta:get_string( "password" ))..
"\"\n Changed to new password: \""..tostring( help[2]).."\".");
meta:set_string( "password", help[2]);
-- reset the list of users who typed the right password
meta:set_string("pw_users","");
if( help[2]=="") then
minetest.chat_send_player(name, "The password is empty and thus will be disabled.");
end
return;
end
if( help[2]==nil or help[2]=="") then
minetest.chat_send_player(name, "Error: Missing parameter (player name) for command \""..tostring( help[1] ).."\"." );
return;
end
-- for add and del: check if the player is already in the list
local found = false;
local anz = 0;
local liste = meta:get_string("allowed_users"):split( "," );
for i in ipairs( liste ) do
anz = anz + 1; -- count players
if( tostring( liste[i] ) == help[2] ) then
found = true;
end
end
if( help[1]=="/add" and found==true ) then
minetest.chat_send_player(name, "Player \""..tostring( help[2] ).."\" is already allowed to use this locked object. Nothing to do.");
return;
end
if( help[1]=="/del" and found==false) then
minetest.chat_send_player(name, "Player \""..tostring( help[2] ).."\" is not amongst the players allowed to use this locked object. Nothing to do.");
return;
end
if( help[1]=="/add" ) then
if( anz >= 6 ) then
minetest.chat_send_player(name, "Sorry, no more players can be added. To save space, only up to 6 players can be added. For more players please use groups!");
return;
end
if( name == help[2] ) then
minetest.chat_send_player(name, "You are already owner of this object.");
return;
end
-- the player might try to add a playergroup
if( help[2]:sub(1,1) == ":" ) then
if( not( playergroups )) then
minetest.chat_send_player(name, "Sorry, this server does not support playergroups.");
return;
end
if( #help[2]<2 ) then
minetest.chat_send_player(name, "Please specify the name of the playergroup you want to add!");
return;
end
if( not( playergroups:is_playergroup(meta:get_string("owner"), help[2]:sub(2) ))) then
minetest.chat_send_player(name, "You do not have a playergroup named \""..tostring( help[2]:sub(2)).."\".");
return;
end
else
-- check if the player exists
local privs = minetest.get_player_privs( help[2] );
if( not( privs ) or not( privs.interact )) then
minetest.chat_send_player(name, "Player \""..help[2].."\" not found or has no interact privs.");
return;
end
end
meta:set_string( "allowed_users", meta:get_string("allowed_users")..","..help[2] );
if( help[2]:sub(1,1) == ":" ) then
minetest.chat_send_player(name, "All members of your playergroup "..tostring(help[2]:sub(2)).." may now use/access this locked object.");
else
minetest.chat_send_player(name, help[2].." may now use/access this locked object.");
end
return;
end
if( help[1]=="/del" ) then
userlist = meta:get_string("allowed_users"):split( ","..help[2] );
meta:set_string( "allowed_users", ( userlist[1] or "" )..(userlist[2] or "" ));
minetest.chat_send_player(name, "Access for player \""..tostring(help[2]).."\" has been revoked.");
return;
end
minetest.chat_send_player(name, "Error: Command \""..tostring(help[1]).."\" not understood.");
end
-- craftitem; that can be used to craft shared locked objects
minetest.register_craftitem("locks:lock", {
description = "Lock to lock and share objects",
image = "locks_lock16.png",
});
minetest.register_craft({
output = "locks:lock 2",
recipe = {
{'default:steel_ingot', 'default:steel_ingot','default:steel_ingot'},
{'default:steel_ingot', '', 'default:steel_ingot'},
{'', 'default:steel_ingot',''},
}
});
-- a key allowes to open your own shared locked objects
minetest.register_craftitem("locks:key", {
description = "Key to open your own shared locked objects",
image = "locks_key32.png",
});
minetest.register_craft({
output = "locks:key",
recipe = {
{'', 'default:stick', ''},
{'', 'default:steel_ingot',''},
}
});
-- in order to open shared locked objects of other players, a keychain is needed (plus the owner has to admit it via /add playername or through /set password)
minetest.register_craftitem("locks:keychain", {
description = "Keychain to open shared locked objects of others",
image = "locks_keychain32.png",
});
minetest.register_craft({
output = "locks:keychain",
recipe = {
{'', 'default:steel_ingot', '' },
{'locks:key', 'locks:key', 'locks:key'},
}
});
dofile(minetest.get_modpath("locks").."/shared_locked_chest.lua");
dofile(minetest.get_modpath("locks").."/shared_locked_sign_wall.lua");
dofile(minetest.get_modpath("locks").."/shared_locked_xdoors2.lua");
dofile(minetest.get_modpath("locks").."/shared_locked_furnace.lua");

View File

@ -1,19 +0,0 @@
License of locks mod for Minetest-c55
-------------------------------------
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

View File

@ -1,136 +0,0 @@
-- 09.01.13 Added support for pipeworks.
locks.chest_add = {};
locks.chest_add.tiles = {"default_chest_top.png", "default_chest_top.png", "default_chest_side.png",
"default_chest_side.png", "default_chest_side.png", "default_chest_front.png"};
locks.chest_add.groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2};
locks.chest_add.tube = {};
-- additional/changed definitions for pipeworks;
-- taken from pipeworks/compat.lua
if( locks.pipeworks_enabled ) then
locks.chest_add.tiles = {
"default_chest_top.png^pipeworks_tube_connection_wooden.png",
"default_chest_top.png^pipeworks_tube_connection_wooden.png",
"default_chest_side.png^pipeworks_tube_connection_wooden.png",
"default_chest_side.png^pipeworks_tube_connection_wooden.png",
"default_chest_side.png^pipeworks_tube_connection_wooden.png"};
locks.chest_add.groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,
tubedevice = 1, tubedevice_receiver = 1 };
locks.chest_add.tube = {
insert_object = function(pos, node, stack, direction)
local meta = minetest.env: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.env:get_meta(pos)
local inv = meta:get_inventory()
return inv:room_for_item("main", stack)
end,
input_inventory = "main",
connect_sides = {left=1, right=1, back=1, front=1, bottom=1, top=1}
};
end
minetest.register_node("locks:shared_locked_chest", {
description = "Shared locked chest",
tiles = locks.chest_add.tiles,
paramtype2 = "facedir",
groups = locks.chest_add.groups,
tube = locks.chest_add.tube,
legacy_facedir_simple = true,
on_construct = function(pos)
local meta = minetest.env:get_meta(pos)
-- prepare the lock of the chest
locks:lock_init( pos,
"size[8,10]"..
-- "field[0.5,0.2;8,1.0;locks_sent_lock_command;Locked chest. Type password, command or /help for help:;]"..
-- "button_exit[3,0.8;2,1.0;locks_sent_input;Proceed]"..
"list[current_name;main;0,0;8,4;]"..
"list[current_player;main;0,5;8,4;]"..
"field[0.3,9.6;6,0.7;locks_sent_lock_command;Locked chest. Type /help for help:;]"..
"button_exit[6.3,9.2;1.7,0.7;locks_sent_input;Proceed]" );
-- "size[8,9]"..
-- "list[current_name;main;0,0;8,4;]"..
-- "list[current_player;main;0,5;8,4;]");
local inv = meta:get_inventory()
inv:set_size("main", 8*4)
end,
after_place_node = function(pos, placer)
if( locks.pipeworks_enabled ) then
pipeworks.scan_for_tube_objects( pos );
end
locks:lock_set_owner( pos, placer, "Shared locked chest" );
end,
can_dig = function(pos,player)
if( not(locks:lock_allow_dig( pos, player ))) then
return false;
end
local meta = minetest.env:get_meta(pos);
local inv = meta:get_inventory()
return inv:is_empty("main")
end,
on_receive_fields = function(pos, formname, fields, sender)
locks:lock_handle_input( pos, formname, fields, sender );
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
if( not( locks:lock_allow_use( pos, player ))) then
return 0;
end
return count;
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
if( not( locks:lock_allow_use( pos, player ))) then
return 0;
end
return stack:get_count()
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
if( not( locks:lock_allow_use( pos, player ))) then
return 0;
end
return stack:get_count()
end,
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
minetest.log("action", player:get_player_name()..
" moves stuff in locked shared chest at "..minetest.pos_to_string(pos))
end,
on_metadata_inventory_put = function(pos, listname, index, stack, player)
minetest.log("action", player:get_player_name()..
" moves stuff to locked shared chest at "..minetest.pos_to_string(pos))
end,
on_metadata_inventory_take = function(pos, listname, index, stack, player)
minetest.log("action", player:get_player_name()..
" takes stuff from locked shared chest at "..minetest.pos_to_string(pos))
end,
after_dig_node = function( pos )
if( locks.pipeworks_enabled ) then
pipeworks.scan_for_tube_objects(pos)
end
end
})
minetest.register_craft({
output = 'locks:shared_locked_chest',
recipe = {
{ 'default:chest', 'locks:lock', '' },
},
})
print( "[Mod] locks: loading locks:shared_locked_chest");

View File

@ -1,434 +0,0 @@
-- this is a (slightly!) modified copy of minetest_game/mods/default/nodes.lua,
-- containing only the furnace and adopted slightly for my locks mod
-- 09.01.13 Added support for pipeworks.
locks.furnace_add = {};
locks.furnace_add.tiles_normal = {"default_furnace_top.png", "default_furnace_bottom.png", "default_furnace_side.png",
"default_furnace_side.png", "default_furnace_side.png", "default_furnace_front.png"};
locks.furnace_add.tiles_active = {"default_furnace_top.png", "default_furnace_bottom.png", "default_furnace_side.png",
"default_furnace_side.png", "default_furnace_side.png", --"default_furnace_front_active.png"};
{
image = "default_furnace_front_active.png",
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 1.5
},
}};
locks.furnace_add.groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2};
locks.furnace_add.tube = {};
-- additional/changed definitions for pipeworks;
-- taken from pipeworks/compat.lua
if( locks.pipeworks_enabled ) then
locks.furnace_add.tiles_normal = {
"default_furnace_top.png^pipeworks_tube_connection_stony.png",
"default_furnace_bottom.png^pipeworks_tube_connection_stony.png",
"default_furnace_side.png^pipeworks_tube_connection_stony.png",
"default_furnace_side.png^pipeworks_tube_connection_stony.png",
"default_furnace_side.png^pipeworks_tube_connection_stony.png",
"default_furnace_front.png" };
locks.furnace_add.tiles_active = {
"default_furnace_top.png^pipeworks_tube_connection_stony.png",
"default_furnace_bottom.png^pipeworks_tube_connection_stony.png",
"default_furnace_side.png^pipeworks_tube_connection_stony.png",
"default_furnace_side.png^pipeworks_tube_connection_stony.png",
"default_furnace_side.png^pipeworks_tube_connection_stony.png",
{
image = "default_furnace_front_active.png",
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 1.5
},
}};
-- "default_furnace_front_active.png" };
locks.furnace_add.groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,
tubedevice = 1, tubedevice_receiver = 1 };
locks.furnace_add.tube = {
insert_object = function(pos, node, stack, direction)
local meta = minetest.env:get_meta(pos)
local inv = meta:get_inventory()
if direction.y == 1 then
return inv:add_item("fuel",stack)
else
return inv:add_item("src",stack)
end
end,
can_insert = function(pos, node, stack, direction)
local meta = minetest.env:get_meta(pos)
local inv = meta:get_inventory()
if direction.y == 1 then
return inv:room_for_item("fuel", stack)
else
return inv:room_for_item("src", stack)
end
end,
input_inventory = "dst",
connect_sides = {left=1, right=1, back=1, front=1, bottom=1, top=1}
};
end
function locks.get_furnace_active_formspec(pos, percent)
local formspec =
"size[8,9]"..
"image[2,2;1,1;default_furnace_fire_bg.png^[lowpart:"..
(100-percent)..":default_furnace_fire_fg.png]"..
"list[current_name;fuel;2,3;1,1;]"..
"list[current_name;src;2,1;1,1;]"..
"list[current_name;dst;5,1;2,2;]"..
"list[current_player;main;0,5;8,4;]"..
"field[0.3,4.5;6,0.7;locks_sent_lock_command;Locked furnace. Type /help for help:;]"..
"button_exit[6.3,4;1.7,0.7;locks_sent_input;Proceed]" ;
return formspec
end
locks.furnace_inactive_formspec =
"size[8,9]"..
"image[2,2;1,1;default_furnace_fire_bg.png]"..
"list[current_name;fuel;2,3;1,1;]"..
"list[current_name;src;2,1;1,1;]"..
"list[current_name;dst;5,1;2,2;]"..
"list[current_player;main;0,5;8,4;]"..
"field[0.3,4.5;6,0.7;locks_sent_lock_command;Locked furnace. Type /help for help:;]"..
"button_exit[6.3,4;1.7,0.7;locks_sent_input;Proceed]" ;
minetest.register_node("locks:shared_locked_furnace", {
description = "Shared locked furnace",
paramtype2 = "facedir",
groups = {cracky=2},
legacy_facedir_simple = true,
tiles = locks.furnace_add.tiles_normal,
groups = locks.furnace_add.groups,
tube = locks.furnace_add.tube,
-- sounds = default.node_sound_stone_defaults(),
on_construct = function(pos)
local meta = minetest.get_meta(pos)
locks:lock_init( pos, locks.furnace_inactive_formspec)
meta:set_string("infotext", "Shared locked furnace")
local inv = meta:get_inventory()
inv:set_size("fuel", 1)
inv:set_size("src", 1)
inv:set_size("dst", 4)
end,
after_place_node = function(pos, placer)
if( locks.pipeworks_enabled ) then
pipeworks.scan_for_tube_objects(pos)
end
locks:lock_set_owner( pos, placer, "Shared locked furnace" );
end,
after_dig_node = function(pos)
if( locks.pipeworks_enabled ) then
pipeworks.scan_for_tube_objects(pos)
end
end,
can_dig = function(pos,player)
if( not(locks:lock_allow_dig( pos, player ))) then
return false;
end
local meta = minetest.get_meta(pos);
local inv = meta:get_inventory()
if not inv:is_empty("fuel") then
return false
elseif not inv:is_empty("dst") then
return false
elseif not inv:is_empty("src") then
return false
end
return true
end,
on_receive_fields = function(pos, formname, fields, sender)
locks:lock_handle_input( pos, formname, fields, sender );
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
if( not( locks:lock_allow_use( pos, player ))) then
return 0;
end
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
if listname == "fuel" then
if minetest.get_craft_result({method="fuel",width=1,items={stack}}).time ~= 0 then
if inv:is_empty("src") then
meta:set_string("infotext","Furnace is empty")
end
return stack:get_count()
else
return 0
end
elseif listname == "src" then
return stack:get_count()
elseif listname == "dst" then
return 0
end
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
if( not( locks:lock_allow_use( pos, player ))) then
return 0;
end
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local stack = inv:get_stack(from_list, from_index)
if to_list == "fuel" then
if minetest.get_craft_result({method="fuel",width=1,items={stack}}).time ~= 0 then
if inv:is_empty("src") then
meta:set_string("infotext","Furnace is empty")
end
return count
else
return 0
end
elseif to_list == "src" then
return count
elseif to_list == "dst" then
return 0
end
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
if( not( locks:lock_allow_use( pos, player ))) then
return 0;
end
return stack:get_count()
end,
})
minetest.register_node("locks:shared_locked_furnace_active", {
description = "Furnace",
paramtype2 = "facedir",
light_source = 8,
drop = "locks:shared_locked_furnace",
groups = {cracky=2, not_in_creative_inventory=1},
legacy_facedir_simple = true,
tiles = locks.furnace_add.tiles_active,
groups = locks.furnace_add.groups,
tube = locks.furnace_add.tube,
-- sounds = default.node_sound_stone_defaults(),
on_construct = function(pos)
local meta = minetest.get_meta(pos)
locks:lock_init( pos, locks.furnace_inactive_formspec)
meta:set_string("infotext", "Shared locked furnace");
local inv = meta:get_inventory()
inv:set_size("fuel", 1)
inv:set_size("src", 1)
inv:set_size("dst", 4)
end,
can_dig = function(pos,player)
if( not(locks:lock_allow_dig( pos, player ))) then
return false;
end
local meta = minetest.get_meta(pos);
local inv = meta:get_inventory()
if not inv:is_empty("fuel") then
return false
elseif not inv:is_empty("dst") then
return false
elseif not inv:is_empty("src") then
return false
end
return true
end,
after_place_node = function(pos, placer)
if( locks.pipeworks_enabled ) then
pipeworks.scan_for_tube_objects(pos)
end
locks:lock_set_owner( pos, placer, "Shared locked furnace (active)" );
end,
after_dig_node = function(pos)
if( locks.pipeworks_enabled ) then
pipeworks.scan_for_tube_objects(pos)
end
end,
on_receive_fields = function(pos, formname, fields, sender)
locks:lock_handle_input( pos, formname, fields, sender );
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
if( not( locks:lock_allow_use( pos, player ))) then
return 0;
end
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
if listname == "fuel" then
if minetest.get_craft_result({method="fuel",width=1,items={stack}}).time ~= 0 then
if inv:is_empty("src") then
meta:set_string("infotext","Shared locked furnace (empty)")
end
return stack:get_count()
else
return 0
end
elseif listname == "src" then
return stack:get_count()
elseif listname == "dst" then
return 0
end
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
if( not( locks:lock_allow_use( pos, player ))) then
return 0;
end
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local stack = inv:get_stack(from_list, from_index)
if to_list == "fuel" then
if minetest.get_craft_result({method="fuel",width=1,items={stack}}).time ~= 0 then
if inv:is_empty("src") then
meta:set_string("infotext","Shared locked furnace (empty)")
end
return count
else
return 0
end
elseif to_list == "src" then
return count
elseif to_list == "dst" then
return 0
end
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
if( not( locks:lock_allow_use( pos, player ))) then
return 0;
end
return stack:get_count()
end,
})
-- better make this a function specific to this mod to avoid trouble with the same function in default
locks.hacky_swap_node = function(pos,name)
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos)
local meta0 = meta:to_table()
if node.name == name then
return
end
node.name = name
local meta0 = meta:to_table()
minetest.set_node(pos,node)
meta = minetest.get_meta(pos)
meta:from_table(meta0)
end
minetest.register_abm({
nodenames = {"locks:shared_locked_furnace","locks:shared_locked_furnace_active"},
interval = 1.0,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
local meta = minetest.get_meta(pos)
for i, name in ipairs({
"fuel_totaltime",
"fuel_time",
"src_totaltime",
"src_time"
}) do
if meta:get_string(name) == "" then
meta:set_float(name, 0.0)
end
end
local inv = meta:get_inventory()
local srclist = inv:get_list("src")
local cooked = nil
local aftercooked
if srclist then
cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
end
local was_active = false
if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then
was_active = true
meta:set_float("fuel_time", meta:get_float("fuel_time") + 1)
meta:set_float("src_time", meta:get_float("src_time") + 1)
if cooked and cooked.item and meta:get_float("src_time") >= cooked.time then
-- check if there's room for output in "dst" list
if inv:room_for_item("dst",cooked.item) then
-- Put result in "dst" list
inv:add_item("dst", cooked.item)
-- take stuff from "src" list
inv:set_stack("src", 1, aftercooked.items[1])
else
print("Could not insert '"..cooked.item:to_string().."'")
end
meta:set_string("src_time", 0)
end
end
if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then
local percent = math.floor(meta:get_float("fuel_time") /
meta:get_float("fuel_totaltime") * 100)
meta:set_string("infotext","Shared locked furnace active: "..percent.."%")
locks.hacky_swap_node(pos,"locks:shared_locked_furnace_active")
meta:set_string("formspec",locks.get_furnace_active_formspec(pos, percent))
return
end
local fuel = nil
local afterfuel
local cooked = nil
local fuellist = inv:get_list("fuel")
local srclist = inv:get_list("src")
if srclist then
cooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
end
if fuellist then
fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
end
if not( fuel) or fuel.time <= 0 then
meta:set_string("infotext","Shared locked furnace out of fuel")
locks.hacky_swap_node(pos,"locks:shared_locked_furnace")
meta:set_string("formspec", locks.furnace_inactive_formspec)
return
end
if cooked.item:is_empty() then
if was_active then
meta:set_string("infotext","Shared locked furnace is empty")
locks.hacky_swap_node(pos,"locks:shared_locked_furnace")
meta:set_string("formspec", locks.furnace_inactive_formspec)
end
return
end
meta:set_string("fuel_totaltime", fuel.time)
meta:set_string("fuel_time", 0)
inv:set_stack("fuel", 1, afterfuel.items[1])
end,
})
minetest.register_craft({
output = 'locks:shared_locked_furnace',
recipe = {
{ 'default:furnace', 'locks:lock', '' },
},
})
print( "[Mod] locks: loading locks:shared_locked_furnace");

View File

@ -1,81 +0,0 @@
-- allow aborting with ESC in newer Versions of MT again
-- a sign
minetest.register_node("locks:shared_locked_sign_wall", {
description = "Shared locked sign",
drawtype = "signlike",
tiles = {"default_sign_wall.png"},
inventory_image = "default_sign_wall.png",
wield_image = "default_sign_wall.png",
paramtype = "light",
paramtype2 = "wallmounted",
sunlight_propagates = true,
walkable = false,
selection_box = {
type = "wallmounted",
--wall_top = <default>
--wall_bottom = <default>
--wall_side = <default>
},
groups = {choppy=2,dig_immediate=2},
legacy_wallmounted = true,
on_construct = function(pos)
local meta = minetest.env:get_meta(pos)
-- prepare the lock of the sign
locks:lock_init( pos,
"size[8,4]"..
"field[0.3,0.6;6,0.7;text;Text:;]"..
"field[0.3,3.6;6,0.7;locks_sent_lock_command;Locked sign. Type /help for help:;]"..
"button_exit[6.3,3.2;1.7,0.7;locks_sent_input;Proceed]" );
end,
after_place_node = function(pos, placer)
locks:lock_set_owner( pos, placer, "Shared locked sign" );
end,
can_dig = function(pos,player)
return locks:lock_allow_dig( pos, player );
end,
on_receive_fields = function(pos, formname, fields, sender)
-- abort if no input has been sent
if( fields.quit ) then
return;
end
-- if the user already has the right to use this and did input text
if( fields.text
and ( not(fields.locks_sent_lock_command)
or fields.locks_sent_lock_command=="")
and locks:lock_allow_use( pos, sender )) then
--print("Sign at "..minetest.pos_to_string(pos).." got "..dump(fields))
local meta = minetest.env:get_meta(pos)
fields.text = fields.text or "";
print((sender:get_player_name() or "").." wrote \""..fields.text..
"\" to sign at "..minetest.pos_to_string(pos));
meta:set_string("text", fields.text.." ["..sender:get_player_name().."]");
meta:set_string("infotext", '"'..fields.text..'"'.." ["..sender:get_player_name().."]");
-- a command for the lock?
else
locks:lock_handle_input( pos, formname, fields, sender );
end
end,
});
minetest.register_craft({
output = 'locks:shared_locked_sign_wall',
recipe = {
{ 'default:sign_wall', 'locks:lock', '' },
},
})
print( "[Mod] locks: loading locks:shared_locked_sign_wall");

View File

@ -1,212 +0,0 @@
-- xDoors² mod by xyz
-- modified by Sokomine to allow locked doors that can only be opened/closed/dig up by the player who placed them
-- a little bit modified by addi to allow someone with the priv "opendoors" to open/close/dig all locked doors.
-- Sokomine: modified again so that it uses the new locks-mod
local door_bottom = {-0.5, -0.5, -0.5, 0.5, 0.5, -0.4}
local door_top = {
{-0.5, -0.5, -0.5, -0.3, 0.5, -0.4},
{0.3, -0.5, -0.5, 0.5, 0.5, -0.4},
{-0.3, 0.3, -0.5, 0.3, 0.5, -0.4},
{-0.3, -0.5, -0.5, 0.3, -0.4, -0.4},
{-0.05, -0.4, -0.5, 0.05, 0.3, -0.4},
{-0.3, -0.1, -0.5, -0.05, 0, -0.4},
{0.05, -0.1, -0.5, 0.3, 0, -0.4}
}
local is_top = function(name)
return name:sub(12, 12) == "t"
end
local xdoors2_transform = function(pos, node, puncher)
if( not( locks:lock_allow_use( pos, puncher ))) then
minetest.chat_send_player( puncher:get_player_name(), "This door is locked. It can only be opened by its owner or people with a key that fits.");
return;
end
if is_top(node.name) then
pos = {x = pos.x, y = pos.y - 1, z = pos.z}
end
local t = 3 - node.name:sub(-1)
local p2 = 0
if t == 2 then
p2 = (node.param2 + 1) % 4
else
p2 = (node.param2 + 3) % 4
end
local olddata = locks:get_lockdata( pos );
minetest.env:add_node(pos, {name = "locks:door_bottom_"..t, param2 = p2})
minetest.env:add_node({x = pos.x, y = pos.y + 1, z = pos.z}, {name = "locks:door_top_"..t, param2 = p2})
-- remember who owns the door, what passwords are set etc.
locks:set_lockdata( pos, olddata );
locks:set_lockdata( {x = pos.x, y = pos.y + 1, z = pos.z}, olddata );
end
local xdoors2_destruct = function(pos, oldnode)
if is_top(oldnode.name) then
pos = {x = pos.x, y = pos.y - 1, z = pos.z}
end
minetest.env:remove_node(pos)
minetest.env:remove_node({x = pos.x, y = pos.y + 1, z = pos.z})
end
for i = 1, 2 do
minetest.register_node("locks:door_top_"..i, {
tile_images = {"xdoors2_side.png", "xdoors2_side.png", "xdoors2_top.png", "xdoors2_bottom.png", "xdoors2_top_"..(3 - i)..".png", "xdoors2_top_"..i..".png"},
paramtype = "light",
paramtype2 = "facedir",
drawtype = "nodebox",
drop = "locks:door",
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
node_box = {
type = "fixed",
fixed = door_top
},
selection_box = {
type = "fixed",
fixed = door_bottom
},
on_punch = xdoors2_transform,
after_dig_node = xdoors2_destruct,
on_construct = function(pos)
locks:lock_init( pos,
"size[8,2]"..
"field[0.3,0.6;6,0.7;locks_sent_lock_command;Locked door. Type /help for help:;]"..
"button_exit[6.3,1.2;1.7,0.7;locks_sent_input;Proceed]" );
end,
on_receive_fields = function(pos, formname, fields, sender)
locks:lock_handle_input( pos, formname, fields, sender );
end,
can_dig = function(pos,player)
return locks:lock_allow_dig( pos, player );
end
})
minetest.register_node("locks:door_bottom_"..i, {
tile_images = {"xdoors2_side.png", "xdoors2_side.png", "xdoors2_top.png", "xdoors2_bottom.png", "locks_xdoors2_bottom_"..(3 - i)..".png", "locks_xdoors2_bottom_"..i..".png"},
paramtype = "light",
paramtype2 = "facedir",
drawtype = "nodebox",
drop = "locks:door",
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
node_box = {
type = "fixed",
fixed = door_bottom
},
selection_box = {
type = "fixed",
fixed = door_bottom
},
on_punch = xdoors2_transform,
after_dig_node = xdoors2_destruct,
on_construct = function(pos)
locks:lock_init( pos,
"size[8,2]"..
"field[0.3,0.6;6,0.7;locks_sent_lock_command;Locked door. Type /help for help:;]"..
"button_exit[6.3,0.2;1.7,0.7;locks_sent_input;Proceed]" );
end,
on_receive_fields = function(pos, formname, fields, sender)
locks:lock_handle_input( pos, formname, fields, sender );
end,
can_dig = function(pos,player)
return locks:lock_allow_dig( pos, player );
end
})
end
local delta = {
{x = -1, z = 0},
{x = 0, z = 1},
{x = 1, z = 0},
{x = 0, z = -1}
}
minetest.register_node("locks:door", {
description = "Shared locked Wooden Door",
node_placement_prediction = "",
inventory_image = 'locks_xdoors2_door.png',
wield_image = 'xdoors2_door.png',
stack_max = 1,
on_place = function(itemstack, placer, pointed_thing)
local above = pointed_thing.above
-- there should be 2 empty nodes
if minetest.env:get_node({x = above.x, y = above.y + 1, z = above.z}).name ~= "air" then
return itemstack
end
local fdir = 0
local placer_pos = placer:getpos()
if placer_pos then
dir = {
x = above.x - placer_pos.x,
y = above.y - placer_pos.y,
z = above.z - placer_pos.z
}
fdir = minetest.dir_to_facedir(dir)
end
local t = 1
local another_door = minetest.env:get_node({x = above.x + delta[fdir + 1].x, y = above.y, z = above.z + delta[fdir + 1].z})
if (another_door.name:sub(-1) == "1" and another_door.param2 == fdir)
or (another_door.name:sub(-1) == "2" and another_door.param2 == (fdir + 1) % 4) then
t = 2
end
minetest.env:add_node(above, {name = "locks:door_bottom_"..t, param2 = fdir})
minetest.env:add_node({x = above.x, y = above.y + 1, z = above.z}, {name = "locks:door_top_"..t, param2 = fdir})
-- store who owns the door; the other data can be default for now
locks:lock_set_owner( above, placer:get_player_name() or "", "Shared locked door");
locks:lock_set_owner( {x = above.x, y = above.y + 1, z = above.z}, placer:get_player_name() or "", "Shared locked door");
return ItemStack("")
end
})
-- if xdoors2 is installed
if( minetest.get_modpath("xdoors2") ~= nil ) then
minetest.register_craft({
output = 'locks:door',
recipe = {
{ 'xdoors2:door', 'locks:lock', '' },
},
});
-- if the normal doors are installed
else if( minetest.get_modpath("doors") ~= nil ) then
minetest.register_craft({
output = 'locks:door',
recipe = {
{ 'doors:door_wood', 'locks:lock', '' },
},
})
-- fallback if no doors can be found
else
minetest.register_craft({
output = 'locks:door',
recipe = {
{ 'default:wood', 'default:wood', '' },
{ 'default:wood', 'default:wood', 'locks:lock' },
{ 'default:wood', 'default:wood', '' },
},
});
end
end -- of previous else
print( "[Mod] locks: loading locks:door");

View File

@ -1,88 +0,0 @@
Licence for the following grafiks:
lock
key
keychain
author: addi
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
http://creativecommons.org/licenses/by-sa/3.0/
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
You are free:
to Share — to copy, distribute and transmit the work
to Remix — to adapt the work
Under the following conditions:
Attribution — You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work).
Share Alike — If you alter, transform, or build upon this work, you may distribute the resulting work only under the same or similar license to this one.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
License
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
1. Definitions
"Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License.
"Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(f) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined below) for the purposes of this License.
"Creative Commons Compatible License" means a license that is listed at http://creativecommons.org/compatiblelicenses that has been approved by Creative Commons as being essentially equivalent to this License, including, at a minimum, because that license: (i) contains terms that have the same purpose, meaning and effect as the License Elements of this License; and, (ii) explicitly permits the relicensing of adaptations of works made available under that license under this License or a Creative Commons jurisdiction license with the same License Elements as this License.
"Distribute" means to make available to the public the original and copies of the Work or Adaptation, as appropriate, through sale or other transfer of ownership.
"License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, ShareAlike.
"Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License.
"Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast.
"Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work.
"You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.
"Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images.
"Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium.
2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws.
3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:
to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections;
to create and Reproduce Adaptations provided that any such Adaptation, including any translation in any medium, takes reasonable steps to clearly label, demarcate or otherwise identify that changes were made to the original Work. For example, a translation could be marked "The original work was translated from English to Spanish," or a modification could indicate "The original work has been modified.";
to Distribute and Publicly Perform the Work including as incorporated in Collections; and,
to Distribute and Publicly Perform Adaptations.
For the avoidance of doubt:
Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License;
Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor waives the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; and,
Voluntary License Schemes. The Licensor waives the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License.
The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. Subject to Section 8(f), all rights not expressly granted by Licensor are hereby reserved.
4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:
You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(c), as requested. If You create an Adaptation, upon notice from any Licensor You must, to the extent practicable, remove from the Adaptation any credit as required by Section 4(c), as requested.
You may Distribute or Publicly Perform an Adaptation only under the terms of: (i) this License; (ii) a later version of this License with the same License Elements as this License; (iii) a Creative Commons jurisdiction license (either this or a later license version) that contains the same License Elements as this License (e.g., Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible License. If you license the Adaptation under one of the licenses mentioned in (iv), you must comply with the terms of that license. If you license the Adaptation under the terms of any of the licenses mentioned in (i), (ii) or (iii) (the "Applicable License"), you must comply with the terms of the Applicable License generally and the following provisions: (I) You must include a copy of, or the URI for, the Applicable License with every copy of each Adaptation You Distribute or Publicly Perform; (II) You may not offer or impose any terms on the Adaptation that restrict the terms of the Applicable License or the ability of the recipient of the Adaptation to exercise the rights granted to that recipient under the terms of the Applicable License; (III) You must keep intact all notices that refer to the Applicable License and to the disclaimer of warranties with every copy of the Work as included in the Adaptation You Distribute or Publicly Perform; (IV) when You Distribute or Publicly Perform the Adaptation, You may not impose any effective technological measures on the Adaptation that restrict the ability of a recipient of the Adaptation from You to exercise the rights granted to that recipient under the terms of the Applicable License. This Section 4(b) applies to the Adaptation as incorporated in a Collection, but this does not require the Collection apart from the Adaptation itself to be made subject to the terms of the Applicable License.
If You Distribute, or Publicly Perform the Work or any Adaptations or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and (iv) , consistent with Ssection 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the Adaptation (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). The credit required by this Section 4(c) may be implemented in any reasonable manner; provided, however, that in the case of a Adaptation or Collection, at a minimum such credit will appear, if a credit for all contributing authors of the Adaptation or Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties.
Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Adaptations or Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. Licensor agrees that in those jurisdictions (e.g. Japan), in which any exercise of the right granted in Section 3(b) of this License (the right to make Adaptations) would be deemed to be a distortion, mutilation, modification or other derogatory action prejudicial to the Original Author's honor and reputation, the Licensor will waive or not assert, as appropriate, this Section, to the fullest extent permitted by the applicable national law, to enable You to reasonably exercise Your right under Section 3(b) of this License (right to make Adaptations) but not otherwise.
5. Representations, Warranties and Disclaimer
UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
7. Termination
This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Adaptations or Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.
Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.
8. Miscellaneous
Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.
Each time You Distribute or Publicly Perform an Adaptation, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License.
If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.
This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.
The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 390 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 726 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 756 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 727 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 B

Some files were not shown because too many files have changed in this diff Show More