diff --git a/minetest.conf b/minetest.conf index 97d1f5cd6..423ac3a34 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 = 4 + # MCL2-specific stuff keepInventory = false diff --git a/mods/CORE/mcl_mapgen/init.lua b/mods/CORE/mcl_mapgen/init.lua index d751e9eb4..f24d76880 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,33 @@ 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) + 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) + 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 +mcl_mapgen.get_block_seed2 = get_block_seed2 +mcl_mapgen.get_block_seed3 = get_block_seed3 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/CORE/mcl_time/README.md b/mods/CORE/mcl_time/README.md index c3a1bb3af..ff4263f3f 100644 --- a/mods/CORE/mcl_time/README.md +++ b/mods/CORE/mcl_time/README.md @@ -1,9 +1,10 @@ -# mcl_time +# mcl_time v2.2 ## by kay27 for MineClone 5 --------------------------- 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. @@ -15,13 +16,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 +32,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 31bcbbe29..5a3a2487a 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() @@ -51,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 @@ -66,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 @@ -86,44 +96,56 @@ 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 + 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) - touch(pos) - return number_of_times, seconds_irl_public + 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) + 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) - if last_time == 0 then return end + 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 return delta_time diff --git a/mods/CORE/mcl_util/init.lua b/mods/CORE/mcl_util/init.lua index 50e3d61fc..90e44cedc 100644 --- a/mods/CORE/mcl_util/init.lua +++ b/mods/CORE/mcl_util/init.lua @@ -498,3 +498,24 @@ 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 + 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/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 24ec502e1..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, "wb")) - 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/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/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index 91e152ca1..b1202f4ad 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) @@ -43,6 +42,8 @@ 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 +local is_player = mcl_util.is_player + local function get_gravity() return tonumber(minetest.settings:get("movement_gravity")) or 9.81 end @@ -133,7 +134,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 @@ -167,7 +168,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 @@ -230,7 +231,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 @@ -340,7 +341,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/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/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 diff --git a/mods/ENTITIES/mobs_mc/blaze.lua b/mods/ENTITIES/mobs_mc/blaze.lua index 8f4a96db4..e02c57a8f 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, diff --git a/mods/HELP/doc/doc/init.lua b/mods/HELP/doc/doc/init.lua index 304900753..fc684246b 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")) diff --git a/mods/HELP/mcl_craftguide/init.lua b/mods/HELP/mcl_craftguide/init.lua index 3bc7b705a..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 @@ -1093,8 +1097,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 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] @@ -1126,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/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_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) diff --git a/mods/HUD/mcl_experience/init.lua b/mods/HUD/mcl_experience/init.lua index aea805fa2..65f456f81 100644 --- a/mods/HUD/mcl_experience/init.lua +++ b/mods/HUD/mcl_experience/init.lua @@ -156,13 +156,38 @@ 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) local cache = caches[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" @@ -186,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) diff --git a/mods/HUD/mcl_inventory/init.lua b/mods/HUD/mcl_inventory/init.lua index f59476965..0a8b9a7bc 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) @@ -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 @@ -130,6 +131,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") @@ -142,6 +144,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 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) 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") 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 000000000..023d1f946 Binary files /dev/null and b/mods/ITEMS/REDSTONE/mcl_bells/sounds/bell_stroke.ogg differ diff --git a/mods/ITEMS/REDSTONE/mcl_bells/textures/bell.png b/mods/ITEMS/REDSTONE/mcl_bells/textures/bell.png new file mode 100644 index 000000000..34140288c Binary files /dev/null and b/mods/ITEMS/REDSTONE/mcl_bells/textures/bell.png differ 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 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) 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 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/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 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 000000000..6229fe08a Binary files /dev/null and b/mods/ITEMS/mcl_core/textures/mcl_core_crying_obsidian.png differ diff --git a/mods/ITEMS/mcl_enchanting/engine.lua b/mods/ITEMS/mcl_enchanting/engine.lua index 97a176b97..d6407d0bc 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) @@ -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) 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 diff --git a/mods/ITEMS/mcl_fireworks/register.lua b/mods/ITEMS/mcl_fireworks/register.lua index 23066b663..f113a6678 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/ITEMS/mcl_maps/init.lua b/mods/ITEMS/mcl_maps/init.lua index d2ff951ad..413e7382a 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-%.0f", minetest.hash_node_position(minp), mcl_time.get_seconds_irl()) 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,93 +48,114 @@ 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 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 .. ".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) + 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 @@ -229,14 +236,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 +269,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 +306,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 +326,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/mod.conf b/mods/ITEMS/mcl_maps/mod.conf index e1f068963..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, tga_encoder, tt, mcl_colors, mcl_skins, mcl_util +depends = mcl_core, mcl_flowers, tt, mcl_colors, mcl_skins, mcl_util, mcl_time diff --git a/mods/ITEMS/mcl_nether/nether_wart.lua b/mods/ITEMS/mcl_nether/nether_wart.lua index 0fe1a990a..90af6bdd6 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(), + on_construct = mcl_time.touch, }) minetest.register_node("mcl_nether:nether_wart_1", { @@ -48,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", { @@ -70,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", { @@ -154,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 @@ -168,9 +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 @@ -186,8 +187,8 @@ 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 - grow(pos, node) + for i = 1, mcl_time.get_number_of_times_at_pos(pos, interval, chance) do + grow(pos) end end }) @@ -204,7 +205,7 @@ 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 end }) 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: diff --git a/mods/ITEMS/mcl_shields/init.lua b/mods/ITEMS/mcl_shields/init.lua index 913a7005d..65ffc6b4b 100644 --- a/mods/ITEMS/mcl_shields/init.lua +++ b/mods/ITEMS/mcl_shields/init.lua @@ -22,6 +22,8 @@ interact_priv.give_to_admin = false local overlay = mcl_enchanting.overlay local hud = "mcl_shield_hud.png" +local is_player = mcl_util.is_player + 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."), @@ -107,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() @@ -121,7 +124,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(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 @@ -287,8 +290,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 is_player(player) then handle_blocking(player) local blocking, shieldstack = mcl_shields.is_blocking(player) @@ -360,7 +362,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) 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/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_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 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/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/ruined_portal.lua b/mods/MAPGEN/mcl_structures/ruined_portal.lua new file mode 100644 index 000000000..40484f9c9 --- /dev/null +++ b/mods/MAPGEN/mcl_structures/ruined_portal.lua @@ -0,0 +1,632 @@ +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) + +local chance_per_chunk = 400 +local noise_multiplier = 2.5 +local random_offset = 9159 +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, + ["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 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"} +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_swap_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 == 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({ + 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_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}, + 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 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_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 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"}, + {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 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) + 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 + 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 stair_layer = true + local y = y2 + local place_slabs = true + local x_key, z_key + local need_to_place_chest = true + local chest_pos + 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 + local pos = {x = x, y = y, z = z} + 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, 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"}) + need_to_place_chest = false + end + end + elseif not stair_layer then + 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 + 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 + 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) + 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] + 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) + 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) + 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, + 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 + 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 fd6b21b26..32a399ae3 100644 --- a/mods/MAPGEN/mcl_structures/structures.lua +++ b/mods/MAPGEN/mcl_structures/structures.lua @@ -11,7 +11,8 @@ 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 .. "/ruined_portal.lua") dofile(modpath .. "/stronghold.lua") dofile(modpath .. "/witch_hut.lua") end 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/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/buildings.lua b/mods/MAPGEN/mcl_villages/buildings.lua deleted file mode 100644 index 0860ce9a5..000000000 --- a/mods/MAPGEN/mcl_villages/buildings.lua +++ /dev/null @@ -1,280 +0,0 @@ ---[[ -------------------------------------------------------------------------------- --- 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 = {} - - -- 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 --------------------------------------------------------------------------------- -function settlements.create_site_plan(maxp, minp, 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) - } - -- find center_surface of chunk - local center_surface , surface_material = settlements.find_surface(center, true) - local chunks = {} - chunks[mcl_mapgen.get_chunk_number(center)] = true - - -- 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+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, true) - end - 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 47ca91f2e..e837ab027 100644 --- a/mods/MAPGEN/mcl_villages/init.lua +++ b/mods/MAPGEN/mcl_villages/init.lua @@ -1,26 +1,379 @@ -settlements = {} -settlements.modpath = minetest.get_modpath(minetest.get_current_modname()) +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 noise_multiplier = 1 +local random_offset = 1 +local random_multiply = 19 +local struct_threshold = chance_per_chunk +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) +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", 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 }, +} +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" }, + ["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 {} +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 minetest_get_perlin = minetest.get_perlin +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 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 = {} +for k, _ in pairs(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") ---dofile(settlements.modpath.."/convert_lua_mts.lua") --- --- load settlements on server --- -settlements_in_world = settlements.load() -settlements.grundstellungen() +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, minetest_get_node(surface_pos).name + end + end +end +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 distance2 < 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_buildings[schematic_index] = count_buildings[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(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 + 4, maxp.y), + z = pos.z + fdepth - 1 + } + 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 + 1, 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) + 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(pos, {name = "mcl_core:sandstonesmooth2"}) + else + minetest.swap_node(pos, {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", "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] + 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 +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 replace_wall = built_house.building.rplc + 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. + 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 -- +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 = ("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, @@ -30,93 +383,142 @@ 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 }) - ---[[ 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 -- -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) - - -- fill settlement_info with buildings and their data - local settlement_info = settlements.create_site_plan(maxp, minp, pr) - if not settlement_info then return end - - -- evaluate settlement_info and prepair terrain - settlements.terraform(settlement_info, pr) - - -- evaluate settlement_info and build paths between buildings - settlements.paths(settlement_info) - - -- evaluate settlement_info and place schematics - settlements.place_schematics(settlement_info, 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 + 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) + villages[#villages + 1] = minp + storage:set_string("villages", minetest.serialize(villages)) end -- Disable natural generation in singlenode. -local mg_name = minetest.get_mapgen_setting("mg_name") 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 - -- 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 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 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 random_number = pr:next(1, chance_per_chunk) + 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 + local surface_point = find_surface( + vector.add( + vector.new( + pr:next(scan_offset, scan_last_node), + 0, + 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) end - height_difference = max - min + 1 - -------------------------------------------------------------------------- - + local height_difference = max - min if height_difference > max_height_difference then return end - - build_a_settlement(minp, maxp, blockseed) + build_a_village(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)) + +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 }) - mcl_wip.register_experimental_item("mcl_villages:tool") +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 new file mode 100644 index 000000000..325d3b191 --- /dev/null +++ b/mods/MAPGEN/mcl_villages/locale/mcl_villages.ru.tr @@ -0,0 +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 new file mode 100644 index 000000000..7d9fcb43b --- /dev/null +++ b/mods/MAPGEN/mcl_villages/locale/template.txt @@ -0,0 +1,3 @@ +# textdomain: mcl_villages +Chiseled Stone Village Bricks= +Map chunk @1 to @2 is not suitable for placing villages.= diff --git a/mods/MAPGEN/mcl_villages/mod.conf b/mods/MAPGEN/mcl_villages/mod.conf index d8e2aa7d4..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 -description = This mod adds settlements on world generation. -depends = mcl_util, mcl_mapgen_core, mcl_structures, mcl_core, mcl_loot +author = Rochambeau, MysticTempest, kay27 +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 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/schematics/blacksmith.mts b/mods/MAPGEN/mcl_villages/schematics/blacksmith.mts index d7fb66593..09665654a 100644 Binary files a/mods/MAPGEN/mcl_villages/schematics/blacksmith.mts and b/mods/MAPGEN/mcl_villages/schematics/blacksmith.mts differ diff --git a/mods/MAPGEN/mcl_villages/schematics/butcher.mts b/mods/MAPGEN/mcl_villages/schematics/butcher.mts index 251033b1e..03353de10 100644 Binary files a/mods/MAPGEN/mcl_villages/schematics/butcher.mts and b/mods/MAPGEN/mcl_villages/schematics/butcher.mts differ diff --git a/mods/MAPGEN/mcl_villages/schematics/church.mts b/mods/MAPGEN/mcl_villages/schematics/church.mts index dbf022cb4..a4fab8952 100644 Binary files a/mods/MAPGEN/mcl_villages/schematics/church.mts and b/mods/MAPGEN/mcl_villages/schematics/church.mts differ diff --git a/mods/MAPGEN/mcl_villages/schematics/farm.mts b/mods/MAPGEN/mcl_villages/schematics/farm.mts index 9094c8681..e47f6e22f 100644 Binary files a/mods/MAPGEN/mcl_villages/schematics/farm.mts and b/mods/MAPGEN/mcl_villages/schematics/farm.mts differ diff --git a/mods/MAPGEN/mcl_villages/schematics/lamp.mts b/mods/MAPGEN/mcl_villages/schematics/lamp.mts index c8d907eba..4d2d1a350 100644 Binary files a/mods/MAPGEN/mcl_villages/schematics/lamp.mts and b/mods/MAPGEN/mcl_villages/schematics/lamp.mts differ diff --git a/mods/MAPGEN/mcl_villages/schematics/large_house.mts b/mods/MAPGEN/mcl_villages/schematics/large_house.mts index 36be603f4..1a55c32d9 100644 Binary files a/mods/MAPGEN/mcl_villages/schematics/large_house.mts and b/mods/MAPGEN/mcl_villages/schematics/large_house.mts differ diff --git a/mods/MAPGEN/mcl_villages/schematics/library.mts b/mods/MAPGEN/mcl_villages/schematics/library.mts index b47e0b413..2986a7162 100644 Binary files a/mods/MAPGEN/mcl_villages/schematics/library.mts and b/mods/MAPGEN/mcl_villages/schematics/library.mts differ diff --git a/mods/MAPGEN/mcl_villages/schematics/medium_house.mts b/mods/MAPGEN/mcl_villages/schematics/medium_house.mts index 43ce2391b..85ef0f903 100644 Binary files a/mods/MAPGEN/mcl_villages/schematics/medium_house.mts and b/mods/MAPGEN/mcl_villages/schematics/medium_house.mts differ diff --git a/mods/MAPGEN/mcl_villages/schematics/small_house.mts b/mods/MAPGEN/mcl_villages/schematics/small_house.mts index d7b62529c..d09fbfe00 100644 Binary files a/mods/MAPGEN/mcl_villages/schematics/small_house.mts and b/mods/MAPGEN/mcl_villages/schematics/small_house.mts differ diff --git a/mods/MAPGEN/mcl_villages/schematics/tavern.mts b/mods/MAPGEN/mcl_villages/schematics/tavern.mts index 5eae8ae23..f6f3a5979 100644 Binary files a/mods/MAPGEN/mcl_villages/schematics/tavern.mts and b/mods/MAPGEN/mcl_villages/schematics/tavern.mts differ diff --git a/mods/MAPGEN/mcl_villages/schematics/well.mts b/mods/MAPGEN/mcl_villages/schematics/well.mts index 6ea47fea4..8b543dbf4 100644 Binary files a/mods/MAPGEN/mcl_villages/schematics/well.mts and b/mods/MAPGEN/mcl_villages/schematics/well.mts differ diff --git a/mods/MAPGEN/mcl_villages/utils.lua b/mods/MAPGEN/mcl_villages/utils.lua deleted file mode 100644 index 1d94ead0c..000000000 --- a/mods/MAPGEN/mcl_villages/utils.lua +++ /dev/null @@ -1,217 +0,0 @@ -local get_node = mcl_mapgen.get_far_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, wait) - 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)) - end - - 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) - end - settlements.debug("find_surface5: cnt_max overflow") - return nil -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 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") 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_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]] diff --git a/mods/PLAYER/mcl_playerinfo/init.lua b/mods/PLAYER/mcl_playerinfo/init.lua index 9c5d1433f..6c714c78b 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_authplayer(function(name, ip, is_success) + if not is_success then return end mcl_playerinfo[name] = { node_head = "", node_feet = "", diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index 720c11525..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 - - if object and (object:is_player() - or (object:get_luaentity()._cmi_is_mob == true and object ~= player)) then + local luaentity = object:get_luaentity() + if object and ((mcl_util and mcl_util.is_player(object)) + 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} @@ -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: 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