forked from VoxeLibre/VoxeLibre
Compare commits
102 Commits
8919b69d13
...
15fa3ff775
Author | SHA1 | Date |
---|---|---|
cora | 15fa3ff775 | |
WillConker | 11168f226a | |
teknomunk | 2ad59c6df9 | |
the-real-herowl | 948da34755 | |
WillConker | 406e0e8169 | |
the-real-herowl | 09aba760cf | |
William Goodspeed | a6136ad158 | |
William Goodspeed | 77bcf6cff3 | |
WillConker | 293eb6d021 | |
the-real-herowl | 1c5f7d05fe | |
seventeenthShulker | f8fcd9954f | |
seventeenthShulker | 8b9666137d | |
seventeenthShulker | b3087118fa | |
seventeenthShulker | b79a19f4d6 | |
seventeenthShulker | b0b5cc1265 | |
seventeenthShulker | b237c4642d | |
seventeenthShulker | 49b2491b70 | |
seventeenthShulker | 0408f9c3d8 | |
seventeenthShulker | cbafdfa585 | |
seventeenthShulker | 2312989503 | |
seventeenthShulker | 1471ad7181 | |
seventeenthShulker | 38d7609173 | |
seventeenthShulker | 5bce56cdd6 | |
seventeenthShulker | 7a05c32198 | |
seventeenthShulker | ff386e395f | |
the-real-herowl | a687ef19f6 | |
William Goodspeed | c03f9abd18 | |
William Goodspeed | 9657c9d8bb | |
blitzdoughnuts | 95aadd40b9 | |
THE-NERD2 | 86e3446407 | |
William Goodspeed | ee4d1efaa5 | |
kno10 | 5e6e4967f0 | |
kno10 | df60ec947d | |
kno10 | 02cb0818a1 | |
kno10 | 77382d930e | |
the-real-herowl | 5e366a8916 | |
WillConker | 6c614d8376 | |
WillConker | a785be59d9 | |
cora | f23014005f | |
cora | c2098d777f | |
cora | dc07eea590 | |
tacotexmex | 3460e27468 | |
OgelGames | 0012bdb71e | |
kno10 | b8d7139792 | |
WillConker | cddc1982be | |
kno10 | 9595b0df59 | |
WillConker | ff21d1eab1 | |
WillConker | 9d5b46c28a | |
kno10 | 80a6a6efb0 | |
the-real-herowl | 32148262e1 | |
Mikita Wiśniewski | 567d112942 | |
Mikita Wiśniewski | 347305eaea | |
Mikita Wiśniewski | 508bc19f6a | |
Mikita Wiśniewski | c1e9e4b1a2 | |
Mikita Wiśniewski | 7bf15642ca | |
Mikita Wiśniewski | f1fa6240bb | |
Mikita Wiśniewski | c5bc6ff189 | |
Mikita Wiśniewski | 70e903b716 | |
Mikita Wiśniewski | 209b24a2fb | |
cora | ac05f8bad6 | |
Mikita Wiśniewski | 76cff76d91 | |
Mikita Wiśniewski | 49b6d09985 | |
Mikita Wiśniewski | a66c35a9ea | |
Mikita Wiśniewski | a28e55160f | |
Mikita Wiśniewski | 6bbb6b8dec | |
Mikita Wiśniewski | b4b5bf8391 | |
Mikita Wiśniewski | 16dd8694a6 | |
Jürgen Rühle | 7a5ee4e6e2 | |
Jürgen Rühle | d0d9600709 | |
cora | 709b73295c | |
Mikita Wiśniewski | 1d77017ca9 | |
Mikita Wiśniewski | d6d64d8837 | |
Mikita Wiśniewski | e771f0e3ff | |
Mikita Wiśniewski | b10bfe27ce | |
Mikita Wiśniewski | d5b3a6f658 | |
JoseDouglas26 | f7ee3b59d7 | |
the-real-herowl | 1745b6d400 | |
teknomunk | bb9ed4498b | |
teknomunk | 94981d9c09 | |
teknomunk | 7ae05d9c06 | |
teknomunk | 177e8f4b9d | |
the-real-herowl | 026ea5940c | |
the-real-herowl | be9fece0d3 | |
the-real-herowl | 27f8a008c3 | |
the-real-herowl | 8bbceddbc2 | |
the-real-herowl | 6e70c760d6 | |
the-real-herowl | 53802b270d | |
teknomunk | 3928e12634 | |
teknomunk | 304550d90c | |
teknomunk | 0a2336ad82 | |
teknomunk | 75a767a0ab | |
teknomunk | 7e0afd7e21 | |
teknomunk | 15fa925aae | |
teknomunk | 4935f5fdda | |
teknomunk | 41032ec999 | |
teknomunk | d64ee18f75 | |
teknomunk | 1942384fe5 | |
teknomunk | 9b50dd6565 | |
teknomunk | a88951ac6a | |
teknomunk | bc343769ee | |
seventeenthShulker | 8aa65f85f2 | |
qoheniac | e27e70a91b |
|
@ -20,10 +20,8 @@
|
|||
* epCode
|
||||
* chmodsayshello
|
||||
* MrRar
|
||||
* FossFanatic
|
||||
* SmokeyDope
|
||||
* Faerraven / Michieal
|
||||
* Codiac
|
||||
* rudzik8
|
||||
* teknomunk
|
||||
|
||||
|
@ -36,6 +34,8 @@
|
|||
* NO11
|
||||
* SumianVoice
|
||||
* PrairieWind
|
||||
* FossFanatic
|
||||
* Codiac
|
||||
|
||||
## Contributors
|
||||
* RandomLegoBrick
|
||||
|
@ -140,6 +140,7 @@
|
|||
* SOS-Games
|
||||
* Bram
|
||||
* qoheniac
|
||||
* WillConker
|
||||
|
||||
## Music
|
||||
* Jordach for the jukebox music compilation from Big Freaking Dig
|
||||
|
|
3
LEGAL.md
3
LEGAL.md
|
@ -46,6 +46,9 @@ Armor trim models were created by Aeonix_Aeon
|
|||
Source: <https://www.curseforge.com/minecraft/texture-packs/ozocraft-remix>
|
||||
License: [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/)
|
||||
|
||||
Charcoal block texture was created by [blitzdoughnuts](https://gitlab.com/ApplemunchFromDaDead), based on the Pixel Perfection coal block.
|
||||
License: [CC BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/)
|
||||
|
||||
The main menu images are released under: [CC0](https://creativecommons.org/publicdomain/zero/1.0/)
|
||||
|
||||
All other files, unless mentioned otherwise, fall under:
|
||||
|
|
|
@ -83,7 +83,7 @@ The VoxeLibre repository is hosted at Mesehub. To contribute or report issues, h
|
|||
* Discord: <https://discord.gg/xE4z8EEpDC>
|
||||
* YouTube: <https://www.youtube.com/channel/UClI_YcsXMF3KNeJtoBfnk9A>
|
||||
* ContentDB: <https://content.minetest.net/packages/wuzzy/mineclone2/>
|
||||
* OpenCollective: <https://opencollective.com/mineclone2>
|
||||
* OpenCollective: <https://opencollective.com/voxelibre>
|
||||
* Mastodon: <https://fosstodon.org/@VoxeLibre>
|
||||
* Lemmy: <https://lemm.ee/c/voxelibre>
|
||||
* Matrix space: <https://app.element.io/#/room/#voxelibre:matrix.org>
|
||||
|
|
|
@ -136,6 +136,7 @@ local function try_object_pickup(player, inv, object, checkpos)
|
|||
-- Destroy entity
|
||||
-- This just prevents this section to be run again because object:remove() doesn't remove the item immediately.
|
||||
le.target = checkpos
|
||||
le.itemstring = ""
|
||||
le._removed = true
|
||||
|
||||
-- Stop the object
|
||||
|
@ -957,6 +958,7 @@ minetest.register_entity(":__builtin:item", {
|
|||
self.random_velocity = 0
|
||||
self:set_item(own_stack:to_string())
|
||||
|
||||
entity.itemstring = ""
|
||||
entity._removed = true
|
||||
object:remove()
|
||||
return true
|
||||
|
|
|
@ -18,7 +18,7 @@ mcl_mobs.invis = {}
|
|||
local remove_far = true
|
||||
|
||||
local mobs_debug = minetest.settings:get_bool("mobs_debug", false) -- Shows helpful debug info above each mob
|
||||
local spawn_logging = minetest.settings:get_bool("mcl_logging_mobs_spawn",true)
|
||||
local spawn_logging = minetest.settings:get_bool("mcl_logging_mobs_spawn", false)
|
||||
|
||||
local MAPGEN_LIMIT = mcl_vars.mapgen_limit
|
||||
local MAPGEN_MOB_LIMIT = MAPGEN_LIMIT - 90
|
||||
|
@ -150,6 +150,11 @@ function mob_class:mob_activate(staticdata, def, dtime)
|
|||
local tmp = minetest.deserialize(staticdata)
|
||||
|
||||
if tmp then
|
||||
-- Patch incorrectly converted mobs
|
||||
if tmp.base_mesh ~= minetest.registered_entities[self.name].mesh then
|
||||
mcl_mobs.strip_staticdata(tmp)
|
||||
end
|
||||
|
||||
for _,stat in pairs(tmp) do
|
||||
self[_] = stat
|
||||
end
|
||||
|
|
|
@ -342,13 +342,33 @@ function mcl_mobs.register_mob(name, def)
|
|||
minetest.register_entity(name, setmetatable(final_def,mcl_mobs.mob_class_meta))
|
||||
end -- END mcl_mobs.register_mob function
|
||||
|
||||
|
||||
local STRIP_FIELDS = { "mesh", "base_size", "textures", "base_mesh", "base_texture" }
|
||||
function mcl_mobs.strip_staticdata(unpacked_staticdata)
|
||||
-- Strip select fields from the staticdata to prevent conversion issues
|
||||
for i = 1,#STRIP_FIELDS do
|
||||
unpacked_staticdata[STRIP_FIELDS[i]] = nil
|
||||
end
|
||||
end
|
||||
function mcl_mobs.register_conversion(old_name, new_name)
|
||||
minetest.register_entity(old_name, {
|
||||
on_activate = function(self, staticdata, dtime)
|
||||
local obj = minetest.add_entity(self.object:get_pos(), new_name, staticdata)
|
||||
local hook = (obj:get_luaentity() or {})._on_after_convert
|
||||
if hook then hook(obj) end
|
||||
self.object:remove()
|
||||
local unpacked_staticdata = minetest.deserialize(staticdata)
|
||||
mcl_mobs.strip_staticdata(unpacked_staticdata)
|
||||
staticdata = minetest.serialize(unpacked_staticdata)
|
||||
|
||||
local old_object = self.object
|
||||
if not old_object then return end
|
||||
|
||||
local pos = old_object:get_pos()
|
||||
if not pos then return end
|
||||
old_object:remove()
|
||||
|
||||
local new_object = minetest.add_entity(pos, new_name, staticdata)
|
||||
if not new_object then return end
|
||||
|
||||
local hook = (new_object:get_luaentity() or {})._on_after_convert
|
||||
if hook then hook(new_object) end
|
||||
end,
|
||||
_convert_to = new_name,
|
||||
})
|
||||
|
@ -572,7 +592,12 @@ function mcl_mobs.register_egg(mob, desc, background_color, overlay_color, addeg
|
|||
--minetest.log("min light: " .. mob_light_lvl[1])
|
||||
--minetest.log("max light: " .. mob_light_lvl[2])
|
||||
|
||||
mcl_mobspawners.setup_spawner(pointed_thing.under, itemstack:get_name(), mob_light_lvl[1], mob_light_lvl[2])
|
||||
-- Handle egg conversion
|
||||
local mob_name = itemstack:get_name()
|
||||
local convert_to = (minetest.registered_entities[mob_name] or {})._convert_to
|
||||
if convert_to then mob_name = convert_to end
|
||||
|
||||
mcl_mobspawners.setup_spawner(pointed_thing.under, mob_name, mob_light_lvl[1], mob_light_lvl[2])
|
||||
if not minetest.is_creative_enabled(name) then
|
||||
itemstack:take_item()
|
||||
end
|
||||
|
|
|
@ -258,6 +258,18 @@ function mcl_mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
|
|||
end
|
||||
end
|
||||
|
||||
-- Stop!
|
||||
local s = get_sign(entity.v)
|
||||
|
||||
entity.v = entity.v - 0.02 * s
|
||||
|
||||
if s ~= get_sign(entity.v) then
|
||||
|
||||
entity.object:set_velocity({x = 0, y = 0, z = 0})
|
||||
entity.v = 0
|
||||
return
|
||||
end
|
||||
|
||||
-- if not moving then set animation and return
|
||||
if entity.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then
|
||||
|
||||
|
@ -273,18 +285,6 @@ function mcl_mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime)
|
|||
mcl_mobs:set_animation(entity, moving_anim)
|
||||
end
|
||||
|
||||
-- Stop!
|
||||
local s = get_sign(entity.v)
|
||||
|
||||
entity.v = entity.v - 0.02 * s
|
||||
|
||||
if s ~= get_sign(entity.v) then
|
||||
|
||||
entity.object:set_velocity({x = 0, y = 0, z = 0})
|
||||
entity.v = 0
|
||||
return
|
||||
end
|
||||
|
||||
-- enforce speed limit forward and reverse
|
||||
local max_spd = entity.max_speed_reverse
|
||||
|
||||
|
|
|
@ -17,12 +17,13 @@ local mt_get_biome_name = minetest.get_biome_name
|
|||
local get_objects_inside_radius = minetest.get_objects_inside_radius
|
||||
local get_connected_players = minetest.get_connected_players
|
||||
|
||||
local math_min = math.min
|
||||
local math_max = math.max
|
||||
local math_random = math.random
|
||||
local math_floor = math.floor
|
||||
local math_ceil = math.ceil
|
||||
local math_cos = math.cos
|
||||
local math_sin = math.sin
|
||||
local math_round = function(x) return (x > 0) and math_floor(x + 0.5) or math_ceil(x - 0.5) end
|
||||
local math_sqrt = math.sqrt
|
||||
|
||||
local vector_distance = vector.distance
|
||||
|
@ -33,9 +34,9 @@ local table_copy = table.copy
|
|||
local table_remove = table.remove
|
||||
local pairs = pairs
|
||||
|
||||
local LOGGING_ON = minetest.settings:get_bool("mcl_logging_mobs_spawning", false)
|
||||
local logging = minetest.settings:get_bool("mcl_logging_mobs_spawn", false)
|
||||
local function mcl_log (message, property)
|
||||
if LOGGING_ON then
|
||||
if logging then
|
||||
if property then
|
||||
message = message .. ": " .. dump(property)
|
||||
end
|
||||
|
@ -54,8 +55,10 @@ local FIND_SPAWN_POS_RETRIES = 16
|
|||
local FIND_SPAWN_POS_RETRIES_SUCCESS_RESPIN = 8
|
||||
|
||||
local MOB_SPAWN_ZONE_INNER = 24
|
||||
local MOB_SPAWN_ZONE_INNER_SQ = MOB_SPAWN_ZONE_INNER^2 -- squared
|
||||
local MOB_SPAWN_ZONE_MIDDLE = 32
|
||||
local MOB_SPAWN_ZONE_OUTER = 128
|
||||
local MOB_SPAWN_ZONE_OUTER_SQ = MOB_SPAWN_ZONE_OUTER^2 -- squared
|
||||
|
||||
-- range for mob count
|
||||
local MOB_CAP_INNER_RADIUS = 32
|
||||
|
@ -95,7 +98,6 @@ mcl_log("Percentage of hostile spawns are group: " .. hostile_group_percentage_s
|
|||
--do mobs spawn?
|
||||
local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false
|
||||
local spawn_protected = minetest.settings:get_bool("mobs_spawn_protected") ~= false
|
||||
local logging = minetest.settings:get_bool("mcl_logging_mobs_spawn",true)
|
||||
|
||||
-- THIS IS THE BIG LIST OF ALL BIOMES - used for programming/updating mobs
|
||||
-- Also used for missing parameter
|
||||
|
@ -601,71 +603,40 @@ function mcl_mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_
|
|||
spawn_dictionary[key]["check_position"] = check_position
|
||||
end
|
||||
|
||||
-- Calculate the inverse of a piecewise linear function f(x). Line segments are represented as two
|
||||
-- adjacent points specified as { x, f(x) }. At least 2 points are required. If there are most solutions,
|
||||
-- the one with a lower x value will be chosen.
|
||||
local function inverse_pwl(fx, f)
|
||||
if fx < f[1][2] then
|
||||
return f[1][1]
|
||||
end
|
||||
|
||||
for i=2,#f do
|
||||
local x0,fx0 = unpack(f[i-1])
|
||||
local x1,fx1 = unpack(f[i ])
|
||||
if fx < fx1 then
|
||||
return (fx - fx0) * (x1 - x0) / (fx1 - fx0) + x0
|
||||
end
|
||||
end
|
||||
|
||||
return f[#f][1]
|
||||
end
|
||||
|
||||
local SPAWN_DISTANCE_CDF_PWL = {
|
||||
{0.000,0.00},
|
||||
{0.083,0.40},
|
||||
{0.416,0.75},
|
||||
{1.000,1.00},
|
||||
}
|
||||
|
||||
local two_pi = 2 * math.pi
|
||||
local function get_next_mob_spawn_pos(pos)
|
||||
-- Select a distance such that distances closer to the player are selected much more often than
|
||||
-- those further away from the player.
|
||||
local fx = (math_random(1,10000)-1) / 10000
|
||||
local x = inverse_pwl(fx, SPAWN_DISTANCE_CDF_PWL)
|
||||
local distance = x * (MOB_SPAWN_ZONE_OUTER - MOB_SPAWN_ZONE_INNER) + MOB_SPAWN_ZONE_INNER
|
||||
-- those further away from the player. This does produce a concentration at INNER (24 blocks)
|
||||
local distance = math_random()^2 * (MOB_SPAWN_ZONE_OUTER - MOB_SPAWN_ZONE_INNER) + MOB_SPAWN_ZONE_INNER
|
||||
--print("Using spawn distance of "..tostring(distance).." fx="..tostring(fx)..",x="..tostring(x))
|
||||
|
||||
-- TODO Floor xoff and zoff and add 0.5 so it tries to spawn in the middle of the square. Less failed attempts.
|
||||
-- Use spherical coordinates https://en.wikipedia.org/wiki/Spherical_coordinate_system#Cartesian_coordinates
|
||||
local theta = math_random() * two_pi
|
||||
local phi = math_random() * two_pi
|
||||
local xoff = math_round(distance * math_sin(theta) * math_cos(phi))
|
||||
local yoff = math_round(distance * math_cos(theta))
|
||||
local zoff = math_round(distance * math_sin(theta) * math_sin(phi))
|
||||
-- Choose a random direction. Rejection sampling is simple and fast (1-2 tries usually)
|
||||
local xoff, yoff, zoff, dd
|
||||
repeat
|
||||
xoff, yoff, zoff = math_random() * 2 - 1, math_random() * 2 - 1, math_random() * 2 - 1
|
||||
dd = xoff*xoff + yoff*yoff + zoff*zoff
|
||||
until (dd <= 1 and dd >= 1e-6) -- outside of uniform ball, retry
|
||||
dd = distance / math_sqrt(dd) -- distance scaling factor
|
||||
xoff, yoff, zoff = xoff * dd, yoff * dd, zoff * dd
|
||||
local goal_pos = vector.offset(pos, xoff, yoff, zoff)
|
||||
|
||||
if not ( math.abs(goal_pos.x) <= SPAWN_MAPGEN_LIMIT and math.abs(pos.y) <= SPAWN_MAPGEN_LIMIT and math.abs(goal_pos.z) <= SPAWN_MAPGEN_LIMIT ) then
|
||||
if not ( math.abs(goal_pos.x) <= SPAWN_MAPGEN_LIMIT and math.abs(goal_pos.y) <= SPAWN_MAPGEN_LIMIT and math.abs(goal_pos.z) <= SPAWN_MAPGEN_LIMIT ) then
|
||||
mcl_log("Pos outside mapgen limits: " .. minetest.pos_to_string(goal_pos))
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Calculate upper/lower y limits
|
||||
local R1 = MOB_SPAWN_ZONE_OUTER
|
||||
local d = vector_distance( pos, vector.new( goal_pos.x, pos.y, goal_pos.z ) ) -- distance from player to projected point on horizontal plane
|
||||
local y1 = math_sqrt( R1*R1 - d*d ) -- absolue value of distance to outer sphere
|
||||
local d2 = xoff*xoff + zoff*zoff -- squared distance in x,z plane only
|
||||
local y1 = math_sqrt( MOB_SPAWN_ZONE_OUTER_SQ - d2 ) -- absolue value of distance to outer sphere
|
||||
|
||||
local y_min
|
||||
local y_max
|
||||
if d >= MOB_SPAWN_ZONE_INNER then
|
||||
local y_min, y_max
|
||||
if d2 >= MOB_SPAWN_ZONE_INNER_SQ then
|
||||
-- Outer region, y range has both ends on the outer sphere
|
||||
y_min = pos.y - y1
|
||||
y_max = pos.y + y1
|
||||
else
|
||||
-- Inner region, y range spans between inner and outer spheres
|
||||
local R2 = MOB_SPAWN_ZONE_INNER
|
||||
local y2 = math_sqrt( R2*R2 - d*d )
|
||||
if goal_pos.y > pos. y then
|
||||
local y2 = math_sqrt( MOB_SPAWN_ZONE_INNER_SQ - d2 )
|
||||
if goal_pos.y > pos.y then
|
||||
-- Upper hemisphere
|
||||
y_min = pos.y + y2
|
||||
y_max = pos.y + y1
|
||||
|
@ -675,16 +646,9 @@ local function get_next_mob_spawn_pos(pos)
|
|||
y_max = pos.y - y2
|
||||
end
|
||||
end
|
||||
y_min = math_round(y_min)
|
||||
y_max = math_round(y_max)
|
||||
|
||||
-- Limit total range of check to 32 nodes (maximum of 3 map blocks)
|
||||
if y_max > goal_pos.y + 16 then
|
||||
y_max = goal_pos.y + 16
|
||||
end
|
||||
if y_min < goal_pos.y - 16 then
|
||||
y_min = goal_pos.y - 16
|
||||
end
|
||||
y_min = math_max(math_floor(y_min), goal_pos.y - 16)
|
||||
y_max = math_min(math_ceil(y_max), goal_pos.y + 16)
|
||||
|
||||
-- Ask engine for valid spawn locations
|
||||
local spawning_position_list = find_nodes_in_area_under_air(
|
||||
|
@ -997,7 +961,7 @@ if mobs_spawn then
|
|||
mob_total_wide = 0
|
||||
end
|
||||
|
||||
local cap_space_wide = math.max(type_cap - mob_total_wide, 0)
|
||||
local cap_space_wide = math_max(type_cap - mob_total_wide, 0)
|
||||
|
||||
mcl_log("mob_type", mob_type)
|
||||
mcl_log("cap_space_wide", cap_space_wide)
|
||||
|
@ -1005,10 +969,10 @@ if mobs_spawn then
|
|||
local cap_space_available = 0
|
||||
if mob_type == "hostile" then
|
||||
mcl_log("cap_space_global", cap_space_hostile)
|
||||
cap_space_available = math.min(cap_space_hostile, cap_space_wide)
|
||||
cap_space_available = math_min(cap_space_hostile, cap_space_wide)
|
||||
else
|
||||
mcl_log("cap_space_global", cap_space_non_hostile)
|
||||
cap_space_available = math.min(cap_space_non_hostile, cap_space_wide)
|
||||
cap_space_available = math_min(cap_space_non_hostile, cap_space_wide)
|
||||
end
|
||||
|
||||
local mob_total_close = mob_counts_close[mob_type]
|
||||
|
@ -1017,8 +981,8 @@ if mobs_spawn then
|
|||
mob_total_close = 0
|
||||
end
|
||||
|
||||
local cap_space_close = math.max(close_zone_cap - mob_total_close, 0)
|
||||
cap_space_available = math.min(cap_space_available, cap_space_close)
|
||||
local cap_space_close = math_max(close_zone_cap - mob_total_close, 0)
|
||||
cap_space_available = math_min(cap_space_available, cap_space_close)
|
||||
|
||||
mcl_log("cap_space_close", cap_space_close)
|
||||
mcl_log("cap_space_available", cap_space_available)
|
||||
|
@ -1145,7 +1109,7 @@ if mobs_spawn then
|
|||
|
||||
local amount_to_spawn = math.random(group_min, spawn_in_group)
|
||||
mcl_log("Spawning quantity: " .. amount_to_spawn)
|
||||
amount_to_spawn = math.min(amount_to_spawn, cap_space_available)
|
||||
amount_to_spawn = math_min(amount_to_spawn, cap_space_available)
|
||||
mcl_log("throttled spawning quantity: " .. amount_to_spawn)
|
||||
|
||||
if logging then
|
||||
|
@ -1196,8 +1160,8 @@ if mobs_spawn then
|
|||
local players = get_connected_players()
|
||||
local total_mobs, total_non_hostile, total_hostile = count_mobs_total_cap()
|
||||
|
||||
local cap_space_hostile = math.max(mob_cap.global_hostile - total_hostile, 0)
|
||||
local cap_space_non_hostile = math.max(mob_cap.global_non_hostile - total_non_hostile, 0)
|
||||
local cap_space_hostile = math_max(mob_cap.global_hostile - total_hostile, 0)
|
||||
local cap_space_non_hostile = math_max(mob_cap.global_non_hostile - total_non_hostile, 0)
|
||||
mcl_log("global cap_space_hostile", cap_space_hostile)
|
||||
mcl_log("global cap_space_non_hostile", cap_space_non_hostile)
|
||||
|
||||
|
|
|
@ -4,21 +4,17 @@
|
|||
|
||||
local S = minetest.get_translator("mobs_mc")
|
||||
|
||||
local BEAM_CHECK_FREQUENCY = 2
|
||||
local BEAM_CHECK_FREQUENCY = 1
|
||||
local POS_CHECK_FREQUENCY = 15
|
||||
local HEAL_AMMOUNT = 37
|
||||
local HEAL_INTERVAL = 1
|
||||
local HEAL_AMOUNT = 2
|
||||
|
||||
local function heal(self)
|
||||
local o = self.object
|
||||
self.health = math.min(self.hp_max,self.health + HEAL_AMMOUNT)
|
||||
end
|
||||
local function check_beam(self)
|
||||
for _, obj in ipairs(minetest.get_objects_inside_radius(self.object:get_pos(), 80)) do
|
||||
local luaentity = obj:get_luaentity()
|
||||
if luaentity and luaentity.name == "mcl_end:crystal" then
|
||||
if luaentity.beam then
|
||||
if luaentity.beam == self.beam then
|
||||
heal(self)
|
||||
break
|
||||
end
|
||||
else
|
||||
|
@ -106,7 +102,6 @@ mcl_mobs.register_mob("mobs_mc:enderdragon", {
|
|||
},
|
||||
ignores_nametag = true,
|
||||
do_custom = function(self,dtime)
|
||||
mcl_bossbars.update_boss(self.object, "Ender Dragon", "light_purple")
|
||||
if self._pos_timer == nil or self._pos_timer > POS_CHECK_FREQUENCY then
|
||||
self._pos_timer = 0
|
||||
check_pos(self)
|
||||
|
@ -115,8 +110,20 @@ mcl_mobs.register_mob("mobs_mc:enderdragon", {
|
|||
self._beam_timer = 0
|
||||
check_beam(self)
|
||||
end
|
||||
|
||||
self._beam_timer = self._beam_timer + dtime
|
||||
self._pos_timer = self._pos_timer + dtime
|
||||
|
||||
if self.beam ~= nil then
|
||||
-- heal
|
||||
self._heal_timer = (self._heal_timer or 0) + dtime
|
||||
if self._heal_timer > HEAL_INTERVAL then
|
||||
self.health = math.min(self.hp_max,self.health + HEAL_AMOUNT)
|
||||
self._heal_timer = self._heal_timer - HEAL_INTERVAL
|
||||
end
|
||||
end
|
||||
|
||||
mcl_bossbars.update_boss(self.object, "Ender Dragon", "light_purple")
|
||||
end,
|
||||
on_die = function(self, pos, cmi_cause)
|
||||
if self._portal_pos then
|
||||
|
|
|
@ -83,8 +83,8 @@ mcl_mobs.register_mob("mobs_mc:iron_golem", {
|
|||
stand_speed = 15, walk_speed = 15, run_speed = 25, punch_speed = 15,
|
||||
stand_start = 0, stand_end = 0,
|
||||
walk_start = 0, walk_end = 40,
|
||||
run_start = 0, run_end = 40,
|
||||
punch_start = 40, punch_end = 50,
|
||||
run_start = 40, run_end = 80,
|
||||
punch_start = 80, punch_end = 90,
|
||||
},
|
||||
jump = true,
|
||||
do_custom = function(self, dtime)
|
||||
|
|
|
@ -10,6 +10,10 @@ mcl_weather.thunder = {
|
|||
init_done = false,
|
||||
}
|
||||
|
||||
lightning.register_on_strike(function(pos, pos2, objects)
|
||||
if not mcl_weather.has_rain(pos) then return nil, true end
|
||||
end)
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
if mcl_weather.get_weather() ~= "thunder" then
|
||||
return false
|
||||
|
|
|
@ -678,6 +678,7 @@ local function make_formspec(name)
|
|||
image_button[2.4,0.12;0.8,0.8;craftguide_search_icon.png;search;]
|
||||
image_button[3.05,0.12;0.8,0.8;craftguide_clear_icon.png;clear;]
|
||||
field_close_on_enter[filter;false]
|
||||
field_enter_after_edit[filter;true]
|
||||
]]
|
||||
|
||||
fs[#fs + 1] = fmt([[ tooltip[search;%s]
|
||||
|
|
|
@ -330,9 +330,16 @@ function hb.change_hudbar(player, identifier, new_value, new_max_value, new_icon
|
|||
|
||||
local name = player:get_player_name()
|
||||
local hudtable = hb.get_hudtable(identifier)
|
||||
|
||||
-- hb.change_hudbar may be called with a non-existing hudbar like hunger.
|
||||
if hudtable == nil then
|
||||
return false
|
||||
end
|
||||
|
||||
if not hudtable.hudstate[name] then
|
||||
return false
|
||||
end
|
||||
|
||||
local value_changed, max_changed = false, false
|
||||
|
||||
if new_value then
|
||||
|
|
|
@ -22,10 +22,8 @@ return {
|
|||
"epCode",
|
||||
"chmodsayshello",
|
||||
"MrRar",
|
||||
"FossFanatic ",
|
||||
"SmokeyDope",
|
||||
"Faerraven / Michieal",
|
||||
"Codiac",
|
||||
"rudzik8",
|
||||
"teknomunk",
|
||||
}},
|
||||
|
@ -38,6 +36,8 @@ return {
|
|||
"NO11",
|
||||
"SumianVoice",
|
||||
"PrairieWind",
|
||||
"FossFanatic",
|
||||
"Codiac",
|
||||
}},
|
||||
{S("Contributors"), 0x52FF00, {
|
||||
"RandomLegoBrick",
|
||||
|
@ -142,6 +142,7 @@ return {
|
|||
"SOS-Games",
|
||||
"Bram",
|
||||
"qoheniac",
|
||||
"WillConker",
|
||||
}},
|
||||
{S("Music"), 0xA60014, {
|
||||
"Jordach for the jukebox music compilation from Big Freaking Dig",
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
local size_min, size_max = 20, 59
|
||||
local delta_size = size_max - size_min
|
||||
-- Constants
|
||||
local size_min = 20 / 100 -- minimum size, prescaled
|
||||
local size_max = 59 / 100 -- maximum size, prescaled
|
||||
local delta_size = (size_max - size_min) / 10 -- Size change for each XP size level
|
||||
local max_orb_age = 300 -- seconds
|
||||
local gravity = vector.new(0, -((tonumber(minetest.settings:get("movement_gravity"))) or 9.81), 0)
|
||||
|
||||
local size_to_xp = {
|
||||
-- min and max XP amount for a given size
|
||||
{-32768, 2}, -- 1
|
||||
{ 3, 6}, -- 2
|
||||
{ 7, 16}, -- 3
|
||||
|
@ -16,24 +21,20 @@ local size_to_xp = {
|
|||
}
|
||||
|
||||
local function xp_to_size(xp)
|
||||
local i, l = 1, #size_to_xp
|
||||
xp = xp or 0
|
||||
|
||||
while xp > size_to_xp[i][1] and i < l do
|
||||
i = i + 1
|
||||
-- Find the size for the xp amount
|
||||
for i=1,11 do
|
||||
local bucket = size_to_xp[i]
|
||||
if xp >= bucket[1] and xp <= bucket[2] then
|
||||
return (i - 1) * delta_size + size_min
|
||||
end
|
||||
end
|
||||
|
||||
return ((i - 1) / (l - 1) * delta_size + size_min) / 100
|
||||
-- Fallback is the minimum size
|
||||
return size_min
|
||||
end
|
||||
|
||||
local max_orb_age = 300 -- seconds
|
||||
local gravity = vector.new(0, -((tonumber(minetest.settings:get("movement_gravity"))) or 9.81), 0)
|
||||
|
||||
local collector, pos, pos2
|
||||
local direction, distance, player_velocity, goal
|
||||
local currentvel, acceleration, multiplier, velocity
|
||||
local node, vel, def
|
||||
local is_moving, is_slippery, slippery, slip_factor
|
||||
local size
|
||||
local function xp_step(self, dtime)
|
||||
--if item set to be collected then only execute go to player
|
||||
if self.collected == true then
|
||||
|
@ -41,33 +42,32 @@ local function xp_step(self, dtime)
|
|||
self.collected = false
|
||||
return
|
||||
end
|
||||
collector = minetest.get_player_by_name(self.collector)
|
||||
|
||||
local collector = minetest.get_player_by_name(self.collector)
|
||||
if collector and collector:get_hp() > 0 and vector.distance(self.object:get_pos(),collector:get_pos()) < 7.25 then
|
||||
self.object:set_acceleration(vector.new(0,0,0))
|
||||
self.disable_physics(self)
|
||||
--get the variables
|
||||
pos = self.object:get_pos()
|
||||
pos2 = collector:get_pos()
|
||||
local pos = self.object:get_pos()
|
||||
local pos2 = collector:get_pos()
|
||||
|
||||
player_velocity = collector:get_velocity() or collector:get_player_velocity()
|
||||
local player_velocity = collector:get_velocity() or collector:get_player_velocity()
|
||||
|
||||
pos2.y = pos2.y + 0.8
|
||||
|
||||
direction = vector.direction(pos,pos2)
|
||||
distance = vector.distance(pos2,pos)
|
||||
multiplier = distance
|
||||
local direction = vector.direction(pos,pos2)
|
||||
local distance = vector.distance(pos2,pos)
|
||||
local multiplier = distance
|
||||
if multiplier < 1 then
|
||||
multiplier = 1
|
||||
end
|
||||
goal = vector.multiply(direction,multiplier)
|
||||
currentvel = self.object:get_velocity()
|
||||
local currentvel = self.object:get_velocity()
|
||||
|
||||
if distance > 1 then
|
||||
multiplier = 20 - distance
|
||||
velocity = vector.multiply(direction,multiplier)
|
||||
goal = velocity
|
||||
acceleration = vector.new(goal.x-currentvel.x,goal.y-currentvel.y,goal.z-currentvel.z)
|
||||
self.object:add_velocity(vector.add(acceleration,player_velocity))
|
||||
local velocity = vector.multiply(direction, multiplier)
|
||||
local acceleration = vector.new(velocity.x - currentvel.x, velocity.y - currentvel.y, velocity.z - currentvel.z)
|
||||
self.object:add_velocity(vector.add(acceleration, player_velocity))
|
||||
elseif distance < 0.8 then
|
||||
mcl_experience.add_xp(collector, self._xp)
|
||||
self.object:remove()
|
||||
|
@ -75,28 +75,26 @@ local function xp_step(self, dtime)
|
|||
return
|
||||
else
|
||||
self.collector = nil
|
||||
self.enable_physics(self)
|
||||
self:enable_physics()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Age orbs
|
||||
self.age = self.age + dtime
|
||||
if self.age > max_orb_age then
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
|
||||
pos = self.object:get_pos()
|
||||
local pos = self.object:get_pos()
|
||||
if not pos then return end
|
||||
|
||||
if pos then
|
||||
node = minetest.get_node_or_nil({
|
||||
-- Get the node directly below the XP orb
|
||||
local node = minetest.get_node_or_nil({
|
||||
x = pos.x,
|
||||
y = pos.y -0.25,
|
||||
y = pos.y - 0.25, -- Orb collision box is +/-0.2, so go a bit below that
|
||||
z = pos.z
|
||||
})
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
-- Remove nodes in 'ignore'
|
||||
if node and node.name == "ignore" then
|
||||
|
@ -109,18 +107,18 @@ local function xp_step(self, dtime)
|
|||
end
|
||||
|
||||
-- Slide on slippery nodes
|
||||
vel = self.object:get_velocity()
|
||||
def = node and minetest.registered_nodes[node.name]
|
||||
is_moving = (def and not def.walkable) or
|
||||
local vel = self.object:get_velocity()
|
||||
local def = node and minetest.registered_nodes[node.name]
|
||||
local is_moving = (def and not def.walkable) or
|
||||
vel.x ~= 0 or vel.y ~= 0 or vel.z ~= 0
|
||||
is_slippery = false
|
||||
local is_slippery = false
|
||||
|
||||
if def and def.walkable then
|
||||
slippery = minetest.get_item_group(node.name, "slippery")
|
||||
local slippery = minetest.get_item_group(node.name, "slippery")
|
||||
is_slippery = slippery ~= 0
|
||||
if is_slippery and (math.abs(vel.x) > 0.2 or math.abs(vel.z) > 0.2) then
|
||||
-- Horizontal deceleration
|
||||
slip_factor = 4.0 / (slippery + 4)
|
||||
local slip_factor = 4.0 / (slippery + 4)
|
||||
self.object:set_acceleration({
|
||||
x = -vel.x * slip_factor,
|
||||
y = 0,
|
||||
|
@ -160,7 +158,6 @@ minetest.register_entity("mcl_experience:orb", {
|
|||
initial_sprite_basepos = {x = 0, y = 0},
|
||||
is_visible = true,
|
||||
pointable = false,
|
||||
static_save = false,
|
||||
},
|
||||
moving_state = true,
|
||||
slippery_state = false,
|
||||
|
@ -191,7 +188,7 @@ minetest.register_entity("mcl_experience:orb", {
|
|||
-- This was a minetest bug for a while: https://github.com/minetest/minetest/issues/14420
|
||||
local xp = tonumber(staticdata) or 0
|
||||
self._xp = xp
|
||||
size = xp_to_size(xp)
|
||||
local size = xp_to_size(xp)
|
||||
|
||||
self.object:set_properties({
|
||||
visual_size = {x = size, y = size},
|
||||
|
@ -199,6 +196,9 @@ minetest.register_entity("mcl_experience:orb", {
|
|||
})
|
||||
self.object:set_sprite({x=1,y=math.random(1,14)}, 14, 0.05, false)
|
||||
end,
|
||||
get_staticdata = function(self)
|
||||
return tostring(self._xp or 0)
|
||||
end,
|
||||
|
||||
enable_physics = function(self)
|
||||
if not self.physical_state then
|
||||
|
|
|
@ -113,8 +113,8 @@ mesecon.register_node("mcl_observers:observer", {
|
|||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
paramtype2 = "facedir",
|
||||
on_rotate = false,
|
||||
_mcl_blast_resistance = 3.5,
|
||||
_mcl_hardness = 3.5,
|
||||
_mcl_blast_resistance = 3,
|
||||
_mcl_hardness = 3,
|
||||
}, {
|
||||
description = S("Observer"),
|
||||
_tt_help = S("Emits redstone pulse when block in front changes"),
|
||||
|
@ -172,8 +172,8 @@ mesecon.register_node("mcl_observers:observer_down", {
|
|||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
groups = {pickaxey=1, material_stone=1, not_opaque=1, not_in_creative_inventory=1 },
|
||||
on_rotate = false,
|
||||
_mcl_blast_resistance = 3.5,
|
||||
_mcl_hardness = 3.5,
|
||||
_mcl_blast_resistance = 3,
|
||||
_mcl_hardness = 3,
|
||||
drop = "mcl_observers:observer_off",
|
||||
}, {
|
||||
tiles = {
|
||||
|
@ -224,8 +224,8 @@ mesecon.register_node("mcl_observers:observer_up", {
|
|||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
groups = {pickaxey=1, material_stone=1, not_opaque=1, not_in_creative_inventory=1 },
|
||||
on_rotate = false,
|
||||
_mcl_blast_resistance = 3.5,
|
||||
_mcl_hardness = 3.5,
|
||||
_mcl_blast_resistance = 3,
|
||||
_mcl_hardness = 3,
|
||||
drop = "mcl_observers:observer_off",
|
||||
}, {
|
||||
tiles = {
|
||||
|
|
|
@ -218,7 +218,7 @@ minetest.register_node("mesecons_pistons:piston_normal_off", {
|
|||
},
|
||||
},
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
_mcl_hardness = 1.5,
|
||||
on_rotate = function(pos, node, user, mode)
|
||||
if mode == screwdriver.ROTATE_AXIS then
|
||||
minetest.set_node(pos, {name="mesecons_pistons:piston_up_normal_off"})
|
||||
|
@ -255,7 +255,7 @@ minetest.register_node("mesecons_pistons:piston_normal_on", {
|
|||
},
|
||||
},
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
_mcl_hardness = 1.5,
|
||||
on_rotate = false,
|
||||
})
|
||||
|
||||
|
@ -326,7 +326,7 @@ minetest.register_node("mesecons_pistons:piston_sticky_off", {
|
|||
},
|
||||
},
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
_mcl_hardness = 1.5,
|
||||
on_rotate = function(pos, node, user, mode)
|
||||
if mode == screwdriver.ROTATE_AXIS then
|
||||
minetest.set_node(pos, {name="mesecons_pistons:piston_up_sticky_off"})
|
||||
|
@ -363,7 +363,7 @@ minetest.register_node("mesecons_pistons:piston_sticky_on", {
|
|||
},
|
||||
},
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
_mcl_hardness = 1.5,
|
||||
on_rotate = false,
|
||||
})
|
||||
|
||||
|
@ -449,7 +449,7 @@ minetest.register_node("mesecons_pistons:piston_up_normal_off", {
|
|||
footstep = mcl_sounds.node_sound_wood_defaults().footstep
|
||||
}),
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
_mcl_hardness = 1.5,
|
||||
on_rotate = function(pos, node, user, mode)
|
||||
if mode == screwdriver.ROTATE_AXIS then
|
||||
minetest.set_node(pos, {name="mesecons_pistons:piston_down_normal_off"})
|
||||
|
@ -487,7 +487,7 @@ minetest.register_node("mesecons_pistons:piston_up_normal_on", {
|
|||
},
|
||||
},
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
_mcl_hardness = 1.5,
|
||||
on_rotate = false,
|
||||
})
|
||||
|
||||
|
@ -556,7 +556,7 @@ minetest.register_node("mesecons_pistons:piston_up_sticky_off", {
|
|||
},
|
||||
},
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
_mcl_hardness = 1.5,
|
||||
on_rotate = function(pos, node, user, mode)
|
||||
if mode == screwdriver.ROTATE_AXIS then
|
||||
minetest.set_node(pos, {name="mesecons_pistons:piston_down_sticky_off"})
|
||||
|
@ -594,7 +594,7 @@ minetest.register_node("mesecons_pistons:piston_up_sticky_on", {
|
|||
},
|
||||
},
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
_mcl_hardness = 1.5,
|
||||
on_rotate = false,
|
||||
})
|
||||
|
||||
|
@ -680,7 +680,7 @@ minetest.register_node("mesecons_pistons:piston_down_normal_off", {
|
|||
},
|
||||
},
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
_mcl_hardness = 1.5,
|
||||
on_rotate = function(pos, node, user, mode)
|
||||
if mode == screwdriver.ROTATE_AXIS then
|
||||
minetest.set_node(pos, {name="mesecons_pistons:piston_normal_off"})
|
||||
|
@ -718,7 +718,7 @@ minetest.register_node("mesecons_pistons:piston_down_normal_on", {
|
|||
},
|
||||
},
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
_mcl_hardness = 1.5,
|
||||
on_rotate = false,
|
||||
})
|
||||
|
||||
|
@ -782,7 +782,7 @@ minetest.register_node("mesecons_pistons:piston_down_sticky_off", {
|
|||
},
|
||||
},
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
_mcl_hardness = 1.5,
|
||||
on_rotate = function(pos, node, user, mode)
|
||||
if mode == screwdriver.ROTATE_AXIS then
|
||||
minetest.set_node(pos, {name="mesecons_pistons:piston_sticky_off"})
|
||||
|
@ -820,7 +820,7 @@ minetest.register_node("mesecons_pistons:piston_down_sticky_on", {
|
|||
},
|
||||
},
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
_mcl_hardness = 1.5,
|
||||
on_rotate = false,
|
||||
})
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ local function get_anvil_formspec(set_name)
|
|||
|
||||
"field[4.125,0.75;7.25,1;name;;" .. F(set_name) .. "]",
|
||||
"field_close_on_enter[name;false]",
|
||||
"field_enter_after_edit[name;true]",
|
||||
"set_focus[name;true]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(1.625, 2.6, 1, 1),
|
||||
|
|
|
@ -62,7 +62,7 @@ local bamboo_def = {
|
|||
inventory_image = "mcl_bamboo_bamboo_shoot.png",
|
||||
wield_image = "mcl_bamboo_bamboo_shoot.png",
|
||||
_mcl_blast_resistance = 1,
|
||||
_mcl_hardness = 1.5,
|
||||
_mcl_hardness = 1,
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
|
@ -277,7 +277,7 @@ local bamboo_block_def = {
|
|||
sounds = node_sound,
|
||||
paramtype2 = "facedir",
|
||||
drops = "mcl_bamboo:bamboo_block",
|
||||
_mcl_blast_resistance = 3,
|
||||
_mcl_blast_resistance = 2,
|
||||
_mcl_hardness = 2,
|
||||
_mcl_stripped_variant = "mcl_bamboo:bamboo_block_stripped", -- this allows us to use the built in Axe's strip block.
|
||||
on_place = mcl_util.rotate_axis,
|
||||
|
|
|
@ -208,7 +208,7 @@ if minetest.get_modpath("mcl_fences") then
|
|||
wood_groups,
|
||||
minetest.registered_nodes["mcl_core:wood"]._mcl_hardness,
|
||||
minetest.registered_nodes["mcl_core:wood"]._mcl_blast_resistance,
|
||||
node_sound) -- note: about missing params.. will use defaults.
|
||||
node_sound)
|
||||
|
||||
mcl_bamboo.mcl_log(dump(fence_id))
|
||||
mcl_bamboo.mcl_log(dump(gate_id))
|
||||
|
|
|
@ -210,7 +210,7 @@ function mcl_beds.register_bed(name, def)
|
|||
stack_max = 1,
|
||||
groups = {handy=1, bed = 1, dig_by_piston=1, bouncy=66, fall_damage_add_percent=-50, deco_block = 1, flammable=-1},
|
||||
_mcl_hardness = 0.2,
|
||||
_mcl_blast_resistance = 1,
|
||||
_mcl_blast_resistance = 0.2,
|
||||
sounds = def.sounds or default_sounds,
|
||||
selection_box = common_box,
|
||||
collision_box = common_box,
|
||||
|
@ -286,10 +286,9 @@ function mcl_beds.register_bed(name, def)
|
|||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
is_ground_content = false,
|
||||
-- FIXME: Should be bouncy=66, but this would be a higher bounciness than slime blocks!
|
||||
groups = {handy = 1, flammable = -1, bed = 2, dig_by_piston=1, bouncy=33, fall_damage_add_percent=-50, not_in_creative_inventory = 1},
|
||||
groups = {handy = 1, flammable = -1, bed = 2, dig_by_piston=1, bouncy=66, fall_damage_add_percent=-50, not_in_creative_inventory = 1},
|
||||
_mcl_hardness = 0.2,
|
||||
_mcl_blast_resistance = 1,
|
||||
_mcl_blast_resistance = 0.2,
|
||||
sounds = def.sounds or default_sounds,
|
||||
drop = "",
|
||||
selection_box = common_box,
|
||||
|
|
|
@ -33,8 +33,8 @@ minetest.register_node("mcl_blackstone:blackstone_gilded", {
|
|||
{items = {"mcl_blackstone:blackstone_gilded"}, rarity = 1},
|
||||
}
|
||||
},
|
||||
_mcl_blast_resistance = 2,
|
||||
_mcl_hardness = 2,
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 1.5,
|
||||
_mcl_silk_touch_drop = true,
|
||||
_mcl_fortune_drop = {
|
||||
discrete_uniform_distribution = true,
|
||||
|
@ -196,7 +196,7 @@ end
|
|||
mcl_stairs.register_stair_and_slab("blackstone", "mcl_blackstone:blackstone",
|
||||
{cracky=3, pickaxey=1, material_stone=1},
|
||||
{"mcl_blackstone_top.png", "mcl_blackstone_top.png", "mcl_blackstone_side.png"},
|
||||
S("Blackstone Stairs"),
|
||||
S("Blackstone Stair"),
|
||||
S("Blackstone Slab"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
S("Double Blackstone Slab"), nil)
|
||||
|
@ -204,7 +204,7 @@ mcl_stairs.register_stair_and_slab("blackstone", "mcl_blackstone:blackstone",
|
|||
mcl_stairs.register_stair_and_slab("blackstone_polished", "mcl_blackstone:blackstone_polished",
|
||||
{cracky=3, pickaxey=1, material_stone=1},
|
||||
{"mcl_blackstone_polished.png"},
|
||||
S("Polished Blackstone Stairs"),
|
||||
S("Polished Blackstone Stair"),
|
||||
S("Polished Blackstone Slab"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
S("Double Polished Blackstone Slab"), nil)
|
||||
|
@ -212,7 +212,7 @@ mcl_stairs.register_stair_and_slab("blackstone_polished", "mcl_blackstone:blacks
|
|||
mcl_stairs.register_stair_and_slab("blackstone_chiseled_polished", "mcl_blackstone:blackstone_chiseled_polished",
|
||||
{cracky=3, pickaxey=1, material_stone=1},
|
||||
{"mcl_blackstone_chiseled_polished.png"},
|
||||
S("Chiseled Polished Blackstone Stairs"),
|
||||
S("Chiseled Polished Blackstone Stair"),
|
||||
S("Chiseled Polished Blackstone Slab"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
S("Double Chiseled Polished Blackstone Slab"), nil)
|
||||
|
@ -220,24 +220,13 @@ mcl_stairs.register_stair_and_slab("blackstone_chiseled_polished", "mcl_blacksto
|
|||
mcl_stairs.register_stair_and_slab("blackstone_brick_polished", "mcl_blackstone:blackstone_brick_polished",
|
||||
{cracky=3, pickaxey=1, material_stone=1},
|
||||
{"mcl_blackstone_polished_bricks.png"},
|
||||
S("Polished Blackstone Brick Stair Stairs"),
|
||||
S("Polished Blackstone Brick Stair Slab"),
|
||||
S("Polished Blackstone Brick Stair"),
|
||||
S("Polished Blackstone Brick Slab"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
S("Double Polished Blackstone Brick Stair Slab"), nil)
|
||||
S("Double Polished Blackstone Brick Slab"), nil)
|
||||
|
||||
--Wall
|
||||
mcl_walls.register_wall(
|
||||
"mcl_blackstone:wall",
|
||||
S("Blackstone Wall"),
|
||||
"mcl_blackstone:blackstone",
|
||||
{
|
||||
"mcl_blackstone_top.png",
|
||||
"mcl_blackstone_top.png",
|
||||
"mcl_blackstone_side.png"
|
||||
},
|
||||
"",
|
||||
{ cracky=3, pickaxey=1, material_stone=1 }
|
||||
)
|
||||
mcl_walls.register_wall("mcl_blackstone:wall", S("Blackstone Wall"), "mcl_blackstone:blackstone")
|
||||
|
||||
--lavacooling
|
||||
|
||||
|
|
|
@ -9,10 +9,10 @@ Blackstone Slab=Schwarzstein Stufe
|
|||
Polished Blackstone Slab=Polierte Schwarzstein Stufe
|
||||
Chiseled Polished Blackstone Slab=Gemeißelte Polierte Schwarzstein Stufe
|
||||
Polished Blackstone Brick Slab=Polierte Schwarzsteinziegel Stufe
|
||||
Blackstone Stairs=Schwarzstein Treppe
|
||||
Polished Blackstone Stairs=Polierte Schwarzstein Treppe
|
||||
Chiseled Polished Blackstone Stairs=Gemeißelte Polierte Schwarzstein Treppe
|
||||
Polished Blackstone Brick Stairs=Polierte Schwarzsteinziegel Treppe
|
||||
Blackstone Stair=Schwarzstein Treppe
|
||||
Polished Blackstone Stair=Polierte Schwarzstein Treppe
|
||||
Chiseled Polished Blackstone Stair=Gemeißelte Polierte Schwarzstein Treppe
|
||||
Polished Blackstone Brick Stair=Polierte Schwarzsteinziegel Treppe
|
||||
Quartz Bricks=Quartz Ziegel
|
||||
Soul Torch=Seelenfakel
|
||||
Soul Lantern=Seelenlaterne
|
||||
|
|
|
@ -456,8 +456,8 @@ minetest.register_node("mcl_brewing:stand_000", {
|
|||
}
|
||||
},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 1,
|
||||
_mcl_hardness = 1,
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
on_destruct = on_destruct,
|
||||
allow_metadata_inventory_take = allow_take,
|
||||
allow_metadata_inventory_put = allow_put,
|
||||
|
@ -537,8 +537,8 @@ minetest.register_node("mcl_brewing:stand_100", {
|
|||
}
|
||||
},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 1,
|
||||
_mcl_hardness = 1,
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
on_destruct = on_destruct,
|
||||
allow_metadata_inventory_take = allow_take,
|
||||
allow_metadata_inventory_put = allow_put,
|
||||
|
@ -617,8 +617,8 @@ minetest.register_node("mcl_brewing:stand_010", {
|
|||
}
|
||||
},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 1,
|
||||
_mcl_hardness = 1,
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
on_destruct = on_destruct,
|
||||
allow_metadata_inventory_take = allow_take,
|
||||
allow_metadata_inventory_put = allow_put,
|
||||
|
@ -692,8 +692,8 @@ minetest.register_node("mcl_brewing:stand_001", {
|
|||
}
|
||||
},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 1,
|
||||
_mcl_hardness = 1,
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
on_destruct = on_destruct,
|
||||
allow_metadata_inventory_take = allow_take,
|
||||
allow_metadata_inventory_put = allow_put,
|
||||
|
@ -777,8 +777,8 @@ minetest.register_node("mcl_brewing:stand_110", {
|
|||
}
|
||||
},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 1,
|
||||
_mcl_hardness = 1,
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
on_destruct = on_destruct,
|
||||
allow_metadata_inventory_take = allow_take,
|
||||
allow_metadata_inventory_put = allow_put,
|
||||
|
@ -858,8 +858,8 @@ minetest.register_node("mcl_brewing:stand_101", {
|
|||
}
|
||||
},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 1,
|
||||
_mcl_hardness = 1,
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
on_destruct = on_destruct,
|
||||
allow_metadata_inventory_take = allow_take,
|
||||
allow_metadata_inventory_put = allow_put,
|
||||
|
@ -939,8 +939,8 @@ minetest.register_node("mcl_brewing:stand_011", {
|
|||
}
|
||||
},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 1,
|
||||
_mcl_hardness = 1,
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
on_destruct = on_destruct,
|
||||
allow_metadata_inventory_take = allow_take,
|
||||
allow_metadata_inventory_put = allow_put,
|
||||
|
@ -1027,8 +1027,8 @@ minetest.register_node("mcl_brewing:stand_111", {
|
|||
}
|
||||
},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 1,
|
||||
_mcl_hardness = 1,
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
on_destruct = on_destruct,
|
||||
allow_metadata_inventory_take = allow_take,
|
||||
allow_metadata_inventory_put = allow_put,
|
||||
|
|
|
@ -19,6 +19,6 @@ Cherry Slab=Dalle en cerisier
|
|||
Double Cherry Slab=Double Dalle en cerisier
|
||||
Cherry Sign=Panneau de cerisier
|
||||
Cherry Fence=Barrière en cerisier
|
||||
Cherry Gate=Portillion en cerisier
|
||||
Cherry Fence Gate=Portillion en cerisier
|
||||
Cherry Pressure Plate=Plaque de pression en cerisier
|
||||
Cherry Button=Bouton de Cerisier
|
||||
|
|
|
@ -19,6 +19,6 @@ Cherry Slab=Laje de Cerejeira
|
|||
Double Cherry Slab=Laje Dupla de Cerejeira
|
||||
Cherry Sign=Placa de Cerejeira
|
||||
Cherry Fence=Cerca de Cerejeira
|
||||
Cherry Gate=Portão de Cerejeira
|
||||
Cherry Fence Gate=Portão de Cerejeira
|
||||
Cherry Pressure Plate=Placa de Pressão de Cerejeira
|
||||
Cherry Button=Botão de Cerejeira
|
||||
|
|
|
@ -19,6 +19,6 @@ Cherry Slab=Вишнёвая плита
|
|||
Double Cherry Slab=Двойная вишнёвая плита
|
||||
Cherry Sign=Вишнёвая табличка
|
||||
Cherry Fence=Вишнёвый забор
|
||||
Cherry Gate=Вишнёвая калитка
|
||||
Cherry Fence Gate=Вишнёвая калитка
|
||||
Cherry Pressure Plate=Вишнёвая нажимная плита
|
||||
Cherry Button=Вишнёвая кнопка
|
||||
|
|
|
@ -19,6 +19,6 @@ Cherry Slab=
|
|||
Double Cherry Slab=
|
||||
Cherry Sign=
|
||||
Cherry Fence=
|
||||
Cherry Gate=
|
||||
Cherry Fence Gate=
|
||||
Cherry Pressure Plate=
|
||||
Cherry Button=
|
||||
|
|
|
@ -51,13 +51,13 @@ mcl_stairs.register_stair("cherrywood", "mcl_cherry_blossom:cherrywood",
|
|||
{handy=1,axey=1, flammable=3,wood_stairs=1, material_wood=1, fire_encouragement=5, fire_flammability=20},
|
||||
{"mcl_cherry_blossom_planks.png"},
|
||||
S("Cherry Stairs"),
|
||||
mcl_sounds.node_sound_wood_defaults(), 3, 2,
|
||||
mcl_sounds.node_sound_wood_defaults(), nil, nil,
|
||||
"woodlike")
|
||||
mcl_stairs.register_slab("cherrywood", "mcl_cherry_blossom:cherrywood",
|
||||
{handy=1,axey=1, flammable=3,wood_slab=1, material_wood=1, fire_encouragement=5, fire_flammability=20},
|
||||
{"mcl_cherry_blossom_planks.png"},
|
||||
S("Cherry Slab"),
|
||||
mcl_sounds.node_sound_wood_defaults(), 3, 2,
|
||||
mcl_sounds.node_sound_wood_defaults(), nil, nil,
|
||||
S("Double Cherry Slab"))
|
||||
|
||||
-- Signs
|
||||
|
@ -69,7 +69,7 @@ mcl_signs.register_sign_custom("mcl_cherry_blossom", "_cherrywood",
|
|||
mcl_fences.register_fence_and_fence_gate(
|
||||
"cherry_fence",
|
||||
S("Cherry Fence"),
|
||||
S("Cherry Gate"),
|
||||
S("Cherry Fence Gate"),
|
||||
"mcl_cherry_blossom_planks.png",
|
||||
{handy=1, axey=1, flammable=2, fence_wood=1, fire_encouragement=5, fire_flammability=20},
|
||||
minetest.registered_nodes["mcl_core:wood"]._mcl_hardness,
|
||||
|
|
|
@ -0,0 +1,233 @@
|
|||
# `mcl_chests` API
|
||||
|
||||
When reading through this documentation, please keep in mind that the chest
|
||||
animations are achieved by giving each chest node an entity, as Minetest (as of
|
||||
5.8.1) doesn't support giving nodes animated meshes, only static ones.
|
||||
|
||||
Because of that, a lot of parameters passed through the exposed functions are
|
||||
be related to nodes and entities.
|
||||
|
||||
Please refer to [Minetest documentation](http://api.minetest.net/) and the code
|
||||
comments in `api.lua`.
|
||||
|
||||
|
||||
## `mcl_chests.register_chest(basename, definition)`
|
||||
|
||||
This function allows for simple chest registration, used by both regular and
|
||||
trapped chests.
|
||||
|
||||
* `basename` is a string that will be concatenated to form full nodenames for
|
||||
chests, for example `"mcl_chests:basename_small"`.
|
||||
* `definition` is a key-value table, with the following fields:
|
||||
|
||||
```lua
|
||||
{
|
||||
desc = S("Stone Chest"),
|
||||
-- Equivalent to `description` field of Item/Node definition.
|
||||
-- Will be shown as chest's name in the inventory.
|
||||
|
||||
title = {
|
||||
small = S("Stone Chest") -- the same as `desc` if not specified
|
||||
double = S("Large Stone Chest") -- defaults to `"Large " .. desc`
|
||||
}
|
||||
-- These will be shown when opening the chest (in formspecs).
|
||||
|
||||
longdesc = S(
|
||||
"Stone Chests are containers which provide 27 inventory slots. Stone Chests can be turned into" ..
|
||||
"large stone chests with double the capacity by placing two stone chests next to each other."
|
||||
),
|
||||
usagehelp = S("To access its inventory, rightclick it. When broken, the items will drop out."),
|
||||
tt_help = S("27 inventory slots") .. "\n" .. S("Can be combined to a large stone chest"),
|
||||
-- Equivalent to `_doc_items_longdesc`, `_doc_items_usagehelp` and
|
||||
-- `_tt_help` fields of Item/Node definition. Shown in the tooltip and wiki.
|
||||
|
||||
tiles = {
|
||||
small = { "vl_stone_chests_small.png" },
|
||||
double = { "vl_stone_chests_double.png" },
|
||||
inv = {
|
||||
"vl_stone_chests_top.png",
|
||||
"vl_stone_chests_bottom.png",
|
||||
"vl_stone_chests_right.png",
|
||||
"vl_stone_chests_left.png",
|
||||
"vl_stone_chests_back.png",
|
||||
"vl_stone_chests_front.png"
|
||||
},
|
||||
},
|
||||
-- `small` and `double` fields contain the textures that will be applied to
|
||||
-- chest entities.
|
||||
-- `inv` field contains table of textures (6 in total, for each cube side),
|
||||
-- that will be used to render the chest "node" in the inventory.
|
||||
|
||||
groups = {
|
||||
pickaxey = 1,
|
||||
stone = 1,
|
||||
material_stone = 1,
|
||||
},
|
||||
-- Equivalent to `groups` field of Item/Node definition. There is some table
|
||||
-- merging occuring internally, but it is purely for entity rendering.
|
||||
|
||||
sounds = {
|
||||
mcl_sounds.node_sound_stone_defaults(), -- defaults to `nil`
|
||||
"vl_stone_chests_sound" -- defaults to `"default_chest"`
|
||||
},
|
||||
-- First value is equivalent to `sounds` field of Item/Node definition.
|
||||
-- Second value is a sound prefix, from which the actual sounds will be
|
||||
-- concatenated (e.g. `vl_stone_chests_sound_open.ogg`). See `api.lua`.
|
||||
|
||||
hardness = 4.0,
|
||||
-- Equivalent to `_mcl_blast_resistance` and `_mcl_hardness` fields of
|
||||
-- Item/Node definition. They are always equal for chests.
|
||||
|
||||
hidden = false,
|
||||
-- Equivalent to `_doc_items_hidden` field of Item/Node definition.
|
||||
|
||||
mesecons = {
|
||||
receptor = {
|
||||
state = mesecon.state.on,
|
||||
rules = mesecon.rules.pplate,
|
||||
},
|
||||
},
|
||||
-- Equivalent to `mesecons` field of Item/Node definition.
|
||||
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
mcl_util.deal_damage(clicker, 2)
|
||||
end,
|
||||
-- If provided, will be executed at the end of the actual `on_rightclick`
|
||||
-- function of the chest node.
|
||||
-- If `on_rightclick_left` or `on_rightclick_right` are not provided, this
|
||||
-- will also be what is executed for left and right double chest nodes,
|
||||
-- respectively.
|
||||
|
||||
drop = "chest",
|
||||
-- If provided, the chest will not drop itself, but the item of the chest
|
||||
-- with that basename.
|
||||
|
||||
canonical_basename = "chest",
|
||||
-- If provided, the chest will turn into chest with that basename in
|
||||
-- `on_construct`.
|
||||
}
|
||||
```
|
||||
|
||||
For usage examples, see `chests.lua` and `example.lua`.
|
||||
|
||||
|
||||
## `mcl_chests.create_entity(pos, node_name, textures, param2, double, sound_prefix, mesh_prefix, animation_type, dir, entity_pos)`
|
||||
|
||||
This function creates a chest entity based on the parameters:
|
||||
|
||||
* `pos` is the position vector.
|
||||
* `node_name` is a string used in initialization data for the entity.
|
||||
* `textures` is the entity textures.
|
||||
* `param2` is a node param2, which then will be converted to entity direction.
|
||||
* `double` is a boolean value for whether the chest is double or not.
|
||||
* `sound_prefix` is a string, from which the actual sounds for the entity will
|
||||
be concatenated.
|
||||
* `mesh_prefix` is the same thing as `sound_prefix`, but for meshes.
|
||||
* `animation_type` is a string that will be used in `set_animation` method of
|
||||
chest entity.
|
||||
* `dir` and `entity_pos` are number and vector values used to get entity info.
|
||||
|
||||
Returned value is either a luaentity, or `nil` if failed (in which case a
|
||||
warning message gets written into the console).
|
||||
|
||||
|
||||
## `mcl_chests.find_or_create_entity(pos, node_name, textures, param2, double, sound_prefix, mesh_prefix, animation_type, dir, entity_pos)`
|
||||
|
||||
This function finds an existing entity, or creates one if failed. Parameters:
|
||||
|
||||
* `pos` is the position vector.
|
||||
* `node_name` is a string used in initialization data for the entity.
|
||||
* `textures` is the entity textures.
|
||||
* `param2` is a node param2, which then will be converted to entity direction.
|
||||
* `double` is a boolean value for whether the chest is double or not.
|
||||
* `sound_prefix` is a string, from which the actual sounds for the entity will
|
||||
be concatenated.
|
||||
* `mesh_prefix` is the same thing as `sound_prefix`, but for meshes.
|
||||
* `animation_type` is a string that will be used in `set_animation` method of
|
||||
chest entity.
|
||||
* `dir` and `entity_pos` are number and vector values used to get entity info.
|
||||
|
||||
Returned value is either a luaentity, or `nil` if failed (in which case a
|
||||
warning message gets written into the console).
|
||||
|
||||
|
||||
## `mcl_chests.select_and_spawn_entity(pos, node)`
|
||||
|
||||
This function is a simple wrapper for `mcl_chests.find_or_create_entity`,
|
||||
getting most of the fields from node definition.
|
||||
|
||||
* `pos` is the position vector.
|
||||
* `node` is a NodeRef.
|
||||
|
||||
Returned value is either a luaentity, or `nil` if failed (in which case a
|
||||
warning message gets written into the console).
|
||||
|
||||
|
||||
## `mcl_chests.no_rotate`
|
||||
|
||||
This function is equivalent to `screwdriver.disallow` and is used when a chest
|
||||
can't be rotated, and is applied in `on_rotate` field of Node definition.
|
||||
|
||||
|
||||
## `mcl_chests.simple_rotate(pos, node, user, mode, new_param2)`
|
||||
|
||||
This function allows for simple rotation with the entity being affected as well,
|
||||
and is applied in `on_rotate` field of Node definition.
|
||||
|
||||
|
||||
## `mcl_chests.open_chests`
|
||||
|
||||
This table contains all currently open chests, indexed by player name.
|
||||
|
||||
`nil` if player is not using a chest, and `{ pos = <chest node position> }`
|
||||
otherwise (where position is a vector value).
|
||||
|
||||
|
||||
## `mcl_chests.protection_check_move(pos, from_list, from_index, to_list, to_index, count, player)`
|
||||
|
||||
This function is called in `allow_metadata_inventory_move` field of Node
|
||||
definition.
|
||||
|
||||
|
||||
## `mcl_chests.protection_check_put_take(pos, listname, index, stack, player)`
|
||||
|
||||
This function is called in `allow_metadata_inventory_put` and
|
||||
`allow_metadata_inventory_take` fields of Node definition.
|
||||
|
||||
|
||||
## `mcl_chests.player_chest_open(player, pos, node_name, textures, param2, double, sound, mesh, shulker)`
|
||||
|
||||
This function opens a chest based on the parameters:
|
||||
|
||||
* `player` is an ObjectRef.
|
||||
* `pos` is the position vector.
|
||||
* `node_name` is a string used in initialization data for the entity.
|
||||
* `textures` is the entity textures.
|
||||
* `param2` is a node param2, which then will be converted to entity direction.
|
||||
* `double` is a boolean value for whether the chest is double or not.
|
||||
* `sound` is a prefix string, from which the actual sounds for the entity will
|
||||
be concatenated.
|
||||
* `mesh` is the same thing as `sound`, but for meshes.
|
||||
* `shulker` is a boolean value for whether the chest is a shulker or not.
|
||||
|
||||
|
||||
## `mcl_chests.player_chest_close(player)`
|
||||
|
||||
This function has to be called when a player closes a chest.
|
||||
|
||||
* `player` is an ObjectRef.
|
||||
|
||||
|
||||
## `mcl_chests.chest_update_after_close(pos)`
|
||||
|
||||
This function is called when a chest is closed by `player_chest_close`.
|
||||
|
||||
* `pos` is the chest's position vector.
|
||||
|
||||
|
||||
## `mcl_chests.is_not_shulker_box(stack)`
|
||||
|
||||
This function checks for whether `stack` is a shulker box, and returns `false`
|
||||
if it is. Used internally to disallow putting shulker boxes into shulker boxes.
|
||||
|
||||
* `stack` is an ItemStack.
|
|
@ -0,0 +1,19 @@
|
|||
# `mcl_chests`
|
||||
|
||||
This mod adds normal and large chests, trapped chests, ender chests and
|
||||
shulkers, providing an API for mods to register their own chests.
|
||||
|
||||
The API is documented in `API.md`.
|
||||
|
||||
|
||||
## License of source code
|
||||
|
||||
Copyright (C) 2011-2012 celeron55, Perttu Ahola <celeron55@gmail.com>\
|
||||
Copyright (C) 2024 rudzik8, Mikita Wiśniewski <rudzik8@protonmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
http://www.gnu.org/licenses/lgpl-2.1.html
|
|
@ -0,0 +1,966 @@
|
|||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
local F = minetest.formspec_escape
|
||||
local C = minetest.colorize
|
||||
|
||||
local get_double_container_neighbor_pos = mcl_util.get_double_container_neighbor_pos
|
||||
|
||||
local string = string
|
||||
local table = table
|
||||
|
||||
local sf = string.format
|
||||
|
||||
-- Recursively merge tables with eachother
|
||||
local function table_merge(tbl, ...)
|
||||
local t = table.copy(tbl)
|
||||
for k,v in pairs(...) do
|
||||
if type(t[k]) == "table" and type(v) == "table" then
|
||||
table_merge(t[k], v)
|
||||
else
|
||||
t[k] = v
|
||||
end
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
-- Chest Entity
|
||||
-- ------------
|
||||
-- This is necessary to show the chest as an animated mesh, as Minetest doesn't support assigning animated meshes to
|
||||
-- nodes directly. We're bypassing this limitation by giving each chest its own entity, and making the chest node
|
||||
-- itself fully transparent.
|
||||
local animated_chests = (minetest.settings:get_bool("animated_chests") ~= false)
|
||||
local entity_animations = {
|
||||
shulker = {
|
||||
speed = 50,
|
||||
open = { x = 45, y = 95 },
|
||||
close = { x = 95, y = 145 },
|
||||
},
|
||||
chest = {
|
||||
speed = 25,
|
||||
open = { x = 0, y = 7 },
|
||||
close = { x = 13, y = 20 },
|
||||
},
|
||||
}
|
||||
|
||||
minetest.register_entity("mcl_chests:chest", {
|
||||
initial_properties = {
|
||||
visual = "mesh",
|
||||
pointable = false,
|
||||
physical = false,
|
||||
static_save = false,
|
||||
},
|
||||
|
||||
set_animation = function(self, animname)
|
||||
local anim_table = entity_animations[self.animation_type]
|
||||
local anim = anim_table[animname]
|
||||
if not anim then return end
|
||||
self.object:set_animation(anim, anim_table.speed, 0, false)
|
||||
end,
|
||||
|
||||
open = function(self, playername)
|
||||
self.players[playername] = true
|
||||
if not self.is_open then
|
||||
self:set_animation("open")
|
||||
minetest.sound_play(self.sound_prefix .. "_open", { pos = self.node_pos, gain = 0.5, max_hear_distance = 16 },
|
||||
true)
|
||||
self.is_open = true
|
||||
end
|
||||
end,
|
||||
|
||||
close = function(self, playername)
|
||||
local playerlist = self.players
|
||||
playerlist[playername] = nil
|
||||
if self.is_open then
|
||||
if next(playerlist) then
|
||||
return
|
||||
end
|
||||
self:set_animation("close")
|
||||
minetest.sound_play(self.sound_prefix .. "_close",
|
||||
{ pos = self.node_pos, gain = 0.3, max_hear_distance = 16 },
|
||||
true)
|
||||
self.is_open = false
|
||||
end
|
||||
end,
|
||||
|
||||
initialize = function(self, node_pos, node_name, textures, dir, double, sound_prefix, mesh_prefix, animation_type)
|
||||
self.node_pos = node_pos
|
||||
self.node_name = node_name
|
||||
self.sound_prefix = sound_prefix
|
||||
self.animation_type = animation_type
|
||||
local obj = self.object
|
||||
obj:set_armor_groups({ immortal = 1 })
|
||||
obj:set_properties({
|
||||
textures = textures,
|
||||
mesh = mesh_prefix .. (double and "_double" or "") .. ".b3d",
|
||||
})
|
||||
self:set_yaw(dir)
|
||||
self.players = {}
|
||||
end,
|
||||
|
||||
reinitialize = function(self, node_name)
|
||||
self.node_name = node_name
|
||||
end,
|
||||
|
||||
set_yaw = function(self, dir)
|
||||
self.object:set_yaw(minetest.dir_to_yaw(dir))
|
||||
end,
|
||||
|
||||
check = function(self)
|
||||
local node_pos, node_name = self.node_pos, self.node_name
|
||||
if not node_pos or not node_name then
|
||||
return false
|
||||
end
|
||||
local node = minetest.get_node(node_pos)
|
||||
if node.name ~= node_name then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end,
|
||||
|
||||
on_activate = function(self, initialization_data)
|
||||
if initialization_data and initialization_data:find("\"###mcl_chests:chest###\"") then
|
||||
self:initialize(unpack(minetest.deserialize(initialization_data)))
|
||||
else
|
||||
minetest.log("warning",
|
||||
"[mcl_chests] on_activate called without proper initialization_data ... removing entity")
|
||||
self.object:remove()
|
||||
end
|
||||
end,
|
||||
|
||||
on_step = function(self, dtime)
|
||||
if not self:check() then
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
local function get_entity_pos(pos, dir, double)
|
||||
pos = vector.copy(pos)
|
||||
if double then
|
||||
local add, mul, vec, cross = vector.add, vector.multiply, vector.new, vector.cross
|
||||
pos = add(pos, mul(cross(dir, vec(0, 1, 0)), -0.5))
|
||||
end
|
||||
return pos
|
||||
end
|
||||
|
||||
local function find_entity(pos)
|
||||
for _, obj in pairs(minetest.get_objects_inside_radius(pos, 0)) do
|
||||
local luaentity = obj:get_luaentity()
|
||||
if luaentity and luaentity.name == "mcl_chests:chest" then
|
||||
return luaentity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function get_entity_info(pos, param2, double, dir, entity_pos)
|
||||
dir = dir or minetest.facedir_to_dir(param2)
|
||||
return dir, get_entity_pos(pos, dir, double)
|
||||
end
|
||||
|
||||
local function create_entity(pos, node_name, textures, param2, double, sound_prefix, mesh_prefix, animation_type, dir,
|
||||
entity_pos)
|
||||
dir, entity_pos = get_entity_info(pos, param2, double, dir, entity_pos)
|
||||
local initialization_data = minetest.serialize({pos, node_name, textures, dir, double, sound_prefix,
|
||||
mesh_prefix, animation_type, "###mcl_chests:chest###"})
|
||||
local obj = minetest.add_entity(entity_pos, "mcl_chests:chest", initialization_data)
|
||||
if obj and obj:get_pos() then
|
||||
return obj:get_luaentity()
|
||||
else
|
||||
minetest.log("warning", "[mcl_chests] Failed to create entity at " ..
|
||||
(entity_pos and minetest.pos_to_string(entity_pos, 1) or "nil"))
|
||||
end
|
||||
end
|
||||
mcl_chests.create_entity = create_entity
|
||||
|
||||
local function find_or_create_entity(pos, node_name, textures, param2, double, sound_prefix, mesh_prefix,
|
||||
animation_type, dir, entity_pos)
|
||||
dir, entity_pos = get_entity_info(pos, param2, double, dir, entity_pos)
|
||||
return find_entity(entity_pos) or
|
||||
create_entity(pos, node_name, textures, param2, double, sound_prefix, mesh_prefix, animation_type, dir,
|
||||
entity_pos)
|
||||
end
|
||||
mcl_chests.find_or_create_entity = find_or_create_entity
|
||||
|
||||
local function select_and_spawn_entity(pos, node)
|
||||
local node_name = node.name
|
||||
local node_def = minetest.registered_nodes[node_name]
|
||||
local double_chest = minetest.get_item_group(node_name, "double_chest") > 0
|
||||
find_or_create_entity(pos, node_name, node_def._chest_entity_textures, node.param2, double_chest,
|
||||
node_def._chest_entity_sound, node_def._chest_entity_mesh, node_def._chest_entity_animation_type)
|
||||
end
|
||||
mcl_chests.select_and_spawn_entity = select_and_spawn_entity
|
||||
|
||||
local no_rotate, simple_rotate
|
||||
if screwdriver then
|
||||
no_rotate = screwdriver.disallow
|
||||
simple_rotate = function(pos, node, user, mode, new_param2)
|
||||
if screwdriver.rotate_simple(pos, node, user, mode, new_param2) ~= false then
|
||||
local nodename = node.name
|
||||
local nodedef = minetest.registered_nodes[nodename]
|
||||
local dir = minetest.facedir_to_dir(new_param2)
|
||||
find_or_create_entity(pos, nodename, nodedef._chest_entity_textures, new_param2, false,
|
||||
nodedef._chest_entity_sound,
|
||||
nodedef._chest_entity_mesh, nodedef._chest_entity_animation_type, dir):set_yaw(dir)
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
mcl_chests.no_rotate, mcl_chests.simple_rotate = no_rotate, simple_rotate
|
||||
|
||||
-- List of open chests
|
||||
-- -------------------
|
||||
-- Key: Player name
|
||||
-- Value:
|
||||
-- If player is using a chest: { pos = <chest node position> }
|
||||
-- Otherwise: nil
|
||||
local open_chests = {}
|
||||
mcl_chests.open_chests = open_chests
|
||||
|
||||
-- To be called if a player opened a chest
|
||||
local function player_chest_open(player, pos, node_name, textures, param2, double, sound, mesh, shulker)
|
||||
local name = player:get_player_name()
|
||||
open_chests[name] = {
|
||||
pos = pos,
|
||||
node_name = node_name,
|
||||
textures = textures,
|
||||
param2 = param2,
|
||||
double = double,
|
||||
sound = sound,
|
||||
mesh = mesh,
|
||||
shulker = shulker
|
||||
}
|
||||
if animated_chests then
|
||||
local dir = minetest.facedir_to_dir(param2)
|
||||
find_or_create_entity(pos, node_name, textures, param2, double, sound, mesh,
|
||||
shulker and "shulker" or "chest", dir):open(name)
|
||||
end
|
||||
end
|
||||
mcl_chests.player_chest_open = player_chest_open
|
||||
|
||||
-- Simple protection checking functions
|
||||
local function protection_check_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local name = player:get_player_name()
|
||||
if minetest.is_protected(pos, name) then
|
||||
minetest.record_protection_violation(pos, name)
|
||||
return 0
|
||||
else
|
||||
return count
|
||||
end
|
||||
end
|
||||
mcl_chests.protection_check_move = protection_check_move
|
||||
|
||||
local function protection_check_take(pos, listname, index, stack, player)
|
||||
local name = player:get_player_name()
|
||||
if minetest.is_protected(pos, name) then
|
||||
minetest.record_protection_violation(pos, name)
|
||||
return 0
|
||||
else
|
||||
return stack:get_count()
|
||||
end
|
||||
end
|
||||
mcl_chests.protection_check_put_take = protection_check_take
|
||||
|
||||
-- Logging functions
|
||||
local function log_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
minetest.log("action", player:get_player_name() ..
|
||||
" moves stuff to chest at " .. minetest.pos_to_string(pos))
|
||||
end
|
||||
|
||||
local function log_inventory_put(pos, listname, index, stack, player)
|
||||
minetest.log("action", player:get_player_name() ..
|
||||
" moves stuff to chest at " .. minetest.pos_to_string(pos))
|
||||
-- BEGIN OF LISTRING WORKAROUND
|
||||
if listname == "input" then
|
||||
local inv = minetest.get_inventory({ type = "node", pos = pos })
|
||||
inv:add_item("main", stack)
|
||||
end
|
||||
-- END OF LISTRING WORKAROUND
|
||||
end
|
||||
|
||||
local function log_inventory_take(pos, listname, index, stack, player)
|
||||
minetest.log("action", player:get_player_name() ..
|
||||
" takes stuff from chest at " .. minetest.pos_to_string(pos))
|
||||
end
|
||||
|
||||
-- To be called when a chest is closed (only relevant for trapped chest atm)
|
||||
local function chest_update_after_close(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
|
||||
if node.name == "mcl_chests:trapped_chest_on_small" then
|
||||
minetest.swap_node(pos, { name = "mcl_chests:trapped_chest_small", param2 = node.param2 })
|
||||
find_or_create_entity(pos, "mcl_chests:trapped_chest_small", { "mcl_chests_trapped.png" }, node.param2, false,
|
||||
"default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_small")
|
||||
mesecon.receptor_off(pos, mesecon.rules.pplate)
|
||||
elseif node.name == "mcl_chests:trapped_chest_on_left" then
|
||||
minetest.swap_node(pos, { name = "mcl_chests:trapped_chest_left", param2 = node.param2 })
|
||||
find_or_create_entity(pos, "mcl_chests:trapped_chest_left", mcl_chests.tiles.chest_trapped_double, node.param2, true,
|
||||
"default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
|
||||
mesecon.receptor_off(pos, mesecon.rules.pplate)
|
||||
|
||||
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, mesecon.rules.pplate)
|
||||
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, mesecon.rules.pplate)
|
||||
|
||||
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.tiles.chest_trapped_double,
|
||||
node.param2, true, "default_chest", "mcl_chests_chest", "chest")
|
||||
:reinitialize("mcl_chests:trapped_chest_left")
|
||||
mesecon.receptor_off(pos_other, mesecon.rules.pplate)
|
||||
end
|
||||
end
|
||||
mcl_chests.chest_update_after_close = chest_update_after_close
|
||||
|
||||
-- To be called if a player closed a chest
|
||||
local function player_chest_close(player)
|
||||
local name = player:get_player_name()
|
||||
local open_chest = open_chests[name]
|
||||
if open_chest == nil then
|
||||
return
|
||||
end
|
||||
if animated_chests then
|
||||
find_or_create_entity(open_chest.pos, open_chest.node_name, open_chest.textures, open_chest.param2,
|
||||
open_chest.double, open_chest.sound, open_chest.mesh, open_chest.shulker and "shulker" or "chest")
|
||||
:close(name)
|
||||
end
|
||||
chest_update_after_close(open_chest.pos)
|
||||
|
||||
open_chests[name] = nil
|
||||
end
|
||||
mcl_chests.player_chest_close = player_chest_close
|
||||
|
||||
local function double_chest_add_item(top_inv, bottom_inv, listname, stack)
|
||||
if not stack or stack:is_empty() then return end
|
||||
|
||||
local name = stack:get_name()
|
||||
|
||||
local function top_off(inv, stack)
|
||||
for c, chest_stack in ipairs(inv:get_list(listname)) do
|
||||
if stack:is_empty() then
|
||||
break
|
||||
end
|
||||
|
||||
if chest_stack:get_name() == name and chest_stack:get_free_space() > 0 then
|
||||
stack = chest_stack:add_item(stack)
|
||||
inv:set_stack(listname, c, chest_stack)
|
||||
end
|
||||
end
|
||||
|
||||
return stack
|
||||
end
|
||||
|
||||
stack = top_off(top_inv, stack)
|
||||
stack = top_off(bottom_inv, stack)
|
||||
|
||||
if not stack:is_empty() then
|
||||
stack = top_inv:add_item(listname, stack)
|
||||
if not stack:is_empty() then
|
||||
bottom_inv:add_item(listname, stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_chest_blast(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
local drop_items_chest = mcl_util.drop_items_from_meta_container("main")
|
||||
drop_items_chest(pos, node)
|
||||
minetest.remove_node(pos)
|
||||
end
|
||||
|
||||
local function limit_put_list(stack, list)
|
||||
for _, other in ipairs(list) do
|
||||
stack = other:add_item(stack)
|
||||
if stack:is_empty() then
|
||||
break
|
||||
end
|
||||
end
|
||||
return stack
|
||||
end
|
||||
|
||||
local function limit_put(stack, top_inv, bottom_inv)
|
||||
local leftover = ItemStack(stack)
|
||||
leftover = limit_put_list(leftover, top_inv:get_list("main"))
|
||||
leftover = limit_put_list(leftover, bottom_inv:get_list("main"))
|
||||
return stack:get_count() - leftover:get_count()
|
||||
end
|
||||
|
||||
local function close_forms(canonical_basename, pos)
|
||||
local players = minetest.get_connected_players()
|
||||
for p = 1, #players do
|
||||
if vector.distance(players[p]:get_pos(), pos) <= 30 then
|
||||
minetest.close_formspec(players[p]:get_player_name(),
|
||||
"mcl_chests:" .. canonical_basename .. "_" .. pos.x .. "_" .. pos.y .. "_" .. pos.z)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function get_chest_inventories(pos, side)
|
||||
local inv = minetest.get_inventory({ type = "node", pos = pos })
|
||||
|
||||
local node = minetest.get_node(pos)
|
||||
local pos_other = get_double_container_neighbor_pos(pos, node.param2, side)
|
||||
local inv_other = minetest.get_inventory({ type = "node", pos = pos_other })
|
||||
|
||||
local top_inv, bottom_inv
|
||||
if side == "left" then
|
||||
top_inv = inv
|
||||
bottom_inv = inv_other
|
||||
else
|
||||
top_inv = inv_other
|
||||
bottom_inv = inv
|
||||
end
|
||||
return top_inv, bottom_inv
|
||||
end
|
||||
|
||||
-- Functions used in double chest registration code
|
||||
-- ------------------------------------------------
|
||||
-- The `return function` wrapping is necessary to avoid stacking up parameters.
|
||||
-- `side` is either "left" or "right".
|
||||
local function hopper_pull_double(side) return function(pos, hop_pos, hop_inv, hop_list)
|
||||
local top_inv, bottom_inv = get_chest_inventories(pos, side)
|
||||
|
||||
local stack_id = mcl_util.select_stack(top_inv, "main", hop_inv, hop_list)
|
||||
if stack_id ~= nil then
|
||||
return top_inv, "main", stack_id
|
||||
end
|
||||
|
||||
stack_id = mcl_util.select_stack(bottom_inv, "main", hop_inv, hop_list)
|
||||
return bottom_inv, "main", stack_id
|
||||
end end
|
||||
|
||||
local function hopper_push_double(side) return function(pos, hop_pos, hop_inv, hop_list)
|
||||
local top_inv, bottom_inv = get_chest_inventories(pos, side)
|
||||
|
||||
local stack_id = mcl_util.select_stack(hop_inv, hop_list, top_inv, "main", nil, 1)
|
||||
if stack_id ~= nil then
|
||||
return top_inv, "main", stack_id
|
||||
end
|
||||
|
||||
stack_id = mcl_util.select_stack(hop_inv, hop_list, bottom_inv, "main", nil, 1)
|
||||
return bottom_inv, "main", stack_id
|
||||
end end
|
||||
|
||||
local function construct_double_chest(side, names) return function(pos)
|
||||
local n = minetest.get_node(pos)
|
||||
local param2 = n.param2
|
||||
local p = get_double_container_neighbor_pos(pos, param2, side)
|
||||
-- Turn into a small chest if the neighbor is gone
|
||||
if not p or minetest.get_node(p).name ~= names[side].cr then
|
||||
n.name = names.small.a
|
||||
minetest.swap_node(pos, n)
|
||||
end
|
||||
end end
|
||||
|
||||
local function destruct_double_chest(side, names, canonical_basename, small_textures, sound_prefix) return function(pos)
|
||||
local n = minetest.get_node(pos)
|
||||
if n.name == names.small.a then
|
||||
return
|
||||
end
|
||||
|
||||
close_forms(canonical_basename, pos)
|
||||
|
||||
local param2 = n.param2
|
||||
local p = get_double_container_neighbor_pos(pos, param2, side)
|
||||
if not p or minetest.get_node(p).name ~= names[side].r then
|
||||
return
|
||||
end
|
||||
close_forms(canonical_basename, p)
|
||||
|
||||
minetest.swap_node(p, { name = names.small.a, param2 = param2 })
|
||||
create_entity(p, names.small.a, small_textures, param2, false, sound_prefix, "mcl_chests_chest", "chest")
|
||||
end end
|
||||
|
||||
-- Small chests use `protection_check_take` for both put and take actions.
|
||||
local function protection_check_put(side) return function(pos, listname, index, stack, player)
|
||||
local name = player:get_player_name()
|
||||
if minetest.is_protected(pos, name) then
|
||||
minetest.record_protection_violation(pos, name)
|
||||
return 0
|
||||
-- BEGIN OF LISTRING WORKAROUND
|
||||
elseif listname == "input" then
|
||||
local top_inv, bottom_inv = get_chest_inventories(pos, side)
|
||||
return limit_put(stack, top_inv, bottom_inv)
|
||||
-- END OF LISTRING WORKAROUND
|
||||
else
|
||||
return stack:get_count()
|
||||
end
|
||||
end end
|
||||
|
||||
local function log_inventory_put_double(side) return function(pos, listname, index, stack, player)
|
||||
minetest.log("action", player:get_player_name() ..
|
||||
" moves stuff to chest at " .. minetest.pos_to_string(pos))
|
||||
-- BEGIN OF LISTRING WORKAROUND
|
||||
if listname == "input" then
|
||||
local top_inv, bottom_inv = get_chest_inventories(pos, side)
|
||||
|
||||
top_inv:set_stack("input", 1, nil)
|
||||
bottom_inv:set_stack("input", 1, nil)
|
||||
|
||||
double_chest_add_item(top_inv, bottom_inv, "main", stack)
|
||||
end
|
||||
-- END OF LISTRING WORKAROUND
|
||||
end end
|
||||
|
||||
-- This is a helper function to register regular chests (both small and double variants).
|
||||
-- Some parameters here are only utilized by trapped chests.
|
||||
function mcl_chests.register_chest(basename, d)
|
||||
-- If this passes without crash, we know for a fact that d = {...}
|
||||
assert((d and type(d) == "table"), "Second argument to mcl_chests.register_chest must be a table")
|
||||
|
||||
-- Fallback for when there is no `title` field
|
||||
if not d.title then d.title = {} end
|
||||
d.title.small = d.title.small or d.desc
|
||||
d.title.double = d.title.double or ("Large " .. d.title.small)
|
||||
|
||||
if not d.drop then
|
||||
d.drop = "mcl_chests:" .. basename
|
||||
else
|
||||
d.drop = "mcl_chests:" .. d.drop
|
||||
end
|
||||
|
||||
local drop_items_chest = mcl_util.drop_items_from_meta_container("main")
|
||||
|
||||
if not d.groups then d.groups = {} end
|
||||
|
||||
if not d.on_rightclick_left then
|
||||
d.on_rightclick_left = d.on_rightclick
|
||||
end
|
||||
if not d.on_rightclick_right then
|
||||
d.on_rightclick_right = d.on_rightclick
|
||||
end
|
||||
--[[local on_rightclick_side = {
|
||||
left = d.on_rightclick_left or d.on_rightclick,
|
||||
right = d.on_rightclick_right or d.on_rightclick,
|
||||
}]]
|
||||
|
||||
if not d.sounds or type(d.sounds) ~= "table" then
|
||||
d.sounds = { nil, "default_chest" }
|
||||
end
|
||||
|
||||
if not d.sounds[2] then
|
||||
d.sounds[2] = "default_chest"
|
||||
end
|
||||
|
||||
-- The basename of the "canonical" version of the node, if set (e.g.: trapped_chest_on → trapped_chest).
|
||||
-- Used to get a shared formspec ID and to swap the node back to the canonical version in on_construct.
|
||||
if not d.canonical_basename then
|
||||
d.canonical_basename = basename
|
||||
end
|
||||
|
||||
-- Names table
|
||||
-- -----------
|
||||
-- Accessed through names["kind"].x (names.kind.x), where x can be:
|
||||
-- a = "actual"
|
||||
-- c = canonical
|
||||
-- r = reverse (only for double chests)
|
||||
-- cr = canonical, reverse (only for double chests)
|
||||
local names = {
|
||||
small = {
|
||||
a = "mcl_chests:" .. basename .. "_small",
|
||||
c = "mcl_chests:" .. d.canonical_basename .. "_small",
|
||||
},
|
||||
left = {
|
||||
a = "mcl_chests:" .. basename .. "_left",
|
||||
c = "mcl_chests:" .. d.canonical_basename .. "_left",
|
||||
},
|
||||
right = {
|
||||
a = "mcl_chests:" .. basename .. "_right",
|
||||
c = "mcl_chests:" .. d.canonical_basename .. "_right",
|
||||
},
|
||||
}
|
||||
names.left.r = names.right.a
|
||||
names.right.r = names.left.a
|
||||
names.left.cr = names.right.c
|
||||
names.right.cr = names.left.c
|
||||
|
||||
local small_textures = d.tiles.small
|
||||
local double_textures = d.tiles.double
|
||||
|
||||
-- Construct groups
|
||||
local groups_inv = table_merge({ deco_block = 1 }, d.groups)
|
||||
local groups_small = table_merge(groups_inv, {
|
||||
container = 2,
|
||||
deco_block = 1,
|
||||
chest_entity = 1,
|
||||
not_in_creative_inventory = 1
|
||||
}, d.groups)
|
||||
local groups_left = table_merge(groups_small, {
|
||||
double_chest = 1
|
||||
}, d.groups)
|
||||
local groups_right = table_merge(groups_small, {
|
||||
-- In a double chest, the entity is assigned to the left side, but not the right one.
|
||||
chest_entity = 0,
|
||||
double_chest = 2
|
||||
}, d.groups)
|
||||
|
||||
|
||||
|
||||
-- Dummy inventory node
|
||||
-- Will turn into names.small.a when placed down
|
||||
minetest.register_node("mcl_chests:" .. basename, {
|
||||
description = d.desc,
|
||||
_tt_help = d.tt_help,
|
||||
_doc_items_longdesc = d.longdesc,
|
||||
_doc_items_usagehelp = d.usagehelp,
|
||||
_doc_items_hidden = d.hidden,
|
||||
drawtype = "mesh",
|
||||
mesh = "mcl_chests_chest.b3d",
|
||||
tiles = small_textures,
|
||||
use_texture_alpha = "opaque",
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
sounds = d.sounds[1],
|
||||
groups = groups_inv,
|
||||
on_construct = function(pos, node)
|
||||
local node = minetest.get_node(pos)
|
||||
node.name = names.small.a
|
||||
minetest.set_node(pos, node)
|
||||
end,
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
minetest.get_meta(pos):set_string("name", itemstack:get_meta():get_string("name"))
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_node(names.small.a, {
|
||||
description = d.desc,
|
||||
_tt_help = d.tt_help,
|
||||
_doc_items_longdesc = d.longdesc,
|
||||
_doc_items_usagehelp = d.usagehelp,
|
||||
_doc_items_hidden = d.hidden,
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.4375, -0.5, -0.4375, 0.4375, 0.375, 0.4375 },
|
||||
},
|
||||
tiles = { "blank.png^[resize:16x16" },
|
||||
use_texture_alpha = "clip",
|
||||
_chest_entity_textures = small_textures,
|
||||
_chest_entity_sound = d.sounds[2],
|
||||
_chest_entity_mesh = "mcl_chests_chest",
|
||||
_chest_entity_animation_type = "chest",
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
drop = d.drop,
|
||||
groups = groups_small,
|
||||
is_ground_content = false,
|
||||
sounds = d.sounds[1],
|
||||
on_construct = function(pos)
|
||||
local param2 = minetest.get_node(pos).param2
|
||||
local meta = minetest.get_meta(pos)
|
||||
|
||||
--[[ This is a workaround for Minetest issue 5894
|
||||
<https://github.com/minetest/minetest/issues/5894>.
|
||||
Apparently if we don't do this, large chests initially don't work when
|
||||
placed at chunk borders, and some chests randomly don't work after
|
||||
placing. ]]
|
||||
-- FIXME: Remove this workaround when the bug has been fixed.
|
||||
-- BEGIN OF WORKAROUND --
|
||||
meta:set_string("workaround", "ignore_me")
|
||||
meta:set_string("workaround", "") -- Done to keep metadata clean
|
||||
-- END OF WORKAROUND --
|
||||
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size("main", 9 * 3)
|
||||
|
||||
--[[ The "input" list is *another* workaround (hahahaha!) around the fact that Minetest
|
||||
does not support listrings to put items into an alternative list if the first one
|
||||
happens to be full. See <https://github.com/minetest/minetest/issues/5343>.
|
||||
This list is a hidden input-only list and immediately puts items into the appropriate chest.
|
||||
It is only used for listrings and hoppers. This workaround is not that bad because it only
|
||||
requires a simple “inventory allows” check for large chests.]]
|
||||
-- FIXME: Refactor the listrings as soon Minetest supports alternative listrings
|
||||
-- BEGIN OF LISTRING WORKAROUND
|
||||
inv:set_size("input", 1)
|
||||
-- END OF LISTRING WORKAROUND
|
||||
|
||||
-- Combine into a double chest if neighbouring another small chest
|
||||
if minetest.get_node(get_double_container_neighbor_pos(pos, param2, "right")).name ==
|
||||
names.small.a then
|
||||
minetest.swap_node(pos, { name = names.right.a, param2 = param2 })
|
||||
local p = get_double_container_neighbor_pos(pos, param2, "right")
|
||||
minetest.swap_node(p, { name = names.left.a, param2 = param2 })
|
||||
create_entity(p, names.left.a, double_textures, param2, true, d.sounds[2],
|
||||
"mcl_chests_chest", "chest")
|
||||
elseif minetest.get_node(get_double_container_neighbor_pos(pos, param2, "left")).name ==
|
||||
names.small.a then
|
||||
minetest.swap_node(pos, { name = names.left.a, param2 = param2 })
|
||||
create_entity(pos, names.left.a, double_textures, param2, true, d.sounds[2],
|
||||
"mcl_chests_chest", "chest")
|
||||
local p = get_double_container_neighbor_pos(pos, param2, "left")
|
||||
minetest.swap_node(p, { name = names.right.a, param2 = param2 })
|
||||
else
|
||||
minetest.swap_node(pos, { name = names.small.a, param2 = param2 })
|
||||
create_entity(pos, names.small.a, small_textures, param2, false, d.sounds[2],
|
||||
"mcl_chests_chest", "chest")
|
||||
end
|
||||
end,
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
minetest.get_meta(pos):set_string("name", itemstack:get_meta():get_string("name"))
|
||||
end,
|
||||
after_dig_node = drop_items_chest,
|
||||
on_blast = on_chest_blast,
|
||||
allow_metadata_inventory_move = protection_check_move,
|
||||
allow_metadata_inventory_take = protection_check_take,
|
||||
allow_metadata_inventory_put = protection_check_take,
|
||||
on_metadata_inventory_move = log_inventory_move,
|
||||
on_metadata_inventory_put = log_inventory_put,
|
||||
on_metadata_inventory_take = log_inventory_take,
|
||||
_mcl_blast_resistance = d.hardness,
|
||||
_mcl_hardness = d.hardness,
|
||||
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
local topnode = minetest.get_node({ x = pos.x, y = pos.y + 1, z = pos.z })
|
||||
if topnode and topnode.name and minetest.registered_nodes[topnode.name] then
|
||||
if minetest.registered_nodes[topnode.name].groups.opaque == 1 then
|
||||
-- won't open if there is no space from the top
|
||||
return false
|
||||
end
|
||||
end
|
||||
local name = minetest.get_meta(pos):get_string("name")
|
||||
if name == "" then
|
||||
name = d.title.small
|
||||
end
|
||||
|
||||
minetest.show_formspec(clicker:get_player_name(),
|
||||
sf("mcl_chests:%s_%s_%s_%s", d.canonical_basename, pos.x, pos.y, pos.z),
|
||||
table.concat({
|
||||
"formspec_version[4]",
|
||||
"size[11.75,10.425]",
|
||||
|
||||
"label[0.375,0.375;" .. F(C(mcl_formspec.label_color, name)) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 0.75, 9, 3),
|
||||
sf("list[nodemeta:%s,%s,%s;main;0.375,0.75;9,3;]", pos.x, pos.y, pos.z),
|
||||
"label[0.375,4.7;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
|
||||
"list[current_player;main;0.375,5.1;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
|
||||
"list[current_player;main;0.375,9.05;9,1;]",
|
||||
sf("listring[nodemeta:%s,%s,%s;main]", pos.x, pos.y, pos.z),
|
||||
"listring[current_player;main]",
|
||||
})
|
||||
)
|
||||
|
||||
if d.on_rightclick then
|
||||
d.on_rightclick(pos, node, clicker)
|
||||
end
|
||||
|
||||
player_chest_open(clicker, pos, names.small.a, small_textures, node.param2, false, d.sounds[2],
|
||||
"mcl_chests_chest")
|
||||
end,
|
||||
|
||||
on_destruct = function(pos)
|
||||
close_forms(d.canonical_basename, pos)
|
||||
end,
|
||||
mesecons = d.mesecons,
|
||||
on_rotate = simple_rotate,
|
||||
})
|
||||
|
||||
minetest.register_node(names.left.a, {
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.4375, -0.5, -0.4375, 0.5, 0.375, 0.4375 },
|
||||
},
|
||||
tiles = { "blank.png^[resize:16x16" },
|
||||
use_texture_alpha = "clip",
|
||||
_chest_entity_textures = double_textures,
|
||||
_chest_entity_sound = d.sounds[2],
|
||||
_chest_entity_mesh = "mcl_chests_chest",
|
||||
_chest_entity_animation_type = "chest",
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
groups = groups_left,
|
||||
drop = d.drop,
|
||||
is_ground_content = false,
|
||||
sounds = d.sounds[1],
|
||||
on_construct = construct_double_chest("left", names),
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
minetest.get_meta(pos):set_string("name", itemstack:get_meta():get_string("name"))
|
||||
end,
|
||||
on_destruct = destruct_double_chest("left", names, d.canonical_basename, small_textures, d.sounds[2]),
|
||||
after_dig_node = drop_items_chest,
|
||||
on_blast = on_chest_blast,
|
||||
allow_metadata_inventory_move = protection_check_move,
|
||||
allow_metadata_inventory_take = protection_check_take,
|
||||
allow_metadata_inventory_put = protection_check_put("left"),
|
||||
on_metadata_inventory_move = log_inventory_move,
|
||||
on_metadata_inventory_put = log_inventory_put_double("left"),
|
||||
on_metadata_inventory_take = log_inventory_take,
|
||||
_mcl_blast_resistance = d.hardness,
|
||||
_mcl_hardness = d.hardness,
|
||||
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
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
|
||||
]
|
||||
|
||||
if (not above_def or above_def.groups.opaque == 1 or not above_def_other
|
||||
or above_def_other.groups.opaque == 1) then
|
||||
-- won't open if there is no space from the top
|
||||
return false
|
||||
end
|
||||
|
||||
local name = minetest.get_meta(pos):get_string("name")
|
||||
if name == "" then -- if empty after that ^
|
||||
name = minetest.get_meta(pos_other):get_string("name")
|
||||
end if name == "" then -- if STILL empty after that ^
|
||||
name = d.title.double
|
||||
end
|
||||
|
||||
minetest.show_formspec(clicker:get_player_name(),
|
||||
sf("mcl_chests:%s_%s_%s_%s", d.canonical_basename, pos.x, pos.y, pos.z),
|
||||
table.concat({
|
||||
"formspec_version[4]",
|
||||
"size[11.75,14.15]",
|
||||
|
||||
"label[0.375,0.375;" .. F(C(mcl_formspec.label_color, name)) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 0.75, 9, 3),
|
||||
sf("list[nodemeta:%s,%s,%s;main;0.375,0.75;9,3;]", pos.x, pos.y, pos.z),
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 4.5, 9, 3),
|
||||
sf("list[nodemeta:%s,%s,%s;main;0.375,4.5;9,3;]", pos_other.x, pos_other.y, pos_other.z),
|
||||
"label[0.375,8.45;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 8.825, 9, 3),
|
||||
"list[current_player;main;0.375,8.825;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 12.775, 9, 1),
|
||||
"list[current_player;main;0.375,12.775;9,1;]",
|
||||
|
||||
--BEGIN OF LISTRING WORKAROUND
|
||||
"listring[current_player;main]",
|
||||
sf("listring[nodemeta:%s,%s,%s;input]", pos.x, pos.y, pos.z),
|
||||
--END OF LISTRING WORKAROUND
|
||||
|
||||
"listring[current_player;main]" ..
|
||||
sf("listring[nodemeta:%s,%s,%s;main]", pos.x, pos.y, pos.z),
|
||||
"listring[current_player;main]",
|
||||
sf("listring[nodemeta:%s,%s,%s;main]", pos_other.x, pos_other.y, pos_other.z),
|
||||
})
|
||||
)
|
||||
|
||||
if d.on_rightclick_left then
|
||||
d.on_rightclick_left(pos, node, clicker)
|
||||
end
|
||||
|
||||
player_chest_open(clicker, pos, names.left.a, double_textures, node.param2, true, d.sounds[2],
|
||||
"mcl_chests_chest")
|
||||
end,
|
||||
mesecons = d.mesecons,
|
||||
on_rotate = no_rotate,
|
||||
_mcl_hoppers_on_try_pull = hopper_pull_double("left"),
|
||||
_mcl_hoppers_on_try_push = hopper_push_double("left"),
|
||||
})
|
||||
|
||||
minetest.register_node(names.right.a, {
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.5, -0.4375, 0.4375, 0.375, 0.4375 },
|
||||
},
|
||||
tiles = { "blank.png^[resize:16x16" },
|
||||
use_texture_alpha = "clip",
|
||||
groups = groups_right,
|
||||
drop = d.drop,
|
||||
is_ground_content = false,
|
||||
sounds = d.sounds[1],
|
||||
on_construct = construct_double_chest("right", names),
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
minetest.get_meta(pos):set_string("name", itemstack:get_meta():get_string("name"))
|
||||
end,
|
||||
on_destruct = destruct_double_chest("right", names, d.canonical_basename, small_textures, d.sounds[2]),
|
||||
after_dig_node = drop_items_chest,
|
||||
on_blast = on_chest_blast,
|
||||
allow_metadata_inventory_move = protection_check_move,
|
||||
allow_metadata_inventory_take = protection_check_take,
|
||||
allow_metadata_inventory_put = protection_check_put("right"),
|
||||
on_metadata_inventory_move = log_inventory_move,
|
||||
on_metadata_inventory_put = log_inventory_put_double("right"),
|
||||
on_metadata_inventory_take = log_inventory_take,
|
||||
_mcl_blast_resistance = d.hardness,
|
||||
_mcl_hardness = d.hardness,
|
||||
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
local pos_other = get_double_container_neighbor_pos(pos, node.param2, "right")
|
||||
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
|
||||
]
|
||||
|
||||
if (not above_def or above_def.groups.opaque == 1 or not above_def_other
|
||||
or above_def_other.groups.opaque == 1) then
|
||||
-- won't open if there is no space from the top
|
||||
return false
|
||||
end
|
||||
|
||||
local name = minetest.get_meta(pos):get_string("name")
|
||||
if name == "" then -- if empty after that ^
|
||||
name = minetest.get_meta(pos_other):get_string("name")
|
||||
end if name == "" then -- if STILL empty after that ^
|
||||
name = d.title.double
|
||||
end
|
||||
|
||||
minetest.show_formspec(clicker:get_player_name(),
|
||||
sf("mcl_chests:%s_%s_%s_%s", d.canonical_basename, pos.x, pos.y, pos.z),
|
||||
table.concat({
|
||||
"formspec_version[4]",
|
||||
"size[11.75,14.15]",
|
||||
|
||||
"label[0.375,0.375;" .. F(C(mcl_formspec.label_color, name)) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 0.75, 9, 3),
|
||||
sf("list[nodemeta:%s,%s,%s;main;0.375,0.75;9,3;]", pos_other.x, pos_other.y, pos_other.z),
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 4.5, 9, 3),
|
||||
sf("list[nodemeta:%s,%s,%s;main;0.375,4.5;9,3;]", pos.x, pos.y, pos.z),
|
||||
"label[0.375,8.45;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 8.825, 9, 3),
|
||||
"list[current_player;main;0.375,8.825;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 12.775, 9, 1),
|
||||
"list[current_player;main;0.375,12.775;9,1;]",
|
||||
|
||||
--BEGIN OF LISTRING WORKAROUND
|
||||
"listring[current_player;main]",
|
||||
sf("listring[nodemeta:%s,%s,%s;input]", pos.x, pos.y, pos.z),
|
||||
--END OF LISTRING WORKAROUND
|
||||
|
||||
"listring[current_player;main]" ..
|
||||
sf("listring[nodemeta:%s,%s,%s;main]", pos_other.x, pos_other.y, pos_other.z),
|
||||
"listring[current_player;main]",
|
||||
sf("listring[nodemeta:%s,%s,%s;main]", pos.x, pos.y, pos.z),
|
||||
})
|
||||
)
|
||||
|
||||
if d.on_rightclick_right then
|
||||
d.on_rightclick_right(pos, node, clicker)
|
||||
end
|
||||
|
||||
player_chest_open(clicker, pos_other, names.left.a, double_textures, node.param2, true, d.sounds[2],
|
||||
"mcl_chests_chest")
|
||||
end,
|
||||
mesecons = d.mesecons,
|
||||
on_rotate = no_rotate,
|
||||
_mcl_hoppers_on_try_pull = hopper_pull_double("right"),
|
||||
_mcl_hoppers_on_try_push = hopper_push_double("right"),
|
||||
})
|
||||
|
||||
if doc then
|
||||
doc.add_entry_alias("nodes", names.small.a, "nodes", names.left.a)
|
||||
doc.add_entry_alias("nodes", names.small.a, "nodes", names.right.a)
|
||||
end
|
||||
end
|
||||
|
||||
-- Returns false if itemstack is a shulker box
|
||||
function mcl_chests.is_not_shulker_box(stack)
|
||||
local g = minetest.get_item_group(stack:get_name(), "shulker_box")
|
||||
return g == 0 or g == nil
|
||||
end
|
|
@ -0,0 +1,165 @@
|
|||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
local get_double_container_neighbor_pos = mcl_util.get_double_container_neighbor_pos
|
||||
|
||||
local chestusage = S("To access its inventory, rightclick it. When broken, the items will drop out.")
|
||||
|
||||
mcl_chests.register_chest("chest", {
|
||||
desc = S("Chest"),
|
||||
longdesc = S(
|
||||
"Chests are containers which provide 27 inventory slots. Chests can be turned into large chests with " ..
|
||||
"double the capacity by placing two chests next to each other."
|
||||
),
|
||||
usagehelp = chestusage,
|
||||
tt_help = S("27 inventory slots") .. "\n" .. S("Can be combined to a large chest"),
|
||||
tiles = {
|
||||
small = mcl_chests.tiles.chest_normal_small,
|
||||
double = mcl_chests.tiles.chest_normal_double,
|
||||
inv = { "default_chest_top.png", "mcl_chests_chest_bottom.png",
|
||||
"mcl_chests_chest_right.png", "mcl_chests_chest_left.png",
|
||||
"mcl_chests_chest_back.png", "default_chest_front.png" },
|
||||
},
|
||||
groups = {
|
||||
handy = 1,
|
||||
axey = 1,
|
||||
material_wood = 1,
|
||||
flammable = -1,
|
||||
},
|
||||
sounds = { mcl_sounds.node_sound_wood_defaults() },
|
||||
hardness = 2.5,
|
||||
hidden = false,
|
||||
})
|
||||
|
||||
local traptiles = {
|
||||
small = mcl_chests.tiles.chest_trapped_small,
|
||||
double = mcl_chests.tiles.chest_trapped_double,
|
||||
}
|
||||
|
||||
mcl_chests.register_chest("trapped_chest", {
|
||||
desc = S("Trapped Chest"),
|
||||
title = {
|
||||
small = S("Chest"),
|
||||
double = S("Large Chest")
|
||||
},
|
||||
longdesc = S(
|
||||
"A trapped chest is a container which provides 27 inventory slots. When it is opened, it sends a redstone " ..
|
||||
"signal to its adjacent blocks as long it stays open. Trapped chests can be turned into large trapped " ..
|
||||
"chests with double the capacity by placing two trapped chests next to each other."
|
||||
),
|
||||
usagehelp = chestusage,
|
||||
tt_help = S("27 inventory slots") ..
|
||||
"\n" .. S("Can be combined to a large chest") .. "\n" .. S("Emits a redstone signal when opened"),
|
||||
tiles = traptiles,
|
||||
groups = {
|
||||
handy = 1,
|
||||
axey = 1,
|
||||
material_wood = 1,
|
||||
flammable = -1,
|
||||
mesecon = 2,
|
||||
},
|
||||
sounds = { mcl_sounds.node_sound_wood_defaults() },
|
||||
hardness = 2.5,
|
||||
hidden = false,
|
||||
mesecons = {
|
||||
receptor = {
|
||||
state = mesecon.state.off,
|
||||
rules = mesecon.rules.pplate,
|
||||
},
|
||||
},
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
minetest.swap_node(pos, { name = "mcl_chests:trapped_chest_on_small", param2 = node.param2 })
|
||||
mcl_chests.find_or_create_entity(pos, "mcl_chests:trapped_chest_on_small", { "mcl_chests_trapped.png" },
|
||||
node.param2, false, "default_chest", "mcl_chests_chest", "chest")
|
||||
:reinitialize("mcl_chests:trapped_chest_on_small")
|
||||
mesecon.receptor_on(pos, mesecon.rules.pplate)
|
||||
end,
|
||||
on_rightclick_left = function(pos, node, clicker)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_int("players", 1)
|
||||
|
||||
minetest.swap_node(pos, { name = "mcl_chests:trapped_chest_on_left", param2 = node.param2 })
|
||||
mcl_chests.find_or_create_entity(pos, "mcl_chests:trapped_chest_on_left",
|
||||
mcl_chests.tiles.chest_trapped_double, node.param2, true, "default_chest", "mcl_chests_chest",
|
||||
"chest"):reinitialize("mcl_chests:trapped_chest_on_left")
|
||||
mesecon.receptor_on(pos, mesecon.rules.pplate)
|
||||
|
||||
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, mesecon.rules.pplate)
|
||||
end,
|
||||
on_rightclick_right = function(pos, node, clicker)
|
||||
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, mesecon.rules.pplate)
|
||||
|
||||
minetest.swap_node(pos_other, { name = "mcl_chests:trapped_chest_on_left", param2 = node.param2 })
|
||||
mcl_chests.find_or_create_entity(pos_other, "mcl_chests:trapped_chest_on_left",
|
||||
mcl_chests.tiles.chest_trapped_double, node.param2, true, "default_chest", "mcl_chests_chest",
|
||||
"chest"):reinitialize("mcl_chests:trapped_chest_on_left")
|
||||
mesecon.receptor_on(pos_other, mesecon.rules.pplate)
|
||||
end
|
||||
})
|
||||
|
||||
mcl_chests.register_chest("trapped_chest_on", {
|
||||
title = {
|
||||
small = S("Chest"),
|
||||
double = S("Large Chest")
|
||||
},
|
||||
tiles = traptiles,
|
||||
groups = {
|
||||
handy = 1,
|
||||
axey = 1,
|
||||
material_wood = 1,
|
||||
flammable = -1,
|
||||
mesecon = 2,
|
||||
},
|
||||
sounds = { mcl_sounds.node_sound_wood_defaults() },
|
||||
hardness = 2.5,
|
||||
hidden = true,
|
||||
mesecons = {
|
||||
receptor = {
|
||||
state = mesecon.state.on,
|
||||
rules = mesecon.rules.pplate,
|
||||
},
|
||||
},
|
||||
drop = "trapped_chest",
|
||||
canonical_basename = "trapped_chest"
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_chests:chest",
|
||||
recipe = {
|
||||
{ "group:wood", "group:wood", "group:wood" },
|
||||
{ "group:wood", "", "group:wood" },
|
||||
{ "group:wood", "group:wood", "group:wood" },
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "fuel",
|
||||
recipe = "mcl_chests:chest",
|
||||
burntime = 15,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "fuel",
|
||||
recipe = "mcl_chests:trapped_chest",
|
||||
burntime = 15,
|
||||
})
|
||||
|
||||
-- Disable active/open trapped chests when loaded because nobody could have them open at loading time.
|
||||
-- Fixes redstone weirdness.
|
||||
minetest.register_lbm({
|
||||
label = "Disable active trapped chests",
|
||||
name = "mcl_chests:reset_trapped_chests",
|
||||
nodenames = {
|
||||
"mcl_chests:trapped_chest_on_small",
|
||||
"mcl_chests:trapped_chest_on_left",
|
||||
"mcl_chests:trapped_chest_on_right"
|
||||
},
|
||||
run_at_every_load = true,
|
||||
action = function(pos, node)
|
||||
minetest.log("action", "[mcl_chests] Disabled active trapped chest on load: " .. minetest.pos_to_string(pos))
|
||||
mcl_chests.chest_update_after_close(pos)
|
||||
end,
|
||||
})
|
|
@ -0,0 +1,138 @@
|
|||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
local F = minetest.formspec_escape
|
||||
local C = minetest.colorize
|
||||
|
||||
local longdesc = S(
|
||||
"Ender chests grant you access to a single personal interdimensional inventory with 27 slots. This " ..
|
||||
"inventory is the same no matter from which ender chest you access it from. If you put one item into one " ..
|
||||
"ender chest, you will find it in all other ender chests. Each player will only see their own items, but " ..
|
||||
"not the items of other players."
|
||||
)
|
||||
|
||||
minetest.register_node("mcl_chests:ender_chest", {
|
||||
description = S("Ender Chest"),
|
||||
_tt_help = S("27 interdimensional inventory slots") ..
|
||||
"\n" .. S("Put items inside, retrieve them from any ender chest"),
|
||||
_doc_items_longdesc = longdesc,
|
||||
_doc_items_usagehelp = S("Rightclick the ender chest to access your personal interdimensional inventory."),
|
||||
drawtype = "mesh",
|
||||
mesh = "mcl_chests_chest.b3d",
|
||||
tiles = mcl_chests.tiles.chest_ender_small,
|
||||
use_texture_alpha = "opaque",
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
groups = { deco_block = 1 },
|
||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
on_construct = function(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
node.name = "mcl_chests:ender_chest_small"
|
||||
minetest.set_node(pos, node)
|
||||
end,
|
||||
})
|
||||
|
||||
local formspec_ender_chest = table.concat({
|
||||
"formspec_version[4]",
|
||||
"size[11.75,10.425]",
|
||||
|
||||
"label[0.375,0.375;" .. F(C(mcl_formspec.label_color, S("Ender Chest"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 0.75, 9, 3),
|
||||
"list[current_player;enderchest;0.375,0.75;9,3;]",
|
||||
"label[0.375,4.7;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
|
||||
"list[current_player;main;0.375,5.1;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
|
||||
"list[current_player;main;0.375,9.05;9,1;]",
|
||||
|
||||
"listring[current_player;enderchest]",
|
||||
"listring[current_player;main]",
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_chests:ender_chest_small", {
|
||||
description = S("Ender Chest"),
|
||||
_tt_help = S("27 interdimensional inventory slots") ..
|
||||
"\n" .. S("Put items inside, retrieve them from any ender chest"),
|
||||
_doc_items_longdesc = longdesc,
|
||||
_doc_items_usagehelp = S("Rightclick the ender chest to access your personal interdimensional inventory."),
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.4375, -0.5, -0.4375, 0.4375, 0.375, 0.4375 },
|
||||
},
|
||||
_chest_entity_textures = mcl_chests.tiles.ender_chest_texture,
|
||||
_chest_entity_sound = "mcl_chests_enderchest",
|
||||
_chest_entity_mesh = "mcl_chests_chest",
|
||||
_chest_entity_animation_type = "chest",
|
||||
tiles = { "blank.png^[resize:16x16" },
|
||||
use_texture_alpha = "clip",
|
||||
-- Note: The “container” group is missing here because the ender chest does not
|
||||
-- have an inventory on its own
|
||||
groups = { pickaxey = 1, deco_block = 1, material_stone = 1, chest_entity = 1, not_in_creative_inventory = 1 },
|
||||
is_ground_content = false,
|
||||
paramtype = "light",
|
||||
light_source = 7,
|
||||
paramtype2 = "facedir",
|
||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
drop = "mcl_core:obsidian 8",
|
||||
on_construct = function(pos)
|
||||
mcl_chests.create_entity(pos, "mcl_chests:ender_chest_small", mcl_chests.tiles.ender_chest_texture,
|
||||
minetest.get_node(pos).param2, false, "mcl_chests_enderchest", "mcl_chests_chest", "chest")
|
||||
end,
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
if minetest.registered_nodes[minetest.get_node(vector.offset(pos, 0, 1, 0)).name].groups.opaque == 1 then
|
||||
-- won't open if there is no space from the top
|
||||
return false
|
||||
end
|
||||
minetest.show_formspec(clicker:get_player_name(), "mcl_chests:ender_chest_" .. clicker:get_player_name(),
|
||||
formspec_ender_chest)
|
||||
mcl_chests.player_chest_open(clicker, pos, "mcl_chests:ender_chest_small",
|
||||
mcl_chests.tiles.ender_chest_texture, node.param2, false, "mcl_chests_enderchest",
|
||||
"mcl_chests_chest")
|
||||
end,
|
||||
on_receive_fields = function(pos, formname, fields, sender)
|
||||
if fields.quit then
|
||||
mcl_chests.player_chest_close(sender)
|
||||
end
|
||||
end,
|
||||
_mcl_blast_resistance = 600,
|
||||
_mcl_hardness = 22.5,
|
||||
_mcl_silk_touch_drop = { "mcl_chests:ender_chest" },
|
||||
on_rotate = mcl_chests.simple_rotate,
|
||||
})
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
local inv = player:get_inventory()
|
||||
inv:set_size("enderchest", 9 * 3)
|
||||
end)
|
||||
|
||||
minetest.register_allow_player_inventory_action(function(player, action, inv, info)
|
||||
if inv:get_location().type == "player" and (
|
||||
action == "move" and (info.from_list == "enderchest" or info.to_list == "enderchest")
|
||||
or action == "put" and info.listname == "enderchest"
|
||||
or action == "take" and info.listname == "enderchest") then
|
||||
local def = player:get_wielded_item():get_definition()
|
||||
local range = (def and def.range or player:get_inventory():get_stack("hand", 1):get_definition().range) + 1
|
||||
if not minetest.find_node_near(player:get_pos(), range, "mcl_chests:ender_chest_small", true) then
|
||||
return 0
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_chests:ender_chest",
|
||||
recipe = {
|
||||
{ "mcl_core:obsidian", "mcl_core:obsidian", "mcl_core:obsidian" },
|
||||
{ "mcl_core:obsidian", "mcl_end:ender_eye", "mcl_core:obsidian" },
|
||||
{ "mcl_core:obsidian", "mcl_core:obsidian", "mcl_core:obsidian" },
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_lbm({
|
||||
label = "Upgrade old ender chest formspec",
|
||||
name = "mcl_chests:replace_old_ender_form",
|
||||
nodenames = { "mcl_chests:ender_chest_small" },
|
||||
run_at_every_load = false,
|
||||
action = function(pos, node)
|
||||
minetest.get_meta(pos):set_string("formspec", "")
|
||||
end,
|
||||
})
|
|
@ -0,0 +1,50 @@
|
|||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
mcl_chests.register_chest("stone_chest", {
|
||||
desc = S("Stone Chest"),
|
||||
title = {
|
||||
small = S("Stone Chest"),
|
||||
double = S("Large Stone Chest")
|
||||
},
|
||||
longdesc = S(
|
||||
"Stone Chests are containers which provide 27 inventory slots. Stone Chests can be turned into" ..
|
||||
"large stone chests with double the capacity by placing two stone chests next to each other."
|
||||
),
|
||||
usagehelp = S("To access its inventory, rightclick it. When broken, the items will drop out."),
|
||||
tt_help = S("27 inventory slots") .. "\n" .. S("Can be combined to a large stone chest"),
|
||||
tiles = {
|
||||
small = { mcl_chests.tiles.chest_normal_small[1] .. "^[hsl:-15:-80:-20" },
|
||||
double = { mcl_chests.tiles.chest_normal_double[1] .. "^[hsl:-15:-80:-20" },
|
||||
inv = { "default_chest_top.png^[hsl:-15:-80:-20",
|
||||
"mcl_chests_chest_bottom.png^[hsl:-15:-80:-20",
|
||||
"mcl_chests_chest_right.png^[hsl:-15:-80:-20",
|
||||
"mcl_chests_chest_left.png^[hsl:-15:-80:-20",
|
||||
"mcl_chests_chest_back.png^[hsl:-15:-80:-20",
|
||||
"default_chest_front.png^[hsl:-15:-80:-20"
|
||||
},
|
||||
},
|
||||
groups = {
|
||||
pickaxey = 1,
|
||||
stone = 1,
|
||||
material_stone = 1,
|
||||
},
|
||||
sounds = {
|
||||
mcl_sounds.node_sound_stone_defaults(),
|
||||
"mcl_chests_enderchest"
|
||||
},
|
||||
hardness = 4.0,
|
||||
hidden = false,
|
||||
-- It bites!
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
mcl_util.deal_damage(clicker, 2)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_chests:stone_chest",
|
||||
recipe = {
|
||||
{ "mcl_core:stone", "mcl_core:stone", "mcl_core:stone" },
|
||||
{ "mcl_core:stone", "", "mcl_core:stone" },
|
||||
{ "mcl_core:stone", "mcl_core:stone", "mcl_core:stone" },
|
||||
},
|
||||
})
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,358 @@
|
|||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
local F = minetest.formspec_escape
|
||||
local C = minetest.colorize
|
||||
|
||||
-- Shulker boxes
|
||||
local boxtypes = {
|
||||
white = S("White Shulker Box"),
|
||||
grey = S("Light Grey Shulker Box"),
|
||||
orange = S("Orange Shulker Box"),
|
||||
cyan = S("Cyan Shulker Box"),
|
||||
magenta = S("Magenta Shulker Box"),
|
||||
violet = S("Purple Shulker Box"),
|
||||
lightblue = S("Light Blue Shulker Box"),
|
||||
blue = S("Blue Shulker Box"),
|
||||
yellow = S("Yellow Shulker Box"),
|
||||
brown = S("Brown Shulker Box"),
|
||||
green = S("Lime Shulker Box"),
|
||||
dark_green = S("Green Shulker Box"),
|
||||
pink = S("Pink Shulker Box"),
|
||||
red = S("Red Shulker Box"),
|
||||
dark_grey = S("Grey Shulker Box"),
|
||||
black = S("Black Shulker Box"),
|
||||
}
|
||||
|
||||
local shulker_mob_textures = {
|
||||
white = "mobs_mc_shulker_white.png",
|
||||
grey = "mobs_mc_shulker_silver.png",
|
||||
orange = "mobs_mc_shulker_orange.png",
|
||||
cyan = "mobs_mc_shulker_cyan.png",
|
||||
magenta = "mobs_mc_shulker_magenta.png",
|
||||
violet = "mobs_mc_shulker_purple.png",
|
||||
lightblue = "mobs_mc_shulker_light_blue.png",
|
||||
blue = "mobs_mc_shulker_blue.png",
|
||||
yellow = "mobs_mc_shulker_yellow.png",
|
||||
brown = "mobs_mc_shulker_brown.png",
|
||||
green = "mobs_mc_shulker_lime.png",
|
||||
dark_green = "mobs_mc_shulker_green.png",
|
||||
pink = "mobs_mc_shulker_pink.png",
|
||||
red = "mobs_mc_shulker_red.png",
|
||||
dark_grey = "mobs_mc_shulker_gray.png",
|
||||
black = "mobs_mc_shulker_black.png",
|
||||
}
|
||||
|
||||
local canonical_shulker_color = "violet"
|
||||
local normal_canonical_name = "mcl_chests:" .. canonical_shulker_color .. "_shulker_box"
|
||||
local small_canonical_name = normal_canonical_name .. "_small"
|
||||
|
||||
--WARNING: after formspec v4 update, old shulker boxes will need to be placed again to get the new formspec
|
||||
local function formspec_shulker_box(name)
|
||||
if not name or name == "" then
|
||||
name = S("Shulker Box")
|
||||
end
|
||||
|
||||
return table.concat({
|
||||
"formspec_version[4]",
|
||||
"size[11.75,10.425]",
|
||||
|
||||
"label[0.375,0.375;" .. F(C(mcl_formspec.label_color, name)) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 0.75, 9, 3),
|
||||
"list[context;main;0.375,0.75;9,3;]",
|
||||
"label[0.375,4.7;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]",
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
|
||||
"list[current_player;main;0.375,5.1;9,3;9]",
|
||||
|
||||
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
|
||||
"list[current_player;main;0.375,9.05;9,1;]",
|
||||
|
||||
"listring[context;main]",
|
||||
"listring[current_player;main]",
|
||||
})
|
||||
end
|
||||
|
||||
local function set_shulkerbox_meta(nmeta, imeta)
|
||||
local name = imeta:get_string("name")
|
||||
nmeta:set_string("description", imeta:get_string("description"))
|
||||
nmeta:set_string("name", name)
|
||||
nmeta:set_string("formspec", formspec_shulker_box(name))
|
||||
end
|
||||
|
||||
for color, desc in pairs(boxtypes) do
|
||||
local mob_texture = shulker_mob_textures[color]
|
||||
local is_canonical = color == canonical_shulker_color
|
||||
local longdesc, usagehelp, create_entry, entry_name
|
||||
if doc then
|
||||
if is_canonical then
|
||||
longdesc = S(
|
||||
"A shulker box is a portable container which provides 27 inventory slots for any item " ..
|
||||
"except shulker boxes. Shulker boxes keep their inventory when broken, so shulker boxes " ..
|
||||
"as well as their contents can be taken as a single item. Shulker boxes come in many " ..
|
||||
"different colors."
|
||||
)
|
||||
usagehelp = S(
|
||||
"To access the inventory of a shulker box, place and right-click it. To take a shulker " ..
|
||||
"box and its contents with you, just break and collect it, the items will not fall out. " ..
|
||||
"Place the shulker box again to be able to retrieve its contents."
|
||||
)
|
||||
entry_name = S("Shulker Box")
|
||||
else
|
||||
create_entry = false
|
||||
end
|
||||
end
|
||||
|
||||
local normal_name = "mcl_chests:" .. color .. "_shulker_box"
|
||||
local small_name = normal_name .. "_small"
|
||||
|
||||
minetest.register_node(normal_name, {
|
||||
description = desc,
|
||||
_tt_help = S("27 inventory slots") .. "\n" .. S("Can be carried around with its contents"),
|
||||
_doc_items_create_entry = create_entry,
|
||||
_doc_items_entry_name = entry_name,
|
||||
_doc_items_longdesc = longdesc,
|
||||
_doc_items_usagehelp = usagehelp,
|
||||
tiles = { mob_texture },
|
||||
use_texture_alpha = "opaque",
|
||||
drawtype = "mesh",
|
||||
mesh = "mcl_chests_shulker.b3d",
|
||||
groups = {
|
||||
handy = 1,
|
||||
pickaxey = 1,
|
||||
container = 2,
|
||||
deco_block = 1,
|
||||
dig_by_piston = 1,
|
||||
shulker_box = 1,
|
||||
old_shulker_box_node = 1
|
||||
},
|
||||
is_ground_content = false,
|
||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
stack_max = 1,
|
||||
drop = "",
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
on_construct = function(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
node.name = small_name
|
||||
minetest.set_node(pos, node)
|
||||
end,
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
local nmeta = minetest.get_meta(pos)
|
||||
local imeta = itemstack:get_meta()
|
||||
|
||||
-- Convert old itemstacks to not use get_metadata()
|
||||
if not imeta:contains("inv") and
|
||||
(itemstack:get_metadata() ~= "") then
|
||||
imeta:set_string("inv", itemstack:get_metadata())
|
||||
itemstack:set_metadata("") -- clear
|
||||
end
|
||||
|
||||
local iinv_main = minetest.deserialize(imeta:get_string("inv"))
|
||||
local ninv = nmeta:get_inventory()
|
||||
ninv:set_list("main", iinv_main)
|
||||
ninv:set_size("main", 9 * 3)
|
||||
set_shulkerbox_meta(nmeta, imeta)
|
||||
|
||||
if minetest.is_creative_enabled(placer:get_player_name()) then
|
||||
if not ninv:is_empty("main") then
|
||||
return nil
|
||||
else
|
||||
return itemstack
|
||||
end
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end,
|
||||
_on_dispense = function(stack, pos, droppos, dropnode, dropdir)
|
||||
-- Place shulker box as node
|
||||
if minetest.registered_nodes[dropnode.name].buildable_to then
|
||||
minetest.set_node(droppos, { name = small_name, param2 = minetest.dir_to_facedir(dropdir) })
|
||||
local ninv = minetest.get_inventory({ type = "node", pos = droppos })
|
||||
local imeta = stack:get_meta()
|
||||
local iinv_main = minetest.deserialize(imeta:get_string("inv"))
|
||||
ninv:set_list("main", iinv_main)
|
||||
ninv:set_size("main", 9 * 3)
|
||||
set_shulkerbox_meta(minetest.get_meta(droppos), imeta)
|
||||
stack:take_item()
|
||||
end
|
||||
return stack
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_node(small_name, {
|
||||
description = desc,
|
||||
_tt_help = S("27 inventory slots") .. "\n" .. S("Can be carried around with its contents"),
|
||||
_doc_items_create_entry = create_entry,
|
||||
_doc_items_entry_name = entry_name,
|
||||
_doc_items_longdesc = longdesc,
|
||||
_doc_items_usagehelp = usagehelp,
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.48, -0.5, -0.48, 0.48, 0.489, 0.48 },
|
||||
},
|
||||
tiles = { "blank.png^[resize:16x16" },
|
||||
use_texture_alpha = "clip",
|
||||
_chest_entity_textures = { mob_texture },
|
||||
_chest_entity_sound = "mcl_chests_shulker",
|
||||
_chest_entity_mesh = "mcl_chests_shulker",
|
||||
_chest_entity_animation_type = "shulker",
|
||||
groups = {
|
||||
handy = 1,
|
||||
pickaxey = 1,
|
||||
container = 2,
|
||||
deco_block = 1,
|
||||
dig_by_piston = 1,
|
||||
shulker_box = 1,
|
||||
chest_entity = 1,
|
||||
not_in_creative_inventory = 1
|
||||
},
|
||||
is_ground_content = false,
|
||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
stack_max = 1,
|
||||
drop = "",
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("formspec", formspec_shulker_box(nil))
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size("main", 9 * 3)
|
||||
mcl_chests.create_entity(pos, small_name, { mob_texture }, minetest.get_node(pos).param2, false,
|
||||
"mcl_chests_shulker", "mcl_chests_shulker", "shulker")
|
||||
end,
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
local nmeta = minetest.get_meta(pos)
|
||||
local imeta = itemstack:get_meta()
|
||||
|
||||
-- Convert old itemstacks to not use get_metadata()
|
||||
if not imeta:contains("inv") and
|
||||
(itemstack:get_metadata() ~= "") then
|
||||
imeta:set_string("inv", itemstack:get_metadata())
|
||||
itemstack:set_metadata("") -- clear
|
||||
end
|
||||
|
||||
local iinv_main = minetest.deserialize(imeta:get_string("inv"))
|
||||
local ninv = nmeta:get_inventory()
|
||||
ninv:set_list("main", iinv_main)
|
||||
ninv:set_size("main", 9 * 3)
|
||||
set_shulkerbox_meta(nmeta, imeta)
|
||||
|
||||
if minetest.is_creative_enabled(placer:get_player_name()) then
|
||||
if not ninv:is_empty("main") then
|
||||
return nil
|
||||
else
|
||||
return itemstack
|
||||
end
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end,
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
mcl_chests.player_chest_open(clicker, pos, small_name, { mob_texture }, node.param2, false,
|
||||
"mcl_chests_shulker", "mcl_chests_shulker", true)
|
||||
end,
|
||||
on_receive_fields = function(pos, formname, fields, sender)
|
||||
if fields.quit then
|
||||
mcl_chests.player_chest_close(sender)
|
||||
end
|
||||
end,
|
||||
on_destruct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local items = {}
|
||||
for i = 1, inv:get_size("main") do
|
||||
local stack = inv:get_stack("main", i)
|
||||
items[i] = stack:to_string()
|
||||
end
|
||||
local data = minetest.serialize(items)
|
||||
local boxitem = ItemStack("mcl_chests:" .. color .. "_shulker_box")
|
||||
local boxitem_meta = boxitem:get_meta()
|
||||
boxitem_meta:set_string("description", meta:get_string("description"))
|
||||
boxitem_meta:set_string("name", meta:get_string("name"))
|
||||
boxitem_meta:set_string("inv", data)
|
||||
|
||||
if minetest.is_creative_enabled("") then
|
||||
if not inv:is_empty("main") then
|
||||
minetest.add_item(pos, boxitem)
|
||||
end
|
||||
else
|
||||
minetest.add_item(pos, boxitem)
|
||||
end
|
||||
end,
|
||||
allow_metadata_inventory_move = mcl_chests.protection_check_move,
|
||||
allow_metadata_inventory_take = mcl_chests.protection_check_put_take,
|
||||
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
local name = player:get_player_name()
|
||||
if minetest.is_protected(pos, name) then
|
||||
minetest.record_protection_violation(pos, name)
|
||||
return 0
|
||||
end
|
||||
-- Do not allow to place shulker boxes into shulker boxes
|
||||
local group = minetest.get_item_group(stack:get_name(), "shulker_box")
|
||||
if group == 0 or group == nil then
|
||||
return stack:get_count()
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end,
|
||||
on_rotate = mcl_chests.simple_rotate,
|
||||
_mcl_blast_resistance = 2,
|
||||
_mcl_hardness = 2,
|
||||
_mcl_hoppers_on_try_push = function(pos, hop_pos, hop_inv, hop_list)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return inv, "main",
|
||||
mcl_util.select_stack(hop_inv, hop_list, inv, "main", mcl_chests.is_not_shulker_box, 1)
|
||||
end,
|
||||
})
|
||||
|
||||
if doc and not is_canonical then
|
||||
doc.add_entry_alias("nodes", normal_canonical_name, "nodes", normal_name)
|
||||
doc.add_entry_alias("nodes", small_canonical_name, "nodes", small_name)
|
||||
end
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = normal_name,
|
||||
recipe = { "group:shulker_box", "mcl_dye:" .. color },
|
||||
})
|
||||
end
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_chests:violet_shulker_box",
|
||||
recipe = {
|
||||
{ "mcl_mobitems:shulker_shell" },
|
||||
{ "mcl_chests:chest" },
|
||||
{ "mcl_mobitems:shulker_shell" },
|
||||
},
|
||||
})
|
||||
|
||||
-- Save metadata of shulker box when used in crafting
|
||||
minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv)
|
||||
if minetest.get_item_group(itemstack:get_name(), "shulker_box") ~= 1 then return end
|
||||
|
||||
local original
|
||||
for i = 1, #old_craft_grid do
|
||||
local item = old_craft_grid[i]:get_name()
|
||||
if minetest.get_item_group(item, "shulker_box") == 1 then
|
||||
original = old_craft_grid[i]
|
||||
break
|
||||
end
|
||||
end
|
||||
if original then
|
||||
local ometa = original:get_meta():to_table()
|
||||
local nmeta = itemstack:get_meta()
|
||||
nmeta:from_table(ometa)
|
||||
return itemstack
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_lbm({
|
||||
label = "Update shulker box formspecs (0.72.0)",
|
||||
name = "mcl_chests:update_shulker_box_formspecs_0_72_0",
|
||||
nodenames = { "group:shulker_box" },
|
||||
run_at_every_load = false,
|
||||
action = function(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("formspec", formspec_shulker_box(meta:get_string("name")))
|
||||
end,
|
||||
})
|
|
@ -162,7 +162,7 @@ for _, row in ipairs(block.dyes) do
|
|||
stack_max = 64,
|
||||
is_ground_content = false,
|
||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
_mcl_blast_resistance = 4.2,
|
||||
_mcl_blast_resistance = 1.4,
|
||||
_mcl_hardness = 1.4,
|
||||
on_rotate = on_rotate,
|
||||
})
|
||||
|
|
|
@ -312,8 +312,8 @@ minetest.register_node("mcl_compass:lodestone",{
|
|||
"lodestone_side4.png"
|
||||
},
|
||||
groups = {pickaxey=1, material_stone=1},
|
||||
_mcl_hardness = 1.5,
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 3.5,
|
||||
_mcl_blast_resistance = 3.5,
|
||||
sounds = mcl_sounds.node_sound_stone_defaults()
|
||||
})
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ minetest.register_node("mcl_copper:block_exposed", {
|
|||
groups = {pickaxey = 2, building_block = 1, oxidizable = 1},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 5,
|
||||
_mcl_hardness = 3,
|
||||
_mcl_oxidized_variant = "mcl_copper:block_weathered",
|
||||
_mcl_waxed_variant = "mcl_copper:waxed_block_exposed",
|
||||
_mcl_stripped_variant = "mcl_copper:block",
|
||||
|
@ -72,7 +72,7 @@ minetest.register_node("mcl_copper:waxed_block_exposed", {
|
|||
groups = {pickaxey = 2, building_block = 1, waxed = 1},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 5,
|
||||
_mcl_hardness = 3,
|
||||
_mcl_stripped_variant = "mcl_copper:block_exposed",
|
||||
})
|
||||
|
||||
|
@ -84,7 +84,7 @@ minetest.register_node("mcl_copper:block_weathered", {
|
|||
groups = {pickaxey = 2, building_block = 1, oxidizable = 1},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 5,
|
||||
_mcl_hardness = 3,
|
||||
_mcl_oxidized_variant = "mcl_copper:block_oxidized",
|
||||
_mcl_waxed_variant = "mcl_copper:waxed_block_weathered",
|
||||
_mcl_stripped_variant = "mcl_copper:block_exposed",
|
||||
|
@ -98,7 +98,7 @@ minetest.register_node("mcl_copper:waxed_block_weathered", {
|
|||
groups = {pickaxey = 2, building_block = 1, waxed = 1},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 5,
|
||||
_mcl_hardness = 3,
|
||||
_mcl_stripped_variant = "mcl_copper:block_weathered",
|
||||
})
|
||||
|
||||
|
@ -110,7 +110,7 @@ minetest.register_node("mcl_copper:block_oxidized", {
|
|||
groups = {pickaxey = 2, building_block = 1},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 5,
|
||||
_mcl_hardness = 3,
|
||||
_mcl_waxed_variant = "mcl_copper:waxed_block_oxidized",
|
||||
_mcl_stripped_variant = "mcl_copper:block_weathered",
|
||||
})
|
||||
|
@ -123,7 +123,7 @@ minetest.register_node("mcl_copper:waxed_block_oxidized", {
|
|||
groups = {pickaxey = 2, building_block = 1, waxed = 1},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 5,
|
||||
_mcl_hardness = 3,
|
||||
_mcl_stripped_variant = "mcl_copper:block_oxidized",
|
||||
})
|
||||
|
||||
|
@ -135,7 +135,7 @@ minetest.register_node("mcl_copper:block_cut", {
|
|||
groups = {pickaxey = 2, building_block = 1, oxidizable = 1},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 5,
|
||||
_mcl_hardness = 3,
|
||||
_mcl_oxidized_variant = "mcl_copper:block_exposed_cut",
|
||||
_mcl_waxed_variant = "mcl_copper:waxed_block_cut",
|
||||
})
|
||||
|
@ -148,7 +148,7 @@ minetest.register_node("mcl_copper:waxed_block_cut", {
|
|||
groups = {pickaxey = 2, building_block = 1, waxed = 1},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 5,
|
||||
_mcl_hardness = 3,
|
||||
_mcl_stripped_variant = "mcl_copper:block_cut",
|
||||
})
|
||||
|
||||
|
@ -160,7 +160,7 @@ minetest.register_node("mcl_copper:block_exposed_cut", {
|
|||
groups = {pickaxey = 2, building_block = 1, oxidizable = 1},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 5,
|
||||
_mcl_hardness = 3,
|
||||
_mcl_waxed_variant = "mcl_copper:waxed_block_exposed_cut",
|
||||
_mcl_oxidized_variant = "mcl_copper:block_weathered_cut",
|
||||
_mcl_stripped_variant = "mcl_copper:block_cut",
|
||||
|
@ -174,7 +174,7 @@ minetest.register_node("mcl_copper:waxed_block_exposed_cut", {
|
|||
groups = {pickaxey = 2, building_block = 1, waxed = 1},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 5,
|
||||
_mcl_hardness = 3,
|
||||
_mcl_stripped_variant = "mcl_copper:block_exposed_cut",
|
||||
})
|
||||
|
||||
|
@ -186,7 +186,7 @@ minetest.register_node("mcl_copper:block_weathered_cut", {
|
|||
groups = {pickaxey = 2, building_block = 1, oxidizable = 1},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 5,
|
||||
_mcl_hardness = 3,
|
||||
_mcl_stripped_variant = "mcl_copper:block_exposed_cut",
|
||||
_mcl_oxidized_variant = "mcl_copper:block_oxidized_cut",
|
||||
_mcl_waxed_variant = "mcl_copper:waxed_block_weathered_cut",
|
||||
|
@ -200,7 +200,7 @@ minetest.register_node("mcl_copper:waxed_block_weathered_cut", {
|
|||
groups = {pickaxey = 2, building_block = 1, waxed = 1},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 5,
|
||||
_mcl_hardness = 3,
|
||||
_mcl_stripped_variant = "mcl_copper:block_weathered_cut",
|
||||
})
|
||||
|
||||
|
@ -212,7 +212,7 @@ minetest.register_node("mcl_copper:block_oxidized_cut", {
|
|||
groups = {pickaxey = 2, building_block = 1},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 5,
|
||||
_mcl_hardness = 3,
|
||||
_mcl_stripped_variant = "mcl_copper:block_weathered_cut",
|
||||
_mcl_waxed_variant = "mcl_copper:waxed_block_oxidized_cut",
|
||||
})
|
||||
|
@ -225,7 +225,7 @@ minetest.register_node("mcl_copper:waxed_block_oxidized_cut", {
|
|||
groups = {pickaxey = 2, building_block = 1, waxed = 1},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 5,
|
||||
_mcl_hardness = 3,
|
||||
_mcl_stripped_variant = "mcl_copper:block_oxidized_cut",
|
||||
})
|
||||
|
||||
|
@ -289,54 +289,54 @@ mcl_stairs.register_stair("copper_cut", "mcl_copper:block_cut",
|
|||
{pickaxey = 2, oxidizable = 1},
|
||||
{"mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png"},
|
||||
S("Stairs of Cut Copper"),
|
||||
nil, 6, nil,
|
||||
nil, nil, nil,
|
||||
"woodlike")
|
||||
|
||||
mcl_stairs.register_stair("waxed_copper_cut", "mcl_copper:waxed_block_cut",
|
||||
{pickaxey = 2, waxed = 1},
|
||||
{"mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png", "mcl_copper_block_cut.png"},
|
||||
S("Waxed Stairs of Cut Copper"),
|
||||
nil, 6, nil,
|
||||
nil, nil, nil,
|
||||
"woodlike")
|
||||
|
||||
mcl_stairs.register_stair("copper_exposed_cut", "mcl_copper:block_exposed_cut",
|
||||
{pickaxey = 2, oxidizable = 1},
|
||||
{"mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png"},
|
||||
S("Stairs of Exposed Cut Copper"),
|
||||
nil, 6, nil,
|
||||
nil, nil, nil,
|
||||
"woodlike")
|
||||
|
||||
mcl_stairs.register_stair("waxed_copper_exposed_cut", "mcl_copper:waxed_block_exposed_cut",
|
||||
{pickaxey = 2, waxed = 1},
|
||||
{"mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png", "mcl_copper_exposed_cut.png"},
|
||||
S("Waxed Stairs of Exposed Cut Copper"),
|
||||
nil, 6, nil,
|
||||
nil, nil, nil,
|
||||
"woodlike")
|
||||
|
||||
mcl_stairs.register_stair("copper_weathered_cut", "mcl_copper:block_weathered_cut",
|
||||
{pickaxey = 2, oxidizable = 1},
|
||||
{"mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png"},
|
||||
S("Stairs of Weathered Cut Copper"),
|
||||
nil, 6, nil,
|
||||
nil, nil, nil,
|
||||
"woodlike")
|
||||
|
||||
mcl_stairs.register_stair("waxed_copper_weathered_cut", "mcl_copper:waxed_block_weathered_cut",
|
||||
{pickaxey = 2, waxed = 1},
|
||||
{"mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png", "mcl_copper_weathered_cut.png"},
|
||||
S("Waxed Stairs of Weathered Cut Copper"),
|
||||
nil, 6, nil,
|
||||
nil, nil, nil,
|
||||
"woodlike")
|
||||
|
||||
mcl_stairs.register_stair("copper_oxidized_cut", "mcl_copper:block_oxidized_cut",
|
||||
{pickaxey = 2},
|
||||
{"mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png"},
|
||||
S("Stairs of Oxidized Cut Copper"),
|
||||
nil, 6, nil,
|
||||
nil, nil, nil,
|
||||
"woodlike")
|
||||
|
||||
mcl_stairs.register_stair("waxed_copper_oxidized_cut", "mcl_copper:waxed_block_oxidized_cut",
|
||||
{pickaxey = 2, waxed = 1},
|
||||
{"mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png", "mcl_copper_oxidized_cut.png"},
|
||||
S("Waxed Stairs of Oxidized Cut Copper"),
|
||||
nil, 6, nil,
|
||||
nil, nil, nil,
|
||||
"woodlike")
|
||||
|
|
|
@ -165,6 +165,22 @@ minetest.register_craft({
|
|||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_core:charcoalblock",
|
||||
recipe = {
|
||||
{"mcl_core:charcoal_lump", "mcl_core:charcoal_lump", "mcl_core:charcoal_lump"},
|
||||
{"mcl_core:charcoal_lump", "mcl_core:charcoal_lump", "mcl_core:charcoal_lump"},
|
||||
{"mcl_core:charcoal_lump", "mcl_core:charcoal_lump", "mcl_core:charcoal_lump"},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_core:charcoal_lump 9",
|
||||
recipe = {
|
||||
{"mcl_core:charcoalblock"},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_core:ironblock",
|
||||
recipe = {
|
||||
|
@ -497,6 +513,12 @@ minetest.register_craft({
|
|||
burntime = 800,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "fuel",
|
||||
recipe = "mcl_core:charcoalblock",
|
||||
burntime = 800,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "fuel",
|
||||
recipe = "mcl_core:coal_lump",
|
||||
|
|
|
@ -1451,6 +1451,22 @@ minetest.register_abm({
|
|||
end
|
||||
})
|
||||
|
||||
-- Freeze water
|
||||
minetest.register_abm({
|
||||
label = "Freeze water in cold areas",
|
||||
nodenames = {"mcl_core:water_source", "mclx_core:river_water_source"},
|
||||
interval = 32,
|
||||
chance = 8,
|
||||
action = function(pos, node)
|
||||
if mcl_weather.has_snow(pos)
|
||||
and minetest.get_natural_light(vector.offset(pos,0,1,0), 0.5) == minetest.LIGHT_MAX + 1
|
||||
and minetest.get_artificial_light(minetest.get_node(pos).param1) < 10 then
|
||||
node.name = "mcl_core:ice"
|
||||
minetest.swap_node(pos, node)
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
--[[ Call this for vines nodes only.
|
||||
Given the pos and node of a vines node, this returns true if the vines are supported
|
||||
and false if the vines are currently floating.
|
||||
|
@ -1642,32 +1658,30 @@ end
|
|||
|
||||
|
||||
-- Obsidian crying
|
||||
|
||||
local crobby_particle = {
|
||||
velocity = vector.new(0,0,0),
|
||||
size = math.random(1.3,2.5),
|
||||
velocity = vector.zero(),
|
||||
acceleration = vector.zero(),
|
||||
texture = "mcl_core_crying_obsidian_tear.png",
|
||||
collisiondetection = false,
|
||||
collision_removal = false,
|
||||
}
|
||||
|
||||
|
||||
minetest.register_abm({
|
||||
label = "Obsidian cries",
|
||||
nodenames = {"mcl_core:crying_obsidian"},
|
||||
interval = 5,
|
||||
chance = 10,
|
||||
action = function(pos, node)
|
||||
minetest.after(math.random(0.1,1.5),function()
|
||||
minetest.after(0.1 + math.random() * 1.4, function()
|
||||
local pt = table.copy(crobby_particle)
|
||||
pt.acceleration = vector.new(0,0,0)
|
||||
pt.collisiondetection = false
|
||||
pt.expirationtime = math.random(0.5,1.5)
|
||||
pt.pos = vector.offset(pos,math.random(-0.5,0.5),-0.51,math.random(-0.5,0.5))
|
||||
pt.size = 1.3 + math.random() * 1.2
|
||||
pt.expirationtime = 0.5 + math.random()
|
||||
pt.pos = vector.offset(pos, math.random() - 0.5, -0.51, math.random() - 0.5)
|
||||
minetest.add_particle(pt)
|
||||
minetest.after(pt.expirationtime,function()
|
||||
pt.acceleration = vector.new(0,-9,0)
|
||||
minetest.after(pt.expirationtime, function()
|
||||
pt.acceleration = vector.new(0, -9, 0)
|
||||
pt.collisiondetection = true
|
||||
pt.expirationtime = math.random(1.2,4.5)
|
||||
pt.expirationtime = 1.2 + math.random() * 3.3
|
||||
minetest.add_particle(pt)
|
||||
end)
|
||||
end)
|
||||
|
|
|
@ -35,11 +35,13 @@ Birch Wood Planks=Birkenholzplanken
|
|||
Birch leaves are grown from birch trees.=Birkenblätter wachsen an Birken.
|
||||
Black Stained Glass=Schwarzes Buntglas
|
||||
Block of Coal=Kohleblock
|
||||
Block of Charcoal=
|
||||
Block of Diamond=Diamantblock
|
||||
Block of Emerald=Smaragdblock
|
||||
Block of Gold=Goldblock
|
||||
Block of Iron=Eisenblock
|
||||
Blocks of coal are useful as a compact storage of coal and very useful as a furnace fuel. A block of coal is as efficient as 10 coal.=Kohleblöcke sind für eine kompakte Aufbewahrung von Kohle nützlich und sehr nützlich als Ofenbrennstoff. Ein Kohleblock ist so effizient wie 10 mal Kohle.
|
||||
Blocks of charcoal are useful as a compact storage of charcoal and very useful as a furnace fuel. A block of charcoal is as efficient as 10 charcoal.=
|
||||
Blue Stained Glass=Blaues Buntglas
|
||||
Bone Block=Knochenblock
|
||||
Bone blocks are decorative blocks and a compact storage of bone meal.=Knochenblöcke sind Deko-Blöcke und geeignet zur kompakten Aufbewahrung von Knochenmehl.
|
||||
|
|
|
@ -35,11 +35,13 @@ Birch Wood Planks=Madera de abedul
|
|||
Birch leaves are grown from birch trees.=Las hojas de abedul se cultivan a partir de abedules.
|
||||
Black Stained Glass=Cristal negro
|
||||
Block of Coal=Bloque de carbón
|
||||
Block of Charcoal=
|
||||
Block of Diamond=Bloque de diamante
|
||||
Block of Emerald=Bloque de esmeralda
|
||||
Block of Gold=Bloque de oro
|
||||
Block of Iron=Bloque de hierro
|
||||
Blocks of coal are useful as a compact storage of coal and very useful as a furnace fuel. A block of coal is as efficient as 10 coal.=Los bloques de carbón son útiles como almacenamiento compacto de carbón y son muy útiles como combustible de horno. Un bloque de carbón es tan eficiente como 10 de carbón.
|
||||
Blocks of charcoal are useful as a compact storage of charcoal and very useful as a furnace fuel. A block of charcoal is as efficient as 10 charcoal.=
|
||||
Blue Stained Glass=Cristal azul
|
||||
Bone Block=Bloque de hueso
|
||||
Bone blocks are decorative blocks and a compact storage of bone meal.=Los bloques óseos son bloques decorativos y un almacenamiento compacto de harina de huesos.
|
||||
|
|
|
@ -35,11 +35,13 @@ Birch Wood Planks=Planches de bouleau
|
|||
Birch leaves are grown from birch trees.=Les feuilles de bouleau poussent sur les bouleaux.
|
||||
Black Stained Glass=Verre noir
|
||||
Block of Coal=Bloc de charbon
|
||||
Block of Charcoal=
|
||||
Block of Diamond=Bloc de diamant
|
||||
Block of Emerald=Bloc d'émeraude
|
||||
Block of Gold=Bloc d'or
|
||||
Block of Iron=Bloc de fer
|
||||
Blocks of coal are useful as a compact storage of coal and very useful as a furnace fuel. A block of coal is as efficient as 10 coal.=Les blocs de charbon sont utiles pour stocker du charbon et très utiles comme combustible de four. Un bloc de charbon est aussi efficace que 10 charbon.
|
||||
Blocks of charcoal are useful as a compact storage of charcoal and very useful as a furnace fuel. A block of charcoal is as efficient as 10 charcoal.=
|
||||
Blue Stained Glass=Verre bleu
|
||||
Bone Block=Bloc d'os
|
||||
Bone blocks are decorative blocks and a compact storage of bone meal.=Les blocs d'os sont des blocs décoratifs et servent à stocker la poudre d'os.
|
||||
|
|
|
@ -35,11 +35,13 @@ Birch Wood Planks=シラカバの板材
|
|||
Birch leaves are grown from birch trees.=シラカバの葉は、シラカバの木から育ちます。
|
||||
Black Stained Glass=黒色ガラス
|
||||
Block of Coal=石炭ブロック
|
||||
Block of Charcoal=
|
||||
Block of Diamond=ダイヤモンドブロック
|
||||
Block of Emerald=エメラルドブロック
|
||||
Block of Gold=金ブロック
|
||||
Block of Iron=鉄ブロック
|
||||
Blocks of coal are useful as a compact storage of coal and very useful as a furnace fuel. A block of coal is as efficient as 10 coal.=石炭ブロックは、石炭をコンパクトに保管でき、炉の燃料として非常に便利です。1個の石炭ブロックは、10個の石炭と同じ効率です。
|
||||
Blocks of charcoal are useful as a compact storage of charcoal and very useful as a furnace fuel. A block of charcoal is as efficient as 10 charcoal.=
|
||||
Blue Stained Glass=青色ガラス
|
||||
Bone Block=骨ブロック
|
||||
Bone blocks are decorative blocks and a compact storage of bone meal.=骨ブロックは装飾用ブロックで、骨粉をコンパクトに保管できます。
|
||||
|
|
|
@ -35,11 +35,13 @@ Birch Wood Planks=Brzozowe deski
|
|||
Birch leaves are grown from birch trees.=Brzozowe liście rosną na brzozach.
|
||||
Black Stained Glass=Czarne szkło
|
||||
Block of Coal=Blok węgla
|
||||
Block of Charcoal=
|
||||
Block of Diamond=Blok diamentu
|
||||
Block of Emerald=Blok szmaragdu
|
||||
Block of Gold=Blok złota
|
||||
Block of Iron=Blok żelaza
|
||||
Blocks of coal are useful as a compact storage of coal and very useful as a furnace fuel. A block of coal is as efficient as 10 coal.=Bloki węgla są użyteczne do kompaktowego przechowywania diamentów i bardzo użyteczne jako paliwo do pieca.
|
||||
Blocks of charcoal are useful as a compact storage of charcoal and very useful as a furnace fuel. A block of charcoal is as efficient as 10 charcoal.=
|
||||
Blue Stained Glass=Niebieskie szkło
|
||||
Bone Block=Blok kości
|
||||
Bone blocks are decorative blocks and a compact storage of bone meal.=Bloki kości są blokami dekoracyjnymi i są użyteczne do kompaktowego przechowywania mączki kostnej.
|
||||
|
|
|
@ -35,11 +35,13 @@ Birch Wood Planks=Tábuas de Bétula
|
|||
Birch leaves are grown from birch trees.=Folhas de bétula crescem a partir de árvores de bétula.
|
||||
Black Stained Glass=Vidro Tingido de Preto
|
||||
Block of Coal=Bloco de Carvão
|
||||
Block of Charcoal=
|
||||
Block of Diamond=Bloco de Diamante
|
||||
Block of Emerald=Bloco de Esmeralda
|
||||
Block of Gold=Bloco de Ouro
|
||||
Block of Iron=Bloco de Ferro
|
||||
Blocks of coal are useful as a compact storage of coal and very useful as a furnace fuel. A block of coal is as efficient as 10 coal.=Blocos de carvão são úteis para armzenad carvão de forma compacta e muito úteis como combustível de fornalas. Um bloco de carvão é tão eficiente quanto 10 carvões.
|
||||
Blocks of charcoal are useful as a compact storage of charcoal and very useful as a furnace fuel. A block of charcoal is as efficient as 10 charcoal.=
|
||||
Blue Stained Glass=Vidro Tingido de Azul
|
||||
Bone Block=Bloco de Osso
|
||||
Bone blocks are decorative blocks and a compact storage of bone meal.=Blocos de osso são blocos decorativos e uma forma compacta de armazenar farinha de osso.
|
||||
|
|
|
@ -35,11 +35,13 @@ Birch Wood Planks=Берёзовые доски
|
|||
Birch leaves are grown from birch trees.=Листва берёзы произрастает на берёзах.
|
||||
Black Stained Glass=Чёрное стекло
|
||||
Block of Coal=Угольный блок
|
||||
Block of Charcoal=Блок древесного угля
|
||||
Block of Diamond=Алмазный блок
|
||||
Block of Emerald=Изумрудный блок
|
||||
Block of Gold=Золотой блок
|
||||
Block of Iron=Железный блок
|
||||
Blocks of coal are useful as a compact storage of coal and very useful as a furnace fuel. A block of coal is as efficient as 10 coal.=Угольный блок удобен для компактного хранения угля, а также полезен как топливо для печи.
|
||||
Blocks of charcoal are useful as a compact storage of charcoal and very useful as a furnace fuel. A block of charcoal is as efficient as 10 charcoal.=Блок древесного угля удобен для компактного хранения древесного угля, а также полезен как топливо для печи.
|
||||
Blue Stained Glass=Синее стекло
|
||||
Bone Block=Костный блок
|
||||
Bone blocks are decorative blocks and a compact storage of bone meal.=Костные блоки это декоративные блоки, а также способ компактного хранения костной муки.
|
||||
|
|
|
@ -34,11 +34,13 @@ Birch Wood Planks=白樺樹木材
|
|||
Birch leaves are grown from birch trees.=白樺樹葉是由白樺樹樹生長出來的。
|
||||
Black Stained Glass=黑色玻璃
|
||||
Block of Coal=煤炭磚
|
||||
Block of Charcoal=
|
||||
Block of Diamond=鑽石磚
|
||||
Block of Emerald=綠寶石磚
|
||||
Block of Gold=金磚
|
||||
Block of Iron=鐵磚
|
||||
Blocks of coal are useful as a compact storage of coal and very useful as a furnace fuel. A block of coal is as efficient as 10 coal.=煤炭磚作為煤炭的省位存儲方式,作為熔爐燃料非常有用。一個煤炭磚的燃燒時間相當於10塊煤炭。
|
||||
Blocks of charcoal are useful as a compact storage of charcoal and very useful as a furnace fuel. A block of charcoal is as efficient as 10 charcoal.=
|
||||
Blue Stained Glass=藍色玻璃
|
||||
Bone Block=骨塊
|
||||
Bone blocks are decorative blocks and a compact storage of bone meal.=骨粉塊是一個裝飾方塊,也是骨粉的省位存儲方式。
|
||||
|
|
|
@ -35,11 +35,13 @@ Birch Wood Planks=
|
|||
Birch leaves are grown from birch trees.=
|
||||
Black Stained Glass=
|
||||
Block of Coal=
|
||||
Block of Charcoal=
|
||||
Block of Diamond=
|
||||
Block of Emerald=
|
||||
Block of Gold=
|
||||
Block of Iron=
|
||||
Blocks of coal are useful as a compact storage of coal and very useful as a furnace fuel. A block of coal is as efficient as 10 coal.=
|
||||
Blocks of charcoal are useful as a compact storage of charcoal and very useful as a furnace fuel. A block of charcoal is as efficient as 10 charcoal.=
|
||||
Blue Stained Glass=
|
||||
Bone Block=
|
||||
Bone blocks are decorative blocks and a compact storage of bone meal.=
|
||||
|
|
|
@ -288,7 +288,7 @@ minetest.register_node("mcl_core:stone_smooth", {
|
|||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
is_ground_content = false,
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 1.5,
|
||||
_mcl_hardness = 2,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_core:granite", {
|
||||
|
@ -424,7 +424,7 @@ minetest.register_node("mcl_core:grass_path", {
|
|||
footstep = {name="default_grass_footstep", gain=0.1},
|
||||
}),
|
||||
_mcl_blast_resistance = 0.65,
|
||||
_mcl_hardness = 0.6,
|
||||
_mcl_hardness = 0.65,
|
||||
})
|
||||
|
||||
-- TODO: Add particles
|
||||
|
@ -497,8 +497,8 @@ minetest.register_node("mcl_core:podzol", {
|
|||
sounds = mcl_sounds.node_sound_dirt_defaults(),
|
||||
on_construct = mcl_core.on_snowable_construct,
|
||||
_mcl_snowed = "mcl_core:podzol_snow",
|
||||
_mcl_blast_resistance = 0.8,
|
||||
_mcl_hardness = 0.8,
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 0.5,
|
||||
_mcl_silk_touch_drop = true,
|
||||
})
|
||||
mcl_core.register_snowed_node("mcl_core:podzol_snow", "mcl_core:podzol", nil, nil, false, S("Podzol with Snow"))
|
||||
|
@ -600,8 +600,8 @@ minetest.register_node("mcl_core:sandstonesmooth", {
|
|||
stack_max = 64,
|
||||
groups = {pickaxey=1, sandstone=1, normal_sandstone=1, building_block=1, material_stone=1},
|
||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 2,
|
||||
_mcl_blast_resistance = 0.8,
|
||||
_mcl_hardness = 0.8,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_core:sandstonecarved", {
|
||||
|
@ -687,8 +687,8 @@ minetest.register_node("mcl_core:redsandstonesmooth2", {
|
|||
stack_max = 64,
|
||||
groups = {pickaxey=1, sandstone=1, red_sandstone=1, building_block=1, material_stone=1},
|
||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
_mcl_blast_resistance = 0.8,
|
||||
_mcl_hardness = 0.8,
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 2,
|
||||
})
|
||||
|
||||
---
|
||||
|
@ -798,6 +798,18 @@ minetest.register_node("mcl_core:coalblock", {
|
|||
_mcl_hardness = 5,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_core:charcoalblock", {
|
||||
description = S("Block of Charcoal"),
|
||||
_doc_items_longdesc = S("Blocks of charcoal are useful as a compact storage of charcoal and very useful as a furnace fuel. A block of charcoal is as efficient as 10 charcoal."),
|
||||
tiles = {"mcl_core_charcoal_block.png"},
|
||||
is_ground_content = false,
|
||||
stack_max = 64,
|
||||
groups = {pickaxey=1, flammable=1, building_block=1, material_stone=1, fire_encouragement=5, fire_flammability=5},
|
||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 5,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_core:ironblock", {
|
||||
description = S("Block of Iron"),
|
||||
_doc_items_longdesc = S("A block of iron is mostly a decorative block but also useful as a compact storage of iron ingots."),
|
||||
|
@ -1051,7 +1063,15 @@ for i=1,8 do
|
|||
local itemstring = itemstack:get_name()
|
||||
local itemcount = itemstack:get_count()
|
||||
local fakestack = ItemStack(itemstring.." "..itemcount)
|
||||
fakestack:set_name("mcl_core:snow_"..math.min(8, (i+g)))
|
||||
if i+g < 8 then
|
||||
fakestack:set_name("mcl_core:snow_"..(i+g))
|
||||
else
|
||||
-- To stack `mcl_core:snow_8', just replacing it with `mcl_core:snowblock' Issue#4483
|
||||
if i+g == 9 then
|
||||
fakestack:set_count(itemcount + 1)
|
||||
end
|
||||
fakestack:set_name("mcl_core:snowblock")
|
||||
end
|
||||
itemstack = minetest.item_place(fakestack, placer, pointed_thing)
|
||||
minetest.sound_play(mcl_sounds.node_sound_snow_defaults().place, {pos = pointed_thing.under}, true)
|
||||
itemstack:set_name(itemstring)
|
||||
|
@ -1119,8 +1139,8 @@ minetest.register_node("mcl_core:snowblock", {
|
|||
on_construct = mcl_core.on_snow_construct,
|
||||
after_destruct = mcl_core.after_snow_destruct,
|
||||
drop = "mcl_throwing:snowball 4",
|
||||
_mcl_blast_resistance = 0.1,
|
||||
_mcl_hardness = 0.1,
|
||||
_mcl_blast_resistance = 0.2,
|
||||
_mcl_hardness = 0.2,
|
||||
_mcl_silk_touch_drop = true,
|
||||
})
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ end
|
|||
minetest.register_node("mcl_core:ladder", {
|
||||
description = S("Ladder"),
|
||||
_doc_items_longdesc = S(
|
||||
"A piece of ladder which allows you to climb vertically. Ladders can only be placed on the side of solid blocks and not on glass, leaves, ice, slabs, glowstone, nor sea lanterns."),
|
||||
"A piece of ladder which allows you to climb vertically. Ladders can only be placed on the side of solid blocks."),
|
||||
drawtype = "signlike",
|
||||
is_ground_content = false,
|
||||
tiles = { "default_ladder.png" },
|
||||
|
@ -85,9 +85,8 @@ minetest.register_node("mcl_core:ladder", {
|
|||
end
|
||||
local groups = def.groups
|
||||
|
||||
-- Don't allow to place the ladder at particular nodes
|
||||
if (groups and (groups.glass or groups.leaves or groups.slab)) or
|
||||
node.name == "mcl_core:ladder" or node.name == "mcl_core:ice" or node.name == "mcl_nether:glowstone" or node.name == "mcl_ocean:sea_lantern" then
|
||||
-- Don't allow to place the ladder at non-solid nodes
|
||||
if (groups and (not groups.solid)) then
|
||||
return itemstack
|
||||
end
|
||||
|
||||
|
@ -105,9 +104,10 @@ minetest.register_node("mcl_core:ladder", {
|
|||
return itemstack
|
||||
end
|
||||
local idef = itemstack:get_definition()
|
||||
local success = minetest.item_place_node(itemstack, placer, pointed_thing)
|
||||
local itemstack, pos = minetest.item_place_node(itemstack, placer, pointed_thing)
|
||||
|
||||
if success then
|
||||
-- A non-nil pos indicates the node was placed in a valid position.
|
||||
if pos then
|
||||
if idef.sounds and idef.sounds.place then
|
||||
minetest.sound_play(idef.sounds.place, { pos = above, gain = 1 }, true)
|
||||
end
|
||||
|
|
|
@ -191,8 +191,7 @@ minetest.register_node("mcl_crimson:twisting_vines", {
|
|||
"mcl_crimson:twisting_vines",
|
||||
"mcl_crimson:twisting_vines",
|
||||
},
|
||||
_mcl_blast_resistance = 0.2,
|
||||
_mcl_hardness = 0.2,
|
||||
_mcl_blast_resistance = 0,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_crimson:weeping_vines", {
|
||||
|
@ -281,8 +280,7 @@ minetest.register_node("mcl_crimson:weeping_vines", {
|
|||
"mcl_crimson:weeping_vines",
|
||||
"mcl_crimson:weeping_vines",
|
||||
},
|
||||
_mcl_blast_resistance = 0.2,
|
||||
_mcl_hardness = 0.2,
|
||||
_mcl_blast_resistance = 0,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_crimson:nether_sprouts", {
|
||||
|
@ -465,6 +463,7 @@ minetest.register_node("mcl_crimson:warped_hyphae_wood", {
|
|||
tiles = {"mcl_crimson_warped_hyphae_wood.png"},
|
||||
groups = {handy = 5,axey = 1, wood=1,building_block = 1, material_wood = 1},
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
_mcl_blast_resistance = 3,
|
||||
_mcl_hardness = 2,
|
||||
})
|
||||
|
||||
|
@ -662,6 +661,7 @@ minetest.register_node("mcl_crimson:crimson_hyphae_wood", {
|
|||
tiles = {"mcl_crimson_crimson_hyphae_wood.png"},
|
||||
groups = {handy = 5, axey = 1, wood = 1, building_block = 1, material_wood = 1},
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
_mcl_blast_resistance = 3,
|
||||
_mcl_hardness = 2,
|
||||
})
|
||||
|
||||
|
|
|
@ -38,8 +38,8 @@ minetest.register_node("mcl_deepslate:infested_deepslate", {
|
|||
drop = "",
|
||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
after_dig_node = spawn_silverfish,
|
||||
_mcl_hardness = 0,
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = 1.5,
|
||||
_mcl_blast_resistance = 0.75,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_deepslate:tuff", {
|
||||
|
@ -218,10 +218,7 @@ local function register_deepslate_variant(item, desc, longdesc)
|
|||
end
|
||||
if item ~= "chiseled" then
|
||||
mcl_stairs.register_stair_and_slab_simple("deepslate_"..item, "mcl_deepslate:deepslate_"..item, S(desc.." Stairs"), S(desc.." Slab"), S("Double "..desc.." Slab"))
|
||||
mcl_walls.register_wall(
|
||||
"mcl_deepslate:deepslate"..item.."wall",
|
||||
S(desc.." Wall"),
|
||||
"mcl_deepslate:deepslate_"..item)
|
||||
mcl_walls.register_wall("mcl_deepslate:deepslate"..item.."wall", S(desc.." Wall"), "mcl_deepslate:deepslate_"..item)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -230,7 +230,7 @@ minetest.register_node("mcl_end:chorus_flower_dead", {
|
|||
groups = {handy=1,axey=1, deco_block = 1, dig_by_piston = 1, destroy_by_lava_flow = 1,chorus_plant = 1, not_in_creative_inventory=1},
|
||||
after_dig_node = mcl_end.check_detach_chorus_plant,
|
||||
on_blast = mcl_end.check_blast_chorus_plant,
|
||||
_mcl_blast_resistance = 2,
|
||||
_mcl_blast_resistance = 0.4,
|
||||
_mcl_hardness = 0.4,
|
||||
})
|
||||
|
||||
|
@ -309,7 +309,7 @@ minetest.register_node("mcl_end:chorus_plant", {
|
|||
end,
|
||||
after_dig_node = mcl_end.check_detach_chorus_plant,
|
||||
on_blast = mcl_end.check_blast_chorus_plant,
|
||||
_mcl_blast_resistance = 2,
|
||||
_mcl_blast_resistance = 0.4,
|
||||
_mcl_hardness = 0.4,
|
||||
})
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ minetest.register_node("mcl_farming:soil_wet", {
|
|||
end,
|
||||
groups = {handy=1,shovely=1, not_in_creative_inventory=1, dirtifies_below_solid=1, dirtifier=1, soil=3, soil_sapling=1 },
|
||||
sounds = mcl_sounds.node_sound_dirt_defaults(),
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_blast_resistance = 0.6,
|
||||
_mcl_hardness = 0.6,
|
||||
})
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@ local lectern_def = {
|
|||
walkable = true,
|
||||
is_ground_content = false,
|
||||
node_placement_prediction = "",
|
||||
_mcl_blast_resistance = 3,
|
||||
_mcl_hardness = 2,
|
||||
_mcl_blast_resistance = 2.5,
|
||||
_mcl_hardness = 2.5,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
|
|
|
@ -60,7 +60,8 @@ local rod_def = {
|
|||
return minetest.item_place(itemstack, placer, pointed_thing, param2)
|
||||
end,
|
||||
|
||||
_mcl_blast_resistance = 0,
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 3,
|
||||
}
|
||||
|
||||
minetest.register_node("mcl_lightning_rods:rod", rod_def)
|
||||
|
|
|
@ -221,7 +221,7 @@ local wlroots = {
|
|||
liquids_pointable = true,
|
||||
drop = "mcl_mangrove:mangrove_roots",
|
||||
groups = {
|
||||
handy = 1, hoey = 1, water=3, liquid=3, puts_out_fire=1, dig_by_piston = 1, deco_block = 1, waterlogged = 1, not_in_creative_inventory=1 },
|
||||
handy = 1, hoey = 1, water=4, liquid=3, puts_out_fire=1, dig_by_piston = 1, deco_block = 1, not_in_creative_inventory=1 },
|
||||
_mcl_blast_resistance = 100,
|
||||
_mcl_hardness = -1, -- Hardness intentionally set to infinite instead of 100 (Minecraft value) to avoid problems in creative mode
|
||||
on_construct = function(pos)
|
||||
|
@ -322,14 +322,14 @@ mcl_stairs.register_stair("mangrove_wood", "mcl_mangrove:mangrove_wood",
|
|||
{handy=1,axey=1, flammable=3,wood_stairs=1, material_wood=1, fire_encouragement=5, fire_flammability=20},
|
||||
{"mcl_mangrove_planks.png"},
|
||||
S("Mangrove Wood Stairs"),
|
||||
mcl_sounds.node_sound_wood_defaults(), 3, 2,
|
||||
mcl_sounds.node_sound_wood_defaults(), nil, nil,
|
||||
"woodlike")
|
||||
|
||||
mcl_stairs.register_slab("mangrove_wood", "mcl_mangrove:mangrove_wood",
|
||||
{handy=1,axey=1, flammable=3,wood_slab=1, material_wood=1, fire_encouragement=5, fire_flammability=20},
|
||||
{"mcl_mangrove_planks.png"},
|
||||
S("Mangrove Wood Slab"),
|
||||
mcl_sounds.node_sound_wood_defaults(), 3, 2,
|
||||
mcl_sounds.node_sound_wood_defaults(), nil, nil,
|
||||
S("Double Mangrove Wood Slab"))
|
||||
|
||||
minetest.register_craft({
|
||||
|
|
|
@ -83,6 +83,13 @@ local function respawn_doll(pos)
|
|||
local mob = meta:get_string("Mob")
|
||||
local doll
|
||||
if mob and mob ~= "" then
|
||||
-- Handle conversion of mob spawners
|
||||
local convert_to = (minetest.registered_entities[mob] or {})._convert_to
|
||||
if convert_to then
|
||||
mob = convert_to
|
||||
meta:set_string("Mob", mob)
|
||||
end
|
||||
|
||||
doll = find_doll(pos)
|
||||
if not doll then
|
||||
doll = spawn_doll(pos)
|
||||
|
@ -128,7 +135,6 @@ function mcl_mobspawners.setup_spawner(pos, Mob, MinLight, MaxLight, MaxMobsInAr
|
|||
end
|
||||
set_doll_properties(doll, Mob)
|
||||
|
||||
|
||||
-- Start spawning very soon
|
||||
local t = minetest.get_node_timer(pos)
|
||||
t:start(2)
|
||||
|
@ -165,7 +171,6 @@ local function spawn_mobs(pos, elapsed)
|
|||
local count = 0
|
||||
local ent
|
||||
|
||||
|
||||
local timer = minetest.get_node_timer(pos)
|
||||
|
||||
-- spawn mob if player detected and in range
|
||||
|
@ -367,7 +372,6 @@ doll_def.on_activate = function(self, staticdata, dtime_s)
|
|||
self.object:set_velocity({x=0, y=0, z=0})
|
||||
self.object:set_acceleration({x=0, y=0, z=0})
|
||||
self.object:set_armor_groups({immortal=1})
|
||||
|
||||
end
|
||||
|
||||
doll_def.on_step = function(self, dtime)
|
||||
|
|
|
@ -10,10 +10,15 @@ local function spawn_silverfish(pos, oldnode, oldmetadata, digger)
|
|||
end
|
||||
|
||||
-- Template function for registering monster egg blocks
|
||||
local function register_block(subname, description, tiles, is_ground_content)
|
||||
local function register_block(subname, description, tiles, is_ground_content, hardness_override)
|
||||
if is_ground_content == nil then
|
||||
is_ground_content = false
|
||||
end
|
||||
-- Default hardness matches for stone and stone brick variants; cobble has 1.0
|
||||
local hardness = 0.75
|
||||
if hardness_override then
|
||||
hardness = hardness_override
|
||||
end
|
||||
minetest.register_node("mcl_monster_eggs:monster_egg_"..subname, {
|
||||
description = description,
|
||||
tiles = tiles,
|
||||
|
@ -24,14 +29,14 @@ local function register_block(subname, description, tiles, is_ground_content)
|
|||
after_dig_node = spawn_silverfish,
|
||||
_tt_help = S("Hides a silverfish"),
|
||||
_doc_items_longdesc = S("An infested block is a block from which a silverfish will pop out when it is broken. It looks identical to its normal counterpart."),
|
||||
_mcl_hardness = 0,
|
||||
_mcl_blast_resistance = 0.5,
|
||||
_mcl_hardness = hardness,
|
||||
_mcl_blast_resistance = 0.75,
|
||||
})
|
||||
end
|
||||
|
||||
-- Register all the monster egg blocks
|
||||
register_block("stone", S("Infested Stone"), {"default_stone.png"}, true)
|
||||
register_block("cobble", S("Infested Cobblestone"), {"default_cobble.png"})
|
||||
register_block("cobble", S("Infested Cobblestone"), {"default_cobble.png"}, nil, 1.0)
|
||||
register_block("stonebrick", S("Infested Stone Bricks"), {"default_stone_brick.png"})
|
||||
register_block("stonebrickcracked", S("Infested Cracked Stone Bricks"), {"mcl_core_stonebrick_cracked.png"})
|
||||
register_block("stonebrickmossy", S("Infested Mossy Stone Bricks"), {"mcl_core_stonebrick_mossy.png"})
|
||||
|
|
|
@ -259,8 +259,8 @@ minetest.register_node("mcl_nether:quartz_smooth", {
|
|||
tiles = {"mcl_nether_quartz_block_bottom.png"},
|
||||
groups = {pickaxey=1, quartz_block=1,building_block=1, material_stone=1},
|
||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
_mcl_blast_resistance = 0.8,
|
||||
_mcl_hardness = 0.8,
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 2,
|
||||
})
|
||||
|
||||
minetest.register_craftitem("mcl_nether:glowstone_dust", {
|
||||
|
|
|
@ -81,7 +81,8 @@ end
|
|||
-- Is this water?
|
||||
-- Returns the liquidtype, if indeed water.
|
||||
function kelp.is_submerged(node)
|
||||
if mt_get_item_group(node.name, "water") ~= 0 then
|
||||
local g = mt_get_item_group(node.name, "water")
|
||||
if g > 0 and g <= 3 then
|
||||
-- Expected only "source" and "flowing" from water liquids
|
||||
return mt_registered_nodes[node.name].liquidtype
|
||||
end
|
||||
|
@ -267,8 +268,7 @@ function kelp.next_height(pos, node, pos_tip, node_tip, submerged, downward_flow
|
|||
-- Flowing liquid: Grow 1 step, but also turn the tip node into a liquid source.
|
||||
if downward_flowing then
|
||||
local alt_liq = mt_registered_nodes[node_tip.name].liquid_alternative_source
|
||||
local alt_liq_accessible = mt_get_item_group(node_tip.name,"waterlogged") -- returns 0 if it isn't waterlogged.
|
||||
if alt_liq and not alt_liq_accessible then
|
||||
if alt_liq and mt_registered_nodes[alt_liq] then
|
||||
mt_set_node(pos_tip, {name=alt_liq})
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1260,7 +1260,11 @@ local function potions_init_icons(player)
|
|||
})
|
||||
table.insert(icon_ids[name], id)
|
||||
end
|
||||
|
||||
-- Absorption bar in damage disabled server is unneccessary
|
||||
if minetest.settings:get_bool("enable_damage") == true then
|
||||
hb.init_hudbar(player, "absorption")
|
||||
end
|
||||
end
|
||||
|
||||
local function potions_set_icons(player)
|
||||
|
|
|
@ -194,7 +194,7 @@ minetest.register_node("mcl_sculk:sculk", {
|
|||
is_ground_content = false,
|
||||
on_destruct = sculk_on_destruct,
|
||||
_mcl_blast_resistance = 0.2,
|
||||
_mcl_hardness = 0.6,
|
||||
_mcl_hardness = 0.2,
|
||||
_mcl_silk_touch_drop = true,
|
||||
})
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ minetest.register_node("mcl_sponges:sponge_wet", {
|
|||
buildable_to = false,
|
||||
stack_max = 64,
|
||||
sounds = mcl_sounds.node_sound_dirt_defaults(),
|
||||
groups = {handy=1, hoey=1, waterlogged = 1, building_block=1},
|
||||
groups = {handy=1, hoey=1, building_block=1},
|
||||
on_place = place_wet_sponge,
|
||||
_mcl_blast_resistance = 0.6,
|
||||
_mcl_hardness = 0.6,
|
||||
|
@ -175,7 +175,7 @@ if minetest.get_modpath("mclx_core") then
|
|||
buildable_to = false,
|
||||
stack_max = 64,
|
||||
sounds = mcl_sounds.node_sound_dirt_defaults(),
|
||||
groups = {handy=1, waterlogged = 1, building_block=1},
|
||||
groups = {handy=1, building_block=1},
|
||||
on_place = place_wet_sponge,
|
||||
_mcl_blast_resistance = 0.6,
|
||||
_mcl_hardness = 0.6,
|
||||
|
|
|
@ -11,7 +11,8 @@ mcl_stairs.register_stair_and_slab_simple("platinum", "example:platinum", "Plati
|
|||
```
|
||||
|
||||
## `mcl_stairs.register_stair_and_slab_simple(subname, sourcenode, desc_stair, desc_slab, double_description, corner_stair_texture_override)`
|
||||
Register a simple stair and a slab. The stair and slab will inherit all attributes from `sourcenode`. The `sourcenode` is also used as the item for crafting recipes.
|
||||
Register a simple stair and a slab. The stair and slab will inherit all attributes from `sourcenode`. The `sourcenode` is also used as the item for crafting recipes. If multiple nodes should craft into the same stairs/slab, see
|
||||
`mcl_stairs.register_craft_stairs` or `mcl_stairs.register_craft_slab`
|
||||
|
||||
This function is meant for simple nodes; if you need more flexibility, use one of the other functions instead.
|
||||
|
||||
|
@ -44,7 +45,7 @@ The itemstrings for the registered nodes will be of the form:
|
|||
|
||||
### Parameters
|
||||
* `subname`: Name fragment for node itemstrings (see above)
|
||||
* `recipeitem`: Item for crafting recipe. Use `group:` prefix to use a group instead
|
||||
* `recipeitem`: Item for crafting recipe and attribute inheritance. Do not use `group:` prefix here, alternative recipes can be registered using `mcl_stairs.register_craft_stairs(subname, recipeitem_or_group)`.
|
||||
* `groups`: Groups used for stair
|
||||
* `images`: Textures
|
||||
* `description`: Stair description/tooltip
|
||||
|
@ -81,3 +82,35 @@ The itemstrings for the registered nodes will be of the form:
|
|||
* `double_description`: Node description/tooltip for double slab
|
||||
* Other parameters: Same as for `register_stair`
|
||||
|
||||
## `mcl_stairs.register_craft_stairs(subname, recipeitem)`
|
||||
Just registers a recipe for `mcl_stairs:stair_<subname>`.
|
||||
Useful if a node variant should craft the same stairs as the base node, since the above functions use the same
|
||||
parameter for crafting material and attribute inheritance.
|
||||
e.g. 6 Purpur Pillar -> 4 Purpur Stairs is an alternate recipe.
|
||||
|
||||
Creates staircase recipes with 6 input items, both left-facing and right-facing. Outputs 4 stairs.
|
||||
|
||||
The itemstring for the output node will be of the form:
|
||||
|
||||
* `mcl_stairs:stair_<subname>`: Normal stair
|
||||
|
||||
### Parameters
|
||||
* `subname`: Name fragment for node itemstring (see above)
|
||||
* `recipeitem`: Item for crafting recipe. Use `group:` prefix to use a group instead
|
||||
|
||||
## `mcl_stairs.register_craft_slab(subname, recipeitem)`
|
||||
Just registers a recipe for `mcl_stairs:slab_<subname>`.
|
||||
Useful if a node variant should craft the same stairs as the base node, since the above functions use the same
|
||||
parameter for crafting material and attribute inheritance.
|
||||
e.g. 3 Quartz Pillar -> 6 Quartz Slab is an alternate recipe.
|
||||
|
||||
Creates slab recipe with 3 input items in any horizontal line. Outputs 6 slabs.
|
||||
|
||||
The itemstring for the output node will be of the form:
|
||||
|
||||
* `mcl_stairs:slab_<subname>`: Slab
|
||||
|
||||
### Parameters
|
||||
* `subname`: Name fragment for node itemstring (see above)
|
||||
* `recipeitem`: Item for crafting recipe. Use `group:` prefix to use a group instead
|
||||
|
||||
|
|
|
@ -237,30 +237,43 @@ function mcl_stairs.register_slab(subname, recipeitem, groups, images, descripti
|
|||
fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
|
||||
},
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
local under = minetest.get_node(pointed_thing.under)
|
||||
if not placer then return end
|
||||
|
||||
local above = pointed_thing.above
|
||||
local under = pointed_thing.under
|
||||
local anode = minetest.get_node(above)
|
||||
local unode = minetest.get_node(under)
|
||||
local adefs = minetest.registered_nodes[anode.name]
|
||||
local udefs = minetest.registered_nodes[unode.name]
|
||||
local wield_item = itemstack:get_name()
|
||||
local creative_enabled = minetest.is_creative_enabled(placer:get_player_name())
|
||||
local player_name = placer:get_player_name()
|
||||
local creative_enabled = minetest.is_creative_enabled(player_name)
|
||||
|
||||
-- place slab using under node orientation
|
||||
local dir = vector.subtract(pointed_thing.above, pointed_thing.under)
|
||||
local dir = vector.subtract(above, under)
|
||||
local p2 = unode.param2
|
||||
|
||||
local p2 = under.param2
|
||||
if minetest.is_protected(under, player_name) and not
|
||||
minetest.check_player_privs(placer, "protection_bypass") then
|
||||
minetest.record_protection_violation(under, player_name)
|
||||
return
|
||||
end
|
||||
|
||||
-- combine two slabs if possible
|
||||
-- Requirements: Same slab material, must be placed on top of lower slab, or on bottom of upper slab
|
||||
if (wield_item == under.name or (minetest.registered_nodes[under.name] and wield_item == minetest.registered_nodes[under.name]._mcl_other_slab_half)) and
|
||||
not ((dir.y >= 0 and minetest.get_item_group(under.name, "slab_top") == 1) or
|
||||
(dir.y <= 0 and minetest.get_item_group(under.name, "slab_top") == 0)) then
|
||||
if (wield_item == unode.name or (udefs and wield_item == udefs._mcl_other_slab_half)) and
|
||||
not ((dir.y >= 0 and minetest.get_item_group(unode.name, "slab_top") == 1) or
|
||||
(dir.y <= 0 and minetest.get_item_group(unode.name, "slab_top") == 0)) then
|
||||
|
||||
local player_name = placer:get_player_name()
|
||||
if minetest.is_protected(pointed_thing.under, player_name) and not
|
||||
minetest.check_player_privs(placer, "protection_bypass") then
|
||||
minetest.record_protection_violation(pointed_thing.under,
|
||||
player_name)
|
||||
return
|
||||
minetest.set_node(under, {name = double_slab, param2 = p2})
|
||||
|
||||
if not creative_enabled then
|
||||
itemstack:take_item()
|
||||
end
|
||||
local newnode = double_slab
|
||||
minetest.set_node(pointed_thing.under, {name = newnode, param2 = p2})
|
||||
return itemstack
|
||||
elseif (wield_item == anode.name or (adefs and wield_item == adefs._mcl_other_slab_half)) then
|
||||
minetest.set_node(above, {name = double_slab, param2 = p2})
|
||||
|
||||
if not creative_enabled then
|
||||
itemstack:take_item()
|
||||
end
|
||||
|
|
|
@ -1,10 +1,39 @@
|
|||
-- Register all Minecraft stairs and slabs
|
||||
-- Note about hardness: For some reason, the hardness of slabs and stairs don't always match nicely, so that some
|
||||
-- slabs actually take slightly longer to be dug than their stair counterparts.
|
||||
-- Note sure if it is a good idea to preserve this oddity.
|
||||
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
-- Cut Sandstone Stairs do not exist, and register_stair_and_slab does not allow multiple recipes
|
||||
-- (e.g. using group:node) if we try to copy the properties of the node at the same parameter.
|
||||
-- The missing recipes can be added separately via these:
|
||||
function mcl_stairs.register_craft_stairs(subname, recipeitem)
|
||||
minetest.register_craft({
|
||||
output = "mcl_stairs:stair_" .. subname .. " 4",
|
||||
recipe = {
|
||||
{recipeitem, "", ""},
|
||||
{recipeitem, recipeitem, ""},
|
||||
{recipeitem, recipeitem, recipeitem},
|
||||
},
|
||||
})
|
||||
-- Flipped recipe
|
||||
minetest.register_craft({
|
||||
output = "mcl_stairs:stair_" .. subname .. " 4",
|
||||
recipe = {
|
||||
{"", "", recipeitem},
|
||||
{"", recipeitem, recipeitem},
|
||||
{recipeitem, recipeitem, recipeitem},
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
function mcl_stairs.register_craft_slab(subname, recipeitem)
|
||||
minetest.register_craft({
|
||||
output = "mcl_stairs:slab_" .. subname .. " 6",
|
||||
recipe = {
|
||||
{recipeitem, recipeitem, recipeitem},
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
local woods = {
|
||||
{ "wood", "default_wood.png", S("Oak Wood Stairs"), S("Oak Wood Slab"), S("Double Oak Wood Slab") },
|
||||
{ "junglewood", "default_junglewood.png", S("Jungle Wood Stairs"), S("Jungle Wood Slab"), S("Double Jungle Wood Slab") },
|
||||
|
@ -20,13 +49,13 @@ for w=1, #woods do
|
|||
{handy=1,axey=1, flammable=3,wood_stairs=1, material_wood=1, fire_encouragement=5, fire_flammability=20},
|
||||
{wood[2]},
|
||||
wood[3],
|
||||
mcl_sounds.node_sound_wood_defaults(), 3, 2,
|
||||
mcl_sounds.node_sound_wood_defaults(), nil, nil,
|
||||
"woodlike")
|
||||
mcl_stairs.register_slab(wood[1], "mcl_core:"..wood[1],
|
||||
{handy=1,axey=1, flammable=3,wood_slab=1, material_wood=1, fire_encouragement=5, fire_flammability=20},
|
||||
{wood[2]},
|
||||
wood[4],
|
||||
mcl_sounds.node_sound_wood_defaults(), 3, 2,
|
||||
mcl_sounds.node_sound_wood_defaults(), nil, nil,
|
||||
wood[5])
|
||||
end
|
||||
|
||||
|
@ -47,7 +76,7 @@ mcl_stairs.register_slab("stone", "mcl_core:stone_smooth",
|
|||
{pickaxey=1, material_stone=1},
|
||||
{"mcl_stairs_stone_slab_top.png", "mcl_stairs_stone_slab_top.png", "mcl_stairs_stone_slab_side.png"},
|
||||
S("Polished Stone Slab"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
mcl_sounds.node_sound_stone_defaults(), nil, nil,
|
||||
S("Double Polished Stone Slab"))
|
||||
|
||||
mcl_stairs.register_stair("andesite", "mcl_core:andesite",
|
||||
|
@ -77,7 +106,7 @@ mcl_stairs.register_slab("granite", "mcl_core:granite",
|
|||
mcl_stairs.register_stair("diorite", "mcl_core:diorite",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"mcl_core_diorite.png"},
|
||||
S("Granite Stairs"),
|
||||
S("Diorite Stairs"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8)
|
||||
mcl_stairs.register_slab("diorite", "mcl_core:diorite",
|
||||
{pickaxey=1, material_stone=1},
|
||||
|
@ -86,118 +115,95 @@ mcl_stairs.register_slab("diorite", "mcl_core:diorite",
|
|||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
S("Double Diorite Slab"))
|
||||
|
||||
mcl_stairs.register_stair("cobble", "mcl_core:cobble",
|
||||
mcl_stairs.register_stair_and_slab("cobble", "mcl_core:cobble",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"default_cobble.png"},
|
||||
S("Cobblestone Stairs"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8)
|
||||
mcl_stairs.register_slab("cobble", "mcl_core:cobble",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"default_cobble.png"},
|
||||
S("Cobblestone Slab"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
mcl_sounds.node_sound_stone_defaults(), nil, nil,
|
||||
S("Double Cobblestone Slab"))
|
||||
|
||||
mcl_stairs.register_stair("mossycobble", "mcl_core:mossycobble",
|
||||
mcl_stairs.register_stair_and_slab("mossycobble", "mcl_core:mossycobble",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"default_mossycobble.png"},
|
||||
S("Mossy Cobblestone Stairs"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8)
|
||||
mcl_stairs.register_slab("mossycobble", "mcl_core:mossycobble",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"default_mossycobble.png"},
|
||||
S("Mossy Cobblestone Slab"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
mcl_sounds.node_sound_stone_defaults(), nil, nil,
|
||||
S("Double Mossy Cobblestone Slab"))
|
||||
|
||||
mcl_stairs.register_stair("brick_block", "mcl_core:brick_block",
|
||||
mcl_stairs.register_stair_and_slab("brick_block", "mcl_core:brick_block",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"default_brick.png"},
|
||||
S("Brick Stairs"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8)
|
||||
mcl_stairs.register_slab("brick_block", "mcl_core:brick_block",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"default_brick.png"},
|
||||
S("Brick Slab"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
mcl_sounds.node_sound_stone_defaults(), nil, nil,
|
||||
S("Double Brick Slab"))
|
||||
|
||||
mcl_stairs.register_stair("sandstone", "mcl_core:sandstone",
|
||||
mcl_stairs.register_stair_and_slab("sandstone", "mcl_core:sandstone",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"mcl_core_sandstone_top.png", "mcl_core_sandstone_bottom.png", "mcl_core_sandstone_normal.png"},
|
||||
S("Sandstone Stairs"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8,
|
||||
nil, "mcl_core:sandstone") --fixme: extra parameter from previous release
|
||||
mcl_stairs.register_slab("sandstone", "mcl_core:sandstone",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"mcl_core_sandstone_top.png", "mcl_core_sandstone_bottom.png", "mcl_core_sandstone_normal.png"},
|
||||
S("Sandstone Slab"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
S("Double Sandstone Slab"), "mcl_core:sandstone") --fixme: extra parameter from previous release
|
||||
mcl_sounds.node_sound_stone_defaults(), nil, nil,
|
||||
S("Double Sandstone Slab"))
|
||||
mcl_stairs.register_craft_stairs("sandstone", "mcl_core:sandstonesmooth") -- Comment this line out if Cut Sandstone Stairs are implemented
|
||||
mcl_stairs.register_craft_stairs("sandstone", "mcl_core:sandstonecarved")
|
||||
mcl_stairs.register_craft_slab("sandstone", "mcl_core:sandstonecarved")
|
||||
|
||||
mcl_stairs.register_stair("sandstonesmooth2", "mcl_core:sandstonesmooth2",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"mcl_core_sandstone_top.png"},
|
||||
S("Smooth Sandstone Stairs"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8)
|
||||
mcl_stairs.register_slab("sandstonesmooth2", "mcl_core:sandstonesmooth2",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"mcl_core_sandstone_top.png"},
|
||||
S("Smooth Sandstone Slab"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
S("Double Smooth Sandstone Slab"))
|
||||
-- mcl_stairs.register_stair_and_slab("sandstonesmooth", "mcl_core:sandstonesmooth",
|
||||
-- {pickaxey=1, material_stone=1},
|
||||
-- {"mcl_core_sandstone_top.png", "mcl_core_sandstone_bottom.png", "mcl_core_sandstone_smooth.png"},
|
||||
-- S("Cut Sandstone Stairs"), S("Cut Sandstone Slab"),
|
||||
-- mcl_sounds.node_sound_stone_defaults(), nil, nil,
|
||||
-- S("Double Cut Sandstone Slab"))
|
||||
|
||||
mcl_stairs.register_stair("redsandstone", "mcl_core:redsandstone",
|
||||
mcl_stairs.register_stair_and_slab_simple("sandstonesmooth2", "mcl_core:sandstonesmooth2", S("Smooth Sandstone Stairs"), S("Smooth Sandstone Slab"), S("Double Smooth Sandstone Slab"))
|
||||
|
||||
mcl_stairs.register_stair_and_slab("redsandstone", "mcl_core:redsandstone",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"mcl_core_red_sandstone_top.png", "mcl_core_red_sandstone_bottom.png", "mcl_core_red_sandstone_normal.png"},
|
||||
S("Red Sandstone Stairs"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8,
|
||||
nil, "mcl_core:redsandstone") --fixme: extra parameter from previous release
|
||||
mcl_stairs.register_slab("redsandstone", "mcl_core:redsandstone",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"mcl_core_red_sandstone_top.png", "mcl_core_red_sandstone_bottom.png", "mcl_core_red_sandstone_normal.png"},
|
||||
S("Red Sandstone Slab"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
S("Double Red Sandstone Slab"), "mcl_core:redsandstone") --fixme: extra parameter from previous release
|
||||
mcl_sounds.node_sound_stone_defaults(), nil, nil,
|
||||
S("Double Red Sandstone Slab"))
|
||||
mcl_stairs.register_craft_stairs("redsandstone", "mcl_core:redsandstonesmooth") -- Comment this line out if Cut Red Sandstone Stairs are implemented
|
||||
mcl_stairs.register_craft_stairs("redsandstone", "mcl_core:redsandstonecarved")
|
||||
mcl_stairs.register_craft_slab("redsandstone", "mcl_core:redsandstonecarved")
|
||||
|
||||
mcl_stairs.register_stair("redsandstonesmooth2", "mcl_core:redsandstonesmooth2",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"mcl_core_red_sandstone_top.png"},
|
||||
S("Smooth Red Sandstone Stairs"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8)
|
||||
mcl_stairs.register_slab("redsandstonesmooth2", "mcl_core:redsandstonesmooth2",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"mcl_core_red_sandstone_top.png"},
|
||||
S("Smooth Red Sandstone Slab"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
S("Double Smooth Red Sandstone Slab"))
|
||||
-- mcl_stairs.register_stair_and_slab("redsandstonesmooth", "mcl_core:redsandstonesmooth",
|
||||
-- {pickaxey=1, material_stone=1},
|
||||
-- {"mcl_core_red_sandstone_top.png", "mcl_core_red_sandstone_bottom.png", "mcl_core_red_sandstone_smooth.png"},
|
||||
-- S("Cut Red Sandstone Stairs"), S("Cut Red Sandstone Slab"),
|
||||
-- mcl_sounds.node_sound_stone_defaults(), nil, nil,
|
||||
-- S("Double Cut Red Sandstone Slab"))
|
||||
|
||||
mcl_stairs.register_stair_and_slab_simple("redsandstonesmooth2", "mcl_core:redsandstonesmooth2", S("Smooth Red Sandstone Stairs"), S("Smooth Red Sandstone Slab"), S("Double Smooth Red Sandstone Slab"))
|
||||
|
||||
-- Intentionally not group:stonebrick because of mclx_stairs
|
||||
mcl_stairs.register_stair("stonebrick", "mcl_core:stonebrick",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"default_stone_brick.png"},
|
||||
S("Stone Bricks Stairs"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 1.5,
|
||||
nil, "mcl_core:stonebrick") --fixme: extra parameter from previous release
|
||||
mcl_sounds.node_sound_stone_defaults(), nil, nil,
|
||||
nil)
|
||||
mcl_stairs.register_slab("stonebrick", "mcl_core:stonebrick",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"default_stone_brick.png"},
|
||||
S("Stone Bricks Slab"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
S("Double Stone Bricks Slab"), "mcl_core:stonebrick") --fixme: extra parameter from previous release
|
||||
mcl_sounds.node_sound_stone_defaults(), nil, nil,
|
||||
S("Double Stone Bricks Slab"))
|
||||
|
||||
mcl_stairs.register_stair("quartzblock", "mcl_nether:quartz_block",
|
||||
mcl_stairs.register_stair_and_slab("quartzblock", "mcl_nether:quartz_block",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"mcl_nether_quartz_block_top.png", "mcl_nether_quartz_block_bottom.png", "mcl_nether_quartz_block_side.png"},
|
||||
S("Quartz Stairs"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 0.8, 0.8,
|
||||
nil, "mcl_nether:quartz_block") --fixme: extra parameter from previous release
|
||||
mcl_stairs.register_slab("quartzblock", "mcl_nether:quartz_block",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"mcl_nether_quartz_block_top.png", "mcl_nether_quartz_block_bottom.png", "mcl_nether_quartz_block_side.png"},
|
||||
S("Quartz Slab"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
S("Double Quartz Slab"), "mcl_nether:quartz_block") --fixme: extra parameter from previous release
|
||||
mcl_sounds.node_sound_stone_defaults(), nil, nil,
|
||||
S("Double Quartz Slab"))
|
||||
mcl_stairs.register_craft_stairs("quartzblock", "mcl_nether:quartz_pillar")
|
||||
mcl_stairs.register_craft_stairs("quartzblock", "mcl_nether:quartz_chiseled")
|
||||
mcl_stairs.register_craft_slab("quartzblock", "mcl_nether:quartz_pillar")
|
||||
mcl_stairs.register_craft_slab("quartzblock", "mcl_nether:quartz_chiseled")
|
||||
|
||||
mcl_stairs.register_stair("quartz_smooth", "mcl_nether:quartz_smooth",
|
||||
{pickaxey=1, material_stone=1},
|
||||
|
@ -216,14 +222,14 @@ mcl_stairs.register_stair_and_slab("nether_brick", "mcl_nether:nether_brick",
|
|||
{"mcl_nether_nether_brick.png"},
|
||||
S("Nether Brick Stairs"),
|
||||
S("Nether Brick Slab"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
mcl_sounds.node_sound_stone_defaults(), nil, nil,
|
||||
S("Double Nether Brick Slab"), nil)
|
||||
mcl_stairs.register_stair_and_slab("red_nether_brick", "mcl_nether:red_nether_brick",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"mcl_nether_red_nether_brick.png"},
|
||||
S("Red Nether Brick Stairs"),
|
||||
S("Red Nether Brick Slab"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
mcl_sounds.node_sound_stone_defaults(), nil, nil,
|
||||
S("Double Red Nether Brick Slab"), nil)
|
||||
|
||||
mcl_stairs.register_stair_and_slab("end_bricks", "mcl_end:end_bricks",
|
||||
|
@ -234,18 +240,15 @@ mcl_stairs.register_stair_and_slab("end_bricks", "mcl_end:end_bricks",
|
|||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
S("Double End Stone Brick Slab"), nil)
|
||||
|
||||
mcl_stairs.register_stair("purpur_block", "mcl_end:purpur_block",
|
||||
mcl_stairs.register_stair_and_slab("purpur_block", "mcl_end:purpur_block",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"mcl_end_purpur_block.png"},
|
||||
S("Purpur Stairs"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 1.5,
|
||||
nil)
|
||||
mcl_stairs.register_slab("purpur_block", "mcl_end:purpur_block",
|
||||
{pickaxey=1, material_stone=1},
|
||||
{"mcl_end_purpur_block.png"},
|
||||
S("Purpur Slab"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
mcl_sounds.node_sound_stone_defaults(), nil, nil,
|
||||
S("Double Purpur Slab"))
|
||||
mcl_stairs.register_craft_stairs("purpur_block", "mcl_end:purpur_pillar")
|
||||
mcl_stairs.register_craft_slab("purpur_block", "mcl_end:purpur_pillar")
|
||||
|
||||
mcl_stairs.register_stair("prismarine", "mcl_ocean:prismarine",
|
||||
{pickaxey=1, material_stone=1},
|
||||
|
@ -298,52 +301,52 @@ mcl_stairs.register_slab("andesite_smooth", "mcl_core:andesite_smooth",
|
|||
{pickaxey=1},
|
||||
{"mcl_core_andesite_smooth.png", "mcl_core_andesite_smooth.png", "mcl_stairs_andesite_smooth_slab.png"},
|
||||
S("Polished Andesite Slab"),
|
||||
nil, 6, nil,
|
||||
nil, nil, nil,
|
||||
S("Double Polished Andesite Slab"))
|
||||
mcl_stairs.register_stair("andesite_smooth", "mcl_core:andesite_smooth",
|
||||
{pickaxey=1},
|
||||
{"mcl_stairs_andesite_smooth_slab.png", "mcl_core_andesite_smooth.png", "mcl_core_andesite_smooth.png", "mcl_core_andesite_smooth.png", "mcl_core_andesite_smooth.png", "mcl_stairs_andesite_smooth_slab.png"},
|
||||
S("Polished Andesite Stairs"),
|
||||
nil, 6, nil,
|
||||
nil, nil, nil,
|
||||
"woodlike")
|
||||
|
||||
mcl_stairs.register_slab("granite_smooth", "mcl_core:granite_smooth",
|
||||
{pickaxey=1},
|
||||
{"mcl_core_granite_smooth.png", "mcl_core_granite_smooth.png", "mcl_stairs_granite_smooth_slab.png"},
|
||||
S("Polished Granite Slab"),
|
||||
nil, 6, nil,
|
||||
nil, nil, nil,
|
||||
S("Double Polished Granite Slab"))
|
||||
mcl_stairs.register_stair("granite_smooth", "mcl_core:granite_smooth",
|
||||
{pickaxey=1},
|
||||
{"mcl_stairs_granite_smooth_slab.png", "mcl_core_granite_smooth.png", "mcl_core_granite_smooth.png", "mcl_core_granite_smooth.png", "mcl_core_granite_smooth.png", "mcl_stairs_granite_smooth_slab.png"},
|
||||
S("Polished Granite Stairs"),
|
||||
nil, 6, nil,
|
||||
nil, nil, nil,
|
||||
"woodlike")
|
||||
|
||||
mcl_stairs.register_slab("diorite_smooth", "mcl_core:diorite_smooth",
|
||||
{pickaxey=1},
|
||||
{"mcl_core_diorite_smooth.png", "mcl_core_diorite_smooth.png", "mcl_stairs_diorite_smooth_slab.png"},
|
||||
S("Polished Diorite Slab"),
|
||||
nil, 6, nil,
|
||||
nil, nil, nil,
|
||||
S("Double Polished Diorite Slab"))
|
||||
mcl_stairs.register_stair("diorite_smooth", "mcl_core:diorite_smooth",
|
||||
{pickaxey=1},
|
||||
{"mcl_stairs_diorite_smooth_slab.png", "mcl_core_diorite_smooth.png", "mcl_core_diorite_smooth.png", "mcl_core_diorite_smooth.png", "mcl_core_diorite_smooth.png", "mcl_stairs_diorite_smooth_slab.png"},
|
||||
S("Polished Diorite Stairs"),
|
||||
nil, 6, nil,
|
||||
nil, nil, nil,
|
||||
"woodlike")
|
||||
|
||||
mcl_stairs.register_stair("stonebrickmossy", "mcl_core:stonebrickmossy",
|
||||
{pickaxey=1},
|
||||
{"mcl_core_stonebrick_mossy.png"},
|
||||
S("Mossy Stone Brick Stairs"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 1.5,
|
||||
mcl_sounds.node_sound_stone_defaults(), nil, nil,
|
||||
nil)
|
||||
|
||||
mcl_stairs.register_slab("stonebrickmossy", "mcl_core:stonebrickmossy",
|
||||
{pickaxey=1},
|
||||
{"mcl_core_stonebrick_mossy.png"},
|
||||
S("Mossy Stone Brick Slab"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
S("Double Mossy Stone Brick Slab"), "mcl_core:stonebrickmossy") --fixme: extra parameter from previous release
|
||||
mcl_sounds.node_sound_stone_defaults(), nil, nil,
|
||||
S("Double Mossy Stone Brick Slab"))
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ local function snowball_on_step(self, dtime)
|
|||
self.object:remove()
|
||||
return
|
||||
end
|
||||
self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set _lastpos-->Node will be added at last pos outside the node
|
||||
self._lastpos = pos -- Set _lastpos-->Node will be added at last pos outside the node
|
||||
end
|
||||
|
||||
-- Movement function of egg
|
||||
|
@ -133,19 +133,19 @@ local function egg_on_step(self, dtime)
|
|||
local node = minetest.get_node(pos)
|
||||
local def = minetest.registered_nodes[node.name]
|
||||
|
||||
-- Destroy when hitting a solid node with chance to spawn chicks
|
||||
if self._lastpos.x then
|
||||
if (def and def.walkable) or not def then
|
||||
-- Destroy when hitting a solid node or entity, with chance to spawn chicks
|
||||
if (def and def.walkable) or not def or check_object_hit(self, pos, 0) then
|
||||
-- If egg has just been thrown, use current position
|
||||
if not self._lastpos.x then
|
||||
self._lastpos = pos
|
||||
end
|
||||
-- 1/8 chance to spawn a chick
|
||||
-- FIXME: Chicks have a quite good chance to spawn in walls
|
||||
local r = math.random(1,8)
|
||||
|
||||
if r == 1 then
|
||||
if math.random(1,8) == 1 then
|
||||
mcl_mobs.spawn_child(self._lastpos, "mobs_mc:chicken")
|
||||
|
||||
-- BONUS ROUND: 1/32 chance to spawn 3 additional chicks
|
||||
local r = math.random(1,32)
|
||||
if r == 1 then
|
||||
if math.random(1,32) == 1 then
|
||||
local offsets = {
|
||||
{ x=0.7, y=0, z=0 },
|
||||
{ x=-0.7, y=0, z=-0.7 },
|
||||
|
@ -164,16 +164,8 @@ local function egg_on_step(self, dtime)
|
|||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- Destroy when hitting a mob or player (no chick spawning)
|
||||
if check_object_hit(self, pos, 0) then
|
||||
minetest.sound_play("mcl_throwing_egg_impact", { pos = self.object:get_pos(), max_hear_distance=10, gain=0.5 }, true)
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
|
||||
self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node
|
||||
self._lastpos = pos -- Set lastpos-->Node will be added at last pos outside the node
|
||||
end
|
||||
|
||||
-- Movement function of ender pearl
|
||||
|
@ -272,7 +264,7 @@ local function pearl_on_step(self, dtime)
|
|||
return
|
||||
end
|
||||
end
|
||||
self._lastpos={x=pos.x, y=pos.y, z=pos.z} -- Set lastpos-->Node will be added at last pos outside the node
|
||||
self._lastpos = pos -- Set lastpos-->Node will be added at last pos outside the node
|
||||
end
|
||||
|
||||
snowball_ENTITY.on_step = snowball_on_step
|
||||
|
|
|
@ -116,6 +116,7 @@ minetest.register_node("mcl_tnt:tnt", {
|
|||
local TNT = {
|
||||
-- Static definition
|
||||
physical = true, -- Collides with things
|
||||
collide_with_objects = false,
|
||||
--weight = -100,
|
||||
collisionbox = { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
|
||||
visual = "cube",
|
||||
|
|
|
@ -22,13 +22,13 @@ for b=1, #barks do
|
|||
{handy=1,axey=1, flammable=3, bark_stairs=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
|
||||
{minetest.registered_nodes[id].tiles[3]},
|
||||
bark[2],
|
||||
mcl_sounds.node_sound_wood_defaults(), 3, 2,
|
||||
mcl_sounds.node_sound_wood_defaults(), nil, nil,
|
||||
"woodlike")
|
||||
mcl_stairs.register_slab(sub, id,
|
||||
{handy=1,axey=1, flammable=3, bark_slab=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
|
||||
{minetest.registered_nodes[id].tiles[3]},
|
||||
bark[3],
|
||||
mcl_sounds.node_sound_wood_defaults(), 3, 2,
|
||||
mcl_sounds.node_sound_wood_defaults(), nil, nil,
|
||||
bark[4])
|
||||
end
|
||||
|
||||
|
@ -42,7 +42,7 @@ mcl_stairs.register_stair("lapisblock", "mcl_core:lapisblock",
|
|||
{pickaxey=3},
|
||||
{"mcl_stairs_lapis_block_slab.png", "mcl_core_lapis_block.png", "mcl_core_lapis_block.png", "mcl_core_lapis_block.png", "mcl_core_lapis_block.png", "mcl_stairs_lapis_block_slab.png"},
|
||||
S("Lapis Lazuli Stairs"),
|
||||
nil, 6, nil,
|
||||
nil, nil, nil,
|
||||
"woodlike")
|
||||
|
||||
mcl_stairs.register_slab("goldblock", "mcl_core:goldblock",
|
||||
|
@ -55,7 +55,7 @@ mcl_stairs.register_stair("goldblock", "mcl_core:goldblock",
|
|||
{pickaxey=4},
|
||||
{"mcl_stairs_gold_block_slab.png", "default_gold_block.png", "default_gold_block.png", "default_gold_block.png", "default_gold_block.png", "mcl_stairs_gold_block_slab.png"},
|
||||
S("Stairs of Gold"),
|
||||
nil, 6, nil,
|
||||
nil, nil, nil,
|
||||
"woodlike")
|
||||
|
||||
mcl_stairs.register_slab("ironblock", "mcl_core:ironblock",
|
||||
|
@ -68,21 +68,21 @@ mcl_stairs.register_stair("ironblock", "mcl_core:ironblock",
|
|||
{pickaxey=2},
|
||||
{"mcl_stairs_iron_block_slab.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "default_steel_block.png", "mcl_stairs_iron_block_slab.png"},
|
||||
S("Stairs of Iron"),
|
||||
nil, 6, nil,
|
||||
nil, nil, nil,
|
||||
"woodlike")
|
||||
|
||||
mcl_stairs.register_stair("stonebrickcracked", "mcl_core:stonebrickcracked",
|
||||
{pickaxey=1},
|
||||
{"mcl_core_stonebrick_cracked.png"},
|
||||
S("Cracked Stone Brick Stairs"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 1.5,
|
||||
mcl_sounds.node_sound_stone_defaults(), nil, nil,
|
||||
"woodlike")
|
||||
|
||||
mcl_stairs.register_slab("stonebrickcracked", "mcl_core:stonebrickcracked",
|
||||
{pickaxey=1},
|
||||
{"mcl_core_stonebrick_cracked.png"},
|
||||
S("Cracked Stone Brick Slab"),
|
||||
mcl_sounds.node_sound_stone_defaults(), 6, 2,
|
||||
mcl_sounds.node_sound_stone_defaults(), nil, nil,
|
||||
S("Double Cracked Stone Brick Slab"))
|
||||
|
||||
local block = {}
|
||||
|
|
|
@ -4027,7 +4027,7 @@ local function register_decorations()
|
|||
rotation = "random",
|
||||
})
|
||||
minetest.register_decoration({
|
||||
name = "mcl_biomes:mangrove_tree_4",
|
||||
name = "mcl_biomes:mangrove_tree_5",
|
||||
deco_type = "schematic",
|
||||
place_on = {"mcl_mud:mud"},
|
||||
sidelen = 80,
|
||||
|
@ -4040,6 +4040,7 @@ local function register_decorations()
|
|||
rotation = "random",
|
||||
})
|
||||
minetest.register_decoration({
|
||||
name = "mcl_biomes:mangrove_bee_nest",
|
||||
deco_type = "schematic",
|
||||
place_on = {"mcl_mud:mud"},
|
||||
sidelen = 80,
|
||||
|
@ -6099,6 +6100,9 @@ if mg_name ~= "singlenode" then
|
|||
minetest.get_decoration_id("mcl_biomes:mangrove_tree_1"),
|
||||
minetest.get_decoration_id("mcl_biomes:mangrove_tree_2"),
|
||||
minetest.get_decoration_id("mcl_biomes:mangrove_tree_3"),
|
||||
minetest.get_decoration_id("mcl_biomes:mangrove_tree_4"),
|
||||
minetest.get_decoration_id("mcl_biomes:mangrove_tree_5"),
|
||||
minetest.get_decoration_id("mcl_biomes:mangrove_bee_nest"),
|
||||
}
|
||||
for _, f in pairs(deco_ids_fungus) do
|
||||
minetest.set_gen_notify({decoration = true}, {f})
|
||||
|
@ -6158,29 +6162,20 @@ if mg_name ~= "singlenode" then
|
|||
|
||||
if not (maxp.y < mcl_vars.mg_overworld_min or minp.y > mcl_vars.mg_overworld_max) then
|
||||
local biomemap = minetest.get_mapgen_object("biomemap")
|
||||
--minetest.log("mangrove stuff: " .. dump(biomemap))
|
||||
local swamp_biome_id = minetest.get_biome_id("MangroveSwamp")
|
||||
local swamp_shore_id = minetest.get_biome_id("MangroveSwamp_shore")
|
||||
local is_swamp = table.indexof(biomemap, swamp_biome_id) ~= -1
|
||||
local is_swamp_shore = table.indexof(biomemap, swamp_shore_id) ~= -1
|
||||
|
||||
if is_swamp or is_swamp_shore then
|
||||
--minetest.log("Mangrove swamp biomes...")
|
||||
--minetest.log("is_swamp: " .. dump(is_swamp))
|
||||
--minetest.log("is_swamp_shore: " .. dump(is_swamp_shore))
|
||||
mangrove_roots_gen(gennotify, pr)
|
||||
else
|
||||
--minetest.log("is not mangrove swamp biomes...")
|
||||
end
|
||||
end
|
||||
|
||||
if not (maxp.y < mcl_vars.mg_end_min or minp.y > mcl_vars.mg_end_max) then
|
||||
--minetest.log("chorus stuff")
|
||||
chorus_gen(gennotify, pr)
|
||||
end
|
||||
|
||||
if not (maxp.y < mcl_vars.mg_nether_min or minp.y > mcl_vars.mg_nether_max) then
|
||||
--minetest.log("nether stuff")
|
||||
crimson_warped_gen(gennotify)
|
||||
end
|
||||
end)
|
||||
|
|
|
@ -116,6 +116,7 @@ mcl_structures.register_structure("shipwreck",{
|
|||
y_offset = function(pr) return pr:next(-4,-2) end,
|
||||
loot = {
|
||||
["mcl_chests:chest_small"] = {
|
||||
{
|
||||
stacks_min = 3,
|
||||
stacks_max = 10,
|
||||
items = {
|
||||
|
@ -137,10 +138,10 @@ mcl_structures.register_structure("shipwreck",{
|
|||
mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}) end },
|
||||
{ itemstring = "mcl_armor:boots_leather_enchanted", weight = 3, func = function(stack, pr)
|
||||
mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}) end },
|
||||
--{ itemstring = "TODO:bamboo", weight = 2, amount_min = 1, amount_max = 3 },
|
||||
{ itemstring = "mcl_bamboo:bamboo", weight = 2, amount_min = 1, amount_max = 3 },
|
||||
{ itemstring = "mcl_farming:pumpkin", weight = 2, amount_min = 1, amount_max = 3 },
|
||||
{ itemstring = "mcl_tnt:tnt", weight = 1, amount_min = 1, amount_max = 2 },
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
stacks_min = 2,
|
||||
|
@ -207,6 +208,7 @@ mcl_structures.register_structure("ocean_temple",{
|
|||
end,
|
||||
loot = {
|
||||
["mcl_chests:chest_small"] = {
|
||||
{
|
||||
stacks_min = 3,
|
||||
stacks_max = 10,
|
||||
items = {
|
||||
|
@ -215,6 +217,7 @@ mcl_structures.register_structure("ocean_temple",{
|
|||
{ itemstring = "mcl_fishing:fish_raw", weight = 5, amount_min = 8, amount_max = 21 },
|
||||
{ itemstring = "mcl_fishing:salmon_raw", weight = 7, amount_min = 4, amount_max = 8 },
|
||||
{ itemstring = "mcl_tnt:tnt", weight = 1, amount_min = 1, amount_max = 2 },
|
||||
}
|
||||
},
|
||||
{
|
||||
stacks_min = 2,
|
||||
|
|
|
@ -512,23 +512,27 @@ minetest.register_globalstep(function(dtime)
|
|||
local boots = player:get_inventory():get_stack("armor", 5)
|
||||
local soul_speed = mcl_enchanting.get_enchantment(boots, "soul_speed")
|
||||
if soul_speed > 0 then
|
||||
playerphysics.add_physics_factor(player, "speed", "mcl_playerplus:surface", soul_speed * 0.105 + 1.3)
|
||||
playerphysics.add_physics_factor(player, "speed", "mcl_playerplus:soul_speed", soul_speed * 0.105 + 1.3)
|
||||
else
|
||||
if node_stand_below == "mcl_core:ice" or node_stand_below == "mcl_core:packed_ice" or node_stand_below == "mcl_core:slimeblock" or node_stand_below == "mcl_core:water_source" then
|
||||
playerphysics.add_physics_factor(player, "speed", "mcl_playerplus:surface", 0.1)
|
||||
playerphysics.add_physics_factor(player, "speed", "mcl_playerplus:soul_speed", 0.1)
|
||||
else
|
||||
playerphysics.add_physics_factor(player, "speed", "mcl_playerplus:surface", 0.4)
|
||||
playerphysics.add_physics_factor(player, "speed", "mcl_playerplus:soul_speed", 0.4)
|
||||
end
|
||||
end
|
||||
elseif get_item_group(node_feet, "liquid") ~= 0 and mcl_enchanting.get_enchantment(player:get_inventory():get_stack("armor", 5), "depth_strider") then
|
||||
else
|
||||
playerphysics.remove_physics_factor(player, "speed", "mcl_playerplus:soul_speed")
|
||||
end
|
||||
if get_item_group(node_feet, "liquid") ~= 0 and mcl_enchanting.get_enchantment(player:get_inventory():get_stack("armor", 5), "depth_strider") then
|
||||
local boots = player:get_inventory():get_stack("armor", 5)
|
||||
local depth_strider = mcl_enchanting.get_enchantment(boots, "depth_strider")
|
||||
|
||||
if depth_strider > 0 then
|
||||
playerphysics.add_physics_factor(player, "speed", "mcl_playerplus:surface", (depth_strider / 3) + 0.75)
|
||||
playerphysics.add_physics_factor(player, "speed", "mcl_playerplus:depth_strider", (depth_strider / 3) + 0.75)
|
||||
else
|
||||
playerphysics.remove_physics_factor(player, "speed", "mcl_playerplus:depth_strider")
|
||||
end
|
||||
else
|
||||
playerphysics.remove_physics_factor(player, "speed", "mcl_playerplus:surface")
|
||||
playerphysics.remove_physics_factor(player, "speed", "mcl_playerplus:depth_strider")
|
||||
end
|
||||
|
||||
-- Is player suffocating inside node? (Only for solid full opaque cube type nodes
|
||||
|
@ -679,6 +683,8 @@ minetest.register_on_joinplayer(function(player)
|
|||
player:respawn()
|
||||
minetest.log("warning", name .. " joined the game with 0 hp and has been forced to respawn")
|
||||
end
|
||||
|
||||
playerphysics.remove_physics_factor(player, "speed", "mcl_playerplus:surface")
|
||||
end)
|
||||
|
||||
-- clear when player leaves
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* SOS-Games
|
||||
* Bram
|
||||
* qoheniac
|
||||
* WillConker
|
||||
|
||||
### Game rename
|
||||
Based on months of collecting suggestions, analysis and vetting of possible names, community voting and discussion between developers, the rename of the game has reached its conclusion! The project has been renamed to **VoxeLibre**.
|
||||
|
@ -165,16 +166,34 @@ One of our tools, the Python script allowing conversion of Minecraft resource pa
|
|||
* XP orbs related crash – by teknomunk
|
||||
* Ghast fireball related crash – by Araca
|
||||
* Crash related to server restart while a player is dead – by teknomunk
|
||||
* Crashes related to the new effects API - by teknomunk and Herowl
|
||||
* Crashes related to the new effects API – by teknomunk and Herowl
|
||||
|
||||
## 0.87.1 hotfix
|
||||
* Fixed crash when shooting potions from a dispenser - by teknomunk
|
||||
* Fixed crash related to custom mobspawners - by teknomunk
|
||||
* Fixed beacon crash - by teknomunk
|
||||
* Fixed eye of ender crash - by Herowl
|
||||
* Fixed Stalker texture generation - by teknomunk
|
||||
* Correctly refresh enchanted tool capabilities - by teknomunk
|
||||
* Fixed creative inventory misbehaving - by Herowl
|
||||
* Fixed variable definition in mob spawning code - by teknomunk
|
||||
* Updated documentation - by Herowl and teknomunk
|
||||
* Increased stack size for snowballs and eggs - by JoseDouglas26
|
||||
* Fixed crash when shooting potions from a dispenser – by teknomunk
|
||||
* Fixed crash related to custom mobspawners – by teknomunk
|
||||
* Fixed beacon crash – by teknomunk
|
||||
* Fixed eye of ender crash – by Herowl
|
||||
* Fixed Stalker texture generation – by teknomunk
|
||||
* Correctly refresh enchanted tool capabilities – by teknomunk
|
||||
* Fixed creative inventory misbehaving – by Herowl
|
||||
* Fixed variable definition in mob spawning code – by teknomunk
|
||||
* Updated documentation – by Herowl and teknomunk
|
||||
* Increased stack size for snowballs and eggs – by JoseDouglas26
|
||||
|
||||
## 0.87.2 hotfix
|
||||
* Zombie texture improvements – by SmokeyDope
|
||||
* Wrong name of diorite stairs fixed – by qoheniac
|
||||
* Fixed flint and steel wearing down when not placing fire – by JoseDouglas26 and WillConker
|
||||
* Fixed brewing stands' rotation – by JoseDouglas26 and WillConker
|
||||
* Fixed beacon formspec – by teknomunk
|
||||
* Made all hollow logs breakable properly – by teknomunk
|
||||
* Instructions on how to eat added to the help menu – by teknomunk
|
||||
* Potion conversion fixed – by Herowl
|
||||
* Fixed some node names – by seventeenthShulker
|
||||
* Fixed anvil and craftguide formspecs on mobile – by Herowl
|
||||
* Fixed effect loading – by Herowl
|
||||
* Fixed crash while fighting wither – by teknomunk
|
||||
* Fixed crash when bonemealing sweet berry bushes – by teknomunk
|
||||
* Fixed some mob conversion crashes – by teknomunk
|
||||
* Fixed crash related to the frost walker enchantment – by WillConker
|
||||
* Fixed some mob-related crashes – by Herowl
|
||||
|
|
|
@ -329,13 +329,13 @@ give_starting_inv (Player Starter Pack) bool false
|
|||
mcl_item_id_debug (Item ID Debug) bool false
|
||||
|
||||
#Log mob spawning and despawning events
|
||||
mcl_logging_mobs_spawn (Log Mob Spawning) bool true
|
||||
mcl_logging_mobs_spawn (Log Mob Spawning) bool false
|
||||
|
||||
# If enabled mapgen timings will be dumped to log
|
||||
mcl_logging_mapgen (Chunk generation logging) bool false
|
||||
|
||||
# If enabled generated structures will be logged
|
||||
mcl_logging_structures (Structure generation logging) bool true
|
||||
mcl_logging_structures (Structure generation logging) bool false
|
||||
|
||||
#Complete debug logging for mcl_signs events. Use this if you have issues with signs.
|
||||
mcl_logging_mcl_signs (Complete debug logging for mcl_signs) bool false
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 224 B |
Loading…
Reference in New Issue