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
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.
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},
}
local EDGE_MIN = mcl_mapgen.EDGE_MIN
local EDGE_MAX = mcl_mapgen.EDGE_MAX
local function is_chunk_finished(minp)
local center = vector.add(minp, HALF_CS_NODES)
for check_x = center.x - CS_NODES, center.x + CS_NODES, CS_NODES do
for check_y = center.y - CS_NODES, center.y + CS_NODES, CS_NODES do
for check_z = center.z - CS_NODES, center.z + CS_NODES, CS_NODES do
local pos = vector.new(check_x, check_y, check_z)
if pos ~= center then
minetest_get_voxel_manip():read_from_map(pos, pos)
local node = minetest_get_node(pos)
local center_x = minp.x + HALF_CS_NODES
local center_y = minp.y + HALF_CS_NODES
local center_z = minp.z + HALF_CS_NODES
local from_x = center_x - CS_NODES
local from_y = center_y - CS_NODES
local from_z = center_z - CS_NODES
local to_x = center_x + CS_NODES
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
-- 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
end
end

View File

@ -1,5 +1,11 @@
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*.
function table.update(t, ...)
for _, to in ipairs{...} do
@ -33,36 +39,6 @@ function mcl_util.rotate_axis(itemstack, placer, pointed_thing)
return itemstack
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
-- returns the slot of the first item which matches a condition.
-- Returns nil if no item was found.
@ -87,7 +63,7 @@ end
-- Returns true if itemstack is a shulker box
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
end
@ -133,137 +109,117 @@ 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)
--- destination_list (optional): List name of the destination inventory. Default is normally "main"; "src" for furnace
-- 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)
local dpos = table.copy(destination_pos)
local spos = table.copy(source_pos)
local snode = minetest.get_node(spos)
local dnode = minetest.get_node(dpos)
local dctype = minetest.get_item_group(dnode.name, "container")
local sctype = minetest.get_item_group(snode.name, "container")
-- Container type 7 does not allow any movement
if sctype == 7 then
return false
local spos = table_copy(source_pos)
local snode = minetest_get_node(spos)
local sctype = minetest_get_item_group(snode.name, "container")
local default_source_list = CONTAINER_GROUP_TO_LIST[sctype]
if not default_source_list then return end
if sctype == DOUBLE_CHEST_RIGHT then
local sparam2 = snode.param2
if sparam2 == 0 then spos.x = spos.x - 1
elseif sparam2 == 1 then spos.z = spos.z + 1
elseif sparam2 == 2 then spos.x = spos.x + 1
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
snode = minetest_get_node(spos)
sctype = minetest_get_item_group(snode.name, "container")
if sctype ~= DOUBLE_CHEST_LEFT then return end
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
return pos, node, ctype
end
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 smeta = minetest_get_meta(spos)
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()
-- 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
if not source_stack_id then
source_stack_id = -1
end
local source_stack_id = source_stack_id or -1
if source_stack_id == -1 then
local cond = nil
-- Prevent shulker box inception
if dctype == 3 then
cond = is_not_shulker_box
end
if dctype == SHULKER_BOX then cond = is_not_shulker_box end
source_stack_id = mcl_util.get_eligible_transfer_item_slot(sinv, source_list, dinv, dpos, cond)
if not source_stack_id then
-- Try again if source is a double container
if sctype == 5 then
spos = mcl_util.get_double_container_neighbor_pos(spos, snode.param2, "left")
smeta = minetest.get_meta(spos)
if sctype == DOUBLE_CHEST_LEFT then
local sparam2 = snode.param2
if sparam2 == 0 then spos.x = spos.x + 1
elseif sparam2 == 1 then spos.z = spos.z - 1
elseif sparam2 == 2 then spos.x = spos.x - 1
elseif sparam2 == 3 then spos.z = spos.z + 1
end
snode = minetest_get_node(spos)
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)
if not source_stack_id then
return false
end
else
return false
end
end
if not source_stack_id then return end
end
-- 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)
if stack and minetest.get_item_group(stack:get_name(), "shulker_box") == 1 then
return false
end
end
-- Container type 7 does not allow any placement
if dctype == 7 then
return false
if stack and minetest_get_item_group(stack:get_name(), "shulker_box") == 1 then return end
end
-- If it's a container, put it into the container
if dctype ~= 0 then
-- Automatically select a destination list if omitted
if not destination_list then
-- Main inventory for most container types
if dctype == 2 or dctype == 3 or dctype == 5 or dctype == 6 or dctype == 7 then
destination_list = "main"
-- Furnace source slot
elseif dctype == 4 then
destination_list = "src"
end
end
if destination_list then
local destination_list = destination_list or default_destination_list
-- Move item
local ok = mcl_util.move_item(sinv, source_list, source_stack_id, dinv, destination_list)
-- Try transfer to neighbor node if transfer failed and double container
if not ok and dctype == 5 then
dpos = mcl_util.get_double_container_neighbor_pos(dpos, dnode.param2, "left")
dmeta = minetest.get_meta(dpos)
if not ok then
if dctype == DOUBLE_CHEST_LEFT 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_RIGHT then return end
dmeta = minetest_get_meta(dpos)
dinv = dmeta:get_inventory()
ok = mcl_util.move_item(sinv, source_list, source_stack_id, dinv, destination_list)
end
end
-- Update furnace
if ok and dctype == 4 then
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)
minetest_get_node_timer(dpos):start(1.0)
end
return ok
end
end
return false
end
-- Returns the ID of the first non-empty slot in the given inventory list
-- or nil, if inventory is empty.
@ -292,7 +248,7 @@ function mcl_util.generate_on_place_plant_function(condition)
end
-- 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 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
@ -300,8 +256,8 @@ function mcl_util.generate_on_place_plant_function(condition)
end
local place_pos
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_under = minetest.registered_nodes[minetest_get_node(pointed_thing.under).name]
local def_above = minetest.registered_nodes[minetest_get_node(pointed_thing.above).name]
if not def_under or not def_above then
return itemstack
end
@ -359,7 +315,7 @@ function mcl_util.call_on_rightclick(itemstack, player, pointed_thing)
-- Call on_rightclick if the pointed node defines it
if pointed_thing and pointed_thing.type == "node" then
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
local nodedef = minetest.registered_nodes[node.name]
local on_rightclick = nodedef and nodedef.on_rightclick
@ -372,7 +328,7 @@ end
function mcl_util.calculate_durability(itemstack)
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

View File

@ -88,7 +88,7 @@ local function land_state_switch(self, dtime)
end
--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_timer or (self.breed_timer and self.breed_timer == 0)) then
self.state = "follow"
@ -984,7 +984,7 @@ function mobs.mob_step(self, dtime)
--go get the closest player
if attacking then
mobs.do_head_logic(self, dtime, attacking)
self.memory = 6 --6 seconds of memory
--set initial punch timer
@ -1040,6 +1040,7 @@ function mobs.mob_step(self, dtime)
--don't break eye contact
if self.hostile and self.attacking then
mobs.set_yaw_while_attacking(self)
mobs.do_head_logic(self, dtime, self.attacking)
end
--perfectly reset pause_timer

