forked from MineClone5/MineClone5
Merge remote-tracking branch 'origin/production'
This commit is contained in:
commit
ce6929c8e0
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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`.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
|
@ -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
|
|
@ -1,3 +0,0 @@
|
|||
name = tga_encoder
|
||||
author = Fleckenstein
|
||||
description = A TGA Encoder written in Lua without the use of external Libraries.
|
|
@ -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"})
|
||||
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,
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
* sounds/bell_stroke.ogg
|
||||
* created by edsward
|
||||
* modified by sorcerykid
|
||||
* obtained from https://freesound.org/people/edsward/sounds/341866/
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
# textdomain: mcl_observers
|
||||
Bell=
|
|
@ -0,0 +1,3 @@
|
|||
name = mcl_bells
|
||||
depends = mesecons
|
||||
optional_depends = mcl_wip
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 368 B |
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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."))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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=
|
||||
|
|
|
@ -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."),
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 250 B |
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
})
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
})
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
# textdomain: mcl_villages
|
||||
Chiseled Stone Village Bricks=Точёный каменный блок из деревни
|
||||
Map chunk @1 to @2 is not suitable for placing villages.=Чанк с @1 по @2 непригоден для размещения деревень.
|
|
@ -0,0 +1,3 @@
|
|||
# textdomain: mcl_villages
|
||||
Chiseled Stone Village Bricks=
|
||||
Map chunk @1 to @2 is not suitable for placing villages.=
|
|
@ -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
|
||||
|
|
|
@ -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
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
mcl_commands = {}
|
||||
|
||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
|
||||
dofile(modpath.."/gamemode.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
|
||||
|
|
|
@ -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]]
|
||||
|
|
|
@ -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 = "",
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue