diff --git a/mods/ITEMS/mcl_chests/init.lua b/mods/ITEMS/mcl_chests/init.lua index 6c37cff3..0f1e44c1 100644 --- a/mods/ITEMS/mcl_chests/init.lua +++ b/mods/ITEMS/mcl_chests/init.lua @@ -3,12 +3,19 @@ local mod_doc = minetest.get_modpath("doc") -- Chest Entity local animate_chests = (minetest.settings:get_bool("animated_chests") ~= false) -local entity_animation_speed = 25 local entity_animations = { - ["open"] = {x = 0, y = 10}, - ["open_partly"] = {x = 0, y = 7}, - ["close"] = {x = 10, y = 20}, - ["close_partly"] = {x = 13, y = 20}, + shulker = { + speed = 50, + open = {x = 45, y = 95}, + 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", { @@ -21,9 +28,10 @@ minetest.register_entity("mcl_chests:chest", { }, 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 - self.object:set_animation(anim, entity_animation_speed, 0, false) + self.object:set_animation(anim, anim_table.speed, 0, false) end, open = function(self, playername, partly) @@ -54,10 +62,11 @@ minetest.register_entity("mcl_chests:chest", { 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_name = node_name self.sound_prefix = sound_prefix + self.animation_type = animation_type local obj = self.object obj:set_properties({ textures = textures, @@ -117,19 +126,22 @@ local function find_entity(pos) 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) - 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 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 end -local function find_or_create_entity(pos, node_name, textures, param2, double, sound_prefix, mesh_prefix, dir) - local dir = dir or minetest.facedir_to_dir(param2) - 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, dir, entity_pos) +local function find_or_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) + return find_entity(entity_pos) or create_entity(pos, node_name, textures, param2, double, sound_prefix, mesh_prefix, animation_type, dir, entity_pos) end 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 local nodename = node.name 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 return false 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 end -- 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() - 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 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 @@ -198,11 +212,11 @@ local chest_update_after_close = function(pos) if node.name == "mcl_chests:trapped_chest_on_small" then 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) elseif node.name == "mcl_chests:trapped_chest_on_left" then 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) 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") 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) end end @@ -227,7 +241,7 @@ local player_chest_close = function(player) return end 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 chest_update_after_close(open_chest.pos) @@ -374,6 +388,7 @@ minetest.register_node(small_name, { _chest_entity_textures = small_textures, _chest_entity_sound = "default_chest", _chest_entity_mesh = "mcl_chests_chest", + _chest_entity_animation_type = "chest", paramtype = "light", paramtype2 = "facedir", stack_max = 64, @@ -410,15 +425,15 @@ minetest.register_node(small_name, { minetest.swap_node(pos, {name="mcl_chests:"..canonical_basename.."_right",param2=param2}) local p = mcl_util.get_double_container_neighbor_pos(pos, param2, "right") 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 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") minetest.swap_node(p, { name = "mcl_chests:"..canonical_basename.."_right", param2 = param2 }) else 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, 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_sound = "default_chest", _chest_entity_mesh = "mcl_chests_chest", + _chest_entity_animation_type = "chest", paramtype = "light", 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}, @@ -512,7 +528,7 @@ minetest.register_node(left_name, { n.name = "mcl_chests:"..canonical_basename.."_small" minetest.swap_node(pos, n) 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, after_place_node = function(pos, placer, itemstack, pointed_thing) 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) 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, after_dig_node = drop_items_chest, on_blast = on_chest_blast, @@ -680,7 +696,7 @@ minetest.register_node("mcl_chests:"..basename.."_right", { close_forms(canonical_basename, p) 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) end, after_dig_node = drop_items_chest, @@ -845,7 +861,7 @@ register_chest("trapped_chest", }}, function(pos, node, clicker) 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) end, function(pos, node, clicker) @@ -853,7 +869,7 @@ register_chest("trapped_chest", meta:set_int("players", 1) 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) 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) 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) end ) @@ -888,13 +904,13 @@ local function close_if_trapped_chest(pos, player) if node.name == "mcl_chests:trapped_chest_on_small" then 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) player_chest_close(player) elseif node.name == "mcl_chests:trapped_chest_on_left" then 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) 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") 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) 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_sound = "mcl_chests_enderchest", _chest_entity_mesh = "mcl_chests_chest", + _chest_entity_animation_type = "chest", tiles = {"mcl_chests_blank.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", @@ -1011,10 +1028,10 @@ minetest.register_node("mcl_chests:ender_chest_small", { on_construct = function(pos) local meta = minetest.get_meta(pos) 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, 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, on_receive_fields = function(pos, formname, fields, sender) if fields.quit then @@ -1027,16 +1044,6 @@ minetest.register_node("mcl_chests:ender_chest_small", { 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) local inv = player:get_inventory() inv:set_size("enderchest", 9*3) @@ -1129,6 +1136,8 @@ for color, desc in pairs(boxtypes) do end end + local small_name = "mcl_chests:"..color.."_shulker_box_small" + minetest.register_node("mcl_chests:"..color.."_shulker_box", { description = desc, _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_longdesc = longdesc, _doc_items_usagehelp = usagehelp, - tiles = { - "mcl_chests_"..color.."_shulker_box_top.png", -- top + tiles = {mob_texture}, + drawtype = "mesh", + mesh = "mcl_chests_shulker.obj", + --[["mcl_chests_"..color.."_shulker_box_top.png", -- top "[combine:16x16:-32,-28="..mob_texture, -- bottom "[combine:16x16:0,-36="..mob_texture..":0,-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:-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}, + "[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}, 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) - 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 + local node = minetest.get_node(pos) + node.name = small_name + minetest.set_node(pos, node) end, after_place_node = function(pos, placer, itemstack, pointed_thing) local nmeta = minetest.get_meta(pos) @@ -1193,6 +1185,79 @@ for color, desc in pairs(boxtypes) do return nil 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) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() @@ -1238,6 +1303,7 @@ for color, desc in pairs(boxtypes) do 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_small", "nodes", "mcl_chests:"..color.."_shulker_box_small") end minetest.register_craft({ @@ -1282,7 +1348,7 @@ local function select_and_spawn_entity(pos, node) local node_name = node.name local node_def = minetest.registered_nodes[node_name] 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 minetest.register_lbm({ @@ -1296,7 +1362,7 @@ minetest.register_lbm({ minetest.register_lbm({ label = "Replace old chest nodes", 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, action = function(pos, node) local node_name = node.name diff --git a/mods/ITEMS/mcl_chests/models/mcl_chests_shulker.b3d b/mods/ITEMS/mcl_chests/models/mcl_chests_shulker.b3d new file mode 100644 index 00000000..86dde145 Binary files /dev/null and b/mods/ITEMS/mcl_chests/models/mcl_chests_shulker.b3d differ diff --git a/mods/ITEMS/mcl_chests/models/mcl_chests_shulker.obj b/mods/ITEMS/mcl_chests/models/mcl_chests_shulker.obj new file mode 100644 index 00000000..ca12b682 --- /dev/null +++ b/mods/ITEMS/mcl_chests/models/mcl_chests_shulker.obj @@ -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 diff --git a/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_close.0.ogg b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_close.0.ogg new file mode 100644 index 00000000..e97e22b3 Binary files /dev/null and b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_close.0.ogg differ diff --git a/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_close.1.ogg b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_close.1.ogg new file mode 100644 index 00000000..d61c81cc Binary files /dev/null and b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_close.1.ogg differ diff --git a/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_close.2.ogg b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_close.2.ogg new file mode 100644 index 00000000..865e8190 Binary files /dev/null and b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_close.2.ogg differ diff --git a/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_close.3.ogg b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_close.3.ogg new file mode 100644 index 00000000..20388a40 Binary files /dev/null and b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_close.3.ogg differ diff --git a/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_close.4.ogg b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_close.4.ogg new file mode 100644 index 00000000..4a361644 Binary files /dev/null and b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_close.4.ogg differ diff --git a/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_open.0.ogg b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_open.0.ogg new file mode 100644 index 00000000..c63da1d1 Binary files /dev/null and b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_open.0.ogg differ diff --git a/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_open.1.ogg b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_open.1.ogg new file mode 100644 index 00000000..1dc60280 Binary files /dev/null and b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_open.1.ogg differ diff --git a/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_open.2.ogg b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_open.2.ogg new file mode 100644 index 00000000..e1af5da8 Binary files /dev/null and b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_open.2.ogg differ diff --git a/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_open.3.ogg b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_open.3.ogg new file mode 100644 index 00000000..d7ad1a3a Binary files /dev/null and b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_open.3.ogg differ diff --git a/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_open.4.ogg b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_open.4.ogg new file mode 100644 index 00000000..faf751c9 Binary files /dev/null and b/mods/ITEMS/mcl_chests/sounds/mcl_chests_shulker_open.4.ogg differ diff --git a/mods/ITEMS/mcl_core/functions.lua b/mods/ITEMS/mcl_core/functions.lua index b09ffdc8..3d47336f 100644 --- a/mods/ITEMS/mcl_core/functions.lua +++ b/mods/ITEMS/mcl_core/functions.lua @@ -899,99 +899,118 @@ local treelight = 9 local sapling_grow_action = function(tree_id, soil_needed, one_by_one, two_by_two, sapling) 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 - local sapling_is_growable = function(pos) - local light = minetest.get_node_light(pos) - 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") - return soiltype >= soil_needed and light and light >= treelight and not minetest.get_meta(pos):get("grown") + 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 sapling_is_growable(pos) then - -- Increase and check growth stage - local meta = minetest.get_meta(pos) - local stage = meta:get_int("stage") - if stage == nil then stage = 0 end - stage = stage + 1 - if stage >= 3 then - meta:set_string("grown", "true") - -- This sapling grows in a special way when there are 4 saplings in a 2×2 pattern - if two_by_two then - -- Check 8 surrounding saplings and try to find a 2×2 pattern - local is_sapling = function(pos, sapling) - return minetest.get_node(pos).name == sapling - end - local p2 = {x=pos.x+1, y=pos.y, z=pos.z} - local p3 = {x=pos.x, y=pos.y, z=pos.z-1} - local p4 = {x=pos.x+1, y=pos.y, z=pos.z-1} - local p5 = {x=pos.x-1, y=pos.y, z=pos.z-1} - local p6 = {x=pos.x-1, y=pos.y, z=pos.z} - local p7 = {x=pos.x-1, y=pos.y, z=pos.z+1} - local p8 = {x=pos.x, y=pos.y, z=pos.z+1} - local p9 = {x=pos.x+1, y=pos.y, z=pos.z+1} - local s2 = is_sapling(p2, sapling) - local s3 = is_sapling(p3, sapling) - local s4 = is_sapling(p4, sapling) - local s5 = is_sapling(p5, sapling) - local s6 = is_sapling(p6, sapling) - local s7 = is_sapling(p7, sapling) - local s8 = is_sapling(p8, sapling) - local s9 = is_sapling(p9, sapling) - -- In a 9×9 field there are 4 possible 2×2 squares. We check them all. - if s2 and s3 and s4 and check_tree_growth(pos, tree_id, { two_by_two = true }) then - -- Success: Remove saplings and place tree - minetest.remove_node(pos) - minetest.remove_node(p2) - minetest.remove_node(p3) - minetest.remove_node(p4) - mcl_core.generate_tree(pos, tree_id, { two_by_two = true }) - return - elseif s3 and s5 and s6 and check_tree_growth(p6, tree_id, { two_by_two = true }) then - minetest.remove_node(pos) - minetest.remove_node(p3) - minetest.remove_node(p5) - minetest.remove_node(p6) - mcl_core.generate_tree(p6, tree_id, { two_by_two = true }) - return - elseif s6 and s7 and s8 and check_tree_growth(p7, tree_id, { two_by_two = true }) then - minetest.remove_node(pos) - minetest.remove_node(p6) - minetest.remove_node(p7) - minetest.remove_node(p8) - mcl_core.generate_tree(p7, tree_id, { two_by_two = true }) - return - elseif s2 and s8 and s9 and check_tree_growth(p8, tree_id, { two_by_two = true }) then - minetest.remove_node(pos) - minetest.remove_node(p2) - minetest.remove_node(p8) - minetest.remove_node(p9) - mcl_core.generate_tree(p8, tree_id, { two_by_two = true }) - return - end - end - 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 - if math.random(1, 12) == 1 then - -- Check if there is room for that - if check_tree_growth(pos, tree_id, { balloon = true }) then - minetest.set_node(pos, {name="air"}) - mcl_core.generate_tree(pos, tree_id, { balloon = true }) - return - end - end - 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 - -- If this sapling can grow alone - if one_by_one and check_tree_growth(pos, tree_id) then - -- Single sapling - minetest.set_node(pos, {name="air"}) - local r = math.random(1, 12) - mcl_core.generate_tree(pos, tree_id) + -- 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 soiltype = minetest.get_item_group(soilnode.name, "soil_sapling") + if soiltype < soil_needed then return end + + -- Increase and check growth stage + local meta = minetest.get_meta(pos) + local stage = meta:get_int("stage") + if stage == nil then stage = 0 end + stage = stage + math.max(1, math.floor(delta)) + if stage >= 3 then + meta:set_string("grown", "true") + -- This sapling grows in a special way when there are 4 saplings in a 2×2 pattern + if two_by_two then + -- Check 8 surrounding saplings and try to find a 2×2 pattern + local is_sapling = function(pos, sapling) + return minetest.get_node(pos).name == sapling + end + local p2 = {x=pos.x+1, y=pos.y, z=pos.z} + local p3 = {x=pos.x, y=pos.y, z=pos.z-1} + local p4 = {x=pos.x+1, y=pos.y, z=pos.z-1} + local p5 = {x=pos.x-1, y=pos.y, z=pos.z-1} + local p6 = {x=pos.x-1, y=pos.y, z=pos.z} + local p7 = {x=pos.x-1, y=pos.y, z=pos.z+1} + local p8 = {x=pos.x, y=pos.y, z=pos.z+1} + local p9 = {x=pos.x+1, y=pos.y, z=pos.z+1} + local s2 = is_sapling(p2, sapling) + local s3 = is_sapling(p3, sapling) + local s4 = is_sapling(p4, sapling) + local s5 = is_sapling(p5, sapling) + local s6 = is_sapling(p6, sapling) + local s7 = is_sapling(p7, sapling) + local s8 = is_sapling(p8, sapling) + local s9 = is_sapling(p9, sapling) + -- In a 9×9 field there are 4 possible 2×2 squares. We check them all. + if s2 and s3 and s4 and check_tree_growth(pos, tree_id, { two_by_two = true }) then + -- Success: Remove saplings and place tree + minetest.remove_node(pos) + minetest.remove_node(p2) + minetest.remove_node(p3) + minetest.remove_node(p4) + mcl_core.generate_tree(pos, tree_id, { two_by_two = true }) + return + elseif s3 and s5 and s6 and check_tree_growth(p6, tree_id, { two_by_two = true }) then + minetest.remove_node(pos) + minetest.remove_node(p3) + minetest.remove_node(p5) + minetest.remove_node(p6) + mcl_core.generate_tree(p6, tree_id, { two_by_two = true }) + return + elseif s6 and s7 and s8 and check_tree_growth(p7, tree_id, { two_by_two = true }) then + minetest.remove_node(pos) + minetest.remove_node(p6) + minetest.remove_node(p7) + minetest.remove_node(p8) + mcl_core.generate_tree(p7, tree_id, { two_by_two = true }) + return + elseif s2 and s8 and s9 and check_tree_growth(p8, tree_id, { two_by_two = true }) then + minetest.remove_node(pos) + minetest.remove_node(p2) + minetest.remove_node(p8) + minetest.remove_node(p9) + mcl_core.generate_tree(p8, tree_id, { two_by_two = true }) return end - else - meta:set_int("stage", stage) end + 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 + if math.random(1, 12) == 1 then + -- Check if there is room for that + if check_tree_growth(pos, tree_id, { balloon = true }) then + minetest.set_node(pos, {name="air"}) + mcl_core.generate_tree(pos, tree_id, { balloon = true }) + return + end + end + end + -- If this sapling can grow alone + if one_by_one and check_tree_growth(pos, tree_id) then + -- Single sapling + minetest.set_node(pos, {name="air"}) + local r = math.random(1, 12) + mcl_core.generate_tree(pos, tree_id) + return + end + else + meta:set_int("stage", stage) end end end @@ -1040,7 +1059,14 @@ minetest.register_abm({ neighbors = {"group:soil_sapling"}, interval = 25, 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 @@ -1050,7 +1076,14 @@ minetest.register_abm({ neighbors = {"group:soil_sapling"}, interval = 25, 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 @@ -1060,7 +1093,14 @@ minetest.register_abm({ neighbors = {"group:soil_sapling"}, interval = 25, 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 @@ -1072,6 +1112,13 @@ minetest.register_abm({ chance = 2, 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 minetest.register_abm({ @@ -1080,7 +1127,14 @@ minetest.register_abm({ neighbors = {"group:soil_sapling"}, interval = 25, 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 @@ -1090,7 +1144,14 @@ minetest.register_abm({ neighbors = {"group:soil_sapling"}, interval = 20, 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) diff --git a/mods/MAPGEN/mcl_villages/buildings.lua b/mods/MAPGEN/mcl_villages/buildings.lua index 1dc9d0c2..05f08bdc 100644 --- a/mods/MAPGEN/mcl_villages/buildings.lua +++ b/mods/MAPGEN/mcl_villages/buildings.lua @@ -61,8 +61,7 @@ function settlements.initialize_settlement_info(pr) local count_buildings = {} -- count_buildings table reset - for k,v in pairs(schematic_table) do - -- local name = schematic_table[v]["name"] + for k,v in pairs(settlements.schematic_table) do count_buildings[v["name"]] = 0 end @@ -74,96 +73,6 @@ function settlements.initialize_settlement_info(pr) return count_buildings, number_of_buildings, number_built 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 -------------------------------------------------------------------------------- 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 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] + building_all_info = settlements.schematic_table[1] local rotation = possible_rotations[ pr:next(1, #possible_rotations ) ] -- add to settlement info table local index = 1 @@ -216,7 +125,7 @@ function settlements.create_site_plan(maxp, minp, pr) local pos_surface, surface_material = settlements.find_surface(pos1) 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 local size = #randomized_schematic_table for i = size, 1, -1 do @@ -255,60 +164,10 @@ end ------------------------------------------------------------------------------- -- 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) local building_all_info 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 building_all_info = schem break @@ -318,10 +177,10 @@ function settlements.place_schematics(settlement_info, pr) 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"] + 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 material = wallmaterial[pr:next(1,#wallmaterial)] -- local building = building_all_info["mts"] local replace_wall = building_all_info["rplc"] @@ -330,8 +189,28 @@ function settlements.place_schematics(settlement_info, pr) "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) + if replace_wall then + --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 schem_lua = schem_lua:gsub("mcl_core:dirt_with_grass", platform_material) diff --git a/mods/MAPGEN/mcl_villages/const.lua b/mods/MAPGEN/mcl_villages/const.lua index 285152f5..09c17434 100644 --- a/mods/MAPGEN/mcl_villages/const.lua +++ b/mods/MAPGEN/mcl_villages/const.lua @@ -5,11 +5,7 @@ settlements.debug = function(message) minetest.log("verbose", "[mcl_villages] "..message) end --- switch for lvm -settlements.lvm = false - -settlements.last_settlement = os.time() - +--[[ Manually set in 'buildings.lua' -- material to replace cobblestone with wallmaterial = { "mcl_core:junglewood", @@ -23,6 +19,7 @@ wallmaterial = { "mcl_core:sandstone", "mcl_core:sandstonesmooth2" } +--]] settlements.surface_mat = {} ------------------------------------------------------------------------------- -- Set array to list @@ -38,7 +35,7 @@ function settlements.grundstellungen() "mcl_core:sand", "mcl_core:redsand", --"mcl_core:silver_sand", - "mcl_core:snowblock" + "mcl_core:snow" } end -- @@ -52,27 +49,27 @@ schem_path = settlements.modpath.."/schematics/" -- -- list of schematics -- -schematic_table = { - {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"}, - {name = "butcher", mts = schem_path.."butcher.mts", hwidth = 11, hdepth = 8, hheight = 10, hsize = 14, max_num = 0.03, rplc = "n"}, - {name = "church", mts = schem_path.."church.mts", hwidth = 13, hdepth = 13, hheight = 14, hsize = 15, 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 = "n"}, - {name = "lamp", mts = schem_path.."lamp.mts", hwidth = 3, hdepth = 3, hheight = 13, hsize = 10, max_num = 0.1, rplc = "n"}, - {name = "library", mts = schem_path.."library.mts", hwidth = 12, hdepth = 12, hheight = 8, hsize = 13, max_num = 0.04, rplc = "n"}, - {name = "medium_house", mts = schem_path.."medium_house.mts", hwidth = 8, hdepth = 12, hheight = 8, hsize = 14, max_num = 0.08, rplc = "n"}, - {name = "small_house", mts = schem_path.."small_house.mts", hwidth = 9, hdepth = 7, hheight = 8, hsize = 13, max_num = 0.7, rplc = "n"}, - {name = "tavern", mts = schem_path.."tavern.mts", hwidth = 11, hdepth = 10, hheight = 10, hsize = 13, max_num = 0.050, rplc = "n"}, - {name = "well", mts = schem_path.."well.mts", hwidth = 6, hdepth = 8, hheight = 6, hsize = 10, max_num = 0.045, rplc = "n"}, +local basic_pseudobiome_villages = minetest.settings:get_bool("basic_pseudobiome_villages", false) + +settlements.schematic_table = { + {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 = "blacksmith", mts = schem_path.."blacksmith.mts", hwidth = 7, hdepth = 7, hheight = 13, hsize = 13, max_num = 0.055, rplc = basic_pseudobiome_villages }, + {name = "butcher", mts = schem_path.."butcher.mts", hwidth = 11, hdepth = 8, hheight = 10, hsize = 14, max_num = 0.03 , rplc = basic_pseudobiome_villages }, + {name = "church", mts = schem_path.."church.mts", hwidth = 13, hdepth = 13, hheight = 14, hsize = 15, max_num = 0.04 , rplc = basic_pseudobiome_villages }, + {name = "farm", mts = schem_path.."farm.mts", hwidth = 7, hdepth = 7, hheight = 13, hsize = 13, max_num = 0.1 , rplc = basic_pseudobiome_villages }, + {name = "lamp", mts = schem_path.."lamp.mts", hwidth = 3, hdepth = 3, hheight = 13, hsize = 10, max_num = 0.1 , rplc = false }, + {name = "library", mts = schem_path.."library.mts", hwidth = 12, hdepth = 12, hheight = 8, hsize = 13, max_num = 0.04 , 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 = basic_pseudobiome_villages }, + {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 -- settlements_in_world = {} -- --- min_distance between settlements --- -settlements.min_dist_settlements = 64 -- -- maximum allowed difference in height for building a sttlement -- diff --git a/mods/MAPGEN/mcl_villages/convert_lua_mts.lua b/mods/MAPGEN/mcl_villages/convert_lua_mts.lua index e66905ba..cf30e006 100644 --- a/mods/MAPGEN/mcl_villages/convert_lua_mts.lua +++ b/mods/MAPGEN/mcl_villages/convert_lua_mts.lua @@ -1,23 +1,22 @@ -- function settlements.convert_mts_to_lua() - local building = schem_path.."townhall.mts" - local str = minetest.serialize_schematic(building, "lua", {lua_use_comments = true, lua_num_indent_spaces = 0}).." return(schematic)" - local schematic = loadstring(str)() - local file = io.open(schem_path.."church"..".lua", "w") - file:write(dump(schematic)) - file:close() -print(dump(schematic)) + local building = schem_path.."townhall.mts" + local str = minetest.serialize_schematic(building, "lua", {lua_use_comments = true, lua_num_indent_spaces = 0}).." return(schematic)" + local schematic = loadstring(str)() + local file = io.open(schem_path.."church"..".lua", "w") + file:write(dump(schematic)) + file:close() + print(dump(schematic)) end - function settlements.mts_save() - local f = assert(io.open(schem_path.."hut.lua", "r")) - local content = f:read("*all").." return(schematic2)" - f:close() + local f = assert(io.open(schem_path.."hut.lua", "r")) + local content = f:read("*all").." return(schematic2)" + f:close() - local schematic2 = loadstring("schematic2 = "..content)() - local seb = minetest.serialize_schematic(schematic2, "mts", {}) + local schematic2 = loadstring("schematic2 = "..content)() + local seb = minetest.serialize_schematic(schematic2, "mts", {}) local filename = schem_path .. "hut2" .. ".mts" filename = filename:gsub("\"", "\\\""):gsub("\\", "\\\\") local file, err = io.open(filename, "wb") @@ -27,4 +26,4 @@ function settlements.mts_save() file:close() end print("Wrote: " .. filename) -end \ No newline at end of file +end diff --git a/mods/MAPGEN/mcl_villages/foundation.lua b/mods/MAPGEN/mcl_villages/foundation.lua index 677b4efd..15936ef4 100644 --- a/mods/MAPGEN/mcl_villages/foundation.lua +++ b/mods/MAPGEN/mcl_villages/foundation.lua @@ -1,28 +1,6 @@ ------------------------------------------------------------------------------- -- 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 local p2 = vector.new(pos) local cnt = 0 @@ -41,113 +19,47 @@ end ------------------------------------------------------------------------------- -- 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) - local fheight - local fwidth - local fdepth - local schematic_data + local fheight, fwidth, fdepth, schematic_data - 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 - fheight = schematic_data["hheight"] -- remove trees and leaves above - -- - -- now that every info is available -> create platform and clear space above - -- - for xi = 0,fwidth-1 do - for zi = 0,fdepth-1 do - for yi = 0,fheight *3 do - if yi == 0 then - local p = {x=pos.x+xi, y=pos.y, z=pos.z+zi} - settlements.ground(p, pr) - else - -- write ground - local p = {x=pos.x+xi, y=pos.y+yi, z=pos.z+zi} - minetest.forceload_block(p) - local node = minetest.get_node_or_nil(p) - if node then - if node.name ~= "air" - then - minetest.swap_node(p,{name="air"}) - end - end - end - end - end - end - - end + for i, built_house in ipairs(settlement_info) do + -- pick right schematic_info to current built_house + for j, schem in ipairs(settlements.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 + fheight = schematic_data["hheight"] -- remove trees and leaves above + -- + -- now that every info is available -> create platform and clear space above + -- + for xi = 0,fwidth-1 do + for zi = 0,fdepth-1 do + for yi = 0,fheight *3 do + if yi == 0 then + local p = {x=pos.x+xi, y=pos.y, z=pos.z+zi} + settlements.ground(p, pr) + else + -- write ground + local p = {x=pos.x+xi, y=pos.y+yi, z=pos.z+zi} + minetest.forceload_block(p) + local node = minetest.get_node_or_nil(p) + if node and node.name ~= "air" then + minetest.swap_node(p,{name="air"}) + end + end + end + end + end + end end diff --git a/mods/MAPGEN/mcl_villages/init.lua b/mods/MAPGEN/mcl_villages/init.lua index a931d952..61e370d5 100644 --- a/mods/MAPGEN/mcl_villages/init.lua +++ b/mods/MAPGEN/mcl_villages/init.lua @@ -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.modpath = minetest.get_modpath("mcl_villages"); +settlements.modpath = minetest.get_modpath("mcl_villages") dofile(settlements.modpath.."/const.lua") dofile(settlements.modpath.."/utils.lua") dofile(settlements.modpath.."/foundation.lua") dofile(settlements.modpath.."/buildings.lua") dofile(settlements.modpath.."/paths.lua") -dofile(settlements.modpath.."/convert_lua_mts.lua") +--dofile(settlements.modpath.."/convert_lua_mts.lua") -- -- load settlements on server -- @@ -55,42 +47,20 @@ end -- on map generation, try to build a settlement -- local function build_a_settlement_no_delay(minp, maxp, blockseed) - local settlement_info local pr = PseudoRandom(blockseed) - -- + -- fill settlement_info with buildings and their data - -- - 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 + local settlement_info = settlements.create_site_plan(maxp, minp, pr) 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 + settlements.terraform(settlement_info, pr) -- 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 + settlements.paths(settlement_info) -- 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 + settlements.place_schematics(settlement_info, pr) -- evaluate settlement_info and initialize furnaces and chests settlements.initialize_nodes(settlement_info, pr) @@ -112,126 +82,27 @@ minetest.register_on_generated(function(minp, maxp, blockseed) -- don't build settlement underground 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 local height_difference = settlements.evaluate_heightmap(minp, maxp) 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}) -- 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}) end) --- --- manually place buildings, for debugging only --- -minetest.register_craftitem("mcl_villages:tool", { - description = "mcl_villages build tool", - 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 - -- - on_place = function(itemstack, placer, pointed_thing) - local pr = PseudoRandom(math.random(0,32767)) - -- enable debug routines - local center_surface = pointed_thing.under - if center_surface then - 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 - }) - +-- manually place villages +if minetest.is_creative_enabled("") then + minetest.register_craftitem("mcl_villages:tool", { + description = "mcl_villages build tool", + inventory_image = "default_tool_woodshovel.png", + -- build ssettlement + on_place = function(itemstack, placer, pointed_thing) + if not pointed_thing.under then return end + local minp = vector.subtract( pointed_thing.under, half_map_chunk_size) + local maxp = vector.add( pointed_thing.under, half_map_chunk_size) + build_a_settlement_no_delay(minp, maxp, math.random(0,32767)) + end + }) +end diff --git a/mods/MAPGEN/mcl_villages/paths.lua b/mods/MAPGEN/mcl_villages/paths.lua index 6601fc76..4973171a 100644 --- a/mods/MAPGEN/mcl_villages/paths.lua +++ b/mods/MAPGEN/mcl_villages/paths.lua @@ -1,99 +1,6 @@ ------------------------------------------------------------------------------- -- 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) local starting_point local end_point @@ -164,7 +71,11 @@ function settlements.paths(settlement_info) -- replace surface node with mcl_core:grass_path if surface_point then - minetest.swap_node(surface_point,{name="mcl_core:grass_path"}) + 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"}) + end -- don't set y coordinate, surface might be too low or high starting_point.x = surface_point.x starting_point.z = surface_point.z diff --git a/mods/MAPGEN/mcl_villages/utils.lua b/mods/MAPGEN/mcl_villages/utils.lua index 0e892bfe..96d540b5 100644 --- a/mods/MAPGEN/mcl_villages/utils.lua +++ b/mods/MAPGEN/mcl_villages/utils.lua @@ -1,5 +1,3 @@ -mcl_villages = {} - 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_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_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_2 = 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 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 -- returns surface postion @@ -169,79 +117,58 @@ end -- check distance for new building ------------------------------------------------------------------------------- function settlements.check_distance(settlement_info, building_pos, building_size) - local distance - for i, built_house in ipairs(settlement_info) do - distance = math.sqrt( - ((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))) - if distance < building_size or - distance < built_house["hsize"] - then - return false - end - end - return true -end -------------------------------------------------------------------------------- --- save list of generated settlements -------------------------------------------------------------------------------- -function settlements.save() - local file = io.open(minetest.get_worldpath().."/settlements.txt", "w") - if file then - file:write(minetest.serialize(settlements_in_world)) - file:close() - end -end -------------------------------------------------------------------------------- --- load list of generated settlements -------------------------------------------------------------------------------- -function settlements.load() - local file = io.open(minetest.get_worldpath().."/settlements.txt", "r") - if file then - local table = minetest.deserialize(file:read("*all")) - if type(table) == "table" then - return table - end - end - return {} -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 + local distance + for i, built_house in ipairs(settlement_info) do + distance = math.sqrt( + ((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))) + if distance < building_size or distance < built_house["hsize"] then return false end end return true end -]] +------------------------------------------------------------------------------- +-- save list of generated settlements +------------------------------------------------------------------------------- +function settlements.save() + local file = io.open(minetest.get_worldpath().."/settlements.txt", "w") + if file then + file:write(minetest.serialize(settlements_in_world)) + file:close() + end +end +------------------------------------------------------------------------------- +-- load list of generated settlements +------------------------------------------------------------------------------- +function settlements.load() + local file = io.open(minetest.get_worldpath().."/settlements.txt", "r") + if file then + local table = minetest.deserialize(file:read("*all")) + if type(table) == "table" then + return table + end + end + return {} +end ------------------------------------------------------------------------------- -- fill chests ------------------------------------------------------------------------------- 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) - local meta = minetest.get_meta(chestpos) - if meta:get_string("infotext") ~= "Chest" then - -- For MineClone2 0.70 or before - -- minetest.registered_nodes["mcl_chests:chest"].on_construct(chestpos) - -- - -- For MineClone2 after commit 09ab1482b5 (the new entity chests) - minetest.registered_nodes["mcl_chests:chest_small"].on_construct(chestpos) - end - -- fill chest - local inv = minetest.get_inventory( {type="node", pos=chestpos} ) - function mcl_villages.get_treasures(pr) - local loottable = { - { + -- initialize chest (mts chests don't have meta) + local meta = minetest.get_meta(pos) + if meta:get_string("infotext") ~= "Chest" then + -- For MineClone2 0.70 or before + -- minetest.registered_nodes["mcl_chests:chest"].on_construct(pos) + -- + -- For MineClone2 after commit 09ab1482b5 (the new entity chests) + minetest.registered_nodes["mcl_chests:chest_small"].on_construct(pos) + end + -- fill chest + local inv = minetest.get_inventory( {type="node", pos=pos} ) + + local function get_treasures(pr) + local loottable = {{ stacks_min = 3, stacks_max = 8, items = { @@ -263,14 +190,13 @@ function settlements.fill_chest(pos, pr) { itemstring = "mobs_mc:gold_horse_armor", weight = 1 }, { itemstring = "mobs_mc:diamond_horse_armor", weight = 1 }, } - }, - } + }} local items = mcl_loot.get_multi_loot(loottable, pr) return items end -local items = mcl_villages.get_treasures(pr) -mcl_loot.fill_inventory(inv, "main", items) + local items = get_treasures(pr) + mcl_loot.fill_inventory(inv, "main", items) end ------------------------------------------------------------------------------- @@ -315,23 +241,23 @@ end local building_all_info function settlements.initialize_nodes(settlement_info, pr) 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 building_all_info = schem break end end - local width = building_all_info["hwidth"] - local depth = building_all_info["hdepth"] - local height = building_all_info["hheight"] + local width = building_all_info["hwidth"] + local depth = building_all_info["hdepth"] + local height = building_all_info["hheight"] local p = settlement_info[i]["pos"] for yi = 1,height do for xi = 0,width do for zi = 0,depth do local ptemp = {x=p.x+xi, y=p.y+yi, z=p.z+zi} - local node = minetest.get_node(ptemp) + local node = minetest.get_node(ptemp) if node.name == "mcl_furnaces:furnace" or node.name == "mcl_chests:chest" or node.name == "mcl_anvils:anvil" then @@ -402,32 +328,11 @@ function settlements.evaluate_heightmap() return height_diff 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 -- https://stackoverflow.com/questions/656199/search-for-an-item-in-a-lua-list ------------------------------------------------------------------------------- function settlements.Set (list) - local set = {} - for _, l in ipairs(list) do set[l] = true end - return set + local set = {} + for _, l in ipairs(list) do set[l] = true end + return set end diff --git a/settingtypes.txt b/settingtypes.txt index 5c9fc177..d41ff369 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -130,6 +130,8 @@ mcl_superflat_classic (Classic superflat map generation) bool false # game by a lot. 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. fix_doubleplants (Mcimport double plant fixes) bool true