Update Fork #9

Merged
chmodsayshello merged 403 commits from MineClone5/MineClone5:master into master 2022-08-02 15:50:37 +02:00
33 changed files with 1296 additions and 923 deletions
Showing only changes of commit 6c2bdf3156 - Show all commits

View File

@ -70,7 +70,11 @@ an explanation.
## Installation ## Installation
This game requires latest stable [Minetest](http://minetest.net) to run, please install This game requires latest stable [Minetest](http://minetest.net) to run, please install
it first. Only stable versions of Minetest are officially supported. it first. Only latest stable version of Minetest is officially supported.
There are lots of questions about Ubuntu, which has minetest-5.1.1 still.
Please, first of all, visit this page, it should fix the problem: https://launchpad.net/~minetestdevs/+archive/ubuntu/stable
Also, here is endless issue #123: https://git.minetest.land/MineClone5/MineClone5/issues/123 - really less preferable way.
There is no support for running MineClone 5 in development versions of Minetest. There is no support for running MineClone 5 in development versions of Minetest.
To install MineClone 5 (if you haven't already), move this directory into the To install MineClone 5 (if you haven't already), move this directory into the

View File

@ -148,16 +148,48 @@ local chunk_scan_range = {
[ CS_NODES] = {LAST_BLOCK+1, LAST_BLOCK+1}, [ CS_NODES] = {LAST_BLOCK+1, LAST_BLOCK+1},
} }
local EDGE_MIN = mcl_mapgen.EDGE_MIN
local EDGE_MAX = mcl_mapgen.EDGE_MAX
local function is_chunk_finished(minp) local function is_chunk_finished(minp)
local center = vector.add(minp, HALF_CS_NODES) local center_x = minp.x + HALF_CS_NODES
for check_x = center.x - CS_NODES, center.x + CS_NODES, CS_NODES do local center_y = minp.y + HALF_CS_NODES
for check_y = center.y - CS_NODES, center.y + CS_NODES, CS_NODES do local center_z = minp.z + HALF_CS_NODES
for check_z = center.z - CS_NODES, center.z + CS_NODES, CS_NODES do local from_x = center_x - CS_NODES
local pos = vector.new(check_x, check_y, check_z) local from_y = center_y - CS_NODES
if pos ~= center then local from_z = center_z - CS_NODES
minetest_get_voxel_manip():read_from_map(pos, pos) local to_x = center_x + CS_NODES
local node = minetest_get_node(pos) local to_y = center_y + CS_NODES
local to_z = center_z + CS_NODES
if from_x < EDGE_MIN then from_x = center_x end
if from_y < EDGE_MIN then from_y = center_y end
if from_z < EDGE_MIN then from_z = center_z end
if to_x > EDGE_MAX then to_x = center_x end
if to_y > EDGE_MAX then to_y = center_y end
if to_z > EDGE_MAX then to_z = center_z end
for check_x = from_x, to_x, CS_NODES do
local are_we_in_central_chunk = check_x == center_x
for check_y = from_y, to_y, CS_NODES do
are_we_in_central_chunk = are_we_in_central_chunk and (check_y == center_y)
for check_z = from_z, to_z, CS_NODES do
are_we_in_central_chunk = are_we_in_central_chunk and (check_z == center_z)
if not are_we_in_central_chunk then
local check_pos = {x = check_x, y = check_y, z = check_z}
minetest_get_voxel_manip():read_from_map(check_pos, check_pos)
local node = minetest_get_node(check_pos)
if node.name == "ignore" then if node.name == "ignore" then
-- return nil, means false, means, there is something to generate still,
-- (because one of adjacent chunks is unfinished - "ignore" means that),
-- means this chunk will be changed, at least one of its sides or corners
-- means it's unsafe to place anything there right now, it might disappar,
-- better to wait, see the diagram of conflict/ok areas per a single axis:
-- conflict| ok |conflict|conflict| ok |conflict|conflict| ok |conflict
-- (_________Chunk1_________)|(_________Chunk2_________)|(_________Chunk3_________)
-- [Block1]|[MidBlk]|[BlockN]|[Block1]|[MidBlk]|[BlockN]|[Block1]|[MidBlk]|[BlockN]
-- \_____________Chunk2-with-shell____________/
-- ...______Chunk1-with-shell________/ \________Chunk3-with-shell______...
-- Generation of chunk 1 AFFECTS 2 ^^^ ^^^ Generation of chunk 3 affects 2
-- ^^^^^^^^Chunk 2 gen. affects 1 and 3^^^^^^^^
return return
end end
end end

View File

@ -1,5 +1,11 @@
mcl_util = {} mcl_util = {}
local minetest_get_item_group = minetest.get_item_group
local minetest_get_meta = minetest.get_meta
local minetest_get_node = minetest.get_node
local minetest_get_node_timer = minetest.get_node_timer
local table_copy = table.copy
-- Updates all values in t using values from to*. -- Updates all values in t using values from to*.
function table.update(t, ...) function table.update(t, ...)
for _, to in ipairs{...} do for _, to in ipairs{...} do
@ -33,36 +39,6 @@ function mcl_util.rotate_axis(itemstack, placer, pointed_thing)
return itemstack return itemstack
end end
-- Returns position of the neighbor of a double chest node
-- or nil if node is invalid.
-- This function assumes that the large chest is actually intact
-- * pos: Position of the node to investigate
-- * param2: param2 of that node
-- * side: Which "half" the investigated node is. "left" or "right"
function mcl_util.get_double_container_neighbor_pos(pos, param2, side)
if side == "right" then
if param2 == 0 then
return {x=pos.x-1, y=pos.y, z=pos.z}
elseif param2 == 1 then
return {x=pos.x, y=pos.y, z=pos.z+1}
elseif param2 == 2 then
return {x=pos.x+1, y=pos.y, z=pos.z}
elseif param2 == 3 then
return {x=pos.x, y=pos.y, z=pos.z-1}
end
else
if param2 == 0 then
return {x=pos.x+1, y=pos.y, z=pos.z}
elseif param2 == 1 then
return {x=pos.x, y=pos.y, z=pos.z-1}
elseif param2 == 2 then
return {x=pos.x-1, y=pos.y, z=pos.z}
elseif param2 == 3 then
return {x=pos.x, y=pos.y, z=pos.z+1}
end
end
end
-- Iterates through all items in the given inventory and -- Iterates through all items in the given inventory and
-- returns the slot of the first item which matches a condition. -- returns the slot of the first item which matches a condition.
-- Returns nil if no item was found. -- Returns nil if no item was found.
@ -87,7 +63,7 @@ end
-- Returns true if itemstack is a shulker box -- Returns true if itemstack is a shulker box
local function is_not_shulker_box(itemstack) local function is_not_shulker_box(itemstack)
local g = minetest.get_item_group(itemstack:get_name(), "shulker_box") local g = minetest_get_item_group(itemstack:get_name(), "shulker_box")
return g == 0 or g == nil return g == 0 or g == nil
end end
@ -133,136 +109,116 @@ end
--- source_stack_id (optional): The inventory position ID of the source inventory to take the item from (-1 for slot of the first valid item; -1 is default) --- source_stack_id (optional): The inventory position ID of the source inventory to take the item from (-1 for slot of the first valid item; -1 is default)
--- destination_list (optional): List name of the destination inventory. Default is normally "main"; "src" for furnace --- destination_list (optional): List name of the destination inventory. Default is normally "main"; "src" for furnace
-- Returns true on success and false on failure. -- Returns true on success and false on failure.
local SHULKER_BOX = 3
local FURNACE = 4
local DOUBLE_CHEST_LEFT = 5
local DOUBLE_CHEST_RIGHT = 6
local CONTAINER_GROUP_TO_LIST = {
[1] = "main",
[2] = "main",
[SHULKER_BOX] = "main",
[FURNACE] = "dst",
[DOUBLE_CHEST_LEFT] = "main",
[DOUBLE_CHEST_RIGHT] = "main",
}
function mcl_util.move_item_container(source_pos, destination_pos, source_list, source_stack_id, destination_list) function mcl_util.move_item_container(source_pos, destination_pos, source_list, source_stack_id, destination_list)
local dpos = table.copy(destination_pos) local spos = table_copy(source_pos)
local spos = table.copy(source_pos) local snode = minetest_get_node(spos)
local snode = minetest.get_node(spos) local sctype = minetest_get_item_group(snode.name, "container")
local dnode = minetest.get_node(dpos) local default_source_list = CONTAINER_GROUP_TO_LIST[sctype]
if not default_source_list then return end
local dctype = minetest.get_item_group(dnode.name, "container") if sctype == DOUBLE_CHEST_RIGHT then
local sctype = minetest.get_item_group(snode.name, "container") local sparam2 = snode.param2
if sparam2 == 0 then spos.x = spos.x - 1
-- Container type 7 does not allow any movement elseif sparam2 == 1 then spos.z = spos.z + 1
if sctype == 7 then elseif sparam2 == 2 then spos.x = spos.x + 1
return false elseif sparam2 == 3 then spos.z = spos.z - 1
end
-- Normalize double container by forcing to always use the left segment first
local function normalize_double_container(pos, node, ctype)
if ctype == 6 then
pos = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "right")
if not pos then
return false
end
node = minetest.get_node(pos)
ctype = minetest.get_item_group(node.name, "container")
-- The left segment seems incorrect? We better bail out!
if ctype ~= 5 then
return false
end
end end
return pos, node, ctype snode = minetest_get_node(spos)
sctype = minetest_get_item_group(snode.name, "container")
if sctype ~= DOUBLE_CHEST_LEFT then return end
end end
local smeta = minetest_get_meta(spos)
spos, snode, sctype = normalize_double_container(spos, snode, sctype)
dpos, dnode, dctype = normalize_double_container(dpos, dnode, dctype)
if not spos or not dpos then return false end
local smeta = minetest.get_meta(spos)
local dmeta = minetest.get_meta(dpos)
local sinv = smeta:get_inventory() local sinv = smeta:get_inventory()
local source_list = source_list or default_source_list
local dpos = table_copy(destination_pos)
local dnode = minetest_get_node(dpos)
local dctype = minetest_get_item_group(dnode.name, "container")
local default_destination_list = CONTAINER_GROUP_TO_LIST[sctype]
if not default_destination_list then return end
if dctype == DOUBLE_CHEST_RIGHT then
local dparam2 = dnode.param2
if dparam2 == 0 then dpos.x = dpos.x - 1
elseif dparam2 == 1 then dpos.z = dpos.z + 1
elseif dparam2 == 2 then dpos.x = dpos.x + 1
elseif dparam2 == 3 then dpos.z = dpos.z - 1
end
dnode = minetest_get_node(dpos)
dctype = minetest_get_item_group(dnode.name, "container")
if dctype ~= DOUBLE_CHEST_LEFT then return end
end
local dmeta = minetest_get_meta(dpos)
local dinv = dmeta:get_inventory() local dinv = dmeta:get_inventory()
-- Default source lists
if not source_list then
-- Main inventory for most container types
if sctype == 2 or sctype == 3 or sctype == 5 or sctype == 6 or sctype == 7 then
source_list = "main"
-- Furnace: output
elseif sctype == 4 then
source_list = "dst"
-- Unknown source container type. Bail out
else
return false
end
end
-- Automatically select stack slot ID if set to automatic -- Automatically select stack slot ID if set to automatic
if not source_stack_id then local source_stack_id = source_stack_id or -1
source_stack_id = -1
end
if source_stack_id == -1 then if source_stack_id == -1 then
local cond = nil local cond = nil
-- Prevent shulker box inception -- Prevent shulker box inception
if dctype == 3 then if dctype == SHULKER_BOX then cond = is_not_shulker_box end
cond = is_not_shulker_box
end
source_stack_id = mcl_util.get_eligible_transfer_item_slot(sinv, source_list, dinv, dpos, cond) source_stack_id = mcl_util.get_eligible_transfer_item_slot(sinv, source_list, dinv, dpos, cond)
if not source_stack_id then if not source_stack_id then
-- Try again if source is a double container if sctype == DOUBLE_CHEST_LEFT then
if sctype == 5 then local sparam2 = snode.param2
spos = mcl_util.get_double_container_neighbor_pos(spos, snode.param2, "left") if sparam2 == 0 then spos.x = spos.x + 1
smeta = minetest.get_meta(spos) elseif sparam2 == 1 then spos.z = spos.z - 1
sinv = smeta:get_inventory() elseif sparam2 == 2 then spos.x = spos.x - 1
elseif sparam2 == 3 then spos.z = spos.z + 1
source_stack_id = mcl_util.get_eligible_transfer_item_slot(sinv, source_list, dinv, dpos, cond)
if not source_stack_id then
return false
end end
else snode = minetest_get_node(spos)
return false sctype = minetest_get_item_group(snode.name, "container")
if sctype ~= DOUBLE_CHEST_RIGHT then return end
smeta = minetest_get_meta(spos)
sinv = smeta:get_inventory()
source_stack_id = mcl_util.get_eligible_transfer_item_slot(sinv, source_list, dinv, dpos, cond)
end end
end end
if not source_stack_id then return end
end end
-- Abort transfer if shulker box wants to go into shulker box -- Abort transfer if shulker box wants to go into shulker box
if dctype == 3 then if dctype == SHULKER_BOX then
local stack = sinv:get_stack(source_list, source_stack_id) local stack = sinv:get_stack(source_list, source_stack_id)
if stack and minetest.get_item_group(stack:get_name(), "shulker_box") == 1 then if stack and minetest_get_item_group(stack:get_name(), "shulker_box") == 1 then return end
return false
end
end
-- Container type 7 does not allow any placement
if dctype == 7 then
return false
end end
-- If it's a container, put it into the container local destination_list = destination_list or default_destination_list
if dctype ~= 0 then -- Move item
-- Automatically select a destination list if omitted local ok = mcl_util.move_item(sinv, source_list, source_stack_id, dinv, destination_list)
if not destination_list then -- Try transfer to neighbor node if transfer failed and double container
-- Main inventory for most container types if not ok then
if dctype == 2 or dctype == 3 or dctype == 5 or dctype == 6 or dctype == 7 then if dctype == DOUBLE_CHEST_LEFT then
destination_list = "main" local dparam2 = dnode.param2
-- Furnace source slot if dparam2 == 0 then dpos.x = dpos.x + 1
elseif dctype == 4 then elseif dparam2 == 1 then dpos.z = dpos.z - 1
destination_list = "src" elseif dparam2 == 2 then dpos.x = dpos.x - 1
elseif dparam2 == 3 then dpos.z = dpos.z + 1
end end
end dnode = minetest_get_node(dpos)
if destination_list then dctype = minetest_get_item_group(dnode.name, "container")
-- Move item if dctype ~= DOUBLE_CHEST_RIGHT then return end
local ok = mcl_util.move_item(sinv, source_list, source_stack_id, dinv, destination_list) dmeta = minetest_get_meta(dpos)
dinv = dmeta:get_inventory()
-- Try transfer to neighbor node if transfer failed and double container ok = mcl_util.move_item(sinv, source_list, source_stack_id, dinv, destination_list)
if not ok and dctype == 5 then
dpos = mcl_util.get_double_container_neighbor_pos(dpos, dnode.param2, "left")
dmeta = minetest.get_meta(dpos)
dinv = dmeta:get_inventory()
ok = mcl_util.move_item(sinv, source_list, source_stack_id, dinv, destination_list)
end
-- Update furnace
if ok and dctype == 4 then
-- Start furnace's timer function, it will sort out whether furnace can burn or not.
minetest.get_node_timer(dpos):start(1.0)
end
return ok
end end
end end
return false -- Update furnace
if ok and dctype == FURNACE then
-- Start furnace's timer function, it will sort out whether furnace can burn or not.
minetest_get_node_timer(dpos):start(1.0)
end
return ok
end end
-- Returns the ID of the first non-empty slot in the given inventory list -- Returns the ID of the first non-empty slot in the given inventory list
@ -292,7 +248,7 @@ function mcl_util.generate_on_place_plant_function(condition)
end end
-- Call on_rightclick if the pointed node defines it -- Call on_rightclick if the pointed node defines it
local node = minetest.get_node(pointed_thing.under) local node = minetest_get_node(pointed_thing.under)
if placer and not placer:get_player_control().sneak then if placer and not placer:get_player_control().sneak then
if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then
return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack
@ -300,8 +256,8 @@ function mcl_util.generate_on_place_plant_function(condition)
end end
local place_pos local place_pos
local def_under = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name] local def_under = minetest.registered_nodes[minetest_get_node(pointed_thing.under).name]
local def_above = minetest.registered_nodes[minetest.get_node(pointed_thing.above).name] local def_above = minetest.registered_nodes[minetest_get_node(pointed_thing.above).name]
if not def_under or not def_above then if not def_under or not def_above then
return itemstack return itemstack
end end
@ -359,7 +315,7 @@ function mcl_util.call_on_rightclick(itemstack, player, pointed_thing)
-- Call on_rightclick if the pointed node defines it -- Call on_rightclick if the pointed node defines it
if pointed_thing and pointed_thing.type == "node" then if pointed_thing and pointed_thing.type == "node" then
local pos = pointed_thing.under local pos = pointed_thing.under
local node = minetest.get_node(pos) local node = minetest_get_node(pos)
if player and not player:get_player_control().sneak then if player and not player:get_player_control().sneak then
local nodedef = minetest.registered_nodes[node.name] local nodedef = minetest.registered_nodes[node.name]
local on_rightclick = nodedef and nodedef.on_rightclick local on_rightclick = nodedef and nodedef.on_rightclick
@ -372,7 +328,7 @@ end
function mcl_util.calculate_durability(itemstack) function mcl_util.calculate_durability(itemstack)
local unbreaking_level = mcl_enchanting.get_enchantment(itemstack, "unbreaking") local unbreaking_level = mcl_enchanting.get_enchantment(itemstack, "unbreaking")
local armor_uses = minetest.get_item_group(itemstack:get_name(), "mcl_armor_uses") local armor_uses = minetest_get_item_group(itemstack:get_name(), "mcl_armor_uses")
local uses local uses

View File

@ -88,7 +88,7 @@ local function land_state_switch(self, dtime)
end end
--ignore everything else if following --ignore everything else if following
if mobs.check_following(self) and if mobs.check_following(self, dtime) and
(not self.breed_lookout_timer or (self.breed_lookout_timer and self.breed_lookout_timer == 0)) and (not self.breed_lookout_timer or (self.breed_lookout_timer and self.breed_lookout_timer == 0)) and
(not self.breed_timer or (self.breed_timer and self.breed_timer == 0)) then (not self.breed_timer or (self.breed_timer and self.breed_timer == 0)) then
self.state = "follow" self.state = "follow"
@ -984,7 +984,7 @@ function mobs.mob_step(self, dtime)
--go get the closest player --go get the closest player
if attacking then if attacking then
mobs.do_head_logic(self, dtime, attacking)
self.memory = 6 --6 seconds of memory self.memory = 6 --6 seconds of memory
--set initial punch timer --set initial punch timer
@ -1040,6 +1040,7 @@ function mobs.mob_step(self, dtime)
--don't break eye contact --don't break eye contact
if self.hostile and self.attacking then if self.hostile and self.attacking then
mobs.set_yaw_while_attacking(self) mobs.set_yaw_while_attacking(self)
mobs.do_head_logic(self, dtime, self.attacking)
end end
--perfectly reset pause_timer --perfectly reset pause_timer

View File

@ -3,7 +3,7 @@ local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius
local vector = vector local vector = vector
--check to see if someone nearby has some tasty food --check to see if someone nearby has some tasty food
mobs.check_following = function(self) -- returns true or false mobs.check_following = function(self, dtime) -- returns true or false
--ignore --ignore
if not self.follow then if not self.follow then
self.following_person = nil self.following_person = nil
@ -15,6 +15,7 @@ mobs.check_following = function(self) -- returns true or false
--check if the follower is a player incase they log out --check if the follower is a player incase they log out
if follower and follower:is_player() then if follower and follower:is_player() then
mobs.do_head_logic(self, dtime, follower)
local stack = follower:get_wielded_item() local stack = follower:get_wielded_item()
--safety check --safety check
if not stack then if not stack then

View File

@ -6,9 +6,9 @@ local degrees = function(yaw)
return yaw*180.0/math.pi return yaw*180.0/math.pi
end end
mobs.do_head_logic = function(self,dtime) mobs.do_head_logic = function(self, dtime, player)
local player = minetest.get_player_by_name("singleplayer") local player = player or minetest.get_player_by_name("singleplayer")
local look_at = player:get_pos() local look_at = player:get_pos()
look_at.y = look_at.y + player:get_properties().eye_height look_at.y = look_at.y + player:get_properties().eye_height
@ -89,10 +89,21 @@ mobs.do_head_logic = function(self,dtime)
head_pitch = head_pitch + self.head_pitch_modifier head_pitch = head_pitch + self.head_pitch_modifier
end end
if self.swap_y_with_x then local head_bone = self.head_bone
self.object:set_bone_position(self.head_bone, bone_pos, vector.new(degrees(head_pitch),degrees(head_yaw),0)) if (type(head_bone) == "table") then
for _, v in pairs(head_bone) do
if self.swap_y_with_x then
self.object:set_bone_position(v, bone_pos, vector.new(degrees(head_pitch),degrees(head_yaw),0))
else
self.object:set_bone_position(v, bone_pos, vector.new(degrees(head_pitch),0,degrees(head_yaw)))
end
end
else else
self.object:set_bone_position(self.head_bone, bone_pos, vector.new(degrees(head_pitch),0,degrees(head_yaw))) if self.swap_y_with_x then
self.object:set_bone_position(head_bone, bone_pos, vector.new(degrees(head_pitch),degrees(head_yaw),0))
else
self.object:set_bone_position(head_bone, bone_pos, vector.new(degrees(head_pitch),0,degrees(head_yaw)))
end
end end
--set_bone_position([bone, position, rotation]) --set_bone_position([bone, position, rotation])
end end

View File

@ -82,7 +82,7 @@ mobs:register_mob("mobs_mc:sheep", {
--head code --head code
has_head = true, has_head = true,
head_bone = "head", head_bone = {"hea1", "hea2",},
swap_y_with_x = false, swap_y_with_x = false,
reverse_head_yaw = false, reverse_head_yaw = false,

View File

@ -611,11 +611,14 @@ do
io.close(file) io.close(file)
if string then if string then
local savetable = minetest.deserialize(string) local savetable = minetest.deserialize(string)
for name, players_stored_data in pairs(savetable.players_stored_data) do local savetable_players_stored_data = savetable and savetable.players_stored_data
doc.data.players[name] = {} if savetable_players_stored_data then
doc.data.players[name].stored_data = players_stored_data for name, players_stored_data in pairs(savetable_players_stored_data) do
doc.data.players[name] = {}
doc.data.players[name].stored_data = players_stored_data
end
minetest.log("action", "[doc] doc.mt successfully read.")
end end
minetest.log("action", "[doc] doc.mt successfully read.")
end end
end end
end end

View File

@ -6,6 +6,7 @@ Alexander Minges
aligator aligator
ArTee3 ArTee3
Artem Arbatsky Artem Arbatsky
balazsszalab
basxto basxto
Benjamin Schötz Benjamin Schötz
Blue Blancmange Blue Blancmange
@ -13,6 +14,7 @@ Booglejr
Brandon Brandon
Bu-Gee Bu-Gee
bzoss bzoss
CableGuy67
chmodsayshello chmodsayshello
Code-Sploit Code-Sploit
cora cora
@ -31,6 +33,7 @@ Emojigit
epCode epCode
erlehmann erlehmann
FinishedFragment FinishedFragment
FlamingRCCars
Glaucos Ginez Glaucos Ginez
Gustavo Ramos Rehermann Gustavo Ramos Rehermann
Guy Liner Guy Liner
@ -39,6 +42,7 @@ HimbeerserverDE
iliekprogrammar iliekprogrammar
j1233 j1233
Jared Moody Jared Moody
Johannes Fritz
jordan4ibanez jordan4ibanez
kabou kabou
kay27 kay27
@ -46,13 +50,14 @@ Laurent Rocher
Li0n Li0n
marcin-serwin marcin-serwin
Marcin Serwin Marcin Serwin
Mark Roth
Mental-Inferno Mental-Inferno
Midgard Midgard
MysticTempest MysticTempest
Nicholas Niro Nicholas Niro
nickolas360 nickolas360
Nicu Nicu
nikolaus-albinger Niklp
Nils Dagsson Moskopp Nils Dagsson Moskopp
NO11 NO11
NO411 NO411
@ -60,6 +65,7 @@ Oil_boi
pitchum pitchum
PrairieAstronomer PrairieAstronomer
PrairieWind PrairieWind
River River
Rocher Laurent Rocher Laurent
rootyjr rootyjr
Rootyjr Rootyjr
@ -68,6 +74,7 @@ Sab Pyrope
Saku Laesvuori Saku Laesvuori
sfan5 sfan5
SmallJoker SmallJoker
Sumyjkl
superfloh247 superfloh247
Sven792 Sven792
Sydney Gems Sydney Gems
@ -75,6 +82,7 @@ talamh
TechDudie TechDudie
Thinking Thinking
Tianyang Zhang Tianyang Zhang
unknown
U.N.Owen U.N.Owen
Wouters Dorian Wouters Dorian
wuniversales wuniversales

View File

@ -1,8 +1,4 @@
Please run the following command to update contributor list: Please run `./update_credits.sh` from [tools](../../../tools) folder to update contributor list.
```bash
# git log --pretty="%an" | sort | uniq >CONTRUBUTOR_LIST.txt
```
Please check that there is no error on execution, and `CONTRUBUTOR_LIST.txt` is updated. Please check that there is no error on execution, and `CONTRUBUTOR_LIST.txt` is updated.

View File

@ -1,14 +1,20 @@
local refresh_interval = .63 local refresh_interval = .63
local huds = {} local huds = {}
local default_debug = 3 local default_debug = 5
local after = minetest.after local after = minetest.after
local get_connected_players = minetest.get_connected_players local get_connected_players = minetest.get_connected_players
local get_biome_name = minetest.get_biome_name local get_biome_name = minetest.get_biome_name
local get_biome_data = minetest.get_biome_data local get_biome_data = minetest.get_biome_data
local get_node = minetest.get_node
local format = string.format local format = string.format
local table_concat = table.concat
local floor = math.floor
local minetest_get_gametime = minetest.get_gametime
local get_voxel_manip = minetest.get_voxel_manip
local min1, min2, min3 = mcl_mapgen.overworld.min, mcl_mapgen.end_.min, mcl_mapgen.nether.min local min1, min2, min3 = mcl_mapgen.overworld.min, mcl_mapgen.end_.min, mcl_mapgen.nether.min
local max1, max2, max3 = mcl_mapgen.overworld.max, mcl_mapgen.end_.max, mcl_mapgen.nether.max + 128 local max1, max2, max3 = mcl_mapgen.overworld.max, mcl_mapgen.end_.max, mcl_mapgen.nether.max + 128
local CS = mcl_mapgen.CS_NODES
local modname = minetest.get_current_modname() local modname = minetest.get_current_modname()
local modpath = minetest.get_modpath(modname) local modpath = minetest.get_modpath(modname)
@ -17,6 +23,7 @@ local storage = minetest.get_mod_storage()
local player_dbg = minetest.deserialize(storage:get_string("player_dbg") or "return {}") or {} local player_dbg = minetest.deserialize(storage:get_string("player_dbg") or "return {}") or {}
local function get_text(pos, bits) local function get_text(pos, bits)
local pos = pos
local bits = bits local bits = bits
if bits == 0 then return "" end if bits == 0 then return "" end
local y = pos.y local y = pos.y
@ -27,16 +34,42 @@ local function get_text(pos, bits)
elseif y >= min2 and y <= max2 then elseif y >= min2 and y <= max2 then
y = y - min2 y = y - min2
end end
local biome_data = get_biome_data(pos)
local biome_name = biome_data and get_biome_name(biome_data.biome) or "No biome" local will_show_mapgen_status = bits % 8 > 3
local text local will_show_coordinates = bits % 4 > 1
if bits == 1 then local will_show_biome_name = bits % 2 > 0
text = biome_name local will_be_shown = {}
elseif bits == 2 then
text = format("x:%.1f y:%.1f z:%.1f", pos.x, y, pos.z) if will_show_biome_name then
elseif bits == 3 then local biome_data = get_biome_data(pos)
text = format("%s x:%.1f y:%.1f z:%.1f", biome_name, pos.x, y, pos.z) local biome_name = biome_data and get_biome_name(biome_data.biome) or "No biome"
will_be_shown[#will_be_shown + 1] = biome_name
end end
if will_show_coordinates then
local coordinates = format("x:%.1f y:%.1f z:%.1f", pos.x, y, pos.z)
will_be_shown[#will_be_shown + 1] = coordinates
end
if will_show_mapgen_status then
local pos_x = floor(pos.x)
local pos_y = floor(pos.y)
local pos_z = floor(pos.z)
local c = 0
for x = pos_x - CS, pos_x + CS, CS do
for y = pos_y - CS, pos_y + CS, CS do
for z = pos_z - CS, pos_z + CS, CS do
local pos = {x = x, y = y, z = z}
get_voxel_manip():read_from_map(pos, pos)
local node = get_node(pos)
if node.name ~= "ignore" then c = c + 1 end
end
end
end
local p = floor(c / 27 * 100 + 0.5)
local status = format("Generated %u%% (%u/27 chunks)", p, c)
will_be_shown[#will_be_shown + 1] = status
end
local text = table_concat(will_be_shown, ' ')
return text return text
end end
@ -82,11 +115,11 @@ minetest.register_on_authplayer(function(name, ip, is_success)
end) end)
minetest.register_chatcommand("debug",{ minetest.register_chatcommand("debug",{
description = S("Set debug bit mask: 0 = disable, 1 = biome name, 2 = coordinates, 3 = all"), description = S("Set debug bit mask: 0 = disable, 1 = biome name, 2 = coordinates, 4 = mapgen status, 7 = all"),
func = function(name, params) func = function(name, params)
local dbg = math.floor(tonumber(params) or default_debug) local dbg = math.floor(tonumber(params) or default_debug)
if dbg < 0 or dbg > 3 then if dbg < 0 or dbg > 7 then
minetest.chat_send_player(name, S("Error! Possible values are integer numbers from @1 to @2", 0, 3)) minetest.chat_send_player(name, S("Error! Possible values are integer numbers from @1 to @2", 0, 7))
return return
end end
if dbg == default_debug then if dbg == default_debug then

View File

@ -1,4 +1,4 @@
# textdomain: mcl_info # textdomain: mcl_info
Set debug bit mask: 0 @= disable, 1 @= biome name, 2 @= coordinates, 3 @= all=Réglage du masque de débugage : 0 @= désactiver, 1 @= nom de biome, 2 @= coordonnées, 3 @= tout= Set debug bit mask: 0 @= disable, 1 @= biome name, 2 @= coordinates, 4 @= mapgen status, 7 @= all=Réglage du masque de débugage : 0 @= désactiver, 1 @= nom de biome, 2 @= coordonnées, 4 @= mapgen status, 7 @= tout=
Error! Possible values are integer numbers from @1 to @2=Erreur ! Les valeurs autorisées sont des nombres entiers de @1 à @2 Error! Possible values are integer numbers from @1 to @2=Erreur ! Les valeurs autorisées sont des nombres entiers de @1 à @2
Debug bit mask set to @1=Masque de débugage réglé à @1 Debug bit mask set to @1=Masque de débugage réglé à @1

View File

@ -1,4 +1,4 @@
# textdomain: mcl_info # textdomain: mcl_info
Set debug bit mask: 0 @= disable, 1 @= biome name, 2 @= coordinates, 3 @= all=Установка отладочной битовой маски: 0 @= отключить, 1 @= биом, 2 @= координаты, 3 @= всё Set debug bit mask: 0 @= disable, 1 @= biome name, 2 @= coordinates, 4 @= mapgen status, 7 @= all=Установка отладочной битовой маски: 0 @= отключить, 1 @= биом, 2 @= координаты, 4 @= состояние мапгена, 7 @= всё
Error! Possible values are integer numbers from @1 to @2=Ошибка! Допустимые значения - целые числа от @1 до @2 Error! Possible values are integer numbers from @1 to @2=Ошибка! Допустимые значения - целые числа от @1 до @2
Debug bit mask set to @1=Отладочной битовой маске присвоено значение @1 Debug bit mask set to @1=Отладочной битовой маске присвоено значение @1

View File

@ -1,4 +1,4 @@
# textdomain: mcl_info # textdomain: mcl_info
Set debug bit mask: 0 @= disable, 1 @= biome name, 2 @= coordinates, 3 @= all= Set debug bit mask: 0 @= disable, 1 @= biome name, 2 @= coordinates, 4 @= mapgen status, 7 @= all=
Error! Possible values are integer numbers from @1 to @2= Error! Possible values are integer numbers from @1 to @2=
Debug bit mask set to @1= Debug bit mask set to @1=

View File

@ -18,6 +18,30 @@ local entity_animations = {
} }
} }
-- Returns position of the neighbor of a double chest node
-- or nil if node is invalid.
-- This function assumes that the large chest is actually intact
-- * pos: Position of the node to investigate
-- * param2: param2 of that node
-- * side: Which "half" the investigated node is. "left" or "right"
local function get_double_container_neighbor_pos(pos, param2, side)
local pos = pos
local param2 = param2
if side == "right" then
if param2 == 0 then return {x=pos.x-1, y=pos.y, z=pos.z}
elseif param2 == 1 then return {x=pos.x, y=pos.y, z=pos.z+1}
elseif param2 == 2 then return {x=pos.x+1, y=pos.y, z=pos.z}
elseif param2 == 3 then return {x=pos.x, y=pos.y, z=pos.z-1}
end
else
if param2 == 0 then return {x=pos.x+1, y=pos.y, z=pos.z}
elseif param2 == 1 then return {x=pos.x, y=pos.y, z=pos.z-1}
elseif param2 == 2 then return {x=pos.x-1, y=pos.y, z=pos.z}
elseif param2 == 3 then return {x=pos.x, y=pos.y, z=pos.z+1}
end
end
end
minetest.register_entity("mcl_chests:chest", { minetest.register_entity("mcl_chests:chest", {
initial_properties = { initial_properties = {
visual = "mesh", visual = "mesh",
@ -217,14 +241,14 @@ local function chest_update_after_close(pos)
find_or_create_entity(pos, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left") find_or_create_entity(pos, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
mesecon.receptor_off(pos, trapped_chest_mesecons_rules) mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left") local pos_other = get_double_container_neighbor_pos(pos, node.param2, "left")
minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_right", param2 = node.param2}) minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_right", param2 = node.param2})
mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules) mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules)
elseif node.name == "mcl_chests:trapped_chest_on_right" then elseif node.name == "mcl_chests:trapped_chest_on_right" then
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_right", param2 = node.param2}) minetest.swap_node(pos, {name="mcl_chests:trapped_chest_right", param2 = node.param2})
mesecon.receptor_off(pos, trapped_chest_mesecons_rules) mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "right") local pos_other = get_double_container_neighbor_pos(pos, node.param2, "right")
minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_left", param2 = node.param2}) minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_left", param2 = node.param2})
find_or_create_entity(pos_other, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left") find_or_create_entity(pos_other, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules) mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules)
@ -438,15 +462,15 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
-- BEGIN OF LISTRING WORKAROUND -- BEGIN OF LISTRING WORKAROUND
inv:set_size("input", 1) inv:set_size("input", 1)
-- END OF LISTRING WORKAROUND -- END OF LISTRING WORKAROUND
if minetest.get_node(mcl_util.get_double_container_neighbor_pos(pos, param2, "right")).name == "mcl_chests:"..canonical_basename.."_small" then if minetest.get_node(get_double_container_neighbor_pos(pos, param2, "right")).name == "mcl_chests:"..canonical_basename.."_small" then
minetest.swap_node(pos, {name="mcl_chests:"..canonical_basename.."_right",param2=param2}) minetest.swap_node(pos, {name="mcl_chests:"..canonical_basename.."_right",param2=param2})
local p = mcl_util.get_double_container_neighbor_pos(pos, param2, "right") local p = get_double_container_neighbor_pos(pos, param2, "right")
minetest.swap_node(p, { name = "mcl_chests:"..canonical_basename.."_left", param2 = param2 }) minetest.swap_node(p, { name = "mcl_chests:"..canonical_basename.."_left", param2 = param2 })
create_entity(p, "mcl_chests:"..canonical_basename.."_left", left_textures, param2, true, "default_chest", "mcl_chests_chest", "chest") create_entity(p, "mcl_chests:"..canonical_basename.."_left", left_textures, param2, true, "default_chest", "mcl_chests_chest", "chest")
elseif minetest.get_node(mcl_util.get_double_container_neighbor_pos(pos, param2, "left")).name == "mcl_chests:"..canonical_basename.."_small" then elseif minetest.get_node(get_double_container_neighbor_pos(pos, param2, "left")).name == "mcl_chests:"..canonical_basename.."_small" then
minetest.swap_node(pos, {name="mcl_chests:"..canonical_basename.."_left",param2=param2}) minetest.swap_node(pos, {name="mcl_chests:"..canonical_basename.."_left",param2=param2})
create_entity(pos, "mcl_chests:"..canonical_basename.."_left", left_textures, param2, true, "default_chest", "mcl_chests_chest", "chest") create_entity(pos, "mcl_chests:"..canonical_basename.."_left", left_textures, param2, true, "default_chest", "mcl_chests_chest", "chest")
local p = mcl_util.get_double_container_neighbor_pos(pos, param2, "left") local p = get_double_container_neighbor_pos(pos, param2, "left")
minetest.swap_node(p, { name = "mcl_chests:"..canonical_basename.."_right", param2 = param2 }) minetest.swap_node(p, { name = "mcl_chests:"..canonical_basename.."_right", param2 = param2 })
else else
minetest.swap_node(pos, { name = "mcl_chests:"..canonical_basename.."_small", param2 = param2 }) minetest.swap_node(pos, { name = "mcl_chests:"..canonical_basename.."_small", param2 = param2 })
@ -541,7 +565,7 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
on_construct = function(pos) on_construct = function(pos)
local n = minetest.get_node(pos) local n = minetest.get_node(pos)
local param2 = n.param2 local param2 = n.param2
local p = mcl_util.get_double_container_neighbor_pos(pos, param2, "left") local p = get_double_container_neighbor_pos(pos, param2, "left")
if not p or minetest.get_node(p).name ~= "mcl_chests:"..canonical_basename.."_right" then if not p or minetest.get_node(p).name ~= "mcl_chests:"..canonical_basename.."_right" then
n.name = "mcl_chests:"..canonical_basename.."_small" n.name = "mcl_chests:"..canonical_basename.."_small"
minetest.swap_node(pos, n) minetest.swap_node(pos, n)
@ -560,7 +584,7 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
close_forms(canonical_basename, pos) close_forms(canonical_basename, pos)
local param2 = n.param2 local param2 = n.param2
local p = mcl_util.get_double_container_neighbor_pos(pos, param2, "left") local p = get_double_container_neighbor_pos(pos, param2, "left")
if not p or minetest.get_node(p).name ~= "mcl_chests:"..basename.."_right" then if not p or minetest.get_node(p).name ~= "mcl_chests:"..basename.."_right" then
return return
end end
@ -581,7 +605,7 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
-- BEGIN OF LISTRING WORKAROUND -- BEGIN OF LISTRING WORKAROUND
elseif listname == "input" then elseif listname == "input" then
local inv = minetest.get_inventory({type="node", pos=pos}) local inv = minetest.get_inventory({type="node", pos=pos})
local other_pos = mcl_util.get_double_container_neighbor_pos(pos, minetest.get_node(pos).param2, "left") local other_pos = get_double_container_neighbor_pos(pos, minetest.get_node(pos).param2, "left")
local other_inv = minetest.get_inventory({type="node", pos=other_pos}) local other_inv = minetest.get_inventory({type="node", pos=other_pos})
return limit_put(stack, inv, other_inv) return limit_put(stack, inv, other_inv)
--[[if inv:room_for_item("main", stack) then --[[if inv:room_for_item("main", stack) then
@ -609,7 +633,7 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
-- BEGIN OF LISTRING WORKAROUND -- BEGIN OF LISTRING WORKAROUND
if listname == "input" then if listname == "input" then
local inv = minetest.get_inventory({type="node", pos=pos}) local inv = minetest.get_inventory({type="node", pos=pos})
local other_pos = mcl_util.get_double_container_neighbor_pos(pos, minetest.get_node(pos).param2, "left") local other_pos = get_double_container_neighbor_pos(pos, minetest.get_node(pos).param2, "left")
local other_inv = minetest.get_inventory({type="node", pos=other_pos}) local other_inv = minetest.get_inventory({type="node", pos=other_pos})
inv:set_stack("input", 1, nil) inv:set_stack("input", 1, nil)
@ -626,7 +650,7 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
_mcl_hardness = 2.5, _mcl_hardness = 2.5,
on_rightclick = function(pos, node, clicker) on_rightclick = function(pos, node, clicker)
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left") local pos_other = get_double_container_neighbor_pos(pos, node.param2, "left")
local above_def = minetest.registered_nodes[minetest.get_node({x = pos.x, y = pos.y + 1, z = pos.z}).name] local above_def = minetest.registered_nodes[minetest.get_node({x = pos.x, y = pos.y + 1, z = pos.z}).name]
local above_def_other = minetest.registered_nodes[minetest.get_node({x = pos_other.x, y = pos_other.y + 1, z = pos_other.z}).name] local above_def_other = minetest.registered_nodes[minetest.get_node({x = pos_other.x, y = pos_other.y + 1, z = pos_other.z}).name]
@ -692,7 +716,7 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
on_construct = function(pos) on_construct = function(pos)
local n = minetest.get_node(pos) local n = minetest.get_node(pos)
local param2 = n.param2 local param2 = n.param2
local p = mcl_util.get_double_container_neighbor_pos(pos, param2, "right") local p = get_double_container_neighbor_pos(pos, param2, "right")
if not p or minetest.get_node(p).name ~= "mcl_chests:"..canonical_basename.."_left" then if not p or minetest.get_node(p).name ~= "mcl_chests:"..canonical_basename.."_left" then
n.name = "mcl_chests:"..canonical_basename.."_small" n.name = "mcl_chests:"..canonical_basename.."_small"
minetest.swap_node(pos, n) minetest.swap_node(pos, n)
@ -710,7 +734,7 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
close_forms(canonical_basename, pos) close_forms(canonical_basename, pos)
local param2 = n.param2 local param2 = n.param2
local p = mcl_util.get_double_container_neighbor_pos(pos, param2, "right") local p = get_double_container_neighbor_pos(pos, param2, "right")
if not p or minetest.get_node(p).name ~= "mcl_chests:"..basename.."_left" then if not p or minetest.get_node(p).name ~= "mcl_chests:"..basename.."_left" then
return return
end end
@ -730,7 +754,7 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
return 0 return 0
-- BEGIN OF LISTRING WORKAROUND -- BEGIN OF LISTRING WORKAROUND
elseif listname == "input" then elseif listname == "input" then
local other_pos = mcl_util.get_double_container_neighbor_pos(pos, minetest.get_node(pos).param2, "right") local other_pos = get_double_container_neighbor_pos(pos, minetest.get_node(pos).param2, "right")
local other_inv = minetest.get_inventory({type="node", pos=other_pos}) local other_inv = minetest.get_inventory({type="node", pos=other_pos})
local inv = minetest.get_inventory({type="node", pos=pos}) local inv = minetest.get_inventory({type="node", pos=pos})
--[[if other_inv:room_for_item("main", stack) then --[[if other_inv:room_for_item("main", stack) then
@ -757,7 +781,7 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
" moves stuff to chest at "..minetest.pos_to_string(pos)) " moves stuff to chest at "..minetest.pos_to_string(pos))
-- BEGIN OF LISTRING WORKAROUND -- BEGIN OF LISTRING WORKAROUND
if listname == "input" then if listname == "input" then
local other_pos = mcl_util.get_double_container_neighbor_pos(pos, minetest.get_node(pos).param2, "right") local other_pos = get_double_container_neighbor_pos(pos, minetest.get_node(pos).param2, "right")
local other_inv = minetest.get_inventory({type="node", pos=other_pos}) local other_inv = minetest.get_inventory({type="node", pos=other_pos})
local inv = minetest.get_inventory({type="node", pos=pos}) local inv = minetest.get_inventory({type="node", pos=pos})
@ -775,7 +799,7 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
_mcl_hardness = 2.5, _mcl_hardness = 2.5,
on_rightclick = function(pos, node, clicker) on_rightclick = function(pos, node, clicker)
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "right") local pos_other = get_double_container_neighbor_pos(pos, node.param2, "right")
if minetest.registered_nodes[minetest.get_node({x = pos.x, y = pos.y + 1, z = pos.z}).name].groups.opaque == 1 if minetest.registered_nodes[minetest.get_node({x = pos.x, y = pos.y + 1, z = pos.z}).name].groups.opaque == 1
or minetest.registered_nodes[minetest.get_node({x = pos_other.x, y = pos_other.y + 1, z = pos_other.z}).name].groups.opaque == 1 then or minetest.registered_nodes[minetest.get_node({x = pos_other.x, y = pos_other.y + 1, z = pos_other.z}).name].groups.opaque == 1 then
-- won't open if there is no space from the top -- won't open if there is no space from the top
@ -892,12 +916,12 @@ register_chest("trapped_chest",
find_or_create_entity(pos, "mcl_chests:trapped_chest_on_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_on_left") find_or_create_entity(pos, "mcl_chests:trapped_chest_on_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_on_left")
mesecon.receptor_on(pos, trapped_chest_mesecons_rules) mesecon.receptor_on(pos, trapped_chest_mesecons_rules)
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left") local pos_other = get_double_container_neighbor_pos(pos, node.param2, "left")
minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_on_right", param2 = node.param2}) minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_on_right", param2 = node.param2})
mesecon.receptor_on(pos_other, trapped_chest_mesecons_rules) mesecon.receptor_on(pos_other, trapped_chest_mesecons_rules)
end, end,
function(pos, node, clicker) function(pos, node, clicker)
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "right") local pos_other = get_double_container_neighbor_pos(pos, node.param2, "right")
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_on_right", param2 = node.param2}) minetest.swap_node(pos, {name="mcl_chests:trapped_chest_on_right", param2 = node.param2})
mesecon.receptor_on(pos, trapped_chest_mesecons_rules) mesecon.receptor_on(pos, trapped_chest_mesecons_rules)

View File

@ -63,40 +63,42 @@ local function add_wear(placer, itemstack)
end end
local function anti_oxidation(itemstack, placer, pointed_thing) local function anti_oxidation(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then return end local pointed_thing = pointed_thing
if pointed_thing.type ~= "node" then return end
local node = minetest.get_node(pointed_thing.under) local pointed_thing_under = pointed_thing.under
local noddef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name] local node = minetest.get_node(pointed_thing_under)
local node_def = minetest.registered_nodes[node.name]
if not node_def then return end
if not placer:get_player_control().sneak and noddef.on_rightclick then if not placer:get_player_control().sneak and node_def.on_rightclick then
return minetest.item_place(itemstack, placer, pointed_thing) return minetest.item_place(itemstack, placer, pointed_thing)
end end
if minetest.is_protected(pointed_thing.under, placer:get_player_name()) then local placer_name = placer:get_player_name()
minetest.record_protection_violation(pointed_thing.under, placer:get_player_name()) if minetest.is_protected(pointed_thing_under, placer_name) then
return itemstack minetest.record_protection_violation(pointed_thing_under, placer_name)
end return itemstack
end
if noddef._mcl_stripped_variant == nil then if not node_def._mcl_stripped_variant then
for _, c in pairs(stairs) do for _, c in pairs(stairs) do
if noddef.name == "mcl_stairs:"..c[1].."_copper_"..c[2].."_cut"..c[3] then if node_def.name == "mcl_stairs:"..c[1].."_copper_"..c[2].."_cut"..c[3] then
minetest.swap_node(pointed_thing.under, {name="mcl_stairs:"..c[1].."_copper_"..c[4], param2=node.param2}) minetest.swap_node(pointed_thing_under, {name="mcl_stairs:"..c[1].."_copper_"..c[4], param2=node.param2})
anti_oxidation_particles(pointed_thing) anti_oxidation_particles(pointed_thing)
add_wear(placer, itemstack) add_wear(placer, itemstack)
end end
end end
if noddef._mcl_anti_oxidation_variant ~= nil then if node_def._mcl_anti_oxidation_variant then
minetest.swap_node(pointed_thing.under, {name=noddef._mcl_anti_oxidation_variant, param2=node.param2}) minetest.swap_node(pointed_thing_under, {name=node_def._mcl_anti_oxidation_variant, param2=node.param2})
anti_oxidation_particles(pointed_thing) anti_oxidation_particles(pointed_thing)
add_wear(placer, itemstack) add_wear(placer, itemstack)
end end
elseif noddef._mcl_stripped_variant ~= nil then elseif node_def._mcl_stripped_variant then
minetest.swap_node(pointed_thing.under, {name=noddef._mcl_stripped_variant, param2=node.param2}) minetest.swap_node(pointed_thing_under, {name=node_def._mcl_stripped_variant, param2=node.param2})
add_wear(placer, itemstack) add_wear(placer, itemstack)
else
return itemstack
end end
return itemstack return itemstack
end end
local function register_axe_override(axe_name) local function register_axe_override(axe_name)

View File

@ -4,11 +4,21 @@
local modpath = minetest.get_modpath(minetest.get_current_modname()) local modpath = minetest.get_modpath(minetest.get_current_modname())
local mg_name = mcl_mapgen.name
local v6 = mcl_mapgen.v6
local math = math local math = math
local vector = vector local vector = vector
local math_random = math.random
local minetest_after = minetest.after
local minetest_get_node = minetest.get_node
local minetest_get_node_drops = minetest.get_node_drops
local minetest_get_node_or_nil = minetest.get_node_or_nil
local minetest_get_node_light = minetest.get_node_light
local minetest_get_item_group = minetest.get_item_group
local mcl_time_get_number_of_times_at_pos = mcl_time.get_number_of_times_at_pos
local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius
local minetest_registered_nodes = minetest.registered_nodes
local mg_name = mcl_mapgen.name
local v6 = mcl_mapgen.v6
local OAK_TREE_ID = 1 local OAK_TREE_ID = 1
local DARK_OAK_TREE_ID = 2 local DARK_OAK_TREE_ID = 2
@ -26,11 +36,11 @@ minetest.register_abm({
action = function(pos, node, active_object_count, active_object_count_wider) action = function(pos, node, active_object_count, active_object_count_wider)
local water = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+1, z=pos.z+1}, "group:water") local water = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+1, z=pos.z+1}, "group:water")
local lavatype = minetest.registered_nodes[node.name].liquidtype local lavatype = minetest_registered_nodes[node.name].liquidtype
for w=1, #water do for w=1, #water do
--local waternode = minetest.get_node(water[w]) --local waternode = minetest_get_node(water[w])
--local watertype = minetest.registered_nodes[waternode.name].liquidtype --local watertype = minetest_registered_nodes[waternode.name].liquidtype
-- Lava on top of water: Water turns into stone -- Lava on top of water: Water turns into stone
if water[w].y < pos.y and water[w].x == pos.x and water[w].z == pos.z then if water[w].y < pos.y and water[w].x == pos.x and water[w].z == pos.z then
minetest.set_node(water[w], {name="mcl_core:stone"}) minetest.set_node(water[w], {name="mcl_core:stone"})
@ -72,11 +82,48 @@ local lava_spark_census = 0
function mcl_core.lava_spark_set_chance() function mcl_core.lava_spark_set_chance()
lava_spark_chance = lava_spark_limit / lava_spark_abm_census lava_spark_chance = lava_spark_limit / lava_spark_abm_census
minetest.after(LAVA_SPARK_ABM_INTERVAL, mcl_core.lava_spark_set_chance) minetest_after(LAVA_SPARK_ABM_INTERVAL, mcl_core.lava_spark_set_chance)
lava_spark_abm_census = 0 lava_spark_abm_census = 0
lava_spark_census = 0 lava_spark_census = 0
end end
function lava_spark_add(pos)
local node = minetest_get_node(pos)
if minetest_get_item_group(node.name, "lava") == 0 then return end
local above = minetest_get_node(vector.new(pos.x, pos.y + 1, pos.z))
if above.name ~= "air" then return end
local pos_addend = vector.new(
(math_random() - 0.5) * 0.8,
(math_random() - 0.5) * 0.8,
(math_random() - 0.5) * 0.8
)
local spark_pos = vector.add(pos, pos_addend)
local spark = minetest.add_entity(spark_pos, "mcl_core:lava_spark")
if not spark then return end
local velocity = vector.new(
(math_random() - 0.5) * 3,
(math_random() + 2) * 2,
(math_random() - 0.5) * 3
)
spark:set_velocity(velocity)
spark:set_acceleration(vector.new(0, -9, 0))
-- Set a random size
local size = 0.2 + math_random() * 0.2
local props = spark:get_properties()
if not props then return end
props.visual_size = vector.new(size, size, size)
spark:set_properties(props)
local luaentity = spark:get_luaentity()
if not luaentity then return end
luaentity._life_timer = 0.4 + math_random()
end
if lava_spark_limit > 0 then if lava_spark_limit > 0 then
mcl_core.lava_spark_set_chance() mcl_core.lava_spark_set_chance()
@ -87,57 +134,20 @@ if lava_spark_limit > 0 then
interval = LAVA_SPARK_ABM_INTERVAL, interval = LAVA_SPARK_ABM_INTERVAL,
chance = 18, chance = 18,
action = function(pos, node) action = function(pos, node)
local above = minetest.get_node(vector.new(pos.x, pos.y + 1, pos.z)) local above = minetest_get_node(vector.new(pos.x, pos.y + 1, pos.z))
if above.name ~= "air" then return end if above.name ~= "air" then return end
lava_spark_abm_census = lava_spark_abm_census + 1 lava_spark_abm_census = lava_spark_abm_census + 1
if lava_spark_census >= lava_spark_limit then return end if lava_spark_census >= lava_spark_limit then return end
if math.random() > lava_spark_chance then return end if math_random() > lava_spark_chance then return end
lava_spark_census = lava_spark_census + 1 lava_spark_census = lava_spark_census + 1
minetest.after(math.random() * LAVA_SPARK_ABM_INTERVAL, mcl_core.lava_spark_add, pos) minetest_after(math_random() * LAVA_SPARK_ABM_INTERVAL, lava_spark_add, pos)
end end
}) })
end end
function mcl_core.lava_spark_add(pos)
local node = minetest.get_node(pos)
if minetest.get_node_group(node.name, "lava") == 0 then return end
local above = minetest.get_node(vector.new(pos.x, pos.y + 1, pos.z))
if above.name ~= "air" then return end
local pos_addend = vector.new(
(math.random() - 0.5) * 0.8,
(math.random() - 0.5) * 0.8,
(math.random() - 0.5) * 0.8
)
local spark_pos = vector.add(pos, pos_addend)
local spark = minetest.add_entity(spark_pos, "mcl_core:lava_spark")
if not spark then return end
local velocity = vector.new(
(math.random() - 0.5) * 3,
(math.random() + 2) * 2,
(math.random() - 0.5) * 3
)
spark:set_velocity(velocity)
spark:set_acceleration(vector.new(0, -9, 0))
-- Set a random size
local size = 0.2 + math.random() * 0.2
local props = spark:get_properties()
if not props then return end
props.visual_size = vector.new(size, size, size)
spark:set_properties(props)
local luaentity = spark:get_luaentity()
if not luaentity then return end
luaentity._life_timer = 0.4 + math.random()
end
minetest.register_entity("mcl_core:lava_spark", { minetest.register_entity("mcl_core:lava_spark", {
physical = true, physical = true,
visual = "sprite", visual = "sprite",
@ -159,7 +169,7 @@ minetest.register_entity("mcl_core:lava_spark", {
self._smoke_timer = self._smoke_timer - dtime self._smoke_timer = self._smoke_timer - dtime
if self._smoke_timer > 0 then return end if self._smoke_timer > 0 then return end
self._smoke_timer = 0.2 + math.random() * 0.3 self._smoke_timer = 0.2 + math_random() * 0.3
local pos = self.object:get_pos() local pos = self.object:get_pos()
@ -185,44 +195,23 @@ minetest.register_entity("mcl_core:lava_spark", {
end end
}) })
--
-- Papyrus and cactus growing
--
-- Functions -- Functions
function mcl_core.grow_cactus(pos, node)
pos.y = pos.y-1
local name = minetest.get_node(pos).name
if minetest.get_item_group(name, "sand") ~= 0 then
pos.y = pos.y+1
local height = 0
while minetest.get_node(pos).name == "mcl_core:cactus" and height < 4 do
height = height+1
pos.y = pos.y+1
end
if height < 3 then
if minetest.get_node(pos).name == "air" then
minetest.set_node(pos, {name="mcl_core:cactus"})
end
end
end
end
function mcl_core.grow_reeds(pos, node) function mcl_core.grow_reeds(pos, node)
pos.y = pos.y-1 pos.y = pos.y-1
local name = minetest.get_node(pos).name local name = minetest_get_node(pos).name
if minetest.get_item_group(name, "soil_sugarcane") ~= 0 then if minetest_get_item_group(name, "soil_sugarcane") ~= 0 then
if minetest.find_node_near(pos, 1, {"group:water"}) == nil and minetest.find_node_near(pos, 1, {"group:frosted_ice"}) == nil then if minetest.find_node_near(pos, 1, {"group:water"}) == nil and minetest.find_node_near(pos, 1, {"group:frosted_ice"}) == nil then
return return
end end
pos.y = pos.y+1 pos.y = pos.y+1
local height = 0 local height = 0
while minetest.get_node(pos).name == "mcl_core:reeds" and height < 3 do while minetest_get_node(pos).name == "mcl_core:reeds" and height < 3 do
height = height+1 height = height+1
pos.y = pos.y+1 pos.y = pos.y+1
end end
if height < 3 then if height < 3 then
if minetest.get_node(pos).name == "air" then if minetest_get_node(pos).name == "air" then
minetest.set_node(pos, {name="mcl_core:reeds"}) minetest.set_node(pos, {name="mcl_core:reeds"})
end end
end end
@ -231,18 +220,17 @@ end
-- ABMs -- ABMs
local function drop_attached_node(p) local function drop_attached_node(p)
local nn = minetest.get_node(p).name local nn = minetest_get_node(p).name
if nn == "air" or nn == "ignore" then if nn == "air" or nn == "ignore" then
return return
end end
minetest.remove_node(p) minetest.remove_node(p)
for _, item in pairs(minetest.get_node_drops(nn, "")) do for _, item in pairs(minetest_get_node_drops(nn, "")) do
local pos = { local pos = {
x = p.x + math.random()/2 - 0.25, x = p.x + math_random()/2 - 0.25,
y = p.y + math.random()/2 - 0.25, y = p.y + math_random()/2 - 0.25,
z = p.z + math.random()/2 - 0.25, z = p.z + math_random()/2 - 0.25,
} }
if item ~= "" then if item ~= "" then
minetest.add_item(pos, item) minetest.add_item(pos, item)
@ -254,11 +242,11 @@ end
local function liquid_flow_action(pos, group, action) local function liquid_flow_action(pos, group, action)
local function check_detach(pos, xp, yp, zp) local function check_detach(pos, xp, yp, zp)
local p = {x=pos.x+xp, y=pos.y+yp, z=pos.z+zp} local p = {x=pos.x+xp, y=pos.y+yp, z=pos.z+zp}
local n = minetest.get_node_or_nil(p) local n = minetest_get_node_or_nil(p)
if not n then if not n then
return false return false
end end
local d = minetest.registered_nodes[n.name] local d = minetest_registered_nodes[n.name]
if not d then if not d then
return false return false
end end
@ -267,7 +255,7 @@ local function liquid_flow_action(pos, group, action)
* 2a: If target node is below liquid, always succeed * 2a: If target node is below liquid, always succeed
* 2b: If target node is horizontal to liquid: succeed if source, otherwise check param2 for horizontal flow direction ]] * 2b: If target node is horizontal to liquid: succeed if source, otherwise check param2 for horizontal flow direction ]]
local range = d.liquid_range or 8 local range = d.liquid_range or 8
if (minetest.get_item_group(n.name, group) ~= 0) and if (minetest_get_item_group(n.name, group) ~= 0) and
((yp > 0) or ((yp > 0) or
(yp == 0 and ((d.liquidtype == "source") or (n.param2 > (8-range) and n.param2 < 9)))) then (yp == 0 and ((d.liquidtype == "source") or (n.param2 > (8-range) and n.param2 < 9)))) then
action(pos) action(pos)
@ -316,17 +304,23 @@ minetest.register_abm({
end, end,
}) })
-- Cactus mechanisms local function cactus_grow(pos, node)
minetest.register_abm({ local pos = pos
label = "Cactus growth", local y = pos.y
nodenames = {"mcl_core:cactus"}, pos.y = y - 1
neighbors = {"group:sand"}, local name = minetest_get_node(pos).name
interval = 25, if minetest_get_item_group(name, "sand") == 0 then return end
chance = 10,
action = function(pos) for i = 1, 2 do
mcl_core.grow_cactus(pos) pos.y = y + i
end, name = minetest_get_node(pos).name
}) if name == "air" then
minetest.set_node(pos, {name = "mcl_core:cactus"})
return
end
if name ~= "mcl_core:cactus" then return end
end
end
minetest.register_abm({ minetest.register_abm({
label = "Cactus mechanisms", label = "Cactus mechanisms",
@ -334,39 +328,34 @@ minetest.register_abm({
interval = 1, interval = 1,
chance = 1, chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider) action = function(pos, node, active_object_count, active_object_count_wider)
for _, object in pairs(minetest.get_objects_inside_radius(pos, 0.9)) do local pos = pos
local x, y, z = pos.x, pos.y, pos.z
if minetest_registered_nodes[minetest_get_node({x = x + 1, y = y, z = z}).name].walkable
or minetest_registered_nodes[minetest_get_node({x = x - 1, y = y, z = z}).name].walkable
or minetest_registered_nodes[minetest_get_node({x = x, y = y, z = z + 1}).name].walkable
or minetest_registered_nodes[minetest_get_node({x = x, y = y, z = z - 1}).name].walkable
then
while minetest_get_node(pos).name == "mcl_core:cactus" do
minetest.remove_node(pos)
minetest.add_item(vector.offset(pos, math_random(-0.5, 0.5), 0, math_random(-0.5, 0.5)), "mcl_core:cactus")
pos.y = pos.y + 1
end
return
end
for _, object in pairs(minetest_get_objects_inside_radius(pos, 0.9)) do
local entity = object:get_luaentity() local entity = object:get_luaentity()
if entity then if entity then
local entity_name = entity.name local entity_name = entity.name
if entity_name == "__builtin:item" then if entity_name == "__builtin:item" then
object:remove() object:remove()
elseif entity_name == "mcl_minecarts:minecart" then
local pos = object:get_pos()
local driver = entity._driver
if driver then
mcl_player.player_attached[driver] = nil
local player = minetest.get_player_by_name(driver)
player:set_detach()
player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0})
mcl_player.player_set_animation(player, "stand" , 30)
end
minetest.add_item(pos, "mcl_minecarts:minecart")
object:remove()
end end
end end
end end
local posses = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } }
for _, p in pairs(posses) do for i = 1, mcl_time_get_number_of_times_at_pos(pos, 25, 10) do
if minetest.registered_nodes[minetest.get_node(vector.new(pos.x + p[1], pos.y, pos.z + p[2])).name].walkable then cactus_grow(pos)
local posy = pos.y
while minetest.get_node(vector.new(pos.x, posy, pos.z)).name == "mcl_core:cactus" do
local pos = vector.new(pos.x, posy, pos.z)
minetest.remove_node(pos)
minetest.add_item(vector.offset(pos, math.random(-0.5, 0.5), 0, math.random(-0.5, 0.5)), "mcl_core:cactus")
posy = posy + 1
end
break
end
end end
end, end,
}) })
@ -393,7 +382,7 @@ minetest.register_on_dignode(function(pos, node)
local i=1 local i=1
while timber_nodenames[i]~=nil do while timber_nodenames[i]~=nil do
local np={x=pos.x, y=pos.y+1, z=pos.z} local np={x=pos.x, y=pos.y+1, z=pos.z}
while minetest.get_node(np).name==timber_nodenames[i] do while minetest_get_node(np).name==timber_nodenames[i] do
minetest.remove_node(np) minetest.remove_node(np)
minetest.add_item(np, timber_nodenames[i]) minetest.add_item(np, timber_nodenames[i])
np={x=np.x, y=np.y+1, z=np.z} np={x=np.x, y=np.y+1, z=np.z}
@ -403,7 +392,7 @@ minetest.register_on_dignode(function(pos, node)
end) end)
local function air_leaf(leaftype) local function air_leaf(leaftype)
if math.random(0, 50) == 3 then if math_random(0, 50) == 3 then
return {name = "air"} return {name = "air"}
else else
return {name = leaftype} return {name = leaftype}
@ -417,7 +406,7 @@ local function node_stops_growth(node)
return false return false
end end
local def = minetest.registered_nodes[node.name] local def = minetest_registered_nodes[node.name]
if not def then if not def then
return true return true
end end
@ -450,7 +439,7 @@ local function check_growth_width(pos, width, height)
pos.x + x, pos.x + x,
pos.y + y, pos.y + y,
pos.z + z) pos.z + z)
if node_stops_growth(minetest.get_node(np)) then if node_stops_growth(minetest_get_node(np)) then
return false return false
end end
end end
@ -502,10 +491,10 @@ end
-- oak tree. -- oak tree.
function mcl_core.generate_tree(pos, tree_type, options) function mcl_core.generate_tree(pos, tree_type, options)
pos.y = pos.y-1 pos.y = pos.y-1
--local nodename = minetest.get_node(pos).name --local nodename = minetest_get_node(pos).name
pos.y = pos.y+1 pos.y = pos.y+1
if not minetest.get_node_light(pos) then if not minetest_get_node_light(pos) then
return return
end end
@ -558,7 +547,7 @@ function mcl_core.generate_v6_oak_tree(pos)
local node local node
for dy=1,4 do for dy=1,4 do
pos.y = pos.y+dy pos.y = pos.y+dy
if minetest.get_node(pos).name ~= "air" then if minetest_get_node(pos).name ~= "air" then
return return
end end
pos.y = pos.y-dy pos.y = pos.y-dy
@ -566,7 +555,7 @@ function mcl_core.generate_v6_oak_tree(pos)
node = {name = trunk} node = {name = trunk}
for dy=0,4 do for dy=0,4 do
pos.y = pos.y+dy pos.y = pos.y+dy
if minetest.get_node(pos).name == "air" then if minetest_get_node(pos).name == "air" then
minetest.add_node(pos, node) minetest.add_node(pos, node)
end end
pos.y = pos.y-dy pos.y = pos.y-dy
@ -575,7 +564,7 @@ function mcl_core.generate_v6_oak_tree(pos)
node = {name = leaves} node = {name = leaves}
pos.y = pos.y+3 pos.y = pos.y+3
--[[local rarity = 0 --[[local rarity = 0
if math.random(0, 10) == 3 then if math_random(0, 10) == 3 then
rarity = 1 rarity = 1
end]] end]]
for dx=-2,2 do for dx=-2,2 do
@ -586,23 +575,23 @@ function mcl_core.generate_v6_oak_tree(pos)
pos.z = pos.z+dz pos.z = pos.z+dz
if dx == 0 and dz == 0 and dy==3 then if dx == 0 and dz == 0 and dy==3 then
if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 4 then if minetest_get_node(pos).name == "air" and math_random(1, 5) <= 4 then
minetest.add_node(pos, node) minetest.add_node(pos, node)
minetest.add_node(pos, air_leaf(leaves)) minetest.add_node(pos, air_leaf(leaves))
end end
elseif dx == 0 and dz == 0 and dy==4 then elseif dx == 0 and dz == 0 and dy==4 then
if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 4 then if minetest_get_node(pos).name == "air" and math_random(1, 5) <= 4 then
minetest.add_node(pos, node) minetest.add_node(pos, node)
minetest.add_node(pos, air_leaf(leaves)) minetest.add_node(pos, air_leaf(leaves))
end end
elseif math.abs(dx) ~= 2 and math.abs(dz) ~= 2 then elseif math.abs(dx) ~= 2 and math.abs(dz) ~= 2 then
if minetest.get_node(pos).name == "air" then if minetest_get_node(pos).name == "air" then
minetest.add_node(pos, node) minetest.add_node(pos, node)
minetest.add_node(pos, air_leaf(leaves)) minetest.add_node(pos, air_leaf(leaves))
end end
else else
if math.abs(dx) ~= 2 or math.abs(dz) ~= 2 then if math.abs(dx) ~= 2 or math.abs(dz) ~= 2 then
if minetest.get_node(pos).name == "air" and math.random(1, 5) <= 4 then if minetest_get_node(pos).name == "air" and math_random(1, 5) <= 4 then
minetest.add_node(pos, node) minetest.add_node(pos, node)
minetest.add_node(pos, air_leaf(leaves)) minetest.add_node(pos, air_leaf(leaves))
end end
@ -620,14 +609,14 @@ end
function mcl_core.generate_balloon_oak_tree(pos) function mcl_core.generate_balloon_oak_tree(pos)
local path local path
local offset local offset
local s = math.random(1, 12) local s = math_random(1, 12)
if s == 1 then if s == 1 then
-- Small balloon oak -- Small balloon oak
path = modpath .. "/schematics/mcl_core_oak_balloon.mts" path = modpath .. "/schematics/mcl_core_oak_balloon.mts"
offset = { x = -2, y = -1, z = -2 } offset = { x = -2, y = -1, z = -2 }
else else
-- Large balloon oak -- Large balloon oak
local t = math.random(1, 4) local t = math_random(1, 4)
path = modpath .. "/schematics/mcl_core_oak_large_"..t..".mts" path = modpath .. "/schematics/mcl_core_oak_large_"..t..".mts"
if t == 1 or t == 3 then if t == 1 or t == 3 then
offset = { x = -3, y = -1, z = -3 } offset = { x = -3, y = -1, z = -3 }
@ -666,7 +655,7 @@ end
function mcl_core.generate_v6_spruce_tree(pos) function mcl_core.generate_v6_spruce_tree(pos)
local x, y, z = pos.x, pos.y, pos.z local x, y, z = pos.x, pos.y, pos.z
local maxy = y + math.random(9, 13) -- Trunk top local maxy = y + math_random(9, 13) -- Trunk top
local c_air = minetest.get_content_id("air") local c_air = minetest.get_content_id("air")
local c_ignore = minetest.get_content_id("ignore") local c_ignore = minetest.get_content_id("ignore")
@ -689,7 +678,7 @@ function mcl_core.generate_v6_spruce_tree(pos)
local vi = a:index(x - dev, yy, zz) local vi = a:index(x - dev, yy, zz)
local via = a:index(x - dev, yy + 1, zz) local via = a:index(x - dev, yy + 1, zz)
for xx = x - dev, x + dev do for xx = x - dev, x + dev do
if math.random() < 0.95 - dev * 0.05 then if math_random() < 0.95 - dev * 0.05 then
add_spruce_leaves(data, vi, c_air, c_ignore, c_snow, add_spruce_leaves(data, vi, c_air, c_ignore, c_snow,
c_spruce_leaves) c_spruce_leaves)
end end
@ -709,9 +698,9 @@ function mcl_core.generate_v6_spruce_tree(pos)
-- Lower branches layer -- Lower branches layer
local my = 0 local my = 0
for i = 1, 20 do -- Random 2x2 squares of leaves for i = 1, 20 do -- Random 2x2 squares of leaves
local xi = x + math.random(-3, 2) local xi = x + math_random(-3, 2)
local yy = maxy + math.random(-6, -5) local yy = maxy + math_random(-6, -5)
local zi = z + math.random(-3, 2) local zi = z + math_random(-3, 2)
if yy > my then if yy > my then
my = yy my = yy
end end
@ -733,7 +722,7 @@ function mcl_core.generate_v6_spruce_tree(pos)
local vi = a:index(x - dev, yy, zz) local vi = a:index(x - dev, yy, zz)
local via = a:index(x - dev, yy + 1, zz) local via = a:index(x - dev, yy + 1, zz)
for xx = x - dev, x + dev do for xx = x - dev, x + dev do
if math.random() < 0.95 - dev * 0.05 then if math_random() < 0.95 - dev * 0.05 then
add_spruce_leaves(data, vi, c_air, c_ignore, c_snow, add_spruce_leaves(data, vi, c_air, c_ignore, c_snow,
c_spruce_leaves) c_spruce_leaves)
end end
@ -761,14 +750,14 @@ function mcl_core.generate_v6_spruce_tree(pos)
end end
function mcl_core.generate_spruce_tree(pos) function mcl_core.generate_spruce_tree(pos)
local r = math.random(1, 3) local r = math_random(1, 3)
local path = modpath .. "/schematics/mcl_core_spruce_"..r..".mts" local path = modpath .. "/schematics/mcl_core_spruce_"..r..".mts"
minetest.place_schematic({ x = pos.x - 3, y = pos.y - 1, z = pos.z - 3 }, path, "0", nil, false) minetest.place_schematic({ x = pos.x - 3, y = pos.y - 1, z = pos.z - 3 }, path, "0", nil, false)
end end
function mcl_core.generate_huge_spruce_tree(pos) function mcl_core.generate_huge_spruce_tree(pos)
local r1 = math.random(1, 2) local r1 = math_random(1, 2)
local r2 = math.random(1, 4) local r2 = math_random(1, 4)
local path local path
local offset = { x = -4, y = -1, z = -5 } local offset = { x = -4, y = -1, z = -5 }
if r1 <= 2 then if r1 <= 2 then
@ -788,7 +777,7 @@ end
-- Acacia tree (multiple variants) -- Acacia tree (multiple variants)
function mcl_core.generate_acacia_tree(pos) function mcl_core.generate_acacia_tree(pos)
local r = math.random(1, 7) local r = math_random(1, 7)
local offset = vector.new() local offset = vector.new()
if r == 2 or r == 3 then if r == 2 or r == 3 then
offset = { x = -4, y = -1, z = -4 } offset = { x = -4, y = -1, z = -4 }
@ -840,9 +829,9 @@ local function add_trunk_and_leaves(data, a, pos, tree_cid, leaves_cid,
-- Randomly add leaves in 2x2x2 clusters. -- Randomly add leaves in 2x2x2 clusters.
for i = 1, iters do for i = 1, iters do
local clust_x = x + math.random(-size, size - 1) local clust_x = x + math_random(-size, size - 1)
local clust_y = y + height + math.random(-size, 0) local clust_y = y + height + math_random(-size, 0)
local clust_z = z + math.random(-size, size - 1) local clust_z = z + math_random(-size, size - 1)
for xi = 0, 1 do for xi = 0, 1 do
for yi = 0, 1 do for yi = 0, 1 do
@ -866,7 +855,7 @@ function mcl_core.generate_v6_jungle_tree(pos)
--]] --]]
local x, y, z = pos.x, pos.y, pos.z local x, y, z = pos.x, pos.y, pos.z
local height = math.random(8, 12) local height = math_random(8, 12)
local c_air = minetest.get_content_id("air") local c_air = minetest.get_content_id("air")
local c_ignore = minetest.get_content_id("ignore") local c_ignore = minetest.get_content_id("ignore")
local c_jungletree = minetest.get_content_id("mcl_core:jungletree") local c_jungletree = minetest.get_content_id("mcl_core:jungletree")
@ -887,7 +876,7 @@ function mcl_core.generate_v6_jungle_tree(pos)
local vi_1 = a:index(x - 1, y - 1, z + z_dist) local vi_1 = a:index(x - 1, y - 1, z + z_dist)
local vi_2 = a:index(x - 1, y, z + z_dist) local vi_2 = a:index(x - 1, y, z + z_dist)
for x_dist = -1, 1 do for x_dist = -1, 1 do
if math.random(1, 3) >= 2 then if math_random(1, 3) >= 2 then
if data[vi_1] == c_air or data[vi_1] == c_ignore then if data[vi_1] == c_air or data[vi_1] == c_ignore then
data[vi_1] = c_jungletree data[vi_1] = c_jungletree
elseif data[vi_2] == c_air or data[vi_2] == c_ignore then elseif data[vi_2] == c_air or data[vi_2] == c_ignore then
@ -912,7 +901,7 @@ end
-- With pos being the lower X and the higher Z value of the trunk. -- With pos being the lower X and the higher Z value of the trunk.
function mcl_core.generate_huge_jungle_tree(pos) function mcl_core.generate_huge_jungle_tree(pos)
-- 2 variants -- 2 variants
local r = math.random(1, 2) local r = math_random(1, 2)
local path = modpath.."/schematics/mcl_core_jungle_tree_huge_"..r..".mts" local path = modpath.."/schematics/mcl_core_jungle_tree_huge_"..r..".mts"
minetest.place_schematic({x = pos.x - 6, y = pos.y - 1, z = pos.z - 7}, path, "random", nil, false) minetest.place_schematic({x = pos.x - 6, y = pos.y - 1, z = pos.z - 7}, path, "random", nil, false)
end end
@ -954,12 +943,12 @@ minetest.register_abm({
return return
end end
local above = {x=pos.x, y=pos.y+1, z=pos.z} local above = {x=pos.x, y=pos.y+1, z=pos.z}
local abovenode = minetest.get_node(above) local abovenode = minetest_get_node(above)
if minetest.get_item_group(abovenode.name, "liquid") ~= 0 or minetest.get_item_group(abovenode.name, "opaque") == 1 then if minetest_get_item_group(abovenode.name, "liquid") ~= 0 or minetest_get_item_group(abovenode.name, "opaque") == 1 then
-- Never grow directly below liquids or opaque blocks -- Never grow directly below liquids or opaque blocks
return return
end end
local light_self = minetest.get_node_light(above) local light_self = minetest_get_node_light(above)
if not light_self then return end if not light_self then return end
--[[ Try to find a spreading dirt-type block (e.g. grass block or mycelium) --[[ Try to find a spreading dirt-type block (e.g. grass block or mycelium)
within a 3×5×3 area, with the source block being on the 2nd-topmost layer. ]] within a 3×5×3 area, with the source block being on the 2nd-topmost layer. ]]
@ -974,20 +963,20 @@ minetest.register_abm({
-- Found it! Now check light levels! -- Found it! Now check light levels!
local source_above = {x=p2.x, y=p2.y+1, z=p2.z} local source_above = {x=p2.x, y=p2.y+1, z=p2.z}
local light_source = minetest.get_node_light(source_above) local light_source = minetest_get_node_light(source_above)
if not light_source then return end if not light_source then return end
if light_self >= 4 and light_source >= 9 then if light_self >= 4 and light_source >= 9 then
-- All checks passed! Let's spread the grass/mycelium! -- All checks passed! Let's spread the grass/mycelium!
local n2 = minetest.get_node(p2) local n2 = minetest_get_node(p2)
if minetest.get_item_group(n2.name, "grass_block") ~= 0 then if minetest_get_item_group(n2.name, "grass_block") ~= 0 then
n2 = mcl_core.get_grass_block_type(pos) n2 = mcl_core.get_grass_block_type(pos)
end end
minetest.set_node(pos, {name=n2.name}) minetest.set_node(pos, {name=n2.name})
-- If this was mycelium, uproot plant above -- If this was mycelium, uproot plant above
if n2.name == "mcl_core:mycelium" then if n2.name == "mcl_core:mycelium" then
local tad = minetest.registered_nodes[minetest.get_node(above).name] local tad = minetest_registered_nodes[minetest_get_node(above).name]
if tad.groups and tad.groups.non_mycelium_plant then if tad.groups and tad.groups.non_mycelium_plant then
minetest.dig_node(above) minetest.dig_node(above)
end end
@ -1005,9 +994,9 @@ minetest.register_abm({
catch_up = false, catch_up = false,
action = function(pos, node) action = function(pos, node)
local above = {x = pos.x, y = pos.y + 1, z = pos.z} local above = {x = pos.x, y = pos.y + 1, z = pos.z}
local name = minetest.get_node(above).name local name = minetest_get_node(above).name
-- Kill grass/mycelium when below opaque block or liquid -- Kill grass/mycelium when below opaque block or liquid
if name ~= "ignore" and (minetest.get_item_group(name, "opaque") == 1 or minetest.get_item_group(name, "liquid") ~= 0) then if name ~= "ignore" and (minetest_get_item_group(name, "opaque") == 1 or minetest_get_item_group(name, "liquid") ~= 0) then
minetest.set_node(pos, {name = "mcl_core:dirt"}) minetest.set_node(pos, {name = "mcl_core:dirt"})
end end
end end
@ -1015,11 +1004,11 @@ minetest.register_abm({
-- Turn Grass Path and similar nodes to Dirt if a solid node is placed above it -- Turn Grass Path and similar nodes to Dirt if a solid node is placed above it
minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing) minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
if minetest.get_item_group(newnode.name, "solid") ~= 0 or if minetest_get_item_group(newnode.name, "solid") ~= 0 or
minetest.get_item_group(newnode.name, "dirtifier") ~= 0 then minetest_get_item_group(newnode.name, "dirtifier") ~= 0 then
local below = {x=pos.x, y=pos.y-1, z=pos.z} local below = {x=pos.x, y=pos.y-1, z=pos.z}
local belownode = minetest.get_node(below) local belownode = minetest_get_node(below)
if minetest.get_item_group(belownode.name, "dirtifies_below_solid") == 1 then if minetest_get_item_group(belownode.name, "dirtifies_below_solid") == 1 then
minetest.set_node(below, {name="mcl_core:dirt"}) minetest.set_node(below, {name="mcl_core:dirt"})
end end
end end
@ -1033,8 +1022,8 @@ minetest.register_abm({
chance = 50, chance = 50,
action = function(pos, node) action = function(pos, node)
local above = {x = pos.x, y = pos.y + 1, z = pos.z} local above = {x = pos.x, y = pos.y + 1, z = pos.z}
local name = minetest.get_node(above).name local name = minetest_get_node(above).name
local nodedef = minetest.registered_nodes[name] local nodedef = minetest_registered_nodes[name]
if name ~= "ignore" and nodedef and (nodedef.groups and nodedef.groups.solid) then if name ~= "ignore" and nodedef and (nodedef.groups and nodedef.groups.solid) then
minetest.set_node(pos, {name = "mcl_core:dirt"}) minetest.set_node(pos, {name = "mcl_core:dirt"})
end end
@ -1083,7 +1072,7 @@ local function sapling_grow_action(tree_id, soil_needed, one_by_one, two_by_two,
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
if meta:get("grown") then return end if meta:get("grown") then return end
-- Checks if the sapling at pos has enough light and the correct soil -- Checks if the sapling at pos has enough light and the correct soil
local light = minetest.get_node_light(pos) local light = minetest_get_node_light(pos)
if not light then return end if not light then return end
local low_light = (light < treelight) local low_light = (light < treelight)
@ -1101,13 +1090,13 @@ local function sapling_grow_action(tree_id, soil_needed, one_by_one, two_by_two,
if low_light then if low_light then
if delta < 1.2 then return end if delta < 1.2 then return end
if minetest.get_node_light(pos, 0.5) < treelight then return end if minetest_get_node_light(pos, 0.5) < treelight then return end
end end
-- TODO: delta is [days] missed in inactive area. Currently we just add it to stage, which is far from a perfect calculation... -- TODO: delta is [days] missed in inactive area. Currently we just add it to stage, which is far from a perfect calculation...
local soilnode = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}) local soilnode = minetest_get_node({x=pos.x, y=pos.y-1, z=pos.z})
local soiltype = minetest.get_item_group(soilnode.name, "soil_sapling") local soiltype = minetest_get_item_group(soilnode.name, "soil_sapling")
if soiltype < soil_needed then return end if soiltype < soil_needed then return end
-- Increase and check growth stage -- Increase and check growth stage
@ -1121,7 +1110,7 @@ local function sapling_grow_action(tree_id, soil_needed, one_by_one, two_by_two,
if two_by_two then if two_by_two then
-- Check 8 surrounding saplings and try to find a 2×2 pattern -- Check 8 surrounding saplings and try to find a 2×2 pattern
local function is_sapling(pos, sapling) local function is_sapling(pos, sapling)
return minetest.get_node(pos).name == sapling return minetest_get_node(pos).name == sapling
end end
local p2 = {x=pos.x+1, y=pos.y, z=pos.z} local p2 = {x=pos.x+1, y=pos.y, z=pos.z}
local p3 = {x=pos.x, y=pos.y, z=pos.z-1} local p3 = {x=pos.x, y=pos.y, z=pos.z-1}
@ -1173,7 +1162,7 @@ local function sapling_grow_action(tree_id, soil_needed, one_by_one, two_by_two,
end end
if one_by_one and tree_id == OAK_TREE_ID then if one_by_one and tree_id == OAK_TREE_ID then
-- There is a chance that this tree wants to grow as a balloon oak -- There is a chance that this tree wants to grow as a balloon oak
if math.random(1, 12) == 1 then if math_random(1, 12) == 1 then
-- Check if there is room for that -- Check if there is room for that
if check_tree_growth(pos, tree_id, { balloon = true }) then if check_tree_growth(pos, tree_id, { balloon = true }) then
minetest.set_node(pos, {name="air"}) minetest.set_node(pos, {name="air"})
@ -1186,7 +1175,7 @@ local function sapling_grow_action(tree_id, soil_needed, one_by_one, two_by_two,
if one_by_one and check_tree_growth(pos, tree_id) then if one_by_one and check_tree_growth(pos, tree_id) then
-- Single sapling -- Single sapling
minetest.set_node(pos, {name="air"}) minetest.set_node(pos, {name="air"})
--local r = math.random(1, 12) --local r = math_random(1, 12)
mcl_core.generate_tree(pos, tree_id) mcl_core.generate_tree(pos, tree_id)
return return
end end
@ -1205,7 +1194,7 @@ local grow_birch = sapling_grow_action(BIRCH_TREE_ID, 1, true, false)
-- Attempts to grow the sapling at the specified position -- Attempts to grow the sapling at the specified position
-- pos: Position -- pos: Position
-- node: Node table of the node at this position, from minetest.get_node -- node: Node table of the node at this position, from minetest_get_node
-- Returns true on success and false on failure -- Returns true on success and false on failure
function mcl_core.grow_sapling(pos, node) function mcl_core.grow_sapling(pos, node)
local grow local grow
@ -1337,7 +1326,7 @@ minetest.register_lbm({
local function leafdecay_particles(pos, node) local function leafdecay_particles(pos, node)
minetest.add_particlespawner({ minetest.add_particlespawner({
amount = math.random(10, 20), amount = math_random(10, 20),
time = 0.1, time = 0.1,
minpos = vector.add(pos, {x=-0.4, y=-0.4, z=-0.4}), minpos = vector.add(pos, {x=-0.4, y=-0.4, z=-0.4}),
maxpos = vector.add(pos, {x=0.4, y=0.4, z=0.4}), maxpos = vector.add(pos, {x=0.4, y=0.4, z=0.4}),
@ -1375,7 +1364,7 @@ local function vinedecay_particles(pos, node)
end end
minetest.add_particlespawner({ minetest.add_particlespawner({
amount = math.random(8, 16), amount = math_random(8, 16),
time = 0.1, time = 0.1,
minpos = vector.add(pos, relpos1), minpos = vector.add(pos, relpos1),
maxpos = vector.add(pos, relpos2), maxpos = vector.add(pos, relpos2),
@ -1413,8 +1402,8 @@ minetest.register_abm({
-- Add vines below pos (if empty) -- Add vines below pos (if empty)
local function spread_down(origin, target, dir, node) local function spread_down(origin, target, dir, node)
if math.random(1, 2) == 1 then if math_random(1, 2) == 1 then
if minetest.get_node(target).name == "air" then if minetest_get_node(target).name == "air" then
minetest.add_node(target, {name = "mcl_core:vine", param2 = node.param2}) minetest.add_node(target, {name = "mcl_core:vine", param2 = node.param2})
end end
end end
@ -1425,11 +1414,11 @@ minetest.register_abm({
local vines_in_area = minetest.find_nodes_in_area({x=origin.x-4, y=origin.y-1, z=origin.z-4}, {x=origin.x+4, y=origin.y+1, z=origin.z+4}, "mcl_core:vine") local vines_in_area = minetest.find_nodes_in_area({x=origin.x-4, y=origin.y-1, z=origin.z-4}, {x=origin.x+4, y=origin.y+1, z=origin.z+4}, "mcl_core:vine")
-- Less then 4 vines blocks around the ticked vines block (remember the ticked block is counted by above function as well) -- Less then 4 vines blocks around the ticked vines block (remember the ticked block is counted by above function as well)
if #vines_in_area < 5 then if #vines_in_area < 5 then
if math.random(1, 2) == 1 then if math_random(1, 2) == 1 then
if minetest.get_node(target).name == "air" then if minetest_get_node(target).name == "air" then
local backup_dir = minetest.wallmounted_to_dir(node.param2) local backup_dir = minetest.wallmounted_to_dir(node.param2)
local backup = vector.subtract(target, backup_dir) local backup = vector.subtract(target, backup_dir)
local backupnodename = minetest.get_node(backup).name local backupnodename = minetest_get_node(backup).name
-- Check if the block above is supported -- Check if the block above is supported
if mcl_core.supports_vines(backupnodename) then if mcl_core.supports_vines(backupnodename) then
@ -1447,10 +1436,10 @@ minetest.register_abm({
-- Spread horizontally -- Spread horizontally
local backup_dir = minetest.wallmounted_to_dir(node.param2) local backup_dir = minetest.wallmounted_to_dir(node.param2)
if not vector.equals(backup_dir, dir) then if not vector.equals(backup_dir, dir) then
local target_node = minetest.get_node(target) local target_node = minetest_get_node(target)
if target_node.name == "air" then if target_node.name == "air" then
local backup = vector.add(target, backup_dir) local backup = vector.add(target, backup_dir)
local backupnodename = minetest.get_node(backup).name local backupnodename = minetest_get_node(backup).name
if mcl_core.supports_vines(backupnodename) then if mcl_core.supports_vines(backupnodename) then
minetest.add_node(target, {name = "mcl_core:vine", param2 = node.param2}) minetest.add_node(target, {name = "mcl_core:vine", param2 = node.param2})
end end
@ -1468,7 +1457,7 @@ minetest.register_abm({
{ { x= 0, y= 0, z=-1 }, spread_horizontal }, { { x= 0, y= 0, z=-1 }, spread_horizontal },
} }
local d = math.random(1, #directions) local d = math_random(1, #directions)
local dir = directions[d][1] local dir = directions[d][1]
local spread = directions[d][2] local spread = directions[d][2]
@ -1478,7 +1467,7 @@ minetest.register_abm({
-- Returns true of the node supports vines -- Returns true of the node supports vines
function mcl_core.supports_vines(nodename) function mcl_core.supports_vines(nodename)
local def = minetest.registered_nodes[nodename] local def = minetest_registered_nodes[nodename]
-- Rules: 1) walkable 2) full cube -- Rules: 1) walkable 2) full cube
return def.walkable and return def.walkable and
(def.node_box == nil or def.node_box.type == "regular") and (def.node_box == nil or def.node_box.type == "regular") and
@ -1516,11 +1505,11 @@ minetest.register_abm({
action = function(p0, node, _, _) action = function(p0, node, _, _)
local do_preserve = false local do_preserve = false
local d = minetest.registered_nodes[node.name].groups.leafdecay local d = minetest_registered_nodes[node.name].groups.leafdecay
if not d or d == 0 then if not d or d == 0 then
return return
end end
local n0 = minetest.get_node(p0) local n0 = minetest_get_node(p0)
if n0.param2 ~= 0 then if n0.param2 ~= 0 then
-- Prevent leafdecay for player-placed leaves. -- Prevent leafdecay for player-placed leaves.
-- param2 is set to 1 after it was placed by the player -- param2 is set to 1 after it was placed by the player
@ -1531,8 +1520,8 @@ minetest.register_abm({
p0_hash = minetest.hash_node_position(p0) p0_hash = minetest.hash_node_position(p0)
local trunkp = mcl_core.leafdecay_trunk_cache[p0_hash] local trunkp = mcl_core.leafdecay_trunk_cache[p0_hash]
if trunkp then if trunkp then
local n = minetest.get_node(trunkp) local n = minetest_get_node(trunkp)
local reg = minetest.registered_nodes[n.name] local reg = minetest_registered_nodes[n.name]
-- Assume ignore is a trunk, to make the thing work at the border of the active area -- Assume ignore is a trunk, to make the thing work at the border of the active area
if n.name == "ignore" or (reg and reg.groups.tree and reg.groups.tree ~= 0) then if n.name == "ignore" or (reg and reg.groups.tree and reg.groups.tree ~= 0) then
return return
@ -1557,12 +1546,12 @@ minetest.register_abm({
end end
if not do_preserve then if not do_preserve then
-- Drop stuff other than the node itself -- Drop stuff other than the node itself
local itemstacks = minetest.get_node_drops(n0.name) local itemstacks = minetest_get_node_drops(n0.name)
for _, itemname in pairs(itemstacks) do for _, itemname in pairs(itemstacks) do
local p_drop = { local p_drop = {
x = p0.x - 0.5 + math.random(), x = p0.x - 0.5 + math_random(),
y = p0.y - 0.5 + math.random(), y = p0.y - 0.5 + math_random(),
z = p0.z - 0.5 + math.random(), z = p0.z - 0.5 + math_random(),
} }
minetest.add_item(p_drop, itemname) minetest.add_item(p_drop, itemname)
end end
@ -1581,7 +1570,7 @@ minetest.register_abm({
} }
for s=1, #surround do for s=1, #surround do
local spos = vector.add(p0, surround[s]) local spos = vector.add(p0, surround[s])
local maybe_vine = minetest.get_node(spos) local maybe_vine = minetest_get_node(spos)
--local surround_inverse = vector.multiply(surround[s], -1) --local surround_inverse = vector.multiply(surround[s], -1)
if maybe_vine.name == "mcl_core:vine" and (not mcl_core.check_vines_supported(spos, maybe_vine)) then if maybe_vine.name == "mcl_core:vine" and (not mcl_core.check_vines_supported(spos, maybe_vine)) then
minetest.remove_node(spos) minetest.remove_node(spos)
@ -1622,7 +1611,7 @@ minetest.register_abm({
interval = 16, interval = 16,
chance = 8, chance = 8,
action = function(pos, node) action = function(pos, node)
if minetest.get_node_light(pos, 0) >= 12 then if minetest_get_node_light(pos, 0) >= 12 then
if node.name == "mcl_core:ice" then if node.name == "mcl_core:ice" then
mcl_core.melt_ice(pos) mcl_core.melt_ice(pos)
else else
@ -1640,7 +1629,7 @@ function mcl_core.check_vines_supported(pos, node)
local supported = false local supported = false
local dir = minetest.wallmounted_to_dir(node.param2) local dir = minetest.wallmounted_to_dir(node.param2)
local pos1 = vector.add(pos, dir) local pos1 = vector.add(pos, dir)
local node_neighbor = minetest.get_node(pos1) local node_neighbor = minetest_get_node(pos1)
-- Check if vines are attached to a solid block. -- Check if vines are attached to a solid block.
-- If ignore, we assume its solid. -- If ignore, we assume its solid.
if node_neighbor.name == "ignore" or mcl_core.supports_vines(node_neighbor.name) then if node_neighbor.name == "ignore" or mcl_core.supports_vines(node_neighbor.name) then
@ -1649,7 +1638,7 @@ function mcl_core.check_vines_supported(pos, node)
-- Vines are not attached, now we check if the vines are “hanging” below another vines block -- Vines are not attached, now we check if the vines are “hanging” below another vines block
-- of equal orientation. -- of equal orientation.
local pos2 = vector.add(pos, {x=0, y=1, z=0}) local pos2 = vector.add(pos, {x=0, y=1, z=0})
local node2 = minetest.get_node(pos2) local node2 = minetest_get_node(pos2)
-- Again, ignore means we assume its supported -- Again, ignore means we assume its supported
if node2.name == "ignore" or (node2.name == "mcl_core:vine" and node2.param2 == node.param2) then if node2.name == "ignore" or (node2.name == "mcl_core:vine" and node2.param2 == node.param2) then
supported = true supported = true
@ -1662,7 +1651,7 @@ end
function mcl_core.melt_ice(pos) function mcl_core.melt_ice(pos)
-- Create a water source if ice is destroyed and there was something below it -- Create a water source if ice is destroyed and there was something below it
local below = {x=pos.x, y=pos.y-1, z=pos.z} local below = {x=pos.x, y=pos.y-1, z=pos.z}
local belownode = minetest.get_node(below) local belownode = minetest_get_node(below)
local dim = mcl_worlds.pos_to_dimension(below) local dim = mcl_worlds.pos_to_dimension(below)
if dim ~= "nether" and belownode.name ~= "air" and belownode.name ~= "ignore" and belownode.name ~= "mcl_core:void" then if dim ~= "nether" and belownode.name ~= "air" and belownode.name ~= "ignore" and belownode.name ~= "mcl_core:void" then
minetest.set_node(pos, {name="mcl_core:water_source"}) minetest.set_node(pos, {name="mcl_core:water_source"})
@ -1697,7 +1686,7 @@ end
-- The snowable nodes also MUST have _mcl_snowed defined to contain the name -- The snowable nodes also MUST have _mcl_snowed defined to contain the name
-- of the snowed node. -- of the snowed node.
function mcl_core.register_snowed_node(itemstring_snowed, itemstring_clear, tiles, sounds, clear_colorization, desc) function mcl_core.register_snowed_node(itemstring_snowed, itemstring_clear, tiles, sounds, clear_colorization, desc)
local def = table.copy(minetest.registered_nodes[itemstring_clear]) local def = table.copy(minetest_registered_nodes[itemstring_clear])
local create_doc_alias local create_doc_alias
if def.description then if def.description then
create_doc_alias = true create_doc_alias = true
@ -1760,7 +1749,7 @@ end
-- This function assumes there is no snow cover node above. This function -- This function assumes there is no snow cover node above. This function
-- MUST NOT be called if there is a snow cover node above pos. -- MUST NOT be called if there is a snow cover node above pos.
function mcl_core.clear_snow_dirt(pos, node) function mcl_core.clear_snow_dirt(pos, node)
local def = minetest.registered_nodes[node.name] local def = minetest_registered_nodes[node.name]
if def._mcl_snowless then if def._mcl_snowless then
minetest.swap_node(pos, {name = def._mcl_snowless, param2=node.param2}) minetest.swap_node(pos, {name = def._mcl_snowless, param2=node.param2})
end end
@ -1773,15 +1762,15 @@ end
-- Makes constructed snowable node snowed if placed below a snow cover node. -- Makes constructed snowable node snowed if placed below a snow cover node.
function mcl_core.on_snowable_construct(pos) function mcl_core.on_snowable_construct(pos)
-- Myself -- Myself
local node = minetest.get_node(pos) local node = minetest_get_node(pos)
-- Above -- Above
local apos = {x=pos.x, y=pos.y+1, z=pos.z} local apos = {x=pos.x, y=pos.y+1, z=pos.z}
local anode = minetest.get_node(apos) local anode = minetest_get_node(apos)
-- Make snowed if needed -- Make snowed if needed
if minetest.get_item_group(anode.name, "snow_cover") == 1 then if minetest_get_item_group(anode.name, "snow_cover") == 1 then
local def = minetest.registered_nodes[node.name] local def = minetest_registered_nodes[node.name]
if def._mcl_snowed then if def._mcl_snowed then
minetest.swap_node(pos, {name = def._mcl_snowed, param2=node.param2}) minetest.swap_node(pos, {name = def._mcl_snowed, param2=node.param2})
end end
@ -1801,8 +1790,8 @@ end
-- Makes snowable node below snowed. -- Makes snowable node below snowed.
function mcl_core.on_snow_construct(pos) function mcl_core.on_snow_construct(pos)
local npos = {x=pos.x, y=pos.y-1, z=pos.z} local npos = {x=pos.x, y=pos.y-1, z=pos.z}
local node = minetest.get_node(npos) local node = minetest_get_node(npos)
local def = minetest.registered_nodes[node.name] local def = minetest_registered_nodes[node.name]
if def._mcl_snowed then if def._mcl_snowed then
minetest.swap_node(npos, {name = def._mcl_snowed, param2=node.param2}) minetest.swap_node(npos, {name = def._mcl_snowed, param2=node.param2})
end end
@ -1810,13 +1799,13 @@ end
-- after_destruct -- after_destruct
-- Clears snowed dirtlike node below. -- Clears snowed dirtlike node below.
function mcl_core.after_snow_destruct(pos) function mcl_core.after_snow_destruct(pos)
local nn = minetest.get_node(pos).name local nn = minetest_get_node(pos).name
-- No-op if snow was replaced with snow -- No-op if snow was replaced with snow
if minetest.get_item_group(nn, "snow_cover") == 1 then if minetest_get_item_group(nn, "snow_cover") == 1 then
return return
end end
local npos = {x=pos.x, y=pos.y-1, z=pos.z} local npos = {x=pos.x, y=pos.y-1, z=pos.z}
local node = minetest.get_node(npos) local node = minetest_get_node(npos)
mcl_core.clear_snow_dirt(npos, node) mcl_core.clear_snow_dirt(npos, node)
end end

View File

@ -1,4 +1,4 @@
name = mcl_core name = mcl_core
description = Core items of MineClone 2: Basic biome blocks (dirt, sand, stones, etc.), derived items, glass, sugar cane, cactus, barrier, mining tools, hand, craftitems, and misc. items which don't really fit anywhere else. description = Core items of MineClone 2: Basic biome blocks (dirt, sand, stones, etc.), derived items, glass, sugar cane, cactus, barrier, mining tools, hand, craftitems, and misc. items which don't really fit anywhere else.
depends = mcl_autogroup, mcl_init, mcl_sounds, mcl_particles, mcl_util, mcl_worlds, doc_items, mcl_enchanting, mcl_colors, mcl_mapgen depends = mcl_autogroup, mcl_init, mcl_sounds, mcl_particles, mcl_util, mcl_worlds, doc_items, mcl_enchanting, mcl_colors, mcl_mapgen, mcl_time
optional_depends = doc optional_depends = doc

View File

@ -11,7 +11,23 @@ else
ice_drawtype = "normal" ice_drawtype = "normal"
ice_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false ice_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false
end end
local mossnodes = {"mcl_core:stone", "mcl_core:granite", "mcl_core:granite_smooth", "mcl_core:diorite", "mcl_core:diorite_smooth", "mcl_core:andesite", "mcl_core:andesite_smooth", "mcl_deepslate:deepslate", --[[glowberries, ]]"mcl_core:dirt", "mcl_core:dirt_with_grass", "mcl_core:podzol", "mcl_core:coarse_dirt", "mcl_core:mycelium"}
local moss_nodes = {
"mcl_core:stone",
"mcl_core:granite",
"mcl_core:granite_smooth",
"mcl_core:diorite",
"mcl_core:diorite_smooth",
"mcl_core:andesite",
"mcl_core:andesite_smooth",
"mcl_deepslate:deepslate",
--[[glowberries, ]]
"mcl_core:dirt",
"mcl_core:dirt_with_grass",
"mcl_core:podzol",
"mcl_core:coarse_dirt",
"mcl_core:mycelium",
}
mcl_core.fortune_drop_ore = { mcl_core.fortune_drop_ore = {
discrete_uniform_distribution = true, discrete_uniform_distribution = true,
@ -1089,7 +1105,9 @@ minetest.register_node("mcl_core:snowblock", {
_mcl_silk_touch_drop = true, _mcl_silk_touch_drop = true,
}) })
minetest.register_node("mcl_core:moss", { local MOSS_ITEMSTRING = "mcl_core:moss"
local MOSS_NODE = {name = MOSS_ITEMSTRING}
minetest.register_node(MOSS_ITEMSTRING, {
description = S("Moss"), description = S("Moss"),
_doc_items_longdesc = S("A moss block is a natural block that can be spread to some other blocks by using bone meal."),--TODO: Other desciption? _doc_items_longdesc = S("A moss block is a natural block that can be spread to some other blocks by using bone meal."),--TODO: Other desciption?
_doc_items_hidden = false, _doc_items_hidden = false,
@ -1101,41 +1119,41 @@ minetest.register_node("mcl_core:moss", {
_mcl_blast_resistance = 0.1, _mcl_blast_resistance = 0.1,
_mcl_hardness = 0.1, _mcl_hardness = 0.1,
on_rightclick = function(pos, node, player, itemstack, pointed_thing) on_rightclick = function(pos, node, player, itemstack, pointed_thing)
if player:get_wielded_item():get_name() == "mcl_dye:white" then local pos = pos
if not minetest.is_creative_enabled(player) and not minetest.check_player_privs(player, "creative") then local x, y, z = pos.x, pos.y, pos.z
itemstack:take_item() local player_wielded_item = player:get_wielded_item()
end local item_name = player_wielded_item:get_name()
if item_name == "mcl_dye:white" then
for i, j in pairs(minetest.find_nodes_in_area_under_air({x = pos.x-1, y = pos.y-1, z = pos.z-1}, {x = pos.x+1, y = pos.y+1, z = pos.z+1}, mossnodes)) do if not minetest.is_creative_enabled(player) then
minetest.set_node(j, {name="mcl_core:moss"})
end
for i, j in pairs(minetest.find_nodes_in_area_under_air({x = pos.x-2, y = pos.y-1, z = pos.z-2}, {x = pos.x+2, y = pos.y+1, z = pos.z+2}, mossnodes)) do
if math.random(1,3) == 1 then minetest.set_node(j, {name="mcl_core:moss"}) end
end
for i, j in pairs(minetest.find_nodes_in_area_under_air({x = pos.x-3, y = pos.y-1, z = pos.z-3}, {x = pos.x+3, y = pos.y+1, z = pos.z+3}, mossnodes)) do
if math.random(1,9) == 1 then minetest.set_node(j, {name="mcl_core:moss"}) end
end
for i, j in pairs(minetest.find_nodes_in_area_under_air({x = pos.x-3, y = pos.y-1, z = pos.z-3}, {x = pos.x+3, y = pos.y+1, z = pos.z+3}, {"mcl_core:moss"})) do
if math.random(1,2) == 1 then
minetest.set_node({x=j.x,y=j.y+1,z=j.z} ,{name="mcl_flowers:tallgrass"})
end
end
for i, j in pairs(minetest.find_nodes_in_area_under_air({x = pos.x-3, y = pos.y-1, z = pos.z-3}, {x = pos.x+3, y = pos.y+1, z = pos.z+3}, {"mcl_core:moss"})) do
if math.random(1,4) == 1 then
minetest.set_node({x=j.x,y=j.y+1,z=j.z}, {name="mcl_core:moss_carpet"})
end
end
for i, j in pairs(minetest.find_nodes_in_area_under_air({x = pos.x-3, y = pos.y-1, z = pos.z-3}, {x = pos.x+3, y = pos.y+1, z = pos.z+3}, {"mcl_core:moss"})) do
if math.random(1,10) == 1 then
minetest.set_node({x=j.x,y=j.y+1,z=j.z} ,{name="mcl_flowers:double_grass"})
minetest.set_node({x=j.x,y=j.y+2,z=j.z} ,{name="mcl_flowers:double_grass_top"})
end
end
elseif minetest.registered_nodes[player:get_wielded_item():get_name()] then
itemstack:take_item() itemstack:take_item()
minetest.set_node(pointed_thing.above, {name=player:get_wielded_item():get_name()}) end
end for _, p in pairs(minetest.find_nodes_in_area_under_air({x=x-1, y=y-1, z=z-1}, {x=x+1, y=y+1, z=z+1}, moss_nodes)) do
end, minetest.set_node(p, MOSS_NODE)
end
for _, p in pairs(minetest.find_nodes_in_area_under_air({x=x-2, y=y-2, z=z-2}, {x=x+2, y=y+2, z=z+2}, moss_nodes)) do
if math.random(1,3) == 1 then minetest.set_node(p, MOSS_NODE) end
end
for _, p in pairs(minetest.find_nodes_in_area_under_air({x=x-3, y=y-3, z=z-3}, {x=x+3, y=y+3, z=z+3}, moss_nodes)) do
if math.random(1,9) == 1 then minetest.set_node(p, MOSS_NODE) end
end
for _, p in pairs(minetest.find_nodes_in_area_under_air({x=x-3, y=y-3, z=z-3}, {x=x+3, y=y+3, z=z+3}, {MOSS_ITEMSTRING})) do
if math.random(1,2) == 1 then
minetest.set_node({x=p.x, y=p.y+1, z=p.z}, {name="mcl_flowers:tallgrass"})
elseif math.random(1,4) == 1 then
minetest.set_node({x=p.x, y=p.y+1, z=p.z}, {name="mcl_core:moss_carpet"})
elseif math.random(1,10) == 1 then
minetest.set_node({x=p.x, y=p.y+1, z=p.z}, {name="mcl_flowers:double_grass"})
minetest.set_node({x=p.x, y=p.y+2, z=p.z}, {name="mcl_flowers:double_grass_top"})
end
end
elseif minetest.registered_nodes[item_name] then
if not minetest.is_creative_enabled(player) then
itemstack:take_item()
end
local set_pos = pointed_thing and pointed_thing.above or {x = pos.x, y = pos.y + 1, z = pos.z}
minetest.set_node(set_pos, {name = item_name})
end
end,
}) })
minetest.register_node("mcl_core:moss_carpet", { minetest.register_node("mcl_core:moss_carpet", {

View File

@ -1,13 +0,0 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

View File

@ -1,5 +0,0 @@
# Hoppers
This is the Hoppers mod for Minetest. It's just a clone of Minecraft hoppers, functions nearly identical to them minus mesecons making them stop and the way they're placed.
## Forum Topic
- https://forum.minetest.net/viewtopic.php?f=11&t=12379

View File

@ -1,9 +1,26 @@
local S = minetest.get_translator(minetest.get_current_modname()) local S = minetest.get_translator(minetest.get_current_modname())
local get_item_group = minetest.get_item_group local math_abs = math.abs
local mcl_util_move_item_container = mcl_util.move_item_container
--[[ BEGIN OF NODE DEFINITIONS ]] local minetest_facedir_to_dir = minetest.facedir_to_dir
local minetest_get_inventory = minetest.get_inventory
local minetest_get_item_group = minetest.get_item_group
local minetest_get_meta = minetest.get_meta
local minetest_get_node = minetest.get_node
local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius
local minetest_registered_nodes = minetest.registered_nodes
local HOPPER = "mcl_hoppers:hopper"
local HOPPER_SIDE = "mcl_hoppers:hopper_side"
local GROUPS_TO_PUT_INTO_COMMON_SLOT = {
[2] = true,
[3] = true,
[5] = true,
[6] = true,
}
local GROUPS_TO_PUT_INTO_FUEL_SLOT = {
[4] = true,
}
local mcl_hoppers_formspec = local mcl_hoppers_formspec =
"size[9,7]".. "size[9,7]"..
"label[2,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Hopper"))).."]".. "label[2,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Hopper"))).."]"..
@ -25,44 +42,50 @@ local def_hopper = {
groups = {pickaxey=1, container=2,deco_block=1,hopper=1}, groups = {pickaxey=1, container=2,deco_block=1,hopper=1},
drawtype = "nodebox", drawtype = "nodebox",
paramtype = "light", paramtype = "light",
-- FIXME: mcl_hoppers_hopper_inside.png is unused by hoppers. tiles = {
tiles = {"mcl_hoppers_hopper_inside.png^mcl_hoppers_hopper_top.png", "mcl_hoppers_hopper_outside.png", "mcl_hoppers_hopper_outside.png", "mcl_hoppers_hopper_outside.png", "mcl_hoppers_hopper_outside.png", "mcl_hoppers_hopper_outside.png"}, "mcl_hoppers_hopper_inside.png^mcl_hoppers_hopper_top.png",
"mcl_hoppers_hopper_outside.png",
"mcl_hoppers_hopper_outside.png",
"mcl_hoppers_hopper_outside.png",
"mcl_hoppers_hopper_outside.png",
"mcl_hoppers_hopper_outside.png"
},
node_box = { node_box = {
type = "fixed", type = "fixed",
fixed = { fixed = {
--funnel walls --funnel walls
{-0.5, 0.0, 0.4, 0.5, 0.5, 0.5}, {-0.5, 0.0, 0.4, 0.5, 0.5, 0.5,},
{0.4, 0.0, -0.5, 0.5, 0.5, 0.5}, { 0.4, 0.0, -0.5, 0.5, 0.5, 0.5,},
{-0.5, 0.0, -0.5, -0.4, 0.5, 0.5}, {-0.5, 0.0, -0.5, -0.4, 0.5, 0.5,},
{-0.5, 0.0, -0.5, 0.5, 0.5, -0.4}, {-0.5, 0.0, -0.5, 0.5, 0.5, -0.4,},
--funnel base --funnel base
{-0.5, 0.0, -0.5, 0.5, 0.1, 0.5}, {-0.5, 0.0, -0.5, 0.5, 0.1, 0.5,},
--spout --spout
{-0.3, -0.3, -0.3, 0.3, 0.0, 0.3}, {-0.3, -0.3, -0.3, 0.3, 0.0, 0.3,},
{-0.1, -0.3, -0.1, 0.1, -0.5, 0.1}, {-0.1, -0.3, -0.1, 0.1, -0.5, 0.1,},
}, },
}, },
selection_box = { selection_box = {
type = "fixed", type = "fixed",
fixed = { fixed = {
--funnel --funnel
{-0.5, 0.0, -0.5, 0.5, 0.5, 0.5}, {-0.5, 0.0, -0.5, 0.5, 0.5, 0.5,},
--spout --spout
{-0.3, -0.3, -0.3, 0.3, 0.0, 0.3}, {-0.3, -0.3, -0.3, 0.3, 0.0, 0.3,},
{-0.1, -0.3, -0.1, 0.1, -0.5, 0.1}, {-0.1, -0.3, -0.1, 0.1, -0.5, 0.1,},
}, },
}, },
is_ground_content = false, is_ground_content = false,
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.get_meta(pos) local meta = minetest_get_meta(pos)
meta:set_string("formspec", mcl_hoppers_formspec) meta:set_string("formspec", mcl_hoppers_formspec)
local inv = meta:get_inventory() local inv = meta:get_inventory()
inv:set_size("main", 5) inv:set_size("main", 5)
end, end,
after_dig_node = function(pos, oldnode, oldmetadata, digger) after_dig_node = function(pos, oldnode, oldmetadata, digger)
local meta = minetest.get_meta(pos) local meta = minetest_get_meta(pos)
local meta2 = meta:to_table() local meta2 = meta:to_table()
meta:from_table(oldmetadata) meta:from_table(oldmetadata)
local inv = meta:get_inventory() local inv = meta:get_inventory()
@ -120,10 +143,8 @@ local def_hopper = {
_mcl_hardness = 3, _mcl_hardness = 3,
} }
-- Redstone variants (on/off) of downwards hopper.
-- Note a hopper is enabled when it is *not* supplied with redstone power and disabled when it is supplied with redstone power.
-- Enabled downwards hopper -- Enabled downwards hopper
local def_hopper_enabled = table.copy(def_hopper) local def_hopper_enabled = table.copy(def_hopper)
def_hopper_enabled.description = S("Hopper") def_hopper_enabled.description = S("Hopper")
def_hopper_enabled._tt_help = S("5 inventory slots").."\n"..S("Collects items from above, moves items to container below").."\n"..S("Can be disabled with redstone power") def_hopper_enabled._tt_help = S("5 inventory slots").."\n"..S("Collects items from above, moves items to container below").."\n"..S("Can be disabled with redstone power")
@ -140,8 +161,8 @@ def_hopper_enabled.on_place = function(itemstack, placer, pointed_thing)
local upos = pointed_thing.under local upos = pointed_thing.under
local apos = pointed_thing.above local apos = pointed_thing.above
local uposnode = minetest.get_node(upos) local uposnode = minetest_get_node(upos)
local uposnodedef = minetest.registered_nodes[uposnode.name] local uposnodedef = minetest_registered_nodes[uposnode.name]
if not uposnodedef then return itemstack end if not uposnodedef then return itemstack end
-- Use pointed node's on_rightclick function first, if present -- Use pointed node's on_rightclick function first, if present
if placer and not placer:get_player_control().sneak then if placer and not placer:get_player_control().sneak then
@ -150,26 +171,16 @@ def_hopper_enabled.on_place = function(itemstack, placer, pointed_thing)
end end
end end
local x = upos.x - apos.x
local z = upos.z - apos.z
local fake_itemstack = ItemStack(itemstack) local fake_itemstack = ItemStack(itemstack)
local dx = apos.x - upos.x
local dz = apos.z - upos.z
local param2 local param2
if x == -1 then if (dx ~= 0) or (dz ~= 0) then
fake_itemstack:set_name("mcl_hoppers:hopper_side") param2 = minetest.dir_to_facedir({x = dx, y = 0, z = dz})
param2 = 0 fake_itemstack:set_name(HOPPER_SIDE)
elseif x == 1 then
fake_itemstack:set_name("mcl_hoppers:hopper_side")
param2 = 2
elseif z == -1 then
fake_itemstack:set_name("mcl_hoppers:hopper_side")
param2 = 3
elseif z == 1 then
fake_itemstack:set_name("mcl_hoppers:hopper_side")
param2 = 1
end end
local itemstack,_ = minetest.item_place_node(fake_itemstack, placer, pointed_thing, param2) local itemstack, _ = minetest.item_place_node(fake_itemstack, placer, pointed_thing, param2)
itemstack:set_name("mcl_hoppers:hopper") itemstack:set_name(HOPPER)
return itemstack return itemstack
end end
def_hopper_enabled.mesecons = { def_hopper_enabled.mesecons = {
@ -180,77 +191,84 @@ def_hopper_enabled.mesecons = {
}, },
} }
minetest.register_node("mcl_hoppers:hopper", def_hopper_enabled) minetest.register_node(HOPPER, def_hopper_enabled)
-- Disabled downwards hopper -- Disabled downwards hopper
local def_hopper_disabled = table.copy(def_hopper) local def_hopper_disabled = table.copy(def_hopper)
def_hopper_disabled.description = S("Disabled Hopper") def_hopper_disabled.description = S("Disabled Hopper")
def_hopper_disabled.inventory_image = nil def_hopper_disabled.inventory_image = nil
def_hopper_disabled._doc_items_create_entry = false def_hopper_disabled._doc_items_create_entry = false
def_hopper_disabled.groups.not_in_creative_inventory = 1 def_hopper_disabled.groups.not_in_creative_inventory = 1
def_hopper_disabled.drop = "mcl_hoppers:hopper" def_hopper_disabled.drop = HOPPER
def_hopper_disabled.mesecons = { def_hopper_disabled.mesecons = {
effector = { effector = {
action_off = function(pos, node) action_off = function(pos, node)
minetest.swap_node(pos, {name="mcl_hoppers:hopper", param2=node.param2}) minetest.swap_node(pos, {name=HOPPER, param2=node.param2})
end, end,
}, },
} }
minetest.register_node("mcl_hoppers:hopper_disabled", def_hopper_disabled) minetest.register_node("mcl_hoppers:hopper_disabled", def_hopper_disabled)
-- Sidewadrs hopper (base definition)
local on_rotate
if minetest.get_modpath("screwdriver") then
on_rotate = screwdriver.rotate_simple
end
-- Sidewars hopper (base definition)
local def_hopper_side = { local def_hopper_side = {
_doc_items_create_entry = false, _doc_items_create_entry = false,
drop = "mcl_hoppers:hopper", drop = HOPPER,
groups = {pickaxey=1, container=2,not_in_creative_inventory=1,hopper=2}, groups = {
container = 2,
hopper = 2,
not_in_creative_inventory = 1,
pickaxey = 1,
},
drawtype = "nodebox", drawtype = "nodebox",
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
tiles = {"mcl_hoppers_hopper_inside.png^mcl_hoppers_hopper_top.png", "mcl_hoppers_hopper_outside.png", "mcl_hoppers_hopper_outside.png", "mcl_hoppers_hopper_outside.png", "mcl_hoppers_hopper_outside.png", "mcl_hoppers_hopper_outside.png"}, tiles = {
"mcl_hoppers_hopper_inside.png^mcl_hoppers_hopper_top.png",
"mcl_hoppers_hopper_outside.png",
"mcl_hoppers_hopper_outside.png",
"mcl_hoppers_hopper_outside.png",
"mcl_hoppers_hopper_outside.png",
"mcl_hoppers_hopper_outside.png",
},
node_box = { node_box = {
type = "fixed", type = "fixed",
fixed = { fixed = {
--funnel walls --funnel walls
{-0.5, 0.0, 0.4, 0.5, 0.5, 0.5}, {-0.5, 0.0, 0.4, 0.5, 0.5, 0.5,},
{0.4, 0.0, -0.5, 0.5, 0.5, 0.5}, { 0.4, 0.0, -0.5, 0.5, 0.5, 0.5,},
{-0.5, 0.0, -0.5, -0.4, 0.5, 0.5}, {-0.5, 0.0, -0.5, -0.4, 0.5, 0.5,},
{-0.5, 0.0, -0.5, 0.5, 0.5, -0.4}, {-0.5, 0.0, -0.5, 0.5, 0.5, -0.4,},
--funnel base --funnel base
{-0.5, 0.0, -0.5, 0.5, 0.1, 0.5}, {-0.5, 0.0, -0.5, 0.5, 0.1, 0.5,},
--spout --spout
{-0.3, -0.3, -0.3, 0.3, 0.0, 0.3}, {-0.3, -0.3, -0.3, 0.3, 0.0, 0.3,},
{-0.5, -0.3, -0.1, 0.1, -0.1, 0.1}, {-0.1, -0.3, -0.5, 0.1, -0.1, 0.1,},
}, },
}, },
selection_box = { selection_box = {
type = "fixed", type = "fixed",
fixed = { fixed = {
--funnel --funnel
{-0.5, 0.0, -0.5, 0.5, 0.5, 0.5}, {-0.5, 0.0, -0.5, 0.5, 0.5, 0.5,},
--spout --spout
{-0.3, -0.3, -0.3, 0.3, 0.0, 0.3}, {-0.3, -0.3, -0.3, 0.3, 0.0, 0.3,},
{-0.5, -0.3, -0.1, 0.1, -0.1, 0.1}, {-0.1, -0.3, -0.5, 0.1, -0.1, 0.1,},
}, },
}, },
is_ground_content = false, is_ground_content = false,
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.get_meta(pos) local meta = minetest_get_meta(pos)
meta:set_string("formspec", mcl_hoppers_formspec) meta:set_string("formspec", mcl_hoppers_formspec)
local inv = meta:get_inventory() local inv = meta:get_inventory()
inv:set_size("main", 5) inv:set_size("main", 5)
end, end,
after_dig_node = function(pos, oldnode, oldmetadata, digger) after_dig_node = function(pos, oldnode, oldmetadata, digger)
local meta = minetest.get_meta(pos) local meta = minetest_get_meta(pos)
local meta2 = meta local meta2 = meta
meta:from_table(oldmetadata) meta:from_table(oldmetadata)
local inv = meta:get_inventory() local inv = meta:get_inventory()
@ -302,13 +320,15 @@ local def_hopper_side = {
minetest.log("action", player:get_player_name().. minetest.log("action", player:get_player_name()..
" takes stuff from mcl_hoppers at "..minetest.pos_to_string(pos)) " takes stuff from mcl_hoppers at "..minetest.pos_to_string(pos))
end, end,
on_rotate = on_rotate, on_rotate = screwdriver.rotate_simple,
sounds = mcl_sounds.node_sound_metal_defaults(), sounds = mcl_sounds.node_sound_metal_defaults(),
_mcl_blast_resistance = 4.8, _mcl_blast_resistance = 4.8,
_mcl_hardness = 3, _mcl_hardness = 3,
} }
-- Enabled sidewards hopper
local def_hopper_side_enabled = table.copy(def_hopper_side) local def_hopper_side_enabled = table.copy(def_hopper_side)
def_hopper_side_enabled.description = S("Side Hopper") def_hopper_side_enabled.description = S("Side Hopper")
def_hopper_side_enabled.mesecons = { def_hopper_side_enabled.mesecons = {
@ -318,53 +338,105 @@ def_hopper_side_enabled.mesecons = {
end, end,
}, },
} }
minetest.register_node("mcl_hoppers:hopper_side", def_hopper_side_enabled) minetest.register_node(HOPPER_SIDE, def_hopper_side_enabled)
-- Disabled sidewards hopper
local def_hopper_side_disabled = table.copy(def_hopper_side) local def_hopper_side_disabled = table.copy(def_hopper_side)
def_hopper_side_disabled.description = S("Disabled Side Hopper") def_hopper_side_disabled.description = S("Disabled Side Hopper")
def_hopper_side_disabled.mesecons = { def_hopper_side_disabled.mesecons = {
effector = { effector = {
action_off = function(pos, node) action_off = function(pos, node)
minetest.swap_node(pos, {name="mcl_hoppers:hopper_side", param2=node.param2}) minetest.swap_node(pos, {name=HOPPER_SIDE, param2=node.param2})
end, end,
}, },
} }
minetest.register_node("mcl_hoppers:hopper_side_disabled", def_hopper_side_disabled) minetest.register_node("mcl_hoppers:hopper_side_disabled", def_hopper_side_disabled)
--[[ END OF NODE DEFINITIONS ]]
--[[ BEGIN OF ABM DEFINITONS ]]
-- Make hoppers suck in dropped items
minetest.register_abm({ minetest.register_abm({
label = "Hoppers suck in dropped items", label = "Hopper",
nodenames = {"mcl_hoppers:hopper","mcl_hoppers:hopper_side"}, nodenames = {
interval = 1.0, HOPPER,
HOPPER_SIDE,
},
interval = 1,
chance = 1, chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider) action = function(pos, node)
local abovenode = minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z}) local pos = pos
if not minetest.registered_items[abovenode.name] then return end local meta = minetest_get_meta(pos)
-- Don't bother checking item enties if node above is a container (should save some CPU)
if get_item_group(abovenode.name, "container") then
return
end
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory() local inv = meta:get_inventory()
if not inv then return end
for _,object in pairs(minetest.get_objects_inside_radius(pos, 2)) do local x, y, z = pos.x, pos.y, pos.z
local entity = object:get_luaentity()
if not object:is_player() and entity and entity.name == "__builtin:item" and not entity._removed then -- Move an item from the hopper into the container to which the hopper points to
if inv and inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then local dst_pos
-- Item must get sucked in when the item just TOUCHES the block above the hopper if node.name == HOPPER then
-- This is the reason for the Y calculation. dst_pos = {x = x, y = y - 1, z = z}
-- Test: Items on farmland and slabs get sucked, but items on full blocks don't else
local posob = object:get_pos() local param2 = node.param2
local posob_miny = posob.y + object:get_properties().collisionbox[2] local dir = minetest_facedir_to_dir(param2)
if math.abs(posob.x-pos.x) <= 0.5 and (posob_miny-pos.y < 1.5 and posob.y-pos.y >= 0.3) then if not dir then return end
entity._removed = true dst_pos = {x = x - dir.x, y = y, z = z - dir.z}
entity.itemstring = "" end
object:remove() local dst_node = minetest_get_node(dst_pos)
inv:add_item("main", ItemStack(object:get_luaentity().itemstring)) local dst_node_name = dst_node.name
local dst_container_group = minetest_get_item_group(dst_node_name, "container")
if GROUPS_TO_PUT_INTO_COMMON_SLOT[dst_container_group] then
mcl_util_move_item_container(pos, dst_pos)
elseif GROUPS_TO_PUT_INTO_FUEL_SLOT[dst_container_group] then
local sinv = minetest_get_inventory({type="node", pos = pos})
local dinv = minetest_get_inventory({type="node", pos = dst_pos})
local slot_id,_ = mcl_util.get_eligible_transfer_item_slot(
sinv,
"main",
dinv,
"fuel",
function(itemstack, src_inventory, src_list, dst_inventory, dst_list)
-- Returns true if itemstack is fuel, but not for lava bucket if destination already has one
if not mcl_util.is_fuel(itemstack) then return false end
if itemstack:get_name() ~= "mcl_buckets:bucket_lava" then return true end
return dst_inventory:is_empty(dst_list)
end
)
end
local y_above = y + 1
local pos_above = {x = x, y = y_above, z = z}
local above_node = minetest_get_node(pos_above)
local above_node_name = above_node.name
local above_container_group = minetest_get_item_group(above_node_name, "container")
if above_container_group ~= 0 then
-- Suck an item from the container above into the hopper
if not mcl_util_move_item_container(pos_above, pos)
and above_container_group == 4 then
local finv = minetest_get_inventory({type="node", pos = pos_above})
if finv and not mcl_util.is_fuel(finv:get_stack("fuel", 1)) then
mcl_util_move_item_container(pos_above, pos, "fuel")
end
end
else
-- Suck in dropped items
local y_top_touch_to_suck = y_above + 0.5
for _, object in pairs(minetest_get_objects_inside_radius(pos_above, 1)) do
if not object:is_player() then
local entity = object:get_luaentity()
local entity_name = entity and entity.name
if entity_name == "__builtin:item" then
local itemstring = entity.itemstring
if itemstring and itemstring ~= "" and inv:room_for_item("main", ItemStack(itemstring)) then
local object_pos = object:get_pos()
local object_pos_y = object_pos.y
local object_collisionbox = object:get_properties().collisionbox
local touches_from_above = object_pos_y + object_collisionbox[2] <= y_top_touch_to_suck
if touches_from_above
and (math_abs(object_pos.x - x) <= 0.5)
and (math_abs(object_pos.z - z) <= 0.5)
then
object:remove()
inv:add_item("main", ItemStack(itemstring))
end
end
end end
end end
end end
@ -372,116 +444,8 @@ minetest.register_abm({
end, end,
}) })
-- Returns true if itemstack is fuel, but not for lava bucket if destination already has one
local is_transferrable_fuel = function(itemstack, src_inventory, src_list, dst_inventory, dst_list)
if mcl_util.is_fuel(itemstack) then
if itemstack:get_name() == "mcl_buckets:bucket_lava" then
return dst_inventory:is_empty(dst_list)
else
return true
end
else
return false
end
end
minetest.register_abm({
label = "Hopper/container item exchange",
nodenames = {"mcl_hoppers:hopper"},
neighbors = {"group:container"},
interval = 1.0,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
-- Get node pos' for item transfer
local uppos = {x=pos.x,y=pos.y+1,z=pos.z}
local downpos = {x=pos.x,y=pos.y-1,z=pos.z}
-- Suck an item from the container above into the hopper
local upnode = minetest.get_node(uppos)
if not minetest.registered_nodes[upnode.name] then return end
local g = get_item_group(upnode.name, "container")
local sucked = mcl_util.move_item_container(uppos, pos)
-- Also suck in non-fuel items from furnace fuel slot
if not sucked and g == 4 then
local finv = minetest.get_inventory({type="node", pos=uppos})
if finv and not mcl_util.is_fuel(finv:get_stack("fuel", 1)) then
mcl_util.move_item_container(uppos, pos, "fuel")
end
end
-- Move an item from the hopper into container below
local downnode = minetest.get_node(downpos)
if not minetest.registered_nodes[downnode.name] then return end
mcl_util.move_item_container(pos, downpos)
end,
})
minetest.register_abm({
label = "Side-hopper/container item exchange",
nodenames = {"mcl_hoppers:hopper_side"},
neighbors = {"group:container"},
interval = 1.0,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
-- Determine to which side the hopper is facing, get nodes
local face = minetest.get_node(pos).param2
local front = {}
if face == 0 then
front = {x=pos.x-1,y=pos.y,z=pos.z}
elseif face == 1 then
front = {x=pos.x,y=pos.y,z=pos.z+1}
elseif face == 2 then
front = {x=pos.x+1,y=pos.y,z=pos.z}
elseif face == 3 then
front = {x=pos.x,y=pos.y,z=pos.z-1}
end
local above = {x=pos.x,y=pos.y+1,z=pos.z}
local downpos = {x=pos.x,y=pos.y-1,z=pos.z}
local frontnode = minetest.get_node(front)
if not minetest.registered_nodes[frontnode.name] then return end
-- Suck an item from the container above into the hopper
local abovenode = minetest.get_node(above)
if not minetest.registered_nodes[abovenode.name] then return end
local g = get_item_group(abovenode.name, "container")
local sucked = mcl_util.move_item_container(above, pos)
-- Also suck in non-fuel items from furnace fuel slot
if not sucked and g == 4 then
local finv = minetest.get_inventory({type="node", pos=above})
if finv and not mcl_util.is_fuel(finv:get_stack("fuel", 1)) then
mcl_util.move_item_container(above, pos, "fuel")
end
end
-- Try to move an item below before moving it sideways
local downnode = minetest.get_node(downpos)
if minetest.registered_nodes[downnode.name] and
mcl_util.move_item_container(pos, downpos) then return end
-- Move an item from the hopper into the container to which the hopper points to
local g = get_item_group(frontnode.name, "container")
if g == 2 or g == 3 or g == 5 or g == 6 then
mcl_util.move_item_container(pos, front)
elseif g == 4 then
-- Put fuel into fuel slot
local sinv = minetest.get_inventory({type="node", pos = pos})
local dinv = minetest.get_inventory({type="node", pos = front})
local slot_id,_ = mcl_util.get_eligible_transfer_item_slot(sinv, "main", dinv, "fuel", is_transferrable_fuel)
if slot_id then
mcl_util.move_item_container(pos, front, nil, slot_id, "fuel")
end
end
end
})
minetest.register_craft({ minetest.register_craft({
output = "mcl_hoppers:hopper", output = HOPPER,
recipe = { recipe = {
{"mcl_core:iron_ingot","","mcl_core:iron_ingot"}, {"mcl_core:iron_ingot","","mcl_core:iron_ingot"},
{"mcl_core:iron_ingot","mcl_chests:chest","mcl_core:iron_ingot"}, {"mcl_core:iron_ingot","mcl_chests:chest","mcl_core:iron_ingot"},
@ -489,21 +453,20 @@ minetest.register_craft({
} }
}) })
-- Add entry aliases for the Help
if minetest.get_modpath("doc") then if minetest.get_modpath("doc") then
doc.add_entry_alias("nodes", "mcl_hoppers:hopper", "nodes", "mcl_hoppers:hopper_side") doc.add_entry_alias("nodes", HOPPER, "nodes", HOPPER_SIDE)
end end
-- Legacy
minetest.register_alias("mcl_hoppers:hopper_item", "mcl_hoppers:hopper")
minetest.register_lbm({ minetest.register_lbm({
label = "Update hopper formspecs (0.60.0", label = "Update hopper formspecs (0.60.0",
name = "mcl_hoppers:update_formspec_0_60_0", name = "mcl_hoppers:update_formspec_0_60_0",
nodenames = { "group:hopper" }, nodenames = { "group:hopper" },
run_at_every_load = false, run_at_every_load = false,
action = function(pos, node) action = function(pos, node)
local meta = minetest.get_meta(pos) local meta = minetest_get_meta(pos)
meta:set_string("formspec", mcl_hoppers_formspec) meta:set_string("formspec", mcl_hoppers_formspec)
end, end,
}) })
-- Legacy
minetest.register_alias("mcl_hoppers:hopper_item", HOPPER)

View File

@ -1,4 +1,5 @@
name = mcl_hoppers name = mcl_hoppers
author = jordan4ibanez
description = It's just a clone of Minecraft hoppers, functions nearly identical to them minus mesecons making them stop and the way they're placed. description = It's just a clone of Minecraft hoppers, functions nearly identical to them minus mesecons making them stop and the way they're placed.
depends = mcl_core, mcl_formspec, mcl_sounds, mcl_util depends = mcl_core, mcl_formspec, mcl_sounds, mcl_util
optional_depends = doc, screwdriver optional_depends = doc, screwdriver

View File

@ -14,6 +14,7 @@ mcl_shields = {
enchantments = {"mending", "unbreaking"}, enchantments = {"mending", "unbreaking"},
players = {}, players = {},
} }
local players = mcl_shields.players
local interact_priv = minetest.registered_privileges.interact local interact_priv = minetest.registered_privileges.interact
interact_priv.give_to_singleplayer = false interact_priv.give_to_singleplayer = false
@ -110,7 +111,7 @@ end
function mcl_shields.is_blocking(obj) function mcl_shields.is_blocking(obj)
if not mcl_util or not mcl_util.is_player(obj) then return end if not mcl_util or not mcl_util.is_player(obj) then return end
local blocking = mcl_shields.players[obj].blocking local blocking = players[obj].blocking
if blocking > 0 then if blocking > 0 then
local shieldstack = obj:get_wielded_item() local shieldstack = obj:get_wielded_item()
if blocking == 1 then if blocking == 1 then
@ -155,7 +156,7 @@ local function modify_shield(player, vpos, vrot, i)
if i == 1 then if i == 1 then
arm = "Left" arm = "Left"
end end
local player_data = mcl_shields.players[player] local player_data = players[player]
if not player_data then return end if not player_data then return end
local shields = player_data.shields local shields = player_data.shields
if not shields then return end if not shields then return end
@ -178,7 +179,10 @@ local function set_shield(player, block, i)
modify_shield(player, vector.new(3, -5, 0), vector.new(0, 0, 0), i) modify_shield(player, vector.new(3, -5, 0), vector.new(0, 0, 0), i)
end end
end end
local shield = mcl_shields.players[player].shields[i] local player_data = players[player]
if not player_data then return end
local player_shields = player_data.shields
local shield = player_shields[i]
if not shield then return end if not shield then return end
local luaentity = shield:get_luaentity() local luaentity = shield:get_luaentity()
if not luaentity then return end if not luaentity then return end
@ -219,12 +223,12 @@ end
local function add_shield_entity(player, i) local function add_shield_entity(player, i)
local shield = minetest.add_entity(player:get_pos(), "mcl_shields:shield_entity") local shield = minetest.add_entity(player:get_pos(), "mcl_shields:shield_entity")
shield:get_luaentity()._shield_number = i shield:get_luaentity()._shield_number = i
mcl_shields.players[player].shields[i] = shield players[player].shields[i] = shield
set_shield(player, false, i) set_shield(player, false, i)
end end
local function remove_shield_entity(player, i) local function remove_shield_entity(player, i)
local shields = mcl_shields.players[player].shields local shields = players[player].shields
if shields[i] then if shields[i] then
shields[i]:remove() shields[i]:remove()
shields[i] = nil shields[i] = nil
@ -232,7 +236,7 @@ local function remove_shield_entity(player, i)
end end
local function handle_blocking(player) local function handle_blocking(player)
local player_shield = mcl_shields.players[player] local player_shield = players[player]
local rmb = player:get_player_control().RMB local rmb = player:get_player_control().RMB
if rmb then if rmb then
local shield_in_offhand = mcl_shields.wielding_shield(player, 1) local shield_in_offhand = mcl_shields.wielding_shield(player, 1)
@ -274,7 +278,7 @@ local function handle_blocking(player)
end end
local function update_shield_entity(player, blocking, i) local function update_shield_entity(player, blocking, i)
local shield = mcl_shields.players[player].shields[i] local shield = players[player].shields[i]
if mcl_shields.wielding_shield(player, i) then if mcl_shields.wielding_shield(player, i) then
if not shield then if not shield then
add_shield_entity(player, i) add_shield_entity(player, i)
@ -378,7 +382,7 @@ end)
minetest.register_on_leaveplayer(function(player) minetest.register_on_leaveplayer(function(player)
shield_hud[player] = nil shield_hud[player] = nil
mcl_shields.players[player] = nil players[player] = nil
end) end)
minetest.register_craft({ minetest.register_craft({
@ -468,7 +472,7 @@ minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv
end) end)
minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)
mcl_shields.players[player] = { players[player] = {
shields = {}, shields = {},
blocking = 0, blocking = 0,
} }

View File

@ -62,7 +62,6 @@ local spawn_trident = function(player)
durability = durability * (unbreaking + 1) durability = durability * (unbreaking + 1)
end end
wielditem:add_wear(65535/durability) wielditem:add_wear(65535/durability)
minetest.chat_send_all(wielditem:get_wear())
obj:set_velocity(vector.multiply(player:get_look_dir(), 20)) obj:set_velocity(vector.multiply(player:get_look_dir(), 20))
obj:set_acceleration({x=0, y=-GRAVITY, z=0}) obj:set_acceleration({x=0, y=-GRAVITY, z=0})
obj:set_yaw(yaw) obj:set_yaw(yaw)
@ -78,10 +77,10 @@ minetest.register_tool("mcl_tridents:trident", {
stack_max = 1, stack_max = 1,
groups = {weapon=1,weapon_ranged=1,trident=1,enchantability=1}, groups = {weapon=1,weapon_ranged=1,trident=1,enchantability=1},
_mcl_uses = TRIDENT_DURABILITY, _mcl_uses = TRIDENT_DURABILITY,
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
spawn_trident(placer) spawn_trident(placer)
end, end,
on_secondary_use = function(itemstack, user, pointed_thing) on_secondary_use = function(itemstack, user, pointed_thing)
spawn_trident(user) spawn_trident(user)
end end
}) })

View File

@ -3045,8 +3045,8 @@ local function register_decorations()
octaves = 3, octaves = 3,
persist = 0.6 persist = 0.6
}, },
y_min = 4, spawn_by = "air",
y_max = mcl_mapgen.overworld.max, num_spawn_by = 8,
decoration = "mcl_core:cactus", decoration = "mcl_core:cactus",
biomes = {"Desert", biomes = {"Desert",
"Mesa","Mesa_sandlevel", "Mesa","Mesa_sandlevel",

View File

@ -670,8 +670,8 @@ local function register_mgv6_decorations()
octaves = 3, octaves = 3,
persist = 0.6 persist = 0.6
}, },
y_min = 4, spawn_by = "air",
y_max = mcl_mapgen.overworld.max, num_spawn_by = 8,
decoration = "mcl_core:cactus", decoration = "mcl_core:cactus",
height = 1, height = 1,
height_max = 3, height_max = 3,

View File

@ -1,11 +1,8 @@
local modname = minetest.get_current_modname()
local modpath = minetest.get_modpath(modname)
local chance_per_chunk = 400 local chance_per_chunk = 400
local noise_multiplier = 2.5 local noise_multiplier = 2.5
local random_offset = 9159 local random_offset = 9159
local scanning_ratio = 0.001 local scanning_ratio = 0.001
local struct_threshold = 396 local struct_threshold = 393.91
local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level 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_find_nodes_in_area = minetest.find_nodes_in_area
@ -13,6 +10,223 @@ local minetest_swap_node = minetest.swap_node
local math_round = math.round local math_round = math.round
local math_abs = math.abs local math_abs = math.abs
local function insert_times(how_many_times, what, where)
for i = 1, how_many_times do
where[#where + 1] = what
end
end
local function create_probability_picker(table_of_how_many_times_what)
local picker = {}
for _, v in pairs(table_of_how_many_times_what) do
insert_times(v[1], v[2], picker)
end
return picker
end
local STONE_DECOR = {
"mcl_core:stonebrickcarved",
"mcl_blackstone:blackstone_chiseled_polished",
}
local PANE_OR_CHAIN = {
"xpanes:bar",
"mcl_lanterns:chain",
}
local PANE_OR_CHAIN_FLAT = {
"xpanes:bar_flat",
"mcl_lanterns:chain",
}
local STAIR1 = {
"mcl_stairs:stair_stonebrickcracked",
-- TODO: stair_blackstone_brick_polished_cracked:
"mcl_stairs:stair_deepslate_bricks",
}
local STAIR2 = {
"mcl_stairs:stair_stonebrickmossy",
"mcl_stairs:stair_blackstone_brick_polished",
}
local STAIR3 = {
"mcl_stairs:stair_stone_rough",
"mcl_stairs:stair_blackstone_chiseled_polished",
}
local STAIR4 = {
"mcl_stairs:stair_stonebrick",
"mcl_stairs:stair_blackstone_brick_polished",
}
local STAIR_OUTER1 = {
"mcl_stairs:stair_stonebrickcracked_outer",
-- TODO: stair_blackstone_brick_polished_cracked_outer:
"mcl_stairs:stair_deepslate_bricks_outer",
}
local STAIR_OUTER2 = {
"mcl_stairs:stair_stonebrickmossy_outer",
"mcl_stairs:stair_blackstone_brick_polished_outer",
}
local STAIR_OUTER3 = {
"mcl_stairs:stair_stone_rough_outer",
"mcl_stairs:stair_blackstone_chiseled_polished_outer",
}
local STAIR_OUTER4 = {
"mcl_stairs:stair_stonebrick_outer",
"mcl_stairs:stair_blackstone_brick_polished_outer",
}
local TOP_DECOR1 = {
"mcl_core:goldblock",
"mcl_core:goldblock",
}
local TOP_DECOR2 = {
"mcl_core:stone_with_gold",
"mcl_core:stone_with_gold",
}
local STONE1 = {
"mcl_core:stonebrickcracked",
-- TODO: polished_blackstone_brick_cracked:
"mcl_deepslate:deepslate_bricks_cracked",
}
local STONE2 = {
"mcl_core:stonebrickmossy",
"mcl_blackstone:blackstone_brick_polished",
}
local STONE3 = {
"mcl_nether:magma",
"mcl_core:packed_ice",
}
local STONE4 = {
"mcl_core:stonebrick",
"mcl_blackstone:blackstone_brick_polished",
}
local STONE5 = {
"mcl_core:stone",
"mcl_blackstone:blackstone",
}
local STONE6 = {
"mcl_core:cobble",
"mcl_blackstone:basalt_polished",
}
local STONE7 = {
"mcl_core:mossycobble",
"mcl_blackstone:blackstone_chiseled_polished",
}
local SLAB_TOP1 = {
"mcl_stairs:slab_stonebrickcracked_top",
-- TODO: slab_polished_blackstone_brick_cracked_top:
"mcl_stairs:slab_goldblock_top",
}
local SLAB_TOP2 = {
"mcl_stairs:slab_stonebrickmossy_top",
"mcl_stairs:slab_blackstone_brick_polished_top",
}
local SLAB_TOP3 = {
"mcl_stairs:slab_stone_top",
"mcl_stairs:slab_blackstone_top",
}
local SLAB_TOP4 = {
"mcl_stairs:slab_stonebrick_top",
"mcl_stairs:slab_blackstone_brick_polished_top",
}
local SLAB1 = {
"mcl_stairs:slab_stone",
"mcl_stairs:slab_blackstone",
}
local SLAB2 = {
"mcl_stairs:slab_stonebrick",
"mcl_stairs:slab_blackstone_brick_polished",
}
local SLAB3 = {
"mcl_stairs:slab_stonebrickcracked",
-- TODO: slab_polished_blackstone_brick_cracked:
"mcl_stairs:slab_goldblock",
}
local SLAB4 = {
"mcl_stairs:slab_stonebrickmossy",
"mcl_stairs:slab_blackstone_brick_polished",
}
local GARBAGE1 = {
"mcl_nether:netherrack",
"mcl_core:stone",
}
local LAVA_SOURCE = {
"mcl_nether:nether_lava_source",
"mcl_core:lava_source",
}
local GARBAGE3 = {
"mcl_nether:magma",
"mcl_nether:magma",
}
local stair_set_for_frame = create_probability_picker({
{ 3, STAIR1,},
{ 1, STAIR2,},
{ 1, STAIR3,},
{10, STAIR4,},
})
local stone_set_for_frame = create_probability_picker({
{ 3, STONE1,},
{ 1, STONE2,},
{ 1, STONE3,},
{10, STONE4,},
})
local slab_set_for_frame = create_probability_picker({
{ 3, SLAB_TOP1,},
{ 1, SLAB_TOP2,},
{ 1, SLAB_TOP3,},
{10, SLAB_TOP4,},
})
local stair_set_for_stairs = create_probability_picker({
{ 1, STAIR1,},
{ 2, STAIR2,},
{ 7, STAIR3,},
{ 3, STAIR4,},
})
local top_decoration_list = create_probability_picker({
{ 2, TOP_DECOR1,},
{ 1, TOP_DECOR2,},
})
local node_garbage = create_probability_picker({
{ 4, GARBAGE1,},
{ 1, LAVA_SOURCE,},
{ 1, GARBAGE3,},
})
local stair_replacement_list = {
"air",
"group:water",
"group:lava",
"group:buildable_to",
"group:deco_block",
}
local stair_outer_names = {
STAIR_OUTER1,
STAIR_OUTER2,
STAIR_OUTER3,
STAIR_OUTER4,
}
local stair_content = create_probability_picker({
{1, LAVA_SOURCE,},
{5, STONE5,},
{1, STONE4,},
{1, STONE3,},
{2, GARBAGE1,},
})
local stair_content_bottom = create_probability_picker({
{2, STONE3,},
{4, GARBAGE1,},
})
local slabs = create_probability_picker({
{5, SLAB1,},
{2, SLAB2,},
{1, SLAB3,},
{1, SLAB4,},
})
local stones = create_probability_picker({
{3, STONE5,},
{1, STONE6,},
{1, STONE7,},
})
local rotation_to_orientation = { local rotation_to_orientation = {
["0"] = 1, ["0"] = 1,
@ -28,39 +242,11 @@ local rotation_to_param2 = {
["270"] = 2, ["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 function draw_frame(frame_pos, frame_width, frame_height, orientation, pr, is_chain, rotation, is_blackstone)
local param2 = rotation_to_param2[rotation] local param2 = rotation_to_param2[rotation]
local variant = is_blackstone and 2 or 1
local function set_ruined_node(pos, node) local function set_ruined_node(pos, node)
if pr:next(1, 5) == 4 then return end if pr:next(1, 5) == 4 then return end
@ -68,28 +254,20 @@ local function draw_frame(frame_pos, frame_width, frame_height, orientation, pr,
end end
local function get_random_stone_material() local function get_random_stone_material()
local rnd = pr:next(1, 15) local rnd = pr:next(1, #stone_set_for_frame)
if rnd < 4 then return stone1 end return {name = stone_set_for_frame[rnd][variant]}
if rnd == 4 then return stone2 end
if rnd == 5 then return stone3 end
return stone4
end end
local function get_random_slab() local function get_random_slab()
local rnd = pr:next(1, 15) local rnd = pr:next(1, 15)
if rnd < 4 then return slab1 end return {name = slab_set_for_frame[rnd][variant]}
if rnd == 4 then return slab2 end
if rnd == 5 then return slab3 end
return slab4
end end
local function get_random_stair(param2_offset) local function get_random_stair(param2_offset)
local param2 = (param2 + (param2_offset or 0)) % 4 local param2 = (param2 + (param2_offset or 0)) % 4
local rnd = pr:next(1, 15) local rnd = pr:next(1, #stair_set_for_frame)
if rnd < 4 then return {name = stair1, param2 = param2} end local stare_name = stair_set_for_frame[rnd][variant]
if rnd == 4 then return {name = stair2, param2 = param2} end return {name = stare_name, param2 = param2}
if rnd == 5 then return {name = stair3, param2 = param2} end
return {name = stair4, param2 = param2}
end end
local function set_frame_stone_material(pos) local function set_frame_stone_material(pos)
@ -118,7 +296,6 @@ local function draw_frame(frame_pos, frame_width, frame_height, orientation, pr,
local air_nodes = frame_nodes - obsidian_nodes local air_nodes = frame_nodes - obsidian_nodes
local function set_frame_node(pos) local function set_frame_node(pos)
-- local node_choice = pr:next(1, air_nodes + obsidian_nodes)
local node_choice = math_round(mcl_structures_get_perlin_noise_level(pos) * (air_nodes + obsidian_nodes)) local node_choice = math_round(mcl_structures_get_perlin_noise_level(pos) * (air_nodes + obsidian_nodes))
if node_choice > obsidian_nodes and air_nodes > 0 then if node_choice > obsidian_nodes and air_nodes > 0 then
air_nodes = air_nodes - 1 air_nodes = air_nodes - 1
@ -141,7 +318,7 @@ local function draw_frame(frame_pos, frame_width, frame_height, orientation, pr,
local is_top_hole = is_top and frame_width > 5 and ((pos2.x == x1 + slide_x * 2 and pos2.z == z1 + slide_z * 2) or (pos2.x == last_x - slide_x * 2 and pos2.z == last_z - slide_z * 2)) 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 is_top_hole then
if pr:next(1, 7) > 1 then if pr:next(1, 7) > 1 then
minetest_swap_node(pos2, {name = "xpanes:bar_flat", param2 = orientation}) minetest_swap_node(pos2, {name = PANE_OR_CHAIN_FLAT[variant], param2 = orientation})
end end
else else
set_frame_stone_material(pos2) set_frame_stone_material(pos2)
@ -152,18 +329,18 @@ local function draw_frame(frame_pos, frame_width, frame_height, orientation, pr,
local pos = def.pos_outer1 local pos = def.pos_outer1
local is_decor_here = not is_top and pos.y % 3 == 2 local is_decor_here = not is_top and pos.y % 3 == 2
if is_decor_here then if is_decor_here then
minetest_swap_node(pos, {name = "mcl_core:stonebrickcarved"}) minetest_swap_node(pos, {name = STONE_DECOR[variant]})
elseif is_chain then elseif is_chain then
if not is_top and not is_obsidian then if not is_top and not is_obsidian then
minetest_swap_node(pos, {name = "xpanes:bar"}) minetest_swap_node(pos, {name = PANE_OR_CHAIN[variant]})
else else
minetest_swap_node(pos, {name = "xpanes:bar_flat", param2 = orientation}) minetest_swap_node(pos, {name = PANE_OR_CHAIN_FLAT[variant], param2 = orientation})
end end
else else
if pr:next(1, 5) == 3 then if pr:next(1, 5) == 3 then
minetest_swap_node(pos, {name = "mcl_core:stonebrickcracked"}) minetest_swap_node(pos, {name = STONE1[variant]})
else else
minetest_swap_node(pos, {name = "mcl_core:stonebrick"}) minetest_swap_node(pos, {name = STONE4[variant]})
end end
end end
end end
@ -253,7 +430,7 @@ local function draw_frame(frame_pos, frame_width, frame_height, orientation, pr,
}) })
end end end end
local node_top = {name = node_top[pr:next(1, #node_top)]} local node_top = {name = top_decoration_list[pr:next(1, #top_decoration_list)][variant]}
if is_chain then 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 * 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 = x1 + slide_x , y = last_y + 3, z = z1 + slide_z })
@ -281,7 +458,9 @@ end
local possible_rotations = {"0", "90", "180", "270"} local possible_rotations = {"0", "90", "180", "270"}
local function draw_trash(pos, width, height, lift, orientation, pr) local function draw_trash(pos, width, height, lift, orientation, pr, is_blackstone)
local variant = is_blackstone and 2 or 1
local pos = pos
local slide_x = (1 - orientation) local slide_x = (1 - orientation)
local slide_z = orientation local slide_z = orientation
local x1 = pos.x - lift - 1 local x1 = pos.x - lift - 1
@ -297,7 +476,7 @@ local function draw_trash(pos, width, height, lift, orientation, pr)
for x = x1 + pr:next(0, 2), x2 - pr:next(0, 2) do 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 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 if inverted_opacity_0_5 == 0 or (x % inverted_opacity_0_5 ~= pr:next(0, 1) and z % inverted_opacity_0_5 ~= pr:next(0, 1)) then
minetest_swap_node({x = x, y = y, z = z}, {name = node_garbage[pr:next(1, #node_garbage)]}) minetest_swap_node({x = x, y = y, z = z}, {name = node_garbage[pr:next(1, #node_garbage)][variant]})
end end
end end
end end
@ -305,77 +484,6 @@ local function draw_trash(pos, width, height, lift, orientation, pr)
end end
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 = { local stair_selector = {
[-1] = { [-1] = {
[-1] = { [-1] = {
@ -383,7 +491,7 @@ local stair_selector = {
param2 = 1, param2 = 1,
}, },
[0] = { [0] = {
names = stair_names, names = stair_set_for_stairs,
param2 = 1, param2 = 1,
}, },
[1] = { [1] = {
@ -393,14 +501,14 @@ local stair_selector = {
}, },
[0] = { [0] = {
[-1] = { [-1] = {
names = stair_names, names = stair_set_for_stairs,
param2 = 0, param2 = 0,
}, },
[0] = { [0] = {
names = stair_content, names = stair_content,
}, },
[1] = { [1] = {
names = stair_names, names = stair_set_for_stairs,
param2 = 2, param2 = 2,
}, },
}, },
@ -410,7 +518,7 @@ local stair_selector = {
param2 = 0, param2 = 0,
}, },
[0] = { [0] = {
names = stair_names, names = stair_set_for_stairs,
param2 = 3, param2 = 3,
}, },
[1] = { [1] = {
@ -422,25 +530,14 @@ local stair_selector = {
local stair_offset_from_bottom = 2 local stair_offset_from_bottom = 2
local function draw_stairs(pos, width, height, lift, orientation, pr, is_chain, param2) local function draw_stairs(pos, width, height, lift, orientation, pr, is_chain, param2, is_blackstone)
local variant = is_blackstone and 2 or 1
local current_stair_content = stair_content local current_stair_content = stair_content
local current_stones = stones 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 param2 = param2
local mirror = param2 == 1 or param2 == 2 local mirror = param2 == 1 or param2 == 2
if mirror then if mirror then param2 = (param2 + 2) % 4 end
param2 = (param2 + 2) % 4
end
local chain_offset = is_chain and 1 or 0 local chain_offset = is_chain and 1 or 0
local lift = lift + stair_offset_from_bottom local lift = lift + stair_offset_from_bottom
local slide_x = (1 - orientation) local slide_x = (1 - orientation)
local slide_z = orientation local slide_z = orientation
@ -455,52 +552,63 @@ local function draw_stairs(pos, width, height, lift, orientation, pr, is_chain,
local y = y2 local y = y2
local place_slabs = true local place_slabs = true
local x_key, z_key local x_key, z_key
local need_to_place_chest = true
local chest_pos local chest_pos
local bad_nodes_ratio = 0 local ruinity = height + lift
while (y >= y1) or (bad_nodes_ratio > 0.07) do local y_layer_to_start_squeezing = y1 - 2 * lift
local good_nodes_counter = 0 while (true) do
for x = x1, x2 do local x11 = math_round(x1)
x_key = (x == x1) and -1 or (x == x2) and 1 or 0 local x22 = math_round(x2)
for z = z1, z2 do local z11 = math_round(z1)
local pos = {x = x, y = y, z = z} local z22 = math_round(z2)
if #minetest_find_nodes_in_area(pos, pos, stair_replacement_list, false) > 0 then local good_nodes = minetest_find_nodes_in_area({x = x11, y = y, z = z11}, {x = x22, y = y, z = z22}, stair_replacement_list, false)
z_key = (z == z1) and -1 or (z == z2) and 1 or 0 local good_nodes_ratio = #good_nodes / (x22 - x11 + 1) / (z22 - z11 + 1)
local stair_coverage = (x_key ~= 0) or (z_key ~= 0) if y < y1 and good_nodes_ratio <= 0.07 then return chest_pos end
if stair_coverage then for _, pos in pairs(good_nodes) do
if stair_layer then if pr:next(1, ruinity) > 1 then
local stair = stair_selector[x_key][z_key] local x, z = pos.x, pos.z
local names = stair.names x_key = (x == x11) and -1 or (x == x22) and 1 or 0
set_ruined_node(pos, {name = names[pr:next(1, #names)], param2 = stair.param2}) z_key = (z == z11) and -1 or (z == z22) and 1 or 0
elseif place_slabs then local should_be_a_stair_here = (x_key ~= 0) or (z_key ~= 0)
set_ruined_node(pos, slabs[pr:next(1, #slabs)]) if should_be_a_stair_here then
else if stair_layer then
local placed = set_ruined_node(pos, current_stones[pr:next(1, #current_stones)]) local stair = stair_selector[x_key][z_key]
if need_to_place_chest and placed then local names = stair.names
chest_pos = {x = pos.x, y = pos.y + 1, z = pos.z} minetest_swap_node(pos, {name = names[pr:next(1, #names)][variant], param2 = stair.param2})
minetest_swap_node(chest_pos, {name = "mcl_chests:chest_small"}) elseif place_slabs then
need_to_place_chest = false minetest_swap_node(pos, {name = slabs[pr:next(1, #slabs)][variant]})
end else
minetest_swap_node(pos, {name = current_stones[pr:next(1, #current_stones)][variant]})
if not chest_pos then
chest_pos = {x = pos.x, y = pos.y + 1, z = pos.z}
minetest_swap_node(chest_pos, {name = "mcl_chests:chest_small"})
end end
elseif not stair_layer then
set_ruined_node(pos, current_stair_content[pr:next(1, #current_stair_content)])
end end
else elseif not stair_layer then
good_nodes_counter = good_nodes_counter + 1 minetest_swap_node(pos, {name = current_stair_content[pr:next(1, #current_stair_content)][variant]})
end end
end end
end end
bad_nodes_ratio = 1 - good_nodes_counter / ((x2 - x1 + 1) * (z2 - z1 + 1)) if y >= y1 - lift then
if y >= y1 then
x1 = x1 - 1 x1 = x1 - 1
x2 = x2 + 1 x2 = x2 + 1
z1 = z1 - 1 z1 = z1 - 1
z2 = z2 + 1 z2 = z2 + 1
elseif y < y_layer_to_start_squeezing then
local noise = mcl_structures_get_perlin_noise_level(pos) + 0.5
x1 = x1 + noise * pr:next(0,2)
x2 = x2 - noise * pr:next(0,2)
z1 = z1 + noise * pr:next(0,2)
z2 = z2 - noise * pr:next(0,2)
if x1 >= x2 then return chest_pos end
if z1 >= z2 then return chest_pos end
elseif y == y_layer_to_start_squeezing then
current_stones = stair_content_bottom
end
if y >= y1 then
if (stair_layer or place_slabs) then if (stair_layer or place_slabs) then
y = y - 1 y = y - 1
if y <= y1 then if y <= y1 then
current_stair_content = stair_content_bottom current_stair_content = stair_content_bottom
current_stones = stair_content_bottom
end end
end end
place_slabs = not place_slabs place_slabs = not place_slabs
@ -508,19 +616,9 @@ local function draw_stairs(pos, width, height, lift, orientation, pr, is_chain,
else else
place_slabs = false place_slabs = false
y = y - 1 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
if ruinity > 2 then ruinity = math.max(ruinity - pr:next(0,2), 2) end
end end
return chest_pos
end end
local function enchant(stack, pr) local function enchant(stack, pr)
@ -533,19 +631,18 @@ local function enchant_armor(stack, pr)
mcl_enchanting.enchant_randomly(stack, 30, false, false, false, pr) mcl_enchanting.enchant_randomly(stack, 30, false, false, false, pr)
end end
local function place(pos, rotation, pr) local function common_place(pos, rotation, pr, width, height, lift, is_blackstone)
local width = pr:next(2, 10) local pos = pos
local height = pr:next(((width < 3) and 3 or 2), 10) local width = width
local lift = pr:next(0, 4) local height = height
local rotation = rotation or possible_rotations[pr:next(1, #possible_rotations)] local lift = lift
local rotation = rotation
local orientation = rotation_to_orientation[rotation] local orientation = rotation_to_orientation[rotation]
assert(orientation)
local param2 = rotation_to_param2[rotation] local param2 = rotation_to_param2[rotation]
assert(param2)
local is_chain = pr:next(1, 3) > 1 local is_chain = pr:next(1, 3) > 1
draw_trash(pos, width, height, lift, orientation, pr) draw_trash(pos, width, height, lift, orientation, pr, is_blackstone)
local chest_pos = draw_stairs(pos, width, height, lift, orientation, pr, is_chain, param2) local chest_pos = draw_stairs(pos, width, height, lift, orientation, pr, is_chain, param2, is_blackstone)
draw_frame({x = pos.x, y = pos.y + lift, z = pos.z}, width + 2, height + 2, orientation, pr, is_chain, rotation) draw_frame({x = pos.x, y = pos.y + lift, z = pos.z}, width + 2, height + 2, orientation, pr, is_chain, rotation, is_blackstone)
if not chest_pos then return end if not chest_pos then return end
local lootitems = mcl_loot.get_loot( local lootitems = mcl_loot.get_loot(
@ -575,7 +672,7 @@ local function place(pos, rotation, pr)
{itemstring = "mcl_clock:clock", weight = 5}, {itemstring = "mcl_clock:clock", weight = 5},
{itemstring = "mesecons_pressureplates:pressure_plate_gold_off", weight = 5}, {itemstring = "mesecons_pressureplates:pressure_plate_gold_off", weight = 5},
{itemstring = "mobs_mc:gold_horse_armor", weight = 5}, {itemstring = "mobs_mc:gold_horse_armor", weight = 5},
{itemstring = "mcl_core:goldblock", weight = 1, amount_min = 1, amount_max = 2}, {itemstring = TOP_DECOR1, weight = 1, amount_min = 1, amount_max = 2},
{itemstring = "mcl_bells:bell", weight = 1}, {itemstring = "mcl_bells:bell", weight = 1},
{itemstring = "mcl_core:apple_gold_enchanted", weight = 1}, {itemstring = "mcl_core:apple_gold_enchanted", weight = 1},
} }
@ -588,6 +685,24 @@ local function place(pos, rotation, pr)
mcl_loot.fill_inventory(inv, "main", lootitems, pr) mcl_loot.fill_inventory(inv, "main", lootitems, pr)
end end
local function place(pos, rotation, pr)
local width = pr:next(2, 10)
local height = pr:next(((width < 3) and 3 or 2), math.floor((10 + width/2)))
local lift = pr:next(0, 2)
local rotation = rotation or possible_rotations[pr:next(1, #possible_rotations)]
common_place(pos, rotation, pr, width, height, lift, false)
minetest.log("action","Ruined portal generated at " .. minetest.pos_to_string(pos))
end
local function place_blackstone(pos, rotation, pr)
local width = pr:next(2, 5)
local height = pr:next(((width < 3) and 3 or 2), math.floor((5 + width/2)))
local lift = pr:next(0, 1)
local rotation = rotation or possible_rotations[pr:next(1, #possible_rotations)]
common_place(pos, rotation, pr, width, height, lift, true)
minetest.log("action","Ruined portal v2 generated at " .. minetest.pos_to_string(pos))
end
local function get_place_rank(pos) local function get_place_rank(pos)
local x, y, z = pos.x, pos.y, pos.z local x, y, z = pos.x, pos.y, pos.z
local p1 = {x = x , y = y, z = z } local p1 = {x = x , y = y, z = z }
@ -630,3 +745,35 @@ mcl_structures.register_structure({
end, end,
place_function = place, place_function = place,
}) })
mcl_structures.register_structure({
name = "ruined_portal_black",
decoration = {
deco_type = "simple",
flags = "all_floors",
fill_ratio = scanning_ratio,
height = 1,
place_on = {"mcl_nether:netherrack", "mcl_nether:soul_sand", "mcl_nether:nether_lava_source", "mcl_core:lava_source"},
},
on_finished_chunk = function(minp, maxp, seed, vm_context, pos_list)
if minp.y > mcl_mapgen.nether.max 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_blackstone(pos, nil, pr)
end,
place_function = place_blackstone,
})

View File

@ -1,3 +1,6 @@
local modpath = minetest.get_modpath(minetest.get_current_modname())
dofile(modpath .. "/ratelimit.lua")
local enable_anticheat = true local enable_anticheat = true
local kick_cheaters = false local kick_cheaters = false
local kick_threshold = 10 local kick_threshold = 10

View File

@ -0,0 +1,21 @@
-- by LoneWolfHT
-- https://github.com/minetest/minetest/issues/12220#issuecomment-1108789409
local ratelimit = {}
local after = minetest.after
local LIMIT = 2
local function remove_entry(ip)
ratelimit[ip] = nil
end
minetest.register_on_mods_loaded(function()
table.insert(core.registered_on_prejoinplayers, 1, function(player, ip)
if ratelimit[ip] then
return "You are joining too fast, please try again"
else
ratelimit[ip] = true
after(LIMIT, remove_entry, ip)
end
end)
end)

154
tools/texture_editor.py Normal file
View File

@ -0,0 +1,154 @@
from http.server import BaseHTTPRequestHandler, HTTPServer
from pathlib import Path
import pprint
import time
import glob
import os
hostName = "localhost"
serverPort = 8080
paths = {}
def dump(obj):
s = ''
for attr in dir(obj):
s = s + "obj.%s = %r" % (attr, getattr(obj, attr)) + "\n"
return s
def get_png(path):
if path in paths:
return Path(pahts[path]).read_bytes()
for file in glob.glob("../**/" + path, recursive = True):
paths[path] = file
return Path(file).read_bytes()
return
def scan():
for file in glob.glob("../**/*.png", recursive = True):
basename = os.path.basename(file)
if basename in paths:
print("Duplicate texture name, please fix:\n * %s:\n - %s\n - %s\n" % (basename, paths[basename], file))
else:
paths[basename] = file
def color_picker():
return """
<canvas id="myCanvas" width="256" height="256"></canvas>
<br/>
<input type='text' size=7 id='color'/>
<script>
function componentToHex(c) {
var hex = c.toString(16);
return hex.length == 1 ? "0" + hex : hex;
}
function function_down(v, d){
if (d<=1) {
return Math.min(255, Math.floor((1-v) * d * 255))
}
return 255-Math.min(255, Math.floor(v * (2-d) * 255))
}
function function_up(v, d){
if (d<=1) {
return Math.min(255, Math.floor(v * d * 255))
}
return 255-Math.min(255, Math.floor((1-v) * (2-d) * 255))
}
function function_keep(v, d){
return Math.min(Math.floor(d*255), 255)
}
function getColorAtXY(x, y){
var x0 = (x - 128) / 128;
var y0 = (y - 128) / 128;
var alpha = 0.5 - Math.atan2(y0, x0) / 2 / Math.PI;
var sector_alpha = alpha*3;
var sector_number = 2 - Math.floor(sector_alpha);
sector_alpha = sector_alpha - Math.floor(sector_alpha);
var distance = Math.sqrt(x0 * x0 + y0*y0) * dist_mult;
if (sector_number == 0) {
return {
"r" : function_up(sector_alpha, distance),
"b" : function_down(sector_alpha, distance),
"g" : function_keep(sector_alpha, distance)
};
}
if (sector_number == 1) {
return {
"g" : function_up(sector_alpha, distance),
"r" : function_down(sector_alpha, distance),
"b" : function_keep(sector_alpha, distance)
};
}
return {
"b" : function_up(sector_alpha, distance),
"g" : function_down(sector_alpha, distance),
"r" : function_keep(sector_alpha, distance)
};
};
var canvas = document.getElementById("myCanvas");
canvas.addEventListener('mousedown', function(e) {
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const color = getColorAtXY(x, y);
const rgb = '#' + componentToHex(color.r) + componentToHex(color.g) + componentToHex(color.b);
document.body.style.background = rgb;
document.getElementById('color').value = rgb;
}, false)
var ctx = canvas.getContext("2d");
var canvasData = ctx.getImageData(0, 0, 256, 256);
var dist_mult = 2 / Math.sqrt(2);
var index = 0;
for (var y = 0; y < 256; y++) {
for (var x = 0; x < 256; x++) {
var color = getColorAtXY(x, y);
canvasData.data[index++] = color.r;
canvasData.data[index++] = color.g;
canvasData.data[index++] = color.b;
canvasData.data[index++] = 255;
}
}
ctx.putImageData(canvasData, 0, 0)
</script>
"""
def get_html(path):
content = "<p>Request: %s</p>" % path
content += "<body>"
content += color_picker()
content += "<ul>Texture List:"
for key, value in paths.items():
content += "<li><a href='%s'>%s</a></li>" % (key, key)
content += "</ul>"
content += "</body></html>"
return content
class MyServer(BaseHTTPRequestHandler):
def do_GET(self):
path = self.path
if path.endswith(".png"):
content = get_png(path)
self.send_response(200)
self.send_header("Content-type", "image/png")
self.end_headers()
self.wfile.write(content)
else:
content = get_html(path)
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(bytes(content, "utf-8"))
if __name__ == "__main__":
scan()
webServer = HTTPServer((hostName, serverPort), MyServer)
print("Server started http://%s:%s" % (hostName, serverPort))
try:
webServer.serve_forever()
except KeyboardInterrupt:
pass
webServer.server_close()
print("Server stopped.")

21
tools/update_credits.sh Executable file
View File

@ -0,0 +1,21 @@
#!/bin/bash
#
TMP_FILE=$(mktemp /tmp/mcl5.XXXXXXXX)
git --version 2>/dev/null 1>/dev/null
IS_GIT_AVAILABLE=$?
if [ $IS_GIT_AVAILABLE -ne 0 ]; then
echo "Please install git!\n\n"
fi
`git log --pretty="%an" 1>$TMP_FILE 2>/dev/null`
IS_GIT_REPO=$?
if [ $IS_GIT_REPO -ne 0 ]; then
echo "You have to be inside a git repo to update CONTRUBUTOR_LIST.txt\n\n"
fi
# Edit names here:
sed -i 's/nikolaus-albinger/Niklp/g' $TMP_FILE
cat $TMP_FILE | sort | uniq >../mods/HUD/mcl_credits/CONTRUBUTOR_LIST.txt