This commit is contained in:
HimbeerserverDE 2021-01-30 19:35:32 +01:00
commit a654db7684
22 changed files with 636 additions and 874 deletions

@ -3,12 +3,19 @@ local mod_doc = minetest.get_modpath("doc")
-- Chest Entity -- Chest Entity
local animate_chests = (minetest.settings:get_bool("animated_chests") ~= false) local animate_chests = (minetest.settings:get_bool("animated_chests") ~= false)
local entity_animation_speed = 25
local entity_animations = { local entity_animations = {
["open"] = {x = 0, y = 10}, shulker = {
["open_partly"] = {x = 0, y = 7}, speed = 50,
["close"] = {x = 10, y = 20}, open = {x = 45, y = 95},
["close_partly"] = {x = 13, y = 20}, close = {x = 95, y = 145},
},
chest = {
speed = 25,
open = {x = 0, y = 10},
open_partly = {x = 0, y = 7},
close = {x = 10, y = 20},
close_partly = {x = 13, y = 20},
}
} }
minetest.register_entity("mcl_chests:chest", { minetest.register_entity("mcl_chests:chest", {
@ -21,9 +28,10 @@ minetest.register_entity("mcl_chests:chest", {
}, },
set_animation = function(self, animname) set_animation = function(self, animname)
local anim = entity_animations[animname] local anim_table = entity_animations[self.animation_type]
local anim = anim_table[animname]
if not anim then return end if not anim then return end
self.object:set_animation(anim, entity_animation_speed, 0, false) self.object:set_animation(anim, anim_table.speed, 0, false)
end, end,
open = function(self, playername, partly) open = function(self, playername, partly)
@ -54,10 +62,11 @@ minetest.register_entity("mcl_chests:chest", {
end end
end, end,
initialize = function(self, node_pos, node_name, textures, dir, double, sound_prefix, mesh_prefix) initialize = function(self, node_pos, node_name, textures, dir, double, sound_prefix, mesh_prefix, animation_type)
self.node_pos = node_pos self.node_pos = node_pos
self.node_name = node_name self.node_name = node_name
self.sound_prefix = sound_prefix self.sound_prefix = sound_prefix
self.animation_type = animation_type
local obj = self.object local obj = self.object
obj:set_properties({ obj:set_properties({
textures = textures, textures = textures,
@ -117,19 +126,22 @@ local function find_entity(pos)
end end
end end
local function create_entity(pos, node_name, textures, param2, double, sound_prefix, mesh_prefix, dir, entity_pos) local function get_entity_info(pos, param2, double, dir, entity_pos)
dir = dir or minetest.facedir_to_dir(param2) dir = dir or minetest.facedir_to_dir(param2)
entity_pos = entity_pos or get_entity_pos(pos, dir, double) return dir, get_entity_pos(pos, dir, double)
end
local function create_entity(pos, node_name, textures, param2, double, sound_prefix, mesh_prefix, animation_type, dir, entity_pos)
dir, entity_pos = get_entity_info(pos, param2, double, dir, entity_pos)
local obj = minetest.add_entity(entity_pos, "mcl_chests:chest") local obj = minetest.add_entity(entity_pos, "mcl_chests:chest")
local luaentity = obj:get_luaentity() local luaentity = obj:get_luaentity()
luaentity:initialize(pos, node_name, textures, dir, double, sound_prefix, mesh_prefix) luaentity:initialize(pos, node_name, textures, dir, double, sound_prefix, mesh_prefix, animation_type)
return luaentity return luaentity
end end
local function find_or_create_entity(pos, node_name, textures, param2, double, sound_prefix, mesh_prefix, dir) local function find_or_create_entity(pos, node_name, textures, param2, double, sound_prefix, mesh_prefix, animation_type, dir, entity_pos)
local dir = dir or minetest.facedir_to_dir(param2) dir, entity_pos = get_entity_info(pos, param2, double, dir, entity_pos)
local entity_pos = get_entity_pos(pos, dir, double) return find_entity(entity_pos) or create_entity(pos, node_name, textures, param2, double, sound_prefix, mesh_prefix, animation_type, dir, entity_pos)
return find_entity(entity_pos) or create_entity(pos, node_name, textures, param2, double, sound_prefix, mesh_prefix, dir, entity_pos)
end end
local no_rotate, simple_rotate local no_rotate, simple_rotate
@ -139,7 +151,8 @@ if minetest.get_modpath("screwdriver") then
if screwdriver.rotate_simple(pos, node, user, mode, new_param2) ~= false then if screwdriver.rotate_simple(pos, node, user, mode, new_param2) ~= false then
local nodename = node.name local nodename = node.name
local nodedef = minetest.registered_nodes[nodename] local nodedef = minetest.registered_nodes[nodename]
find_or_create_entity(pos, nodename, nodedef._chest_entity_textures, new_param2, false, nodedef._chest_entity_sound, nodedef._chest_entity_mesh):set_yaw(minetest.facedir_to_dir(new_param2)) local dir = minetest.facedir_to_dir(new_param2)
find_or_create_entity(pos, nodename, nodedef._chest_entity_textures, new_param2, false, nodedef._chest_entity_sound, nodedef._chest_entity_mesh, nodedef._chest_entity_animation_type, dir):set_yaw(dir)
else else
return false return false
end end
@ -161,12 +174,13 @@ local function back_is_blocked(pos, dir)
return not def or def.groups.opaque == 1 or not def2 or def2.groups.opaque == 1 return not def or def.groups.opaque == 1 or not def2 or def2.groups.opaque == 1
end end
-- To be called if a player opened a chest -- To be called if a player opened a chest
local player_chest_open = function(player, pos, node_name, textures, param2, double, sound, mesh) local player_chest_open = function(player, pos, node_name, textures, param2, double, sound, mesh, shulker)
local name = player:get_player_name() local name = player:get_player_name()
open_chests[name] = {pos = pos, node_name = node_name, textures = textures, param2 = param2, double = double, sound = sound, mesh = mesh} open_chests[name] = {pos = pos, node_name = node_name, textures = textures, param2 = param2, double = double, sound = sound, mesh = mesh, shulker = shulker}
if animate_chests then if animate_chests then
local dir = minetest.facedir_to_dir(param2) local dir = minetest.facedir_to_dir(param2)
find_or_create_entity(pos, node_name, textures, param2, double, sound, mesh, dir):open(name, back_is_blocked(pos, dir) or double and back_is_blocked(mcl_util.get_double_container_neighbor_pos(pos, param2, node_name:sub(-4)), dir)) local blocked = not shulker and (back_is_blocked(pos, dir) or double and back_is_blocked(mcl_util.get_double_container_neighbor_pos(pos, param2, node_name:sub(-4)), dir))
find_or_create_entity(pos, node_name, textures, param2, double, sound, mesh, shulker and "shulker" or "chest", dir):open(name, blocked)
end end
end end
@ -198,11 +212,11 @@ local chest_update_after_close = function(pos)
if node.name == "mcl_chests:trapped_chest_on_small" then if node.name == "mcl_chests:trapped_chest_on_small" then
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_small", param2 = node.param2}) minetest.swap_node(pos, {name="mcl_chests:trapped_chest_small", param2 = node.param2})
find_or_create_entity(pos, "mcl_chests:trapped_chest_small", {"mcl_chests_trapped.png"}, node.param2, false, "default_chest", "mcl_chests_chest"):reinitialize("mcl_chests:trapped_chest_small") find_or_create_entity(pos, "mcl_chests:trapped_chest_small", {"mcl_chests_trapped.png"}, node.param2, false, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_small")
mesecon.receptor_off(pos, trapped_chest_mesecons_rules) mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
elseif node.name == "mcl_chests:trapped_chest_on_left" then elseif node.name == "mcl_chests:trapped_chest_on_left" then
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_left", param2 = node.param2}) minetest.swap_node(pos, {name="mcl_chests:trapped_chest_left", param2 = node.param2})
find_or_create_entity(pos, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest"):reinitialize("mcl_chests:trapped_chest_left") find_or_create_entity(pos, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
mesecon.receptor_off(pos, trapped_chest_mesecons_rules) mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left") local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left")
@ -214,7 +228,7 @@ local chest_update_after_close = function(pos)
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "right") local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "right")
minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_left", param2 = node.param2}) minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_left", param2 = node.param2})
find_or_create_entity(pos_other, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest"):reinitialize("mcl_chests:trapped_chest_left") find_or_create_entity(pos_other, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules) mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules)
end end
end end
@ -227,7 +241,7 @@ local player_chest_close = function(player)
return return
end end
if animate_chests then if animate_chests then
find_or_create_entity(open_chest.pos, open_chest.node_name, open_chest.textures, open_chest.param2, open_chest.double, open_chest.sound, open_chest.mesh):close(name) find_or_create_entity(open_chest.pos, open_chest.node_name, open_chest.textures, open_chest.param2, open_chest.double, open_chest.sound, open_chest.mesh, open_chest.shulker and "shulker" or "chest"):close(name)
end end
chest_update_after_close(open_chest.pos) chest_update_after_close(open_chest.pos)
@ -374,6 +388,7 @@ minetest.register_node(small_name, {
_chest_entity_textures = small_textures, _chest_entity_textures = small_textures,
_chest_entity_sound = "default_chest", _chest_entity_sound = "default_chest",
_chest_entity_mesh = "mcl_chests_chest", _chest_entity_mesh = "mcl_chests_chest",
_chest_entity_animation_type = "chest",
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
stack_max = 64, stack_max = 64,
@ -410,15 +425,15 @@ minetest.register_node(small_name, {
minetest.swap_node(pos, {name="mcl_chests:"..canonical_basename.."_right",param2=param2}) minetest.swap_node(pos, {name="mcl_chests:"..canonical_basename.."_right",param2=param2})
local p = mcl_util.get_double_container_neighbor_pos(pos, param2, "right") local p = mcl_util.get_double_container_neighbor_pos(pos, param2, "right")
minetest.swap_node(p, { name = "mcl_chests:"..canonical_basename.."_left", param2 = param2 }) minetest.swap_node(p, { name = "mcl_chests:"..canonical_basename.."_left", param2 = param2 })
create_entity(p, "mcl_chests:"..canonical_basename.."_left", left_textures, param2, true, "default_chest", "mcl_chests_chest") create_entity(p, "mcl_chests:"..canonical_basename.."_left", left_textures, param2, true, "default_chest", "mcl_chests_chest", "chest")
elseif minetest.get_node(mcl_util.get_double_container_neighbor_pos(pos, param2, "left")).name == "mcl_chests:"..canonical_basename.."_small" then elseif minetest.get_node(mcl_util.get_double_container_neighbor_pos(pos, param2, "left")).name == "mcl_chests:"..canonical_basename.."_small" then
minetest.swap_node(pos, {name="mcl_chests:"..canonical_basename.."_left",param2=param2}) minetest.swap_node(pos, {name="mcl_chests:"..canonical_basename.."_left",param2=param2})
create_entity(pos, "mcl_chests:"..canonical_basename.."_left", left_textures, param2, true, "default_chest", "mcl_chests_chest") create_entity(pos, "mcl_chests:"..canonical_basename.."_left", left_textures, param2, true, "default_chest", "mcl_chests_chest", "chest")
local p = mcl_util.get_double_container_neighbor_pos(pos, param2, "left") local p = mcl_util.get_double_container_neighbor_pos(pos, param2, "left")
minetest.swap_node(p, { name = "mcl_chests:"..canonical_basename.."_right", param2 = param2 }) minetest.swap_node(p, { name = "mcl_chests:"..canonical_basename.."_right", param2 = param2 })
else else
minetest.swap_node(pos, { name = "mcl_chests:"..canonical_basename.."_small", param2 = param2 }) minetest.swap_node(pos, { name = "mcl_chests:"..canonical_basename.."_small", param2 = param2 })
create_entity(pos, small_name, small_textures, param2, false, "default_chest", "mcl_chests_chest") create_entity(pos, small_name, small_textures, param2, false, "default_chest", "mcl_chests_chest", "chest")
end end
end, end,
after_place_node = function(pos, placer, itemstack, pointed_thing) after_place_node = function(pos, placer, itemstack, pointed_thing)
@ -498,6 +513,7 @@ minetest.register_node(left_name, {
_chest_entity_textures = left_textures, _chest_entity_textures = left_textures,
_chest_entity_sound = "default_chest", _chest_entity_sound = "default_chest",
_chest_entity_mesh = "mcl_chests_chest", _chest_entity_mesh = "mcl_chests_chest",
_chest_entity_animation_type = "chest",
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
groups = {handy=1,axey=1, container=5,not_in_creative_inventory=1, material_wood=1,flammable=-1,chest_entity=1,double_chest=1}, groups = {handy=1,axey=1, container=5,not_in_creative_inventory=1, material_wood=1,flammable=-1,chest_entity=1,double_chest=1},
@ -512,7 +528,7 @@ minetest.register_node(left_name, {
n.name = "mcl_chests:"..canonical_basename.."_small" n.name = "mcl_chests:"..canonical_basename.."_small"
minetest.swap_node(pos, n) minetest.swap_node(pos, n)
end end
create_entity(pos, left_name, left_textures, param2, true, "default_chest", "mcl_chests_chest") create_entity(pos, left_name, left_textures, param2, true, "default_chest", "mcl_chests_chest", "chest")
end, end,
after_place_node = function(pos, placer, itemstack, pointed_thing) after_place_node = function(pos, placer, itemstack, pointed_thing)
minetest.get_meta(pos):set_string("name", itemstack:get_meta():get_string("name")) minetest.get_meta(pos):set_string("name", itemstack:get_meta():get_string("name"))
@ -533,7 +549,7 @@ minetest.register_node(left_name, {
close_forms(canonical_basename, p) close_forms(canonical_basename, p)
minetest.swap_node(p, { name = small_name, param2 = param2 }) minetest.swap_node(p, { name = small_name, param2 = param2 })
create_entity(p, small_name, small_textures, param2, false, "default_chest", "mcl_chests_chest") create_entity(p, small_name, small_textures, param2, false, "default_chest", "mcl_chests_chest", "chest")
end, end,
after_dig_node = drop_items_chest, after_dig_node = drop_items_chest,
on_blast = on_chest_blast, on_blast = on_chest_blast,
@ -680,7 +696,7 @@ minetest.register_node("mcl_chests:"..basename.."_right", {
close_forms(canonical_basename, p) close_forms(canonical_basename, p)
minetest.swap_node(p, { name = small_name, param2 = param2 }) minetest.swap_node(p, { name = small_name, param2 = param2 })
create_entity(p, small_name, small_textures, param2, false, "default_chest", "mcl_chests_chest") create_entity(p, small_name, small_textures, param2, false, "default_chest", "mcl_chests_chest", "chest")
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
end, end,
after_dig_node = drop_items_chest, after_dig_node = drop_items_chest,
@ -845,7 +861,7 @@ register_chest("trapped_chest",
}}, }},
function(pos, node, clicker) function(pos, node, clicker)
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_on_small", param2 = node.param2}) minetest.swap_node(pos, {name="mcl_chests:trapped_chest_on_small", param2 = node.param2})
find_or_create_entity(pos, "mcl_chests:trapped_chest_on_small", {"mcl_chests_trapped.png"}, node.param2, false, "default_chest", "mcl_chests_chest"):reinitialize("mcl_chests:trapped_chest_on_small") find_or_create_entity(pos, "mcl_chests:trapped_chest_on_small", {"mcl_chests_trapped.png"}, node.param2, false, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_on_small")
mesecon.receptor_on(pos, trapped_chest_mesecons_rules) mesecon.receptor_on(pos, trapped_chest_mesecons_rules)
end, end,
function(pos, node, clicker) function(pos, node, clicker)
@ -853,7 +869,7 @@ register_chest("trapped_chest",
meta:set_int("players", 1) meta:set_int("players", 1)
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_on_left", param2 = node.param2}) minetest.swap_node(pos, {name="mcl_chests:trapped_chest_on_left", param2 = node.param2})
find_or_create_entity(pos, "mcl_chests:trapped_chest_on_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest"):reinitialize("mcl_chests:trapped_chest_on_left") find_or_create_entity(pos, "mcl_chests:trapped_chest_on_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_on_left")
mesecon.receptor_on(pos, trapped_chest_mesecons_rules) mesecon.receptor_on(pos, trapped_chest_mesecons_rules)
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left") local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left")
@ -867,7 +883,7 @@ register_chest("trapped_chest",
mesecon.receptor_on(pos, trapped_chest_mesecons_rules) mesecon.receptor_on(pos, trapped_chest_mesecons_rules)
minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_on_left", param2 = node.param2}) minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_on_left", param2 = node.param2})
find_or_create_entity(pos_other, "mcl_chests:trapped_chest_on_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest"):reinitialize("mcl_chests:trapped_chest_on_left") find_or_create_entity(pos_other, "mcl_chests:trapped_chest_on_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_on_left")
mesecon.receptor_on(pos_other, trapped_chest_mesecons_rules) mesecon.receptor_on(pos_other, trapped_chest_mesecons_rules)
end end
) )
@ -888,13 +904,13 @@ local function close_if_trapped_chest(pos, player)
if node.name == "mcl_chests:trapped_chest_on_small" then if node.name == "mcl_chests:trapped_chest_on_small" then
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_small", param2 = node.param2}) minetest.swap_node(pos, {name="mcl_chests:trapped_chest_small", param2 = node.param2})
find_or_create_entity(pos, "mcl_chests:trapped_chest_small", {"mcl_chests_trapped.png"}, node.param2, false, "default_chest", "mcl_chests_chest"):reinitialize("mcl_chests:trapped_chest_small") find_or_create_entity(pos, "mcl_chests:trapped_chest_small", {"mcl_chests_trapped.png"}, node.param2, false, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_small")
mesecon.receptor_off(pos, trapped_chest_mesecons_rules) mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
player_chest_close(player) player_chest_close(player)
elseif node.name == "mcl_chests:trapped_chest_on_left" then elseif node.name == "mcl_chests:trapped_chest_on_left" then
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_left", param2 = node.param2}) minetest.swap_node(pos, {name="mcl_chests:trapped_chest_left", param2 = node.param2})
find_or_create_entity(pos, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest"):reinitialize("mcl_chests:trapped_chest_left") find_or_create_entity(pos, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
mesecon.receptor_off(pos, trapped_chest_mesecons_rules) mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left") local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left")
@ -908,7 +924,7 @@ local function close_if_trapped_chest(pos, player)
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "right") local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "right")
minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_left", param2 = node.param2}) minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_left", param2 = node.param2})
find_or_create_entity(pos_other, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest"):reinitialize("mcl_chests:trapped_chest_left") find_or_create_entity(pos_other, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules) mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules)
player_chest_close(player) player_chest_close(player)
@ -995,6 +1011,7 @@ minetest.register_node("mcl_chests:ender_chest_small", {
_chest_entity_textures = {"mcl_chests_ender.png"}, _chest_entity_textures = {"mcl_chests_ender.png"},
_chest_entity_sound = "mcl_chests_enderchest", _chest_entity_sound = "mcl_chests_enderchest",
_chest_entity_mesh = "mcl_chests_chest", _chest_entity_mesh = "mcl_chests_chest",
_chest_entity_animation_type = "chest",
tiles = {"mcl_chests_blank.png"}, tiles = {"mcl_chests_blank.png"},
--[[{"mcl_chests_ender_chest_top.png", "mcl_chests_ender_chest_bottom.png", --[[{"mcl_chests_ender_chest_top.png", "mcl_chests_ender_chest_bottom.png",
"mcl_chests_ender_chest_right.png", "mcl_chests_ender_chest_left.png", "mcl_chests_ender_chest_right.png", "mcl_chests_ender_chest_left.png",
@ -1011,10 +1028,10 @@ minetest.register_node("mcl_chests:ender_chest_small", {
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
meta:set_string("formspec", formspec_ender_chest) meta:set_string("formspec", formspec_ender_chest)
create_entity(pos, "mcl_chests:ender_chest_small", {"mcl_chests_ender.png"}, minetest.get_node(pos).param2, false, "mcl_chests_enderchest", "mcl_chests_chest") create_entity(pos, "mcl_chests:ender_chest_small", {"mcl_chests_ender.png"}, minetest.get_node(pos).param2, false, "mcl_chests_enderchest", "mcl_chests_chest", "chest")
end, end,
on_rightclick = function(pos, node, clicker) on_rightclick = function(pos, node, clicker)
player_chest_open(clicker, pos, "mcl_chests:ender_chest_small", {"mcl_chests_ender.png"}, minetest.get_node(pos).param2, false, "mcl_chests_enderchest", "mcl_chests_chest") player_chest_open(clicker, pos, "mcl_chests:ender_chest_small", {"mcl_chests_ender.png"}, node.param2, false, "mcl_chests_enderchest", "mcl_chests_chest")
end, end,
on_receive_fields = function(pos, formname, fields, sender) on_receive_fields = function(pos, formname, fields, sender)
if fields.quit then if fields.quit then
@ -1027,16 +1044,6 @@ minetest.register_node("mcl_chests:ender_chest_small", {
on_rotate = simple_rotate, on_rotate = simple_rotate,
}) })
minetest.register_lbm({
label = "Update shulker box formspecs (0.51.0)",
name = "mcl_chests:update_formspecs_0_51_0",
nodenames = { "group:shulker_box" },
action = function(pos, node)
minetest.registered_nodes[node.name].on_construct(pos)
minetest.log("action", "[mcl_chests] Node formspec updated at "..minetest.pos_to_string(pos))
end,
})
minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)
local inv = player:get_inventory() local inv = player:get_inventory()
inv:set_size("enderchest", 9*3) inv:set_size("enderchest", 9*3)
@ -1129,6 +1136,8 @@ for color, desc in pairs(boxtypes) do
end end
end end
local small_name = "mcl_chests:"..color.."_shulker_box_small"
minetest.register_node("mcl_chests:"..color.."_shulker_box", { minetest.register_node("mcl_chests:"..color.."_shulker_box", {
description = desc, description = desc,
_tt_help = S("27 inventory slots") .. "\n" .. S("Can be carried around with its contents"), _tt_help = S("27 inventory slots") .. "\n" .. S("Can be carried around with its contents"),
@ -1136,43 +1145,26 @@ for color, desc in pairs(boxtypes) do
_doc_items_entry_name = entry_name, _doc_items_entry_name = entry_name,
_doc_items_longdesc = longdesc, _doc_items_longdesc = longdesc,
_doc_items_usagehelp = usagehelp, _doc_items_usagehelp = usagehelp,
tiles = { tiles = {mob_texture},
"mcl_chests_"..color.."_shulker_box_top.png", -- top drawtype = "mesh",
mesh = "mcl_chests_shulker.obj",
--[["mcl_chests_"..color.."_shulker_box_top.png", -- top
"[combine:16x16:-32,-28="..mob_texture, -- bottom "[combine:16x16:-32,-28="..mob_texture, -- bottom
"[combine:16x16:0,-36="..mob_texture..":0,-16="..mob_texture, -- side "[combine:16x16:0,-36="..mob_texture..":0,-16="..mob_texture, -- side
"[combine:16x16:-32,-36="..mob_texture..":-32,-16="..mob_texture, -- side "[combine:16x16:-32,-36="..mob_texture..":-32,-16="..mob_texture, -- side
"[combine:16x16:-16,-36="..mob_texture..":-16,-16="..mob_texture, -- side "[combine:16x16:-16,-36="..mob_texture..":-16,-16="..mob_texture, -- side
"[combine:16x16:-48,-36="..mob_texture..":-48,-16="..mob_texture, -- side "[combine:16x16:-48,-36="..mob_texture..":-48,-16="..mob_texture, -- side]]--
}, groups = {handy=1,pickaxey=1, container=3, deco_block=1, dig_by_piston=1, shulker_box=1, old_shulker_box_node=1},
groups = {handy=1,pickaxey=1, container=3, deco_block=1, dig_by_piston=1, shulker_box=1},
is_ground_content = false, is_ground_content = false,
sounds = mcl_sounds.node_sound_stone_defaults(), sounds = mcl_sounds.node_sound_stone_defaults(),
stack_max = 1, stack_max = 1,
drop = "", drop = "",
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
-- TODO: Make shulker boxes rotatable
-- This doesn't work, it just destroys the inventory:
-- on_place = minetest.rotate_node,
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.get_meta(pos) local node = minetest.get_node(pos)
meta:set_string("formspec", formspec_shulker_box(nil)) node.name = small_name
local inv = meta:get_inventory() minetest.set_node(pos, node)
inv:set_size("main", 9*3)
end,
_on_dispense = function(stack, pos, droppos, dropnode, dropdir)
-- Place shulker box as node
if minetest.registered_nodes[dropnode.name].buildable_to then
minetest.set_node(droppos, {name = stack:get_name(), param2 = minetest.dir_to_facedir(dropdir)})
local ninv = minetest.get_inventory({type="node", pos=droppos})
local imetadata = stack:get_metadata()
local iinv_main = minetest.deserialize(imetadata)
ninv:set_list("main", iinv_main)
ninv:set_size("main", 9*3)
set_shulkerbox_meta(minetest.get_meta(droppos), stack:get_meta())
stack:take_item()
end
return stack
end, end,
after_place_node = function(pos, placer, itemstack, pointed_thing) after_place_node = function(pos, placer, itemstack, pointed_thing)
local nmeta = minetest.get_meta(pos) local nmeta = minetest.get_meta(pos)
@ -1193,6 +1185,79 @@ for color, desc in pairs(boxtypes) do
return nil return nil
end end
end, end,
_on_dispense = function(stack, pos, droppos, dropnode, dropdir)
-- Place shulker box as node
if minetest.registered_nodes[dropnode.name].buildable_to then
minetest.set_node(droppos, {name = small_name, param2 = minetest.dir_to_facedir(dropdir)})
local ninv = minetest.get_inventory({type="node", pos=droppos})
local imetadata = stack:get_metadata()
local iinv_main = minetest.deserialize(imetadata)
ninv:set_list("main", iinv_main)
ninv:set_size("main", 9*3)
set_shulkerbox_meta(minetest.get_meta(droppos), stack:get_meta())
stack:take_item()
end
return stack
end,
})
minetest.register_node(small_name, {
description = desc,
_tt_help = S("27 inventory slots") .. "\n" .. S("Can be carried around with its contents"),
_doc_items_create_entry = create_entry,
_doc_items_entry_name = entry_name,
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usagehelp,
drawtype = "nodebox",
tiles = {"mcl_chests_blank.png"},
_chest_entity_textures = {mob_texture},
_chest_entity_sound = "mcl_chests_shulker",
_chest_entity_mesh = "mcl_chests_shulker",
_chest_entity_animation_type = "shulker",
groups = {handy=1,pickaxey=1, container=3, deco_block=1, dig_by_piston=1, shulker_box=1, chest_entity=1, not_in_creative_inventory=1},
is_ground_content = false,
sounds = mcl_sounds.node_sound_stone_defaults(),
stack_max = 1,
drop = "",
paramtype = "light",
paramtype2 = "facedir",
-- TODO: Make shulker boxes rotatable
-- This doesn't work, it just destroys the inventory:
-- on_place = minetest.rotate_node,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec", formspec_shulker_box(nil))
local inv = meta:get_inventory()
inv:set_size("main", 9*3)
create_entity(pos, small_name, {mob_texture}, minetest.get_node(pos).param2, false, "mcl_chests_shulker", "mcl_chests_shulker", "shulker")
end,
after_place_node = function(pos, placer, itemstack, pointed_thing)
local nmeta = minetest.get_meta(pos)
local imetadata = itemstack:get_metadata()
local iinv_main = minetest.deserialize(imetadata)
local ninv = nmeta:get_inventory()
ninv:set_list("main", iinv_main)
ninv:set_size("main", 9*3)
set_shulkerbox_meta(nmeta, itemstack:get_meta())
if minetest.is_creative_enabled(placer:get_player_name()) then
if not ninv:is_empty("main") then
return nil
else
return itemstack
end
else
return nil
end
end,
on_rightclick = function(pos, node, clicker)
player_chest_open(clicker, pos, small_name, {mob_texture}, node.param2, false, "mcl_chests_shulker", "mcl_chests_shulker", true)
end,
on_receive_fields = function(pos, formname, fields, sender)
if fields.quit then
player_chest_close(sender)
end
end,
on_destruct = function(pos) on_destruct = function(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local inv = meta:get_inventory() local inv = meta:get_inventory()
@ -1238,6 +1303,7 @@ for color, desc in pairs(boxtypes) do
if mod_doc and not is_canonical then if mod_doc and not is_canonical then
doc.add_entry_alias("nodes", "mcl_chests:"..canonical_shulker_color.."_shulker_box", "nodes", "mcl_chests:"..color.."_shulker_box") doc.add_entry_alias("nodes", "mcl_chests:"..canonical_shulker_color.."_shulker_box", "nodes", "mcl_chests:"..color.."_shulker_box")
doc.add_entry_alias("nodes", "mcl_chests:"..canonical_shulker_color.."_shulker_box_small", "nodes", "mcl_chests:"..color.."_shulker_box_small")
end end
minetest.register_craft({ minetest.register_craft({
@ -1282,7 +1348,7 @@ local function select_and_spawn_entity(pos, node)
local node_name = node.name local node_name = node.name
local node_def = minetest.registered_nodes[node_name] local node_def = minetest.registered_nodes[node_name]
local double_chest = minetest.get_item_group(node_name, "double_chest") > 0 local double_chest = minetest.get_item_group(node_name, "double_chest") > 0
create_entity(pos, node_name, node_def._chest_entity_textures, node.param2, double_chest, node_def._chest_entity_sound, node_def._chest_entity_mesh) create_entity(pos, node_name, node_def._chest_entity_textures, node.param2, double_chest, node_def._chest_entity_sound, node_def._chest_entity_mesh, node_def._chest_entity_animation_type)
end end
minetest.register_lbm({ minetest.register_lbm({
@ -1296,7 +1362,7 @@ minetest.register_lbm({
minetest.register_lbm({ minetest.register_lbm({
label = "Replace old chest nodes", label = "Replace old chest nodes",
name = "mcl_chests:replace_old", name = "mcl_chests:replace_old",
nodenames = {"mcl_chests:chest", "mcl_chests:trapped_chest", "mcl_chests:trapped_chest_on", "mcl_chests:ender_chest"}, nodenames = {"mcl_chests:chest", "mcl_chests:trapped_chest", "mcl_chests:trapped_chest_on", "mcl_chests:ender_chest", "group:old_shulker_box_node"},
run_at_every_load = true, run_at_every_load = true,
action = function(pos, node) action = function(pos, node)
local node_name = node.name local node_name = node.name

Binary file not shown.

@ -0,0 +1,159 @@
# Blender v2.79 (sub 0) OBJ File: 'shulkerbox2.blend'
# www.blender.org
mtllib shulkerbox2.mtl
o low1_Cube.006
v -0.500000 -0.500001 0.500000
v -0.500000 0.062499 0.500000
v -0.500000 -0.500001 -0.500000
v -0.500000 0.062499 -0.500000
v 0.500000 -0.500001 0.500000
v 0.500000 0.062499 0.500000
v 0.500000 -0.500001 -0.500000
v 0.500000 0.062499 -0.500000
vt 0.250000 0.187500
vt -0.000000 0.187500
vt -0.000000 0.312500
vt 0.250000 0.312500
vt 1.000000 0.187500
vt 0.750000 0.187500
vt 0.750000 0.312500
vt 1.000000 0.312500
vt 0.500000 0.187500
vt 0.500000 0.312500
vt 0.750000 0.562500
vt 0.750000 0.312500
vt 0.500000 0.312500
vt 0.500000 0.562500
vt 0.500000 0.562500
vt 0.250000 0.562500
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 1.0000 0.0000
vn 0.0000 -1.0000 0.0000
usemtl None
s off
f 1/1/1 3/2/1 4/3/1 2/4/1
f 3/5/2 7/6/2 8/7/2 4/8/2
f 7/6/3 5/9/3 6/10/3 8/7/3
f 5/9/4 1/1/4 2/4/4 6/10/4
f 3/11/5 1/12/5 5/13/5 7/14/5
f 8/15/6 6/10/6 2/4/6 4/16/6
o top1_Cube.005
v -0.500313 -0.220552 0.500313
v -0.500313 0.530073 0.500313
v -0.500313 -0.220552 -0.500313
v -0.500313 0.530073 -0.500313
v 0.500313 -0.220552 0.500313
v 0.500313 0.530073 0.500313
v 0.500313 -0.220552 -0.500313
v 0.500313 0.530073 -0.500313
vt 0.250000 0.562500
vt -0.000000 0.562500
vt -0.000000 0.750000
vt 0.250000 0.750000
vt 1.000000 0.562500
vt 0.750000 0.562500
vt 0.750000 0.750000
vt 1.000000 0.750000
vt 0.500000 0.562500
vt 0.500000 0.750000
vt 0.750000 1.000000
vt 0.750000 0.750000
vt 0.500000 0.750000
vt 0.500000 1.000000
vt 0.500000 1.000000
vt 0.250000 1.000000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 1.0000 0.0000
vn 0.0000 -1.0000 0.0000
usemtl None
s off
f 9/17/7 11/18/7 12/19/7 10/20/7
f 11/21/8 15/22/8 16/23/8 12/24/8
f 15/22/9 13/25/9 14/26/9 16/23/9
f 13/25/10 9/17/10 10/20/10 14/26/10
f 11/27/11 9/28/11 13/29/11 15/30/11
f 16/31/12 14/26/12 10/20/12 12/32/12
o top2_Cube.002
v -0.500247 -0.220392 0.500247
v -0.500247 0.530234 0.500247
v -0.500247 -0.220392 -0.500378
v -0.500247 0.530234 -0.500378
v 0.500378 -0.220392 0.500247
v 0.500378 0.530234 0.500247
v 0.500378 -0.220392 -0.500378
v 0.500378 0.530234 -0.500378
vt 0.250000 0.562500
vt 0.250000 0.750000
vt -0.000000 0.750000
vt -0.000000 0.562500
vt 1.000000 0.562500
vt 1.000000 0.750000
vt 0.750000 0.750000
vt 0.750000 0.562500
vt 0.500000 0.750000
vt 0.500000 0.562500
vt 0.750000 1.000000
vt 0.500000 1.000000
vt 0.500000 0.750000
vt 0.750000 0.750000
vt 0.500000 1.000000
vt 0.250000 1.000000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
usemtl None
s off
f 17/33/13 18/34/13 20/35/13 19/36/13
f 19/37/14 20/38/14 24/39/14 23/40/14
f 23/40/15 24/39/15 22/41/15 21/42/15
f 21/42/16 22/41/16 18/34/16 17/33/16
f 19/43/17 23/44/17 21/45/17 17/46/17
f 24/47/18 20/48/18 18/34/18 22/41/18
o low2_Cube.001
v -0.499935 -0.499936 0.499935
v -0.499935 0.062565 0.499935
v -0.499935 -0.499936 -0.500066
v -0.499935 0.062565 -0.500066
v 0.500066 -0.499936 0.499935
v 0.500066 0.062565 0.499935
v 0.500066 -0.499936 -0.500066
v 0.500066 0.062565 -0.500066
vt 0.250000 0.187500
vt 0.250000 0.312500
vt -0.000000 0.312500
vt -0.000000 0.187500
vt 1.000000 0.187500
vt 1.000000 0.312500
vt 0.750000 0.312500
vt 0.750000 0.187500
vt 0.500000 0.312500
vt 0.500000 0.187500
vt 0.750000 0.562500
vt 0.500000 0.562500
vt 0.500000 0.312500
vt 0.750000 0.312500
vt 0.500000 0.562500
vt 0.250000 0.562500
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
usemtl None
s off
f 25/49/19 26/50/19 28/51/19 27/52/19
f 27/53/20 28/54/20 32/55/20 31/56/20
f 31/56/21 32/55/21 30/57/21 29/58/21
f 29/58/22 30/57/22 26/50/22 25/49/22
f 27/59/23 31/60/23 29/61/23 25/62/23
f 32/63/24 28/64/24 26/50/24 30/57/24

@ -899,19 +899,41 @@ local treelight = 9
local sapling_grow_action = function(tree_id, soil_needed, one_by_one, two_by_two, sapling) local sapling_grow_action = function(tree_id, soil_needed, one_by_one, two_by_two, sapling)
return function(pos) return function(pos)
local meta = minetest.get_meta(pos)
if meta:get("grown") then return end
-- Checks if the sapling at pos has enough light and the correct soil -- Checks if the sapling at pos has enough light and the correct soil
local sapling_is_growable = function(pos)
local light = minetest.get_node_light(pos) local light = minetest.get_node_light(pos)
if not light then return end
local low_light = (light < treelight)
local delta = 1
local current_game_time = minetest.get_day_count() + minetest.get_timeofday()
local last_game_time = tonumber(meta:get_string("last_gametime"))
meta:set_string("last_gametime", tostring(current_game_time))
if last_game_time then
delta = current_game_time - last_game_time
elseif low_light then
return
end
if low_light then
if delta < 1.2 then return end
if minetest.get_node_light(pos, 0.5) < treelight then return end
end
-- TODO: delta is [days] missed in inactive area. Currently we just add it to stage, which is far from a perfect calculation...
local soilnode = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}) local soilnode = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z})
local soiltype = minetest.get_item_group(soilnode.name, "soil_sapling") local soiltype = minetest.get_item_group(soilnode.name, "soil_sapling")
return soiltype >= soil_needed and light and light >= treelight and not minetest.get_meta(pos):get("grown") if soiltype < soil_needed then return end
end
if sapling_is_growable(pos) then
-- Increase and check growth stage -- Increase and check growth stage
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local stage = meta:get_int("stage") local stage = meta:get_int("stage")
if stage == nil then stage = 0 end if stage == nil then stage = 0 end
stage = stage + 1 stage = stage + math.max(1, math.floor(delta))
if stage >= 3 then if stage >= 3 then
meta:set_string("grown", "true") meta:set_string("grown", "true")
-- This sapling grows in a special way when there are 4 saplings in a 2×2 pattern -- This sapling grows in a special way when there are 4 saplings in a 2×2 pattern
@ -968,7 +990,6 @@ local sapling_grow_action = function(tree_id, soil_needed, one_by_one, two_by_tw
return return
end end
end end
if one_by_one and tree_id == OAK_TREE_ID then if one_by_one and tree_id == OAK_TREE_ID then
-- There is a chance that this tree wants to grow as a balloon oak -- There is a chance that this tree wants to grow as a balloon oak
if math.random(1, 12) == 1 then if math.random(1, 12) == 1 then
@ -980,7 +1001,6 @@ local sapling_grow_action = function(tree_id, soil_needed, one_by_one, two_by_tw
end end
end end
end end
-- If this sapling can grow alone -- If this sapling can grow alone
if one_by_one and check_tree_growth(pos, tree_id) then if one_by_one and check_tree_growth(pos, tree_id) then
-- Single sapling -- Single sapling
@ -994,7 +1014,6 @@ local sapling_grow_action = function(tree_id, soil_needed, one_by_one, two_by_tw
end end
end end
end end
end
local grow_oak = sapling_grow_action(OAK_TREE_ID, 1, true, false) local grow_oak = sapling_grow_action(OAK_TREE_ID, 1, true, false)
local grow_dark_oak = sapling_grow_action(DARK_OAK_TREE_ID, 2, false, true, "mcl_core:darksapling") local grow_dark_oak = sapling_grow_action(DARK_OAK_TREE_ID, 2, false, true, "mcl_core:darksapling")
@ -1040,7 +1059,14 @@ minetest.register_abm({
neighbors = {"group:soil_sapling"}, neighbors = {"group:soil_sapling"},
interval = 25, interval = 25,
chance = 2, chance = 2,
action = grow_oak, action = grow_oak
})
minetest.register_lbm({
label = "Add growth for unloaded oak tree",
name = "mcl_core:lbm_oak",
nodenames = {"mcl_core:sapling"},
run_at_every_load = true,
action = grow_oak
}) })
-- Dark oak tree -- Dark oak tree
@ -1050,7 +1076,14 @@ minetest.register_abm({
neighbors = {"group:soil_sapling"}, neighbors = {"group:soil_sapling"},
interval = 25, interval = 25,
chance = 2, chance = 2,
action = grow_dark_oak, action = grow_dark_oak
})
minetest.register_lbm({
label = "Add growth for unloaded dark oak tree",
name = "mcl_core:lbm_dark_oak",
nodenames = {"mcl_core:darksapling"},
run_at_every_load = true,
action = grow_dark_oak
}) })
-- Jungle Tree -- Jungle Tree
@ -1060,7 +1093,14 @@ minetest.register_abm({
neighbors = {"group:soil_sapling"}, neighbors = {"group:soil_sapling"},
interval = 25, interval = 25,
chance = 2, chance = 2,
action = grow_jungle_tree, action = grow_jungle_tree
})
minetest.register_lbm({
label = "Add growth for unloaded jungle tree",
name = "mcl_core:lbm_jungle_tree",
nodenames = {"mcl_core:junglesapling"},
run_at_every_load = true,
action = grow_jungle_tree
}) })
-- Spruce tree -- Spruce tree
@ -1072,6 +1112,13 @@ minetest.register_abm({
chance = 2, chance = 2,
action = grow_spruce action = grow_spruce
}) })
minetest.register_lbm({
label = "Add growth for unloaded spruce tree",
name = "mcl_core:lbm_spruce",
nodenames = {"mcl_core:sprucesapling"},
run_at_every_load = true,
action = grow_spruce
})
-- Birch tree -- Birch tree
minetest.register_abm({ minetest.register_abm({
@ -1080,7 +1127,14 @@ minetest.register_abm({
neighbors = {"group:soil_sapling"}, neighbors = {"group:soil_sapling"},
interval = 25, interval = 25,
chance = 2, chance = 2,
action = grow_birch, action = grow_birch
})
minetest.register_lbm({
label = "Add growth for unloaded birch tree",
name = "mcl_core:lbm_birch",
nodenames = {"mcl_core:birchsapling"},
run_at_every_load = true,
action = grow_birch
}) })
-- Acacia tree -- Acacia tree
@ -1090,7 +1144,14 @@ minetest.register_abm({
neighbors = {"group:soil_sapling"}, neighbors = {"group:soil_sapling"},
interval = 20, interval = 20,
chance = 2, chance = 2,
action = grow_acacia, action = grow_acacia
})
minetest.register_lbm({
label = "Add growth for unloaded acacia tree",
name = "mcl_core:lbm_acacia",
nodenames = {"mcl_core:acaciasapling"},
run_at_every_load = true,
action = grow_acacia
}) })
local function leafdecay_particles(pos, node) local function leafdecay_particles(pos, node)

@ -61,8 +61,7 @@ function settlements.initialize_settlement_info(pr)
local count_buildings = {} local count_buildings = {}
-- count_buildings table reset -- count_buildings table reset
for k,v in pairs(schematic_table) do for k,v in pairs(settlements.schematic_table) do
-- local name = schematic_table[v]["name"]
count_buildings[v["name"]] = 0 count_buildings[v["name"]] = 0
end end
@ -74,96 +73,6 @@ function settlements.initialize_settlement_info(pr)
return count_buildings, number_of_buildings, number_built return count_buildings, number_of_buildings, number_built
end end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- fill settlement_info with LVM
--------------------------------------------------------------------------------
function settlements.create_site_plan_lvm(maxp, minp, pr)
local settlement_info = {}
local building_all_info
local possible_rotations = {"0", "90", "180", "270"}
-- find center of chunk
local center = {
x=maxp.x-half_map_chunk_size,
y=maxp.y,
z=maxp.z-half_map_chunk_size
}
-- find center_surface of chunk
local center_surface, surface_material = settlements.find_surface_lvm(center, minp)
-- go build settlement around center
if not center_surface then return false end
-- add settlement to list
table.insert(settlements_in_world, center_surface)
-- save list to file
settlements.save()
-- initialize all settlement_info table
local count_buildings, number_of_buildings, number_built = settlements.initialize_settlement_info(pr)
-- first building is townhall in the center
building_all_info = schematic_table[1]
local rotation = possible_rotations[ pr:next(1, #possible_rotations ) ]
-- add to settlement info table
local index = 1
settlement_info[index] = {
pos = center_surface,
name = building_all_info["name"],
hsize = building_all_info["hsize"],
rotat = rotation,
surface_mat = surface_material
}
-- increase index for following buildings
index = index + 1
-- now some buildings around in a circle, radius = size of town center
local x, z, r = center_surface.x, center_surface.z, building_all_info["hsize"]
-- draw j circles around center and increase radius by math.random(2,5)
for j = 1,20 do
if number_built < number_of_buildings then
-- set position on imaginary circle
for j = 0, 360, 15 do
local angle = j * math.pi / 180
local ptx, ptz = x + r * math.cos( angle ), z + r * math.sin( angle )
ptx = settlements.round(ptx, 0)
ptz = settlements.round(ptz, 0)
local pos1 = { x=ptx, y=center_surface.y+50, z=ptz}
local pos_surface, surface_material = settlements.find_surface_lvm(pos1, minp)
if not pos_surface then break end
local randomized_schematic_table = shuffle(schematic_table, pr)
-- pick schematic
local size = #randomized_schematic_table
for i = size, 1, -1 do
-- already enough buildings of that type?
if count_buildings[randomized_schematic_table[i]["name"]] < randomized_schematic_table[i]["max_num"]*number_of_buildings then
building_all_info = randomized_schematic_table[i]
-- check distance to other buildings
local distance_to_other_buildings_ok = settlements.check_distance(settlement_info, pos_surface, building_all_info["hsize"])
if distance_to_other_buildings_ok then
-- count built houses
count_buildings[building_all_info["name"]] = count_buildings[building_all_info["name"]] +1
rotation = possible_rotations[ pr:next(1, #possible_rotations ) ]
number_built = number_built + 1
settlement_info[index] = {
pos = pos_surface,
name = building_all_info["name"],
hsize = building_all_info["hsize"],
rotat = rotation,
surface_mat = surface_material
}
index = index + 1
break
end
end
end
if number_of_buildings == number_built then
break
end
end
r = r + pr:next(2,5)
end
end
settlements.debug("really ".. number_built)
return settlement_info
end
-------------------------------------------------------------------------------
-- fill settlement_info -- fill settlement_info
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
function settlements.create_site_plan(maxp, minp, pr) function settlements.create_site_plan(maxp, minp, pr)
@ -188,7 +97,7 @@ function settlements.create_site_plan(maxp, minp, pr)
-- initialize all settlement_info table -- initialize all settlement_info table
local count_buildings, number_of_buildings, number_built = settlements.initialize_settlement_info(pr) local count_buildings, number_of_buildings, number_built = settlements.initialize_settlement_info(pr)
-- first building is townhall in the center -- first building is townhall in the center
building_all_info = schematic_table[1] building_all_info = settlements.schematic_table[1]
local rotation = possible_rotations[ pr:next(1, #possible_rotations ) ] local rotation = possible_rotations[ pr:next(1, #possible_rotations ) ]
-- add to settlement info table -- add to settlement info table
local index = 1 local index = 1
@ -216,7 +125,7 @@ function settlements.create_site_plan(maxp, minp, pr)
local pos_surface, surface_material = settlements.find_surface(pos1) local pos_surface, surface_material = settlements.find_surface(pos1)
if not pos_surface then break end if not pos_surface then break end
local randomized_schematic_table = shuffle(schematic_table, pr) local randomized_schematic_table = shuffle(settlements.schematic_table, pr)
-- pick schematic -- pick schematic
local size = #randomized_schematic_table local size = #randomized_schematic_table
for i = size, 1, -1 do for i = size, 1, -1 do
@ -255,60 +164,10 @@ end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- evaluate settlement_info and place schematics -- evaluate settlement_info and place schematics
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
function settlements.place_schematics_lvm(settlement_info, pr)
for i, built_house in ipairs(settlement_info) do
for j, schem in ipairs(schematic_table) do
if settlement_info[i]["name"] == schem["name"] then
building_all_info = schem
break
end
end
local pos = settlement_info[i]["pos"]
local rotation = settlement_info[i]["rotat"]
-- get building node material for better integration to surrounding
local platform_material = settlement_info[i]["surface_mat"]
platform_material_name = minetest.get_name_from_content_id(platform_material)
-- pick random material
local material = wallmaterial[pr:next(1,#wallmaterial)]
--
local building = building_all_info["mts"]
local replace_wall = building_all_info["rplc"]
-- schematic conversion to lua
local schem_lua = minetest.serialize_schematic(building,
"lua",
{lua_use_comments = false, lua_num_indent_spaces = 0}).." return(schematic)"
-- replace material
if replace_wall == "y" then
schem_lua = schem_lua:gsub("mcl_core:cobble", material)
end
schem_lua = schem_lua:gsub("mcl_core:dirt_with_grass", platform_material_name)
--[[ Disable special junglewood for now.
-- special material for spawning npcs
schem_lua = schem_lua:gsub("mcl_core:junglewood", "settlements:junglewood")
--]]
-- format schematic string
local schematic = loadstring(schem_lua)()
-- build foundation for the building an make room above
-- place schematic
minetest.place_schematic_on_vmanip(
vm,
pos,
schematic,
rotation,
nil,
true)
end
end
-------------------------------------------------------------------------------
-- evaluate settlement_info and place schematics
-------------------------------------------------------------------------------
function settlements.place_schematics(settlement_info, pr) function settlements.place_schematics(settlement_info, pr)
local building_all_info local building_all_info
for i, built_house in ipairs(settlement_info) do for i, built_house in ipairs(settlement_info) do
for j, schem in ipairs(schematic_table) do for j, schem in ipairs(settlements.schematic_table) do
if settlement_info[i]["name"] == schem["name"] then if settlement_info[i]["name"] == schem["name"] then
building_all_info = schem building_all_info = schem
break break
@ -321,7 +180,7 @@ function settlements.place_schematics(settlement_info, pr)
local platform_material = settlement_info[i]["surface_mat"] local platform_material = settlement_info[i]["surface_mat"]
--platform_material_name = minetest.get_name_from_content_id(platform_material) --platform_material_name = minetest.get_name_from_content_id(platform_material)
-- pick random material -- pick random material
local material = wallmaterial[pr:next(1,#wallmaterial)] --local material = wallmaterial[pr:next(1,#wallmaterial)]
-- --
local building = building_all_info["mts"] local building = building_all_info["mts"]
local replace_wall = building_all_info["rplc"] local replace_wall = building_all_info["rplc"]
@ -330,8 +189,28 @@ function settlements.place_schematics(settlement_info, pr)
"lua", "lua",
{lua_use_comments = false, lua_num_indent_spaces = 0}).." return(schematic)" {lua_use_comments = false, lua_num_indent_spaces = 0}).." return(schematic)"
-- replace material -- replace material
if replace_wall == "y" then if replace_wall then
schem_lua = schem_lua:gsub("mcl_core:cobble", material) --Note, block substitution isn't matching node names exactly; so nodes that are to be substituted that have the same prefixes cause bugs.
-- Example: Attempting to swap out 'mcl_core:stonebrick'; which has multiple, additional sub-variants: (carved, cracked, mossy). Will currently cause issues, so leaving disabled.
if platform_material == "mcl_core:snow" or platform_material == "mcl_core:dirt_with_grass_snow" or platform_material == "mcl_core:podzol" then
schem_lua = schem_lua:gsub("mcl_core:tree", "mcl_core:sprucetree")
schem_lua = schem_lua:gsub("mcl_core:wood", "mcl_core:sprucewood")
--schem_lua = schem_lua:gsub("mcl_fences:fence", "mcl_fences:spruce_fence")
--schem_lua = schem_lua:gsub("mcl_stairs:slab_wood_top", "mcl_stairs:slab_sprucewood_top")
--schem_lua = schem_lua:gsub("mcl_stairs:stair_wood", "mcl_stairs:stair_sprucewood")
--schem_lua = schem_lua:gsub("mesecons_pressureplates:pressure_plate_wood_off", "mesecons_pressureplates:pressure_plate_sprucewood_off")
elseif platform_material == "mcl_core:sand" or platform_material == "mcl_core:redsand" then
schem_lua = schem_lua:gsub("mcl_core:tree", "mcl_core:sandstonecarved")
schem_lua = schem_lua:gsub("mcl_core:cobble", "mcl_core:sandstone")
schem_lua = schem_lua:gsub("mcl_core:wood", "mcl_core:sandstonesmooth")
--schem_lua = schem_lua:gsub("mcl_fences:fence", "mcl_fences:birch_fence")
--schem_lua = schem_lua:gsub("mcl_stairs:slab_wood_top", "mcl_stairs:slab_birchwood_top")
--schem_lua = schem_lua:gsub("mcl_stairs:stair_wood", "mcl_stairs:stair_birchwood")
--schem_lua = schem_lua:gsub("mesecons_pressureplates:pressure_plate_wood_off", "mesecons_pressureplates:pressure_plate_birchwood_off")
--schem_lua = schem_lua:gsub("mcl_stairs:stair_stonebrick", "mcl_stairs:stair_redsandstone")
--schem_lua = schem_lua:gsub("mcl_core:stonebrick", "mcl_core:redsandstonesmooth")
schem_lua = schem_lua:gsub("mcl_core:brick_block", "mcl_core:redsandstone")
end
end end
schem_lua = schem_lua:gsub("mcl_core:dirt_with_grass", platform_material) schem_lua = schem_lua:gsub("mcl_core:dirt_with_grass", platform_material)

@ -5,11 +5,7 @@ settlements.debug = function(message)
minetest.log("verbose", "[mcl_villages] "..message) minetest.log("verbose", "[mcl_villages] "..message)
end end
-- switch for lvm --[[ Manually set in 'buildings.lua'
settlements.lvm = false
settlements.last_settlement = os.time()
-- material to replace cobblestone with -- material to replace cobblestone with
wallmaterial = { wallmaterial = {
"mcl_core:junglewood", "mcl_core:junglewood",
@ -23,6 +19,7 @@ wallmaterial = {
"mcl_core:sandstone", "mcl_core:sandstone",
"mcl_core:sandstonesmooth2" "mcl_core:sandstonesmooth2"
} }
--]]
settlements.surface_mat = {} settlements.surface_mat = {}
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- Set array to list -- Set array to list
@ -38,7 +35,7 @@ function settlements.grundstellungen()
"mcl_core:sand", "mcl_core:sand",
"mcl_core:redsand", "mcl_core:redsand",
--"mcl_core:silver_sand", --"mcl_core:silver_sand",
"mcl_core:snowblock" "mcl_core:snow"
} }
end end
-- --
@ -52,27 +49,27 @@ schem_path = settlements.modpath.."/schematics/"
-- --
-- list of schematics -- list of schematics
-- --
schematic_table = { local basic_pseudobiome_villages = minetest.settings:get_bool("basic_pseudobiome_villages", false)
{name = "large_house", mts = schem_path.."large_house.mts", hwidth = 11, hdepth = 12, hheight = 9, hsize = 14, max_num = 0.08, rplc = "n"},
{name = "blacksmith", mts = schem_path.."blacksmith.mts", hwidth = 7, hdepth = 7, hheight = 13, hsize = 13, max_num = 0.055, rplc = "n"}, settlements.schematic_table = {
{name = "butcher", mts = schem_path.."butcher.mts", hwidth = 11, hdepth = 8, hheight = 10, hsize = 14, max_num = 0.03, rplc = "n"}, {name = "large_house", mts = schem_path.."large_house.mts", hwidth = 11, hdepth = 12, hheight = 9, hsize = 14, max_num = 0.08 , rplc = basic_pseudobiome_villages },
{name = "church", mts = schem_path.."church.mts", hwidth = 13, hdepth = 13, hheight = 14, hsize = 15, max_num = 0.04, rplc = "n"}, {name = "blacksmith", mts = schem_path.."blacksmith.mts", hwidth = 7, hdepth = 7, hheight = 13, hsize = 13, max_num = 0.055, rplc = basic_pseudobiome_villages },
{name = "farm", mts = schem_path.."farm.mts", hwidth = 7, hdepth = 7, hheight = 13, hsize = 13, max_num = 0.1, rplc = "n"}, {name = "butcher", mts = schem_path.."butcher.mts", hwidth = 11, hdepth = 8, hheight = 10, hsize = 14, max_num = 0.03 , rplc = basic_pseudobiome_villages },
{name = "lamp", mts = schem_path.."lamp.mts", hwidth = 3, hdepth = 3, hheight = 13, hsize = 10, max_num = 0.1, rplc = "n"}, {name = "church", mts = schem_path.."church.mts", hwidth = 13, hdepth = 13, hheight = 14, hsize = 15, max_num = 0.04 , rplc = basic_pseudobiome_villages },
{name = "library", mts = schem_path.."library.mts", hwidth = 12, hdepth = 12, hheight = 8, hsize = 13, max_num = 0.04, rplc = "n"}, {name = "farm", mts = schem_path.."farm.mts", hwidth = 7, hdepth = 7, hheight = 13, hsize = 13, max_num = 0.1 , rplc = basic_pseudobiome_villages },
{name = "medium_house", mts = schem_path.."medium_house.mts", hwidth = 8, hdepth = 12, hheight = 8, hsize = 14, max_num = 0.08, rplc = "n"}, {name = "lamp", mts = schem_path.."lamp.mts", hwidth = 3, hdepth = 3, hheight = 13, hsize = 10, max_num = 0.1 , rplc = false },
{name = "small_house", mts = schem_path.."small_house.mts", hwidth = 9, hdepth = 7, hheight = 8, hsize = 13, max_num = 0.7, rplc = "n"}, {name = "library", mts = schem_path.."library.mts", hwidth = 12, hdepth = 12, hheight = 8, hsize = 13, max_num = 0.04 , rplc = basic_pseudobiome_villages },
{name = "tavern", mts = schem_path.."tavern.mts", hwidth = 11, hdepth = 10, hheight = 10, hsize = 13, max_num = 0.050, rplc = "n"}, {name = "medium_house", mts = schem_path.."medium_house.mts", hwidth = 8, hdepth = 12, hheight = 8, hsize = 14, max_num = 0.08 , rplc = basic_pseudobiome_villages },
{name = "well", mts = schem_path.."well.mts", hwidth = 6, hdepth = 8, hheight = 6, hsize = 10, max_num = 0.045, rplc = "n"}, {name = "small_house", mts = schem_path.."small_house.mts", hwidth = 9, hdepth = 7, hheight = 8, hsize = 13, max_num = 0.7 , rplc = basic_pseudobiome_villages },
{name = "tavern", mts = schem_path.."tavern.mts", hwidth = 11, hdepth = 10, hheight = 10, hsize = 13, max_num = 0.050, rplc = basic_pseudobiome_villages },
{name = "well", mts = schem_path.."well.mts", hwidth = 6, hdepth = 8, hheight = 6, hsize = 10, max_num = 0.045, rplc = basic_pseudobiome_villages },
} }
-- --
-- list of settlements, load on server start up -- list of settlements, load on server start up
-- --
settlements_in_world = {} settlements_in_world = {}
-- --
-- min_distance between settlements
--
settlements.min_dist_settlements = 64
-- --
-- maximum allowed difference in height for building a sttlement -- maximum allowed difference in height for building a sttlement
-- --

@ -10,7 +10,6 @@ print(dump(schematic))
end end
function settlements.mts_save() function settlements.mts_save()
local f = assert(io.open(schem_path.."hut.lua", "r")) local f = assert(io.open(schem_path.."hut.lua", "r"))
local content = f:read("*all").." return(schematic2)" local content = f:read("*all").." return(schematic2)"

@ -1,28 +1,6 @@
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- function to fill empty space below baseplate when building on a hill -- function to fill empty space below baseplate when building on a hill
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
function settlements.ground_lvm(pos, pr) -- role model: Wendelsteinkircherl, Brannenburg
local c_dirt = minetest.get_content_id("mcl_core:dirt")
local c_stone = minetest.get_content_id("mcl_core:stone")
--
local p2 = vector.new(pos)
local cnt = 0
local mat = c_dirt
p2.y = p2.y-1
while true do
cnt = cnt+1
if cnt > 20 then break end
if cnt>pr:next(2,4) then mat = c_stone end
--minetest.swap_node(p2, {name="mcl_core:"..mat})
local vi = va:index(p2.x, p2.y, p2.z)
data[vi] = mat
p2.y = p2.y-1
end
-- return data
end
-------------------------------------------------------------------------------
-- function to fill empty space below baseplate when building on a hill
-------------------------------------------------------------------------------
function settlements.ground(pos, pr) -- role model: Wendelsteinkircherl, Brannenburg function settlements.ground(pos, pr) -- role model: Wendelsteinkircherl, Brannenburg
local p2 = vector.new(pos) local p2 = vector.new(pos)
local cnt = 0 local cnt = 0
@ -41,81 +19,19 @@ end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- function clear space above baseplate -- function clear space above baseplate
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
function settlements.terraform_lvm(settlement_info, pr)
local c_air = minetest.get_content_id("air")
local fheight
local fwidth
local fdepth
for i, built_house in ipairs(settlement_info) do
-- pick right schematic_info to current built_house
for j, schem in ipairs(schematic_table) do
if settlement_info[i]["name"] == schem["name"]
then
schematic_data = schem
break
end
end
local pos = settlement_info[i]["pos"]
if settlement_info[i]["rotat"] == "0" or settlement_info[i]["rotat"] == "180"
then
fwidth = schematic_data["hwidth"]
fdepth = schematic_data["hdepth"]
else
fwidth = schematic_data["hdepth"]
fdepth = schematic_data["hwidth"]
end
fheight = schematic_data["hheight"] * 3 -- remove trees and leaves above
--
-- now that every info is available -> create platform and clear space above
--
for zi = 0,fdepth-1 do
for yi = 0,fheight do
for xi = 0,fwidth-1 do
if yi == 0 then
local p = {x=pos.x+xi, y=pos.y, z=pos.z+zi}
settlements.ground_lvm(p, pr)
else
--break --todo
-- write ground
local vi = va:index(pos.x+xi, pos.y+yi, pos.z+zi)
if data[vi] ~= c_air
--local node = minetest.get_node_or_nil({x=p5.x+xi, y=p5.y+yi, z=p5.z+zi})
--if node then
--if node.name ~= "air"
then
--minetest.swap_node({x=pos.x+xi, y=pos.y+yi, z=pos.z+zi},{name="air"})
data[vi] = c_air
end
end
end
end
end
end
end
-------------------------------------------------------------------------------
-- function clear space above baseplate
-------------------------------------------------------------------------------
function settlements.terraform(settlement_info, pr) function settlements.terraform(settlement_info, pr)
local fheight local fheight, fwidth, fdepth, schematic_data
local fwidth
local fdepth
local schematic_data
for i, built_house in ipairs(settlement_info) do for i, built_house in ipairs(settlement_info) do
-- pick right schematic_info to current built_house -- pick right schematic_info to current built_house
for j, schem in ipairs(schematic_table) do for j, schem in ipairs(settlements.schematic_table) do
if settlement_info[i]["name"] == schem["name"] if settlement_info[i]["name"] == schem["name"] then
then
schematic_data = schem schematic_data = schem
break break
end end
end end
local pos = settlement_info[i]["pos"] local pos = settlement_info[i]["pos"]
if settlement_info[i]["rotat"] == "0" or settlement_info[i]["rotat"] == "180" if settlement_info[i]["rotat"] == "0" or settlement_info[i]["rotat"] == "180" then
then
fwidth = schematic_data["hwidth"] fwidth = schematic_data["hwidth"]
fdepth = schematic_data["hdepth"] fdepth = schematic_data["hdepth"]
else else
@ -138,9 +54,7 @@ function settlements.terraform(settlement_info, pr)
local p = {x=pos.x+xi, y=pos.y+yi, z=pos.z+zi} local p = {x=pos.x+xi, y=pos.y+yi, z=pos.z+zi}
minetest.forceload_block(p) minetest.forceload_block(p)
local node = minetest.get_node_or_nil(p) local node = minetest.get_node_or_nil(p)
if node then if node and node.name ~= "air" then
if node.name ~= "air"
then
minetest.swap_node(p,{name="air"}) minetest.swap_node(p,{name="air"})
end end
end end
@ -148,6 +62,4 @@ function settlements.terraform(settlement_info, pr)
end end
end end
end end
end
end end

@ -1,20 +1,12 @@
-- eclipse debugging lines
--require("debugger")(idehost, ideport, idekey)
--zerobrane debugging lines
--package.cpath = package.cpath .. ";/usr/share/lua/5.2/?.so"
--package.path = package.path .. ";/usr/share/zbstudio/lualibs/mobdebug/?.lua"
--require('mobdebug').start()
settlements = {} settlements = {}
settlements.modpath = minetest.get_modpath("mcl_villages"); settlements.modpath = minetest.get_modpath("mcl_villages")
dofile(settlements.modpath.."/const.lua") dofile(settlements.modpath.."/const.lua")
dofile(settlements.modpath.."/utils.lua") dofile(settlements.modpath.."/utils.lua")
dofile(settlements.modpath.."/foundation.lua") dofile(settlements.modpath.."/foundation.lua")
dofile(settlements.modpath.."/buildings.lua") dofile(settlements.modpath.."/buildings.lua")
dofile(settlements.modpath.."/paths.lua") dofile(settlements.modpath.."/paths.lua")
dofile(settlements.modpath.."/convert_lua_mts.lua") --dofile(settlements.modpath.."/convert_lua_mts.lua")
-- --
-- load settlements on server -- load settlements on server
-- --
@ -55,42 +47,20 @@ end
-- on map generation, try to build a settlement -- on map generation, try to build a settlement
-- --
local function build_a_settlement_no_delay(minp, maxp, blockseed) local function build_a_settlement_no_delay(minp, maxp, blockseed)
local settlement_info
local pr = PseudoRandom(blockseed) local pr = PseudoRandom(blockseed)
--
-- fill settlement_info with buildings and their data -- fill settlement_info with buildings and their data
-- local settlement_info = settlements.create_site_plan(maxp, minp, pr)
if settlements.lvm == true then
-- get LVM of current chunk
local vm, data, va, emin, emax = settlements.getlvm(minp, maxp)
settlement_info = settlements.create_site_plan_lvm(maxp, minp, pr)
else
settlement_info = settlements.create_site_plan(maxp, minp, pr)
end
if not settlement_info then return end if not settlement_info then return end
-- evaluate settlement_info and prepair terrain -- evaluate settlement_info and prepair terrain
if settlements.lvm == true then
settlements.terraform_lvm(settlement_info, pr)
else
settlements.terraform(settlement_info, pr) settlements.terraform(settlement_info, pr)
end
-- evaluate settlement_info and build paths between buildings -- evaluate settlement_info and build paths between buildings
if settlements.lvm == true then
settlements.paths_lvm(settlement_info, minp)
else
settlements.paths(settlement_info) settlements.paths(settlement_info)
end
-- evaluate settlement_info and place schematics -- evaluate settlement_info and place schematics
if settlements.lvm == true then
vm:set_data(data)
settlements.place_schematics_lvm(settlement_info, pr)
vm:write_to_map(true)
else
settlements.place_schematics(settlement_info, pr) settlements.place_schematics(settlement_info, pr)
end
-- evaluate settlement_info and initialize furnaces and chests -- evaluate settlement_info and initialize furnaces and chests
settlements.initialize_nodes(settlement_info, pr) settlements.initialize_nodes(settlement_info, pr)
@ -112,126 +82,27 @@ minetest.register_on_generated(function(minp, maxp, blockseed)
-- don't build settlement underground -- don't build settlement underground
if maxp.y < 0 then return end if maxp.y < 0 then return end
-- don't build settlements too close to each other
--[[
local center_of_chunk = {
x=maxp.x-half_map_chunk_size,
y=maxp.y-half_map_chunk_size,
z=maxp.z-half_map_chunk_size
}
local dist_ok = settlements.check_distance_other_settlements(center_of_chunk)
if dist_ok == false then return end
]]
-- don't build settlements on (too) uneven terrain -- don't build settlements on (too) uneven terrain
local height_difference = settlements.evaluate_heightmap(minp, maxp) local height_difference = settlements.evaluate_heightmap(minp, maxp)
if height_difference > max_height_difference then return end if height_difference > max_height_difference then return end
-- new way - slow :(((((
minetest.emerge_area(vector.subtract(minp,24), vector.add(maxp,24), ecb_build_a_settlement, {minp = vector.new(minp), maxp=vector.new(maxp), blockseed=blockseed}) minetest.emerge_area(vector.subtract(minp,24), vector.add(maxp,24), ecb_build_a_settlement, {minp = vector.new(minp), maxp=vector.new(maxp), blockseed=blockseed})
-- old way - wait 3 seconds: -- old way - wait 3 seconds:
-- minetest.after(3, ecb_build_a_settlement, nil, 1, 0, {minp = vector.new(minp), maxp=vector.new(maxp), blockseed=blockseed}) -- minetest.after(3, ecb_build_a_settlement, nil, 1, 0, {minp = vector.new(minp), maxp=vector.new(maxp), blockseed=blockseed})
end) end)
-- -- manually place villages
-- manually place buildings, for debugging only if minetest.is_creative_enabled("") then
--
minetest.register_craftitem("mcl_villages:tool", { minetest.register_craftitem("mcl_villages:tool", {
description = "mcl_villages build tool", description = "mcl_villages build tool",
inventory_image = "default_tool_woodshovel.png", inventory_image = "default_tool_woodshovel.png",
--[[ Disable on_use for now.
-- build single house
--
on_use = function(itemstack, placer, pointed_thing)
local center_surface = pointed_thing.under
if center_surface then
local building_all_info = {name = "blacksmith",
mts = schem_path.."blacksmith.mts",
hsize = 13,
max_num = 0.9,
rplc = "n"}
settlements.build_schematic(center_surface,
building_all_info["mts"],
building_all_info["rplc"],
building_all_info["name"])
-- settlements.convert_mts_to_lua()
-- settlements.mts_save()
end
end,
--]]
--
-- build ssettlement -- build ssettlement
--
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
local pr = PseudoRandom(math.random(0,32767)) if not pointed_thing.under then return end
-- enable debug routines local minp = vector.subtract( pointed_thing.under, half_map_chunk_size)
local center_surface = pointed_thing.under local maxp = vector.add( pointed_thing.under, half_map_chunk_size)
if center_surface then build_a_settlement_no_delay(minp, maxp, math.random(0,32767))
local minp = {
x=center_surface.x-half_map_chunk_size,
y=center_surface.y-half_map_chunk_size,
z=center_surface.z-half_map_chunk_size
}
local maxp = {
x=center_surface.x+half_map_chunk_size,
y=center_surface.y+half_map_chunk_size,
z=center_surface.z+half_map_chunk_size
}
--
-- get LVM of current chunk
--
local vm, data, va, emin, emax = settlements.getlvm(minp, maxp)
--
-- fill settlement_info with buildings and their data
--
local start_time = os.time()
local settlement_info
if settlements.lvm == true then
settlement_info = settlements.create_site_plan_lvm(maxp, minp, pr)
else
settlement_info = settlements.create_site_plan(maxp, minp, pr)
end
if not settlement_info then return end
--
-- evaluate settlement_info and prepair terrain
--
if settlements.lvm == true then
settlements.terraform_lvm(settlement_info, pr)
else
settlements.terraform(settlement_info, pr)
end
--
-- evaluate settlement_info and build paths between buildings
--
if settlements.lvm == true then
settlements.paths_lvm(settlement_info, minp)
else
settlements.paths(settlement_info)
end
--
-- evaluate settlement_info and place schematics
--
if settlements.lvm == true then
vm:set_data(data)
settlements.place_schematics_lvm(settlement_info, pr)
vm:write_to_map(true)
else
settlements.place_schematics(settlement_info, pr)
end
--
-- evaluate settlement_info and initialize furnaces and chests
--
settlements.initialize_nodes(settlement_info, pr)
local end_time = os.time()
minetest.chat_send_all("Time ".. end_time - start_time)
--
--settlements.convert_mts_to_lua()
--settlements.mts_save()
end
end end
}) })
end

@ -1,99 +1,6 @@
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- generate paths between buildings -- generate paths between buildings
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
function settlements.paths_lvm(settlement_info, minp)
local c_grasspath = minetest.get_content_id("mcl_core:grass_path")
local starting_point
local end_point
local distance
--for k,v in pairs(settlement_info) do
starting_point = settlement_info[1]["pos"]
for o,p in pairs(settlement_info) do
end_point = settlement_info[o]["pos"]
if starting_point ~= end_point
then
-- loop until end_point is reched (distance == 0)
while true do
-- define surrounding pos to starting_point
local north_p = {x=starting_point.x+1, y=starting_point.y, z=starting_point.z}
local south_p = {x=starting_point.x-1, y=starting_point.y, z=starting_point.z}
local west_p = {x=starting_point.x, y=starting_point.y, z=starting_point.z+1}
local east_p = {x=starting_point.x, y=starting_point.y, z=starting_point.z-1}
-- measure distance to end_point
local dist_north_p_to_end = math.sqrt(
((north_p.x - end_point.x)*(north_p.x - end_point.x))+
((north_p.z - end_point.z)*(north_p.z - end_point.z))
)
local dist_south_p_to_end = math.sqrt(
((south_p.x - end_point.x)*(south_p.x - end_point.x))+
((south_p.z - end_point.z)*(south_p.z - end_point.z))
)
local dist_west_p_to_end = math.sqrt(
((west_p.x - end_point.x)*(west_p.x - end_point.x))+
((west_p.z - end_point.z)*(west_p.z - end_point.z))
)
local dist_east_p_to_end = math.sqrt(
((east_p.x - end_point.x)*(east_p.x - end_point.x))+
((east_p.z - end_point.z)*(east_p.z - end_point.z))
)
-- evaluate which pos is closer to the end_point
if dist_north_p_to_end <= dist_south_p_to_end and
dist_north_p_to_end <= dist_west_p_to_end and
dist_north_p_to_end <= dist_east_p_to_end
then
starting_point = north_p
distance = dist_north_p_to_end
elseif dist_south_p_to_end <= dist_north_p_to_end and
dist_south_p_to_end <= dist_west_p_to_end and
dist_south_p_to_end <= dist_east_p_to_end
then
starting_point = south_p
distance = dist_south_p_to_end
elseif dist_west_p_to_end <= dist_north_p_to_end and
dist_west_p_to_end <= dist_south_p_to_end and
dist_west_p_to_end <= dist_east_p_to_end
then
starting_point = west_p
distance = dist_west_p_to_end
elseif dist_east_p_to_end <= dist_north_p_to_end and
dist_east_p_to_end <= dist_south_p_to_end and
dist_east_p_to_end <= dist_west_p_to_end
then
starting_point = east_p
distance = dist_east_p_to_end
end
-- find surface of new starting point
local surface_point, surface_mat = settlements.find_surface_lvm(starting_point, minp)
-- replace surface node with mcl_core:grass_path
if surface_point
then
local vi = va:index(surface_point.x, surface_point.y, surface_point.z)
data[vi] = c_grasspath
--minetest.swap_node(surface_point,{name="mcl_core:grass_path"})
-- don't set y coordinate, surface might be too low or high
starting_point.x = surface_point.x
starting_point.z = surface_point.z
end
if distance <= 1 or
starting_point == end_point
then
break
end
end
end
end
--end
--return data
end
-------------------------------------------------------------------------------
-- generate paths between buildings
-------------------------------------------------------------------------------
function settlements.paths(settlement_info) function settlements.paths(settlement_info)
local starting_point local starting_point
local end_point local end_point
@ -164,7 +71,11 @@ function settlements.paths(settlement_info)
-- replace surface node with mcl_core:grass_path -- replace surface node with mcl_core:grass_path
if surface_point if surface_point
then then
if surface_mat == "mcl_core:sand" or surface_mat == "mcl_core:redsand" then
minetest.swap_node(surface_point,{name="mcl_core:sandstonesmooth2"})
else
minetest.swap_node(surface_point,{name="mcl_core:grass_path"}) minetest.swap_node(surface_point,{name="mcl_core:grass_path"})
end
-- don't set y coordinate, surface might be too low or high -- don't set y coordinate, surface might be too low or high
starting_point.x = surface_point.x starting_point.x = surface_point.x
starting_point.z = surface_point.z starting_point.z = surface_point.z

@ -1,5 +1,3 @@
mcl_villages = {}
local c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass") local c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass")
local c_dirt_with_snow = minetest.get_content_id("mcl_core:dirt_with_grass_snow") local c_dirt_with_snow = minetest.get_content_id("mcl_core:dirt_with_grass_snow")
--local c_dirt_with_dry_grass = minetest.get_content_id("mcl_core:dirt_with_dry_grass") --local c_dirt_with_dry_grass = minetest.get_content_id("mcl_core:dirt_with_dry_grass")
@ -9,7 +7,7 @@ local c_desert_sand = minetest.get_content_id("mcl_core:redsand"
--local c_silver_sand = minetest.get_content_id("mcl_core:silver_sand") --local c_silver_sand = minetest.get_content_id("mcl_core:silver_sand")
-- --
local c_air = minetest.get_content_id("air") local c_air = minetest.get_content_id("air")
local c_snow = minetest.get_content_id("mcl_core:snowblock") local c_snow = minetest.get_content_id("mcl_core:snow")
local c_fern_1 = minetest.get_content_id("mcl_flowers:fern") local c_fern_1 = minetest.get_content_id("mcl_flowers:fern")
local c_fern_2 = minetest.get_content_id("mcl_flowers:fern") local c_fern_2 = minetest.get_content_id("mcl_flowers:fern")
local c_fern_3 = minetest.get_content_id("mcl_flowers:fern") local c_fern_3 = minetest.get_content_id("mcl_flowers:fern")
@ -43,56 +41,6 @@ function settlements.round(num, numDecimalPlaces)
return math.floor(num * mult + 0.5) / mult return math.floor(num * mult + 0.5) / mult
end end
-------------------------------------------------------------------------------
-- function to find surface block y coordinate
-------------------------------------------------------------------------------
function settlements.find_surface_lvm(pos, minp)
--ab hier altes verfahren
local p6 = vector.new(pos)
local surface_mat = {
c_dirt_with_grass,
c_dirt_with_snow,
--c_dirt_with_dry_grass,
c_podzol,
c_sand,
c_desert_sand
}
local cnt = 0
local itter -- count up or down
local cnt_max = 200
-- starting point for looking for surface
local vi = va:index(p6.x, p6.y, p6.z)
if data[vi] == nil then return nil end
local tmp = minetest.get_name_from_content_id(data[vi])
if data[vi] == c_air then
itter = -1
else
itter = 1
end
while cnt < cnt_max do
cnt = cnt+1
local vi = va:index(p6.x, p6.y, p6.z)
-- local tmp = minetest.get_name_from_content_id(data[vi])
-- if vi == nil
-- then
-- return nil
-- end
for i, mats in ipairs(surface_mat) do
local node_check = va:index(p6.x, p6.y+1, p6.z)
if node_check and vi and data[vi] == mats and
(data[node_check] ~= c_water_source and
data[node_check] ~= c_water_flowing
)
then
local tmp = minetest.get_name_from_content_id(data[node_check])
return p6, mats
end
end
p6.y = p6.y + itter
if p6.y < 0 then return nil end
end
return nil --]]
end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- function to find surface block y coordinate -- function to find surface block y coordinate
-- returns surface postion -- returns surface postion
@ -174,9 +122,7 @@ function settlements.check_distance(settlement_info, building_pos, building_size
distance = math.sqrt( distance = math.sqrt(
((building_pos.x - built_house["pos"].x)*(building_pos.x - built_house["pos"].x))+ ((building_pos.x - built_house["pos"].x)*(building_pos.x - built_house["pos"].x))+
((building_pos.z - built_house["pos"].z)*(building_pos.z - built_house["pos"].z))) ((building_pos.z - built_house["pos"].z)*(building_pos.z - built_house["pos"].z)))
if distance < building_size or if distance < building_size or distance < built_house["hsize"] then
distance < built_house["hsize"]
then
return false return false
end end
end end
@ -206,42 +152,23 @@ function settlements.load()
return {} return {}
end end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- check distance to other settlements
-------------------------------------------------------------------------------
--[[
function settlements.check_distance_other_settlements(center_new_chunk)
-- local min_dist_settlements = 300
for i, pos in ipairs(settlements_in_world) do
local distance = vector.distance(center_new_chunk, pos)
-- minetest.chat_send_all("dist ".. distance)
if distance < settlements.min_dist_settlements then
return false
end
end
return true
end
]]
-------------------------------------------------------------------------------
-- fill chests -- fill chests
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
function settlements.fill_chest(pos, pr) function settlements.fill_chest(pos, pr)
-- find chests within radius
--local chestpos = minetest.find_node_near(pos, 6, {"mcl_core:chest"})
local chestpos = pos
-- initialize chest (mts chests don't have meta) -- initialize chest (mts chests don't have meta)
local meta = minetest.get_meta(chestpos) local meta = minetest.get_meta(pos)
if meta:get_string("infotext") ~= "Chest" then if meta:get_string("infotext") ~= "Chest" then
-- For MineClone2 0.70 or before -- For MineClone2 0.70 or before
-- minetest.registered_nodes["mcl_chests:chest"].on_construct(chestpos) -- minetest.registered_nodes["mcl_chests:chest"].on_construct(pos)
-- --
-- For MineClone2 after commit 09ab1482b5 (the new entity chests) -- For MineClone2 after commit 09ab1482b5 (the new entity chests)
minetest.registered_nodes["mcl_chests:chest_small"].on_construct(chestpos) minetest.registered_nodes["mcl_chests:chest_small"].on_construct(pos)
end end
-- fill chest -- fill chest
local inv = minetest.get_inventory( {type="node", pos=chestpos} ) local inv = minetest.get_inventory( {type="node", pos=pos} )
function mcl_villages.get_treasures(pr)
local loottable = { local function get_treasures(pr)
{ local loottable = {{
stacks_min = 3, stacks_min = 3,
stacks_max = 8, stacks_max = 8,
items = { items = {
@ -263,13 +190,12 @@ function settlements.fill_chest(pos, pr)
{ itemstring = "mobs_mc:gold_horse_armor", weight = 1 }, { itemstring = "mobs_mc:gold_horse_armor", weight = 1 },
{ itemstring = "mobs_mc:diamond_horse_armor", weight = 1 }, { itemstring = "mobs_mc:diamond_horse_armor", weight = 1 },
} }
}, }}
}
local items = mcl_loot.get_multi_loot(loottable, pr) local items = mcl_loot.get_multi_loot(loottable, pr)
return items return items
end end
local items = mcl_villages.get_treasures(pr) local items = get_treasures(pr)
mcl_loot.fill_inventory(inv, "main", items) mcl_loot.fill_inventory(inv, "main", items)
end end
@ -315,7 +241,7 @@ end
local building_all_info local building_all_info
function settlements.initialize_nodes(settlement_info, pr) function settlements.initialize_nodes(settlement_info, pr)
for i, built_house in ipairs(settlement_info) do for i, built_house in ipairs(settlement_info) do
for j, schem in ipairs(schematic_table) do for j, schem in ipairs(settlements.schematic_table) do
if settlement_info[i]["name"] == schem["name"] then if settlement_info[i]["name"] == schem["name"] then
building_all_info = schem building_all_info = schem
break break
@ -402,27 +328,6 @@ function settlements.evaluate_heightmap()
return height_diff return height_diff
end end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- get LVM of current chunk
-------------------------------------------------------------------------------
function settlements.getlvm(minp, maxp)
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map(minp, maxp)
local va = VoxelArea:new{
MinEdge = emin,
MaxEdge = emax
}
local data = vm:get_data()
return vm, data, va, emin, emax
end
-------------------------------------------------------------------------------
-- get LVM of current chunk
-------------------------------------------------------------------------------
function settlements.setlvm(vm, data)
-- Write data
vm:set_data(data)
vm:write_to_map(true)
end
-------------------------------------------------------------------------------
-- Set array to list -- Set array to list
-- https://stackoverflow.com/questions/656199/search-for-an-item-in-a-lua-list -- https://stackoverflow.com/questions/656199/search-for-an-item-in-a-lua-list
------------------------------------------------------------------------------- -------------------------------------------------------------------------------

@ -130,6 +130,8 @@ mcl_superflat_classic (Classic superflat map generation) bool false
# game by a lot. # game by a lot.
mcl_node_particles (Block particles detail level) enum none high,medium,low,none mcl_node_particles (Block particles detail level) enum none high,medium,low,none
# If enabled, this will substitute a few blocks in village schematics so they blend into normal, snowy, and sandy areas. Defaults to false.
basic_pseudobiome_villages (Enables very basic, and experimental "pseudobiome-based" villages) bool false
# If enabled, will run an LBM to fix the top 1/2 of double plants in mcimported worlds; defaults to true. # If enabled, will run an LBM to fix the top 1/2 of double plants in mcimported worlds; defaults to true.
fix_doubleplants (Mcimport double plant fixes) bool true fix_doubleplants (Mcimport double plant fixes) bool true