View File

@ -3,7 +3,7 @@ local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius
local vector = vector
--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
if not self.follow then
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
if follower and follower:is_player() then
mobs.do_head_logic(self, dtime, follower)
local stack = follower:get_wielded_item()
--safety check
if not stack then

View File

@ -6,9 +6,9 @@ local degrees = function(yaw)
return yaw*180.0/math.pi
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()
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
end
local head_bone = self.head_bone
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(self.head_bone, bone_pos, vector.new(degrees(head_pitch),degrees(head_yaw),0))
self.object:set_bone_position(v, bone_pos, vector.new(degrees(head_pitch),degrees(head_yaw),0))
else
self.object:set_bone_position(self.head_bone, bone_pos, vector.new(degrees(head_pitch),0,degrees(head_yaw)))
self.object:set_bone_position(v, bone_pos, vector.new(degrees(head_pitch),0,degrees(head_yaw)))
end
end
else
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
--set_bone_position([bone, position, rotation])
end

View File

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

View File

@ -611,7 +611,9 @@ do
io.close(file)
if string then
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
if savetable_players_stored_data then
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
@ -619,6 +621,7 @@ do
end
end
end
end
function doc.save_to_file()
local savetable = {}

View File

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

View File

@ -1,8 +1,4 @@
Please run the following command to update contributor list:
```bash
# git log --pretty="%an" | sort | uniq >CONTRUBUTOR_LIST.txt
```
Please run `./update_credits.sh` from [tools](../../../tools) folder to update contributor list.
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 huds = {}
local default_debug = 3
local default_debug = 5
local after = minetest.after
local get_connected_players = minetest.get_connected_players
local get_biome_name = minetest.get_biome_name
local get_biome_data = minetest.get_biome_data
local get_node = minetest.get_node
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 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 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 function get_text(pos, bits)
local pos = pos
local bits = bits
if bits == 0 then return "" end
local y = pos.y
@ -27,16 +34,42 @@ local function get_text(pos, bits)
elseif y >= min2 and y <= max2 then
y = y - min2
end
local will_show_mapgen_status = bits % 8 > 3
local will_show_coordinates = bits % 4 > 1
local will_show_biome_name = bits % 2 > 0
local will_be_shown = {}
if will_show_biome_name then
local biome_data = get_biome_data(pos)
local biome_name = biome_data and get_biome_name(biome_data.biome) or "No biome"
local text
if bits == 1 then
text = biome_name
elseif bits == 2 then
text = format("x:%.1f y:%.1f z:%.1f", pos.x, y, pos.z)
elseif bits == 3 then
text = format("%s x:%.1f y:%.1f z:%.1f", biome_name, pos.x, y, pos.z)
will_be_shown[#will_be_shown + 1] = biome_name
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
end
@ -82,11 +115,11 @@ minetest.register_on_authplayer(function(name, ip, is_success)
end)
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)
local dbg = math.floor(tonumber(params) or default_debug)
if dbg < 0 or dbg > 3 then
minetest.chat_send_player(name, S("Error! Possible values are integer numbers from @1 to @2", 0, 3))
if dbg < 0 or dbg > 7 then
minetest.chat_send_player(name, S("Error! Possible values are integer numbers from @1 to @2", 0, 7))
return
end
if dbg == default_debug then

View File

@ -1,4 +1,4 @@
# 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
Debug bit mask set to @1=Masque de débugage réglé à @1

View File

@ -1,4 +1,4 @@
# 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
Debug bit mask set to @1=Отладочной битовой маске присвоено значение @1

View File

@ -1,4 +1,4 @@
# 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=
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", {
initial_properties = {
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")
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})
mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules)
elseif node.name == "mcl_chests:trapped_chest_on_right" then
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_right", param2 = node.param2})
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})
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)
@ -438,15 +462,15 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
-- BEGIN OF LISTRING WORKAROUND
inv:set_size("input", 1)
-- 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})
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 })
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})
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 })
else
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)
local n = minetest.get_node(pos)
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
n.name = "mcl_chests:"..canonical_basename.."_small"
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)
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
return
end
@ -581,7 +605,7 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
-- BEGIN OF LISTRING WORKAROUND
elseif listname == "input" then
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})
return limit_put(stack, inv, other_inv)
--[[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
if listname == "input" then
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})
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,
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_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)
local n = minetest.get_node(pos)
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
n.name = "mcl_chests:"..canonical_basename.."_small"
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)
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
return
end
@ -730,7 +754,7 @@ local function register_chest(basename, desc, longdesc, usagehelp, tt_help, tile
return 0
-- BEGIN OF LISTRING WORKAROUND
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 inv = minetest.get_inventory({type="node", pos=pos})
--[[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))
-- BEGIN OF LISTRING WORKAROUND
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 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,
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
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
@ -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")
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})
mesecon.receptor_on(pos_other, trapped_chest_mesecons_rules)
end,
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})
mesecon.receptor_on(pos, trapped_chest_mesecons_rules)

View File

@ -63,38 +63,40 @@ local function add_wear(placer, itemstack)
end
local function anti_oxidation(itemstack, placer, pointed_thing)
local pointed_thing = pointed_thing
if pointed_thing.type ~= "node" then return end
local node = minetest.get_node(pointed_thing.under)
local noddef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
local pointed_thing_under = pointed_thing.under
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)
end
if minetest.is_protected(pointed_thing.under, placer:get_player_name()) then
minetest.record_protection_violation(pointed_thing.under, placer:get_player_name())
local placer_name = placer:get_player_name()
if minetest.is_protected(pointed_thing_under, placer_name) then
minetest.record_protection_violation(pointed_thing_under, placer_name)
return itemstack
end
if noddef._mcl_stripped_variant == nil then
if not node_def._mcl_stripped_variant then
for _, c in pairs(stairs) do
if noddef.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})
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})
anti_oxidation_particles(pointed_thing)
add_wear(placer, itemstack)
end
end
if noddef._mcl_anti_oxidation_variant ~= nil then
minetest.swap_node(pointed_thing.under, {name=noddef._mcl_anti_oxidation_variant, param2=node.param2})
if node_def._mcl_anti_oxidation_variant then
minetest.swap_node(pointed_thing_under, {name=node_def._mcl_anti_oxidation_variant, param2=node.param2})
anti_oxidation_particles(pointed_thing)
add_wear(placer, itemstack)
end
elseif noddef._mcl_stripped_variant ~= nil then
minetest.swap_node(pointed_thing.under, {name=noddef._mcl_stripped_variant, param2=node.param2})
elseif node_def._mcl_stripped_variant then
minetest.swap_node(pointed_thing_under, {name=node_def._mcl_stripped_variant, param2=node.param2})
add_wear(placer, itemstack)
else
return itemstack
end
return itemstack
end

