Merge remote-tracking branch 'origin/production'

This commit is contained in:
kay27 2022-02-24 06:59:26 +04:00
commit ce6929c8e0
90 changed files with 1821 additions and 1312 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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`.

View File

@ -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

View File

@ -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)

View File

@ -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.

View File

@ -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

View File

@ -1,3 +0,0 @@
name = tga_encoder
author = Fleckenstein
description = A TGA Encoder written in Lua without the use of external Libraries.

View File

@ -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,
})

View File

@ -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)

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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"))

View File

@ -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

View File

@ -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()

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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")

View File

@ -0,0 +1,4 @@
* sounds/bell_stroke.ogg
* created by edsward
* modified by sorcerykid
* obtained from https://freesound.org/people/edsward/sounds/341866/

View File

@ -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

View File

@ -0,0 +1,2 @@
# textdomain: mcl_observers
Bell=

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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."))

View File

@ -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

View File

@ -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=

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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
})

View File

@ -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:

View File

@ -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)

View File

@ -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")

View File

@ -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")

View File

@ -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")

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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,
})

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,3 @@
# textdomain: mcl_villages
Chiseled Stone Village Bricks=Точёный каменный блок из деревни
Map chunk @1 to @2 is not suitable for placing villages.=Чанк с @1 по @2 непригоден для размещения деревень.

View File

@ -0,0 +1,3 @@
# textdomain: mcl_villages
Chiseled Stone Village Bricks=
Map chunk @1 to @2 is not suitable for placing villages.=

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -1,3 +1,5 @@
mcl_commands = {}
local modpath = minetest.get_modpath(minetest.get_current_modname())
dofile(modpath.."/gamemode.lua")

View File

@ -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

View File

@ -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]]

View File

@ -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 = "",

View File

@ -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:

View File

@ -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