From 957a831dbfd9521daa397c6992c6e01734aad965 Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 31 Jan 2022 06:41:18 +0400 Subject: [PATCH 01/68] Replace tga to png --- mods/CORE/tga_encoder/README.md | 4 - mods/CORE/tga_encoder/init.lua | 92 ----------- mods/CORE/tga_encoder/mod.conf | 3 - mods/ITEMS/mcl_maps/init.lua | 177 +++++++++++----------- mods/ITEMS/mcl_maps/locale/mcl_maps.fr.tr | 5 +- mods/ITEMS/mcl_maps/mod.conf | 2 +- 6 files changed, 91 insertions(+), 192 deletions(-) delete mode 100644 mods/CORE/tga_encoder/README.md delete mode 100644 mods/CORE/tga_encoder/init.lua delete mode 100644 mods/CORE/tga_encoder/mod.conf diff --git a/mods/CORE/tga_encoder/README.md b/mods/CORE/tga_encoder/README.md deleted file mode 100644 index 9b3293dda..000000000 --- a/mods/CORE/tga_encoder/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# tga_encoder -A TGA Encoder written in Lua without the use of external Libraries. - -May be used as a Minetest mod. diff --git a/mods/CORE/tga_encoder/init.lua b/mods/CORE/tga_encoder/init.lua deleted file mode 100644 index 39309c9c9..000000000 --- a/mods/CORE/tga_encoder/init.lua +++ /dev/null @@ -1,92 +0,0 @@ -tga_encoder = {} - -local image = setmetatable({}, { - __call = function(self, ...) - local t = setmetatable({}, {__index = self}) - t:constructor(...) - return t - end, -}) - -function image:constructor(pixels) - self.data = "" - self.pixels = pixels - self.width = #pixels[1] - self.height = #pixels - - self:encode() -end - -function image:encode_colormap_spec() - self.data = self.data - .. string.char(0, 0) -- first entry index - .. string.char(0, 0) -- number of entries - .. string.char(0) -- bits per pixel -end - -function image:encode_image_spec() - self.data = self.data - .. string.char(0, 0) -- X-origin - .. string.char(0, 0) -- Y-origin - .. string.char(self.width % 256, math.floor(self.width / 256)) -- width - .. string.char(self.height % 256, math.floor(self.height / 256)) -- height - .. string.char(24) -- pixel depth (RGB = 3 bytes = 24 bits) - .. string.char(0) -- image descriptor -end - -function image:encode_header() - self.data = self.data - .. string.char(0) -- image id - .. string.char(0) -- color map type - .. string.char(10) -- image type (RLE RGB = 10) - self:encode_colormap_spec() -- color map specification - self:encode_image_spec() -- image specification -end - -function image:encode_data() - local current_pixel = '' - local previous_pixel = '' - local count = 1 - local packets = {} - local rle_packet = '' - for _, row in ipairs(self.pixels) do - for _, pixel in ipairs(row) do - current_pixel = string.char(pixel[3], pixel[2], pixel[1]) - if current_pixel ~= previous_pixel or count == 128 then - packets[#packets +1] = rle_packet - count = 1 - previous_pixel = current_pixel - else - count = count + 1 - end - rle_packet = string.char(128 + count - 1) .. current_pixel - end - end - packets[#packets +1] = rle_packet - self.data = self.data .. table.concat(packets) -end - -function image:encode_footer() - self.data = self.data - .. string.char(0, 0, 0, 0) -- extension area offset - .. string.char(0, 0, 0, 0) -- developer area offset - .. "TRUEVISION-XFILE" - .. "." - .. string.char(0) -end - -function image:encode() - self:encode_header() -- header - -- no color map and image id data - self:encode_data() -- encode data - -- no extension or developer area - self:encode_footer() -- footer -end - -function image:save(filename) - local f = assert(io.open(filename, "w")) - f:write(self.data) - f:close() -end - -tga_encoder.image = image diff --git a/mods/CORE/tga_encoder/mod.conf b/mods/CORE/tga_encoder/mod.conf deleted file mode 100644 index e4bfac898..000000000 --- a/mods/CORE/tga_encoder/mod.conf +++ /dev/null @@ -1,3 +0,0 @@ -name = tga_encoder -author = Fleckenstein -description = A TGA Encoder written in Lua without the use of external Libraries. diff --git a/mods/ITEMS/mcl_maps/init.lua b/mods/ITEMS/mcl_maps/init.lua index d2ff951ad..954fe9ee7 100644 --- a/mods/ITEMS/mcl_maps/init.lua +++ b/mods/ITEMS/mcl_maps/init.lua @@ -1,24 +1,12 @@ mcl_maps = {} -local modname = minetest.get_current_modname() -local modpath = minetest.get_modpath(modname) -local S = minetest.get_translator(modname) - -local math = math -local vector = vector -local table = table -local pairs = pairs - -local pos_to_string = minetest.pos_to_string -local string_to_pos = minetest.string_to_pos -local get_item_group = minetest.get_item_group -local dynamic_add_media = minetest.dynamic_add_media -local get_connected_players = minetest.get_connected_players - -local storage = minetest.get_mod_storage() +local S = minetest.get_translator("mcl_maps") +local modpath = minetest.get_modpath("mcl_maps") local worldpath = minetest.get_worldpath() local map_textures_path = worldpath .. "/mcl_maps/" ---local last_finished_id = storage:get_int("next_id") - 1 + +local math_min = math.min +local math_max = math.max minetest.mkdir(map_textures_path) @@ -40,17 +28,15 @@ local loaded_maps = {} local c_air = minetest.get_content_id("air") function mcl_maps.create_map(pos) - local minp = vector.multiply(vector.floor(vector.divide(pos, 128)), 128) - local maxp = vector.add(minp, vector.new(127, 127, 127)) + local minp = vector.subtract(vector.floor(pos), 64) + local maxp = vector.add(minp, 127) local itemstack = ItemStack("mcl_maps:filled_map") local meta = itemstack:get_meta() - local next_id = storage:get_int("next_id") - storage:set_int("next_id", next_id + 1) - local id = tostring(next_id) + local id = string.format("%.0f", minetest.hash_node_position(minp)) meta:set_string("mcl_maps:id", id) - meta:set_string("mcl_maps:minp", pos_to_string(minp)) - meta:set_string("mcl_maps:maxp", pos_to_string(maxp)) + meta:set_string("mcl_maps:minp", minetest.pos_to_string(minp)) + meta:set_string("mcl_maps:maxp", minetest.pos_to_string(maxp)) tt.reload_itemstack_description(itemstack) creating_maps[id] = true @@ -62,78 +48,93 @@ function mcl_maps.create_map(pos) local emin, emax = vm:read_from_map(minp, maxp) local data = vm:get_data() local param2data = vm:get_param2_data() - local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax}) + local offset_x, offset_y, offset_z = minp.x - emin.x, minp.y - emin.y, minp.z - emin.z + local dx = emax.x - emin.x + 1 + local dy = (emax.y - emin.y + 1) * dx + local offset = offset_z * dy + offset_y * dx + offset_x + local map_y_start = 64 * dx + local map_y_limit = 127 * dx + local pixels = {} local last_heightmap for x = 1, 128 do - local map_x = minp.x - 1 + x + local map_x = x + offset local heightmap = {} for z = 1, 128 do - local map_z = minp.z - 1 + z + local map_z = (z-1) * dy + map_x local color, height - for map_y = maxp.y, minp.y, -1 do - local index = area:index(map_x, map_y, map_z) - local c_id = data[index] - if c_id ~= c_air then - color = color_cache[c_id] - if color == nil then - local nodename = minetest.get_name_from_content_id(c_id) - local def = minetest.registered_nodes[nodename] - if def then - local texture - if def.palette then - texture = def.palette - elseif def.tiles then - texture = def.tiles[1] - if type(texture) == "table" then - texture = texture.name - end - end - if texture then - texture = texture:match("([^=^%^]-([^.]+))$"):split("^")[1] - end - if def.palette then - local palette = palettes[texture] - color = palette and {palette = palette} - else - color = texture_colors[texture] - end + + local map_y = map_z + map_y_start + local map_y_limit = map_z + map_y_limit + while data[map_y] ~= c_air and map_y < map_y_limit do + map_y = map_y + dx + end + while data[map_y] == c_air and map_y > map_z do + map_y = map_y - dx + end + local c_id = data[map_y] + color = color_cache[c_id] + if color == nil then + local nodename = minetest.get_name_from_content_id(c_id) + local def = minetest.registered_nodes[nodename] + if def then + local texture + if def.palette then + texture = def.palette + elseif def.tiles then + texture = def.tiles[1] + if type(texture) == "table" then + texture = texture.name end end - - if color and color.palette then - color = color.palette[param2data[index] + 1] + if texture then + texture = texture:match("([^=^%^]-([^.]+))$"):split("^")[1] + end + if def.palette then + local palette = palettes[texture] + color = palette and {palette = palette} else - color_cache[c_id] = color or false + color = texture_colors[texture] end - - if color and last_heightmap then - local last_height = last_heightmap[z] - if last_height < map_y then - color = { - math.min(255, color[1] + 16), - math.min(255, color[2] + 16), - math.min(255, color[3] + 16), - } - elseif last_height > map_y then - color = { - math.max(0, color[1] - 16), - math.max(0, color[2] - 16), - math.max(0, color[3] - 16), - } - end - end - height = map_y - break end end + + if color and color.palette then + color = color.palette[param2data[map_y] + 1] + else + color_cache[c_id] = color or false + end + + if color and last_heightmap then + local last_height = last_heightmap[z] + local y = map_y - map_z + if last_height < y then + color = { + math_min(255, color[1] + 16), + math_min(255, color[2] + 16), + math_min(255, color[3] + 16), + } + elseif last_height > y then + color = { + math_max(0, color[1] - 16), + math_max(0, color[2] - 16), + math_max(0, color[3] - 16), + } + end + end + height = map_y - map_z + heightmap[z] = height or minp.y - pixels[z] = pixels[z] or {} - pixels[z][x] = color or {0, 0, 0} + pixels[#pixels + 1] = color and {r = color[1], g = color[2], b = color[3]} or {r = 0, g = 0, b = 0} end last_heightmap = heightmap end - tga_encoder.image(pixels):save(map_textures_path .. "mcl_maps_map_texture_" .. id .. ".tga") + + local png = minetest.encode_png(128, 128, pixels) + local f = io.open(map_textures_path .. "mcl_maps_map_texture_" .. id .. ".png", "w") + if not f then return end + f:write(png) + f:close() creating_maps[id] = nil end) return itemstack @@ -144,11 +145,11 @@ function mcl_maps.load_map(id) return end - local texture = "mcl_maps_map_texture_" .. id .. ".tga" + local texture = "mcl_maps_map_texture_" .. id .. ".png" if not loaded_maps[id] then loaded_maps[id] = true - dynamic_add_media(map_textures_path .. texture, function() end) + minetest.dynamic_add_media(map_textures_path .. texture, function() end) end return texture @@ -229,14 +230,14 @@ end local old_add_item = minetest.add_item function minetest.add_item(pos, stack) stack = ItemStack(stack) - if get_item_group(stack:get_name(), "filled_map") > 0 then + if minetest.get_item_group(stack:get_name(), "filled_map") > 0 then stack:set_name("mcl_maps:filled_map") end return old_add_item(pos, stack) end tt.register_priority_snippet(function(itemstring, _, itemstack) - if itemstack and get_item_group(itemstring, "filled_map") > 0 then + if itemstack and minetest.get_item_group(itemstring, "filled_map") > 0 then local id = itemstack:get_meta():get_string("mcl_maps:id") if id ~= "" then return "#" .. id, mcl_colors.GRAY @@ -262,7 +263,7 @@ minetest.register_craft({ local function on_craft(itemstack, player, old_craft_grid, craft_inv) if itemstack:get_name() == "mcl_maps:filled_map" then for _, stack in pairs(old_craft_grid) do - if get_item_group(stack:get_name(), "filled_map") > 0 then + if minetest.get_item_group(stack:get_name(), "filled_map") > 0 then itemstack:get_meta():from_table(stack:get_meta():to_table()) return itemstack end @@ -299,7 +300,7 @@ minetest.register_on_leaveplayer(function(player) end) minetest.register_globalstep(function(dtime) - for _, player in pairs(get_connected_players()) do + for _, player in pairs(minetest.get_connected_players()) do local wield = player:get_wielded_item() local texture = mcl_maps.load_map_item(wield) local hud = huds[player] @@ -319,8 +320,8 @@ minetest.register_globalstep(function(dtime) local pos = vector.round(player:get_pos()) local meta = wield:get_meta() - local minp = string_to_pos(meta:get_string("mcl_maps:minp")) - local maxp = string_to_pos(meta:get_string("mcl_maps:maxp")) + local minp = minetest.string_to_pos(meta:get_string("mcl_maps:minp")) + local maxp = minetest.string_to_pos(meta:get_string("mcl_maps:maxp")) local marker = "mcl_maps_player_arrow.png" diff --git a/mods/ITEMS/mcl_maps/locale/mcl_maps.fr.tr b/mods/ITEMS/mcl_maps/locale/mcl_maps.fr.tr index 1808e839d..9ef7cd5c5 100644 --- a/mods/ITEMS/mcl_maps/locale/mcl_maps.fr.tr +++ b/mods/ITEMS/mcl_maps/locale/mcl_maps.fr.tr @@ -1,8 +1,5 @@ # textdomain: mcl_maps Empty Map=Carte Vierge Empty maps are not useful as maps, but they can be stacked and turned to maps which can be used.=Les cartes vierges ne sont pas utiles en tant que cartes, mais elles peuvent être empilées et transformées en cartes utilisables. -Rightclick to create a filled map (which can't be stacked anymore).=Clic droit pour créer une carte remplie (qui ne peut plus être empilée). +Rightclick to start using the map (which can't be stacked anymore).=Clic droit pour commencer à utiliser la carte (qui ne peut plus être empilée). Map=Carte -Shows a map image.=Affiche une carte. -When created, the map saves the nearby area as an image that can be viewed any time by holding the map.=Lors de sa création, la carte sauvegarde le terrain proche sous forme d'image qui peut être consultée n'importe quand en tenant la carte dans la main. -Hold the map in your hand. This will display a map on your screen.=Tenez la carte dans votre main. Cela affichera la carte à l'écran. diff --git a/mods/ITEMS/mcl_maps/mod.conf b/mods/ITEMS/mcl_maps/mod.conf index e1f068963..7275471b2 100644 --- a/mods/ITEMS/mcl_maps/mod.conf +++ b/mods/ITEMS/mcl_maps/mod.conf @@ -1,2 +1,2 @@ name = mcl_maps -depends = mcl_core, mcl_flowers, tga_encoder, tt, mcl_colors, mcl_skins, mcl_util +depends = mcl_core, mcl_flowers, tt, mcl_colors, mcl_skins, mcl_util From 4ae1bf711d0282e737b7cf37de0f874fe53eca6b Mon Sep 17 00:00:00 2001 From: kay27 Date: Sun, 6 Feb 2022 06:46:21 +0400 Subject: [PATCH 02/68] Break villages --- mods/CORE/mcl_mapgen/init.lua | 6 ++- mods/MAPGEN/mcl_villages/buildings.lua | 73 ++------------------------ mods/MAPGEN/mcl_villages/init.lua | 32 ++++++----- mods/MAPGEN/mcl_villages/mod.conf | 4 +- mods/MAPGEN/mcl_villages/utils.lua | 73 ++++++++++---------------- 5 files changed, 57 insertions(+), 131 deletions(-) diff --git a/mods/CORE/mcl_mapgen/init.lua b/mods/CORE/mcl_mapgen/init.lua index d751e9eb4..3cc455a88 100644 --- a/mods/CORE/mcl_mapgen/init.lua +++ b/mods/CORE/mcl_mapgen/init.lua @@ -480,7 +480,6 @@ function mcl_mapgen.get_voxel_manip(vm_context) return vm_context.vm end -local CS_NODES = mcl_mapgen.CS_NODES function mcl_mapgen.clamp_to_chunk(x, size) if not size then minetest.log("warning", "[mcl_mapgen] Couldn't clamp " .. tostring(x) .. " - missing size") @@ -504,6 +503,11 @@ function mcl_mapgen.clamp_to_chunk(x, size) end return x - overflow end + function mcl_mapgen.get_chunk_beginning(x) return x - ((x + central_chunk_min_pos) % CS_NODES) end + +function mcl_mapgen.get_chunk_ending(x) + return mcl_mapgen.get_chunk_beginning(x) + LAST_NODE_IN_CHUNK +end diff --git a/mods/MAPGEN/mcl_villages/buildings.lua b/mods/MAPGEN/mcl_villages/buildings.lua index 0860ce9a5..2e9011a22 100644 --- a/mods/MAPGEN/mcl_villages/buildings.lua +++ b/mods/MAPGEN/mcl_villages/buildings.lua @@ -1,62 +1,3 @@ ---[[ -------------------------------------------------------------------------------- --- build schematic, replace material, rotation -------------------------------------------------------------------------------- -function settlements.build_schematic(vm, data, va, pos, building, replace_wall, name) - -- get building node material for better integration to surrounding - local platform_material = mcl_vars.get_node(pos) - if not platform_material or (platform_material.name == "air" or platform_material.name == "ignore") then - return - end - platform_material = platform_material.name - -- pick random material - local material = wallmaterial[math.random(1,#wallmaterial)] - -- 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) - --- 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 - local width = schematic["size"]["x"] - local depth = schematic["size"]["z"] - local height = schematic["size"]["y"] - local possible_rotations = {"0", "90", "180", "270"} - local rotation = possible_rotations[ math.random( #possible_rotations ) ] - settlements.foundation( - pos, - width, - depth, - height, - rotation) - vm:set_data(data) - -- place schematic - - minetest.place_schematic_on_vmanip( - vm, - pos, - schematic, - rotation, - nil, - true) - vm:write_to_map(true) -end]] -------------------------------------------------------------------------------- --- initialize settlement_info -------------------------------------------------------------------------------- function settlements.initialize_settlement_info(pr) local count_buildings = {} @@ -75,18 +16,14 @@ end ------------------------------------------------------------------------------- -- fill settlement_info -------------------------------------------------------------------------------- -function settlements.create_site_plan(maxp, minp, pr) +local possible_rotations = {"0", "90", "180", "270"} +function settlements.create_site_plan(minp, maxp, pr) local settlement_info = {} local building_all_info - local possible_rotations = {"0", "90", "180", "270"} -- find center of chunk - local center = { - x=math.floor((minp.x+maxp.x)/2), - y=maxp.y, - z=math.floor((minp.z+maxp.z)/2) - } + local center = vector.add(minp, mcl_mapgen.HALF_CS_NODES) -- find center_surface of chunk - local center_surface , surface_material = settlements.find_surface(center, true) + local center_surface , surface_material = settlements.find_surface(center) local chunks = {} chunks[mcl_mapgen.get_chunk_number(center)] = true @@ -130,7 +67,7 @@ function settlements.create_site_plan(maxp, minp, pr) pos_surface, surface_material = settlements.find_surface(pos1) else chunks[chunk_number] = true - pos_surface, surface_material = settlements.find_surface(pos1, true) + pos_surface, surface_material = settlements.find_surface(pos1) end if not pos_surface then break end diff --git a/mods/MAPGEN/mcl_villages/init.lua b/mods/MAPGEN/mcl_villages/init.lua index 47ca91f2e..fa4f2b7b7 100644 --- a/mods/MAPGEN/mcl_villages/init.lua +++ b/mods/MAPGEN/mcl_villages/init.lua @@ -59,7 +59,7 @@ local function build_a_settlement(minp, maxp, blockseed) local pr = PseudoRandom(blockseed) -- fill settlement_info with buildings and their data - local settlement_info = settlements.create_site_plan(maxp, minp, pr) + local settlement_info = settlements.create_site_plan(minp, maxp, pr) if not settlement_info then return end -- evaluate settlement_info and prepair terrain @@ -74,33 +74,37 @@ end -- Disable natural generation in singlenode. local mg_name = minetest.get_mapgen_setting("mg_name") +local scan_last_node = (mcl_mapgen.CS - 2) * mcl_mapgen.BS - 1 +local scan_offset = mcl_mapgen.BS if mg_name ~= "singlenode" then mcl_mapgen.register_mapgen(function(minp, maxp, blockseed) -- local str1 = (maxp.y >= 0 and blockseed % 77 == 17) and "YES" or "no" -- minetest.log("action","[mcl_villages] " .. str1 .. ": minp=" .. minetest.pos_to_string(minp) .. ", maxp=" .. minetest.pos_to_string(maxp) .. ", blockseed=" .. tostring(blockseed)) -- don't build settlement underground - if maxp.y < 0 then return end + local y_max = maxp.y + if y_max < -30 then return end -- randomly try to build settlements - if blockseed % 77 ~= 17 then return end + -- if blockseed % 77 ~= 17 then return end -- don't build settlements on (too) uneven terrain -- lame and quick replacement of `heightmap` by kay27 - we maybe need to restore `heightmap` analysis if there will be a way for the engine to avoid cavegen conflicts: -------------------------------------------------------------------------- - local height_difference, min, max - local pr1=PseudoRandom(blockseed) - for i=1,pr1:next(5,10) do - local x = pr1:next(0, 40) + minp.x + 19 - local z = pr1:next(0, 40) + minp.z + 19 - local y = minetest_get_spawn_level(x, z) - if not y then return end - if y < (min or y+1) then min = y end - if y > (max or y-1) then max = y end + local min, max = 9999999, -9999999 + local pr = PseudoRandom(blockseed) + for i = 1, pr:next(5,10) do + local pos = vector.add(vector.new(pr:next(0, scan_last_node) + scan_offset, 0, pr:next(0, scan_last_node) + scan_offset), minp) + local surface_point = settlements.find_surface(pos) + if not surface_point then return end + local y = surface_point.y + min = math.min(y, min) + max = math.max(y, max) end - height_difference = max - min + 1 + local height_difference = max - min -------------------------------------------------------------------------- - if height_difference > max_height_difference then return end + minetest.chat_send_all("height diff="..height_difference) + if height_difference > 10 then return end build_a_settlement(minp, maxp, blockseed) end, mcl_mapgen.order.VILLAGES) diff --git a/mods/MAPGEN/mcl_villages/mod.conf b/mods/MAPGEN/mcl_villages/mod.conf index d8e2aa7d4..c8e0d8149 100644 --- a/mods/MAPGEN/mcl_villages/mod.conf +++ b/mods/MAPGEN/mcl_villages/mod.conf @@ -1,5 +1,5 @@ name = mcl_villages -author = Rochambeau +author = Rochambeau, MysticTempest, kay27 description = This mod adds settlements on world generation. -depends = mcl_util, mcl_mapgen_core, mcl_structures, mcl_core, mcl_loot +depends = mcl_util, mcl_mapgen_core, mcl_structures, mcl_core, mcl_loot, mcl_mapgen optional_depends = mcl_farming, mobs_mc diff --git a/mods/MAPGEN/mcl_villages/utils.lua b/mods/MAPGEN/mcl_villages/utils.lua index 1d94ead0c..589b04403 100644 --- a/mods/MAPGEN/mcl_villages/utils.lua +++ b/mods/MAPGEN/mcl_villages/utils.lua @@ -1,4 +1,4 @@ -local get_node = mcl_mapgen.get_far_node +local get_node = minetest.get_node ------------------------------------------------------------------------------- -- function to copy tables @@ -22,55 +22,36 @@ end -- function to find surface block y coordinate -- returns surface postion ------------------------------------------------------------------------------- -function settlements.find_surface(pos, wait) +function settlements.find_surface(pos) local p6 = vector.new(pos) - local cnt = 0 - local itter = 1 -- count up or down - local cnt_max = 200 - -- check, in which direction to look for surface - local surface_node - if wait then - surface_node = get_node(p6, true, 10000000) - else - surface_node = get_node(p6) - end - if surface_node.name=="air" or surface_node.name=="ignore" then - itter = -1 - end - -- go through nodes an find surface - while cnt < cnt_max do - -- Check Surface_node and Node above - -- - if settlements.surface_mat[surface_node.name] then - local surface_node_plus_1 = get_node({ x=p6.x, y=p6.y+1, z=p6.z}) - if surface_node_plus_1 and surface_node and - (string.find(surface_node_plus_1.name,"air") or - string.find(surface_node_plus_1.name,"snow") or - string.find(surface_node_plus_1.name,"fern") or - string.find(surface_node_plus_1.name,"flower") or - string.find(surface_node_plus_1.name,"bush") or - string.find(surface_node_plus_1.name,"tree") or - string.find(surface_node_plus_1.name,"grass")) - then - settlements.debug("find_surface7: " ..surface_node.name.. " " .. surface_node_plus_1.name) - return p6, surface_node.name - else - settlements.debug("find_surface2: wrong surface+1") - end - else - settlements.debug("find_surface3: wrong surface "..surface_node.name.." at pos "..minetest.pos_to_string(p6)) + p6.y = mcl_mapgen.get_chunk_ending(p6.y) + local ymin = mcl_mapgen.get_chunk_beginning(p6.y) + local node = get_node(p6) + minetest.chat_send_all(node.name) + if node.name ~= "air" then return end + while true do + p6.y = p6.y - 1 + if p6.y < ymin then return end + node = get_node(p6) + if settlements.surface_mat[node.name] then + break end + end + minetest.chat_send_all(node.name) - p6.y = p6.y + itter - if p6.y < 0 then - settlements.debug("find_surface4: y<0") - return nil - end - cnt = cnt+1 - surface_node = get_node(p6) + local prev_node = minetest.get_node(vector.new(p6.x, p6.y + 1, p6.z)) + local name = prev_node.name + if (string.find(name, "air") + or string.find(name, "snow") + or string.find(name, "fern") + or string.find(name, "flower") + or string.find(name, "bush") + or string.find(name, "tree") + or string.find(name, "grass") + ) then + minetest.chat_send_all("found! "..node.name..", "..minetest.pos_to_string(p6)) + return p6, node.name end - settlements.debug("find_surface5: cnt_max overflow") - return nil end ------------------------------------------------------------------------------- -- check distance for new building From 7e7c0c3a3750c65fa5bcbf875658d922d7ed2fe0 Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 7 Feb 2022 04:25:52 +0400 Subject: [PATCH 03/68] Make little cleanup --- mods/MAPGEN/mcl_villages/buildings.lua | 15 +++------------ mods/MAPGEN/mcl_villages/init.lua | 20 +------------------- 2 files changed, 4 insertions(+), 31 deletions(-) diff --git a/mods/MAPGEN/mcl_villages/buildings.lua b/mods/MAPGEN/mcl_villages/buildings.lua index 2e9011a22..b21c0157d 100644 --- a/mods/MAPGEN/mcl_villages/buildings.lua +++ b/mods/MAPGEN/mcl_villages/buildings.lua @@ -23,9 +23,7 @@ function settlements.create_site_plan(minp, maxp, pr) -- find center of chunk local center = vector.add(minp, mcl_mapgen.HALF_CS_NODES) -- find center_surface of chunk - local center_surface , surface_material = settlements.find_surface(center) - local chunks = {} - chunks[mcl_mapgen.get_chunk_number(center)] = true + local center_surface, surface_material = settlements.find_surface(center) -- go build settlement around center if not center_surface then return false end @@ -60,15 +58,8 @@ function settlements.create_site_plan(minp, maxp, pr) 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 chunk_number = mcl_mapgen.get_chunk_number(pos1) - local pos_surface, surface_material - if chunks[chunk_number] then - pos_surface, surface_material = settlements.find_surface(pos1) - else - chunks[chunk_number] = true - pos_surface, surface_material = settlements.find_surface(pos1) - end + local pos1 = { x=ptx, y=center_surface.y, z=ptz} + local pos_surface, surface_material = settlements.find_surface(pos1) if not pos_surface then break end local randomized_schematic_table = shuffle(settlements.schematic_table, pr) diff --git a/mods/MAPGEN/mcl_villages/init.lua b/mods/MAPGEN/mcl_villages/init.lua index fa4f2b7b7..386056ac6 100644 --- a/mods/MAPGEN/mcl_villages/init.lua +++ b/mods/MAPGEN/mcl_villages/init.lua @@ -8,7 +8,7 @@ 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") + -- -- load settlements on server -- @@ -33,24 +33,6 @@ minetest.register_node("mcl_villages:stonebrickcarved", { }) - - ---[[ Enable for testing, but use MineClone2's own spawn code if/when merging. --- --- register inhabitants --- -if minetest.get_modpath("mobs_mc") then - mobs:register_spawn("mobs_mc:villager", --name - {"mcl_core:stonebrickcarved"}, --nodes - 15, --max_light - 0, --min_light - 20, --chance - 7, --active_object_count - 31000, --max_height - nil) --day_toggle -end ---]] - -- -- on map generation, try to build a settlement -- From 4b4e29b3c1345cbdd376419968ab53532d972a67 Mon Sep 17 00:00:00 2001 From: kay27 Date: Tue, 8 Feb 2022 07:39:01 +0400 Subject: [PATCH 04/68] Slightly rewrite villages at all --- mods/CORE/mcl_mapgen/init.lua | 4 + mods/MAPGEN/mcl_villages/buildings.lua | 208 --------- mods/MAPGEN/mcl_villages/const.lua | 81 ---- mods/MAPGEN/mcl_villages/foundation.lua | 65 --- mods/MAPGEN/mcl_villages/init.lua | 428 ++++++++++++++++--- mods/MAPGEN/mcl_villages/locale/template.txt | 2 + mods/MAPGEN/mcl_villages/mod.conf | 2 +- mods/MAPGEN/mcl_villages/paths.lua | 91 ---- mods/MAPGEN/mcl_villages/utils.lua | 198 --------- 9 files changed, 370 insertions(+), 709 deletions(-) delete mode 100644 mods/MAPGEN/mcl_villages/buildings.lua delete mode 100644 mods/MAPGEN/mcl_villages/const.lua delete mode 100644 mods/MAPGEN/mcl_villages/foundation.lua create mode 100644 mods/MAPGEN/mcl_villages/locale/template.txt delete mode 100644 mods/MAPGEN/mcl_villages/paths.lua delete mode 100644 mods/MAPGEN/mcl_villages/utils.lua diff --git a/mods/CORE/mcl_mapgen/init.lua b/mods/CORE/mcl_mapgen/init.lua index 3cc455a88..bc390e597 100644 --- a/mods/CORE/mcl_mapgen/init.lua +++ b/mods/CORE/mcl_mapgen/init.lua @@ -511,3 +511,7 @@ end function mcl_mapgen.get_chunk_ending(x) return mcl_mapgen.get_chunk_beginning(x) + LAST_NODE_IN_CHUNK end + +mcl_mapgen.get_block_seed = get_block_seed +mcl_mapgen.get_block_seed2 = get_block_seed2 +mcl_mapgen.get_block_seed3 = get_block_seed3 diff --git a/mods/MAPGEN/mcl_villages/buildings.lua b/mods/MAPGEN/mcl_villages/buildings.lua deleted file mode 100644 index b21c0157d..000000000 --- a/mods/MAPGEN/mcl_villages/buildings.lua +++ /dev/null @@ -1,208 +0,0 @@ -function settlements.initialize_settlement_info(pr) - local count_buildings = {} - - -- count_buildings table reset - for k,v in pairs(settlements.schematic_table) do - count_buildings[v["name"]] = 0 - end - - -- randomize number of buildings - local number_of_buildings = pr:next(10, 25) - local number_built = 1 - settlements.debug("Village ".. number_of_buildings) - - return count_buildings, number_of_buildings, number_built -end -------------------------------------------------------------------------------- --- fill settlement_info --------------------------------------------------------------------------------- -local possible_rotations = {"0", "90", "180", "270"} -function settlements.create_site_plan(minp, maxp, pr) - local settlement_info = {} - local building_all_info - -- find center of chunk - local center = vector.add(minp, mcl_mapgen.HALF_CS_NODES) - -- find center_surface of chunk - local center_surface, surface_material = settlements.find_surface(center) - - -- 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 = settlements.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 - -- 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, z=ptz} - local pos_surface, surface_material = settlements.find_surface(pos1) - if not pos_surface then break end - - local randomized_schematic_table = shuffle(settlements.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 - if number_built >= number_of_buildings then - break - end - r = r + pr:next(2,5) - end - settlements.debug("really ".. number_built) - return settlement_info -end -------------------------------------------------------------------------------- --- evaluate settlement_info and place schematics -------------------------------------------------------------------------------- --- Initialize node -local function construct_node(p1, p2, name) - local r = minetest.registered_nodes[name] - if r then - if r.on_construct then - local nodes = minetest.find_nodes_in_area(p1, p2, name) - for p=1, #nodes do - local pos = nodes[p] - r.on_construct(pos) - end - return nodes - end - minetest.log("warning", "[mcl_villages] No on_construct defined for node name " .. name) - return - end - minetest.log("warning", "[mcl_villages] Attempt to 'construct' inexistant nodes: " .. name) -end -local function init_nodes(p1, rotation, pr, size) - local p2 = vector.subtract(vector.add(p1, size), 1) - construct_node(p1, p2, "mcl_itemframes:item_frame") - construct_node(p1, p2, "mcl_furnaces:furnace") - construct_node(p1, p2, "mcl_anvils:anvil") - - local nodes = construct_node(p1, p2, "mcl_chests:chest") - if nodes and #nodes > 0 then - for p=1, #nodes do - local pos = nodes[p] - settlements.fill_chest(pos, pr) - end - end -end -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(settlements.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" - schem_lua = schem_lua:gsub("mcl_core:stonebrickcarved", "mcl_villages:stonebrickcarved") - -- replace 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) - - --[[ Disable special junglewood for now. - -- special material for spawning npcs - schem_lua = schem_lua:gsub("mcl_core:junglewood", "settlements:junglewood") - --]] - - schem_lua = schem_lua:gsub("mcl_stairs:stair_wood_outer", "mcl_stairs:slab_wood") - schem_lua = schem_lua:gsub("mcl_stairs:stair_stone_rough_outer", "air") - - -- format schematic string - local schematic = loadstring(schem_lua)() - -- build foundation for the building an make room above - -- place schematic - mcl_structures.place_schematic({ - pos = pos, - schematic = schematic, - rotation = rotation, - on_placed = init_nodes, - pr = pr, - }) - end -end diff --git a/mods/MAPGEN/mcl_villages/const.lua b/mods/MAPGEN/mcl_villages/const.lua deleted file mode 100644 index eb7806209..000000000 --- a/mods/MAPGEN/mcl_villages/const.lua +++ /dev/null @@ -1,81 +0,0 @@ --- switch for debugging -function settlements.debug(message) - -- minetest.chat_send_all(message) - -- minetest.log("warning", "[mcl_villages] "..message) - minetest.log("verbose", "[mcl_villages] "..message) -end - ---[[ Manually set in 'buildings.lua' --- material to replace cobblestone with -local wallmaterial = { - "mcl_core:junglewood", - "mcl_core:sprucewood", - "mcl_core:wood", - "mcl_core:birchwood", - "mcl_core:acaciawood", - "mcl_core:stonebrick", - "mcl_core:cobble", - "mcl_core:sandstonecarved", - "mcl_core:sandstone", - "mcl_core:sandstonesmooth2" -} ---]] -settlements.surface_mat = {} -------------------------------------------------------------------------------- --- Set array to list --- https://stackoverflow.com/questions/656199/search-for-an-item-in-a-lua-list -------------------------------------------------------------------------------- -function settlements.grundstellungen() - settlements.surface_mat = settlements.Set { - "mcl_core:dirt_with_grass", - --"mcl_core:dry_dirt_with_grass", - "mcl_core:dirt_with_grass_snow", - --"mcl_core:dirt_with_dry_grass", - "mcl_core:podzol", - "mcl_core:sand", - "mcl_core:redsand", - --"mcl_core:silver_sand", - "mcl_core:snow" - } -end --- --- possible surfaces where buildings can be built --- - --- --- path to schematics --- -schem_path = settlements.modpath.."/schematics/" --- --- list of schematics --- -local basic_pseudobiome_villages = minetest.settings:get_bool("basic_pseudobiome_villages", true) - -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 = {} --- --- --- maximum allowed difference in height for building a sttlement --- -max_height_difference = 56 --- --- --- -half_map_chunk_size = 40 ---quarter_map_chunk_size = 20 diff --git a/mods/MAPGEN/mcl_villages/foundation.lua b/mods/MAPGEN/mcl_villages/foundation.lua deleted file mode 100644 index 71c5cfdda..000000000 --- a/mods/MAPGEN/mcl_villages/foundation.lua +++ /dev/null @@ -1,65 +0,0 @@ -------------------------------------------------------------------------------- --- 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 - local mat = "mcl_core: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 = "mcl_core:stone" - end - minetest.swap_node(p2, {name=mat}) - p2.y = p2.y-1 - end -end -------------------------------------------------------------------------------- --- function clear space above baseplate -------------------------------------------------------------------------------- -function settlements.terraform(settlement_info, pr) - 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(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} --- local node = mcl_vars.get_node(p) --- if node and node.name ~= "air" then --- minetest.swap_node(p,{name="air"}) --- end - minetest.swap_node({x=pos.x+xi, y=pos.y+yi, z=pos.z+zi},{name="air"}) - end - end - end - end - end -end diff --git a/mods/MAPGEN/mcl_villages/init.lua b/mods/MAPGEN/mcl_villages/init.lua index 386056ac6..6f563e8a5 100644 --- a/mods/MAPGEN/mcl_villages/init.lua +++ b/mods/MAPGEN/mcl_villages/init.lua @@ -1,26 +1,338 @@ -settlements = {} -settlements.modpath = minetest.get_modpath(minetest.get_current_modname()) +mcl_villages = {} +local chunk_offset_top = 16 +local chunk_offset_bottom = 3 +local max_height_difference = 12 +local minp_min = -64 +local chance_per_chunk = 1 +local noise_multiplier = 1 +local random_offset = 1 +local random_multiply = 19 +local struct_threshold = chance_per_chunk - 1 +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) +local S = minetest.get_translator(modname) +local basic_pseudobiome_villages = minetest.settings:get_bool("basic_pseudobiome_villages", true) +local schem_path = modpath .. "/schematics/" +local 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 }, +} +local surface_mat = { + ["mcl_core:dirt_with_dry_grass"] = true, + ["mcl_core:dirt_with_grass"] = true, + ["mcl_core:dirt_with_grass_snow"] = true, + ["mcl_core:podzol"] = true, + ["mcl_core:redsand"] = true, + ["mcl_core:sand"] = true, + ["mcl_core:snow"] = true, +} +local storage = minetest.get_mod_storage() +local villages = minetest.deserialize(storage:get_string("villages") or "return {}") or {} +local minetest_get_spawn_level = minetest.get_spawn_level +local minetest_get_node = minetest.get_node +local minetest_find_nodes_in_area = minetest.find_nodes_in_area +local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level +local math_pi = math.pi +local math_cos = math.cos +local math_sin = math.sin +local math_floor = math.floor +local math_ceil = math.ceil +local minetest_swap_node = minetest.swap_node +local minetest_registered_nodes = minetest.registered_nodes +local air_offset = chunk_offset_top - 1 +local ground_offset = chunk_offset_bottom + 1 +local surface_search_list = {} +for k, _ in surface_mat do + table.insert(surface_search_list, k) +end -local minetest_get_spawn_level = minetest.get_spawn_level +local function math_round(x) + return (x < 0) and math_ceil(x - 0.5) or math_floor(x + 0.5) +end -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") +local function find_surface(pos, minp, maxp) + local x, z = pos.x, pos.z + local y_top = maxp.y + local y_max = y_top - air_offset + if #minetest_find_nodes_in_area({x=x, y=y_max, z=z}, {x=x, y=y_top, z=z}, "air") < chunk_offset_top then return end + y_max = y_max - 1 + local y_bottom = minp.y + local y_min = y_bottom + chunk_offset_bottom + local nodes = minetest_find_nodes_in_area({x=x, y=y_min, z=z}, {x=x, y=y_max, z=z}, surface_search_list) + for _, surface_pos in pairs(nodes) do + local node_name_from_above = minetest_get_node({x=surface_pos.x, y=surface_pos.y+1, z=surface_pos.z}).name + if string.find(node_name_from_above, "air" ) + or string.find(node_name_from_above, "snow" ) + or string.find(node_name_from_above, "fern" ) + or string.find(node_name_from_above, "flower") + or string.find(node_name_from_above, "bush" ) + or string.find(node_name_from_above, "tree" ) + or string.find(node_name_from_above, "grass" ) + then return surface_pos, minetese_get_node(surface_pos).name + end +end --- --- load settlements on server --- -settlements_in_world = settlements.load() -settlements.grundstellungen() +local function get_treasures(pr) + local loottable = {{ + stacks_min = 3, + stacks_max = 8, + items = { + { itemstring = "mcl_core:diamond" , weight = 3, amount_min = 1, amount_max = 3 }, + { itemstring = "mcl_core:iron_ingot" , weight = 10, amount_min = 1, amount_max = 5 }, + { itemstring = "mcl_core:gold_ingot" , weight = 5, amount_min = 1, amount_max = 3 }, + { itemstring = "mcl_farming:bread" , weight = 15, amount_min = 1, amount_max = 3 }, + { itemstring = "mcl_core:apple" , weight = 15, amount_min = 1, amount_max = 3 }, + { itemstring = "mcl_tools:pick_iron" , weight = 5, }, + { itemstring = "mcl_tools:sword_iron" , weight = 5, }, + { itemstring = "mcl_armor:chestplate_iron" , weight = 5, }, + { itemstring = "mcl_armor:helmet_iron" , weight = 5, }, + { itemstring = "mcl_armor:leggings_iron" , weight = 5, }, + { itemstring = "mcl_armor:boots_iron" , weight = 5, }, + { itemstring = "mcl_core:obsidian" , weight = 5, amount_min = 3, amount_max = 7 }, + { itemstring = "mcl_core:sapling" , weight = 5, amount_min = 3, amount_max = 7 }, + { itemstring = "mcl_mobitems:saddle" , weight = 3, }, + { itemstring = "mobs_mc:iron_horse_armor" , weight = 1, }, + { 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 function fill_chest(pos, pr) + local meta = minetest.get_meta(pos) + minetest.registered_nodes["mcl_chests:chest_small"].on_construct(pos) + local inv = minetest.get_inventory( {type="node", pos=pos} ) + local items = get_treasures(pr) + mcl_loot.fill_inventory(inv, "main", items, pr) +end + +local possible_rotations = {"0", "90", "180", "270"} + +local function get_random_rotation(pr) + return possible_rotations[pr:next(1, #possible_rotations)] +end + +local function create_site_plan(minp, maxp, pr) + local plan = {} + local building_all_info + local center = vector.add(minp, mcl_mapgen.HALF_CS_NODES) + local center_surface, surface_material = find_surface(center, minp, maxp) + if not center_surface then return end + + local number_of_buildings = pr:next(10, 25) + local shuffle = {} + local count_buildings = {} + for i = 1, #schematic_table do + shuffle[i] = i + count_buildings[i] = 0 + end + for i = #shuffle, 2, -1 do + local j = pr:next(1, i) + shuffle[i], shuffle[j] = shuffle[j], shuffle[i] + end + local number_built = 1 + local shuffle_index = pr:next(1, #schematic_table) + + -- first building is townhall in the center + plan[#plan + 1] = { + pos = center_surface, + building = schematic_table[shuffle_index], + rotation = get_random_rotation(pr), + surface_mat = surface_material, + } + count_buildings[1] = count_buildings[1] + 1 + -- now some buildings around in a circle, radius = size of town center + local x, z, r = center_surface.x, center_surface.z, schematic_table[1].hsize + -- draw j circles around center and increase radius by random(2, 5) + for k = 1, 20 do + -- set position on imaginary circle + for j = 0, 360, 15 do + local angle = j * math_pi / 180 + local pos_surface, surface_material = find_surface( + { + x = math_round(x + r * math_cos(angle)), + z = math_round(z + r * math_sin(angle)) + }, + minp, + maxp, + ) + if pos_surface then + shuffle_index = (shuffle_index % (#schematic_table)) + 1 + local schematic_index = shuffle[shuffle_index] + local schematic = schematic_table[schematic_index] + if count_buildings[schematic_index] < schematic.max_num * number_of_buildings then + local hsize2 = schematic.hsize^2 + local is_distance_ok = true + for _, built_house in pairs(plan) do + local pos = built_house.pos + local building = built_house.building + local distance2 = (pos_surface.x - pos.x)^2 + (pos_surface.z - pos.z)^2 + if distance2 < building.hsize^2 or distance < hsize2 then + is_distance_ok = false + break + end + end + if is_distance_ok then + plan[#plan + 1] = { + pos = pos_surface, + building = schematic, + rotation = get_random_rotation(pr), + surface_mat = surface_material, + } + count_buildinigs[schematic_index] = count_buildinigs[schematic_index] + 1 + number_built = number_built + 1 + break + end + end + end + if number_built >= number_of_buildings then + break + end + end + if number_built >= number_of_buildings then + break + end + r = r + pr:next(2, 5) + end + return plan +end + +local function ground(pos, minp, maxp, pr) + local p2 = vector.new(pos) + local cnt = 0 + local mat = "mcl_core:dirt" + p2.y = p2.y - 1 + local min_y = math_max(minp.y, p2.y - pr:next(17,27)) + local stone_level = p2.y - pr:next(2, 4) + while p2.y >= min_y do + if p2.y == stone_level then + mat = "mcl_core:stone" + end + minetest.swap_node(p2, {name=mat}) + p2.y = p2.y - 1 + end +end + +local function terraform(plan, minp, maxp, pr) + local fheight, fwidth, fdepth, schematic_data, pos, rotation + for _, built_house in pairs(plan) do + schematic_data = plan[i].building + pos = plan[i].pos + rotation = plan[i].rotation + if rotation == "0" or rotation = "180" then + fwidth = schematic_data.hwidth + fdepth = schematic_data.hdepth + else + fwidth = schematic_data.hdepth + fdepth = schematic_data.hwidth + end + fheight = schematic_data.hheight + for xi = pos.x, pos.x + fwidth - 1 do + for zi = pos.z, pos.z + fdepth - 1 do + for yi = pos.y, math_min(pos.y + fheight * 3, maxp.y) do + local p = {x = xi, y = yi, z = zi} + if yi == pos.y then + ground(p, pr) + else + minetest_swap_node(p, {name = "air"}) + end + end + end + end + end +end + +local function paths(plan) + local starting_point + local end_point + local distance + starting_point = plan[1].pos + for o, p in pairs(plan) do + end_point = settlement_info[o].pos + local path = minetest.find_path(starting_point, end_point, mcl_mapgen.CS_NODES, 2, 2) + if path then + for _, pos in pairs(path) do + local surface_mat = minetest.get_node(pos).name + 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 + end + end + end +end + +local function init_nodes(p1, rotation, pr, size) + local p2 = vector.subtract(vector.add(p1, size), 1) + local nodes = minetest.find_nodes_in_area(p1, p2, {"mcl_itemframes:item_frame", "mcl_furnaces:furnace", "mcl_anvils:anvil"}) + for _, pos in pairs(nodes) do + local name = minetest_get_node(pos).name + local def = minetest_registered_nodes[minetest_get_node(pos).name] + def.on_construct(pos) + if name == "mcl_chests:chest" then + fill_chest(pos, pr) + end + end +end + +local function place_schematics(plan, pr) + for _, built_house in pairs(plan) do + local pos = built_house.pos + local rotation = built_house.rotation + local platform_material = built_house.surface_mat + local building = built_house.building.mts + local replace_wall = built_house.building.rplc + local schem_lua = minetest.serialize_schematic(building, + "lua", + {lua_use_comments = false, lua_num_indent_spaces = 0}).." return schematic" + schem_lua = schem_lua:gsub("mcl_core:stonebrickcarved", "mcl_villages:stonebrickcarved") + 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") + 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_core:brick_block", "mcl_core:redsandstone") + end + end + schem_lua = schem_lua:gsub("mcl_core:dirt_with_grass", platform_material) + schem_lua = schem_lua:gsub("mcl_stairs:stair_wood_outer", "mcl_stairs:slab_wood") + schem_lua = schem_lua:gsub("mcl_stairs:stair_stone_rough_outer", "air") + + local schematic = loadstring(schem_lua)() + -- build foundation for the building an make room above + -- place schematic + mcl_structures.place_schematic({ + pos = pos, + schematic = schematic, + rotation = rotation, + on_placed = init_nodes, + pr = pr, + }) + end +end -- -- register block for npc spawn -- minetest.register_node("mcl_villages:stonebrickcarved", { - description = ("Chiseled Stone Village Bricks"), + description = S("Chiseled Stone Village Bricks"), _doc_items_longdesc = doc.sub.items.temp.build, tiles = {"mcl_core_stonebrick_carved.png"}, stack_max = 64, @@ -36,73 +348,59 @@ minetest.register_node("mcl_villages:stonebrickcarved", { -- -- on map generation, try to build a settlement -- -local function build_a_settlement(minp, maxp, blockseed) - minetest.log("action","[mcl_villages] Building village at mapchunk " .. minetest.pos_to_string(minp) .. "..." .. minetest.pos_to_string(maxp) .. ", blockseed = " .. tostring(blockseed)) - local pr = PseudoRandom(blockseed) +local function build_a_settlement(minp, maxp, pr) + minetest.log("action","[mcl_villages] Building village at mapchunk " .. minetest.pos_to_string(minp) .. "..." .. minetest.pos_to_string(maxp)) + local pr = pr or PseudoRandom(mcl_mapgen.get_block_seed3(minp)) + local plan = create_site_plan(minp, maxp, pr) + if not plan then return end + terraform(plan, minp, maxp, pr) + paths(plan) + place_schematics(plan, pr) - -- fill settlement_info with buildings and their data - local settlement_info = settlements.create_site_plan(minp, maxp, pr) - if not settlement_info then return end + local center = vector.add(minp, mcl_mapgen.HALF_CS_NODES) + local center_surface = settlements.find_surface(center) + table.insert(villages, center_surface) + storage:set_string("villages", minetest.serialize(villages)) - -- evaluate settlement_info and prepair terrain - settlements.terraform(settlement_info, pr) + -- save list to file + settlements.save() - -- evaluate settlement_info and build paths between buildings - settlements.paths(settlement_info) - - -- evaluate settlement_info and place schematics - settlements.place_schematics(settlement_info, pr) end -- Disable natural generation in singlenode. -local mg_name = minetest.get_mapgen_setting("mg_name") -local scan_last_node = (mcl_mapgen.CS - 2) * mcl_mapgen.BS - 1 -local scan_offset = mcl_mapgen.BS if mg_name ~= "singlenode" then - mcl_mapgen.register_mapgen(function(minp, maxp, blockseed) - -- local str1 = (maxp.y >= 0 and blockseed % 77 == 17) and "YES" or "no" - -- minetest.log("action","[mcl_villages] " .. str1 .. ": minp=" .. minetest.pos_to_string(minp) .. ", maxp=" .. minetest.pos_to_string(maxp) .. ", blockseed=" .. tostring(blockseed)) - -- don't build settlement underground - local y_max = maxp.y - if y_max < -30 then return end - -- randomly try to build settlements - -- if blockseed % 77 ~= 17 then return end - - -- don't build settlements on (too) uneven terrain - - -- lame and quick replacement of `heightmap` by kay27 - we maybe need to restore `heightmap` analysis if there will be a way for the engine to avoid cavegen conflicts: - -------------------------------------------------------------------------- + local mg_name = minetest.get_mapgen_setting("mg_name") + local scan_last_node = mcl_mapgen.LAST_BLOCK * mcl_mapgen.BS - 1 + local scan_offset = mcl_mapgen.BS + mcl_mapgen.register_mapgen(function(minp, maxp, chunkseed) + if minp.y < minp_min then return end + local pr = PseudoRandom(chunkseed * random_multiply + random_offset) + local noise = mcl_structures_get_perlin_noise_level(minp) * noise_multiplier + if (random_number + noise) < struct_threshold then return end local min, max = 9999999, -9999999 - local pr = PseudoRandom(blockseed) for i = 1, pr:next(5,10) do - local pos = vector.add(vector.new(pr:next(0, scan_last_node) + scan_offset, 0, pr:next(0, scan_last_node) + scan_offset), minp) - local surface_point = settlements.find_surface(pos) + local surface_point = settlements.find_surface( + vector.add( + vector.new( + pr:next(scan_offset, scan_last_node) + , + 0, + pr:next(0, scan_last_node) + scan_offset + ), + minp + ) + ) if not surface_point then return end local y = surface_point.y min = math.min(y, min) max = math.max(y, max) end local height_difference = max - min - -------------------------------------------------------------------------- - minetest.chat_send_all("height diff="..height_difference) - if height_difference > 10 then return end - - build_a_settlement(minp, maxp, blockseed) + if height_difference > max_height_difference then return end + build_a_settlement(minp, maxp, chunkkseed) end, mcl_mapgen.order.VILLAGES) 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(minp, maxp, math.random(0,32767)) - end - }) - mcl_wip.register_experimental_item("mcl_villages:tool") + +function mcl_villages.get_villages() + return villages end diff --git a/mods/MAPGEN/mcl_villages/locale/template.txt b/mods/MAPGEN/mcl_villages/locale/template.txt new file mode 100644 index 000000000..e396a8b08 --- /dev/null +++ b/mods/MAPGEN/mcl_villages/locale/template.txt @@ -0,0 +1,2 @@ +# textdomain: mcl_villages +Chiseled Stone Village Bricks= diff --git a/mods/MAPGEN/mcl_villages/mod.conf b/mods/MAPGEN/mcl_villages/mod.conf index c8e0d8149..3f9a67bb3 100644 --- a/mods/MAPGEN/mcl_villages/mod.conf +++ b/mods/MAPGEN/mcl_villages/mod.conf @@ -1,5 +1,5 @@ name = mcl_villages author = Rochambeau, MysticTempest, kay27 description = This mod adds settlements on world generation. -depends = mcl_util, mcl_mapgen_core, mcl_structures, mcl_core, mcl_loot, mcl_mapgen +depends = mcl_util, mcl_structures, mcl_core, mcl_loot, mcl_mapgen optional_depends = mcl_farming, mobs_mc diff --git a/mods/MAPGEN/mcl_villages/paths.lua b/mods/MAPGEN/mcl_villages/paths.lua deleted file mode 100644 index 63f2ba146..000000000 --- a/mods/MAPGEN/mcl_villages/paths.lua +++ /dev/null @@ -1,91 +0,0 @@ -------------------------------------------------------------------------------- --- generate paths between buildings -------------------------------------------------------------------------------- -function settlements.paths(settlement_info) - 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(starting_point) - -- replace surface node with mcl_core:grass_path - if surface_point - 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"}) - 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 - end - if distance <= 1 or - starting_point == end_point - then - break - end - end - end - end -end diff --git a/mods/MAPGEN/mcl_villages/utils.lua b/mods/MAPGEN/mcl_villages/utils.lua deleted file mode 100644 index 589b04403..000000000 --- a/mods/MAPGEN/mcl_villages/utils.lua +++ /dev/null @@ -1,198 +0,0 @@ -local get_node = minetest.get_node - -------------------------------------------------------------------------------- --- function to copy tables -------------------------------------------------------------------------------- -function settlements.shallowCopy(original) - local copy = {} - for key, value in pairs(original) do - copy[key] = value - end - return copy -end --- --- --- -function settlements.round(num, numDecimalPlaces) - local mult = 10^(numDecimalPlaces or 0) - return math.floor(num * mult + 0.5) / mult -end - -------------------------------------------------------------------------------- --- function to find surface block y coordinate --- returns surface postion -------------------------------------------------------------------------------- -function settlements.find_surface(pos) - local p6 = vector.new(pos) - p6.y = mcl_mapgen.get_chunk_ending(p6.y) - local ymin = mcl_mapgen.get_chunk_beginning(p6.y) - local node = get_node(p6) - minetest.chat_send_all(node.name) - if node.name ~= "air" then return end - while true do - p6.y = p6.y - 1 - if p6.y < ymin then return end - node = get_node(p6) - if settlements.surface_mat[node.name] then - break - end - end - minetest.chat_send_all(node.name) - - local prev_node = minetest.get_node(vector.new(p6.x, p6.y + 1, p6.z)) - local name = prev_node.name - if (string.find(name, "air") - or string.find(name, "snow") - or string.find(name, "fern") - or string.find(name, "flower") - or string.find(name, "bush") - or string.find(name, "tree") - or string.find(name, "grass") - ) then - minetest.chat_send_all("found! "..node.name..", "..minetest.pos_to_string(p6)) - return p6, node.name - end -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 -------------------------------------------------------------------------------- --- fill chests -------------------------------------------------------------------------------- -function settlements.fill_chest(pos, pr) - -- 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(prand) - local loottable = {{ - stacks_min = 3, - stacks_max = 8, - items = { - { itemstring = "mcl_core:diamond", weight = 3, amount_min = 1, amount_max = 3 }, - { itemstring = "mcl_core:iron_ingot", weight = 10, amount_min = 1, amount_max = 5 }, - { itemstring = "mcl_core:gold_ingot", weight = 5, amount_min = 1, amount_max = 3 }, - { itemstring = "mcl_farming:bread", weight = 15, amount_min = 1, amount_max = 3 }, - { itemstring = "mcl_core:apple", weight = 15, amount_min = 1, amount_max = 3 }, - { itemstring = "mcl_tools:pick_iron", weight = 5 }, - { itemstring = "mcl_tools:sword_iron", weight = 5 }, - { itemstring = "mcl_armor:chestplate_iron", weight = 5 }, - { itemstring = "mcl_armor:helmet_iron", weight = 5 }, - { itemstring = "mcl_armor:leggings_iron", weight = 5 }, - { itemstring = "mcl_armor:boots_iron", weight = 5 }, - { itemstring = "mcl_core:obsidian", weight = 5, amount_min = 3, amount_max = 7 }, - { itemstring = "mcl_core:sapling", weight = 5, amount_min = 3, amount_max = 7 }, - { itemstring = "mcl_mobitems:saddle", weight = 3 }, - { itemstring = "mobs_mc:iron_horse_armor", weight = 1 }, - { itemstring = "mobs_mc:gold_horse_armor", weight = 1 }, - { itemstring = "mobs_mc:diamond_horse_armor", weight = 1 }, - } - }} - local items = mcl_loot.get_multi_loot(loottable, prand) - return items - end - - local items = get_treasures(pr) - mcl_loot.fill_inventory(inv, "main", items, pr) -end - -------------------------------------------------------------------------------- --- initialize furnace -------------------------------------------------------------------------------- -function settlements.initialize_furnace(pos) - -- find chests within radius - local furnacepos = minetest.find_node_near(pos, - 7, --radius - {"mcl_furnaces:furnace"}) - -- initialize furnacepos (mts furnacepos don't have meta) - if furnacepos - then - local meta = minetest.get_meta(furnacepos) - if meta:get_string("infotext") ~= "furnace" - then - minetest.registered_nodes["mcl_furnaces:furnace"].on_construct(furnacepos) - end - end -end -------------------------------------------------------------------------------- --- initialize anvil -------------------------------------------------------------------------------- -function settlements.initialize_anvil(pos) - -- find chests within radius - local anvilpos = minetest.find_node_near(pos, - 7, --radius - {"mcl_anvils:anvil"}) - -- initialize anvilpos (mts anvilpos don't have meta) - if anvilpos - then - local meta = minetest.get_meta(anvilpos) - if meta:get_string("infotext") ~= "anvil" - then - minetest.registered_nodes["mcl_anvils:anvil"].on_construct(anvilpos) - end - end -end -------------------------------------------------------------------------------- --- randomize table -------------------------------------------------------------------------------- -function shuffle(tbl, pr) - local table = settlements.shallowCopy(tbl) - local size = #table - for i = size, 1, -1 do - local rand = pr:next(1, size) - table[i], table[rand] = table[rand], table[i] - end - return table -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 -end From 04fc9217ec754b8bb63f60a1171a834c31550341 Mon Sep 17 00:00:00 2001 From: kay27 Date: Tue, 8 Feb 2022 08:12:53 +0400 Subject: [PATCH 05/68] Make new villages run --- mods/MAPGEN/mcl_villages/init.lua | 74 ++++++++++++++++--------------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/mods/MAPGEN/mcl_villages/init.lua b/mods/MAPGEN/mcl_villages/init.lua index 6f563e8a5..3a0bcfa7c 100644 --- a/mods/MAPGEN/mcl_villages/init.lua +++ b/mods/MAPGEN/mcl_villages/init.lua @@ -44,6 +44,8 @@ local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_le local math_pi = math.pi local math_cos = math.cos local math_sin = math.sin +local math_min = math.min +local math_max = math.max local math_floor = math.floor local math_ceil = math.ceil local minetest_swap_node = minetest.swap_node @@ -51,7 +53,7 @@ local minetest_registered_nodes = minetest.registered_nodes local air_offset = chunk_offset_top - 1 local ground_offset = chunk_offset_bottom + 1 local surface_search_list = {} -for k, _ in surface_mat do +for k, _ in pairs(surface_mat) do table.insert(surface_search_list, k) end @@ -77,7 +79,9 @@ local function find_surface(pos, minp, maxp) or string.find(node_name_from_above, "bush" ) or string.find(node_name_from_above, "tree" ) or string.find(node_name_from_above, "grass" ) - then return surface_pos, minetese_get_node(surface_pos).name + then + return surface_pos, minetest_get_node(surface_pos).name + end end end @@ -165,7 +169,7 @@ local function create_site_plan(minp, maxp, pr) z = math_round(z + r * math_sin(angle)) }, minp, - maxp, + maxp ) if pos_surface then shuffle_index = (shuffle_index % (#schematic_table)) + 1 @@ -178,7 +182,7 @@ local function create_site_plan(minp, maxp, pr) local pos = built_house.pos local building = built_house.building local distance2 = (pos_surface.x - pos.x)^2 + (pos_surface.z - pos.z)^2 - if distance2 < building.hsize^2 or distance < hsize2 then + if distance2 < building.hsize^2 or distance2 < hsize2 then is_distance_ok = false break end @@ -190,7 +194,7 @@ local function create_site_plan(minp, maxp, pr) rotation = get_random_rotation(pr), surface_mat = surface_material, } - count_buildinigs[schematic_index] = count_buildinigs[schematic_index] + 1 + count_buildings[schematic_index] = count_buildings[schematic_index] + 1 number_built = number_built + 1 break end @@ -227,10 +231,10 @@ end local function terraform(plan, minp, maxp, pr) local fheight, fwidth, fdepth, schematic_data, pos, rotation for _, built_house in pairs(plan) do - schematic_data = plan[i].building - pos = plan[i].pos - rotation = plan[i].rotation - if rotation == "0" or rotation = "180" then + schematic_data = built_house.building + pos = built_house.pos + rotation = built_house.rotation + if rotation == "0" or rotation == "180" then fwidth = schematic_data.hwidth fdepth = schematic_data.hdepth else @@ -243,7 +247,7 @@ local function terraform(plan, minp, maxp, pr) for yi = pos.y, math_min(pos.y + fheight * 3, maxp.y) do local p = {x = xi, y = yi, z = zi} if yi == pos.y then - ground(p, pr) + ground(p, minp, maxp, pr) else minetest_swap_node(p, {name = "air"}) end @@ -253,21 +257,24 @@ local function terraform(plan, minp, maxp, pr) end end -local function paths(plan) - local starting_point - local end_point - local distance - starting_point = plan[1].pos - for o, p in pairs(plan) do - end_point = settlement_info[o].pos - local path = minetest.find_path(starting_point, end_point, mcl_mapgen.CS_NODES, 2, 2) +local function paths(plan, minp, maxp) + local starting_point = find_surface({x = plan[1].pos.x + 2, z = plan[1].pos.z + 2}, minp, maxp) + if not starting_point then return end + starting_point.y = starting_point.y + 1 + for i = 2, #plan do + local p = plan[i] + local end_point = p.pos + end_point.y = end_point.y + 1 + local path = minetest.find_path(starting_point, end_point, mcl_mapgen.CS_NODES, 2, 2, "A*_noprefetch") if path then for _, pos in pairs(path) do + pos.y = pos.y - 1 + local surface_mat = minetest.get_node(pos).name if surface_mat == "mcl_core:sand" or surface_mat == "mcl_core:redsand" then - minetest.swap_node(surface_point, {name = "mcl_core:sandstonesmooth2"}) + minetest.swap_node(pos, {name = "mcl_core:sandstonesmooth2"}) else - minetest.swap_node(surface_point, {name = "mcl_core:grass_path"}) + minetest.swap_node(pos, {name = "mcl_core:grass_path"}) end end end @@ -353,18 +360,11 @@ local function build_a_settlement(minp, maxp, pr) local pr = pr or PseudoRandom(mcl_mapgen.get_block_seed3(minp)) local plan = create_site_plan(minp, maxp, pr) if not plan then return end + paths(plan, minp, maxp) terraform(plan, minp, maxp, pr) - paths(plan) place_schematics(plan, pr) - - local center = vector.add(minp, mcl_mapgen.HALF_CS_NODES) - local center_surface = settlements.find_surface(center) - table.insert(villages, center_surface) + table.insert(villages, minp) storage:set_string("villages", minetest.serialize(villages)) - - -- save list to file - settlements.save() - end -- Disable natural generation in singlenode. @@ -375,27 +375,29 @@ if mg_name ~= "singlenode" then mcl_mapgen.register_mapgen(function(minp, maxp, chunkseed) if minp.y < minp_min then return end local pr = PseudoRandom(chunkseed * random_multiply + random_offset) + local random_number = pr:next(1, chance_per_chunk) local noise = mcl_structures_get_perlin_noise_level(minp) * noise_multiplier if (random_number + noise) < struct_threshold then return end local min, max = 9999999, -9999999 for i = 1, pr:next(5,10) do - local surface_point = settlements.find_surface( + local surface_point = find_surface( vector.add( vector.new( - pr:next(scan_offset, scan_last_node) + , + pr:next(scan_offset, scan_last_node), 0, - pr:next(0, scan_last_node) + scan_offset + pr:next(scan_offset, scan_last_node) ), minp - ) + ), + minp, + maxp ) if not surface_point then return end local y = surface_point.y - min = math.min(y, min) - max = math.max(y, max) + min = math_min(y, min) + max = math_max(y, max) end local height_difference = max - min - minetest.chat_send_all("height diff="..height_difference) if height_difference > max_height_difference then return end build_a_settlement(minp, maxp, chunkkseed) end, mcl_mapgen.order.VILLAGES) From f449ba8370cae9cbb41d87a87426242ade64a2fb Mon Sep 17 00:00:00 2001 From: kay27 Date: Wed, 9 Feb 2022 06:34:20 +0400 Subject: [PATCH 06/68] Fix terraform --- mods/MAPGEN/mcl_villages/README.md | 22 +++ mods/MAPGEN/mcl_villages/README.txt | 45 ------ mods/MAPGEN/mcl_villages/init.lua | 133 ++++++++++-------- .../mcl_villages/locale/mcl_villages.ru.tr | 2 + mods/MAPGEN/mcl_villages/mod.conf | 2 +- 5 files changed, 103 insertions(+), 101 deletions(-) create mode 100644 mods/MAPGEN/mcl_villages/README.md delete mode 100644 mods/MAPGEN/mcl_villages/README.txt create mode 100644 mods/MAPGEN/mcl_villages/locale/mcl_villages.ru.tr diff --git a/mods/MAPGEN/mcl_villages/README.md b/mods/MAPGEN/mcl_villages/README.md new file mode 100644 index 000000000..3d1531fb3 --- /dev/null +++ b/mods/MAPGEN/mcl_villages/README.md @@ -0,0 +1,22 @@ +# MCL_Villages version 1.0 +-------------------------- +Originally a fork of Rochambeau's "Settlements", fully rewritten for MineClone 5. + +## Using the mod +---------------- +This mod adds villages on world generation. + +## Credits +---------- + * This mod is originally based on "ruins" by BlockMen + + * Completely new schematics for MineClone2: + * MysticTempest - CC-BY-SA 4.0 + + * Basic conversion of Settlements mod for compatibility with MineClone2: MysticTempest + + * Reimplemention: kay27 + +## License +---------- + * License of source code: WTFPL diff --git a/mods/MAPGEN/mcl_villages/README.txt b/mods/MAPGEN/mcl_villages/README.txt deleted file mode 100644 index 7573084d8..000000000 --- a/mods/MAPGEN/mcl_villages/README.txt +++ /dev/null @@ -1,45 +0,0 @@ -MCL_Villages: -============================ -A fork of Rochambeau's "Settlements" mod converted for use in MineClone5. - --------------- -Using the mod: --------------- -This mod adds settlements on world generation. - -And, in Creative Mode; also comes with a debug tool for spawning in villages. - - -------------- -MCL2 Credits: -------------- -Code forked from: https://github.com/MysticTempest/settlements/tree/mcl_villages - Commit: e24b4be -================================================================================ -Basic conversion of Settlements mod for compatibility with MineClone2, plus new schematics: MysticTempest - -Seed-based Village Generation, multi-threading, bugfixes: kay27 - - - -========================= -version: 0.1 alpha - -License of source code: WTFPL ------------------------------ -(c) Copyright Rochambeau (2018) - -This program is free software. It comes without any warranty, to -the extent permitted by applicable law. You can redistribute it -and/or modify it under the terms of the Do What The Fuck You Want -To Public License, Version 2, as published by Sam Hocevar. See -http://sam.zoy.org/wtfpl/COPYING for more details. - - -Credits: --------------- -This mod is based on "ruins" by BlockMen - -Completely new schematics for MineClone2: -MysticTempest - CC-BY-SA 4.0 - diff --git a/mods/MAPGEN/mcl_villages/init.lua b/mods/MAPGEN/mcl_villages/init.lua index 3a0bcfa7c..6009539da 100644 --- a/mods/MAPGEN/mcl_villages/init.lua +++ b/mods/MAPGEN/mcl_villages/init.lua @@ -15,7 +15,7 @@ local basic_pseudobiome_villages = minetest.settings:get_bool("basic_pseudobiome local schem_path = modpath .. "/schematics/" local 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 = "blacksmith", mts = schem_path.."blacksmith.mts", hwidth = 7, hdepth = 11, hheight = 7, 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 }, @@ -27,13 +27,13 @@ local schematic_table = { {name = "well", mts = schem_path.."well.mts", hwidth = 6, hdepth = 8, hheight = 6, hsize = 10, max_num = 0.045, rplc = basic_pseudobiome_villages }, } local surface_mat = { - ["mcl_core:dirt_with_dry_grass"] = true, - ["mcl_core:dirt_with_grass"] = true, - ["mcl_core:dirt_with_grass_snow"] = true, - ["mcl_core:podzol"] = true, - ["mcl_core:redsand"] = true, - ["mcl_core:sand"] = true, - ["mcl_core:snow"] = true, + ["mcl_core:dirt_with_dry_grass"] = { top = "mcl_core:dirt", bottom = "mcl_core:stone" }, + ["mcl_core:dirt_with_grass"] = { top = "mcl_core:dirt", bottom = "mcl_core:stone" }, + ["mcl_core:dirt_with_grass_snow"] = { top = "mcl_core:dirt", bottom = "mcl_core:stone" }, + ["mcl_core:podzol"] = { top = "mcl_core:podzol", bottom = "mcl_core:stone" }, + ["mcl_core:redsand"] = { top = "mcl_core:redsand", bottom = "mcl_core:redsandstone" }, + ["mcl_core:sand"] = { top = "mcl_core:sand", bottom = "mcl_core:sandstone" }, + ["mcl_core:snow"] = { top = "mcl_core:dirt", bottom = "mcl_core:stone" }, } local storage = minetest.get_mod_storage() local villages = minetest.deserialize(storage:get_string("villages") or "return {}") or {} @@ -48,8 +48,10 @@ local math_min = math.min local math_max = math.max local math_floor = math.floor local math_ceil = math.ceil +local string_find = string.find local minetest_swap_node = minetest.swap_node local minetest_registered_nodes = minetest.registered_nodes +local minetest_bulk_set_node = minetest.bulk_set_node local air_offset = chunk_offset_top - 1 local ground_offset = chunk_offset_bottom + 1 local surface_search_list = {} @@ -72,13 +74,13 @@ local function find_surface(pos, minp, maxp) local nodes = minetest_find_nodes_in_area({x=x, y=y_min, z=z}, {x=x, y=y_max, z=z}, surface_search_list) for _, surface_pos in pairs(nodes) do local node_name_from_above = minetest_get_node({x=surface_pos.x, y=surface_pos.y+1, z=surface_pos.z}).name - if string.find(node_name_from_above, "air" ) - or string.find(node_name_from_above, "snow" ) - or string.find(node_name_from_above, "fern" ) - or string.find(node_name_from_above, "flower") - or string.find(node_name_from_above, "bush" ) - or string.find(node_name_from_above, "tree" ) - or string.find(node_name_from_above, "grass" ) + if string_find(node_name_from_above, "air" ) + or string_find(node_name_from_above, "snow" ) + or string_find(node_name_from_above, "fern" ) + or string_find(node_name_from_above, "flower") + or string_find(node_name_from_above, "bush" ) + or string_find(node_name_from_above, "tree" ) + or string_find(node_name_from_above, "grass" ) then return surface_pos, minetest_get_node(surface_pos).name end @@ -212,49 +214,69 @@ local function create_site_plan(minp, maxp, pr) return plan end -local function ground(pos, minp, maxp, pr) - local p2 = vector.new(pos) - local cnt = 0 - local mat = "mcl_core:dirt" - p2.y = p2.y - 1 - local min_y = math_max(minp.y, p2.y - pr:next(17,27)) - local stone_level = p2.y - pr:next(2, 4) - while p2.y >= min_y do - if p2.y == stone_level then - mat = "mcl_core:stone" - end - minetest.swap_node(p2, {name=mat}) - p2.y = p2.y - 1 - end -end - -local function terraform(plan, minp, maxp, pr) - local fheight, fwidth, fdepth, schematic_data, pos, rotation - for _, built_house in pairs(plan) do - schematic_data = built_house.building - pos = built_house.pos - rotation = built_house.rotation - if rotation == "0" or rotation == "180" then - fwidth = schematic_data.hwidth - fdepth = schematic_data.hdepth - else - fwidth = schematic_data.hdepth - fdepth = schematic_data.hwidth - end - fheight = schematic_data.hheight - for xi = pos.x, pos.x + fwidth - 1 do - for zi = pos.z, pos.z + fdepth - 1 do - for yi = pos.y, math_min(pos.y + fheight * 3, maxp.y) do - local p = {x = xi, y = yi, z = zi} - if yi == pos.y then - ground(p, minp, maxp, pr) - else - minetest_swap_node(p, {name = "air"}) +local function ground(pos1, pos2, minp, maxp, pr, mat) + local pos1, pos2 = pos1, pos2 + local x1, x2, z1, z2, y = pos1.x, pos2.x, pos1.z, pos2.z, pos1.y - 1 + local pos_list_dirt = {} + local pos_list_stone = {} + for x0 = x1, x2 do + for z0 = z1, z2 do + local finish = false + local y1 = y - pr:next(2, 4) + for y0 = y, y1, -1 do + local p0 = {x = x0, y = y0, z = z0} + local node = minetest_get_node(p0) + local node_name = node.name + if node_name ~= "air" and not string_find(node_name, "water") and not string_find(node_name, "flower") then + finish = true + break + end + pos_list_dirt[#pos_list_dirt + 1] = p0 + end + if not finish then + for y0 = y1 - 1, math_max(minp.y, y - pr:next(17, 27)), -1 do + local p0 = {x = x0, y = y0, z = z0} + local node = minetest_get_node(p0) + local node_name = node.name + if node_name ~= "air" and not string_find(node_name, "water") and not string_find(node_name, "flower") then + break end + pos_list_stone[#pos_list_stone + 1] = p0 end end end end + minetest_bulk_set_node(pos_list_dirt, {name = surface_mat[mat].top}) + minetest_bulk_set_node(pos_list_stone, {name = surface_mat[mat].bottom}) +end + +local function terraform(plan, minp, maxp, pr) + local fheight, fwidth, fdepth, schematic_data, pos, rotation, swap_wd, build_material + for _, built_house in pairs(plan) do + schematic_data = built_house.building + pos = built_house.pos + rotation = built_house.rotation + build_material = built_house.surface_mat + swap_wd = rotation == "90" or rotation == "270" + fwidth = swap_wd and schematic_data.hdepth or schematic_data.hwidth + fdepth = swap_wd and schematic_data.hwidth or schematic_data.hdepth + fheight = schematic_data.hheight + local pos2 = { + x = pos.x + fwidth - 1, + y = math_min(pos.y + fheight * 3, maxp.y), + z = pos.z + fdepth - 1 + } + ground(pos, {x = pos2.x, y = pos.y, z = pos2.z}, minp, maxp, pr, build_material) + local node_list = {} + for xi = pos.x, pos2.x do + for zi = pos.z, pos2.z do + for yi = pos.y, pos2.y do + node_list[#node_list + 1] = {x = xi, y = yi, z = zi} + end + end + end + minetest_bulk_set_node(node_list, {name = "air"}) + end end local function paths(plan, minp, maxp) @@ -283,12 +305,13 @@ end local function init_nodes(p1, rotation, pr, size) local p2 = vector.subtract(vector.add(p1, size), 1) - local nodes = minetest.find_nodes_in_area(p1, p2, {"mcl_itemframes:item_frame", "mcl_furnaces:furnace", "mcl_anvils:anvil"}) + local nodes = minetest.find_nodes_in_area(p1, p2, {"mcl_itemframes:item_frame", "mcl_furnaces:furnace", "mcl_anvils:anvil", "mcl_chests:chest"}) for _, pos in pairs(nodes) do local name = minetest_get_node(pos).name local def = minetest_registered_nodes[minetest_get_node(pos).name] def.on_construct(pos) if name == "mcl_chests:chest" then + minetest_swap_node(pos, {name = "mcl_chests:chest_small"}) fill_chest(pos, pr) end end @@ -363,7 +386,7 @@ local function build_a_settlement(minp, maxp, pr) paths(plan, minp, maxp) terraform(plan, minp, maxp, pr) place_schematics(plan, pr) - table.insert(villages, minp) + villages[#villages + 1] = minp storage:set_string("villages", minetest.serialize(villages)) end diff --git a/mods/MAPGEN/mcl_villages/locale/mcl_villages.ru.tr b/mods/MAPGEN/mcl_villages/locale/mcl_villages.ru.tr new file mode 100644 index 000000000..467f31121 --- /dev/null +++ b/mods/MAPGEN/mcl_villages/locale/mcl_villages.ru.tr @@ -0,0 +1,2 @@ +# textdomain: mcl_villages +Chiseled Stone Village Bricks=Точёный каменный блок из деревни diff --git a/mods/MAPGEN/mcl_villages/mod.conf b/mods/MAPGEN/mcl_villages/mod.conf index 3f9a67bb3..eb4a5d080 100644 --- a/mods/MAPGEN/mcl_villages/mod.conf +++ b/mods/MAPGEN/mcl_villages/mod.conf @@ -1,5 +1,5 @@ name = mcl_villages author = Rochambeau, MysticTempest, kay27 -description = This mod adds settlements on world generation. +description = This mod adds villages on world generation. depends = mcl_util, mcl_structures, mcl_core, mcl_loot, mcl_mapgen optional_depends = mcl_farming, mobs_mc From 200536b41601bf1ceb4bfede3982bbb1ff4c3cc3 Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 01:20:30 +0000 Subject: [PATCH 07/68] #198 Fix a crash, step 1 --- mods/HELP/doc/doc/init.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mods/HELP/doc/doc/init.lua b/mods/HELP/doc/doc/init.lua index 304900753..df675bf1d 100644 --- a/mods/HELP/doc/doc/init.lua +++ b/mods/HELP/doc/doc/init.lua @@ -1124,10 +1124,10 @@ minetest.register_chatcommand("helpform", { } ) -minetest.register_on_joinplayer(function(player) - local playername = player:get_player_name() +minetest.register_on_authplayer(function(playername, ip, is_success) + if not is_success then return end local playerdata = doc.data.players[playername] - if playerdata == nil then + if not playerdata then -- Initialize player data doc.data.players[playername] = {} playerdata = doc.data.players[playername] @@ -1171,7 +1171,9 @@ minetest.register_on_joinplayer(function(player) playerdata.stored_data.revealed_count[cid] = rc end end +end +minetest.register_on_joinplayer(function(player) -- Add button for Inventory++ if mod_inventory_plus then inventory_plus.register_button(player, "doc_inventory_plus", S("Help")) From eaa8df9e55963e0536e7f3cbd097969fc1255b7a Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 01:23:01 +0000 Subject: [PATCH 08/68] #198 Fix a crash, step 2 --- mods/HUD/mcl_bossbars/init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/HUD/mcl_bossbars/init.lua b/mods/HUD/mcl_bossbars/init.lua index f1d99e013..be2ed2a2a 100644 --- a/mods/HUD/mcl_bossbars/init.lua +++ b/mods/HUD/mcl_bossbars/init.lua @@ -102,8 +102,8 @@ function mcl_bossbars.update_boss(object, name, color) end end -minetest.register_on_joinplayer(function(player) - local name = player:get_player_name() +minetest.register_on_authplayer(function(name, ip, is_success) + if not is_success then return end mcl_bossbars.huds[name] = {} mcl_bossbars.bars[name] = {} end) From ce0e643cad119fd8f5125a71a2a3a441afa5277f Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 01:23:55 +0000 Subject: [PATCH 09/68] #198 Fix a crash, step 3 --- mods/HELP/doc/doc/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/HELP/doc/doc/init.lua b/mods/HELP/doc/doc/init.lua index df675bf1d..fc684246b 100644 --- a/mods/HELP/doc/doc/init.lua +++ b/mods/HELP/doc/doc/init.lua @@ -1171,7 +1171,7 @@ minetest.register_on_authplayer(function(playername, ip, is_success) playerdata.stored_data.revealed_count[cid] = rc end end -end +end) minetest.register_on_joinplayer(function(player) -- Add button for Inventory++ From 8b441a81567b75f01439b690aea651144f951cbb Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 01:36:38 +0000 Subject: [PATCH 10/68] #198 Fix a crash, step 4 --- mods/ITEMS/mcl_shields/init.lua | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_shields/init.lua b/mods/ITEMS/mcl_shields/init.lua index 913a7005d..ef0e7ba43 100644 --- a/mods/ITEMS/mcl_shields/init.lua +++ b/mods/ITEMS/mcl_shields/init.lua @@ -2,6 +2,8 @@ local minetest, math, vector = minetest, math, vector local modname = minetest.get_current_modname() local S = minetest.get_translator(modname) +local possible_hackers = {} + mcl_shields = { types = { mob = true, @@ -287,8 +289,7 @@ local function update_shield_entity(player, blocking, i) end minetest.register_globalstep(function(dtime) - for _, player in pairs(minetest.get_connected_players()) do - + for _, player in pairs(minetest.get_connected_players()) do if not possible_hackers[player:get_player_name()] then handle_blocking(player) local blocking, shieldstack = mcl_shields.is_blocking(player) @@ -360,7 +361,7 @@ minetest.register_globalstep(function(dtime) for i = 1, 2 do update_shield_entity(player, blocking, i) end - end + end end end) minetest.register_on_dieplayer(function(player) @@ -462,7 +463,13 @@ minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv return craft_banner_on_shield(itemstack, player, old_craft_grid, craft_inv) end) +minetest.register_on_authplayer(function(name, ip, is_success) + if not is_success then return end + possible_hackers[name] = true +end) + minetest.register_on_joinplayer(function(player) + possible_hackers[player:get_player_name()] = nil mcl_shields.players[player] = { shields = {}, blocking = 0, From e9e3479fb3d7a5225aa31918ebe7e34a38cd45a2 Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 01:41:26 +0000 Subject: [PATCH 11/68] #198 Fix a crash, step 5 --- mods/ITEMS/mcl_fireworks/register.lua | 3 ++- mods/PLAYER/mcl_anticheat/init.lua | 2 +- mods/PLAYER/mcl_playerplus/init.lua | 11 +++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/mods/ITEMS/mcl_fireworks/register.lua b/mods/ITEMS/mcl_fireworks/register.lua index 23066b663..5ea31a798 100644 --- a/mods/ITEMS/mcl_fireworks/register.lua +++ b/mods/ITEMS/mcl_fireworks/register.lua @@ -10,7 +10,8 @@ local function register_rocket(n, duration, force) inventory_image = "mcl_fireworks_rocket.png", stack_max = 64, on_use = function(itemstack, user, pointed_thing) - local elytra = mcl_playerplus.elytra[user] + if not user:is_player then return end + local elytra = mcl_playerplus.elytra[user:get_player_name()] if elytra.active and elytra.rocketing <= 0 then elytra.rocketing = duration if not minetest.is_creative_enabled(user:get_player_name()) then diff --git a/mods/PLAYER/mcl_anticheat/init.lua b/mods/PLAYER/mcl_anticheat/init.lua index 9f4078007..f4a3ac909 100644 --- a/mods/PLAYER/mcl_anticheat/init.lua +++ b/mods/PLAYER/mcl_anticheat/init.lua @@ -39,7 +39,7 @@ local function update_player(player_object) local feet_y, head_y = floor(pos.y-0.1), floor(pos.y + 1.49) if mcl_playerplus.elytra then - local elytra = mcl_playerplus.elytra[player_object] + local elytra = mcl_playerplus.elytra[name] if elytra and elytra.active then return end diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index 720c11525..88107442e 100644 --- a/mods/PLAYER/mcl_playerplus/init.lua +++ b/mods/PLAYER/mcl_playerplus/init.lua @@ -275,7 +275,7 @@ minetest.register_globalstep(function(dtime) local fly_pos = player:get_pos() local fly_node = minetest.get_node({x = fly_pos.x, y = fly_pos.y - 0.5, z = fly_pos.z}).name - local elytra = mcl_playerplus.elytra[player] + local elytra = mcl_playerplus.elytra[name] elytra.active = player:get_inventory():get_stack("armor", 3):get_name() == "mcl_armor:elytra" and not player:get_attach() @@ -625,15 +625,14 @@ minetest.register_globalstep(function(dtime) end) -- set to blank on join (for 3rd party mods) -minetest.register_on_joinplayer(function(player) - local name = player:get_player_name() - +minetest.register_on_authplayer(function(name, ip, is_success) + if not is_success then return end mcl_playerplus_internal[name] = { lastPos = nil, swimDistance = 0, jump_cooldown = -1, -- Cooldown timer for jumping, we need this to prevent the jump exhaustion to increase rapidly } - mcl_playerplus.elytra[player] = {active = false, rocketing = 0} + mcl_playerplus.elytra[name] = {active = false, rocketing = 0} end) -- clear when player leaves @@ -641,7 +640,7 @@ minetest.register_on_leaveplayer(function(player) local name = player:get_player_name() mcl_playerplus_internal[name] = nil - mcl_playerplus.elytra[player] = nil + mcl_playerplus.elytra[name] = nil end) -- Don't change HP if the player falls in the water or through End Portal: From 3984c72bbc6fdffb1ff2022fdf3cf45d070be24c Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 01:43:05 +0000 Subject: [PATCH 12/68] #198 Fix a crash, step 6 --- mods/ITEMS/mcl_fireworks/register.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_fireworks/register.lua b/mods/ITEMS/mcl_fireworks/register.lua index 5ea31a798..f113a6678 100644 --- a/mods/ITEMS/mcl_fireworks/register.lua +++ b/mods/ITEMS/mcl_fireworks/register.lua @@ -10,7 +10,7 @@ local function register_rocket(n, duration, force) inventory_image = "mcl_fireworks_rocket.png", stack_max = 64, on_use = function(itemstack, user, pointed_thing) - if not user:is_player then return end + if not user:is_player() then return end local elytra = mcl_playerplus.elytra[user:get_player_name()] if elytra.active and elytra.rocketing <= 0 then elytra.rocketing = duration From 52e2e2506b2c75ec9e22603249ddd857756cd6ef Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 01:48:09 +0000 Subject: [PATCH 13/68] #198 Fix a crash, step 7 --- mods/HELP/mcl_craftguide/init.lua | 6 +++++- mods/PLAYER/mcl_playerinfo/init.lua | 5 ++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/mods/HELP/mcl_craftguide/init.lua b/mods/HELP/mcl_craftguide/init.lua index 3bc7b705a..989f1a2b5 100644 --- a/mods/HELP/mcl_craftguide/init.lua +++ b/mods/HELP/mcl_craftguide/init.lua @@ -1093,9 +1093,13 @@ if progressive_mode then mcl_craftguide.add_recipe_filter("Default progressive filter", progressive_filter) + M.register_on_authplayer(function(name, ip, is_success) + if not is_success then return + init_data(name) + end) + M.register_on_joinplayer(function(player) local name = player:get_player_name() - init_data(name) local meta = player:get_meta() local data = player_data[name] diff --git a/mods/PLAYER/mcl_playerinfo/init.lua b/mods/PLAYER/mcl_playerinfo/init.lua index 9c5d1433f..1ff5add71 100644 --- a/mods/PLAYER/mcl_playerinfo/init.lua +++ b/mods/PLAYER/mcl_playerinfo/init.lua @@ -73,9 +73,8 @@ minetest.register_globalstep(function(dtime) end) -- set to blank on join (for 3rd party mods) -minetest.register_on_joinplayer(function(player) - local name = player:get_player_name() - +minetest.register_on_authlayer(function(name, ip, is_success) + if not is_success then return end mcl_playerinfo[name] = { node_head = "", node_feet = "", From 89a016c0e645b61d988a96f25c90628bf26cb121 Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 02:01:01 +0000 Subject: [PATCH 14/68] #198 Fix a crash, step 8 --- mods/HELP/mcl_craftguide/init.lua | 24 ++++++++++++++++-------- mods/ITEMS/mcl_shields/init.lua | 11 ++++++++++- mods/PLAYER/mcl_playerinfo/init.lua | 2 +- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/mods/HELP/mcl_craftguide/init.lua b/mods/HELP/mcl_craftguide/init.lua index 989f1a2b5..f75ab07f7 100644 --- a/mods/HELP/mcl_craftguide/init.lua +++ b/mods/HELP/mcl_craftguide/init.lua @@ -1,5 +1,7 @@ mcl_craftguide = {} +local awaiting_connection_player_names = {} + local M = minetest local player_data = {} @@ -1075,12 +1077,14 @@ if progressive_mode then for i = 1, #players do local player = players[i] local name = player:get_player_name() - local data = player_data[name] - local inv_items = get_inv_items(player) - local diff = table_diff(inv_items, data.inv_items) + if not awaiting_connection_player_names[name] then + local data = player_data[name] + local inv_items = get_inv_items(player) + local diff = table_diff(inv_items, data.inv_items) - if #diff > 0 then - data.inv_items = table_merge(diff, data.inv_items) + if #diff > 0 then + data.inv_items = table_merge(diff, data.inv_items) + end end end @@ -1094,12 +1098,14 @@ if progressive_mode then mcl_craftguide.add_recipe_filter("Default progressive filter", progressive_filter) M.register_on_authplayer(function(name, ip, is_success) - if not is_success then return - init_data(name) + if not is_success then return end + awaiting_connection_player_names[name] = true end) M.register_on_joinplayer(function(player) local name = player:get_player_name() + awaiting_connection_player_names[name] = nil + init_data(name) local meta = player:get_meta() local data = player_data[name] @@ -1130,7 +1136,9 @@ if progressive_mode then local players = M.get_connected_players() for i = 1, #players do local player = players[i] - save_meta(player) + if not awaiting_connection_player_names[player:get_player_name()] then + save_meta(player) + end end end) else diff --git a/mods/ITEMS/mcl_shields/init.lua b/mods/ITEMS/mcl_shields/init.lua index ef0e7ba43..04bb42db3 100644 --- a/mods/ITEMS/mcl_shields/init.lua +++ b/mods/ITEMS/mcl_shields/init.lua @@ -24,6 +24,15 @@ interact_priv.give_to_admin = false local overlay = mcl_enchanting.overlay local hud = "mcl_shield_hud.png" +local function is_player_for_real(obj) + if not obj then return end + if not obj:is_player() then return end + local name = obj:get_player_name() + if not name then return end + if possible_hackers[name] then return end + return true +end + minetest.register_tool("mcl_shields:shield", { description = S("Shield"), _doc_items_longdesc = S("A shield is a tool used for protecting the player against attacks."), @@ -123,7 +132,7 @@ mcl_damage.register_modifier(function(obj, damage, reason) local type = reason.type local damager = reason.direct local blocking, shieldstack = mcl_shields.is_blocking(obj) - if obj:is_player() and blocking and mcl_shields.types[type] and damager then + if is_player_for_real(obj) and blocking and mcl_shields.types[type] and damager then local entity = damager:get_luaentity() if entity and (type == "arrow" or type == "generic") then damager = entity._shooter diff --git a/mods/PLAYER/mcl_playerinfo/init.lua b/mods/PLAYER/mcl_playerinfo/init.lua index 1ff5add71..6c714c78b 100644 --- a/mods/PLAYER/mcl_playerinfo/init.lua +++ b/mods/PLAYER/mcl_playerinfo/init.lua @@ -73,7 +73,7 @@ minetest.register_globalstep(function(dtime) end) -- set to blank on join (for 3rd party mods) -minetest.register_on_authlayer(function(name, ip, is_success) +minetest.register_on_authplayer(function(name, ip, is_success) if not is_success then return end mcl_playerinfo[name] = { node_head = "", From 636be37c851ea82047a332f41e6465f526920f60 Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 06:06:34 +0400 Subject: [PATCH 15/68] #198 Fix a crash, step 9 --- mods/ITEMS/mcl_shields/init.lua | 13 +++---------- mods/PLAYER/mcl_playerplus/init.lua | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/mods/ITEMS/mcl_shields/init.lua b/mods/ITEMS/mcl_shields/init.lua index 04bb42db3..cfcd721fb 100644 --- a/mods/ITEMS/mcl_shields/init.lua +++ b/mods/ITEMS/mcl_shields/init.lua @@ -21,18 +21,11 @@ local interact_priv = minetest.registered_privileges.interact interact_priv.give_to_singleplayer = false interact_priv.give_to_admin = false +local is_player = mcl_playerplus.is_player + local overlay = mcl_enchanting.overlay local hud = "mcl_shield_hud.png" -local function is_player_for_real(obj) - if not obj then return end - if not obj:is_player() then return end - local name = obj:get_player_name() - if not name then return end - if possible_hackers[name] then return end - return true -end - minetest.register_tool("mcl_shields:shield", { description = S("Shield"), _doc_items_longdesc = S("A shield is a tool used for protecting the player against attacks."), @@ -132,7 +125,7 @@ mcl_damage.register_modifier(function(obj, damage, reason) local type = reason.type local damager = reason.direct local blocking, shieldstack = mcl_shields.is_blocking(obj) - if is_player_for_real(obj) and blocking and mcl_shields.types[type] and damager then + if is_player(obj) and blocking and mcl_shields.types[type] and damager then local entity = damager:get_luaentity() if entity and (type == "arrow" or type == "generic") then damager = entity._shooter diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index 88107442e..1616e3e68 100644 --- a/mods/PLAYER/mcl_playerplus/init.lua +++ b/mods/PLAYER/mcl_playerplus/init.lua @@ -17,6 +17,8 @@ local is_sprinting = mcl_sprint.is_sprinting local exhaust = mcl_hunger.exhaust local playerphysics = playerphysics +local is_player = mcl_player.is_player + local vector = vector local math = math -- Internal player state @@ -25,6 +27,17 @@ local mcl_playerplus_internal = {} local time = 0 local look_pitch = 0 +function mcl_playerplus.is_player(obj) + if not obj then return end + if not obj:is_player() then return end + local name = obj:get_player_name() + if not name then return end + if possible_hackers[name] then return end + return true +end + +local is_player = mcl_playerplus.is_player + local function player_collision(player) local pos = player:get_pos() @@ -35,7 +48,7 @@ local function player_collision(player) for _,object in pairs(minetest.get_objects_inside_radius(pos, width)) do - if object and (object:is_player() + if object and (is_player(object) or (object:get_luaentity()._cmi_is_mob == true and object ~= player)) then local pos2 = object:get_pos() From 7e9388b80d8c050ff807c1fe64c0541949a57937 Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 06:15:03 +0400 Subject: [PATCH 16/68] #198 Fix a crash, step 10 --- mods/ENTITIES/mcl_item_entity/init.lua | 5 ++--- mods/ITEMS/mcl_shields/init.lua | 11 +++++++++-- mods/PLAYER/mcl_player/mod.conf | 1 + mods/PLAYER/mcl_playerplus/init.lua | 4 +--- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index 91e152ca1..f9a717455 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -6,9 +6,8 @@ local pool = {} local tick = false -minetest.register_on_joinplayer(function(player) - local name - name = player:get_player_name() +minetest.register_on_authplayer(function(name, ip, is_success) + if not is_success then return end pool[name] = 0 end) diff --git a/mods/ITEMS/mcl_shields/init.lua b/mods/ITEMS/mcl_shields/init.lua index cfcd721fb..671c42c76 100644 --- a/mods/ITEMS/mcl_shields/init.lua +++ b/mods/ITEMS/mcl_shields/init.lua @@ -21,11 +21,18 @@ local interact_priv = minetest.registered_privileges.interact interact_priv.give_to_singleplayer = false interact_priv.give_to_admin = false -local is_player = mcl_playerplus.is_player - local overlay = mcl_enchanting.overlay local hud = "mcl_shield_hud.png" +function is_player(obj) + if not obj then return end + if not obj:is_player() then return end + local name = obj:get_player_name() + if not name then return end + if possible_hackers[name] then return end + return true +end + minetest.register_tool("mcl_shields:shield", { description = S("Shield"), _doc_items_longdesc = S("A shield is a tool used for protecting the player against attacks."), diff --git a/mods/PLAYER/mcl_player/mod.conf b/mods/PLAYER/mcl_player/mod.conf index 97ccce8e6..d092bd3f3 100644 --- a/mods/PLAYER/mcl_player/mod.conf +++ b/mods/PLAYER/mcl_player/mod.conf @@ -1,3 +1,4 @@ name = mcl_player author = celeron55 description = Adds the 3D player model, taken from Minetest Game 0.4.16. +depends = mcl_shields diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index 1616e3e68..6a191a05a 100644 --- a/mods/PLAYER/mcl_playerplus/init.lua +++ b/mods/PLAYER/mcl_playerplus/init.lua @@ -27,7 +27,7 @@ local mcl_playerplus_internal = {} local time = 0 local look_pitch = 0 -function mcl_playerplus.is_player(obj) +function is_player(obj) if not obj then return end if not obj:is_player() then return end local name = obj:get_player_name() @@ -36,8 +36,6 @@ function mcl_playerplus.is_player(obj) return true end -local is_player = mcl_playerplus.is_player - local function player_collision(player) local pos = player:get_pos() From b86446df3483e4463aeb88708cab711501a32882 Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 06:18:07 +0400 Subject: [PATCH 17/68] #198 Fix a crash, step 11 --- mods/ENTITIES/mcl_item_entity/init.lua | 17 +++++++++++++---- mods/PLAYER/mcl_player/mod.conf | 1 - 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index f9a717455..521c94486 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -42,6 +42,15 @@ item_drop_settings.drop_single_item = false --if true, the drop control dro item_drop_settings.magnet_time = 0.75 -- how many seconds an item follows the player before giving up +function is_player(obj) + if not obj then return end + if not obj:is_player() then return end + local name = obj:get_player_name() + if not name then return end + if possible_hackers[name] then return end + return true +end + local function get_gravity() return tonumber(minetest.settings:get("movement_gravity")) or 9.81 end @@ -132,7 +141,7 @@ minetest.register_globalstep(function(dtime) --magnet and collection for _,object in pairs(minetest.get_objects_inside_radius(checkpos, item_drop_settings.xp_radius_magnet)) do - if not object:is_player() and vector.distance(checkpos, object:get_pos()) < item_drop_settings.radius_magnet and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" and object:get_luaentity()._magnet_timer and (object:get_luaentity()._insta_collect or (object:get_luaentity().age > item_drop_settings.age)) then + if not is_player(object) and vector.distance(checkpos, object:get_pos()) < item_drop_settings.radius_magnet and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" and object:get_luaentity()._magnet_timer and (object:get_luaentity()._insta_collect or (object:get_luaentity().age > item_drop_settings.age)) then if object:get_luaentity()._magnet_timer >= 0 and object:get_luaentity()._magnet_timer < item_drop_settings.magnet_time and inv and inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then @@ -166,7 +175,7 @@ minetest.register_globalstep(function(dtime) end end - elseif not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "mcl_experience:orb" then + elseif not is_player(object) and object:get_luaentity() and object:get_luaentity().name == "mcl_experience:orb" then local entity = object:get_luaentity() entity.collector = player:get_player_name() entity.collected = true @@ -229,7 +238,7 @@ function minetest.handle_node_drops(pos, drops, digger) -- This means there is no digger. This is a special case which allows this function to be called -- by hand. Creative Mode is intentionally ignored in this case. - if (digger and digger:is_player() and minetest.is_creative_enabled(digger:get_player_name())) or doTileDrops == false then + if (digger and is_player(digger) and minetest.is_creative_enabled(digger:get_player_name())) or doTileDrops == false then return end @@ -339,7 +348,7 @@ end -- Drop single items by default function minetest.item_drop(itemstack, dropper, pos) - if dropper and dropper:is_player() then + if dropper and is_player(dropper) then local v = dropper:get_look_dir() local p = {x=pos.x, y=pos.y+1.2, z=pos.z} local cs = itemstack:get_count() diff --git a/mods/PLAYER/mcl_player/mod.conf b/mods/PLAYER/mcl_player/mod.conf index d092bd3f3..97ccce8e6 100644 --- a/mods/PLAYER/mcl_player/mod.conf +++ b/mods/PLAYER/mcl_player/mod.conf @@ -1,4 +1,3 @@ name = mcl_player author = celeron55 description = Adds the 3D player model, taken from Minetest Game 0.4.16. -depends = mcl_shields From 1537232f17e29cc3631f7e5fa75d36f76c59cc67 Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 06:23:27 +0400 Subject: [PATCH 18/68] #198 Fix a crash, step 12 --- mods/CORE/mcl_util/init.lua | 20 ++++++++++++++++++++ mods/ENTITIES/mcl_item_entity/init.lua | 9 +-------- mods/ENTITIES/mcl_item_entity/mod.conf | 2 +- mods/ITEMS/mcl_shields/init.lua | 19 ++----------------- mods/PLAYER/mcl_playerplus/init.lua | 9 --------- 5 files changed, 24 insertions(+), 35 deletions(-) diff --git a/mods/CORE/mcl_util/init.lua b/mods/CORE/mcl_util/init.lua index 50e3d61fc..3a634637a 100644 --- a/mods/CORE/mcl_util/init.lua +++ b/mods/CORE/mcl_util/init.lua @@ -498,3 +498,23 @@ function mcl_util.get_pointed_thing(player) end end end + +local possible_hackers = {} + +function mcl_util.is_player(obj) + if not obj then return end + if not obj:is_player() then return end + local name = obj:get_player_name() + if not name then return end + if possible_hackers[name] then return end + return true +end + +minetest.register_on_authplayer(function(name, ip, is_success) + if not is_success then return end + possible_hackers[name] = true +end) + +minetest.register_on_joinplayer(function(player) + possible_hackers[player:get_player_name()] = nil +end) diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index 521c94486..7b2b6c140 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -42,14 +42,7 @@ item_drop_settings.drop_single_item = false --if true, the drop control dro item_drop_settings.magnet_time = 0.75 -- how many seconds an item follows the player before giving up -function is_player(obj) - if not obj then return end - if not obj:is_player() then return end - local name = obj:get_player_name() - if not name then return end - if possible_hackers[name] then return end - return true -end +function is_player = mcl_util.is_player local function get_gravity() return tonumber(minetest.settings:get("movement_gravity")) or 9.81 diff --git a/mods/ENTITIES/mcl_item_entity/mod.conf b/mods/ENTITIES/mcl_item_entity/mod.conf index acd9f00f3..120b64aa7 100644 --- a/mods/ENTITIES/mcl_item_entity/mod.conf +++ b/mods/ENTITIES/mcl_item_entity/mod.conf @@ -1,4 +1,4 @@ name = mcl_item_entity author = PilzAdam description = Dropped items will be attracted to the player like a magnet. -depends = flowlib, mcl_enchanting +depends = flowlib, mcl_enchanting, mcl_util diff --git a/mods/ITEMS/mcl_shields/init.lua b/mods/ITEMS/mcl_shields/init.lua index 671c42c76..ab4fc70a4 100644 --- a/mods/ITEMS/mcl_shields/init.lua +++ b/mods/ITEMS/mcl_shields/init.lua @@ -2,8 +2,6 @@ local minetest, math, vector = minetest, math, vector local modname = minetest.get_current_modname() local S = minetest.get_translator(modname) -local possible_hackers = {} - mcl_shields = { types = { mob = true, @@ -24,14 +22,7 @@ interact_priv.give_to_admin = false local overlay = mcl_enchanting.overlay local hud = "mcl_shield_hud.png" -function is_player(obj) - if not obj then return end - if not obj:is_player() then return end - local name = obj:get_player_name() - if not name then return end - if possible_hackers[name] then return end - return true -end +local is_player = mcl_util.is_player minetest.register_tool("mcl_shields:shield", { description = S("Shield"), @@ -298,7 +289,7 @@ local function update_shield_entity(player, blocking, i) end minetest.register_globalstep(function(dtime) - for _, player in pairs(minetest.get_connected_players()) do if not possible_hackers[player:get_player_name()] then + for _, player in pairs(minetest.get_connected_players()) do if is_player(player) then handle_blocking(player) local blocking, shieldstack = mcl_shields.is_blocking(player) @@ -472,13 +463,7 @@ minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv return craft_banner_on_shield(itemstack, player, old_craft_grid, craft_inv) end) -minetest.register_on_authplayer(function(name, ip, is_success) - if not is_success then return end - possible_hackers[name] = true -end) - minetest.register_on_joinplayer(function(player) - possible_hackers[player:get_player_name()] = nil mcl_shields.players[player] = { shields = {}, blocking = 0, diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index 6a191a05a..40e667a0b 100644 --- a/mods/PLAYER/mcl_playerplus/init.lua +++ b/mods/PLAYER/mcl_playerplus/init.lua @@ -27,15 +27,6 @@ local mcl_playerplus_internal = {} local time = 0 local look_pitch = 0 -function is_player(obj) - if not obj then return end - if not obj:is_player() then return end - local name = obj:get_player_name() - if not name then return end - if possible_hackers[name] then return end - return true -end - local function player_collision(player) local pos = player:get_pos() From 1ef93eab377e4ab44acdb46a188b6cbe4eeb36f5 Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 02:25:19 +0000 Subject: [PATCH 19/68] #198 Fix a crash, step 13 --- mods/ENTITIES/mcl_item_entity/init.lua | 2 +- mods/ITEMS/mcl_shields/mod.conf | 2 +- mods/PLAYER/mcl_player/mod.conf | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index 7b2b6c140..b1202f4ad 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -42,7 +42,7 @@ item_drop_settings.drop_single_item = false --if true, the drop control dro item_drop_settings.magnet_time = 0.75 -- how many seconds an item follows the player before giving up -function is_player = mcl_util.is_player +local is_player = mcl_util.is_player local function get_gravity() return tonumber(minetest.settings:get("movement_gravity")) or 9.81 diff --git a/mods/ITEMS/mcl_shields/mod.conf b/mods/ITEMS/mcl_shields/mod.conf index 8aded6a62..f30807bf1 100644 --- a/mods/ITEMS/mcl_shields/mod.conf +++ b/mods/ITEMS/mcl_shields/mod.conf @@ -1,3 +1,3 @@ name = mcl_shields author = NO11 -depends = mcl_damage, mcl_enchanting, mcl_banners, mcl_util, playerphysics +depends = mcl_damage, mcl_enchanting, mcl_banners, mcl_util, playerphysics, mcl_playerplus diff --git a/mods/PLAYER/mcl_player/mod.conf b/mods/PLAYER/mcl_player/mod.conf index 97ccce8e6..d092bd3f3 100644 --- a/mods/PLAYER/mcl_player/mod.conf +++ b/mods/PLAYER/mcl_player/mod.conf @@ -1,3 +1,4 @@ name = mcl_player author = celeron55 description = Adds the 3D player model, taken from Minetest Game 0.4.16. +depends = mcl_shields From adec2cbeea7498543abd8b3bf3b0f8992a61fe19 Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 06:28:35 +0400 Subject: [PATCH 20/68] #198 Fix a crash, step 14 --- mods/ITEMS/mcl_shields/mod.conf | 2 +- mods/PLAYER/mcl_player/mod.conf | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_shields/mod.conf b/mods/ITEMS/mcl_shields/mod.conf index f30807bf1..8aded6a62 100644 --- a/mods/ITEMS/mcl_shields/mod.conf +++ b/mods/ITEMS/mcl_shields/mod.conf @@ -1,3 +1,3 @@ name = mcl_shields author = NO11 -depends = mcl_damage, mcl_enchanting, mcl_banners, mcl_util, playerphysics, mcl_playerplus +depends = mcl_damage, mcl_enchanting, mcl_banners, mcl_util, playerphysics diff --git a/mods/PLAYER/mcl_player/mod.conf b/mods/PLAYER/mcl_player/mod.conf index d092bd3f3..97ccce8e6 100644 --- a/mods/PLAYER/mcl_player/mod.conf +++ b/mods/PLAYER/mcl_player/mod.conf @@ -1,4 +1,3 @@ name = mcl_player author = celeron55 description = Adds the 3D player model, taken from Minetest Game 0.4.16. -depends = mcl_shields From d20551589f615c07bf338e089de86732874f9cb4 Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 06:29:53 +0400 Subject: [PATCH 21/68] #198 Fix a crash, step 15 --- mods/PLAYER/mcl_playerplus/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index 40e667a0b..9208f5862 100644 --- a/mods/PLAYER/mcl_playerplus/init.lua +++ b/mods/PLAYER/mcl_playerplus/init.lua @@ -17,7 +17,7 @@ local is_sprinting = mcl_sprint.is_sprinting local exhaust = mcl_hunger.exhaust local playerphysics = playerphysics -local is_player = mcl_player.is_player +local is_player = mcl_util.is_player local vector = vector local math = math From 04094f97fad624b1624836c3cf3520ec41024887 Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 06:32:51 +0400 Subject: [PATCH 22/68] #198 Fix a crash, step 16 --- mods/PLAYER/mcl_playerplus/init.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index 9208f5862..93db2734e 100644 --- a/mods/PLAYER/mcl_playerplus/init.lua +++ b/mods/PLAYER/mcl_playerplus/init.lua @@ -17,8 +17,6 @@ local is_sprinting = mcl_sprint.is_sprinting local exhaust = mcl_hunger.exhaust local playerphysics = playerphysics -local is_player = mcl_util.is_player - local vector = vector local math = math -- Internal player state @@ -37,7 +35,7 @@ local function player_collision(player) for _,object in pairs(minetest.get_objects_inside_radius(pos, width)) do - if object and (is_player(object) + if object and ((mcl_util and mcl_util.is_player(object)) or (object:get_luaentity()._cmi_is_mob == true and object ~= player)) then local pos2 = object:get_pos() From b3059aecbaa165e1335d8d39c61debf07b26e74c Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 06:34:46 +0400 Subject: [PATCH 23/68] #198 Fix a crash, step 17 --- mods/PLAYER/mcl_playerplus/init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index 93db2734e..c7fd5b2b7 100644 --- a/mods/PLAYER/mcl_playerplus/init.lua +++ b/mods/PLAYER/mcl_playerplus/init.lua @@ -34,9 +34,9 @@ local function player_collision(player) local width = .75 for _,object in pairs(minetest.get_objects_inside_radius(pos, width)) do - + local luaentity = object:get_luaentity() if object and ((mcl_util and mcl_util.is_player(object)) - or (object:get_luaentity()._cmi_is_mob == true and object ~= player)) then + or (luaentity and luaentity._cmi_is_mob == true and object ~= player)) then local pos2 = object:get_pos() local vec = {x = pos.x - pos2.x, z = pos.z - pos2.z} From 194ac71c89376fa0e833db96886f9f8f1f38674d Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 06:36:15 +0400 Subject: [PATCH 24/68] #198 Fix a crash, step 18 --- mods/ITEMS/mcl_shields/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ITEMS/mcl_shields/init.lua b/mods/ITEMS/mcl_shields/init.lua index ab4fc70a4..65ffc6b4b 100644 --- a/mods/ITEMS/mcl_shields/init.lua +++ b/mods/ITEMS/mcl_shields/init.lua @@ -109,6 +109,7 @@ for _, e in pairs(mcl_shields.enchantments) do end function mcl_shields.is_blocking(obj) + if not mcl_util or not mcl_util.is_player(obj) then return end local blocking = mcl_shields.players[obj].blocking if blocking > 0 then local shieldstack = obj:get_wielded_item() From e15a82b865fcedd6d5741d804885440013b8a4b4 Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 06:38:19 +0400 Subject: [PATCH 25/68] #198 Fix a crash, step 19 --- mods/HUD/mcl_offhand/init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/HUD/mcl_offhand/init.lua b/mods/HUD/mcl_offhand/init.lua index b0fc223ec..af495b886 100644 --- a/mods/HUD/mcl_offhand/init.lua +++ b/mods/HUD/mcl_offhand/init.lua @@ -55,7 +55,7 @@ local function update_wear_bar(player, itemstack) end minetest.register_globalstep(function(dtime) - for _, player in pairs(minetest.get_connected_players()) do + for _, player in pairs(minetest.get_connected_players()) do if mcl_util and mcl_util.is_player(player:get_player_name()) then local itemstack = mcl_offhand.get_offhand(player) local offhand_item = itemstack:get_name() local offhand_hud = mcl_offhand[player].hud @@ -148,7 +148,7 @@ minetest.register_globalstep(function(dtime) remove_hud(player, index) end end - end + end end end) minetest.register_allow_player_inventory_action(function(player, action, inventory, inventory_info) From 403528e54250b1db4817c35319dd0a6d5e2c04b1 Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 06:39:47 +0400 Subject: [PATCH 26/68] #198 Fix a crash, step 20 --- mods/CORE/mcl_util/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/CORE/mcl_util/init.lua b/mods/CORE/mcl_util/init.lua index 3a634637a..90e44cedc 100644 --- a/mods/CORE/mcl_util/init.lua +++ b/mods/CORE/mcl_util/init.lua @@ -503,6 +503,7 @@ local possible_hackers = {} function mcl_util.is_player(obj) if not obj then return end + if not obj.is_player then return end if not obj:is_player() then return end local name = obj:get_player_name() if not name then return end From adfa83c34c3a5b7333cf56e8f3fa50d8d545b54f Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 06:44:41 +0400 Subject: [PATCH 27/68] #198 Fix a crash, step 21 --- mods/PLAYER/mcl_player/init.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mods/PLAYER/mcl_player/init.lua b/mods/PLAYER/mcl_player/init.lua index 69f126dcf..9d910a89a 100644 --- a/mods/PLAYER/mcl_player/init.lua +++ b/mods/PLAYER/mcl_player/init.lua @@ -127,6 +127,8 @@ function mcl_player.player_get_preview(player) end function mcl_player.get_player_formspec_model(player, x, y, w, h, fsname) + if not mcl_util then return end + if not mcl_util.is_player(player) then return end local name = player:get_player_name() local model = player_model[name] local anim = models[model].animations[player_anim[name]] From 560882b1bacab458f3edfb3873308076ecd6c754 Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 14 Feb 2022 20:55:55 +0400 Subject: [PATCH 28/68] #198 Fix a crash, step 22 --- mods/ITEMS/mcl_bows/arrow.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mods/ITEMS/mcl_bows/arrow.lua b/mods/ITEMS/mcl_bows/arrow.lua index c61dfc26c..baa4d633a 100644 --- a/mods/ITEMS/mcl_bows/arrow.lua +++ b/mods/ITEMS/mcl_bows/arrow.lua @@ -145,7 +145,7 @@ function ARROW_ENTITY.on_step(self, dtime) -- Pickup arrow if player is nearby (not in Creative Mode) local objects = minetest.get_objects_inside_radius(pos, 1) for _,obj in ipairs(objects) do - if obj:is_player() then + if mcl_util and mcl_util.is_player(obj) then if self._collectable and not minetest.is_creative_enabled(obj:get_player_name()) then if obj:get_inventory():room_for_item("main", "mcl_bows:arrow") then obj:get_inventory():add_item("main", "mcl_bows:arrow") @@ -199,7 +199,7 @@ function ARROW_ENTITY.on_step(self, dtime) for k, obj in pairs(objs) do local ok = false -- Arrows can only damage players and mobs - if obj:is_player() then + if mcl_util and mcl_util.is_player(obj) then ok = true elseif obj:get_luaentity() then if (obj:get_luaentity()._cmi_is_mob or obj:get_luaentity()._hittable_by_projectile) then @@ -223,7 +223,7 @@ function ARROW_ENTITY.on_step(self, dtime) if closest_object then local obj = closest_object - local is_player = obj:is_player() + local is_player = mcl_util and mcl_util.is_player(obj) local lua = obj:get_luaentity() if obj == self._shooter and self._time_in_air > 1.02 or obj ~= self._shooter and (is_player or (lua and (lua._cmi_is_mob or lua._hittable_by_projectile))) then if obj:get_hp() > 0 then @@ -258,7 +258,7 @@ function ARROW_ENTITY.on_step(self, dtime) full_punch_interval=1.0, damage_groups={fleshy=self._damage}, }, self.object:get_velocity()) - if obj:is_player() then + if mcl_util and mcl_util.is_player(obj) then if not mcl_shields.is_blocking(obj) then local placement self._placement = math.random(1, 2) @@ -309,7 +309,7 @@ function ARROW_ENTITY.on_step(self, dtime) if is_player then - if self._shooter and self._shooter:is_player() and not self._in_player and not self._blocked then + if self._shooter and (mcl_util and mcl_util.is_player(self._shooter)) and not self._in_player and not self._blocked then -- “Ding” sound for hitting another player minetest.sound_play({name="mcl_bows_hit_player", gain=0.1}, {to_player=self._shooter:get_player_name()}, true) end @@ -320,7 +320,7 @@ function ARROW_ENTITY.on_step(self, dtime) -- Achievement for hitting skeleton, wither skeleton or stray (TODO) with an arrow at least 50 meters away -- NOTE: Range has been reduced because mobs unload much earlier than that ... >_> -- TODO: This achievement should be given for the kill, not just a hit - if self._shooter and self._shooter:is_player() and vector.distance(pos, self._startpos) >= 20 then + if self._shooter and (mcl_util and mcl_util.is_player(self._shooter)) and vector.distance(pos, self._startpos) >= 20 then if mod_awards and (entity_name == "mobs_mc:skeleton" or entity_name == "mobs_mc:stray" or entity_name == "mobs_mc:witherskeleton") then awards.unlock(self._shooter:get_player_name(), "mcl:snipeSkeleton") end @@ -331,7 +331,7 @@ function ARROW_ENTITY.on_step(self, dtime) minetest.sound_play({name="mcl_bows_hit_other", gain=0.3}, {pos=self.object:get_pos(), max_hear_distance=16}, true) end end - if not obj:is_player() then + if not mcl_util or not mcl_util.is_player(obj) then mcl_burning.extinguish(self.object) if self._piercing == 0 then self.object:remove() @@ -457,7 +457,7 @@ function ARROW_ENTITY.get_staticdata(self) end out.stuckstarttime = minetest.get_gametime() - self._stucktimer end - if self._shooter and self._shooter:is_player() then + if self._shooter and mcl_util and mcl_util.is_player(self._shooter) then out.shootername = self._shooter:get_player_name() end return minetest.serialize(out) @@ -493,7 +493,7 @@ function ARROW_ENTITY.on_activate(self, staticdata, dtime_s) self._is_critical = data.is_critical if data.shootername then local shooter = minetest.get_player_by_name(data.shootername) - if shooter and shooter:is_player() then + if shooter and mcl_util and mcl_util.is_player(shooter) then self._shooter = shooter end end From 306a6ad20fa0c6fc23289b0907316aa7a59e4a80 Mon Sep 17 00:00:00 2001 From: kay27 Date: Tue, 15 Feb 2022 03:19:43 +0400 Subject: [PATCH 29/68] #202 Destroy Nether Portals on ABMs --- mods/ITEMS/mcl_portals/portal_nether.lua | 67 +++++++++++------------- 1 file changed, 30 insertions(+), 37 deletions(-) diff --git a/mods/ITEMS/mcl_portals/portal_nether.lua b/mods/ITEMS/mcl_portals/portal_nether.lua index e6dd255f0..3f2f819c8 100644 --- a/mods/ITEMS/mcl_portals/portal_nether.lua +++ b/mods/ITEMS/mcl_portals/portal_nether.lua @@ -209,39 +209,6 @@ local function get_target(p) end end --- Destroy portal if pos (portal frame or portal node) got destroyed -local function destroy_nether_portal(pos, node) - if not node then return end - local nn, orientation = node.name, node.param2 - local obsidian = nn == OBSIDIAN - - local function check_remove(pos, orientation) - local node = get_node(pos) - if node and (node.name == PORTAL and (orientation == nil or (node.param2 == orientation))) then - minetest.remove_node(pos) - remove_exit(pos) - end - end - if obsidian then -- check each of 6 sides of it and destroy every portal: - check_remove({x = pos.x - 1, y = pos.y, z = pos.z}, 0) - check_remove({x = pos.x + 1, y = pos.y, z = pos.z}, 0) - check_remove({x = pos.x, y = pos.y, z = pos.z - 1}, 1) - check_remove({x = pos.x, y = pos.y, z = pos.z + 1}, 1) - check_remove({x = pos.x, y = pos.y - 1, z = pos.z}) - check_remove({x = pos.x, y = pos.y + 1, z = pos.z}) - return - end - if orientation == 0 then - check_remove({x = pos.x - 1, y = pos.y, z = pos.z}, 0) - check_remove({x = pos.x + 1, y = pos.y, z = pos.z}, 0) - else - check_remove({x = pos.x, y = pos.y, z = pos.z - 1}, 1) - check_remove({x = pos.x, y = pos.y, z = pos.z + 1}, 1) - end - check_remove({x = pos.x, y = pos.y - 1, z = pos.z}) - check_remove({x = pos.x, y = pos.y + 1, z = pos.z}) -end - local on_rotate if minetest.get_modpath("screwdriver") then on_rotate = screwdriver.disallow @@ -295,7 +262,6 @@ minetest.register_node(PORTAL, { }, groups = { creative_breakable = 1, portal = 1, not_in_creative_inventory = 1 }, sounds = mcl_sounds.node_sound_glass_defaults(), - after_destruct = destroy_nether_portal, on_rotate = on_rotate, _mcl_hardness = -1, @@ -763,10 +729,38 @@ mcl_structures.register_structure({name = "nether_portal", place_function = mcl_ minetest.register_abm({ label = "Nether portal teleportation and particles", nodenames = {PORTAL}, - interval = 1, - chance = 1, + interval = 0.8, + chance = 3, action = function(pos, node) + -- Don't use call stack! + local upper_node_name = get_node({x = pos.x, y = pos.y + 1, z = pos.z}).name + if upper_node_name ~= PORTAL and upper_node_name ~= OBSIDIAN then + minetest.remove_node(pos) + remove_exit(pos) + return + end + local lower_node_name = get_node({x = pos.x, y = pos.y - 1, z = pos.z}).name + if lower_node_name ~= PORTAL and lower_node_name ~= OBSIDIAN then + minetest.remove_node(pos) + remove_exit(pos) + return + end + local o = node.param2 -- orientation + + local closer_node_name = get_node({x = pos.x - 1 + o, y = pos.y, z = pos.z - o}).name + if closer_node_name ~= PORTAL and closer_node_name ~= OBSIDIAN then + minetest.remove_node(pos) + remove_exit(pos) + return + end + local further_node_name = get_node({x = pos.x + 1 - o, y = pos.y, z = pos.z + o}).name + if further_node_name ~= PORTAL and further_node_name ~= OBSIDIAN then + minetest.remove_node(pos) + remove_exit(pos) + return + end + local d = random(0, 1) -- direction local time = random() * 1.9 + 0.5 local velocity, acceleration @@ -829,7 +823,6 @@ local usagehelp = S("To open a Nether portal, place an upright frame of obsidian minetest.override_item(OBSIDIAN, { _doc_items_longdesc = longdesc, _doc_items_usagehelp = usagehelp, - after_destruct = destroy_nether_portal, _on_ignite = function(user, pointed_thing) local x, y, z = pointed_thing.under.x, pointed_thing.under.y, pointed_thing.under.z -- Check empty spaces around obsidian and light all frames found: From 2bf7ebc2652e5b9187de5a0bbc2e63ddbb7ee4a8 Mon Sep 17 00:00:00 2001 From: kay27 Date: Wed, 16 Feb 2022 03:47:23 +0400 Subject: [PATCH 30/68] Preload village schematics and calc proper sizes --- mods/MAPGEN/mcl_villages/init.lua | 38 +++++++++++++++--- .../mcl_villages/schematics/blacksmith.mts | Bin 986 -> 1052 bytes .../mcl_villages/schematics/butcher.mts | Bin 813 -> 919 bytes .../MAPGEN/mcl_villages/schematics/church.mts | Bin 956 -> 1128 bytes mods/MAPGEN/mcl_villages/schematics/farm.mts | Bin 347 -> 324 bytes mods/MAPGEN/mcl_villages/schematics/lamp.mts | Bin 209 -> 170 bytes .../mcl_villages/schematics/large_house.mts | Bin 1137 -> 1271 bytes .../mcl_villages/schematics/library.mts | Bin 816 -> 892 bytes .../mcl_villages/schematics/medium_house.mts | Bin 760 -> 830 bytes .../mcl_villages/schematics/small_house.mts | Bin 593 -> 617 bytes .../MAPGEN/mcl_villages/schematics/tavern.mts | Bin 1005 -> 1138 bytes mods/MAPGEN/mcl_villages/schematics/well.mts | Bin 476 -> 456 bytes 12 files changed, 32 insertions(+), 6 deletions(-) diff --git a/mods/MAPGEN/mcl_villages/init.lua b/mods/MAPGEN/mcl_villages/init.lua index 6009539da..adbb7a0f5 100644 --- a/mods/MAPGEN/mcl_villages/init.lua +++ b/mods/MAPGEN/mcl_villages/init.lua @@ -13,7 +13,7 @@ local modpath = minetest.get_modpath(modname) local S = minetest.get_translator(modname) local basic_pseudobiome_villages = minetest.settings:get_bool("basic_pseudobiome_villages", true) local schem_path = modpath .. "/schematics/" -local schematic_table = { +--[[local 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 = 11, hheight = 7, 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 }, @@ -25,7 +25,37 @@ local schematic_table = { {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 }, +}]] +local schematic_table = { + {name = "large_house", mts = schem_path.."large_house.mts", max_num = 0.08 , rplc = basic_pseudobiome_villages }, + {name = "blacksmith", mts = schem_path.."blacksmith.mts", max_num = 0.055, rplc = basic_pseudobiome_villages }, + {name = "butcher", mts = schem_path.."butcher.mts", max_num = 0.03 , rplc = basic_pseudobiome_villages }, + {name = "church", mts = schem_path.."church.mts", max_num = 0.04 , rplc = basic_pseudobiome_villages }, + {name = "farm", mts = schem_path.."farm.mts", max_num = 0.1 , rplc = basic_pseudobiome_villages }, + {name = "lamp", mts = schem_path.."lamp.mts", max_num = 0.1 , rplc = false }, + {name = "library", mts = schem_path.."library.mts", max_num = 0.04 , rplc = basic_pseudobiome_villages }, + {name = "medium_house", mts = schem_path.."medium_house.mts", max_num = 0.08 , rplc = basic_pseudobiome_villages }, + {name = "small_house", mts = schem_path.."small_house.mts", max_num = 0.7 , rplc = basic_pseudobiome_villages }, + {name = "tavern", mts = schem_path.."tavern.mts", max_num = 0.050, rplc = basic_pseudobiome_villages }, + {name = "well", mts = schem_path.."well.mts", max_num = 0.045, rplc = basic_pseudobiome_villages }, } +for k, v in pairs(schematic_table) do + local schem_lua = minetest.serialize_schematic( + v.mts, + "lua", + { + lua_use_comments = false, + lua_num_indent_spaces = 0, + } + ):gsub("mcl_core:stonebrickcarved", "mcl_villages:stonebrickcarved") .. " return schematic" + v.preloaded_schematic = schem_lua + local loaded_schematic = loadstring(schem_lua)() + local size = loaded_schematic.size + v.hwidth = size.x + v.hheight = size.y + v.hdepth = size.z + v.hsize = math.ceil(math.sqrt((size.x/2)^2 + (size.y/2)^2) * 2 + 1) +end local surface_mat = { ["mcl_core:dirt_with_dry_grass"] = { top = "mcl_core:dirt", bottom = "mcl_core:stone" }, ["mcl_core:dirt_with_grass"] = { top = "mcl_core:dirt", bottom = "mcl_core:stone" }, @@ -322,12 +352,8 @@ local function place_schematics(plan, pr) local pos = built_house.pos local rotation = built_house.rotation local platform_material = built_house.surface_mat - local building = built_house.building.mts local replace_wall = built_house.building.rplc - local schem_lua = minetest.serialize_schematic(building, - "lua", - {lua_use_comments = false, lua_num_indent_spaces = 0}).." return schematic" - schem_lua = schem_lua:gsub("mcl_core:stonebrickcarved", "mcl_villages:stonebrickcarved") + local schem_lua = built_house.building.preloaded_schematic 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. diff --git a/mods/MAPGEN/mcl_villages/schematics/blacksmith.mts b/mods/MAPGEN/mcl_villages/schematics/blacksmith.mts index d7fb66593dba1636ba133681520ae16721d276b8..09665654a91c13f5ea5f484159ad650954885192 100644 GIT binary patch delta 576 zcmcb`K8HigHze4XfrWvcfsKK)9t;>{7?=|?ix~KGlXK#e^NUiglJk?2a#ANpFquvc zVw9dZRi0k}B$t+&mz-K`1*9e~V3MBvmQhYy1geNl|L*&jGXhNnM zGqZS?rh@U(2W16@56aa&rnNSI{b znVDI5(s{`PIUO>>H*7j=ww_I4xz)8n{84n-g7c0G86R>QcNi#qcDeY7U4^|+{mT2V zEsQ1{1sZ?;|F@4}^HmLb_P@SEYSoIC+pRfLE&}_l6DQ8)58-@bbmj2ZMhSs~RT`~I z?z_Ae7=9ISo~W7fTf%@*nA!0_%PO|{d~R%M8wz`PjxePqxTP*oJMhY8LiL0@N6z%5 iC@VKxaPd!Re88lkHPbM}$UsoA&cXEz55xPgm3sjLWZZfH delta 531 zcmbQkaf`j)Hze4XfrWvcfrEj&9ts%b7$kC&bK;Zpi&CvpGK)&$%QH(d;?s)~i;EeU z6Elk#cu}Mo_~G2-{G_CuR3!P5qSRCd5x9I(QD$;>d{Rz+ayElRMM2_ZM<%g}Rq_f5 z1IzRCQy2t58q!kpl2ePVz|`b^MpH)p$q`JtQfX-nVj$^~{G#Lxpgfq4FHg+LnHVQC zS&2z}ax|kFkd~gz%c#L9GciGoH6_0^DQEIWM#IVTndF!l#3wIc5})WSGx4FAIM^tV z=3=YjlKi|>hyyJrA7<3AubA^Te@%Q6*3pO9x zRHVVca`8z@%bWt%jn0dOQr>(Gygy^lmW5x|UhUv1y76F6RPNQQ8Yh)J;%+_je3lh^ zZK_4>MV87ESF80Llhk)QFU$J>&0@MtX@GTEPRNrt@f|jYea@CP8BeJ=f8|FJS7qkZ ze__8qX9?W+W1~>X;ofAHH^7AZ>?e8b|^Z)qs Q>U;CXzI>f~-O^UC0EnC4S^xk5 diff --git a/mods/MAPGEN/mcl_villages/schematics/butcher.mts b/mods/MAPGEN/mcl_villages/schematics/butcher.mts index 251033b1ec0a3e7bf299f833ab1ffd90e35c18b3..03353de105ded131339bf1d97b4c8dafc59d077b 100644 GIT binary patch delta 589 zcmZ3>Hl5wgHze4XfrWvafrEjq9ts%57?=|?ix~KGlXK#e^NUiglJk?2a#9&2-~uU` zMJ4g&nI#$V=|zdf#giv7nof*RocxGUTr4Tx5J_iFVoFMC5rfR+ct%mq_>}xokU63g z?~6{X&;u%$mXQRRnOTyWn^u&Vn_6rIV#b5n40@A=8FeM|7{owIO7e@6Gl247I=(zH zCui~>M#YKy6ehJQ(qC6oN$CmQX=Bvgo%y3Jd%Thi z;pu}7y0!%d6XwYo6yH%em;bfkK*JdpSM?d^8PcyB8!YHDQV=m{xS`?6d~?HphlVBF z#DhVLBZwiji+O6NP^Ml4cZmFoIn5c$H)GOvlyZnM3r%KxBq#HX zsrBP7@fYS|D_9fM?j+362xwpxeaPiS8y7=SWZ1Vw9e|f>EI!VP8&SN=j-`#hkaH z-9k+Y0yZs1@)x;Z7XSV_!Mx+DM%d#D>nd~Ydz%g^I2c{f3Q%Ea5O#3TF?gd=RhD1< zHD_gHv$Mgqg-ub5xNfjTb*jx;np9kAELdfn|2E}r*PHKJ4_C|&>VJDYV6JSIh3A!t z?FRdkCe977&&z+l#Qd|#7q_Lm|9>f)_&xi9@6+fDr#I-FRC=LSy|}wldfn_#M;32Q znAZFKNx_;=$0pzVap?87w#_L=|2G^Li_ZDDRl?G{PW0lWsy8T1b1(5WRs2oCXwYO78Pw{Y+rY8Z)`euXlZn1Ut?i%aAkCnkSCK} z0T`3P0WgubB$FZn7LyW%zLFAuNMo4FmN;lo=Sdvx3pQDl2qP(l=0h6Buj`G*I?al8aW2QzQu4maF?GGaKx zS`4QP7;)->rE5qi!s-kNZ!|=yAEKkV9+DJs*K?%idXRd2Z6xHnezazSgznI2Jqe&B z1;Jt5dcxfb7;WJ*;;GRY=m17iFO<~atgnaZK(J^ZCG~Isw2L@SeLb=|;tgPc*nr<2 zco-1v9ESS;AOLa)NY8&LsK?-cK-B#Qhi*Lz2SpEx3vimoKtqS(_5u|hiW-XysL@Dd zh!W>e2FgN|M28Yi2Smmx$x%OC9SRJHdi*(yRw2s3fTwh!Y8tH{_*_5m#S^ZoU|hnt=h` z=TvhjioxV0YBp4VQW9a0)-C6?HqDs@TDClv?)HSMLlkZ5}B0Q@T-G3 llxbjQDDh<`bY~Bl;)$qu84LwJQ4U3<3?{nOOaRhvcavh^&eZ`!&5uIht z3IZ+}HnYq!XUEmwj$be2yJK4P!Rd1=EfeN#*q!X)#L>aFQ!=}tQE1uMjT^U@QT;w4`^@JRS7WLkyn0gB zI5GX7)w!4{ezPAhsA6uQE1VQrECLz3YJ6x~EO`t`D=5 z+={KYw{lMjzjnOUc=^dz^K*Oj4xHK@d~xQZIk#I=@0RXP_>@r8*t@wl!e(!QoT>Pe z3RiKLxFtUJrhm1w*Csx_z4E}n8J|RB1-{#tB=YM$=n}CyFQqN??%YDJwdXyu?N;{+ycaaNXT z0wLCW&%TW8$x@b5^zc-aEYw_a_0%*cW-}YXxlRfX93*de_?;7Tws_!>ELFH5q*wED q?-ZGgN9QAbbCjpVPt=MG*&Fcv+OyW*wQk>MITf<~VfL&|?*;&du=@`H diff --git a/mods/MAPGEN/mcl_villages/schematics/farm.mts b/mods/MAPGEN/mcl_villages/schematics/farm.mts index 9094c8681fcde6d5c441593224154176330b7372..e47f6e22f4dd4875a5b3abe920b08e9fa23f7bf8 100644 GIT binary patch delta 214 zcmcc3bc9L7Hze4XfrWvcfsKK^9t;>bC)$fntkmTf$W6|PPfN{9PA#?qQWF>3)-wo# z#7gpuk~4sUV7ekMIl-k-hlk_9p@#YFliCycRBB}$gl9_3keDIqprRbmHnox0W0THBITbP3WV&a$E=2ty=HC zG~lU%4Vyvhv(8`t6$1E0*UBqLX}#wBJ-5*yfkm5f;)9UGXU;IVux#NKo!U~v|J9nI INIBRa01d}caR2}S delta 262 zcmX@YbepN(Hze4XfrWvSfrEj)9ts$^86xEmFD7EaFd|O~5e?3FVL`LSWoFla!i+^pB%(XXOVY#|Cv7Vgj+nIcS=mWz)jegJ{NcwRtHdr?)!fd%N~+@9_s>UvhJ4xoY*{?l c_a*;>w04Ur*~_hX`+3@=-%$(;TmDA_07bKG(EtDd diff --git a/mods/MAPGEN/mcl_villages/schematics/lamp.mts b/mods/MAPGEN/mcl_villages/schematics/lamp.mts index c8d907ebad7a6bbd63574e62b695f22ba428e4b6..4d2d1a350553d2c23044298327b0a732395ac20e 100644 GIT binary patch delta 135 zcmcb}xQfx)Hze4XfrWvYft7)|9t1#)#LOZFf!ySr__Wl#R87mA7Gm?fkpCQ4$H|S2hK1|N>5BsSRuY@ft(Msr@^ZA>(f`b cUyAC_>fzuDpW`^CQP9(c=Lj2vl^M%J0Hnt+FaQ7m delta 152 zcmZ3*c#+Y`Hze4XfrWvYfsKKs9t;@R86o=1t~fGM|{mGuePqYH}cx45P?oLm-~VD8i^VF+gf^ z2NUn)O^njqC8ar;1@Yw>nI)+}t28Elu&=L(OFqCKArY}bLm=%zvV_Hf6AgTdd5NhB z&P{80I0Ea~>Q?Y12DV7P$WmOU(4DkuYT5+Hrb`Lx4~q1qBgDk^`hhL70nYDtbA;ghu9J#9O#wW*)8 z^HI@yjb@DtHg6tkJ5H*Wl=!eTUT;C<8=%pgj*M&pIb4ShOGJvObi9dU+tI&M;=|7A z{aNo?r=-2%k>Q!+@=P)2o$5UnrS3(sKM)uHfiI)B@y(rIRTli6Cmq;U zv@G%Kj2J;y+Wbg2PRSf-Um{ESgrhh198+Z$(HixiX< zUwar%7g;WBAl@GMh~s~!adN2hrky=4O$_sy+}12S=U|x7#K5E9)oB>O&cJZOJH`pj&0uP> z1CtiW4Qfd_rK$1xMadbNDGZWuD~n6=^HP(FGLy5D6N}1HQzkPq%1mZr6rcQnQGW7T zCLUQSuqFBVIaWED=@}*QU}J!43sOrM)IeTRDk;s$EC8CEn3tZ)APQHWUX+@e7Y|lB zxsFkqQGfC*MqQ?~w25mBK<=r}uSl&-jZaC;EUv7W^LE-zp(X2c%DcRJQPu3X*lhCRXB;PiQ2w$-vz%Vm=mOKnRj*k&5xD}MBb-x-P9JI&3$ z{+@RCBlq?d(>|SBH&yPE|9&HB)0El0ht$*#wB9*!_k(xC#+mO8cy8C9ZCID~{V{v` z_muxT=Y@fQm!fe(!O@R5WK9IktavYNOg8@eG|&93i1>~N`+Qdgs_?!1o#lIFmDHli h+_K*SdS4ZUa=yKB>y)6;nrSM3%P#Ma%lNWL2mrP94k`cu diff --git a/mods/MAPGEN/mcl_villages/schematics/library.mts b/mods/MAPGEN/mcl_villages/schematics/library.mts index b47e0b4138f53fbb43aa1887249002d9c1082149..2986a71625064e764e7d60cfeef3eacca8dba011 100644 GIT binary patch delta 587 zcmdnM_J>W^Hze4XfrWvGft`V?9s(GI8JH6@ix~KGlXK#e^NUiglJk?2a#9%-C+9Ls zPflf25fO$<6_@1ar6v_+CTCAR#VEta3zsO*&rg}$!DujXq4;DyMsd-kctZvOkZf9N zUUF)&6_}d*lu>=+F9V4Zprjy3vLwGKIRhvQrWy1mp4Mf|n^>h*UlEt=z}~|n(4lwk z&;hm<9iAiI+(sNm3Bmobb9xz>40RF&n4H*j-lZ_kI@h6i?$`m&mYj$qj!rWkH6=`K zl6Y0v>FjgB#Jz*@iN2!HozAYkrmoMd->h))W0TCh4JMq6 zBPA3*f^2HnLPs`<6qeU5JK9?rcUwp^tF=@(bTBe1emr;N08fdi zhObg`hxJW~8L-QnFxanW9QPr_*J1V`goEq;hrf zz8en@EBa-Z8yO{(t8<5a|6sI%r@^|jzuYfDtKn&$+?0yvjmH#p57!Hen7sJeA?R(F z4 zo~zejaC5M2ijD8riRG%YmNwai(SSKA-f-dv3D%N$Lk7i(0n!sa zR3@(07ZL<%D#!BNik zu+8$`?K@Q_{qk}VJ%U>Q?rht!?eE^8+viv(CkRf^-cYZ%_3q5@2dX<*Zakf|hHZE0 z(n8a)RR0avy5FmJt}>tNQ~ZD3YoV&`VaKdi ztdEfpWnX12@jRiP*-FEXPAgG%7{Li(cm9He#mP{5{nQox{#$U}c<+Wh& cY6bUc>r+oG7iG?N-CCZoR`(_A*T@N30RI{7F#rGn diff --git a/mods/MAPGEN/mcl_villages/schematics/medium_house.mts b/mods/MAPGEN/mcl_villages/schematics/medium_house.mts index 43ce2391b9d1952596c3ec5028d0d66dd7105926..85ef0f9031a47eb81c48356da3c63a7ab12e92d1 100644 GIT binary patch delta 543 zcmeytx{s~iHze4XfrWvCft`V?9s(Fd8JH6@ix~KGlXK#e^NUiglJk?2a#9(DKmz57 zIXT5pk$6J}agbPX2~d5p6_^6*04tV+>n<+I&r3}z%1q8qPAn=*O<~}LOO-GerKV0? zVZetFD$mbPnZzhEc^;$P#0DuKCC*$DZ#dbB(OFUg*{+<#q%mB$=?_?CSKR9 zuZT-tAi`m=!0FI4Ln8$R4^wSsrb9n$cx(~^efBXhZ>nQlz!b*Dr;&0r%W_w3PeN!8 z&l`tW1vTXuadu|4c!n2zi5qrsTu7TxE5kD*oYc6{jBReL7m zo1sC0P)ylsNbp6^$-)ul>x-?Aq|8ZSOn7(4mckEdhkgiTf&O}|Nqz5+Fp?1=v~RLa;PDNe^pgm)r@`r1K4J?Wi@23 zX1AJbQ|oK+`Qpo8Rj+OxcPQL(#hHogtjwH`4hj<=_LR3ZGWYcSc$1cra6tXM$A!B# nHXdFQo!`|Wo7`BUd*UoUoq$H z)K0!;1)er;=}pY#`RjLw%U=`9R?X|K$XQsQ^k?Z5e@hmDg=t|~a=Kq^&v&hS6lokP z*{1p9koLRM)%%Z?c^i3Fyn4;HZC}!3?W23XEq-_5ZRhbO=l2@+0>@t3JomkcK_1ttM8&UD*TRI{;>RkCAS=__^CZXt+$uhES;fm z{<&sp#QE}){)yKC$mA(7> Y9+`7p`pC1USv9EcxqQF)F2}8Y03u+yPXGV_ diff --git a/mods/MAPGEN/mcl_villages/schematics/small_house.mts b/mods/MAPGEN/mcl_villages/schematics/small_house.mts index d7b62529cb804c5fa99a9a99a8677c4f5cc46b9f..d09fbfe00ae358153475021d2d828a1689d93dac 100644 GIT binary patch delta 373 zcmcb}@{&c=Hze4XfrWt`1nVJyL13bT_+&Fi1>xe7#LS{%D=-zGoS&4GlR9yZ{NzAJ z{fQsMCtk9gSRgjJfl*S6K`=KtC%z=VC^;jw*a}QDh=PPr3@FdfPnj&sC{bS#mz;~r;o+Gp%r-b3RWwnb!oG0g(;bb^991M2ni(`5W=>?b@8b3O5a6`6 zQM8|zW2(UQrXOo~j{I!wZJgV9tEMiY<#%H%qu@0jo*k7FDjuk4$w{1Gxx-`QFxQ5s zL*nVNtRP#C2OF4I%Y+C>hsO5{uu4brD_sov_y51VMhyS5R|iEpqT}rwq!b((3f0T( zA9S-UxU9Htefk2m1Shkei4#tqabP{OB+7pco15E;muIF_Oz8Y{fsw)gOUhyZ^-Pa! delta 406 zcmaFKa*?IpHze4XfrWt+2-)jlfI)~sA~!iFJ~_WA)hZ>ks3g8Tvm_%vy(qD`n1L5X zhJiUTvxtEoE|#31l$4XoAPy2JE&<9FTY)K{SzrkfWQm+awxsy-{QQ*3_KXq}6XYg7 z5}$a)QbiD?rX;^8IU}{$3QRMIp=wKtpQx%nv01Ag>`a(FIf)R{fO-om=DZDg%h#;H zqf^pzuJ+fF>aVdgEbQ*^FrBQcn67=}$}<&LC5J{kq09*fo4a>)vDxg}vA4Z^g;BeV zA>P0&%b!TlJ(k@RndKY&#^P_iyt(qx9$nbE2@Yt zd{Mq%rp`!h)vMCB@~S^qC7%^*oRnFYdau~RWX55M``M>6GhAeZ*<)a#Pwp61DM1on=(n8^MWLk^NUigN{Uib z8H7RHtkUe%r2GmiC=D?nIU}{Wq}U2fG3ZTBVbo>JoBWDVZgMD-*u*TUiPudhD>4e# z3xNzMPt3^yD$P$y%1MnkgBXe;W@yA94N{2V*!cX?lGGvwKDevWa}tY-E8>zF7~R-P zID}H2gj16a=xd!&;JDrx&>bss)9%kRqXi6VY(b35%)%n|hu*aOn8BMPz|YJ+;Th{L z=_8^oQhF>RqG<`uT}DcsPG6KfO6-)IB|^4xFmIZ}!EDqpvqS2Yf#@TL**6zN%wd#2 z@YK9)h1!JsHy+eIX71){tUc3kG=G5r<4&I$je>ca%9He29xhr@mwe!%dB=anx)#mE zv z_K!Xvnx@TUj9GDrC;iAecCDV+X%ibY7&b9wN&DC?^V`4?$E-N%%!x3eG6p`;Gc2-x xC(Km7E4^8;EZ2u+@m#NMi5oj+HlA4F%Io%K){FxUGaEx3w#qOt*gdNb001J2L|^~_ delta 670 zcmeyw@s{1wHze4XfrWvaftP`+9vLu5Gf3nn=fo%H7o}RIWEPdgmuHq_#HSY}78f%x zCuSBg@S;dhlvSKOi&1LgMDfW2jH0T-aLMA5{JhkpqRixM1_7{OMrv_Mu~jmVn!Jh8 ze6j$OsIwqQq9nfvBxnVu8Kgl%#U((Cimkv@e0hF;N_>84NooBo}EscQ>ZgF}J(5Vw`E%^`*Eh$P(ot(xfCkplz!ez;cMP;ce6VDk>u4k047Xlek zo|uyZbY*^0Qch~TS;d^UVVy-nP3f7?ut+`qj+d5u$2f3@CPcG{HS{9J8 zTxZVPj=uYMjz2s2`Q{=chtvtW-*f-eU*94ZnzH=(+#4_7dc+pKzG>)&} zQvF^>oKNvRIq`MdlQkjfHQWAAXxb+cdHx)CrS2J7uX{D~#3wxLIK}W*pv*1$1fNSG zkeGY2FJkLIgS;7!jv0QI+xYpRdtH;wex>zNwheo%7aLmJp7M*ZZ_7J*?$XZ5*UB7M zPpCIPdd@Wbnt=88O;y60_Y&LYvfr<7O;>-m{rd~^6R%3xcNf`Se4Sh1RKF@@Wzf=7 zyq?d_>=I9W@j9&VYv=j)Yp&;Gm|leBzk9SnO;hfdckJb)BMT?%bH(Z@CI|9;eqQ2m rRAl>)_aza9d2yO^ixhN@t@_!{pX4@eqp|n5s29Iau5$K?0j-d`W&mMO-oiV;Y+q z+b0HLW|pRsVuKA#it0BM^kh`bnOTes42%zaX?l~En!xT9wx{nw+5<+XyaiHjTwja~ z6n4*KeUoOUboUIyw%KPktXhBk@$O$$6HNFv$?-@m*!2HDGw-VQ2@0`4QYAmkI&+}m kdMM8mW;c&rNesud#GDg0y?OKG#(^U((c%o3{uxFB0D@?)dH?_b delta 275 zcmX@Xe23Z0Hze4XfrWvMft`V)9s(Hn86Pgf$I&kPkkM4BDCu#uDl8Wx9Dy4 From dffdfb3cadcdf9bbedc5f830d1b67d7c8c1552a6 Mon Sep 17 00:00:00 2001 From: kay27 Date: Wed, 16 Feb 2022 03:59:44 +0400 Subject: [PATCH 31/68] Fix terraform --- mods/MAPGEN/mcl_villages/init.lua | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/mods/MAPGEN/mcl_villages/init.lua b/mods/MAPGEN/mcl_villages/init.lua index adbb7a0f5..69debee74 100644 --- a/mods/MAPGEN/mcl_villages/init.lua +++ b/mods/MAPGEN/mcl_villages/init.lua @@ -13,19 +13,6 @@ local modpath = minetest.get_modpath(modname) local S = minetest.get_translator(modname) local basic_pseudobiome_villages = minetest.settings:get_bool("basic_pseudobiome_villages", true) local schem_path = modpath .. "/schematics/" ---[[local 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 = 11, hheight = 7, 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 }, -}]] local schematic_table = { {name = "large_house", mts = schem_path.."large_house.mts", max_num = 0.08 , rplc = basic_pseudobiome_villages }, {name = "blacksmith", mts = schem_path.."blacksmith.mts", max_num = 0.055, rplc = basic_pseudobiome_villages }, @@ -293,14 +280,14 @@ local function terraform(plan, minp, maxp, pr) fheight = schematic_data.hheight local pos2 = { x = pos.x + fwidth - 1, - y = math_min(pos.y + fheight * 3, maxp.y), + y = math_min(pos.y + fheight + 4, maxp.y), z = pos.z + fdepth - 1 } - ground(pos, {x = pos2.x, y = pos.y, z = pos2.z}, minp, maxp, pr, build_material) + ground(pos, {x = pos2.x, y = pos.y + 1, z = pos2.z}, minp, maxp, pr, build_material) local node_list = {} for xi = pos.x, pos2.x do for zi = pos.z, pos2.z do - for yi = pos.y, pos2.y do + for yi = pos.y + 1, pos2.y do node_list[#node_list + 1] = {x = xi, y = yi, z = zi} end end From c21f9b4c4068857f80c8c8081d6bb281844a96cf Mon Sep 17 00:00:00 2001 From: kay27 Date: Wed, 16 Feb 2022 04:10:39 +0400 Subject: [PATCH 32/68] #204 Add own Perlin noise --- mods/MAPGEN/mcl_villages/init.lua | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/mods/MAPGEN/mcl_villages/init.lua b/mods/MAPGEN/mcl_villages/init.lua index 69debee74..022f0ae73 100644 --- a/mods/MAPGEN/mcl_villages/init.lua +++ b/mods/MAPGEN/mcl_villages/init.lua @@ -7,7 +7,20 @@ local chance_per_chunk = 1 local noise_multiplier = 1 local random_offset = 1 local random_multiply = 19 -local struct_threshold = chance_per_chunk - 1 +local struct_threshold = chance_per_chunk -- 1 +local noise_params = { + offset = 0, + scale = 2, + spread = { + x = mcl_mapgen.CS_NODES * chance_per_chunk, + y = mcl_mapgen.CS_NODES * chance_per_chunk, + z = mcl_mapgen.CS_NODES * chance_per_chunk, + }, + seed = 842458, + octaves = 2, + persistence = 0.5, +} +local perlin_noise local modname = minetest.get_current_modname() local modpath = minetest.get_modpath(modname) local S = minetest.get_translator(modname) @@ -57,7 +70,7 @@ local villages = minetest.deserialize(storage:get_string("villages") or "return local minetest_get_spawn_level = minetest.get_spawn_level local minetest_get_node = minetest.get_node local minetest_find_nodes_in_area = minetest.find_nodes_in_area -local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level +local minetest_get_perlin = minetest.get_perlin local math_pi = math.pi local math_cos = math.cos local math_sin = math.sin @@ -412,7 +425,8 @@ if mg_name ~= "singlenode" then if minp.y < minp_min then return end local pr = PseudoRandom(chunkseed * random_multiply + random_offset) local random_number = pr:next(1, chance_per_chunk) - local noise = mcl_structures_get_perlin_noise_level(minp) * noise_multiplier + perlin_noise = perlin_noise or minetest_get_perlin(noise_params) + local noise = perlin_noise:get_3d(minp) * noise_multiplier if (random_number + noise) < struct_threshold then return end local min, max = 9999999, -9999999 for i = 1, pr:next(5,10) do From f61459ae8979febbd32604dcf86b32da289fcff8 Mon Sep 17 00:00:00 2001 From: kay27 Date: Wed, 16 Feb 2022 04:45:42 +0400 Subject: [PATCH 33/68] #204 Register all village schematics as structures --- mods/CORE/mcl_mapgen/init.lua | 22 ++++++++++-- mods/MAPGEN/mcl_villages/init.lua | 57 +++++++++++++++++++++---------- 2 files changed, 59 insertions(+), 20 deletions(-) diff --git a/mods/CORE/mcl_mapgen/init.lua b/mods/CORE/mcl_mapgen/init.lua index bc390e597..f24d76880 100644 --- a/mods/CORE/mcl_mapgen/init.lua +++ b/mods/CORE/mcl_mapgen/init.lua @@ -505,11 +505,29 @@ function mcl_mapgen.clamp_to_chunk(x, size) end function mcl_mapgen.get_chunk_beginning(x) - return x - ((x + central_chunk_min_pos) % CS_NODES) + if tonumber(x) then + return x - ((x + central_chunk_min_pos) % CS_NODES) + end + if x.x then + return { + x = mcl_mapgen.get_chunk_beginning(x.x), + y = mcl_mapgen.get_chunk_beginning(x.y), + z = mcl_mapgen.get_chunk_beginning(x.z) + } + end end function mcl_mapgen.get_chunk_ending(x) - return mcl_mapgen.get_chunk_beginning(x) + LAST_NODE_IN_CHUNK + if tonumber(x) then + return mcl_mapgen.get_chunk_beginning(x) + LAST_NODE_IN_CHUNK + end + if x.x then + return { + x = mcl_mapgen.get_chunk_beginning(x.x) + LAST_NODE_IN_CHUNK, + y = mcl_mapgen.get_chunk_beginning(x.y) + LAST_NODE_IN_CHUNK, + z = mcl_mapgen.get_chunk_beginning(x.z) + LAST_NODE_IN_CHUNK + } + end end mcl_mapgen.get_block_seed = get_block_seed diff --git a/mods/MAPGEN/mcl_villages/init.lua b/mods/MAPGEN/mcl_villages/init.lua index 022f0ae73..6f9cca5ab 100644 --- a/mods/MAPGEN/mcl_villages/init.lua +++ b/mods/MAPGEN/mcl_villages/init.lua @@ -7,7 +7,7 @@ local chance_per_chunk = 1 local noise_multiplier = 1 local random_offset = 1 local random_multiply = 19 -local struct_threshold = chance_per_chunk -- 1 +local struct_threshold = chance_per_chunk - 1 local noise_params = { offset = 0, scale = 2, @@ -39,23 +39,6 @@ local schematic_table = { {name = "tavern", mts = schem_path.."tavern.mts", max_num = 0.050, rplc = basic_pseudobiome_villages }, {name = "well", mts = schem_path.."well.mts", max_num = 0.045, rplc = basic_pseudobiome_villages }, } -for k, v in pairs(schematic_table) do - local schem_lua = minetest.serialize_schematic( - v.mts, - "lua", - { - lua_use_comments = false, - lua_num_indent_spaces = 0, - } - ):gsub("mcl_core:stonebrickcarved", "mcl_villages:stonebrickcarved") .. " return schematic" - v.preloaded_schematic = schem_lua - local loaded_schematic = loadstring(schem_lua)() - local size = loaded_schematic.size - v.hwidth = size.x - v.hheight = size.y - v.hdepth = size.z - v.hsize = math.ceil(math.sqrt((size.x/2)^2 + (size.y/2)^2) * 2 + 1) -end local surface_mat = { ["mcl_core:dirt_with_dry_grass"] = { top = "mcl_core:dirt", bottom = "mcl_core:stone" }, ["mcl_core:dirt_with_grass"] = { top = "mcl_core:dirt", bottom = "mcl_core:stone" }, @@ -453,6 +436,44 @@ if mg_name ~= "singlenode" then end, mcl_mapgen.order.VILLAGES) end +for k, v in pairs(schematic_table) do + local schem_lua = minetest.serialize_schematic( + v.mts, + "lua", + { + lua_use_comments = false, + lua_num_indent_spaces = 0, + } + ):gsub("mcl_core:stonebrickcarved", "mcl_villages:stonebrickcarved") .. " return schematic" + v.preloaded_schematic = schem_lua + local loaded_schematic = loadstring(schem_lua)() + local size = loaded_schematic.size + v.hwidth = size.x + v.hheight = size.y + v.hdepth = size.z + v.hsize = math.ceil(math.sqrt((size.x/2)^2 + (size.y/2)^2) * 2 + 1) + mcl_structures.register_structure({ + name = v.name, + place_function = function(pos, rotation, pr, placer) + local minp = mcl_mapgen.get_chunk_beginning(pos) + local maxp = mcl_mapgen.get_chunk_ending(pos) + local surface_pos, surface_material = find_surface(pos, minp, maxp) + local plan = { + [1] = { + pos = pos, + building = schematic_table[k], + rotation = rotation, + surface_mat = surface_material or "mcl_core:snow", + } + } + if surface_material then + terraform(plan, minp, maxp, pr) + end + place_schematics(plan, pr) + end + }) +end + function mcl_villages.get_villages() return villages end From 44575dfd96df88cf28da289df0ee7f41f1f32a23 Mon Sep 17 00:00:00 2001 From: kay27 Date: Wed, 16 Feb 2022 04:57:38 +0400 Subject: [PATCH 34/68] #204 Register village as a structure --- mods/MAPGEN/mcl_villages/init.lua | 24 +++++++++++++++---- .../mcl_villages/locale/mcl_villages.ru.tr | 1 + mods/MAPGEN/mcl_villages/locale/template.txt | 1 + 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/mods/MAPGEN/mcl_villages/init.lua b/mods/MAPGEN/mcl_villages/init.lua index 6f9cca5ab..9f7a1d334 100644 --- a/mods/MAPGEN/mcl_villages/init.lua +++ b/mods/MAPGEN/mcl_villages/init.lua @@ -7,7 +7,7 @@ local chance_per_chunk = 1 local noise_multiplier = 1 local random_offset = 1 local random_multiply = 19 -local struct_threshold = chance_per_chunk - 1 +local struct_threshold = chance_per_chunk local noise_params = { offset = 0, scale = 2, @@ -387,11 +387,18 @@ minetest.register_node("mcl_villages:stonebrickcarved", { -- -- on map generation, try to build a settlement -- -local function build_a_settlement(minp, maxp, pr) +local function build_a_village(minp, maxp, pr, placer) minetest.log("action","[mcl_villages] Building village at mapchunk " .. minetest.pos_to_string(minp) .. "..." .. minetest.pos_to_string(maxp)) local pr = pr or PseudoRandom(mcl_mapgen.get_block_seed3(minp)) local plan = create_site_plan(minp, maxp, pr) - if not plan then return end + if not plan then + if placer then + if placer:is_player() then + minetest.chat_send_player(placer:get_player_name(), S("Map chunk @1 to @2 is not suitable for placing villages.", minetest.pos_to_string(minp), minetest.pos_to_string(maxp))) + end + end + return + end paths(plan, minp, maxp) terraform(plan, minp, maxp, pr) place_schematics(plan, pr) @@ -432,7 +439,7 @@ if mg_name ~= "singlenode" then end local height_difference = max - min if height_difference > max_height_difference then return end - build_a_settlement(minp, maxp, chunkkseed) + build_a_village(minp, maxp, chunkkseed) end, mcl_mapgen.order.VILLAGES) end @@ -474,6 +481,15 @@ for k, v in pairs(schematic_table) do }) end +mcl_structures.register_structure({ + name = "village", + place_function = function(pos, rotation, pr, placer) + local minp = mcl_mapgen.get_chunk_beginning(pos) + local maxp = mcl_mapgen.get_chunk_ending(pos) + build_a_village(minp, maxp, pr, placer) + end +}) + function mcl_villages.get_villages() return villages end diff --git a/mods/MAPGEN/mcl_villages/locale/mcl_villages.ru.tr b/mods/MAPGEN/mcl_villages/locale/mcl_villages.ru.tr index 467f31121..325d3b191 100644 --- a/mods/MAPGEN/mcl_villages/locale/mcl_villages.ru.tr +++ b/mods/MAPGEN/mcl_villages/locale/mcl_villages.ru.tr @@ -1,2 +1,3 @@ # textdomain: mcl_villages Chiseled Stone Village Bricks=Точёный каменный блок из деревни +Map chunk @1 to @2 is not suitable for placing villages.=Чанк с @1 по @2 непригоден для размещения деревень. \ No newline at end of file diff --git a/mods/MAPGEN/mcl_villages/locale/template.txt b/mods/MAPGEN/mcl_villages/locale/template.txt index e396a8b08..7d9fcb43b 100644 --- a/mods/MAPGEN/mcl_villages/locale/template.txt +++ b/mods/MAPGEN/mcl_villages/locale/template.txt @@ -1,2 +1,3 @@ # textdomain: mcl_villages Chiseled Stone Village Bricks= +Map chunk @1 to @2 is not suitable for placing villages.= From 4f2567bed052f2d3f80edd38f827a6839cd46801 Mon Sep 17 00:00:00 2001 From: kay27 Date: Wed, 16 Feb 2022 05:41:43 +0400 Subject: [PATCH 35/68] #204 Spawn villagers --- mods/MAPGEN/mcl_villages/init.lua | 32 ++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/mods/MAPGEN/mcl_villages/init.lua b/mods/MAPGEN/mcl_villages/init.lua index 9f7a1d334..92af69e76 100644 --- a/mods/MAPGEN/mcl_villages/init.lua +++ b/mods/MAPGEN/mcl_villages/init.lua @@ -318,7 +318,7 @@ end local function init_nodes(p1, rotation, pr, size) local p2 = vector.subtract(vector.add(p1, size), 1) - local nodes = minetest.find_nodes_in_area(p1, p2, {"mcl_itemframes:item_frame", "mcl_furnaces:furnace", "mcl_anvils:anvil", "mcl_chests:chest"}) + local nodes = minetest.find_nodes_in_area(p1, p2, {"mcl_itemframes:item_frame", "mcl_furnaces:furnace", "mcl_anvils:anvil", "mcl_chests:chest", "mcl_villages:stonebrickcarved"}) for _, pos in pairs(nodes) do local name = minetest_get_node(pos).name local def = minetest_registered_nodes[minetest_get_node(pos).name] @@ -370,6 +370,9 @@ end -- -- register block for npc spawn -- +local function spawn_villager(pos) + minetest.add_entity({x = pos.x, y = pos.y + 1, z = pos.z}, "mobs_mc:villager") +end minetest.register_node("mcl_villages:stonebrickcarved", { description = S("Chiseled Stone Village Bricks"), _doc_items_longdesc = doc.sub.items.temp.build, @@ -381,8 +384,35 @@ minetest.register_node("mcl_villages:stonebrickcarved", { is_ground_content = false, _mcl_blast_resistance = 6, _mcl_hardness = 1.5, + on_construct = spawn_villager, }) +minetest.register_abm({ + label = "Spawn villagers", + nodenames = {"mcl_villages:stonebrickcarved"}, + interval = 60, + chance = 3, + action = function(pos, node) + -- check the space above + local p = table.copy(pos) + p.y = p.y + 1 + if minetest_get_node(p).name ~= "air" then return end + p.y = p.y + 1 + if minetest_get_node(p).name ~= "air" then return end + p.y = p.y - 1 + local villagers_counter = 0 + for _, obj in pairs(minetest.get_objects_inside_radius(p, 40)) do + local lua_entity = obj:get_luaentity() + if luaentity and luaentity.name == "mobs_mc:villager" then + villagers_counter = villagers_counter + 1 + if villagers_counter > 7 then return end + end + end + spawn_villager(pos) + end +}) + + -- -- on map generation, try to build a settlement From c3e0b871dc772f6699d241cbb903a3d4c78294d3 Mon Sep 17 00:00:00 2001 From: kay27 Date: Wed, 16 Feb 2022 06:13:39 +0400 Subject: [PATCH 36/68] #204 Fix fireball entities --- mods/ENTITIES/mobs_mc/blaze.lua | 4 ++-- mods/ITEMS/mcl_fire/fire_charge.lua | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/blaze.lua b/mods/ENTITIES/mobs_mc/blaze.lua index 8f4a96db4..a634a6a03 100644 --- a/mods/ENTITIES/mobs_mc/blaze.lua +++ b/mods/ENTITIES/mobs_mc/blaze.lua @@ -68,7 +68,7 @@ mobs:register_mob("mobs_mc:blaze", { light_damage = 0, view_range = 16, attack_type = "projectile", - arrow = "mobs_mc:blaze_fireball", + arrow = "mobs_mc:blaze_fireball_entity", shoot_interval = 3.5, shoot_offset = 1.0, passive = false, @@ -85,7 +85,7 @@ mobs:register_mob("mobs_mc:blaze", { shoot_arrow = function(self, pos, dir) -- 2-4 damage per arrow local dmg = math.random(2,4) - mobs.shoot_projectile_handling("mobs_mc:blaze_fireball", pos, dir, self.object:get_yaw(), self.object, 7, dmg,nil,nil,nil,-0.4) + mobs.shoot_projectile_handling("mobs_mc:blaze_fireball_entity", pos, dir, self.object:get_yaw(), self.object, 7, dmg,nil,nil,nil,-0.4) end, do_custom = function(self) diff --git a/mods/ITEMS/mcl_fire/fire_charge.lua b/mods/ITEMS/mcl_fire/fire_charge.lua index 5c33288f7..3afdbf759 100644 --- a/mods/ITEMS/mcl_fire/fire_charge.lua +++ b/mods/ITEMS/mcl_fire/fire_charge.lua @@ -47,7 +47,7 @@ minetest.register_craftitem("mcl_fire:fire_charge", { _on_dispense = function(stack, pos, droppos, dropnode, dropdir) -- Throw fire charge local shootpos = vector.add(pos, vector.multiply(dropdir, 0.51)) - local fireball = add_entity(shootpos, "mobs_mc:blaze_fireball") + local fireball = add_entity(shootpos, "mobs_mc:blaze_fireball_entity") local ent = fireball:get_luaentity() if ent then ent._shot_from_dispenser = true From a90981988115b40169c508ae14c9156fa0334d13 Mon Sep 17 00:00:00 2001 From: kay27 Date: Wed, 16 Feb 2022 18:55:18 +0400 Subject: [PATCH 37/68] Quickfix a crash --- .../api/mob_functions/projectile_handling.lua | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/projectile_handling.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/projectile_handling.lua index a4b4c075e..bafb12737 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/projectile_handling.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/projectile_handling.lua @@ -28,12 +28,14 @@ mobs.shoot_projectile_handling = function(arrow_item, pos, dir, yaw, shooter, po obj:set_acceleration({x=0, y=gravity, z=0}) obj:set_yaw(yaw-math.pi/2) local le = obj:get_luaentity() - le._shooter = shooter - le._damage = damage - le._is_critical = is_critical - le._startpos = pos - le._knockback = knockback - le._collectable = collectable + if le then + le._shooter = shooter + le._damage = damage + le._is_critical = is_critical + le._startpos = pos + le._knockback = knockback + le._collectable = collectable + end --play custom shoot sound if shooter and shooter.shoot_sound then From 2b7e2e7a255ad78e348f06a91680ecaea2dd24b6 Mon Sep 17 00:00:00 2001 From: kay27 Date: Wed, 16 Feb 2022 19:04:21 +0400 Subject: [PATCH 38/68] Restore blaze fireball --- mods/ENTITIES/mobs_mc/blaze.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mobs_mc/blaze.lua b/mods/ENTITIES/mobs_mc/blaze.lua index a634a6a03..e02c57a8f 100644 --- a/mods/ENTITIES/mobs_mc/blaze.lua +++ b/mods/ENTITIES/mobs_mc/blaze.lua @@ -85,7 +85,7 @@ mobs:register_mob("mobs_mc:blaze", { shoot_arrow = function(self, pos, dir) -- 2-4 damage per arrow local dmg = math.random(2,4) - mobs.shoot_projectile_handling("mobs_mc:blaze_fireball_entity", pos, dir, self.object:get_yaw(), self.object, 7, dmg,nil,nil,nil,-0.4) + mobs.shoot_projectile_handling("mobs_mc:blaze_fireball", pos, dir, self.object:get_yaw(), self.object, 7, dmg,nil,nil,nil,-0.4) end, do_custom = function(self) From 2008239a52633617658fd38e9cfc3d18305d432a Mon Sep 17 00:00:00 2001 From: kay27 Date: Thu, 17 Feb 2022 01:03:28 +0400 Subject: [PATCH 39/68] Fix code style --- mods/ITEMS/REDSTONE/mesecons_mvps/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/REDSTONE/mesecons_mvps/init.lua b/mods/ITEMS/REDSTONE/mesecons_mvps/init.lua index fedb8fa5d..db8eb75a2 100644 --- a/mods/ITEMS/REDSTONE/mesecons_mvps/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_mvps/init.lua @@ -151,7 +151,7 @@ function mesecon.mvps_get_stack(pos, dir, maximum, piston_pos) -- add connected nodes to frontiers, connected is a vector list -- the vectors must be absolute positions local connected = {} - local has_loop + local has_loop if minetest.registered_nodes[nn.name] and minetest.registered_nodes[nn.name].mvps_sticky then connected, has_loop = minetest.registered_nodes[nn.name].mvps_sticky(np, nn, piston_pos) From 86dc2e0495319f3cde10cd0d6895dfe1d7edf304 Mon Sep 17 00:00:00 2001 From: kay27 Date: Thu, 17 Feb 2022 02:49:52 +0400 Subject: [PATCH 40/68] Fix chances of structures --- mods/MAPGEN/mcl_structures/desert_temple.lua | 2 +- mods/MAPGEN/mcl_structures/desert_well.lua | 4 ++-- mods/MAPGEN/mcl_structures/fossil.lua | 2 +- mods/MAPGEN/mcl_structures/ice_spike_small.lua | 2 +- mods/MAPGEN/mcl_structures/igloo.lua | 5 ++--- mods/MAPGEN/mcl_structures/jungle_temple.lua | 4 ++-- mods/MAPGEN/mcl_structures/nice_jungle_temple.lua | 4 ++-- mods/MAPGEN/mcl_structures/witch_hut.lua | 4 ++-- mods/MAPGEN/mcl_villages/init.lua | 2 +- 9 files changed, 14 insertions(+), 15 deletions(-) diff --git a/mods/MAPGEN/mcl_structures/desert_temple.lua b/mods/MAPGEN/mcl_structures/desert_temple.lua index bb4c08b3a..eb1950b18 100644 --- a/mods/MAPGEN/mcl_structures/desert_temple.lua +++ b/mods/MAPGEN/mcl_structures/desert_temple.lua @@ -5,7 +5,7 @@ local chance_per_chunk = 11 local noise_multiplier = 1 local random_offset = 999 local scanning_ratio = 0.00003 -local struct_threshold = chance_per_chunk - 1 +local struct_threshold = chance_per_chunk local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level diff --git a/mods/MAPGEN/mcl_structures/desert_well.lua b/mods/MAPGEN/mcl_structures/desert_well.lua index af57c8183..1bd6691d2 100644 --- a/mods/MAPGEN/mcl_structures/desert_well.lua +++ b/mods/MAPGEN/mcl_structures/desert_well.lua @@ -1,11 +1,11 @@ local modname = minetest.get_current_modname() local modpath = minetest.get_modpath(modname) -local chance_per_chunk = 60 +local chance_per_chunk = 40 local noise_multiplier = 1 local random_offset = 999 local scanning_ratio = 0.00001 -local struct_threshold = chance_per_chunk - 1 +local struct_threshold = chance_per_chunk local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level diff --git a/mods/MAPGEN/mcl_structures/fossil.lua b/mods/MAPGEN/mcl_structures/fossil.lua index b26b7320a..6c6c2d24b 100644 --- a/mods/MAPGEN/mcl_structures/fossil.lua +++ b/mods/MAPGEN/mcl_structures/fossil.lua @@ -4,7 +4,7 @@ local modpath = minetest.get_modpath(modname) local chance_per_block = mcl_structures.from_16x16_to_block_inverted_chance(64) local noise_multiplier = 2 local random_offset = 5 -local struct_threshold = chance_per_block - 1 +local struct_threshold = chance_per_block local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level local minetest_find_nodes_in_area = minetest.find_nodes_in_area local min_y = mcl_worlds.layer_to_y(40) diff --git a/mods/MAPGEN/mcl_structures/ice_spike_small.lua b/mods/MAPGEN/mcl_structures/ice_spike_small.lua index 801c5f66e..387c61bab 100644 --- a/mods/MAPGEN/mcl_structures/ice_spike_small.lua +++ b/mods/MAPGEN/mcl_structures/ice_spike_small.lua @@ -3,7 +3,7 @@ local modpath = minetest.get_modpath(modname) local chance_per_chunk = 3 local random_offset = 1264 -local struct_threshold = chance_per_chunk - 1 +local struct_threshold = chance_per_chunk local noise_params = { offset = 0, scale = 1, diff --git a/mods/MAPGEN/mcl_structures/igloo.lua b/mods/MAPGEN/mcl_structures/igloo.lua index 4f6c9574f..ebb88667b 100644 --- a/mods/MAPGEN/mcl_structures/igloo.lua +++ b/mods/MAPGEN/mcl_structures/igloo.lua @@ -1,11 +1,10 @@ local modname = minetest.get_current_modname() local modpath = minetest.get_modpath(modname) --- local chance_per_chunk = mcl_structures.from_16x16_to_chunk_inverted_chance(4400) -local chance_per_chunk = 100 +local chance_per_chunk = 39 local noise_multiplier = 1.4 local random_offset = 555 -local struct_threshold = chance_per_chunk - 1 +local struct_threshold = chance_per_chunk local scanning_ratio = 0.0003 local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level diff --git a/mods/MAPGEN/mcl_structures/jungle_temple.lua b/mods/MAPGEN/mcl_structures/jungle_temple.lua index 635f35670..9abaf4626 100644 --- a/mods/MAPGEN/mcl_structures/jungle_temple.lua +++ b/mods/MAPGEN/mcl_structures/jungle_temple.lua @@ -1,10 +1,10 @@ local modname = minetest.get_current_modname() local modpath = minetest.get_modpath(modname) -local chance_per_chunk = 9 +local chance_per_chunk = 30 local noise_multiplier = 1.3 local random_offset = 132 -local struct_threshold = chance_per_chunk - 1 +local struct_threshold = chance_per_chunk local scanning_ratio = 0.0003 local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level diff --git a/mods/MAPGEN/mcl_structures/nice_jungle_temple.lua b/mods/MAPGEN/mcl_structures/nice_jungle_temple.lua index dd8df05d3..75a137b03 100644 --- a/mods/MAPGEN/mcl_structures/nice_jungle_temple.lua +++ b/mods/MAPGEN/mcl_structures/nice_jungle_temple.lua @@ -1,10 +1,10 @@ local modname = minetest.get_current_modname() local modpath = minetest.get_modpath(modname) -local chance_per_chunk = 15 +local chance_per_chunk = 40 local noise_multiplier = 1 local random_offset = 133 -local struct_threshold = chance_per_chunk - 1 +local struct_threshold = chance_per_chunk local scanning_ratio = 0.00021 local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level diff --git a/mods/MAPGEN/mcl_structures/witch_hut.lua b/mods/MAPGEN/mcl_structures/witch_hut.lua index f6dc6ec9b..49843bb59 100644 --- a/mods/MAPGEN/mcl_structures/witch_hut.lua +++ b/mods/MAPGEN/mcl_structures/witch_hut.lua @@ -1,11 +1,11 @@ local modname = minetest.get_current_modname() local modpath = minetest.get_modpath(modname) -local chance_per_chunk = 3 +local chance_per_chunk = 17 local noise_multiplier = -0.9 local random_offset = 8 local scanning_ratio = 0.01 -local struct_threshold = chance_per_chunk - 1 +local struct_threshold = chance_per_chunk local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level diff --git a/mods/MAPGEN/mcl_villages/init.lua b/mods/MAPGEN/mcl_villages/init.lua index 92af69e76..4a5da47bf 100644 --- a/mods/MAPGEN/mcl_villages/init.lua +++ b/mods/MAPGEN/mcl_villages/init.lua @@ -1,9 +1,9 @@ mcl_villages = {} +local chance_per_chunk = 100 local chunk_offset_top = 16 local chunk_offset_bottom = 3 local max_height_difference = 12 local minp_min = -64 -local chance_per_chunk = 1 local noise_multiplier = 1 local random_offset = 1 local random_multiply = 19 From 0b17a790081d287c75d121790b2cd901a0cea068 Mon Sep 17 00:00:00 2001 From: kay27 Date: Thu, 17 Feb 2022 02:54:16 +0400 Subject: [PATCH 41/68] Fix ocean monument chance --- mods/MAPGEN/mcl_ocean_monument/init.lua | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/mods/MAPGEN/mcl_ocean_monument/init.lua b/mods/MAPGEN/mcl_ocean_monument/init.lua index fffa6f6b0..44dcabb7c 100644 --- a/mods/MAPGEN/mcl_ocean_monument/init.lua +++ b/mods/MAPGEN/mcl_ocean_monument/init.lua @@ -1,7 +1,8 @@ - --- Check it: --- seed 1, v7 mapgen --- /teleport 14958,8,11370 +local chance_per_chunk = 5 +local noise_multiplier = 1 +local random_offset = 12342 +local struct_threshold = chance_per_chunk +local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level local mcl_mapgen_get_far_node = mcl_mapgen.get_far_node local minetest_log = minetest.log @@ -44,8 +45,12 @@ mcl_mapgen.register_mapgen(function(minp, maxp, seed) local y = minp.y if y ~= y_wanted then return end + local pr = PseudoRandom(seed + random_offset) + local random_number = pr:next(1, chance_per_chunk) + local noise = mcl_structures_get_perlin_noise_level(minp) * noise_multiplier + if not noise or (random_number + noise) < struct_threshold then return end + local x, z = minp.x, minp.z - local pr = PseudoRandom(seed) -- scan the ocean - it should be the ocean: for i = 1, pr:next(10, 100) do From 5f25f0d1a6819d7cc34d740271e614e01ae3ba40 Mon Sep 17 00:00:00 2001 From: kay27 Date: Thu, 17 Feb 2022 03:00:10 +0400 Subject: [PATCH 42/68] Fix protected pistons work --- mods/ITEMS/REDSTONE/mesecons_pistons/init.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mods/ITEMS/REDSTONE/mesecons_pistons/init.lua b/mods/ITEMS/REDSTONE/mesecons_pistons/init.lua index 93b8df96d..e6dde3f99 100644 --- a/mods/ITEMS/REDSTONE/mesecons_pistons/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_pistons/init.lua @@ -138,8 +138,6 @@ local function piston_off(pos, node) end local function piston_orientate(pos, placer) - mesecon.mvps_set_owner(pos, placer) - -- not placed by player if not placer then return end @@ -153,6 +151,7 @@ local function piston_orientate(pos, placer) elseif pitch < -55 then minetest.add_node(pos, {name=pistonspec.piston_down}) end + mesecon.mvps_set_owner(pos, placer) end From 337757f10173c8eb532f6c9e1fdec8dc1f5ecf31 Mon Sep 17 00:00:00 2001 From: kay27 Date: Thu, 17 Feb 2022 05:04:01 +0400 Subject: [PATCH 43/68] #198 Fix a crash, step 23 --- mods/HUD/mcl_inventory/init.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mods/HUD/mcl_inventory/init.lua b/mods/HUD/mcl_inventory/init.lua index f59476965..bcdad90d3 100644 --- a/mods/HUD/mcl_inventory/init.lua +++ b/mods/HUD/mcl_inventory/init.lua @@ -8,7 +8,7 @@ mcl_inventory = {} -- Returns a single itemstack in the given inventory to the main inventory, or drop it when there's no space left function return_item(itemstack, dropper, pos, inv) - if dropper:is_player() then + if mcl_util and mcl_util.is_player(dropper) then -- Return to main inventory if inv:room_for_item("main", itemstack) then inv:add_item("main", itemstack) @@ -130,6 +130,7 @@ end -- Drop items in craft grid and reset inventory on closing minetest.register_on_player_receive_fields(function(player, formname, fields) + if not mcl_util or not mcl_util.is_player(player) then return end if fields.quit then return_fields(player,"craft") return_fields(player,"enchanting_lapis") From e68a9504b2a6dc2fb7ba168f292dce7ed88793a9 Mon Sep 17 00:00:00 2001 From: kay27 Date: Thu, 17 Feb 2022 05:10:23 +0400 Subject: [PATCH 44/68] #198 Fix a crash, step 24 --- mods/HUD/mcl_inventory/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/HUD/mcl_inventory/init.lua b/mods/HUD/mcl_inventory/init.lua index bcdad90d3..6aa4c7c78 100644 --- a/mods/HUD/mcl_inventory/init.lua +++ b/mods/HUD/mcl_inventory/init.lua @@ -143,6 +143,7 @@ end) if not minetest.is_creative_enabled("") then function mcl_inventory.update_inventory_formspec(player) + if not mcl_util or not mcl_util.is_player(player) then return end set_inventory(player) end end From 21fc69efa5cb2e01df5e302edcfec7377bb2ed38 Mon Sep 17 00:00:00 2001 From: kay27 Date: Thu, 17 Feb 2022 05:16:08 +0400 Subject: [PATCH 45/68] #198 Fix a crash, step 25 --- mods/HUD/mcl_inventory/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/HUD/mcl_inventory/init.lua b/mods/HUD/mcl_inventory/init.lua index 6aa4c7c78..0a8b9a7bc 100644 --- a/mods/HUD/mcl_inventory/init.lua +++ b/mods/HUD/mcl_inventory/init.lua @@ -47,6 +47,7 @@ function return_fields(player, name) end local function set_inventory(player, armor_change_only) + if not mcl_util or not mcl_util.is_player(player) then return end if minetest.is_creative_enabled(player:get_player_name()) then if armor_change_only then -- Stay on survival inventory plage if only the armor has been changed From 11c55cce297a2dcba85d60b0bc9962a937999702 Mon Sep 17 00:00:00 2001 From: kay27 Date: Thu, 17 Feb 2022 05:25:05 +0400 Subject: [PATCH 46/68] #198 Fix a crash, step 26 --- mods/HUD/mcl_experience/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/HUD/mcl_experience/init.lua b/mods/HUD/mcl_experience/init.lua index aea805fa2..2b6d4d5bf 100644 --- a/mods/HUD/mcl_experience/init.lua +++ b/mods/HUD/mcl_experience/init.lua @@ -157,6 +157,7 @@ function mcl_experience.throw_xp(pos, total_xp) end function mcl_experience.update(player) + if not mcl_util or not mcl_util.is_player(player) then return end local xp = mcl_experience.get_xp(player) local cache = caches[player] From 14edda4fd002a8ec71a8894f71870e81090a26dc Mon Sep 17 00:00:00 2001 From: kay27 Date: Fri, 18 Feb 2022 18:23:58 +0400 Subject: [PATCH 47/68] Localise a var --- mods/CORE/mcl_mapgen/mod.conf | 8 ++++---- mods/MAPGEN/mcl_mapgen_core/nether_wart.lua | 2 +- mods/MAPGEN/mcl_villages/init.lua | 1 - 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/mods/CORE/mcl_mapgen/mod.conf b/mods/CORE/mcl_mapgen/mod.conf index 76b4a5c93..fa734ae2b 100644 --- a/mods/CORE/mcl_mapgen/mod.conf +++ b/mods/CORE/mcl_mapgen/mod.conf @@ -1,4 +1,4 @@ -name = mcl_mapgen -author = kay27 -description = MineClone 2/5 MapGen Basic Stuff -depends = mcl_init +name = mcl_mapgen +author = kay27 +description = MineClone 2/5 MapGen Basic Stuff +depends = mcl_init diff --git a/mods/MAPGEN/mcl_mapgen_core/nether_wart.lua b/mods/MAPGEN/mcl_mapgen_core/nether_wart.lua index 7ea73ca4b..10554e7c4 100644 --- a/mods/MAPGEN/mcl_mapgen_core/nether_wart.lua +++ b/mods/MAPGEN/mcl_mapgen_core/nether_wart.lua @@ -43,7 +43,7 @@ mcl_mapgen.register_mapgen_block(function(minp, maxp, seed) local p1 = {x = minp.x + decrease_search_area, y = y1 + decrease_search_area, z = minp.z + decrease_search_area} local p2 = {x = maxp.x - decrease_search_area, y = y2 - decrease_search_area, z = maxp.z - decrease_search_area} - pos_list = minetest_find_nodes_in_area_under_air(p1, p2, place_on) + local pos_list = minetest_find_nodes_in_area_under_air(p1, p2, place_on) local pr = PseudoRandom(seed) wart_perlin = wart_perlin or minetest_get_perlin(noise_params) diff --git a/mods/MAPGEN/mcl_villages/init.lua b/mods/MAPGEN/mcl_villages/init.lua index 4a5da47bf..e837ab027 100644 --- a/mods/MAPGEN/mcl_villages/init.lua +++ b/mods/MAPGEN/mcl_villages/init.lua @@ -304,7 +304,6 @@ local function paths(plan, minp, maxp) if path then for _, pos in pairs(path) do pos.y = pos.y - 1 - local surface_mat = minetest.get_node(pos).name if surface_mat == "mcl_core:sand" or surface_mat == "mcl_core:redsand" then minetest.swap_node(pos, {name = "mcl_core:sandstonesmooth2"}) From c96e4dae39100962e319260f42c4dc532fe80097 Mon Sep 17 00:00:00 2001 From: kay27 Date: Sat, 19 Feb 2022 00:13:00 +0400 Subject: [PATCH 48/68] Fix mcl_time node time update --- mods/CORE/mcl_time/init.lua | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/mods/CORE/mcl_time/init.lua b/mods/CORE/mcl_time/init.lua index 31bcbbe29..8e437406b 100644 --- a/mods/CORE/mcl_time/init.lua +++ b/mods/CORE/mcl_time/init.lua @@ -14,11 +14,21 @@ local last_save_seconds_irl = seconds_irl_public local next_save_seconds_irl = last_save_seconds_irl + save_to_storage_interval local previous_seconds_irl = -2 +local time_speed_is_ok = true + local function get_seconds_irl() local time_speed = tonumber(minetest.settings:get("time_speed") or default_time_speed) if time_speed < 1 then - minetest.log("warning", "[mcl_time] time_speed < 1 - please increase to make mcl_time api work (default: " .. default_time_speed .. ")") + if time_speed_is_ok then + minetest.log("warning", "[mcl_time] time_speed < 1 - please increase to make mcl_time api work (default: " .. default_time_speed .. ")") + time_speed_is_ok = false + end return 0 + else + if not time_speed_is_ok then + minetest.log("warning", "[mcl_time] time_speed is now " .. time_speed) + time_speed_is_ok = true + end end local irl_multiplier = 86400 / time_speed local day_count = minetest.get_day_count() @@ -86,14 +96,12 @@ function mcl_time.touch(pos) meta:set_int(meta_name, seconds_irl_public) end -local touch = mcl_time.touch - function mcl_time.get_number_of_times_at_pos(pos, interval, chance) if not pos then return 0 end local meta = minetest.get_meta(pos) local last_time = meta:get_int(meta_name) local number_of_times = (last_time == 0) and 0 or get_number_of_times(last_time, interval, chance) - touch(pos) + meta:set_int(meta_name, seconds_irl_public) return number_of_times, seconds_irl_public end @@ -108,6 +116,7 @@ function mcl_time.get_irl_seconds_passed_at_pos(pos) local meta = minetest.get_meta(pos) local last_time = meta:get_int(meta_name) local irl_seconds_passed = (last_time == 0) and 0 or (seconds_irl_public - last_time) + meta:set_int(meta_name, seconds_irl_public) return irl_seconds_passed end @@ -116,6 +125,7 @@ function mcl_time.get_irl_seconds_passed_at_pos_or_1(pos) local meta = minetest.get_meta(pos) local last_time = meta:get_int(meta_name) local irl_seconds_passed = (last_time == 0) and 1 or (seconds_irl_public - last_time) + meta:set_int(meta_name, seconds_irl_public) return irl_seconds_passed end @@ -126,6 +136,7 @@ function mcl_time.get_irl_seconds_passed_at_pos_or_nil(pos) if last_time == 0 then return end local delta_time = seconds_irl_public - last_time if delta_time <= 0 then return end + meta:set_int(meta_name, seconds_irl_public) return delta_time end From b6b54f84d51cfd642c9af028fff576b3ae3ef293 Mon Sep 17 00:00:00 2001 From: kay27 Date: Sat, 19 Feb 2022 00:48:37 +0400 Subject: [PATCH 49/68] Update mcl_time to v2 --- mods/CORE/mcl_time/README.md | 88 +++++++++++++++++++++++++++++------- mods/CORE/mcl_time/init.lua | 37 +++++++++------ 2 files changed, 95 insertions(+), 30 deletions(-) diff --git a/mods/CORE/mcl_time/README.md b/mods/CORE/mcl_time/README.md index c3a1bb3af..19c461e90 100644 --- a/mods/CORE/mcl_time/README.md +++ b/mods/CORE/mcl_time/README.md @@ -1,4 +1,4 @@ -# mcl_time +# mcl_time v2.0 ## by kay27 for MineClone 5 --------------------------- This mod counts time when all players sleep or some area is inactive. @@ -15,13 +15,15 @@ Usually this value grow smoothly. But when you skip the night being in the bed, ### mcl_time.get_number_of_times(last_time, interval, chance) ------------------------------------------------------------- -Handy to process AMBs. +Returns the number of how many times something would probably happen if the area was active and we didn't skip the nights. -You pass `last_time` - last known value of `seconds_irl`, also ABM `interval` and ABM `chance`. +Arguments: + * `last_time` - you pass last known for you value of `seconds_irl` + * `interval` and `chance` - interval and chance like from ABM setup Returns: - * Integer number of how many times ABM function should be called if the area was active all the time and you didn't skip the night. - * Integer value of realtime (not in-game) seconds since world creation. + * Integer number of how many times something would probably happen if the area was active all the time and we didn't skip the nights. + * Integer value of in-real-life (not in-game) seconds since world creation. ### mcl_time.touch(pos) ----------------------- @@ -29,24 +31,76 @@ This function 'toches' node at position `pos` by writing `_t` meta variable of ` ### mcl_time.get_number_of_times_at_pos(pos, interval, chance) -------------------------------------------------------------- -Much more handy to call from LBM on area load, than `mcl_time.get_number_of_times()`! +Returns the number of how many times something would probably happen for node at pos `pos` if the area was active and we didn't skip the nights. +It reads and updates meta variable `_t` from position `pos` and uses it as previous `seconds_irl`, so we don't need to remember it. -It reads meta variable `_t` from position `pos` and uses it as previous `seconds_irl`, which then pass as first argument into `mcl_time.get_number_of_times()`. -After calling this, it also 'touches' the node at `pos` by writing `seconds_irl` into meta variable `_t`. +Argunments: + * `pos` - node position + * `interval` and `chance` - interval and chance like from ABM setup Returns: - * Integer number of how many times ABM function should be called if the area was active all the time and you didn't skip the night. - * Integer value of realtime (not in-game) seconds since world creation. - -*Warning!* This function can return 0. So it's better not to use it for regular ABMs - use `mcl_time.get_number_of_times_at_pos_or_1()` instead. + * Integer number of how many times something would happen to the node at position `pos` if the area was active all the time and we didn't skip the nights. + * For unclear conditions, like missing meta or zero `time_speed`, this function will return `0`. ### mcl_time.get_number_of_times_at_pos_or_1(pos, interval, chance) ------------------------------------------------------------------- -Much more handy to process ABMs than `mcl_time.get_number_of_times()` and `mcl_time.get_number_of_times_at_pos()`! +Returns the number of how many times something would probably happen for node at pos `pos` if the area was active and we didn't skip the nights. +It reads and updates meta variable `_t` from position `pos` and uses it as previous `seconds_irl`, so we don't need to remember it. -It just calls `mcl_time.get_number_of_times_at_pos()` but doesn't return 0, the minimum number it can return is 1, -which is the most suitable for regular ABM processing function. +Argunments: + * `pos` - node position + * `interval` and `chance` - interval and chance like from ABM setup Returns: - * Integer number of how many times ABM function should be called if the area was active all the time and you didn't skip the night. - * Integer value of realtime (not in-game) seconds since world creation. + * Integer number of how many times something would happen to the node at position `pos` if the area was active all the time and we didn't skip the nights. + * For unclear conditions, like missing meta or zero `time_speed`, this function will return `1`. + +### mcl_time.get_number_of_times_at_pos_or_nil(pos, interval, chance) +--------------------------------------------------------------------- +Returns the number of how many times something would probably happen for node at pos `pos` if the area was active and we didn't skip the nights. +It reads and updates meta variable `_t` from position `pos` and uses it as previous `seconds_irl`, so we don't need to remember it. + +Argunments: + * `pos` - node position + * `interval` and `chance` - interval and chance like from ABM setup + +Returns: + * Integer number of how many times something would happen to the node at position `pos` if the area was active all the time and we didn't skip the nights. + * For unclear conditions, like missing meta or zero `time_speed`, this function will return `nil`. + +### mcl_time.get_irl_seconds_passed_at_pos(pos) +----------------------------------------------- +Returns the number of how many in-real-life seconds would be passed for the node at position `pos`, if the area was active all the time and we didn't skip the nights. +It uses node meta variable `_t` to calculate this value. + +Argunments: + * `pos` - node position + +Returns: + * Integer number of how many in-real-life seconds would be passed for the node at position `pos, if the area was active all the time and we didn't skip the nights. + * For unclear conditions, like missing meta or zero `time_speed`, this function will return `0`. + +### mcl_time.get_irl_seconds_passed_at_pos_or_1(pos) +---------------------------------------------------- +Returns the number of how many in-real-life seconds would be passed for the node at position `pos`, if the area was active all the time and we didn't skip the nights. +It uses node meta variable `_t` to calculate this value. + +Argunments: + * `pos` - node position + +Returns: + * Integer number of how many in-real-life seconds would be passed for the node at position `pos, if the area was active all the time and we didn't skip the nights. + * For unclear conditions, like missing meta or zero `time_speed`, this function will return `1`. + +### mcl_time.get_irl_seconds_passed_at_pos_or_nil(pos) +---------------------------------------------------- +Returns the number of how many in-real-life seconds would be passed for the node at position `pos`, if the area was active all the time and we didn't skip the nights. +It uses node meta variable `_t` to calculate this value. + +Argunments: + * `pos` - node position + +Returns: + * Integer number of how many in-real-life seconds would be passed for the node at position `pos, if the area was active all the time and we didn't skip the nights. + * For unclear conditions, like missing meta or zero `time_speed`, this function will return `nil`. + diff --git a/mods/CORE/mcl_time/init.lua b/mods/CORE/mcl_time/init.lua index 8e437406b..2d7e93f9e 100644 --- a/mods/CORE/mcl_time/init.lua +++ b/mods/CORE/mcl_time/init.lua @@ -76,14 +76,14 @@ local function time_runner() end function mcl_time.get_number_of_times(last_time, interval, chance) - if not last_time then return 0 end - if seconds_irl_public < 2 then return 0 end - if not interval then return 0 end - if not chance then return 0 end - if interval < 1 then return 0 end - if chance < 1 then return 0 end + if not last_time then return 0, seconds_irl_publicend end + if seconds_irl_public < 2 then return 0, seconds_irl_public end + if not interval then return 0, seconds_irl_public end + if not chance then return 0, seconds_irl_public end + if interval < 1 then return 0, seconds_irl_public end + if chance < 1 then return 0, seconds_irl_public end local number_of_intervals = (seconds_irl_public - last_time) / interval - if number_of_intervals < 1 then return 0 end + if number_of_intervals < 1 then return 0, seconds_irl_public end local average_chance = (1 + chance) / 2 local number_of_times = math.floor(number_of_intervals / average_chance) return number_of_times, seconds_irl_public @@ -98,45 +98,56 @@ end function mcl_time.get_number_of_times_at_pos(pos, interval, chance) if not pos then return 0 end + if not time_speed_is_ok then return 0 end local meta = minetest.get_meta(pos) local last_time = meta:get_int(meta_name) - local number_of_times = (last_time == 0) and 0 or get_number_of_times(last_time, interval, chance) meta:set_int(meta_name, seconds_irl_public) - return number_of_times, seconds_irl_public + local number_of_times = (last_time == 0) and 0 or get_number_of_times(last_time, interval, chance) + return number_of_times end local get_number_of_times_at_pos = mcl_time.get_number_of_times_at_pos function mcl_time.get_number_of_times_at_pos_or_1(pos, interval, chance) - return math.max(get_number_of_times_at_pos(pos, interval, chance), 1), seconds_irl_public + return math.max(get_number_of_times_at_pos(pos, interval, chance), 1) +end + +function mcl_time.get_number_of_times_at_pos_or_nil(pos, interval, chance) + local number_of_times_at_pos = get_number_of_times_at_pos(pos, interval, chance) + if number_of_times_at_pos > 0 then + return number_of_times_at_pos + end end function mcl_time.get_irl_seconds_passed_at_pos(pos) if not pos then return 0 end + if not time_speed_is_ok then return 0 end local meta = minetest.get_meta(pos) local last_time = meta:get_int(meta_name) - local irl_seconds_passed = (last_time == 0) and 0 or (seconds_irl_public - last_time) meta:set_int(meta_name, seconds_irl_public) + local irl_seconds_passed = (last_time == 0) and 0 or (seconds_irl_public - last_time) return irl_seconds_passed end function mcl_time.get_irl_seconds_passed_at_pos_or_1(pos) if not pos then return 1 end + if not time_speed_is_ok then return 1 end local meta = minetest.get_meta(pos) local last_time = meta:get_int(meta_name) - local irl_seconds_passed = (last_time == 0) and 1 or (seconds_irl_public - last_time) meta:set_int(meta_name, seconds_irl_public) + local irl_seconds_passed = (last_time == 0) and 1 or (seconds_irl_public - last_time) return irl_seconds_passed end function mcl_time.get_irl_seconds_passed_at_pos_or_nil(pos) if not pos then return end + if not time_speed_is_ok then return end local meta = minetest.get_meta(pos) local last_time = meta:get_int(meta_name) + meta:set_int(meta_name, seconds_irl_public) if last_time == 0 then return end local delta_time = seconds_irl_public - last_time if delta_time <= 0 then return end - meta:set_int(meta_name, seconds_irl_public) return delta_time end From 460fd7fe071b5bad084c4d64ba0e170bc2c86a40 Mon Sep 17 00:00:00 2001 From: kay27 Date: Sat, 19 Feb 2022 01:52:10 +0400 Subject: [PATCH 50/68] Fix nether wart growrh again --- mods/CORE/mcl_time/README.md | 3 ++- mods/ITEMS/mcl_nether/nether_wart.lua | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/mods/CORE/mcl_time/README.md b/mods/CORE/mcl_time/README.md index 19c461e90..24a4cd1cd 100644 --- a/mods/CORE/mcl_time/README.md +++ b/mods/CORE/mcl_time/README.md @@ -3,7 +3,8 @@ --------------------------- This mod counts time when all players sleep or some area is inactive. -It depends very much on `time_speed` configuration variable, which could be changed 'on the fly' by a chat command. +It depends very much on `time_speed` configuration variable, which could be changed 'on the fly' by a chat command: + * `/set time_speed 72` If `time_speed` set to 0, this mod logs warnings and returns zeroes. diff --git a/mods/ITEMS/mcl_nether/nether_wart.lua b/mods/ITEMS/mcl_nether/nether_wart.lua index 0fe1a990a..8e26c529b 100644 --- a/mods/ITEMS/mcl_nether/nether_wart.lua +++ b/mods/ITEMS/mcl_nether/nether_wart.lua @@ -26,6 +26,7 @@ minetest.register_node("mcl_nether:nether_wart_0", { }, groups = {dig_immediate=3, not_in_creative_inventory=1,plant=1,attached_node=1,dig_by_water=1,destroy_by_lava_flow=1,dig_by_piston=1}, sounds = mcl_sounds.node_sound_leaves_defaults(), + after_place_node = mcl_time.touch, }) minetest.register_node("mcl_nether:nether_wart_1", { @@ -170,7 +171,6 @@ local function grow(pos, node) minetest.set_node(pos, new_node) local meta = minetest.get_meta(pos) meta:set_string("gametime", tostring(mcl_time:get_seconds_irl())) - end minetest.register_abm({ @@ -186,9 +186,10 @@ minetest.register_abm({ end pos.y = pos.y+1 - for i = 1, mcl_time.get_number_of_times_at_pos_or_1(pos, interval, chance) do + for i = 1, mcl_time.get_number_of_times_at_pos(pos, interval, chance) do grow(pos, node) end + mcl_time.touch(pos) end }) @@ -206,6 +207,7 @@ minetest.register_lbm({ for i = 1, mcl_time.get_number_of_times_at_pos(pos, interval, chance) do grow(pos, node) end + mcl_time.touch(pos) end }) From 9f395390e4d0df8a6fa45dadd959e1b0a6a61966 Mon Sep 17 00:00:00 2001 From: kay27 Date: Sat, 19 Feb 2022 02:36:02 +0400 Subject: [PATCH 51/68] Fix Nether Wart growth final hopefully --- mods/ITEMS/mcl_nether/nether_wart.lua | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/mods/ITEMS/mcl_nether/nether_wart.lua b/mods/ITEMS/mcl_nether/nether_wart.lua index 8e26c529b..90af6bdd6 100644 --- a/mods/ITEMS/mcl_nether/nether_wart.lua +++ b/mods/ITEMS/mcl_nether/nether_wart.lua @@ -26,7 +26,7 @@ minetest.register_node("mcl_nether:nether_wart_0", { }, groups = {dig_immediate=3, not_in_creative_inventory=1,plant=1,attached_node=1,dig_by_water=1,destroy_by_lava_flow=1,dig_by_piston=1}, sounds = mcl_sounds.node_sound_leaves_defaults(), - after_place_node = mcl_time.touch, + on_construct = mcl_time.touch, }) minetest.register_node("mcl_nether:nether_wart_1", { @@ -49,6 +49,7 @@ minetest.register_node("mcl_nether:nether_wart_1", { }, groups = {dig_immediate=3, not_in_creative_inventory=1,plant=1,attached_node=1,dig_by_water=1,destroy_by_lava_flow=1,dig_by_piston=1}, sounds = mcl_sounds.node_sound_leaves_defaults(), + on_construct = mcl_time.touch, }) minetest.register_node("mcl_nether:nether_wart_2", { @@ -71,6 +72,7 @@ minetest.register_node("mcl_nether:nether_wart_2", { }, groups = {dig_immediate=3, not_in_creative_inventory=1,plant=1,attached_node=1,dig_by_water=1,destroy_by_lava_flow=1,dig_by_piston=1}, sounds = mcl_sounds.node_sound_leaves_defaults(), + on_construct = mcl_time.touch, }) minetest.register_node("mcl_nether:nether_wart", { @@ -155,6 +157,7 @@ local names = {"mcl_nether:nether_wart_0", "mcl_nether:nether_wart_1", "mcl_neth local function grow(pos, node) local step = nil + local node = node or minetest.get_node(pos) for i, name in ipairs(names) do if name == node.name then step = i @@ -169,8 +172,6 @@ local function grow(pos, node) new_node.param = node.param new_node.param2 = node.param2 minetest.set_node(pos, new_node) - local meta = minetest.get_meta(pos) - meta:set_string("gametime", tostring(mcl_time:get_seconds_irl())) end minetest.register_abm({ @@ -178,7 +179,7 @@ minetest.register_abm({ nodenames = {"mcl_nether:nether_wart_0", "mcl_nether:nether_wart_1", "mcl_nether:nether_wart_2"}, neighbors = {"group:soil_nether_wart"}, interval = interval, - chance = chance, + chance = 1, action = function(pos, node) pos.y = pos.y-1 if minetest.get_item_group(minetest.get_node(pos).name, "soil_nether_wart") == 0 then @@ -187,9 +188,8 @@ minetest.register_abm({ pos.y = pos.y+1 for i = 1, mcl_time.get_number_of_times_at_pos(pos, interval, chance) do - grow(pos, node) + grow(pos) end - mcl_time.touch(pos) end }) @@ -205,9 +205,8 @@ minetest.register_lbm({ end pos.y = pos.y+1 for i = 1, mcl_time.get_number_of_times_at_pos(pos, interval, chance) do - grow(pos, node) + grow(pos) end - mcl_time.touch(pos) end }) From 7c5554a0f6c998aeeb0ddfe0d5f060354a24c69d Mon Sep 17 00:00:00 2001 From: kay27 Date: Sat, 19 Feb 2022 03:03:23 +0400 Subject: [PATCH 52/68] Remove crash on creative to survival gamemode change --- mods/HUD/hudbars/init.lua | 4 +-- mods/HUD/mcl_experience/init.lua | 45 ++++++++++++++++++-------------- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/mods/HUD/hudbars/init.lua b/mods/HUD/hudbars/init.lua index 505ff403b..ae4dd1713 100644 --- a/mods/HUD/hudbars/init.lua +++ b/mods/HUD/hudbars/init.lua @@ -52,11 +52,11 @@ end -- Load default settings dofile(modpath.."/default_settings.lua") -if minetest.get_modpath("mcl_experience") and not minetest.is_creative_enabled("") then +--if minetest.get_modpath("mcl_experience") and not minetest.is_creative_enabled("") then -- reserve some space for experience bar: hb.settings.start_offset_left.y = hb.settings.start_offset_left.y - 20 hb.settings.start_offset_right.y = hb.settings.start_offset_right.y - 20 -end +--end local function player_exists(player) return player ~= nil and player:is_player() diff --git a/mods/HUD/mcl_experience/init.lua b/mods/HUD/mcl_experience/init.lua index 2b6d4d5bf..65f456f81 100644 --- a/mods/HUD/mcl_experience/init.lua +++ b/mods/HUD/mcl_experience/init.lua @@ -156,6 +156,27 @@ function mcl_experience.throw_xp(pos, total_xp) end end +local function init_hudbars(player) + if not minetest.is_creative_enabled(player:get_player_name()) then + hud_bars[player] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0.5, y = 1}, + offset = {x = (-9 * 28) - 3, y = -(48 + 24 + 16 - 5)}, + scale = {x = 2.8, y = 3.0}, + alignment = {x = 1, y = 1}, + z_index = 11, + }) + + hud_levels[player] = player:hud_add({ + hud_elem_type = "text", + position = {x = 0.5, y = 1}, + number = 0x80FF20, + offset = {x = 0, y = -(48 + 24 + 24)}, + z_index = 12, + }) + end +end + function mcl_experience.update(player) if not mcl_util or not mcl_util.is_player(player) then return end local xp = mcl_experience.get_xp(player) @@ -164,6 +185,9 @@ function mcl_experience.update(player) cache.level = xp_to_level(xp) if not minetest.is_creative_enabled(player:get_player_name()) then + if not hud_bars[player] then + init_hudbars(player) + end player:hud_change(hud_bars[player], "text", "mcl_experience_bar_background.png^[lowpart:" .. math.floor(math.floor(xp_to_bar(xp, cache.level) * 18) / 18 * 100) .. ":mcl_experience_bar.png^[transformR270" @@ -187,26 +211,7 @@ minetest.register_on_joinplayer(function(player) caches[player] = { last_time = get_time(), } - - if not minetest.is_creative_enabled(player:get_player_name()) then - hud_bars[player] = player:hud_add({ - hud_elem_type = "image", - position = {x = 0.5, y = 1}, - offset = {x = (-9 * 28) - 3, y = -(48 + 24 + 16 - 5)}, - scale = {x = 2.8, y = 3.0}, - alignment = {x = 1, y = 1}, - z_index = 11, - }) - - hud_levels[player] = player:hud_add({ - hud_elem_type = "text", - position = {x = 0.5, y = 1}, - number = 0x80FF20, - offset = {x = 0, y = -(48 + 24 + 24)}, - z_index = 12, - }) - end - + init_hudbars(player) mcl_experience.update(player) end) From 17c30de74a5f9f4f578eb6a3a5e785b20eaafa51 Mon Sep 17 00:00:00 2001 From: kay27 Date: Sat, 19 Feb 2022 06:52:51 +0400 Subject: [PATCH 53/68] Fix maps in a very lame way --- mods/ITEMS/mcl_maps/init.lua | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_maps/init.lua b/mods/ITEMS/mcl_maps/init.lua index 954fe9ee7..314d91688 100644 --- a/mods/ITEMS/mcl_maps/init.lua +++ b/mods/ITEMS/mcl_maps/init.lua @@ -140,16 +140,22 @@ function mcl_maps.create_map(pos) return itemstack end +local loading_maps = {} + function mcl_maps.load_map(id) - if id == "" or creating_maps[id] then + if id == "" or creating_maps[id] or loading_maps[id] then return end local texture = "mcl_maps_map_texture_" .. id .. ".png" if not loaded_maps[id] then - loaded_maps[id] = true - minetest.dynamic_add_media(map_textures_path .. texture, function() end) + loading_maps[id] = true + minetest.dynamic_add_media({filepath = map_textures_path .. texture, ephemeral = true}, function(player_name) + loaded_maps[id] = true + loading_maps[id] = nil + end) + return end return texture From 7c3b0fcfc38a1bf90e23bffc0f646c0940b072c5 Mon Sep 17 00:00:00 2001 From: kay27 Date: Sun, 20 Feb 2022 03:31:36 +0400 Subject: [PATCH 54/68] Append irl time to map hash id --- mods/ITEMS/mcl_maps/init.lua | 2 +- mods/ITEMS/mcl_maps/locale/mcl_maps.fr.tr | 5 ++++- mods/ITEMS/mcl_maps/mod.conf | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_maps/init.lua b/mods/ITEMS/mcl_maps/init.lua index 314d91688..413e7382a 100644 --- a/mods/ITEMS/mcl_maps/init.lua +++ b/mods/ITEMS/mcl_maps/init.lua @@ -33,7 +33,7 @@ function mcl_maps.create_map(pos) local itemstack = ItemStack("mcl_maps:filled_map") local meta = itemstack:get_meta() - local id = string.format("%.0f", minetest.hash_node_position(minp)) + local id = string.format("%.0f-%.0f", minetest.hash_node_position(minp), mcl_time.get_seconds_irl()) meta:set_string("mcl_maps:id", id) meta:set_string("mcl_maps:minp", minetest.pos_to_string(minp)) meta:set_string("mcl_maps:maxp", minetest.pos_to_string(maxp)) diff --git a/mods/ITEMS/mcl_maps/locale/mcl_maps.fr.tr b/mods/ITEMS/mcl_maps/locale/mcl_maps.fr.tr index 9ef7cd5c5..1808e839d 100644 --- a/mods/ITEMS/mcl_maps/locale/mcl_maps.fr.tr +++ b/mods/ITEMS/mcl_maps/locale/mcl_maps.fr.tr @@ -1,5 +1,8 @@ # textdomain: mcl_maps Empty Map=Carte Vierge Empty maps are not useful as maps, but they can be stacked and turned to maps which can be used.=Les cartes vierges ne sont pas utiles en tant que cartes, mais elles peuvent être empilées et transformées en cartes utilisables. -Rightclick to start using the map (which can't be stacked anymore).=Clic droit pour commencer à utiliser la carte (qui ne peut plus être empilée). +Rightclick to create a filled map (which can't be stacked anymore).=Clic droit pour créer une carte remplie (qui ne peut plus être empilée). Map=Carte +Shows a map image.=Affiche une carte. +When created, the map saves the nearby area as an image that can be viewed any time by holding the map.=Lors de sa création, la carte sauvegarde le terrain proche sous forme d'image qui peut être consultée n'importe quand en tenant la carte dans la main. +Hold the map in your hand. This will display a map on your screen.=Tenez la carte dans votre main. Cela affichera la carte à l'écran. diff --git a/mods/ITEMS/mcl_maps/mod.conf b/mods/ITEMS/mcl_maps/mod.conf index 7275471b2..efe1708dd 100644 --- a/mods/ITEMS/mcl_maps/mod.conf +++ b/mods/ITEMS/mcl_maps/mod.conf @@ -1,2 +1,2 @@ name = mcl_maps -depends = mcl_core, mcl_flowers, tt, mcl_colors, mcl_skins, mcl_util +depends = mcl_core, mcl_flowers, tt, mcl_colors, mcl_skins, mcl_util, mcl_time From a6341374362d5f53b368d74eb426e215343c3ddd Mon Sep 17 00:00:00 2001 From: kay27 Date: Sun, 20 Feb 2022 03:36:53 +0400 Subject: [PATCH 55/68] Round seconds and fix minor error in mcl_time --- mods/CORE/mcl_time/README.md | 2 +- mods/CORE/mcl_time/init.lua | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/CORE/mcl_time/README.md b/mods/CORE/mcl_time/README.md index 24a4cd1cd..0fda96ad3 100644 --- a/mods/CORE/mcl_time/README.md +++ b/mods/CORE/mcl_time/README.md @@ -1,4 +1,4 @@ -# mcl_time v2.0 +# mcl_time v2.1 ## by kay27 for MineClone 5 --------------------------- This mod counts time when all players sleep or some area is inactive. diff --git a/mods/CORE/mcl_time/init.lua b/mods/CORE/mcl_time/init.lua index 2d7e93f9e..c4077b1fc 100644 --- a/mods/CORE/mcl_time/init.lua +++ b/mods/CORE/mcl_time/init.lua @@ -61,10 +61,10 @@ local function get_seconds_irl() next_save_seconds_irl = seconds_irl + save_to_storage_interval end - return seconds_irl + return math.floor(seconds_irl) end -local seconds_irl_public = get_seconds_irl() +seconds_irl_public = get_seconds_irl() function mcl_time.get_seconds_irl() return seconds_irl_public From 5ec7c5d246fa6a610912dccc6bb996c06f173a50 Mon Sep 17 00:00:00 2001 From: kay27 Date: Sun, 20 Feb 2022 04:35:46 +0400 Subject: [PATCH 56/68] Fix minor bug in mcl_time --- mods/CORE/mcl_time/README.md | 2 +- mods/CORE/mcl_time/init.lua | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mods/CORE/mcl_time/README.md b/mods/CORE/mcl_time/README.md index 0fda96ad3..ff4263f3f 100644 --- a/mods/CORE/mcl_time/README.md +++ b/mods/CORE/mcl_time/README.md @@ -1,4 +1,4 @@ -# mcl_time v2.1 +# mcl_time v2.2 ## by kay27 for MineClone 5 --------------------------- This mod counts time when all players sleep or some area is inactive. diff --git a/mods/CORE/mcl_time/init.lua b/mods/CORE/mcl_time/init.lua index c4077b1fc..5a3a2487a 100644 --- a/mods/CORE/mcl_time/init.lua +++ b/mods/CORE/mcl_time/init.lua @@ -102,7 +102,7 @@ function mcl_time.get_number_of_times_at_pos(pos, interval, chance) local meta = minetest.get_meta(pos) local last_time = meta:get_int(meta_name) meta:set_int(meta_name, seconds_irl_public) - local number_of_times = (last_time == 0) and 0 or get_number_of_times(last_time, interval, chance) + local number_of_times = (last_time <= 0) and 0 or get_number_of_times(last_time, interval, chance) return number_of_times end @@ -125,7 +125,7 @@ function mcl_time.get_irl_seconds_passed_at_pos(pos) local meta = minetest.get_meta(pos) local last_time = meta:get_int(meta_name) meta:set_int(meta_name, seconds_irl_public) - local irl_seconds_passed = (last_time == 0) and 0 or (seconds_irl_public - last_time) + local irl_seconds_passed = (last_time <= 0) and 0 or (seconds_irl_public - last_time) return irl_seconds_passed end @@ -135,7 +135,7 @@ function mcl_time.get_irl_seconds_passed_at_pos_or_1(pos) local meta = minetest.get_meta(pos) local last_time = meta:get_int(meta_name) meta:set_int(meta_name, seconds_irl_public) - local irl_seconds_passed = (last_time == 0) and 1 or (seconds_irl_public - last_time) + local irl_seconds_passed = (last_time <= 0) and 1 or (seconds_irl_public - last_time) return irl_seconds_passed end @@ -145,7 +145,7 @@ function mcl_time.get_irl_seconds_passed_at_pos_or_nil(pos) local meta = minetest.get_meta(pos) local last_time = meta:get_int(meta_name) meta:set_int(meta_name, seconds_irl_public) - if last_time == 0 then return end + if last_time <= 0 then return end local delta_time = seconds_irl_public - last_time if delta_time <= 0 then return end return delta_time From e155db8f9e305093d5f3dd512aebe288df716365 Mon Sep 17 00:00:00 2001 From: kay27 Date: Sun, 20 Feb 2022 04:39:28 +0400 Subject: [PATCH 57/68] Fix a crash --- mods/ITEMS/mcl_enchanting/engine.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_enchanting/engine.lua b/mods/ITEMS/mcl_enchanting/engine.lua index 97a176b97..1b672aea4 100644 --- a/mods/ITEMS/mcl_enchanting/engine.lua +++ b/mods/ITEMS/mcl_enchanting/engine.lua @@ -509,7 +509,7 @@ function mcl_enchanting.show_enchanting_formspec(player) .. "real_coordinates[true]" .. "image[3.15,0.6;7.6,4.1;mcl_enchanting_button_background.png]" local itemstack = inv:get_stack("enchanting_item", 1) - local player_levels = mcl_experience.get_level(player) + local player_levels = mcl_experience.get_level(player) or 0 local y = 0.65 local any_enchantment = false local table_slots = mcl_enchanting.get_table_slots(player, itemstack, num_bookshelves) From ae63e32048170e949c960d6e77c6fbcb2bfc3de9 Mon Sep 17 00:00:00 2001 From: kay27 Date: Sun, 20 Feb 2022 06:21:40 +0400 Subject: [PATCH 58/68] Add Breaking Changes: gamemode changes fly and noclip; chunksize set to 8 --- minetest.conf | 4 +++ mods/MAPGEN/mcl_mapgen_core/biomes.lua | 1 + mods/MAPGEN/mcl_mapgen_core/init.lua | 2 -- mods/MAPGEN/mcl_mapgen_core/nether.lua | 1 + mods/MISC/mcl_commands/gamemode.lua | 47 ++++++++++++++++++++++++++ mods/MISC/mcl_commands/init.lua | 2 ++ 6 files changed, 55 insertions(+), 2 deletions(-) diff --git a/minetest.conf b/minetest.conf index 97d1f5cd6..22270e9c2 100644 --- a/minetest.conf +++ b/minetest.conf @@ -36,6 +36,10 @@ mgvalleys_spflags = noaltitude_chill,noaltitude_dry,nohumid_rivers,vary_river_de # Probably values >10 won't work because of numerous overridings. Type: int. max_block_generate_distance = 13 +# Size of mapchunks generated by mapgen, stated in mapblocks (16 nodes). +# type: int +chunksize = 8 + # MCL2-specific stuff keepInventory = false diff --git a/mods/MAPGEN/mcl_mapgen_core/biomes.lua b/mods/MAPGEN/mcl_mapgen_core/biomes.lua index d50f4da56..16a19f160 100644 --- a/mods/MAPGEN/mcl_mapgen_core/biomes.lua +++ b/mods/MAPGEN/mcl_mapgen_core/biomes.lua @@ -1,3 +1,4 @@ +local c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass") local c_dirt_with_grass_snow = minetest.get_content_id("mcl_core:dirt_with_grass_snow") local c_top_snow = minetest.get_content_id("mcl_core:snow") local c_snow_block = minetest.get_content_id("mcl_core:snowblock") diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index e628321f0..f8a5d1b53 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -60,8 +60,6 @@ local flat = mcl_mapgen.flat -- Content IDs local c_bedrock = minetest.get_content_id("mcl_core:bedrock") -local c_dirt = minetest.get_content_id("mcl_core:dirt") -local c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass") local c_void = minetest.get_content_id("mcl_core:void") local c_lava = minetest.get_content_id("mcl_core:lava_source") diff --git a/mods/MAPGEN/mcl_mapgen_core/nether.lua b/mods/MAPGEN/mcl_mapgen_core/nether.lua index 1b05d32bf..ec75c80a2 100644 --- a/mods/MAPGEN/mcl_mapgen_core/nether.lua +++ b/mods/MAPGEN/mcl_mapgen_core/nether.lua @@ -5,6 +5,7 @@ local mcl_mushrooms = minetest.get_modpath("mcl_mushrooms") local c_water = minetest.get_content_id("mcl_core:water_source") local c_stone = minetest.get_content_id("mcl_core:stone") local c_sand = minetest.get_content_id("mcl_core:sand") +local c_dirt = minetest.get_content_id("mcl_core:dirt") local c_soul_sand = minetest.get_content_id("mcl_nether:soul_sand") local c_netherrack = minetest.get_content_id("mcl_nether:netherrack") diff --git a/mods/MISC/mcl_commands/gamemode.lua b/mods/MISC/mcl_commands/gamemode.lua index bd24a7685..8d720e21d 100644 --- a/mods/MISC/mcl_commands/gamemode.lua +++ b/mods/MISC/mcl_commands/gamemode.lua @@ -32,8 +32,17 @@ minetest.is_creative_enabled = function(name) return core_is_creative_enabled(name) end +local registered_functions_on_gamemode_change = {} + local function handle_gamemode_command(player_name, new_gamemode) + local old_gamemode_id = player_to_gamemode_id[player_name] + local old_gamemode = old_gamemode_id and id_to_gamemode[old_gamemode_id] player_to_gamemode_id[player_name] = gamemode_ids[new_gamemode] + if old_gamemode ~= new_gamemode then + for _, function_ref in pairs(registered_functions_on_gamemode_change) do + function_ref(player_name, old_gamemode, new_gamemode) + end + end return true end @@ -78,3 +87,41 @@ minetest.register_chatcommand("gamemode", { end end }) + +local action_id_to_index = {} + +function mcl_commands.register_on_gamemode_change(action_id, function_ref) + if action_id_to_index[action_id] then + minetest.log("warning", "[mcl_command] [gamemode] Duplicate register_on_gamemode_change action_id") + return + end + local new_index = #registered_functions_on_gamemode_change + 1 + registered_functions_on_gamemode_change[new_index] = function_ref + action_id_to_index[action_id] = new_index +end + +function mcl_commands.unregister_on_gamemode_change(action_id) + local old_index = action_id_to_index[action_id] + if not old_index then + minetest.log("warning", "[mcl_command] [gamemode] Can't unregister not registered action_id in unregister_on_gamemode_change") + return + end + table.remove(registered_functions_on_gamemode_change, old_index) + action_to_id[action_id] = nil +end + +mcl_commands.register_on_gamemode_change("check_fly_and_noclip", function(player_name, old_gamemode, new_gamemode) + if new_gamemode == "creative" then + local privs = minetest.get_player_privs(player_name) + if not privs then return end + privs.fly = true + privs.noclip = true + minetest.set_player_privs(player_name, privs) + elseif new_gamemode == "survival" then + local privs = minetest.get_player_privs(player_name) + if not privs then return end + privs.fly = nil + privs.noclip = nil + minetest.set_player_privs(player_name, privs) + end +end) diff --git a/mods/MISC/mcl_commands/init.lua b/mods/MISC/mcl_commands/init.lua index b6b07fb22..1fd5ecc3c 100644 --- a/mods/MISC/mcl_commands/init.lua +++ b/mods/MISC/mcl_commands/init.lua @@ -1,3 +1,5 @@ +mcl_commands = {} + local modpath = minetest.get_modpath(minetest.get_current_modname()) dofile(modpath.."/gamemode.lua") From b518bfd5c2e248f70f38dc5d049b8daa7fab503d Mon Sep 17 00:00:00 2001 From: kay27 Date: Sun, 20 Feb 2022 06:24:30 +0400 Subject: [PATCH 59/68] #198 Fix a crash, step 27 --- mods/HUD/mcl_title/init.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mods/HUD/mcl_title/init.lua b/mods/HUD/mcl_title/init.lua index 2ea1571c8..905707be4 100644 --- a/mods/HUD/mcl_title/init.lua +++ b/mods/HUD/mcl_title/init.lua @@ -157,13 +157,14 @@ function mcl_title.set(player, type, data) end function mcl_title.remove(player, type) - if player then + if player and mcl_util and mcl_util.is_player(player) then player:hud_change(huds_idx[type][player], "text", "") --player:hud_change(huds_idx[type][player], "style", 0) --no styling end end function mcl_title.clear(player) + if not mcl_util or not mcl_util.is_player(player) then return end mcl_title.remove(player, "title") mcl_title.remove(player, "subtitle") mcl_title.remove(player, "actionbar") From 63193638ed85d893c41890e6460a3740ee3fa1c6 Mon Sep 17 00:00:00 2001 From: kay27 Date: Sun, 20 Feb 2022 06:54:31 +0400 Subject: [PATCH 60/68] Add noise/chunk border indicator switch into settingtypes --- .../MAPGEN/mcl_structures/noise_indicator.lua | 37 ++++++++++++------- mods/MAPGEN/mcl_structures/structures.lua | 2 +- settingtypes.txt | 4 +- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/mods/MAPGEN/mcl_structures/noise_indicator.lua b/mods/MAPGEN/mcl_structures/noise_indicator.lua index 7cc130358..3845e5784 100644 --- a/mods/MAPGEN/mcl_structures/noise_indicator.lua +++ b/mods/MAPGEN/mcl_structures/noise_indicator.lua @@ -1,5 +1,4 @@ local step = 1 -local chunk_borders = false local levels = { [-9] = "black", @@ -31,21 +30,24 @@ local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_le local noise_offset_x_and_z = math_floor(mcl_mapgen.CS_NODES/2) mcl_mapgen.register_mapgen(function(minp, maxp, seed, vm_context) - local y0 = minp.y - for x0 = minp.x, maxp.x, step do - for z0 = minp.z, maxp.z, step do - local current_noise_level = mcl_structures_get_perlin_noise_level({x = x0 - noise_offset_x_and_z, y = y0, z = z0 - noise_offset_x_and_z}) - local amount - if current_noise_level < 0 then - amount = math_max(math_ceil(current_noise_level * 9), -9) - else - amount = math_min(math_floor(current_noise_level * 9), 9) + if minetest.settings:get_bool("mcl_debug_struct_noise", false) then + local y0 = minp.y + for x0 = minp.x, maxp.x, step do + for z0 = minp.z, maxp.z, step do + local current_noise_level = mcl_structures_get_perlin_noise_level({x = x0 - noise_offset_x_and_z, y = y0, z = z0 - noise_offset_x_and_z}) + local amount + if current_noise_level < 0 then + amount = math_max(math_ceil(current_noise_level * 9), -9) + else + amount = math_min(math_floor(current_noise_level * 9), 9) + end + local y0 = maxp.y - 9 + amount + minetest.set_node({x=x0, y=y0, z=z0}, {name = "mcl_core:glass_"..levels[amount]}) end - local y0 = maxp.y - 9 + amount - minetest.set_node({x=x0, y=y0, z=z0}, {name = "mcl_core:glass_"..levels[amount]}) end end - if chunk_borders then + + if minetest.settings:get_bool("mcl_debug_chunk_borders", false) then for x0 = minp.x, maxp.x, step do for y0 = minp.y, maxp.y, step do minetest.set_node({x=x0, y=y0, z=maxp.z}, {name = "mcl_core:glass"}) @@ -56,5 +58,12 @@ mcl_mapgen.register_mapgen(function(minp, maxp, seed, vm_context) minetest.set_node({x=maxp.x, y=y0, z=z0}, {name = "mcl_core:glass"}) end end + for z0 = minp.z, maxp.z, step do + for x0 = minp.x, maxp.x, step do + minetest.set_node({x=x0, y=maxp.y, z=z0}, {name = "mcl_core:glass"}) + end + end + if not minetest.settings:get_bool("mcl_debug_struct_noise", false) then + end end -end, -1) +end, 999999999999) diff --git a/mods/MAPGEN/mcl_structures/structures.lua b/mods/MAPGEN/mcl_structures/structures.lua index fd6b21b26..b18904d9a 100644 --- a/mods/MAPGEN/mcl_structures/structures.lua +++ b/mods/MAPGEN/mcl_structures/structures.lua @@ -11,7 +11,7 @@ if not mcl_mapgen.singlenode then dofile(modpath .. "/ice_spike_large.lua") dofile(modpath .. "/jungle_temple.lua") dofile(modpath .. "/nice_jungle_temple.lua") - -- dofile(modpath .. "/noise_indicator.lua") + dofile(modpath .. "/noise_indicator.lua") dofile(modpath .. "/stronghold.lua") dofile(modpath .. "/witch_hut.lua") end diff --git a/settingtypes.txt b/settingtypes.txt index 44bea1122..dca03b7e1 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -167,4 +167,6 @@ kick_threshold (Cheat Kicking Threshold) int 10 [Debugging] # If enabled, this will show the itemstring of an item in the description. -mcl_item_id_debug (Item ID Debug) bool false \ No newline at end of file +mcl_item_id_debug (Item ID Debug) bool false +mcl_debug_struct_noise (Show Structures Perlin Noise) bool false +mcl_debug_chunk_borders (Show Chunk Borders) bool false From 1a4ec509392ac3572737676b7ac55d4cea9ec10e Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 21 Feb 2022 05:51:00 +0400 Subject: [PATCH 61/68] #220 Fix a crash in mcl_comparators --- mods/ITEMS/REDSTONE/mcl_comparators/init.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/REDSTONE/mcl_comparators/init.lua b/mods/ITEMS/REDSTONE/mcl_comparators/init.lua index 3517e09cb..b596f26ff 100644 --- a/mods/ITEMS/REDSTONE/mcl_comparators/init.lua +++ b/mods/ITEMS/REDSTONE/mcl_comparators/init.lua @@ -43,7 +43,9 @@ end local function comparator_activate(pos, node) local def = minetest.registered_nodes[node.name] - minetest.swap_node(pos, { name = def.comparator_onstate, param2 = node.param2 }) + local on_state = def.comparator_onstate + if not on_state then return end + minetest.swap_node(pos, { name = on_state, param2 = node.param2 }) minetest.after(0.1, comparator_turnon , {pos = pos, node = node}) end From 9db3b97202bbd6894525df6b5f0dd6bd31296c4d Mon Sep 17 00:00:00 2001 From: kay27 Date: Tue, 22 Feb 2022 03:12:45 +0400 Subject: [PATCH 62/68] Add crying obsidian --- mods/ENTITIES/mcl_dripping/init.lua | 64 ++++++++++++++---- mods/ENTITIES/mcl_dripping/readme.txt | 59 ++++++++-------- mods/ITEMS/mcl_core/locale/template.txt | 2 + mods/ITEMS/mcl_core/nodes_base.lua | 13 ++++ .../textures/mcl_core_crying_obsidian.png | Bin 0 -> 250 bytes 5 files changed, 97 insertions(+), 41 deletions(-) create mode 100644 mods/ITEMS/mcl_core/textures/mcl_core_crying_obsidian.png diff --git a/mods/ENTITIES/mcl_dripping/init.lua b/mods/ENTITIES/mcl_dripping/init.lua index 57ba7ecfe..b1cf79796 100644 --- a/mods/ENTITIES/mcl_dripping/init.lua +++ b/mods/ENTITIES/mcl_dripping/init.lua @@ -1,16 +1,24 @@ -- Dripping Water Mod -- by kddekadenz - -local math = math - -- License of code, textures & sounds: CC0 -local function register_drop(liquid, glow, sound, nodes) - minetest.register_entity("mcl_dripping:drop_" .. liquid, { +local math_random = math.random + +local all_dirs = { + {x = 0, y = 0, z = 1}, + {x = 0, y = 1, z = 0}, + {x = 1, y = 0, z = 0}, + {x = 0, y = 0, z =-1}, + {x = 0, y =-1, z = 0}, + {x =-1, y = 0, z = 0}, +} + +local function register_drop_entity(substance, glow, sound, texture_file_name) + minetest.register_entity("mcl_dripping:drop_" .. substance, { hp_max = 1, physical = true, collide_with_objects = false, - collisionbox = {-0.01, 0.01, -0.01, 0.01, 0.01, 0.01}, + collisionbox = {-0.01, -0.01, -0.01, 0.01, 0.01, 0.01}, glow = glow, pointable = false, visual = "sprite", @@ -22,11 +30,18 @@ local function register_drop(liquid, glow, sound, nodes) _dropped = false, on_activate = function(self) self.object:set_properties({ - textures = {"[combine:2x2:" .. -math.random(1, 16) .. "," .. -math.random(1, 16) .. "=default_" .. liquid .. "_source_animated.png"} + textures = { + "[combine:2x2:" + .. -math_random(1, 16) + .. "," + .. -math_random(1, 16) + .. "=" + .. (texture_file_name or ("default_" .. substance .. "_source_animated.png")) + } }) end, on_step = function(self, dtime) - local k = math.random(1, 222) + local k = math_random(1, 222) local ownpos = self.object:get_pos() if k == 1 then self.object:set_acceleration(vector.new(0, -5, 0)) @@ -38,7 +53,9 @@ local function register_drop(liquid, glow, sound, nodes) local ent = self.object:get_luaentity() if not ent._dropped then ent._dropped = true - minetest.sound_play({name = "drippingwater_" .. sound .. "drip"}, {pos = ownpos, gain = 0.5, max_hear_distance = 8}, true) + if sound then + minetest.sound_play({name = "drippingwater_" .. sound .. "drip"}, {pos = ownpos, gain = 0.5, max_hear_distance = 8}, true) + end end if k < 3 then self.object:remove() @@ -46,6 +63,10 @@ local function register_drop(liquid, glow, sound, nodes) end end, }) +end + +local function register_liquid_drop(liquid, glow, sound, nodes) + register_drop_entity(liquid, glow, sound) minetest.register_abm({ label = "Create drops", nodenames = nodes, @@ -55,12 +76,31 @@ local function register_drop(liquid, glow, sound, nodes) action = function(pos) if minetest.get_item_group(minetest.get_node(vector.offset(pos, 0, 1, 0)).name, liquid) ~= 0 and minetest.get_node(vector.offset(pos, 0, -1, 0)).name == "air" then - local x, z = math.random(-45, 45) / 100, math.random(-45, 45) / 100 + local x, z = math_random(-45, 45) / 100, math_random(-45, 45) / 100 minetest.add_entity(vector.offset(pos, x, -0.520, z), "mcl_dripping:drop_" .. liquid) end end, }) end -register_drop("water", 1, "", {"group:opaque", "group:leaves"}) -register_drop("lava", math.max(7, minetest.registered_nodes["mcl_core:lava_source"].light_source - 3), "lava", {"group:opaque"}) \ No newline at end of file +register_liquid_drop("water", 1, "", {"group:opaque", "group:leaves"}) +register_liquid_drop("lava", math.max(7, minetest.registered_nodes["mcl_core:lava_source"].light_source - 3), "lava", {"group:opaque"}) + +register_drop_entity("crying_obsidian", 10, nil, "mcl_core_crying_obsidian.png") +minetest.register_abm({ + label = "Create crying obsidian drops", + nodenames = {"mcl_core:crying_obsidian"}, + neighbors = {"air"}, + interval = 2, + chance = 22, + action = function(pos) + local i0 = math_random(1, 6) + for i = i0, i0 + 5 do + local dir = all_dirs[(i % 6) + 1] + if minetest.get_node(vector.add(pos, dir)).name == "air" then + minetest.add_entity(vector.offset(pos, dir.x * 0.52, dir.y * 0.52, dir.z * 0.52), "mcl_dripping:drop_crying_obsidian") + return + end + end + end, +}) diff --git a/mods/ENTITIES/mcl_dripping/readme.txt b/mods/ENTITIES/mcl_dripping/readme.txt index afe35608e..583cb65d7 100644 --- a/mods/ENTITIES/mcl_dripping/readme.txt +++ b/mods/ENTITIES/mcl_dripping/readme.txt @@ -1,29 +1,30 @@ -Dripping Mod -by kddekadenz - -modified for MineClone 2 by Wuzzy and NO11 - - -Installing instructions: - - 1. Copy the mcl_dripping mod folder into games/gamemode/mods - - 2. Start game and enjoy :) - - -Manual: - --> drops are generated rarely under solid nodes --> they will stay some time at the generated block and than they fall down --> when they collide with the ground, a sound is played and they are destroyed - - -License: - -code & sounds: CC0 - - -Changelog: - -16.04.2012 - first release -28.04.2012 - drops are now 3D; added lava drops; fixed generating of drops (not at edges now) +Dripping Mod +by kddekadenz + +modified for MineClone 2 by Wuzzy and NO11 +modified for MineClone 5 by kay27 + + +Installing instructions: + + 1. Copy the mcl_dripping mod folder into games/gamemode/mods + + 2. Start game and enjoy :) + + +Manual: + +-> drops are generated rarely under solid nodes +-> they will stay some time at the generated block and than they fall down +-> when they collide with the ground, a sound is played and they are destroyed + + +License: + +code & sounds: CC0 + + +Changelog: + +16.04.2012 - first release +28.04.2012 - drops are now 3D; added lava drops; fixed generating of drops (not at edges now) diff --git a/mods/ITEMS/mcl_core/locale/template.txt b/mods/ITEMS/mcl_core/locale/template.txt index da500ab8c..57b15ef82 100644 --- a/mods/ITEMS/mcl_core/locale/template.txt +++ b/mods/ITEMS/mcl_core/locale/template.txt @@ -155,6 +155,8 @@ Oak Wood Planks= Oak leaves are grown from oak trees.= Obsidian= Obsidian is an extremely hard mineral with an enourmous blast-resistance. Obsidian is formed when water meets lava.= +Crying Obsidian= +Crying obsidian is a luminous obsidian that can generate as part of ruined portals.= One of the most common blocks in the world, almost the entire underground consists of stone. It sometimes contains ores. Stone may be created when water meets lava.= Orange Stained Glass= Packed Ice= diff --git a/mods/ITEMS/mcl_core/nodes_base.lua b/mods/ITEMS/mcl_core/nodes_base.lua index fe1ee58c2..ebae759ac 100644 --- a/mods/ITEMS/mcl_core/nodes_base.lua +++ b/mods/ITEMS/mcl_core/nodes_base.lua @@ -826,6 +826,19 @@ minetest.register_node("mcl_core:obsidian", { end, }) +minetest.register_node("mcl_core:crying_obsidian", { + description = S("Crying Obsidian"), + _doc_items_longdesc = S("Crying obsidian is a luminous obsidian that can generate as part of ruined portals."), + tiles = {"default_obsidian.png^mcl_core_crying_obsidian.png"}, + is_ground_content = false, + light_source = 10, + sounds = mcl_sounds.node_sound_stone_defaults(), + stack_max = 64, + groups = {pickaxey=5, building_block=1, material_stone=1}, + _mcl_blast_resistance = 1200, + _mcl_hardness = 50, +}) + minetest.register_node("mcl_core:ice", { description = S("Ice"), _doc_items_longdesc = S("Ice is a solid block usually found in cold areas. It melts near block light sources at a light level of 12 or higher. When it melts or is broken while resting on top of another block, it will turn into a water source."), diff --git a/mods/ITEMS/mcl_core/textures/mcl_core_crying_obsidian.png b/mods/ITEMS/mcl_core/textures/mcl_core_crying_obsidian.png new file mode 100644 index 0000000000000000000000000000000000000000..6229fe08add9b25be90417e112520c5333b38758 GIT binary patch literal 250 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=85sEXfH33KJw={CLG}_)Usv`g99-Od7E2_Q5`aQgo-U3d7N?UF z7BHx6So`n1M`v29nm3zUlBkh^fx(r36ArH1H}mny|18_C{{JX><;+Kx)i%ODNe9;l zEQ)as5SZ@Gv2((L;6g^X8ny>KCP|As6E83(Es|coD6LQZ|3+2=;cW~@rm4OAXYKd5 oLD|bz&vnP1mPLZ|nPwbh$V>5Na1*?97U&8FPgg&ebxsLQ06)1_&j0`b literal 0 HcmV?d00001 From 0ceb7fa01369709a8cece209e6afdf6a5c4ab767 Mon Sep 17 00:00:00 2001 From: kay27 Date: Wed, 23 Feb 2022 06:26:21 +0400 Subject: [PATCH 63/68] Add ruined portal frames --- mods/MAPGEN/mcl_structures/ruined_portal.lua | 321 +++++++++++++++++++ mods/MAPGEN/mcl_structures/structures.lua | 1 + 2 files changed, 322 insertions(+) create mode 100644 mods/MAPGEN/mcl_structures/ruined_portal.lua diff --git a/mods/MAPGEN/mcl_structures/ruined_portal.lua b/mods/MAPGEN/mcl_structures/ruined_portal.lua new file mode 100644 index 000000000..f75d536cf --- /dev/null +++ b/mods/MAPGEN/mcl_structures/ruined_portal.lua @@ -0,0 +1,321 @@ +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) + +local chance_per_chunk = 400 +chance_per_chunk = 1 +local noise_multiplier = 2.5 +local random_offset = 9159 +local scanning_ratio = 0.0001 +local struct_threshold = chance_per_chunk - 3 + +local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level + +local rotation_to_orientation = { + ["0"] = 1, + ["90"] = 0, + ["180"] = 1, + ["270"] = 0, +} + +local rotation_to_param2 = { + ["0"] = 3, + ["90"] = 0, + ["180"] = 1, + ["270"] = 2, +} + +local node_top = { + "mcl_core:goldblock", + "mcl_core:stone_with_gold", + "mcl_core:goldblock", +} + +local stone1 = {name = "mcl_core:stonebrickcracked"} +local stone2 = {name = "mcl_core:stonebrickmossy"} +local stone4 = {name = "mcl_core:stonebrick"} + +local slab1 = {name = "mcl_stairs:slab_stonebrickcracked_top"} +local slab2 = {name = "mcl_stairs:slab_stonebrickmossy_top"} +local slab3 = {name = "mcl_stairs:slab_stone_top"} +local slab4 = {name = "mcl_stairs:slab_stonebrick_top"} + +local stair1 = "mcl_stairs:stair_stonebrickcracked" +local stair2 = "mcl_stairs:stair_stonebrickmossy" +local stair3 = "mcl_stairs:stair_stone_rough" +local stair4 = "mcl_stairs:stair_stonebrick" + + +local function draw_frame(frame_pos, frame_width, frame_height, orientation, pr, is_chain, rotation) + local param2 = rotation_to_param2[rotation] + + local function set_ruined_node(pos, node) + if pr:next(1, 5) == 4 then return end + minetest.set_node(pos, node) + end + + local function get_random_stone_material() + local rnd = pr:next(1, 15) + if rnd < 4 then return stone1 end + if rnd == 4 then return stone2 end + if rnd == 5 then return stone3 end + return stone4 + end + + local function get_random_slab() + local rnd = pr:next(1, 15) + if rnd < 4 then return slab1 end + if rnd == 4 then return slab2 end + if rnd == 5 then return slab3 end + return slab4 + end + + local function get_random_stair(param2_offset) + local param2 = (param2 + (param2_offset or 0)) % 4 + local rnd = pr:next(1, 15) + if rnd < 4 then return {name = stair1, param2 = param2} end + if rnd == 4 then return {name = stair2, param2 = param2} end + if rnd == 5 then return {name = stair3, param2 = param2} end + return {name = stair4, param2 = param2} + end + + local function set_frame_stone_material(pos) + minetest.swap_node(pos, get_random_stone_material()) + end + + local function set_ruined_frame_stone_material(pos) + set_ruined_node(pos, get_random_stone_material()) + end + + local is_chain = is_chain + local orientation = orientation + local x1 = frame_pos.x + local y1 = frame_pos.y + local z1 = frame_pos.z + local slide_x = (1 - orientation) + local slide_z = orientation + local last_x = x1 + (frame_width - 1) * slide_x + local last_z = z1 + (frame_width - 1) * slide_z + local last_y = y1 + frame_height - 1 + + -- it's about the portal frame itself, what it will consist of + local frame_nodes = 2 * (frame_height + frame_width) - 4 + local obsidian_nodes = pr:next(math.round(frame_nodes * 0.5), math.round(frame_nodes * 0.73)) + local crying_obsidian_nodes = pr:next(math.round(obsidian_nodes * 0.09), math.round(obsidian_nodes * 0.5)) + local air_nodes = frame_nodes - obsidian_nodes + + local function set_frame_node(pos) + -- local node_choice = pr:next(1, air_nodes + obsidian_nodes) + local node_choice = math.round(mcl_structures_get_perlin_noise_level(pos) * (air_nodes + obsidian_nodes)) + if node_choice > obsidian_nodes and air_nodes > 0 then + air_nodes = air_nodes - 1 + return + end + obsidian_nodes = obsidian_nodes - 1 + if node_choice >= crying_obsidian_nodes then + minetest.swap_node(pos, {name = "mcl_core:obsidian"}) + return 1 + end + minetest.swap_node(pos, {name = "mcl_core:crying_obsidian"}) + crying_obsidian_nodes = crying_obsidian_nodes - 1 + return 1 + end + + local function set_outer_frame_node(def) + local is_top = def.is_top + if is_chain then + local pos2 = def.pos_outer2 + local is_top_hole = is_top and frame_width > 5 and ((pos2.x == x1 + slide_x * 2 and pos2.z == z1 + slide_z * 2) or (pos2.x == last_x - slide_x * 2 and pos2.z == last_z - slide_z * 2)) + if is_top_hole then + if pr:next(1, 7) > 1 then + minetest.swap_node(pos2, {name = "xpanes:bar_flat", param2 = orientation}) + end + else + set_frame_stone_material(pos2) + end + end + local is_obsidian = def.is_obsidian + if not is_obsidian and pr:next(1, 2) == 1 then return end + local pos = def.pos_outer1 + local is_decor_here = not is_top and pos.y % 3 == 2 + if is_decor_here then + minetest.swap_node(pos, {name = "mcl_core:stonebrickcarved"}) + elseif is_chain then + if not is_top and not is_obsidian then + minetest.swap_node(pos, {name = "xpanes:bar"}) + else + minetest.swap_node(pos, {name = "xpanes:bar_flat", param2 = orientation}) + end + else + if pr:next(1, 5) == 3 then + minetest.swap_node(pos, {name = "mcl_core:stonebrickcracked"}) + else + minetest.swap_node(pos, {name = "mcl_core:stonebrick"}) + end + end + end + + local function draw_roof(pos, length) + local x = pos.x + local y = pos.y + local z = pos.z + local number_of_roof_nodes = length + if number_of_roof_nodes > 1 then + set_ruined_node({x = x, y = y, z = z}, get_random_stair((param2 == 1 or param2 == 2) and -1 or 1)) + set_ruined_node({x = x + (length - 1) * slide_x, y = y, z = z + (length - 1) * slide_z}, get_random_stair((param2 == 1 or param2 == 2) and 1 or -1)) + number_of_roof_nodes = number_of_roof_nodes - 2 + x = x + slide_x + z = z + slide_z + end + while number_of_roof_nodes > 0 do + set_ruined_node({x = x, y = y, z = z}, get_random_stair((param2 == 1 or param2 == 2) and 2 or 0)) + x = x + slide_x + z = z + slide_z + number_of_roof_nodes = number_of_roof_nodes - 1 + end + end + + -- bottom corners + set_frame_node({x = x1, y = y1, z = z1}) + set_frame_node({x = last_x, y = y1, z = last_z}) + + -- top corners + local is_obsidian_top_left = set_frame_node({x = x1, y = last_y, z = z1}) + local is_obsidian_top_right = set_frame_node({x = last_x, y = last_y, z = last_z}) + + if is_chain then + if is_obsidian_top_left and pr:next(1, 4) ~= 2 then + set_frame_stone_material({x = x1 - slide_x * 2, y = last_y + 2, z = z1 - slide_z * 2}) + end + if is_obsidian_top_left and pr:next(1, 4) ~= 2 then + set_frame_stone_material({x = x1 - slide_x * 2, y = last_y + 1, z = z1 - slide_z * 2}) + end + if is_obsidian_top_left and pr:next(1, 4) ~= 2 then + set_frame_stone_material({x = last_x + slide_x * 2, y = last_y + 2, z = last_z + slide_z * 2}) + end + if is_obsidian_top_left and pr:next(1, 4) ~= 2 then + set_frame_stone_material({x = last_x + slide_x * 2, y = last_y + 1, z = last_z + slide_z * 2}) + end + end + + for y = y1, last_y do + local begin_or_end = y == y1 or y == lasy_y + local is_obsidian_left = begin_or_end and is_obsidian_top_left or set_frame_node({x = x1 , y = y, z = z1 }) + local is_obsidian_right = begin_or_end and is_obsidian_top_right or set_frame_node({x = last_x, y = y, z = last_z}) + set_outer_frame_node({ + pos_outer1 = {x = x1 - slide_x , y = y, z = z1 - slide_z }, + pos_outer2 = {x = x1 - slide_x * 2, y = y, z = z1 - slide_z * 2}, + is_obsidian = is_obsidian_left, + }) + set_outer_frame_node({ + pos_outer1 = {x = last_x + slide_x , y = y, z = last_z + slide_z }, + pos_outer2 = {x = last_x + slide_x * 2, y = y, z = last_z + slide_z * 2}, + is_obsidian = is_obsidian_right, + }) + end + + for i = 0, 1 do + set_outer_frame_node({ + pos_outer1 = {x = x1 - slide_x * i, y = last_y + 1, z = z1 - slide_z * i}, + pos_outer2 = {x = x1 - slide_x * i, y = last_y + 2, z = z1 - slide_z * i}, + is_obsidian = is_obsidian_top_left, + is_top = true, + }) + set_outer_frame_node({ + pos_outer1 = {x = last_x + slide_x * i, y = last_y + 1, z = last_z + slide_z * i}, + pos_outer2 = {x = last_x + slide_x * i, y = last_y + 2, z = last_z + slide_z * i}, + is_obsidian = is_obsidian_top_right, + is_top = true, + }) + end + + for x = x1 + slide_x, last_x - slide_x do for z = z1 + slide_z, last_z - slide_z do + set_frame_node({x = x, y = y1, z = z}) + local is_obsitian_top = set_frame_node({x = x, y = last_y, z = z}) + set_outer_frame_node({ + pos_outer1 = {x = x, y = last_y + 1, z = z}, + pos_outer2 = {x = x, y = last_y + 2, z = z}, + is_obsidian = is_obsidian_top, + is_top = true + }) + end end + + local node_top = {name = node_top[pr:next(1, #node_top)]} + if is_chain then + set_ruined_frame_stone_material({x = x1 + slide_x * 2, y = last_y + 3, z = z1 + slide_z * 2}) + set_ruined_frame_stone_material({x = x1 + slide_x , y = last_y + 3, z = z1 + slide_z }) + set_ruined_frame_stone_material({x = last_x - slide_x , y = last_y + 3, z = last_z - slide_z }) + set_ruined_frame_stone_material({x = last_x - slide_x * 2, y = last_y + 3, z = last_z - slide_z * 2}) + for x = x1 + slide_x * 3, last_x - slide_x * 3 do for z = z1 + slide_z * 3, last_z - slide_z * 3 do + set_ruined_node({x = x, y = last_y + 3, z = z}, node_top) + set_ruined_node({x = x - slide_z, y = last_y + 3, z = z - slide_x}, get_random_slab()) + set_ruined_node({x = x + slide_z, y = last_y + 3, z = z + slide_x}, get_random_slab()) + end end + draw_roof({x = x1 + slide_x * 3, y = last_y + 4, z = z1 + slide_z * 3}, frame_width - 6) + else + set_ruined_frame_stone_material({x = x1 + slide_x * 3, y = last_y + 2, z = z1 + slide_z * 3}) + set_ruined_frame_stone_material({x = x1 + slide_x * 2, y = last_y + 2, z = z1 + slide_z * 2}) + set_ruined_frame_stone_material({x = last_x - slide_x * 2, y = last_y + 2, z = last_z - slide_z * 2}) + set_ruined_frame_stone_material({x = last_x - slide_x * 3, y = last_y + 2, z = last_z - slide_z * 3}) + for x = x1 + slide_x * 4, last_x - slide_x * 4 do for z = z1 + slide_z * 4, last_z - slide_z * 4 do + set_ruined_node({x = x, y = last_y + 2, z = z}, node_top) + set_ruined_node({x = x - slide_z, y = last_y + 2, z = z - slide_x}, get_random_slab()) + set_ruined_node({x = x + slide_z, y = last_y + 2, z = z + slide_x}, get_random_slab()) + end end + draw_roof({x = x1 + slide_x * 3, y = last_y + 3, z = z1 + slide_z * 3}, frame_width - 6) + end +end + +local possible_rotations = {"0", "90", "180", "270"} + +local function place(pos, rotation, pr) + local width = pr:next(2, 10) + local height = pr:next(((width < 3) and 3 or 2), 10) + local lift = pr:next(0, 4) + local rotation = rotation or possible_rotations[pr:next(1, #possible_rotations)] + local orientation = rotation_to_orientation[rotation] + local is_chain = pr:next(1, 3) > 1 + assert(orientation) + draw_frame({x = pos.x, y = pos.y + lift, z = pos.z}, width + 2, height + 2, orientation, pr, is_chain, rotation) +end + +local function get_place_rank(pos) + local x, y, z = pos.x, pos.y, pos.z + local p1 = {x = x , y = y, z = z } + local p2 = {x = x + 7, y = y, z = z + 7} + local air_pos_list_surface = #minetest.find_nodes_in_area(p1, p2, "air", false) + p1.y = p1.y - 1 + p2.y = p2.y - 1 + local opaque_pos_list_surface = #minetest.find_nodes_in_area(p1, p2, "group:opaque", false) + return air_pos_list_surface + 3 * opaque_pos_list_surface +end + +mcl_structures.register_structure({ + name = "ruined_portal", + decoration = { + deco_type = "simple", + flags = "all_floors", + fill_ratio = scanning_ratio, + height = 1, + }, + on_finished_chunk = function(minp, maxp, seed, vm_context, pos_list) + if maxp.y < mcl_mapgen.overworld.min then return end + local pr = PseudoRandom(seed + random_offset) + local random_number = pr:next(1, chance_per_chunk) + local noise = mcl_structures_get_perlin_noise_level(minp) * noise_multiplier + if (random_number + noise) < struct_threshold then return end + local pos = pos_list[1] + if #pos_list > 1 then + local count = get_place_rank(pos) + for i = 2, #pos_list do + local pos_i = pos_list[i] + local count_i = get_place_rank(pos_i) + if count_i > count then + count = count_i + pos = pos_i + end + end + end + place(pos, nil, pr) + end, + place_function = place, +}) diff --git a/mods/MAPGEN/mcl_structures/structures.lua b/mods/MAPGEN/mcl_structures/structures.lua index b18904d9a..32a399ae3 100644 --- a/mods/MAPGEN/mcl_structures/structures.lua +++ b/mods/MAPGEN/mcl_structures/structures.lua @@ -12,6 +12,7 @@ if not mcl_mapgen.singlenode then dofile(modpath .. "/jungle_temple.lua") dofile(modpath .. "/nice_jungle_temple.lua") dofile(modpath .. "/noise_indicator.lua") + dofile(modpath .. "/ruined_portal.lua") dofile(modpath .. "/stronghold.lua") dofile(modpath .. "/witch_hut.lua") end From 8272343084881b5ca91a04b486058d29b1f5eb39 Mon Sep 17 00:00:00 2001 From: kay27 Date: Wed, 23 Feb 2022 07:53:21 +0400 Subject: [PATCH 64/68] Reduce chunk size to 4x4x4, add ruined portals beta --- minetest.conf | 2 +- mods/MAPGEN/mcl_structures/ruined_portal.lua | 87 +++++++++++++++++++- 2 files changed, 84 insertions(+), 5 deletions(-) diff --git a/minetest.conf b/minetest.conf index 22270e9c2..423ac3a34 100644 --- a/minetest.conf +++ b/minetest.conf @@ -38,7 +38,7 @@ max_block_generate_distance = 13 # Size of mapchunks generated by mapgen, stated in mapblocks (16 nodes). # type: int -chunksize = 8 +chunksize = 4 # MCL2-specific stuff keepInventory = false diff --git a/mods/MAPGEN/mcl_structures/ruined_portal.lua b/mods/MAPGEN/mcl_structures/ruined_portal.lua index f75d536cf..b190921fa 100644 --- a/mods/MAPGEN/mcl_structures/ruined_portal.lua +++ b/mods/MAPGEN/mcl_structures/ruined_portal.lua @@ -2,11 +2,10 @@ local modname = minetest.get_current_modname() local modpath = minetest.get_modpath(modname) local chance_per_chunk = 400 -chance_per_chunk = 1 local noise_multiplier = 2.5 local random_offset = 9159 -local scanning_ratio = 0.0001 -local struct_threshold = chance_per_chunk - 3 +local scanning_ratio = 0.01 +local struct_threshold = 390 local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level @@ -30,8 +29,18 @@ local node_top = { "mcl_core:goldblock", } +local node_garbage = { + "mcl_nether:netherrack", + "mcl_core:lava_source", + "mcl_nether:netherrack", + "mcl_nether:netherrack", + "mcl_nether:magma", + "mcl_nether:netherrack", +} + local stone1 = {name = "mcl_core:stonebrickcracked"} local stone2 = {name = "mcl_core:stonebrickmossy"} +local stone3 = {name = "mcl_nether:magma"} local stone4 = {name = "mcl_core:stonebrick"} local slab1 = {name = "mcl_stairs:slab_stonebrickcracked_top"} @@ -267,14 +276,83 @@ end local possible_rotations = {"0", "90", "180", "270"} +local function draw_trash(pos, width, height, lift, orientation, pr) + local slide_x = (1 - orientation) + local slide_z = orientation + local x1 = pos.x - lift - 1 + local x2 = pos.x + (width - 1) * slide_x + lift + 1 + local z1 = pos.z - lift - 1 + local z2 = pos.z + (width - 1) * slide_z + lift + 1 + local y1 = pos.y - pr:next(1, height) - 1 + local y2 = pos.y + local opacity_layers = math.floor((y2 - y1) / 2) + local opacity_layer = -opacity_layers + for y = y1, y2 do + local inverted_opacity_0_5 = math.round(math.abs(opacity_layer) / opacity_layers * 5) + for x = x1 + pr:next(0, 2), x2 - pr:next(0, 2) do + for z = z1 + pr:next(0, 2), z2 - pr:next(0, 2) do + if inverted_opacity_0_5 == 0 or (x % inverted_opacity_0_5 ~= pr:next(0, 1) and z % inverted_opacity_0_5 ~= pr:next(0, 1)) then + minetest.swap_node({x = x, y = y, z = z}, {name = node_garbage[pr:next(1, #node_garbage)]}) + end + end + end + opacity_layer = opacity_layer + 1 + end +end + +local stair_replacement_list = { + "air", + "group:water", + "group:lava", + "group:buildable_to", + "group:deco_block", +} + +local stair_offset_from_bottom = 3 +local function draw_stairs(pos, width, height, lift, orientation, pr, is_chain) + local lift = lift + stair_offset_from_bottom + local slide_x = (1 - orientation) + local slide_z = orientation + local width = width + (is_chain and 2 or 0) + local x1 = pos.x - lift - (is_chain and 1 or 0) - 1 + local x2 = pos.x + lift + width * slide_x + 1 + local z1 = pos.z - lift - (is_chain and 1 or 0) - 1 + local z2 = pos.z + lift + width * slide_z + 1 + local y1 = pos.y - stair_offset_from_bottom + local y2 = pos.y + lift - stair_offset_from_bottom + local current_radius = lift + for y = y1, y2 do + for x = x1, x2 do + for z = z1, z2 do +--local stair1 = "mcl_stairs:stair_stonebrickcracked" +--local stair2 = "mcl_stairs:stair_stonebrickmossy" +--local stair3 = "mcl_stairs:stair_stone_rough" +--local stair4 = "mcl_stairs:stair_stonebrick" + local pos = {x = x, y = y, z = z} + if #minetest.find_nodes_in_area(pos, pos, stair_replacement_list, false) > 0 then + minetest.swap_node(pos, {name = "mcl_stairs:stair_stone_rough"}) + end + end + end + x1 = x1 + 1 + x2 = x2 - 1 + z1 = z1 + 1 + z2 = z2 - 1 + end +end + local function place(pos, rotation, pr) local width = pr:next(2, 10) local height = pr:next(((width < 3) and 3 or 2), 10) local lift = pr:next(0, 4) local rotation = rotation or possible_rotations[pr:next(1, #possible_rotations)] local orientation = rotation_to_orientation[rotation] - local is_chain = pr:next(1, 3) > 1 assert(orientation) + local param2 = rotation_to_param2[rotation] + assert(param2) + local is_chain = pr:next(1, 3) > 1 + draw_trash(pos, width, height, lift, orientation, pr) + draw_stairs(pos, width, height, lift, orientation, pr, is_chain) draw_frame({x = pos.x, y = pos.y + lift, z = pos.z}, width + 2, height + 2, orientation, pr, is_chain, rotation) end @@ -296,6 +374,7 @@ mcl_structures.register_structure({ flags = "all_floors", fill_ratio = scanning_ratio, height = 1, + place_on = {"mcl_core:sand", "mcl_core:dirt_with_grass", "mcl_core:water_source"}, }, on_finished_chunk = function(minp, maxp, seed, vm_context, pos_list) if maxp.y < mcl_mapgen.overworld.min then return end From cfc0fda314ca0809e1d6d50f65ee7c33a03005b0 Mon Sep 17 00:00:00 2001 From: kay27 Date: Thu, 24 Feb 2022 03:59:11 +0400 Subject: [PATCH 65/68] Finish ruined portals --- mods/ITEMS/REDSTONE/mcl_bells/README.md | 4 + mods/ITEMS/REDSTONE/mcl_bells/init.lua | 24 ++ .../REDSTONE/mcl_bells/locale/template.txt | 2 + mods/ITEMS/REDSTONE/mcl_bells/mod.conf | 3 + .../REDSTONE/mcl_bells/sounds/bell_stroke.ogg | Bin 0 -> 61797 bytes .../REDSTONE/mcl_bells/textures/bell.png | Bin 0 -> 368 bytes .../REDSTONE/mesecons_pressureplates/init.lua | 13 +- mods/MAPGEN/mcl_structures/ruined_portal.lua | 277 +++++++++++++++--- 8 files changed, 281 insertions(+), 42 deletions(-) create mode 100644 mods/ITEMS/REDSTONE/mcl_bells/README.md create mode 100644 mods/ITEMS/REDSTONE/mcl_bells/init.lua create mode 100644 mods/ITEMS/REDSTONE/mcl_bells/locale/template.txt create mode 100644 mods/ITEMS/REDSTONE/mcl_bells/mod.conf create mode 100755 mods/ITEMS/REDSTONE/mcl_bells/sounds/bell_stroke.ogg create mode 100644 mods/ITEMS/REDSTONE/mcl_bells/textures/bell.png diff --git a/mods/ITEMS/REDSTONE/mcl_bells/README.md b/mods/ITEMS/REDSTONE/mcl_bells/README.md new file mode 100644 index 000000000..9f0b1d118 --- /dev/null +++ b/mods/ITEMS/REDSTONE/mcl_bells/README.md @@ -0,0 +1,4 @@ + * sounds/bell_stroke.ogg + * created by edsward + * modified by sorcerykid + * obtained from https://freesound.org/people/edsward/sounds/341866/ diff --git a/mods/ITEMS/REDSTONE/mcl_bells/init.lua b/mods/ITEMS/REDSTONE/mcl_bells/init.lua new file mode 100644 index 000000000..9a69e4353 --- /dev/null +++ b/mods/ITEMS/REDSTONE/mcl_bells/init.lua @@ -0,0 +1,24 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + +mcl_bells = {} + +local has_mcl_wip = minetest.get_modpath("mcl_wip") + +minetest.register_node("mcl_bells:bell", { + description = S("Bell"), + inventory_image = "bell.png", + drawtype = "plantlike", + tiles = {"bell.png"}, + stack_max = 64, + selection_box = { + type = "fixed", + fixed = { + -4/16, -6/16, -4/16, + 4/16, 7/16, 4/16, + }, + }, +}) + +if has_mcl_wip then + mcl_wip.register_wip_item("mcl_bells:bell") +end diff --git a/mods/ITEMS/REDSTONE/mcl_bells/locale/template.txt b/mods/ITEMS/REDSTONE/mcl_bells/locale/template.txt new file mode 100644 index 000000000..2f554c2a0 --- /dev/null +++ b/mods/ITEMS/REDSTONE/mcl_bells/locale/template.txt @@ -0,0 +1,2 @@ +# textdomain: mcl_observers +Bell= diff --git a/mods/ITEMS/REDSTONE/mcl_bells/mod.conf b/mods/ITEMS/REDSTONE/mcl_bells/mod.conf new file mode 100644 index 000000000..1685462fc --- /dev/null +++ b/mods/ITEMS/REDSTONE/mcl_bells/mod.conf @@ -0,0 +1,3 @@ +name = mcl_bells +depends = mesecons +optional_depends = mcl_wip diff --git a/mods/ITEMS/REDSTONE/mcl_bells/sounds/bell_stroke.ogg b/mods/ITEMS/REDSTONE/mcl_bells/sounds/bell_stroke.ogg new file mode 100755 index 0000000000000000000000000000000000000000..023d1f94627d2b767bd1437ac3beaa112e4a8cb7 GIT binary patch literal 61797 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�*O?vYn0!;-jAx73sC7rtc2NY5A*Nl| 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

q@an!Ssp+uO@$35$k}ko1Y_TJ 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 literal 0 HcmV?d00001 diff --git a/mods/ITEMS/REDSTONE/mesecons_pressureplates/init.lua b/mods/ITEMS/REDSTONE/mesecons_pressureplates/init.lua index c0894224c..d040c8666 100644 --- a/mods/ITEMS/REDSTONE/mesecons_pressureplates/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_pressureplates/init.lua @@ -201,4 +201,15 @@ mesecon.register_pressure_plate( { player = true, mob = true }, S("A stone pressure plate is a redstone component which supplies its surrounding blocks with redstone power while a player or mob stands on top of it. It is not triggered by anything else.")) - +mesecon.register_pressure_plate( + "mesecons_pressureplates:pressure_plate_gold", + S("Light-Weighted Pressure Plate"), + {"default_gold_block.png"}, + {"default_gold_block.png"}, + "default_gold_block.png", + nil, + {{"mcl_core:gold_ingot", "mcl_core:gold_ingot"}}, + mcl_sounds.node_sound_metal_defaults(), + {pickaxey=1}, + { player = true, mob = true }, + S("A light-weighted pressure plate is a redstone component which supplies its surrounding blocks with redstone power while a player or mob stands on top of it. It is not triggered by anything else.")) diff --git a/mods/MAPGEN/mcl_structures/ruined_portal.lua b/mods/MAPGEN/mcl_structures/ruined_portal.lua index b190921fa..18e8fb9f6 100644 --- a/mods/MAPGEN/mcl_structures/ruined_portal.lua +++ b/mods/MAPGEN/mcl_structures/ruined_portal.lua @@ -4,10 +4,15 @@ local modpath = minetest.get_modpath(modname) local chance_per_chunk = 400 local noise_multiplier = 2.5 local random_offset = 9159 -local scanning_ratio = 0.01 -local struct_threshold = 390 +local scanning_ratio = 0.001 +local struct_threshold = 396 local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level +local minetest_find_nodes_in_area = minetest.find_nodes_in_area +local minetest_swap_node = minetest.swap_node +local math_round = math.round +local math_abs = math.abs + local rotation_to_orientation = { ["0"] = 1, @@ -59,7 +64,7 @@ local function draw_frame(frame_pos, frame_width, frame_height, orientation, pr, local function set_ruined_node(pos, node) if pr:next(1, 5) == 4 then return end - minetest.set_node(pos, node) + minetest_swap_node(pos, node) end local function get_random_stone_material() @@ -88,7 +93,7 @@ local function draw_frame(frame_pos, frame_width, frame_height, orientation, pr, end local function set_frame_stone_material(pos) - minetest.swap_node(pos, get_random_stone_material()) + minetest_swap_node(pos, get_random_stone_material()) end local function set_ruined_frame_stone_material(pos) @@ -108,23 +113,23 @@ local function draw_frame(frame_pos, frame_width, frame_height, orientation, pr, -- it's about the portal frame itself, what it will consist of local frame_nodes = 2 * (frame_height + frame_width) - 4 - local obsidian_nodes = pr:next(math.round(frame_nodes * 0.5), math.round(frame_nodes * 0.73)) - local crying_obsidian_nodes = pr:next(math.round(obsidian_nodes * 0.09), math.round(obsidian_nodes * 0.5)) + local obsidian_nodes = pr:next(math_round(frame_nodes * 0.5), math_round(frame_nodes * 0.73)) + local crying_obsidian_nodes = pr:next(math_round(obsidian_nodes * 0.09), math_round(obsidian_nodes * 0.5)) local air_nodes = frame_nodes - obsidian_nodes local function set_frame_node(pos) -- local node_choice = pr:next(1, air_nodes + obsidian_nodes) - local node_choice = math.round(mcl_structures_get_perlin_noise_level(pos) * (air_nodes + obsidian_nodes)) + local node_choice = math_round(mcl_structures_get_perlin_noise_level(pos) * (air_nodes + obsidian_nodes)) if node_choice > obsidian_nodes and air_nodes > 0 then air_nodes = air_nodes - 1 return end obsidian_nodes = obsidian_nodes - 1 if node_choice >= crying_obsidian_nodes then - minetest.swap_node(pos, {name = "mcl_core:obsidian"}) + minetest_swap_node(pos, {name = "mcl_core:obsidian"}) return 1 end - minetest.swap_node(pos, {name = "mcl_core:crying_obsidian"}) + minetest_swap_node(pos, {name = "mcl_core:crying_obsidian"}) crying_obsidian_nodes = crying_obsidian_nodes - 1 return 1 end @@ -136,7 +141,7 @@ local function draw_frame(frame_pos, frame_width, frame_height, orientation, pr, local is_top_hole = is_top and frame_width > 5 and ((pos2.x == x1 + slide_x * 2 and pos2.z == z1 + slide_z * 2) or (pos2.x == last_x - slide_x * 2 and pos2.z == last_z - slide_z * 2)) if is_top_hole then if pr:next(1, 7) > 1 then - minetest.swap_node(pos2, {name = "xpanes:bar_flat", param2 = orientation}) + minetest_swap_node(pos2, {name = "xpanes:bar_flat", param2 = orientation}) end else set_frame_stone_material(pos2) @@ -147,18 +152,18 @@ local function draw_frame(frame_pos, frame_width, frame_height, orientation, pr, local pos = def.pos_outer1 local is_decor_here = not is_top and pos.y % 3 == 2 if is_decor_here then - minetest.swap_node(pos, {name = "mcl_core:stonebrickcarved"}) + minetest_swap_node(pos, {name = "mcl_core:stonebrickcarved"}) elseif is_chain then if not is_top and not is_obsidian then - minetest.swap_node(pos, {name = "xpanes:bar"}) + minetest_swap_node(pos, {name = "xpanes:bar"}) else - minetest.swap_node(pos, {name = "xpanes:bar_flat", param2 = orientation}) + minetest_swap_node(pos, {name = "xpanes:bar_flat", param2 = orientation}) end else if pr:next(1, 5) == 3 then - minetest.swap_node(pos, {name = "mcl_core:stonebrickcracked"}) + minetest_swap_node(pos, {name = "mcl_core:stonebrickcracked"}) else - minetest.swap_node(pos, {name = "mcl_core:stonebrick"}) + minetest_swap_node(pos, {name = "mcl_core:stonebrick"}) end end end @@ -207,7 +212,7 @@ local function draw_frame(frame_pos, frame_width, frame_height, orientation, pr, end for y = y1, last_y do - local begin_or_end = y == y1 or y == lasy_y + local begin_or_end = y == y1 or y == last_y local is_obsidian_left = begin_or_end and is_obsidian_top_left or set_frame_node({x = x1 , y = y, z = z1 }) local is_obsidian_right = begin_or_end and is_obsidian_top_right or set_frame_node({x = last_x, y = y, z = last_z}) set_outer_frame_node({ @@ -239,7 +244,7 @@ local function draw_frame(frame_pos, frame_width, frame_height, orientation, pr, for x = x1 + slide_x, last_x - slide_x do for z = z1 + slide_z, last_z - slide_z do set_frame_node({x = x, y = y1, z = z}) - local is_obsitian_top = set_frame_node({x = x, y = last_y, z = z}) + local is_obsidian_top = set_frame_node({x = x, y = last_y, z = z}) set_outer_frame_node({ pos_outer1 = {x = x, y = last_y + 1, z = z}, pos_outer2 = {x = x, y = last_y + 2, z = z}, @@ -288,11 +293,11 @@ local function draw_trash(pos, width, height, lift, orientation, pr) local opacity_layers = math.floor((y2 - y1) / 2) local opacity_layer = -opacity_layers for y = y1, y2 do - local inverted_opacity_0_5 = math.round(math.abs(opacity_layer) / opacity_layers * 5) + local inverted_opacity_0_5 = math_round(math_abs(opacity_layer) / opacity_layers * 5) for x = x1 + pr:next(0, 2), x2 - pr:next(0, 2) do for z = z1 + pr:next(0, 2), z2 - pr:next(0, 2) do if inverted_opacity_0_5 == 0 or (x % inverted_opacity_0_5 ~= pr:next(0, 1) and z % inverted_opacity_0_5 ~= pr:next(0, 1)) then - minetest.swap_node({x = x, y = y, z = z}, {name = node_garbage[pr:next(1, #node_garbage)]}) + minetest_swap_node({x = x, y = y, z = z}, {name = node_garbage[pr:next(1, #node_garbage)]}) end end end @@ -309,36 +314,186 @@ local stair_replacement_list = { } local stair_offset_from_bottom = 3 -local function draw_stairs(pos, width, height, lift, orientation, pr, is_chain) +local stair_names = { + "mcl_stairs:stair_stonebrickcracked", + "mcl_stairs:stair_stonebrickmossy", + "mcl_stairs:stair_stone_rough", + "mcl_stairs:stair_stone_rough", + "mcl_stairs:stair_stone_rough", + "mcl_stairs:stair_stone_rough", + "mcl_stairs:stair_stone_rough", + "mcl_stairs:stair_stone_rough", + "mcl_stairs:stair_stone_rough", + "mcl_stairs:stair_stonebrick", + "mcl_stairs:stair_stonebrick", + "mcl_stairs:stair_stonebrick", +} +local stair_outer_names = { + "mcl_stairs:stair_stonebrickcracked_outer", + "mcl_stairs:stair_stonebrickmossy_outer", + "mcl_stairs:stair_stone_rough_outer", + "mcl_stairs:stair_stonebrick_outer", +} + +local stair_content = { + {name = "mcl_core:lava_source"}, + {name = "mcl_core:stone"}, + {name = "mcl_core:stone"}, + {name = "mcl_core:stone"}, + {name = "mcl_core:stone"}, + {name = "mcl_core:stone"}, + {name = "mcl_core:stonebrick"}, + {name = "mcl_nether:magma"}, + {name = "mcl_nether:netherrack"}, + {name = "mcl_nether:netherrack"}, +} + +local slabs = { + {name = "mcl_stairs:slab_stone"}, + {name = "mcl_stairs:slab_stone"}, + {name = "mcl_stairs:slab_stone"}, + {name = "mcl_stairs:slab_stone"}, + {name = "mcl_stairs:slab_stone"}, + {name = "mcl_stairs:slab_stonebrick"}, + {name = "mcl_stairs:slab_stonebrick"}, + {name = "mcl_stairs:slab_stonebrickcracked"}, + {name = "mcl_stairs:slab_stonebrickmossy"}, +} + +local stones = { + {name = "mcl_core:stone"}, + {name = "mcl_core:stone"}, + {name = "mcl_core:stone"}, + {name = "mcl_core:cobble"}, + {name = "mcl_core:mossycobble"}, +} + +local stair_selector = { + [-1] = { + [-1] = { + names = stair_outer_names, + param2 = 1, + }, + [0] = { + names = stair_names, + param2 = 1, + }, + [1] = { + names = stair_outer_names, + param2 = 2, + }, + }, + [0] = { + [-1] = { + names = stair_names, + param2 = 0, + }, + [0] = { + names = stair_content, + }, + [1] = { + names = stair_names, + param2 = 2, + }, + }, + [1] = { + [-1] = { + names = stair_outer_names, + param2 = 0, + }, + [0] = { + names = stair_names, + param2 = 3, + }, + [1] = { + names = stair_outer_names, + param2 = 3, + }, + }, +} + +local function draw_stairs(pos, width, height, lift, orientation, pr, is_chain, param2) + + local function set_ruined_node(pos, node) + if pr:next(1, 7) < 3 then return end + minetest_swap_node(pos, node) + return true + end + + local param2 = param2 + local mirror = param2 == 1 or param2 == 2 + if mirror then + param2 = (param2 + 2) % 4 + end + + local chain_offset = is_chain and 1 or 0 + local lift = lift + stair_offset_from_bottom local slide_x = (1 - orientation) local slide_z = orientation - local width = width + (is_chain and 2 or 0) - local x1 = pos.x - lift - (is_chain and 1 or 0) - 1 - local x2 = pos.x + lift + width * slide_x + 1 - local z1 = pos.z - lift - (is_chain and 1 or 0) - 1 - local z2 = pos.z + lift + width * slide_z + 1 + local width = width + 2 + local x1 = pos.x - (chain_offset + 1 ) * slide_x - 1 + local x2 = pos.x + (chain_offset + width) * slide_x + 1 + local z1 = pos.z - (chain_offset + 1 ) * slide_z - 1 + local z2 = pos.z + (chain_offset + width) * slide_z + 1 local y1 = pos.y - stair_offset_from_bottom local y2 = pos.y + lift - stair_offset_from_bottom - local current_radius = lift - for y = y1, y2 do + local stair_layer = true + local y = y2 + local place_slabs = true + local x_key, y_key + local need_to_place_chest = true + local chest_pos + while y >= y1 do for x = x1, x2 do + x_key = (x == x1) and -1 or (x == x2) and 1 or 0 for z = z1, z2 do ---local stair1 = "mcl_stairs:stair_stonebrickcracked" ---local stair2 = "mcl_stairs:stair_stonebrickmossy" ---local stair3 = "mcl_stairs:stair_stone_rough" ---local stair4 = "mcl_stairs:stair_stonebrick" local pos = {x = x, y = y, z = z} - if #minetest.find_nodes_in_area(pos, pos, stair_replacement_list, false) > 0 then - minetest.swap_node(pos, {name = "mcl_stairs:stair_stone_rough"}) + if #minetest_find_nodes_in_area(pos, pos, stair_replacement_list, false) > 0 then + z_key = (z == z1) and -1 or (z == z2) and 1 or 0 + local stair_coverage = (x_key ~= 0) or (z_key ~= 0) + if stair_coverage then + if stair_layer then + local stair = stair_selector[x_key][z_key] + local names = stair.names + set_ruined_node(pos, {name = names[pr:next(1, #names)], param2 = stair.param2}) + elseif place_slabs then + set_ruined_node(pos, slabs[pr:next(1, #slabs)]) + else + local placed = set_ruined_node(pos, stones[pr:next(1, #stones)]) + if need_to_place_chest and placed then + chest_pos = {x = pos.x, y = pos.y + 1, z = pos.z} + minetest_swap_node(chest_pos, {name = "mcl_chests:chest_small"}) + need_to_place_chest = false + end + end + elseif not stair_layer then + set_ruined_node(pos, stair_content[pr:next(1, #stair_content)]) + end end end end - x1 = x1 + 1 - x2 = x2 - 1 - z1 = z1 + 1 - z2 = z2 - 1 + x1 = x1 - 1 + x2 = x2 + 1 + z1 = z1 - 1 + z2 = z2 + 1 + if (stair_layer or place_slabs) then + y = y - 1 + end + stair_layer = false + place_slabs = not place_slabs end + return chest_pos +end + +local function enchant(stack, pr) + -- 75%-100% damage + mcl_enchanting.enchant_randomly(stack, 30, true, false, false, pr) +end + +local function enchant_armor(stack, pr) + -- itemstack, enchantment_level, treasure, no_reduced_bonus_chance, ignore_already_enchanted, pr) + mcl_enchanting.enchant_randomly(stack, 30, false, false, false, pr) end local function place(pos, rotation, pr) @@ -352,18 +507,58 @@ local function place(pos, rotation, pr) assert(param2) local is_chain = pr:next(1, 3) > 1 draw_trash(pos, width, height, lift, orientation, pr) - draw_stairs(pos, width, height, lift, orientation, pr, is_chain) + local chest_pos = draw_stairs(pos, width, height, lift, orientation, pr, is_chain, param2) draw_frame({x = pos.x, y = pos.y + lift, z = pos.z}, width + 2, height + 2, orientation, pr, is_chain, rotation) + if not chest_pos then return end + + local lootitems = mcl_loot.get_loot( + { + stacks_min = 4, + stacks_max = 8, + items = { + {itemstring = "mcl_core:iron_nugget", weight = 40, amount_min = 9, amount_max = 18}, + {itemstring = "mcl_core:flint", weight = 40, amount_min = 9, amount_max = 18}, + {itemstring = "mcl_core:obsidian", weight = 40, amount_min = 1, amount_max = 2}, + {itemstring = "mcl_fire:fire_charge", weight = 40, amount_min = 1, amount_max = 1}, + {itemstring = "mcl_fire:flint_and_steel", weight = 40, amount_min = 1, amount_max = 1}, + {itemstring = "mcl_core:gold_nugget", weight = 15, amount_min = 4, amount_max = 24}, + {itemstring = "mcl_core:apple_gold", weight = 15}, + {itemstring = "mcl_tools:axe_gold", weight = 15, func = enchant}, + {itemstring = "mcl_farming:hoe_gold", weight = 15, func = enchant}, + {itemstring = "mcl_tools:pick_gold", weight = 15, func = enchant}, + {itemstring = "mcl_tools:shovel_gold", weight = 15, func = enchant}, + {itemstring = "mcl_tools:sword_gold", weight = 15, func = enchant}, + {itemstring = "mcl_armor:helmet_gold", weight = 15, func = enchant_armor}, + {itemstring = "mcl_armor:chestplate_gold", weight = 15, func = enchant_armor}, + {itemstring = "mcl_armor:leggings_gold", weight = 15, func = enchant_armor}, + {itemstring = "mcl_armor:boots_gold", weight = 15, func = enchant_armor}, + {itemstring = "mcl_potions:speckled_melon", weight = 5, amount_min = 4, amount_max = 12}, + {itemstring = "mcl_farming:carrot_item_gold", weight = 5, amount_min = 4, amount_max = 12}, + {itemstring = "mcl_core:gold_ingot", weight = 5, amount_min = 2, amount_max = 8}, + {itemstring = "mcl_clock:clock", weight = 5}, + {itemstring = "mesecons_pressureplates:pressure_plate_gold_off", weight = 5}, + {itemstring = "mobs_mc:gold_horse_armor", weight = 5}, + {itemstring = "mcl_core:goldblock", weight = 1, amount_min = 1, amount_max = 2}, + {itemstring = "mcl_bells:bell", weight = 1}, + {itemstring = "mcl_core:apple_gold_enchanted", weight = 1}, + } + }, + pr + ) + mcl_structures.init_node_construct(chest_pos) + local meta = minetest.get_meta(chest_pos) + local inv = meta:get_inventory() + mcl_loot.fill_inventory(inv, "main", lootitems, pr) end local function get_place_rank(pos) local x, y, z = pos.x, pos.y, pos.z local p1 = {x = x , y = y, z = z } local p2 = {x = x + 7, y = y, z = z + 7} - local air_pos_list_surface = #minetest.find_nodes_in_area(p1, p2, "air", false) + local air_pos_list_surface = #minetest_find_nodes_in_area(p1, p2, "air", false) p1.y = p1.y - 1 p2.y = p2.y - 1 - local opaque_pos_list_surface = #minetest.find_nodes_in_area(p1, p2, "group:opaque", false) + local opaque_pos_list_surface = #minetest_find_nodes_in_area(p1, p2, "group:opaque", false) return air_pos_list_surface + 3 * opaque_pos_list_surface end @@ -374,7 +569,7 @@ mcl_structures.register_structure({ flags = "all_floors", fill_ratio = scanning_ratio, height = 1, - place_on = {"mcl_core:sand", "mcl_core:dirt_with_grass", "mcl_core:water_source"}, + place_on = {"mcl_core:sand", "mcl_core:dirt_with_grass", "mcl_core:water_source", "mcl_core:dirt_with_grass_snow"}, }, on_finished_chunk = function(minp, maxp, seed, vm_context, pos_list) if maxp.y < mcl_mapgen.overworld.min then return end From bbecd6239b7c38bf6b4b0e38ccbde17fdb25ddf9 Mon Sep 17 00:00:00 2001 From: kay27 Date: Thu, 24 Feb 2022 05:45:46 +0400 Subject: [PATCH 66/68] Fix bottom part of ruined portals --- mods/MAPGEN/mcl_structures/ruined_portal.lua | 73 +++++++++++++++----- 1 file changed, 55 insertions(+), 18 deletions(-) diff --git a/mods/MAPGEN/mcl_structures/ruined_portal.lua b/mods/MAPGEN/mcl_structures/ruined_portal.lua index 18e8fb9f6..196a20d95 100644 --- a/mods/MAPGEN/mcl_structures/ruined_portal.lua +++ b/mods/MAPGEN/mcl_structures/ruined_portal.lua @@ -5,7 +5,7 @@ local chance_per_chunk = 400 local noise_multiplier = 2.5 local random_offset = 9159 local scanning_ratio = 0.001 -local struct_threshold = 396 +local struct_threshold = 1 local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level local minetest_find_nodes_in_area = minetest.find_nodes_in_area @@ -313,7 +313,6 @@ local stair_replacement_list = { "group:deco_block", } -local stair_offset_from_bottom = 3 local stair_names = { "mcl_stairs:stair_stonebrickcracked", "mcl_stairs:stair_stonebrickmossy", @@ -348,6 +347,15 @@ local stair_content = { {name = "mcl_nether:netherrack"}, } +local stair_content_bottom = { + {name = "mcl_nether:magma"}, + {name = "mcl_nether:magma"}, + {name = "mcl_nether:netherrack"}, + {name = "mcl_nether:netherrack"}, + {name = "mcl_nether:netherrack"}, + {name = "mcl_nether:netherrack"}, +} + local slabs = { {name = "mcl_stairs:slab_stone"}, {name = "mcl_stairs:slab_stone"}, @@ -412,8 +420,13 @@ local stair_selector = { }, } +local stair_offset_from_bottom = 2 + local function draw_stairs(pos, width, height, lift, orientation, pr, is_chain, param2) + local current_stair_content = stair_content + local current_stones = stones + local function set_ruined_node(pos, node) if pr:next(1, 7) < 3 then return end minetest_swap_node(pos, node) @@ -441,10 +454,12 @@ local function draw_stairs(pos, width, height, lift, orientation, pr, is_chain, local stair_layer = true local y = y2 local place_slabs = true - local x_key, y_key + local x_key, z_key local need_to_place_chest = true local chest_pos - while y >= y1 do + local bad_nodes_ratio = 0 + while (y >= y1) or (bad_nodes_ratio > 0.07) do + local good_nodes_counter = 0 for x = x1, x2 do x_key = (x == x1) and -1 or (x == x2) and 1 or 0 for z = z1, z2 do @@ -460,7 +475,7 @@ local function draw_stairs(pos, width, height, lift, orientation, pr, is_chain, elseif place_slabs then set_ruined_node(pos, slabs[pr:next(1, #slabs)]) else - local placed = set_ruined_node(pos, stones[pr:next(1, #stones)]) + local placed = set_ruined_node(pos, current_stones[pr:next(1, #current_stones)]) if need_to_place_chest and placed then chest_pos = {x = pos.x, y = pos.y + 1, z = pos.z} minetest_swap_node(chest_pos, {name = "mcl_chests:chest_small"}) @@ -468,20 +483,42 @@ local function draw_stairs(pos, width, height, lift, orientation, pr, is_chain, end end elseif not stair_layer then - set_ruined_node(pos, stair_content[pr:next(1, #stair_content)]) + set_ruined_node(pos, current_stair_content[pr:next(1, #current_stair_content)]) end + else + good_nodes_counter = good_nodes_counter + 1 end end end - x1 = x1 - 1 - x2 = x2 + 1 - z1 = z1 - 1 - z2 = z2 + 1 - if (stair_layer or place_slabs) then + bad_nodes_ratio = 1 - good_nodes_counter / ((x2 - x1 + 1) * (z2 - z1 + 1)) + if y >= y1 then + x1 = x1 - 1 + x2 = x2 + 1 + z1 = z1 - 1 + z2 = z2 + 1 + if (stair_layer or place_slabs) then + y = y - 1 + if y <= y1 then + current_stair_content = stair_content_bottom + current_stones = stair_content_bottom + end + end + place_slabs = not place_slabs + stair_layer = false + else + place_slabs = false y = y - 1 + local dx1 = pr:next(0, 10) + if dx1 < 3 then x1 = x1 + dx1 end + local dx2 = pr:next(0, 10) + if dx2 < 3 then x2 = x2 - dx1 end + if x1 >= x2 then return chest_pos end + local dz1 = pr:next(0, 10) + if dz1 < 3 then z1 = z1 + dz1 end + local dz2 = pr:next(0, 10) + if dz2 < 3 then z2 = z2 - dz1 end + if z1 >= z2 then return chest_pos end end - stair_layer = false - place_slabs = not place_slabs end return chest_pos end @@ -536,11 +573,11 @@ local function place(pos, rotation, pr) {itemstring = "mcl_farming:carrot_item_gold", weight = 5, amount_min = 4, amount_max = 12}, {itemstring = "mcl_core:gold_ingot", weight = 5, amount_min = 2, amount_max = 8}, {itemstring = "mcl_clock:clock", weight = 5}, - {itemstring = "mesecons_pressureplates:pressure_plate_gold_off", weight = 5}, - {itemstring = "mobs_mc:gold_horse_armor", weight = 5}, - {itemstring = "mcl_core:goldblock", weight = 1, amount_min = 1, amount_max = 2}, - {itemstring = "mcl_bells:bell", weight = 1}, - {itemstring = "mcl_core:apple_gold_enchanted", weight = 1}, + {itemstring = "mesecons_pressureplates:pressure_plate_gold_off", weight = 5}, + {itemstring = "mobs_mc:gold_horse_armor", weight = 5}, + {itemstring = "mcl_core:goldblock", weight = 1, amount_min = 1, amount_max = 2}, + {itemstring = "mcl_bells:bell", weight = 1}, + {itemstring = "mcl_core:apple_gold_enchanted", weight = 1}, } }, pr From 989d46cc5bec3452b287ee3f1d501ccf68d974fe Mon Sep 17 00:00:00 2001 From: kay27 Date: Thu, 24 Feb 2022 05:46:22 +0400 Subject: [PATCH 67/68] Fix ruined portal spawn probability --- mods/MAPGEN/mcl_structures/ruined_portal.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/MAPGEN/mcl_structures/ruined_portal.lua b/mods/MAPGEN/mcl_structures/ruined_portal.lua index 196a20d95..40484f9c9 100644 --- a/mods/MAPGEN/mcl_structures/ruined_portal.lua +++ b/mods/MAPGEN/mcl_structures/ruined_portal.lua @@ -5,7 +5,7 @@ local chance_per_chunk = 400 local noise_multiplier = 2.5 local random_offset = 9159 local scanning_ratio = 0.001 -local struct_threshold = 1 +local struct_threshold = 396 local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level local minetest_find_nodes_in_area = minetest.find_nodes_in_area From 4ab521ddc8de55c85b8f28304f48e9065bde6212 Mon Sep 17 00:00:00 2001 From: kay27 Date: Thu, 24 Feb 2022 06:00:47 +0400 Subject: [PATCH 68/68] #198 Fix a crash, step 28 --- mods/ITEMS/mcl_enchanting/engine.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_enchanting/engine.lua b/mods/ITEMS/mcl_enchanting/engine.lua index 1b672aea4..d6407d0bc 100644 --- a/mods/ITEMS/mcl_enchanting/engine.lua +++ b/mods/ITEMS/mcl_enchanting/engine.lua @@ -560,7 +560,7 @@ function mcl_enchanting.handle_formspec_fields(player, formname, fields) return end local player_level = mcl_experience.get_level(player) - if player_level < slot.level_requirement then + if not player_level or (player_level < slot.level_requirement) then return end mcl_experience.set_level(player, player_level - button_pressed)