View File

@ -4,11 +4,21 @@
local modpath = minetest.get_modpath(minetest.get_current_modname())
local mg_name = mcl_mapgen.name
local v6 = mcl_mapgen.v6
local math = math
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 DARK_OAK_TREE_ID = 2
@ -26,11 +36,11 @@ minetest.register_abm({
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 lavatype = minetest.registered_nodes[node.name].liquidtype
local lavatype = minetest_registered_nodes[node.name].liquidtype
for w=1, #water do
--local waternode = minetest.get_node(water[w])
--local watertype = minetest.registered_nodes[waternode.name].liquidtype
--local waternode = minetest_get_node(water[w])
--local watertype = minetest_registered_nodes[waternode.name].liquidtype
-- 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
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()
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_census = 0
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
mcl_core.lava_spark_set_chance()
@ -87,57 +134,20 @@ if lava_spark_limit > 0 then
interval = LAVA_SPARK_ABM_INTERVAL,
chance = 18,
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
lava_spark_abm_census = lava_spark_abm_census + 1
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
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
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", {
physical = true,
visual = "sprite",
@ -159,7 +169,7 @@ minetest.register_entity("mcl_core:lava_spark", {
self._smoke_timer = self._smoke_timer - dtime
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()
@ -185,44 +195,23 @@ minetest.register_entity("mcl_core:lava_spark", {
end
})
--
-- Papyrus and cactus growing
--
-- 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)
pos.y = pos.y-1
local name = minetest.get_node(pos).name
if minetest.get_item_group(name, "soil_sugarcane") ~= 0 then
local name = minetest_get_node(pos).name
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
return
end
pos.y = pos.y+1
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
pos.y = pos.y+1
end
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"})
end
end
@ -231,18 +220,17 @@ end
-- ABMs
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
return
end
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 = {
x = p.x + math.random()/2 - 0.25,
y = p.y + math.random()/2 - 0.25,
z = p.z + math.random()/2 - 0.25,
x = p.x + math_random()/2 - 0.25,
y = p.y + math_random()/2 - 0.25,
z = p.z + math_random()/2 - 0.25,
}
if item ~= "" then
minetest.add_item(pos, item)
@ -254,11 +242,11 @@ end
local function liquid_flow_action(pos, group, action)
local function check_detach(pos, xp, yp, 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
return false
end
local d = minetest.registered_nodes[n.name]
local d = minetest_registered_nodes[n.name]
if not d then
return false
end
@ -267,7 +255,7 @@ local function liquid_flow_action(pos, group, action)
* 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 ]]
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 and ((d.liquidtype == "source") or (n.param2 > (8-range) and n.param2 < 9)))) then
action(pos)
@ -316,17 +304,23 @@ minetest.register_abm({
end,
})
-- Cactus mechanisms
minetest.register_abm({
label = "Cactus growth",
nodenames = {"mcl_core:cactus"},
neighbors = {"group:sand"},
interval = 25,
chance = 10,
action = function(pos)
mcl_core.grow_cactus(pos)
end,
})
local function cactus_grow(pos, node)
local pos = pos
local y = pos.y
pos.y = y - 1
local name = minetest_get_node(pos).name
if minetest_get_item_group(name, "sand") == 0 then return end
for i = 1, 2 do
pos.y = y + i
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({
label = "Cactus mechanisms",
@ -334,39 +328,34 @@ minetest.register_abm({
interval = 1,
chance = 1,
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()
if entity then
local entity_name = entity.name
if entity_name == "__builtin:item" then
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
local posses = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } }
for _, p in pairs(posses) do
if minetest.registered_nodes[minetest.get_node(vector.new(pos.x + p[1], pos.y, pos.z + p[2])).name].walkable then
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
for i = 1, mcl_time_get_number_of_times_at_pos(pos, 25, 10) do
cactus_grow(pos)
end
end,
})
@ -393,7 +382,7 @@ minetest.register_on_dignode(function(pos, node)
local i=1
while timber_nodenames[i]~=nil do
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.add_item(np, timber_nodenames[i])
np={x=np.x, y=np.y+1, z=np.z}
@ -403,7 +392,7 @@ minetest.register_on_dignode(function(pos, node)
end)
local function air_leaf(leaftype)
if math.random(0, 50) == 3 then
if math_random(0, 50) == 3 then
return {name = "air"}
else
return {name = leaftype}
@ -417,7 +406,7 @@ local function node_stops_growth(node)
return false
end
local def = minetest.registered_nodes[node.name]
local def = minetest_registered_nodes[node.name]
if not def then
return true
end
@ -450,7 +439,7 @@ local function check_growth_width(pos, width, height)
pos.x + x,
pos.y + y,
pos.z + z)
if node_stops_growth(minetest.get_node(np)) then
if node_stops_growth(minetest_get_node(np)) then
return false
end
end
@ -502,10 +491,10 @@ end
-- oak tree.
function mcl_core.generate_tree(pos, tree_type, options)
pos.y = pos.y-1
--local nodename = minetest.get_node(pos).name
--local nodename = minetest_get_node(pos).name
pos.y = pos.y+1
if not minetest.get_node_light(pos) then
if not minetest_get_node_light(pos) then
return
end
@ -558,7 +547,7 @@ function mcl_core.generate_v6_oak_tree(pos)
local node
for dy=1,4 do
pos.y = pos.y+dy
if minetest.get_node(pos).name ~= "air" then
if minetest_get_node(pos).name ~= "air" then
return
end
pos.y = pos.y-dy
@ -566,7 +555,7 @@ function mcl_core.generate_v6_oak_tree(pos)
node = {name = trunk}
for dy=0,4 do
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)
end
pos.y = pos.y-dy
@ -575,7 +564,7 @@ function mcl_core.generate_v6_oak_tree(pos)
node = {name = leaves}
pos.y = pos.y+3
--[[local rarity = 0
if math.random(0, 10) == 3 then
if math_random(0, 10) == 3 then
rarity = 1
end]]
for dx=-2,2 do
@ -586,23 +575,23 @@ function mcl_core.generate_v6_oak_tree(pos)
pos.z = pos.z+dz
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, air_leaf(leaves))
end
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, air_leaf(leaves))
end
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, air_leaf(leaves))
end
else
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, air_leaf(leaves))
end
@ -620,14 +609,14 @@ end
function mcl_core.generate_balloon_oak_tree(pos)
local path
local offset
local s = math.random(1, 12)
local s = math_random(1, 12)
if s == 1 then
-- Small balloon oak
path = modpath .. "/schematics/mcl_core_oak_balloon.mts"
offset = { x = -2, y = -1, z = -2 }
else
-- Large balloon oak
local t = math.random(1, 4)
local t = math_random(1, 4)
path = modpath .. "/schematics/mcl_core_oak_large_"..t..".mts"
if t == 1 or t == 3 then
offset = { x = -3, y = -1, z = -3 }
@ -666,7 +655,7 @@ end
function mcl_core.generate_v6_spruce_tree(pos)
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_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 via = a:index(x - dev, yy + 1, zz)
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,
c_spruce_leaves)
end
@ -709,9 +698,9 @@ function mcl_core.generate_v6_spruce_tree(pos)
-- Lower branches layer
local my = 0
for i = 1, 20 do -- Random 2x2 squares of leaves
local xi = x + math.random(-3, 2)
local yy = maxy + math.random(-6, -5)
local zi = z + math.random(-3, 2)
local xi = x + math_random(-3, 2)
local yy = maxy + math_random(-6, -5)
local zi = z + math_random(-3, 2)
if yy > my then
my = yy
end
@ -733,7 +722,7 @@ function mcl_core.generate_v6_spruce_tree(pos)
local vi = a:index(x - dev, yy, zz)
local via = a:index(x - dev, yy + 1, zz)
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,
c_spruce_leaves)
end
@ -761,14 +750,14 @@ function mcl_core.generate_v6_spruce_tree(pos)
end
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"
minetest.place_schematic({ x = pos.x - 3, y = pos.y - 1, z = pos.z - 3 }, path, "0", nil, false)
end
function mcl_core.generate_huge_spruce_tree(pos)
local r1 = math.random(1, 2)
local r2 = math.random(1, 4)
local r1 = math_random(1, 2)
local r2 = math_random(1, 4)
local path
local offset = { x = -4, y = -1, z = -5 }
if r1 <= 2 then
@ -788,7 +777,7 @@ end
-- Acacia tree (multiple variants)
function mcl_core.generate_acacia_tree(pos)
local r = math.random(1, 7)
local r = math_random(1, 7)
local offset = vector.new()
if r == 2 or r == 3 then
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.
for i = 1, iters do
local clust_x = x + math.random(-size, size - 1)
local clust_y = y + height + math.random(-size, 0)
local clust_z = z + 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_z = z + math_random(-size, size - 1)
for xi = 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 height = math.random(8, 12)
local height = math_random(8, 12)
local c_air = minetest.get_content_id("air")
local c_ignore = minetest.get_content_id("ignore")
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_2 = a:index(x - 1, y, z + z_dist)
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
data[vi_1] = c_jungletree
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.
function mcl_core.generate_huge_jungle_tree(pos)
-- 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"
minetest.place_schematic({x = pos.x - 6, y = pos.y - 1, z = pos.z - 7}, path, "random", nil, false)
end
@ -954,12 +943,12 @@ minetest.register_abm({
return
end
local above = {x=pos.x, y=pos.y+1, z=pos.z}
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
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
-- Never grow directly below liquids or opaque blocks
return
end
local light_self = minetest.get_node_light(above)
local light_self = minetest_get_node_light(above)
if not light_self then return end
--[[ 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. ]]
@ -974,20 +963,20 @@ minetest.register_abm({
-- Found it! Now check light levels!
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 light_self >= 4 and light_source >= 9 then
-- All checks passed! Let's spread the grass/mycelium!
local n2 = minetest.get_node(p2)
if minetest.get_item_group(n2.name, "grass_block") ~= 0 then
local n2 = minetest_get_node(p2)
if minetest_get_item_group(n2.name, "grass_block") ~= 0 then
n2 = mcl_core.get_grass_block_type(pos)
end
minetest.set_node(pos, {name=n2.name})
-- If this was mycelium, uproot plant above
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
minetest.dig_node(above)
end
@ -1005,9 +994,9 @@ minetest.register_abm({
catch_up = false,
action = function(pos, node)
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
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"})
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
minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
if minetest.get_item_group(newnode.name, "solid") ~= 0 or
minetest.get_item_group(newnode.name, "dirtifier") ~= 0 then
if minetest_get_item_group(newnode.name, "solid") ~= 0 or
minetest_get_item_group(newnode.name, "dirtifier") ~= 0 then
local below = {x=pos.x, y=pos.y-1, z=pos.z}
local belownode = minetest.get_node(below)
if minetest.get_item_group(belownode.name, "dirtifies_below_solid") == 1 then
local belownode = minetest_get_node(below)
if minetest_get_item_group(belownode.name, "dirtifies_below_solid") == 1 then
minetest.set_node(below, {name="mcl_core:dirt"})
end
end
@ -1033,8 +1022,8 @@ minetest.register_abm({
chance = 50,
action = function(pos, node)
local above = {x = pos.x, y = pos.y + 1, z = pos.z}
local name = minetest.get_node(above).name
local nodedef = minetest.registered_nodes[name]
local name = minetest_get_node(above).name
local nodedef = minetest_registered_nodes[name]
if name ~= "ignore" and nodedef and (nodedef.groups and nodedef.groups.solid) then
minetest.set_node(pos, {name = "mcl_core:dirt"})
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)
if meta:get("grown") then return end
-- 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
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 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
-- 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 soiltype = minetest.get_item_group(soilnode.name, "soil_sapling")
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")
if soiltype < soil_needed then return end
-- 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
-- Check 8 surrounding saplings and try to find a 2×2 pattern
local function is_sapling(pos, sapling)
return minetest.get_node(pos).name == sapling
return minetest_get_node(pos).name == sapling
end
local p2 = {x=pos.x+1, y=pos.y, z=pos.z}
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
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
if math.random(1, 12) == 1 then
if math_random(1, 12) == 1 then
-- Check if there is room for that
if check_tree_growth(pos, tree_id, { balloon = true }) then
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
-- Single sapling
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)
return
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
-- 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
function mcl_core.grow_sapling(pos, node)
local grow
@ -1337,7 +1326,7 @@ minetest.register_lbm({
local function leafdecay_particles(pos, node)
minetest.add_particlespawner({
amount = math.random(10, 20),
amount = math_random(10, 20),
time = 0.1,
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}),
@ -1375,7 +1364,7 @@ local function vinedecay_particles(pos, node)
end
minetest.add_particlespawner({
amount = math.random(8, 16),
amount = math_random(8, 16),
time = 0.1,
minpos = vector.add(pos, relpos1),
maxpos = vector.add(pos, relpos2),
@ -1413,8 +1402,8 @@ minetest.register_abm({
-- Add vines below pos (if empty)
local function spread_down(origin, target, dir, node)
if math.random(1, 2) == 1 then
if minetest.get_node(target).name == "air" then
if math_random(1, 2) == 1 then
if minetest_get_node(target).name == "air" then
minetest.add_node(target, {name = "mcl_core:vine", param2 = node.param2})
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")
-- 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 math.random(1, 2) == 1 then
if minetest.get_node(target).name == "air" then
if math_random(1, 2) == 1 then
if minetest_get_node(target).name == "air" then
local backup_dir = minetest.wallmounted_to_dir(node.param2)
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
if mcl_core.supports_vines(backupnodename) then
@ -1447,10 +1436,10 @@ minetest.register_abm({
-- Spread horizontally
local backup_dir = minetest.wallmounted_to_dir(node.param2)
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
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
minetest.add_node(target, {name = "mcl_core:vine", param2 = node.param2})
end
@ -1468,7 +1457,7 @@ minetest.register_abm({
{ { 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 spread = directions[d][2]
@ -1478,7 +1467,7 @@ minetest.register_abm({
-- Returns true of the node supports vines
function mcl_core.supports_vines(nodename)
local def = minetest.registered_nodes[nodename]
local def = minetest_registered_nodes[nodename]
-- Rules: 1) walkable 2) full cube
return def.walkable and
(def.node_box == nil or def.node_box.type == "regular") and
@ -1516,11 +1505,11 @@ minetest.register_abm({
action = function(p0, node, _, _)
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
return
end
local n0 = minetest.get_node(p0)
local n0 = minetest_get_node(p0)
if n0.param2 ~= 0 then
-- Prevent leafdecay for player-placed leaves.
-- 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)
local trunkp = mcl_core.leafdecay_trunk_cache[p0_hash]
if trunkp then
local n = minetest.get_node(trunkp)
local reg = minetest.registered_nodes[n.name]
local n = minetest_get_node(trunkp)
local reg = minetest_registered_nodes[n.name]
-- 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
return
@ -1557,12 +1546,12 @@ minetest.register_abm({
end
if not do_preserve then
-- 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
local p_drop = {
x = p0.x - 0.5 + math.random(),
y = p0.y - 0.5 + math.random(),
z = p0.z - 0.5 + math.random(),
x = p0.x - 0.5 + math_random(),
y = p0.y - 0.5 + math_random(),
z = p0.z - 0.5 + math_random(),
}
minetest.add_item(p_drop, itemname)
end
@ -1581,7 +1570,7 @@ minetest.register_abm({
}
for s=1, #surround do
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)
if maybe_vine.name == "mcl_core:vine" and (not mcl_core.check_vines_supported(spos, maybe_vine)) then
minetest.remove_node(spos)
@ -1622,7 +1611,7 @@ minetest.register_abm({
interval = 16,
chance = 8,
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
mcl_core.melt_ice(pos)
else
@ -1640,7 +1629,7 @@ function mcl_core.check_vines_supported(pos, node)
local supported = false
local dir = minetest.wallmounted_to_dir(node.param2)
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.
-- If ignore, we assume its solid.
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
-- of equal orientation.
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
if node2.name == "ignore" or (node2.name == "mcl_core:vine" and node2.param2 == node.param2) then
supported = true
@ -1662,7 +1651,7 @@ end
function mcl_core.melt_ice(pos)
-- 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 belownode = minetest.get_node(below)
local belownode = minetest_get_node(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
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
-- of the snowed node.
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
if def.description then
create_doc_alias = true
@ -1760,7 +1749,7 @@ end
-- 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.
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
minetest.swap_node(pos, {name = def._mcl_snowless, param2=node.param2})
end
@ -1773,15 +1762,15 @@ end
-- Makes constructed snowable node snowed if placed below a snow cover node.
function mcl_core.on_snowable_construct(pos)
-- Myself
local node = minetest.get_node(pos)
local node = minetest_get_node(pos)
-- Above
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
if minetest.get_item_group(anode.name, "snow_cover") == 1 then
local def = minetest.registered_nodes[node.name]
if minetest_get_item_group(anode.name, "snow_cover") == 1 then
local def = minetest_registered_nodes[node.name]
if def._mcl_snowed then
minetest.swap_node(pos, {name = def._mcl_snowed, param2=node.param2})
end
@ -1801,8 +1790,8 @@ end
-- Makes snowable node below snowed.
function mcl_core.on_snow_construct(pos)
local npos = {x=pos.x, y=pos.y-1, z=pos.z}
local node = minetest.get_node(npos)
local def = minetest.registered_nodes[node.name]
local node = minetest_get_node(npos)
local def = minetest_registered_nodes[node.name]
if def._mcl_snowed then
minetest.swap_node(npos, {name = def._mcl_snowed, param2=node.param2})
end
@ -1810,13 +1799,13 @@ end
-- after_destruct
-- Clears snowed dirtlike node below.
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
if minetest.get_item_group(nn, "snow_cover") == 1 then
if minetest_get_item_group(nn, "snow_cover") == 1 then
return
end
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)
end

View File

@ -1,4 +1,4 @@
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.
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

View File

@ -11,7 +11,23 @@ else
ice_drawtype = "normal"
ice_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false
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 = {
discrete_uniform_distribution = true,
@ -1089,7 +1105,9 @@ minetest.register_node("mcl_core:snowblock", {
_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"),
_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,
@ -1101,39 +1119,39 @@ minetest.register_node("mcl_core:moss", {
_mcl_blast_resistance = 0.1,
_mcl_hardness = 0.1,
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
if player:get_wielded_item():get_name() == "mcl_dye:white" then
if not minetest.is_creative_enabled(player) and not minetest.check_player_privs(player, "creative") then
local pos = pos
local x, y, z = pos.x, pos.y, pos.z
local player_wielded_item = player:get_wielded_item()
local item_name = player_wielded_item:get_name()
if item_name == "mcl_dye:white" then
if not minetest.is_creative_enabled(player) then
itemstack:take_item()
end
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
minetest.set_node(j, {name="mcl_core:moss"})
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
minetest.set_node(p, MOSS_NODE)
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
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 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
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 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
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=j.x,y=j.y+1,z=j.z} ,{name="mcl_flowers:tallgrass"})
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
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
elseif minetest.registered_nodes[item_name] then
if not minetest.is_creative_enabled(player) then
itemstack:take_item()
minetest.set_node(pointed_thing.above, {name=player:get_wielded_item():get_name()})
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,
})

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 get_item_group = minetest.get_item_group
--[[ BEGIN OF NODE DEFINITIONS ]]
local math_abs = math.abs
local mcl_util_move_item_container = mcl_util.move_item_container
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 =
"size[9,7]"..
"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},
drawtype = "nodebox",
paramtype = "light",
-- FIXME: mcl_hoppers_hopper_inside.png is unused by hoppers.
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 = {
type = "fixed",
fixed = {
--funnel walls
{-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.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.4, 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.5, 0.5, -0.4,},
--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
{-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.3, -0.3, -0.3, 0.3, 0.0, 0.3,},
{-0.1, -0.3, -0.1, 0.1, -0.5, 0.1,},
},
},
selection_box = {
type = "fixed",
fixed = {
--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
{-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.3, -0.3, -0.3, 0.3, 0.0, 0.3,},
{-0.1, -0.3, -0.1, 0.1, -0.5, 0.1,},
},
},
is_ground_content = false,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
local meta = minetest_get_meta(pos)
meta:set_string("formspec", mcl_hoppers_formspec)
local inv = meta:get_inventory()
inv:set_size("main", 5)
end,
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()
meta:from_table(oldmetadata)
local inv = meta:get_inventory()
@ -120,10 +143,8 @@ local def_hopper = {
_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
local def_hopper_enabled = table.copy(def_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")
@ -140,8 +161,8 @@ def_hopper_enabled.on_place = function(itemstack, placer, pointed_thing)
local upos = pointed_thing.under
local apos = pointed_thing.above
local uposnode = minetest.get_node(upos)
local uposnodedef = minetest.registered_nodes[uposnode.name]
local uposnode = minetest_get_node(upos)
local uposnodedef = minetest_registered_nodes[uposnode.name]
if not uposnodedef then return itemstack end
-- Use pointed node's on_rightclick function first, if present
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
local x = upos.x - apos.x
local z = upos.z - apos.z
local fake_itemstack = ItemStack(itemstack)
local dx = apos.x - upos.x
local dz = apos.z - upos.z
local param2
if x == -1 then
fake_itemstack:set_name("mcl_hoppers:hopper_side")
param2 = 0
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
if (dx ~= 0) or (dz ~= 0) then
param2 = minetest.dir_to_facedir({x = dx, y = 0, z = dz})
fake_itemstack:set_name(HOPPER_SIDE)
end
local itemstack, _ = minetest.item_place_node(fake_itemstack, placer, pointed_thing, param2)
itemstack:set_name("mcl_hoppers:hopper")
itemstack:set_name(HOPPER)
return itemstack
end
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
local def_hopper_disabled = table.copy(def_hopper)
def_hopper_disabled.description = S("Disabled Hopper")
def_hopper_disabled.inventory_image = nil
def_hopper_disabled._doc_items_create_entry = false
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 = {
effector = {
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,
},
}
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 = {
_doc_items_create_entry = false,
drop = "mcl_hoppers:hopper",
groups = {pickaxey=1, container=2,not_in_creative_inventory=1,hopper=2},
drop = HOPPER,
groups = {
container = 2,
hopper = 2,
not_in_creative_inventory = 1,
pickaxey = 1,
},
drawtype = "nodebox",
paramtype = "light",
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 = {
type = "fixed",
fixed = {
--funnel walls
{-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.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.4, 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.5, 0.5, -0.4,},
--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
{-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.3, -0.3, -0.3, 0.3, 0.0, 0.3,},
{-0.1, -0.3, -0.5, 0.1, -0.1, 0.1,},
},
},
selection_box = {
type = "fixed",
fixed = {
--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
{-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.3, -0.3, -0.3, 0.3, 0.0, 0.3,},
{-0.1, -0.3, -0.5, 0.1, -0.1, 0.1,},
},
},
is_ground_content = false,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
local meta = minetest_get_meta(pos)
meta:set_string("formspec", mcl_hoppers_formspec)
local inv = meta:get_inventory()
inv:set_size("main", 5)
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local meta = minetest.get_meta(pos)
local meta = minetest_get_meta(pos)
local meta2 = meta
meta:from_table(oldmetadata)
local inv = meta:get_inventory()
@ -302,13 +320,15 @@ local def_hopper_side = {
minetest.log("action", player:get_player_name()..
" takes stuff from mcl_hoppers at "..minetest.pos_to_string(pos))
end,
on_rotate = on_rotate,
on_rotate = screwdriver.rotate_simple,
sounds = mcl_sounds.node_sound_metal_defaults(),
_mcl_blast_resistance = 4.8,
_mcl_hardness = 3,
}
-- Enabled sidewards hopper
local def_hopper_side_enabled = table.copy(def_hopper_side)
def_hopper_side_enabled.description = S("Side Hopper")
def_hopper_side_enabled.mesecons = {
@ -318,170 +338,114 @@ def_hopper_side_enabled.mesecons = {
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)
def_hopper_side_disabled.description = S("Disabled Side Hopper")
def_hopper_side_disabled.mesecons = {
effector = {
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,
},
}
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({
label = "Hoppers suck in dropped items",
nodenames = {"mcl_hoppers:hopper","mcl_hoppers:hopper_side"},
interval = 1.0,
label = "Hopper",
nodenames = {
HOPPER,
HOPPER_SIDE,
},
interval = 1,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
local abovenode = minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z})
if not minetest.registered_items[abovenode.name] then return end
-- 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)
action = function(pos, node)
local pos = pos
local meta = minetest_get_meta(pos)
local inv = meta:get_inventory()
if not inv then return end
for _,object in pairs(minetest.get_objects_inside_radius(pos, 2)) do
local entity = object:get_luaentity()
if not object:is_player() and entity and entity.name == "__builtin:item" and not entity._removed then
if inv and inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then
-- Item must get sucked in when the item just TOUCHES the block above the hopper
-- This is the reason for the Y calculation.
-- Test: Items on farmland and slabs get sucked, but items on full blocks don't
local posob = object:get_pos()
local posob_miny = posob.y + object:get_properties().collisionbox[2]
if math.abs(posob.x-pos.x) <= 0.5 and (posob_miny-pos.y < 1.5 and posob.y-pos.y >= 0.3) then
entity._removed = true
entity.itemstring = ""
object:remove()
inv:add_item("main", ItemStack(object:get_luaentity().itemstring))
end
end
end
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
local x, y, z = pos.x, pos.y, pos.z
-- 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")
local dst_pos
if node.name == HOPPER then
dst_pos = {x = x, y = y - 1, z = z}
else
local param2 = node.param2
local dir = minetest_facedir_to_dir(param2)
if not dir then return end
dst_pos = {x = x - dir.x, y = y, z = z - dir.z}
end
local dst_node = minetest_get_node(dst_pos)
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,
})
minetest.register_craft({
output = "mcl_hoppers:hopper",
output = HOPPER,
recipe = {
{"mcl_core:iron_ingot","","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
doc.add_entry_alias("nodes", "mcl_hoppers:hopper", "nodes", "mcl_hoppers:hopper_side")
doc.add_entry_alias("nodes", HOPPER, "nodes", HOPPER_SIDE)
end
-- Legacy
minetest.register_alias("mcl_hoppers:hopper_item", "mcl_hoppers:hopper")
minetest.register_lbm({
label = "Update hopper formspecs (0.60.0",
name = "mcl_hoppers:update_formspec_0_60_0",
nodenames = { "group:hopper" },
run_at_every_load = false,
action = function(pos, node)
local meta = minetest.get_meta(pos)
local meta = minetest_get_meta(pos)
meta:set_string("formspec", mcl_hoppers_formspec)
end,
})
-- Legacy
minetest.register_alias("mcl_hoppers:hopper_item", HOPPER)

View File

@ -1,4 +1,5 @@
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.
depends = mcl_core, mcl_formspec, mcl_sounds, mcl_util
optional_depends = doc, screwdriver

View File

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

View File

@ -62,7 +62,6 @@ local spawn_trident = function(player)
durability = durability * (unbreaking + 1)
end
wielditem:add_wear(65535/durability)
minetest.chat_send_all(wielditem:get_wear())
obj:set_velocity(vector.multiply(player:get_look_dir(), 20))
obj:set_acceleration({x=0, y=-GRAVITY, z=0})
obj:set_yaw(yaw)

View File

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

View File

@ -670,8 +670,8 @@ local function register_mgv6_decorations()
octaves = 3,
persist = 0.6
},
y_min = 4,
y_max = mcl_mapgen.overworld.max,
spawn_by = "air",
num_spawn_by = 8,
decoration = "mcl_core:cactus",
height = 1,
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 noise_multiplier = 2.5
local random_offset = 9159
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 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_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 = {
["0"] = 1,
@ -28,39 +242,11 @@ local rotation_to_param2 = {
["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 variant = is_blackstone and 2 or 1
local function set_ruined_node(pos, node)
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
local function get_random_stone_material()
local rnd = pr:next(1, 15)
if rnd < 4 then return stone1 end
if rnd == 4 then return stone2 end
if rnd == 5 then return stone3 end
return stone4
local rnd = pr:next(1, #stone_set_for_frame)
return {name = stone_set_for_frame[rnd][variant]}
end
local function get_random_slab()
local rnd = pr:next(1, 15)
if rnd < 4 then return slab1 end
if rnd == 4 then return slab2 end
if rnd == 5 then return slab3 end
return slab4
return {name = slab_set_for_frame[rnd][variant]}
end
local function get_random_stair(param2_offset)
local param2 = (param2 + (param2_offset or 0)) % 4
local rnd = pr:next(1, 15)
if rnd < 4 then return {name = stair1, param2 = param2} end
if rnd == 4 then return {name = stair2, param2 = param2} end
if rnd == 5 then return {name = stair3, param2 = param2} end
return {name = stair4, param2 = param2}
local rnd = pr:next(1, #stair_set_for_frame)
local stare_name = stair_set_for_frame[rnd][variant]
return {name = stare_name, param2 = param2}
end
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 function set_frame_node(pos)
-- local node_choice = pr:next(1, air_nodes + obsidian_nodes)
local node_choice = math_round(mcl_structures_get_perlin_noise_level(pos) * (air_nodes + obsidian_nodes))
if node_choice > obsidian_nodes and air_nodes > 0 then
air_nodes = air_nodes - 1
@ -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))
if is_top_hole then
if pr:next(1, 7) > 1 then
minetest_swap_node(pos2, {name = "xpanes:bar_flat", param2 = orientation})
minetest_swap_node(pos2, {name = PANE_OR_CHAIN_FLAT[variant], param2 = orientation})
end
else
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 is_decor_here = not is_top and pos.y % 3 == 2
if is_decor_here then
minetest_swap_node(pos, {name = "mcl_core:stonebrickcarved"})
minetest_swap_node(pos, {name = STONE_DECOR[variant]})
elseif is_chain then
if not is_top and not is_obsidian then
minetest_swap_node(pos, {name = "xpanes:bar"})
minetest_swap_node(pos, {name = PANE_OR_CHAIN[variant]})
else
minetest_swap_node(pos, {name = "xpanes:bar_flat", param2 = orientation})
minetest_swap_node(pos, {name = PANE_OR_CHAIN_FLAT[variant], param2 = orientation})
end
else
if pr:next(1, 5) == 3 then
minetest_swap_node(pos, {name = "mcl_core:stonebrickcracked"})
minetest_swap_node(pos, {name = STONE1[variant]})
else
minetest_swap_node(pos, {name = "mcl_core:stonebrick"})
minetest_swap_node(pos, {name = STONE4[variant]})
end
end
end
@ -253,7 +430,7 @@ local function draw_frame(frame_pos, frame_width, frame_height, orientation, pr,
})
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
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 })
@ -281,7 +458,9 @@ end
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_z = orientation
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 z = z1 + pr:next(0, 2), z2 - pr:next(0, 2) do
if inverted_opacity_0_5 == 0 or (x % inverted_opacity_0_5 ~= pr:next(0, 1) and z % inverted_opacity_0_5 ~= pr:next(0, 1)) then
minetest_swap_node({x = x, y = y, z = z}, {name = node_garbage[pr:next(1, #node_garbage)]})
minetest_swap_node({x = x, y = y, z = z}, {name = node_garbage[pr:next(1, #node_garbage)][variant]})
end
end
end
@ -305,77 +484,6 @@ local function draw_trash(pos, width, height, lift, orientation, pr)
end
end
local stair_replacement_list = {
"air",
"group:water",
"group:lava",
"group:buildable_to",
"group:deco_block",
}
local stair_names = {
"mcl_stairs:stair_stonebrickcracked",
"mcl_stairs:stair_stonebrickmossy",
"mcl_stairs:stair_stone_rough",
"mcl_stairs:stair_stone_rough",
"mcl_stairs:stair_stone_rough",
"mcl_stairs:stair_stone_rough",
"mcl_stairs:stair_stone_rough",
"mcl_stairs:stair_stone_rough",
"mcl_stairs:stair_stone_rough",
"mcl_stairs:stair_stonebrick",
"mcl_stairs:stair_stonebrick",
"mcl_stairs:stair_stonebrick",
}
local stair_outer_names = {
"mcl_stairs:stair_stonebrickcracked_outer",
"mcl_stairs:stair_stonebrickmossy_outer",
"mcl_stairs:stair_stone_rough_outer",
"mcl_stairs:stair_stonebrick_outer",
}
local stair_content = {
{name = "mcl_core:lava_source"},
{name = "mcl_core:stone"},
{name = "mcl_core:stone"},
{name = "mcl_core:stone"},
{name = "mcl_core:stone"},
{name = "mcl_core:stone"},
{name = "mcl_core:stonebrick"},
{name = "mcl_nether:magma"},
{name = "mcl_nether:netherrack"},
{name = "mcl_nether:netherrack"},
}
local stair_content_bottom = {
{name = "mcl_nether:magma"},
{name = "mcl_nether:magma"},
{name = "mcl_nether:netherrack"},
{name = "mcl_nether:netherrack"},
{name = "mcl_nether:netherrack"},
{name = "mcl_nether:netherrack"},
}
local slabs = {
{name = "mcl_stairs:slab_stone"},
{name = "mcl_stairs:slab_stone"},
{name = "mcl_stairs:slab_stone"},
{name = "mcl_stairs:slab_stone"},
{name = "mcl_stairs:slab_stone"},
{name = "mcl_stairs:slab_stonebrick"},
{name = "mcl_stairs:slab_stonebrick"},
{name = "mcl_stairs:slab_stonebrickcracked"},
{name = "mcl_stairs:slab_stonebrickmossy"},
}
local stones = {
{name = "mcl_core:stone"},
{name = "mcl_core:stone"},
{name = "mcl_core:stone"},
{name = "mcl_core:cobble"},
{name = "mcl_core:mossycobble"},
}
local stair_selector = {
[-1] = {
[-1] = {
@ -383,7 +491,7 @@ local stair_selector = {
param2 = 1,
},
[0] = {
names = stair_names,
names = stair_set_for_stairs,
param2 = 1,
},
[1] = {
@ -393,14 +501,14 @@ local stair_selector = {
},
[0] = {
[-1] = {
names = stair_names,
names = stair_set_for_stairs,
param2 = 0,
},
[0] = {
names = stair_content,
},
[1] = {
names = stair_names,
names = stair_set_for_stairs,
param2 = 2,
},
},
@ -410,7 +518,7 @@ local stair_selector = {
param2 = 0,
},
[0] = {
names = stair_names,
names = stair_set_for_stairs,
param2 = 3,
},
[1] = {
@ -422,25 +530,14 @@ local stair_selector = {
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_stones = stones
local function set_ruined_node(pos, node)
if pr:next(1, 7) < 3 then return end
minetest_swap_node(pos, node)
return true
end
local param2 = param2
local mirror = param2 == 1 or param2 == 2
if mirror then
param2 = (param2 + 2) % 4
end
if mirror then param2 = (param2 + 2) % 4 end
local chain_offset = is_chain and 1 or 0
local lift = lift + stair_offset_from_bottom
local slide_x = (1 - orientation)
local slide_z = orientation
@ -455,52 +552,63 @@ local function draw_stairs(pos, width, height, lift, orientation, pr, is_chain,
local y = y2
local place_slabs = true
local x_key, z_key
local need_to_place_chest = true
local chest_pos
local bad_nodes_ratio = 0
while (y >= y1) or (bad_nodes_ratio > 0.07) do
local good_nodes_counter = 0
for x = x1, x2 do
x_key = (x == x1) and -1 or (x == x2) and 1 or 0
for z = z1, z2 do
local pos = {x = x, y = y, z = z}
if #minetest_find_nodes_in_area(pos, pos, stair_replacement_list, false) > 0 then
z_key = (z == z1) and -1 or (z == z2) and 1 or 0
local stair_coverage = (x_key ~= 0) or (z_key ~= 0)
if stair_coverage then
local ruinity = height + lift
local y_layer_to_start_squeezing = y1 - 2 * lift
while (true) do
local x11 = math_round(x1)
local x22 = math_round(x2)
local z11 = math_round(z1)
local z22 = math_round(z2)
local good_nodes = minetest_find_nodes_in_area({x = x11, y = y, z = z11}, {x = x22, y = y, z = z22}, stair_replacement_list, false)
local good_nodes_ratio = #good_nodes / (x22 - x11 + 1) / (z22 - z11 + 1)
if y < y1 and good_nodes_ratio <= 0.07 then return chest_pos end
for _, pos in pairs(good_nodes) do
if pr:next(1, ruinity) > 1 then
local x, z = pos.x, pos.z
x_key = (x == x11) and -1 or (x == x22) and 1 or 0
z_key = (z == z11) and -1 or (z == z22) and 1 or 0
local should_be_a_stair_here = (x_key ~= 0) or (z_key ~= 0)
if should_be_a_stair_here then
if stair_layer then
local stair = stair_selector[x_key][z_key]
local names = stair.names
set_ruined_node(pos, {name = names[pr:next(1, #names)], param2 = stair.param2})
minetest_swap_node(pos, {name = names[pr:next(1, #names)][variant], param2 = stair.param2})
elseif place_slabs then
set_ruined_node(pos, slabs[pr:next(1, #slabs)])
minetest_swap_node(pos, {name = slabs[pr:next(1, #slabs)][variant]})
else
local placed = set_ruined_node(pos, current_stones[pr:next(1, #current_stones)])
if need_to_place_chest and placed then
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"})
need_to_place_chest = false
end
end
elseif not stair_layer then
set_ruined_node(pos, current_stair_content[pr:next(1, #current_stair_content)])
end
else
good_nodes_counter = good_nodes_counter + 1
minetest_swap_node(pos, {name = current_stair_content[pr:next(1, #current_stair_content)][variant]})
end
end
end
bad_nodes_ratio = 1 - good_nodes_counter / ((x2 - x1 + 1) * (z2 - z1 + 1))
if y >= y1 then
if y >= y1 - lift then
x1 = x1 - 1
x2 = x2 + 1
z1 = z1 - 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
y = y - 1
if y <= y1 then
current_stair_content = stair_content_bottom
current_stones = stair_content_bottom
end
end
place_slabs = not place_slabs
@ -508,19 +616,9 @@ local function draw_stairs(pos, width, height, lift, orientation, pr, is_chain,
else
place_slabs = false
y = y - 1
local dx1 = pr:next(0, 10)
if dx1 < 3 then x1 = x1 + dx1 end
local dx2 = pr:next(0, 10)
if dx2 < 3 then x2 = x2 - dx1 end
if x1 >= x2 then return chest_pos end
local dz1 = pr:next(0, 10)
if dz1 < 3 then z1 = z1 + dz1 end
local dz2 = pr:next(0, 10)
if dz2 < 3 then z2 = z2 - dz1 end
if z1 >= z2 then return chest_pos end
end
if ruinity > 2 then ruinity = math.max(ruinity - pr:next(0,2), 2) end
end
return chest_pos
end
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)
end
local function place(pos, rotation, pr)
local width = pr:next(2, 10)
local height = pr:next(((width < 3) and 3 or 2), 10)
local lift = pr:next(0, 4)
local rotation = rotation or possible_rotations[pr:next(1, #possible_rotations)]
local function common_place(pos, rotation, pr, width, height, lift, is_blackstone)
local pos = pos
local width = width
local height = height
local lift = lift
local rotation = rotation
local orientation = rotation_to_orientation[rotation]
assert(orientation)
local param2 = rotation_to_param2[rotation]
assert(param2)
local is_chain = pr:next(1, 3) > 1
draw_trash(pos, width, height, lift, orientation, pr)
local chest_pos = draw_stairs(pos, width, height, lift, orientation, pr, is_chain, param2)
draw_frame({x = pos.x, y = pos.y + lift, z = pos.z}, width + 2, height + 2, orientation, pr, is_chain, rotation)
draw_trash(pos, width, height, lift, orientation, pr, is_blackstone)
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, is_blackstone)
if not chest_pos then return end
local lootitems = mcl_loot.get_loot(
@ -575,7 +672,7 @@ local function place(pos, rotation, pr)
{itemstring = "mcl_clock:clock", weight = 5},
{itemstring = "mesecons_pressureplates:pressure_plate_gold_off", weight = 5},
{itemstring = "mobs_mc:gold_horse_armor", weight = 5},
{itemstring = "mcl_core:goldblock", weight = 1, amount_min = 1, amount_max = 2},
{itemstring = TOP_DECOR1, weight = 1, amount_min = 1, amount_max = 2},
{itemstring = "mcl_bells:bell", 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)
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 x, y, z = pos.x, pos.y, pos.z
local p1 = {x = x , y = y, z = z }
@ -630,3 +745,35 @@ mcl_structures.register_structure({
end,
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 kick_cheaters = false
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