Compare commits

..

5 Commits

Author SHA1 Message Date
Nils Dagsson Moskopp 47ef53db56
Force-detach minecart driver not attached to cart
If the driver manages to either die in a minecart or attach to some
other object, they may still be taking up space in the cart. No new
driver could enter a cart in such a situation, therefore any driver
of a cart without an attached object must be detached immediately.
2021-08-01 21:47:35 +02:00
Nils Dagsson Moskopp 37828b27a0
Do not rotate a boat while it is attached
Rotating a boat while it is attached to another object does not work as
expected: While the boat does not visually rotate, the head of the
driver rotates as if the boat did actually rotate. That looks wrong,
therefore no rotation must happen if the boat is attached to an object,
e.g. a minecart.
2021-08-01 21:05:23 +02:00
Nils Dagsson Moskopp 93b19d1588
Allow players to accelerate a minecart with a boat
In Minecraft you can put a boat in a minecart and steer the minecart
from the boat, which is quite useful to move mobs around – minecarts
have one seat, boats have two.
2021-08-01 19:34:50 +02:00
Nils Dagsson Moskopp cf3c335c37
Inhibit minecart pickup after detaching driver
When a minecart drives over an activator rail, it detaches its driver.
In cases where the “driver” is a mob or a boat, the mob or boat can get
picked up again immediately, which is likely to be unintended behaviour.

By inhibiting minecart pickup for a second when detaching a mob or boat
from a minecart, activator rails behave as expected: Minecart drivers
are detached and not picked up immediately if they are a mob or boat.
2021-07-22 06:50:20 +02:00
Nils Dagsson Moskopp c593036b61
Add support for mobs and boats in minecarts 2021-07-22 06:50:13 +02:00
51 changed files with 210 additions and 9978 deletions

View File

@ -21,7 +21,7 @@ The basic digging time groups determine by which tools a node can be dug.
* `swordy=1`: Diggable by sword (any material), and this node is *not* a cobweb
* `swordy_cobweb=1`: Diggable by sword (any material), and this node is a cobweb
* `shearsy=1`: Diggable by shears, and this node is *not* wool
* `shearsy_wool=1`: Diggable by shears, and this node is wool
* `shearsy=wool=1`: Diggable by shears, and this node is wool
* `handy=1`: Breakable by hand and this node gives it useful drop when dug by hand. All nodes which are breakable by pickaxe, axe, shovel, sword or shears are also automatically breakable by hand, but not neccess
* `creative_breakable=1`: Block is breakable by hand in creative mode. This group is implied if the node belongs to any other digging group
@ -182,10 +182,6 @@ These groups are used mostly for informational purposes
* `redstone_torch=1`: Redstone Torch (lit)
* `redstone_torch=2`: Redstone Torch (unlit)
* `dirt=1`: Uncovered dirt
* `dirt=2`: Covered dirt (grass or mycelium or podzol on top)
* `dirt=3`: Coarse dirt
* `plant=1`: Plant or part of a plant
* `double_plant`: Part of a double-sized plant. 1 = lower part, 2 = upper part

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -1,29 +0,0 @@
#!/bin/sh
set -eu
SVG_FILE=${2%.png}.svg
# How crisp a Minetest menu icon appears is influenced by image height
# and width. Low resolutions lead to blurry edges, as Minetest scales
# menu icons up. High resolutions lead to jagged edges, as Minetest
# scales menu icons down. Height & width of 72 pixes seem to work.
#
# Though usually one would export directly to "${3}", Inkscape 1.0 had
# its command line options changed by people who apparently think that
# backwards compatibility is some kind of swear word: Whereas earlier
# Inkscape versions would export to a file called foo.png.tmp, newer
# behaviour is to ignore the user's wishes & write to foo.png.png
# unless one asks it to write to a filename with a .png extension,
# Inkscape 1.0 changes the filename extension to .png each time.
#
# As we do not know the extension of "${3}", we have to use the
# extension, then rename the resulting file to the proper name;
# only that way the export works with Inkscape 1.0 & earlier …
>&2 inkscape \
--file="${SVG_FILE}" \
--export-png="${3}".png \
--export-area-page \
--export-height 72 \
--export-width 72 \
mv "${3}".png "${3}"

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 509 KiB

View File

@ -1,8 +0,0 @@
# mcl_colors
Mod providing global table containing legacy minecraft colors to be used in mods.
## mcl_colors.*
Colors by upper name, in hex value.
## mcl_colors.background.*
Background colors by upper name, in hex value.

View File

@ -1,36 +0,0 @@
mcl_colors = {
BLACK = "#000000",
DARK_BLUE = "#0000AA",
DARK_GREEN = "#00AA00",
DARK_AQUA = "#00AAAA",
DARK_RED = "#AA0000",
DARK_PURPLE = "#AA00AA",
GOLD = "#FFAA00",
GRAY = "#AAAAAA",
DARK_GRAY = "#555555",
BLUE = "#5555FF",
GREEN = "#55FF55",
AQUA = "#55FFFF",
RED = "#FF5555",
LIGHT_PURPLE = "#FF55FF",
YELLOW = "#FFFF55",
WHITE = "#FFFFFF",
background = {
BLACK = "#000000",
DARK_BLUE = "#00002A",
DARK_GREEN = "#002A00",
DARK_AQUA = "#002A2A",
DARK_RED = "#2A0000",
DARK_PURPLE = "#2A002A",
GOLD = "#2A2A00",
GRAY = "#2A2A2A",
DARK_GRAY = "#151515",
BLUE = "#15153F",
GREEN = "#153F15",
AQUA = "#153F3F",
RED = "#3F1515",
LIGHT_PURPLE = "#3F153F",
YELLOW = "#3F3F15",
WHITE = "#373501",
}
}

View File

@ -1,3 +0,0 @@
name = mcl_colors
author = Fleckenstein
description = The HTML sequences for the minecraft colors

View File

@ -269,6 +269,25 @@ function boat.on_step(self, dtime, moveresult)
self.object:set_animation({x=0, y=40}, paddling_speed, 0, true)
self._animation = 1
end
-- If boat is in a minecart, punch that cart.
--
-- Why? In Minecraft you can put a boat in a
-- minecart and steer the cart from the boat,
-- which is quite useful to move mobs around.
-- (Minecarts have one seat, boats have two.)
--
-- No, this is not a bug. Mojang has known it
-- for years and they never fixed that “bug”.
local parent = self.object:get_attach()
if parent then
local parent_name =
parent:get_luaentity().name
if parent_name == "mcl_minecarts:minecart" then
-- The driver must punch so
-- the steering works here.
parent:punch(self._driver, 1, {})
end
end
elseif ctrl.down then
-- Backwards
self._v = self._v - 0.1 * v_factor
@ -278,6 +297,7 @@ function boat.on_step(self, dtime, moveresult)
self.object:set_animation({x=0, y=40}, -paddling_speed, 0, true)
self._animation = -1
end
-- TODO: If boat is in a minecart, slow cart.
else
-- Stop paddling animation if no control pressed
if self._animation ~= 0 then
@ -285,13 +305,22 @@ function boat.on_step(self, dtime, moveresult)
self._animation = 0
end
end
if ctrl and ctrl.left then
-- Rotating a boat while it is attached to another
-- object does not work as expected: While the boat
-- does not visually rotate, the head of the driver
-- rotates as if the boat did actually rotate. That
-- looks wrong, therefore no rotation must happen if
-- the boat is attached to an object, e.g. a minecart.
--
-- TODO: Actually rotate boat once someone figures out
-- how to rotate an object attached to another object.
if ctrl and ctrl.left and not self.object:get_attach() then
if self._v < 0 then
self.object:set_yaw(yaw - (1 + dtime) * 0.03 * v_factor)
else
self.object:set_yaw(yaw + (1 + dtime) * 0.03 * v_factor)
end
elseif ctrl and ctrl.right then
elseif ctrl and ctrl.right and not self.object:get_attach() then
if self._v < 0 then
self.object:set_yaw(yaw + (1 + dtime) * 0.03 * v_factor)
else

View File

@ -155,16 +155,6 @@ function mcl_burning.set_on_fire(obj, burn_time, reason)
}) + 1
end
local already_burning = mcl_burning.is_burning(obj)
mcl_burning.set(obj, "float", "burn_time", burn_time)
mcl_burning.set(obj, "string", "reason", reason)
if already_burning then
return
end
local hud_id
if obj:is_player() then
hud_id = mcl_burning.get(obj, "int", "hud_id")
@ -178,7 +168,8 @@ function mcl_burning.set_on_fire(obj, burn_time, reason)
}) + 1
end
end
mcl_burning.set(obj, "float", "burn_time", burn_time)
mcl_burning.set(obj, "string", "reason", reason)
mcl_burning.set(obj, "int", "hud_id", hud_id)
mcl_burning.set(obj, "int", "sound_id", sound_id)
@ -294,7 +285,7 @@ function mcl_burning.fire_entity_step(self, dtime)
end
local animation_timer = self.animation_timer + dtime
if animation_timer >= ( 1 / mcl_burning.animation_fps ) then
if animation_timer >= 0.015 then
animation_timer = 0
local animation_frame = self.animation_frame + 1
if animation_frame > mcl_burning.animation_frames - 1 then
@ -305,48 +296,3 @@ function mcl_burning.fire_entity_step(self, dtime)
end
self.animation_timer = animation_timer
end
minetest.register_chatcommand("burn", {
params = S("<playername> <duration> <reason>"),
description = S("Sets a player on fire for the given amount of seconds with the given reason."),
privs = { debug = true },
func = function(name, params)
local playername, duration, reason = params:match("^(.+) (.+) (.+)$")
if not (playername and duration and reason) then
return false, S("Error: Parameter missing.")
end
local player = minetest.get_player_by_name(playername)
if not player then
return false, S(
"Error: Player “@1” not found.",
playername
)
end
local duration_number = tonumber(duration)
-- Lua numbers are truthy
-- NaN is not equal to NaN
if not duration_number or (duration_number ~= duration_number) then
return false, S(
"Error: Duration “@1” is not a number.",
duration
)
end
if duration_number < 0 then
return false, S(
"Error: Duration “@1” is negative.",
duration
)
end
mcl_burning.set_on_fire(
player,
duration_number,
reason
)
return true, S(
"Set @1 on fire for @2s for the following reason: @3",
playername,
duration,
reason
)
end,
})

View File

@ -2,8 +2,7 @@ local S = minetest.get_translator("mcl_burning")
local modpath = minetest.get_modpath("mcl_burning")
mcl_burning = {
animation_frames = tonumber(minetest.settings:get("fire_animation_frames")) or 8,
animation_fps = tonumber(minetest.settings:get("fire_animation_fps")) or 30
animation_frames = tonumber(minetest.settings:get("fire_animation_frames")) or 8
}
dofile(modpath .. "/api.lua")

View File

@ -1,4 +1,3 @@
local S = minetest.get_translator("mcl_item_entity")
--basic settings
local item_drop_settings = {} --settings table
item_drop_settings.age = 1.0 --how old a dropped item (_insta_collect==false) has to be before collecting
@ -449,7 +448,7 @@ minetest.register_entity(":__builtin:item", {
end,
get_staticdata = function(self)
local data = minetest.serialize({
return minetest.serialize({
itemstring = self.itemstring,
always_collect = self.always_collect,
age = self.age,
@ -457,39 +456,6 @@ minetest.register_entity(":__builtin:item", {
_flowing = self._flowing,
_removed = self._removed,
})
-- sfan5 guessed that the biggest serializable item
-- entity would have a size of 65530 bytes. This has
-- been experimentally verified to be still too large.
--
-- anon5 has calculated that the biggest serializable
-- item entity has a size of exactly 65487 bytes:
--
-- 1. serializeString16 can handle max. 65535 bytes.
-- 2. The following engine metadata is always saved:
-- • 1 byte (version)
-- • 2 byte (length prefix)
-- • 14 byte “__builtin:item”
-- • 4 byte (length prefix)
-- • 2 byte (health)
-- • 3 × 4 byte = 12 byte (position)
-- • 4 byte (yaw)
-- • 1 byte (version 2)
-- • 2 × 4 byte = 8 byte (pitch and roll)
-- 3. This leaves 65487 bytes for the serialization.
if #data > 65487 then -- would crash the engine
local stack = ItemStack(self.itemstring)
stack:get_meta():from_table(nil)
self.itemstring = stack:to_string()
minetest.log(
"warning",
"Overlong item entity metadata removed: “" ..
self.itemstring ..
"” had serialized length of " ..
#data
)
return self:get_staticdata()
end
return data
end,
on_activate = function(self, staticdata, dtime_s)
@ -782,29 +748,3 @@ minetest.register_entity(":__builtin:item", {
-- Note: on_punch intentionally left out. The player should *not* be able to collect items by punching
})
-- The “getwrittenbook” command was added as a debug aid. It can help
-- reproducing situations in which items with lots of metadata trigger
-- issues like heavy lag or server crashes. Do not remove this command
-- unless another easy way of getting items with overlong meta exists!
--
-- “/getwrittenbook 65323” creates an item that creates the largest
-- possible serializable written book item entity when dropped.
--
-- “/getwrittenbook 65324” creates an item that creates the smallest
-- possible non-serializable written book item entity when dropped.
minetest.register_chatcommand("getwrittenbook", {
params = S("<Count>"),
description = S("Get a written book with a configurable amount of characters."),
privs = {debug=true},
func = function(name, param)
local count = tonumber(param)
local itemstack = ItemStack("mcl_books:written_book")
local meta = itemstack:get_meta()
meta:set_string("description", "")
meta:set_string("text", string.rep("x", count))
local player = minetest.get_player_by_name(name)
local inv = player:get_inventory()
inv:add_item("main", itemstack)
end
})

View File

@ -12,8 +12,15 @@ local function detach_driver(self)
if not self._driver then
return
end
mcl_player.player_attached[self._driver] = nil
local player = minetest.get_player_by_name(self._driver)
if not self._driver:is_player() then
self._pickup_inhibit_timer = 1
self._driver:set_detach()
self._driver = nil
return
end
local player_name = self._driver:get_player_name()
mcl_player.player_attached[player_name] = nil
local player = minetest.get_player_by_name(player_name)
self._driver = nil
self._start_pos = nil
if player then
@ -75,6 +82,7 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
_old_pos = nil,
_old_vel = {x=0, y=0, z=0},
_old_switch = 0,
_pickup_inhibit_timer = 0, -- how many seconds are mobs and boats not picked up after detaching?
_railtype = nil,
}
@ -151,7 +159,7 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
end
local vel = self.object:get_velocity()
if puncher:get_player_name() == self._driver then
if self._driver and puncher:get_player_name() == self._driver:get_player_name() then
if math.abs(vel.x + vel.z) > 7 then
return
end
@ -175,9 +183,35 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
cart.on_activate_by_rail = on_activate_by_rail
function cart:on_step(dtime)
-- If the driver manages to either die in a minecart
-- or attach to some other object, they may still be
-- taking up space in the cart. Therefore the driver
-- must be detached if the minecart has no children.
if self._driver and
#self.object:get_children() == 0 then
detach_driver(self)
end
if self._pickup_inhibit_timer > 0 then
self._pickup_inhibit_timer = self._pickup_inhibit_timer - dtime
end
local entity_name = self.object:get_luaentity().name
if entity_name == "mcl_minecarts:minecart" and self._pickup_inhibit_timer <= 0 then
for _, obj in ipairs(minetest.get_objects_inside_radius(self.object:get_pos(), 1.3)) do
local entity = obj:get_luaentity()
if not self._driver and entity and ( entity._cmi_is_mob or entity.name == "mcl_boats:boat" ) and not obj:get_attach() then
self._driver = obj
obj:set_attach(self.object)
break
end
end
end
local ctrl, player = nil, nil
if self._driver then
player = minetest.get_player_by_name(self._driver)
if self._driver and self._driver:is_player() then
local player_name = self._driver:get_player_name()
player = minetest.get_player_by_name(player_name)
if player then
ctrl = player:get_player_control()
-- player detach
@ -446,7 +480,7 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
end
-- Give achievement when player reached a distance of 1000 nodes from the start position
if self._driver and (vector.distance(self._start_pos, pos) >= 1000) then
if self._driver and self._driver:is_player() and (vector.distance(self._start_pos, pos) >= 1000) then
awards.unlock(self._driver, "mcl:onARail")
end
@ -634,7 +668,7 @@ register_minecart(
if self._driver and player_name == self._driver then
detach_driver(self)
elseif not self._driver then
self._driver = player_name
self._driver = clicker
self._start_pos = self.object:get_pos()
mcl_player.player_attached[player_name] = true
clicker:set_attach(self.object, "", {x=0, y=-1.75, z=-2}, {x=0, y=0, z=0})

View File

@ -14,8 +14,6 @@ local DEFAULT_FALL_SPEED = -10
local FLOP_HEIGHT = 5.0
local FLOP_HOR_SPEED = 1.5
local LIGHT_SUN = minetest.LIGHT_MAX + 1
local MOB_CAP = {}
MOB_CAP.hostile = 70
MOB_CAP.passive = 10
@ -1059,7 +1057,7 @@ local do_env_damage = function(self)
if mod_worlds then
_, dim = mcl_worlds.y_to_layer(pos.y)
end
if (self.sunlight_damage ~= 0 or self.ignited_by_sunlight) and (minetest.get_node_light(pos) or 0) == LIGHT_SUN and dim == "overworld" then
if (self.sunlight_damage ~= 0 or self.ignited_by_sunlight) and (minetest.get_node_light(pos) or 0) >= minetest.LIGHT_MAX and dim == "overworld" then
if self.ignited_by_sunlight then
mcl_burning.set_on_fire(self.object, 10)
else

View File

@ -3,106 +3,13 @@ local N = function(s) return s end
local function get_tool_name(item)
local name = item:get_meta():get_string("name")
if name == "" then
local def = item:get_definition()
name=def._tt_original_description or def.description
if name ~= "" then
return name
end
local sanitized_name, substitution_count = name:gsub("[\r\n]"," ")
return sanitized_name
local def = item:get_definition()
return def._tt_original_description or def.description
end
local test_tool_1a = {
get_meta = function()
return {
get_string = function()
return "foo 1a"
end
}
end
}
assert( get_tool_name(test_tool_1a) == "foo 1a" )
local test_tool_1b = {
get_meta = function()
return {
get_string = function()
return "bar\rbaz\n1b"
end
}
end
}
assert( get_tool_name(test_tool_1b) == "bar baz 1b" )
local test_tool_2a = {
get_definition = function()
return {
_tt_original_description = "foo 2a"
}
end,
get_meta = function()
return {
get_string = function()
return ""
end
}
end
}
assert( get_tool_name(test_tool_2a) == "foo 2a" )
local test_tool_2b = {
get_definition = function()
return {
_tt_original_description = "bar\rbaz\n2b"
}
end,
get_meta = function()
return {
get_string = function()
return ""
end
}
end
}
assert( get_tool_name(test_tool_2b) == "bar baz 2b" )
local test_tool_3a = {
get_definition = function()
return {
description = "foo 3a"
}
end,
get_meta = function()
return {
get_string = function()
return ""
end
}
end
}
assert( get_tool_name(test_tool_3a) == "foo 3a" )
local test_tool_3b = {
get_definition = function()
return {
description = "bar\rbaz\n3b"
}
end,
get_meta = function()
return {
get_string = function()
return ""
end
}
end
}
assert( get_tool_name(test_tool_3b) == "bar baz 3b" )
mcl_death_messages = {}
-- Death messages

View File

@ -387,15 +387,13 @@ for colorid, colortab in pairs(mcl_banners.colors) do
-- redraw the pattern textures as low-resolution pixel
-- art and use that instead.
local layer = "([combine:20x40:-2,-2=" .. pattern .. "^[resize:16x24^[colorize:" .. color .. ":" .. layer_ratio .. ")"
local mask = "([combine:20x40:-2,-2=" .. pattern .. "^[resize:16x24" .. ")"
local layer = "(([combine:20x40:-2,-2="..pattern.."^[resize:16x24^[colorize:"..color..":"..layer_ratio.."))"
function escape(text)
return text:gsub("%^", "\\%^"):gsub(":", "\\:") -- :gsub("%(", "\\%("):gsub("%)", "\\%)")
end
local layer_masked = layer .. "^[mask:" .. escape(mask)
finished_banner = "[combine:32x32:0,0=" .. escape(base) .. ":8,4=" .. escape(layer_masked)
finished_banner = "[combine:32x32:0,0=" .. escape(base) .. ":8,4=" .. escape(layer)
end
inv = finished_banner

View File

@ -1,41 +1,6 @@
local S = minetest.get_translator("mcl_chests")
local mod_doc = minetest.get_modpath("doc")
-- Christmas chest setup
local it_is_christmas = false
local date = os.date("*t")
if (
date.month == 12 and (
date.day == 24 or
date.day == 25 or
date.day == 26
)
) then
it_is_christmas = true
end
local tiles_chest_normal_small = {"mcl_chests_normal.png"}
local tiles_chest_normal_double = {"mcl_chests_normal_double.png"}
if it_is_christmas then
tiles_chest_normal_small = {"mcl_chests_normal_present.png^mcl_chests_noise.png"}
tiles_chest_normal_double = {"mcl_chests_normal_double_present.png^mcl_chests_noise_double.png"}
end
local tiles_chest_trapped_small = {"mcl_chests_trapped.png"}
local tiles_chest_trapped_double = {"mcl_chests_trapped_double.png"}
if it_is_christmas then
tiles_chest_trapped_small = {"mcl_chests_trapped_present.png^mcl_chests_noise.png"}
tiles_chest_trapped_double = {"mcl_chests_trapped_double_present.png^mcl_chests_noise_double.png"}
end
local tiles_chest_ender_small = {"mcl_chests_ender.png"}
if it_is_christmas then
tiles_chest_ender_small = {"mcl_chests_ender_present.png^mcl_chests_noise.png"}
end
-- Chest Entity
local animate_chests = (minetest.settings:get_bool("animated_chests") ~= false)
local entity_animations = {
@ -187,10 +152,7 @@ if minetest.get_modpath("screwdriver") then
local nodename = node.name
local nodedef = minetest.registered_nodes[nodename]
local dir = minetest.facedir_to_dir(new_param2)
if animate_chests then
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)
end
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
@ -219,10 +181,6 @@ local player_chest_open = function(player, pos, node_name, textures, param2, dou
local dir = minetest.facedir_to_dir(param2)
local blocked = not shulker and (back_is_blocked(pos, dir) or double and back_is_blocked(mcl_util.get_double_container_neighbor_pos(pos, param2, node_name:sub(-4)), dir))
find_or_create_entity(pos, node_name, textures, param2, double, sound, mesh, shulker and "shulker" or "chest", dir):open(name, blocked)
else
minetest.sound_play(sound .. "_open", {
pos = pos,
})
end
end
@ -254,14 +212,11 @@ local chest_update_after_close = function(pos)
if node.name == "mcl_chests:trapped_chest_on_small" then
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_small", param2 = node.param2})
if animate_chests then
find_or_create_entity(pos, "mcl_chests:trapped_chest_small", tiles_chest_trapped_small, node.param2, false, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_small")
end
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, trapped_chest_mesecons_rules)
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", tiles_chest_trapped_double, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
find_or_create_entity(pos, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left")
@ -273,7 +228,7 @@ local chest_update_after_close = function(pos)
local pos_other = mcl_util.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", tiles_chest_trapped_double, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
find_or_create_entity(pos_other, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules)
end
end
@ -287,10 +242,6 @@ local player_chest_close = function(player)
end
if animate_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)
else
minetest.sound_play(open_chest.sound .. "_close", {
pos = open_chest.pos,
})
end
chest_update_after_close(open_chest.pos)
@ -429,21 +380,12 @@ minetest.register_node(small_name, {
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usagehelp,
_doc_items_hidden = hidden,
drawtype = animate_chests and "nodebox" or "mesh",
mesh = not animate_chests and "mcl_chests_chest.obj" or nil,
node_box = animate_chests and {
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {-0.4375, -0.5, -0.4375, 0.4375, 0.375, 0.4375},
} or nil,
collision_box = {
type = "fixed",
fixed = {-0.4375, -0.5, -0.4375, 0.4375, 0.375, 0.4375},
fixed = {-0.4375, -0.5, -0.4375, 0.4375, 0.375, 0.4375},
},
selection_box = {
type = "fixed",
fixed = {-0.4375, -0.5, -0.4375, 0.4375, 0.375, 0.4375},
},
tiles = animate_chests and {"mcl_chests_blank.png"} or small_textures,
tiles = {"mcl_chests_blank.png"},
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true,
_chest_entity_textures = small_textures,
_chest_entity_sound = "default_chest",
@ -493,10 +435,7 @@ minetest.register_node(small_name, {
minetest.swap_node(p, { name = "mcl_chests:"..canonical_basename.."_right", param2 = param2 })
else
minetest.swap_node(pos, { name = "mcl_chests:"..canonical_basename.."_small", param2 = param2 })
if animate_chests then
create_entity(pos, small_name, small_textures, param2, false, "default_chest", "mcl_chests_chest", "chest")
end
create_entity(pos, small_name, small_textures, param2, false, "default_chest", "mcl_chests_chest", "chest")
end
end,
after_place_node = function(pos, placer, itemstack, pointed_thing)
@ -884,8 +823,8 @@ register_chest("chest",
chestusage,
S("27 inventory slots") .. "\n" .. S("Can be combined to a large chest"),
{
small = tiles_chest_normal_small,
double = tiles_chest_normal_double,
small = {"mcl_chests_normal.png"},
double = {"mcl_chests_normal_double.png"},
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"},
@ -900,8 +839,8 @@ register_chest("chest",
)
local traptiles = {
small = tiles_chest_trapped_small,
double = tiles_chest_trapped_double,
small = {"mcl_chests_trapped.png"},
double = {"mcl_chests_trapped_double.png"},
inv = {"mcl_chests_chest_trapped_top.png", "mcl_chests_chest_trapped_bottom.png",
"mcl_chests_chest_trapped_right.png", "mcl_chests_chest_trapped_left.png",
"mcl_chests_chest_trapped_back.png", "mcl_chests_chest_trapped_front.png"},
@ -926,9 +865,7 @@ register_chest("trapped_chest",
}},
function(pos, node, clicker)
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_on_small", param2 = node.param2})
if animate_chests then
find_or_create_entity(pos, "mcl_chests:trapped_chest_on_small", tiles_chest_trapped_small, node.param2, false, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_on_small")
end
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, trapped_chest_mesecons_rules)
end,
function(pos, node, clicker)
@ -936,7 +873,7 @@ register_chest("trapped_chest",
meta:set_int("players", 1)
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_on_left", param2 = node.param2})
find_or_create_entity(pos, "mcl_chests:trapped_chest_on_left", tiles_chest_trapped_double, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_on_left")
find_or_create_entity(pos, "mcl_chests:trapped_chest_on_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_on_left")
mesecon.receptor_on(pos, trapped_chest_mesecons_rules)
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left")
@ -950,7 +887,7 @@ register_chest("trapped_chest",
mesecon.receptor_on(pos, trapped_chest_mesecons_rules)
minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_on_left", param2 = node.param2})
find_or_create_entity(pos_other, "mcl_chests:trapped_chest_on_left", tiles_chest_trapped_double, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_on_left")
find_or_create_entity(pos_other, "mcl_chests:trapped_chest_on_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_on_left")
mesecon.receptor_on(pos_other, trapped_chest_mesecons_rules)
end
)
@ -971,15 +908,13 @@ local function close_if_trapped_chest(pos, player)
if node.name == "mcl_chests:trapped_chest_on_small" then
minetest.swap_node(pos, {name="mcl_chests:trapped_chest_small", param2 = node.param2})
if animate_chests then
find_or_create_entity(pos, "mcl_chests:trapped_chest_small", tiles_chest_trapped_small, node.param2, false, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_small")
end
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, trapped_chest_mesecons_rules)
player_chest_close(player)
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", tiles_chest_trapped_double, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
find_or_create_entity(pos, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left")
@ -993,7 +928,7 @@ local function close_if_trapped_chest(pos, player)
local pos_other = mcl_util.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", tiles_chest_trapped_double, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
find_or_create_entity(pos_other, "mcl_chests:trapped_chest_left", {"mcl_chests_trapped_double.png"}, node.param2, true, "default_chest", "mcl_chests_chest", "chest"):reinitialize("mcl_chests:trapped_chest_left")
mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules)
player_chest_close(player)
@ -1041,7 +976,7 @@ minetest.register_node("mcl_chests:ender_chest", {
_doc_items_usagehelp = S("Rightclick the ender chest to access your personal interdimensional inventory."),
drawtype = "mesh",
mesh = "mcl_chests_chest.obj",
tiles = tiles_chest_ender_small,
tiles = {"mcl_chests_ender.png"},
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
paramtype = "light",
paramtype2 = "facedir",
@ -1067,38 +1002,22 @@ local formspec_ender_chest = "size[9,8.75]"..
"listring[current_player;enderchest]"..
"listring[current_player;main]"
minetest.register_chatcommand("enderchest", {
description = S("Show ender chest inventory formspec."),
privs = { debug = true },
func = function(name, params)
minetest.show_formspec(name, "enderchest:enderchest", formspec_ender_chest)
end
})
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 = 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."),
_doc_items_usagehelp = S("Rightclick the ender chest to access your personal interdimensional inventory."),
drawtype = animate_chests and "nodebox" or "mesh",
mesh = not animate_chests and "mcl_chests_chest.obj" or nil,
node_box = animate_chests and {
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {-0.4375, -0.5, -0.4375, 0.4375, 0.375, 0.4375},
} or nil,
collision_box = {
type = "fixed",
fixed = {-0.4375, -0.5, -0.4375, 0.4375, 0.375, 0.4375},
fixed = {-0.4375, -0.5, -0.4375, 0.5, 0.375, 0.4375},
},
selection_box = {
type = "fixed",
fixed = {-0.4375, -0.5, -0.4375, 0.4375, 0.375, 0.4375},
},
tiles = animate_chests and {"mcl_chests_blank.png"} or tiles_chest_ender_small,
_chest_entity_textures = tiles_chest_ender_small,
_chest_entity_textures = {"mcl_chests_ender.png"},
_chest_entity_sound = "mcl_chests_enderchest",
_chest_entity_mesh = "mcl_chests_chest",
_chest_entity_animation_type = "chest",
tiles = {"mcl_chests_blank.png"},
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true,
--[[{"mcl_chests_ender_chest_top.png", "mcl_chests_ender_chest_bottom.png",
"mcl_chests_ender_chest_right.png", "mcl_chests_ender_chest_left.png",
@ -1115,13 +1034,10 @@ minetest.register_node("mcl_chests:ender_chest_small", {
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec", formspec_ender_chest)
if animate_chests then
create_entity(pos, "mcl_chests:ender_chest_small", tiles_chest_ender_small, minetest.get_node(pos).param2, false, "mcl_chests_enderchest", "mcl_chests_chest", "chest")
end
create_entity(pos, "mcl_chests:ender_chest_small", {"mcl_chests_ender.png"}, minetest.get_node(pos).param2, false, "mcl_chests_enderchest", "mcl_chests_chest", "chest")
end,
on_rightclick = function(pos, node, clicker)
player_chest_open(clicker, pos, "mcl_chests:ender_chest_small", tiles_chest_ender_small, node.param2, false, "mcl_chests_enderchest", "mcl_chests_chest")
player_chest_open(clicker, pos, "mcl_chests:ender_chest_small", {"mcl_chests_ender.png"}, node.param2, false, "mcl_chests_enderchest", "mcl_chests_chest")
end,
on_receive_fields = function(pos, formname, fields, sender)
if fields.quit then
@ -1139,20 +1055,6 @@ minetest.register_on_joinplayer(function(player)
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()
if not minetest.find_node_near(player:get_pos(), def and def.range or ItemStack():get_definition().range, "mcl_chests:ender_chest_small", true) then
return 0
end
end
end)
minetest.register_craft({
output = 'mcl_chests:ender_chest',
recipe = {
@ -1313,9 +1215,8 @@ for color, desc in pairs(boxtypes) do
_doc_items_entry_name = entry_name,
_doc_items_longdesc = longdesc,
_doc_items_usagehelp = usagehelp,
drawtype = animate_chests and "nodebox" or "mesh",
mesh = not animate_chests and "mcl_chests_shulker.obj" or nil,
tiles = animate_chests and {"mcl_chests_blank.png"} or {mob_texture},
drawtype = "nodebox",
tiles = {"mcl_chests_blank.png"},
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "clip" or true,
_chest_entity_textures = {mob_texture},
_chest_entity_sound = "mcl_chests_shulker",
@ -1336,10 +1237,7 @@ for color, desc in pairs(boxtypes) do
meta:set_string("formspec", formspec_shulker_box(nil))
local inv = meta:get_inventory()
inv:set_size("main", 9*3)
if animate_chests then
create_entity(pos, small_name, {mob_texture}, minetest.get_node(pos).param2, false, "mcl_chests_shulker", "mcl_chests_shulker", "shulker")
end
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)
@ -1458,11 +1356,6 @@ 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
if not animate_chests and not double_chest then
return
end
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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 285 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 286 B

View File

@ -4,30 +4,47 @@
-- Crafting definition
--
local function craft_planks(output, input)
minetest.register_craft({
output = "mcl_core:"..output.."wood 4",
recipe = {
{"mcl_core:"..input},
}
})
end
minetest.register_craft({
output = 'mcl_core:wood 4',
recipe = {
{'mcl_core:tree'},
}
})
local planks = {
{"", "oak"},
{"dark", "dark_oak"},
{"jungle", "jungle"},
{"acacia", "acacia"},
{"spruce", "spruce"},
{"birch", "birch"}
}
minetest.register_craft({
output = 'mcl_core:darkwood 4',
recipe = {
{'mcl_core:darktree'},
}
})
for _, p in pairs(planks) do
craft_planks(p[1], p[1].."tree")
craft_planks(p[1], p[1].."tree_bark")
craft_planks(p[1], "stripped_"..p[2])
craft_planks(p[1], "stripped_"..p[2].."_bark")
end
minetest.register_craft({
output = 'mcl_core:junglewood 4',
recipe = {
{'mcl_core:jungletree'},
}
})
minetest.register_craft({
output = 'mcl_core:acaciawood 4',
recipe = {
{'mcl_core:acaciatree'},
}
})
minetest.register_craft({
output = 'mcl_core:sprucewood 4',
recipe = {
{'mcl_core:sprucetree'},
}
})
minetest.register_craft({
output = 'mcl_core:birchwood 4',
recipe = {
{'mcl_core:birchtree'},
}
})
minetest.register_craft({
type = 'shapeless',
@ -382,14 +399,8 @@ minetest.register_craft({
}
})
minetest.register_craft({
output = 'mcl_core:packed_ice 1',
recipe = {
{'mcl_core:ice', 'mcl_core:ice', 'mcl_core:ice'},
{'mcl_core:ice', 'mcl_core:ice', 'mcl_core:ice'},
{'mcl_core:ice', 'mcl_core:ice', 'mcl_core:ice'},
}
})
-- TODO: Add crafting recipe: 9 ice → 1 packed ice
-- Add it when silk touch tools work.
--
-- Crafting (tool repair)

View File

@ -165,7 +165,7 @@ local function eat_gapple(itemstack, placer, pointed_thing)
mcl_potions.fire_resistance_func(placer, 1, 300)
mcl_potions.leaping_func(placer, 1, 300)
end
-- TODO: Absorbtion
mcl_potions.swiftness_func(placer, absorbtion_factor, 120) -- TODO: Absorbtion
mcl_potions.regeneration_func(placer, 2, regen_duration)
return gapple_hunger_restore(itemstack, placer, pointed_thing)
end

View File

@ -202,42 +202,18 @@ Stained glass is a decorative and mostly transparent block which comes in variou
Stick=Stock
Sticks are a very versatile crafting material; used in countless crafting recipes.=Stöcke sind ein vielseitiges Material, sie werden in zahllosen Fertigungsrezepten gebraucht.
Stone=Stein
Stripped Acacia Log=Entrindeter Akazienstamm
Stripped Acacia Wood=Entrindetes Akazienholz
Stripped Birch Log=Entrindeter Birkenstamm
Stripped Birch Wood=Entrindetes Birkenholz
Stripped Dark Oak Log=Entrindeter Schwarzeichenstamm
Stripped Dark Oak Wood=Entrindetes Schwarzeichenholz
Stripped Jungle Log=Entrindeter Dschungelbaumstamm
Stripped Jungle Wood=Entrindetes Dschungelholz
Stripped Oak Log=Entrindeter Eichenstamm
Stripped Oak Wood=Entrindetes Eichenholz
Stripped Spruce Log=Entrindeter Fichtenstamm
Stripped Spruce Wood=Entrindetes Fichtenholz
Stone Bricks=Steinziegel
Sugar=Zucker
Sugar Canes=Zuckerrohr
Sugar canes are a plant which has some uses in crafting. Sugar canes will slowly grow up to 3 blocks when they are next to water and are placed on a grass block, dirt, sand, red sand, podzol or coarse dirt. When a sugar cane is broken, all sugar canes connected above will break as well.=Zuckerrohr ist eine Pflanze, die in der Herstellung gebraucht wird. Zuckerrohr wird in der Nähe von Wasser bis zu 3 zusätzliche Blöcke wachsen lassen, wenn sie sich neben Wasser befinden und auf einem Grasblock, auf Erde, Sand, roten Sand, Podsol oder grobe Erde platziert wurden. Wird ein Zuckerrohr abgebrochen, werden alle verbundenen Zuckerrohrblöcke ebenfalls abbrechen.
Sugar canes can only be placed top of other sugar canes and on top of blocks on which they would grow.=Zuckerrohr kann nur auf Zuckerrohr platziert werden und auf Blöcken, auf denen Zuckerrohr wachsen würde.
Sugar comes from sugar canes and is used to make sweet foods.=Zucker kommt von Zuckerrohr und wird benutzt, um süße Lebensmittel zu machen.
The stripped trunk of an acacia tree.=Der entrindete Stamm einer Akazie.
The stripped trunk of a birch tree.=Der entrindete Stamm einer Birke.
The stripped trunk of a dark oak tree.=Der entrindete Stamm einer Schwarzeiche.
The stripped trunk of a jungle tree.=Der entrindete Stamm eines Dschungelbaums.
The stripped trunk of an oak tree.=Der entrindete Stamm einer Eiche.
The stripped trunk of a spruce tree.=Der entrindete Stamm einer Fichte.
The trunk of a birch tree.=Der Baumstamm einer Birke.
The trunk of a dark oak tree.=Der Baumstamm einer Schwarzeiche.
The trunk of a jungle tree.=Der Baumstamm eines Dschungelbaums.
The trunk of a spruce tree.=Der Baumstamm einer Fichte.
The trunk of an acacia.=Der Baumstamm einer Akazie.
The trunk of an oak tree.=Der Baumstamm einer Eiche.
The stripped wood of an acacia tree.=Das entrindete Holz einer Akazie.
The stripped wood of a birch tree.=Das entrindete Holz einer Birke.
The stripped wood of a dark oak tree.=Das entrindete Holz einer Schwarzeiche.
The stripped wood of a jungle tree.=Das entrindete Holz eines Dschungelbaums.
The stripped wood of an oak tree.=Das entrindete Holz einer Eiche.
The stripped wood of a spruce tree.=Das entrindete Holz einer Fichte.
This block consists of a couple of loose stones and can't support itself.=Diser Block besteht aus ein paar losen Steinchen und kann sich nicht selbst tragen.
This is a decorative block surrounded by the bark of a tree trunk.=Dies ist ein dekorativer Block, der von der Rinde eines Baumstamms umgeben ist.
This is a full block of snow. Snow of this thickness is usually found in areas of extreme cold.=Ein ganzer Block aus Schnee. Schnee von dieser Dicke wird üblicherweise in Gebieten extremer Kälte gefunden.

View File

@ -202,42 +202,18 @@ Stained glass is a decorative and mostly transparent block which comes in variou
Stick=
Sticks are a very versatile crafting material; used in countless crafting recipes.=
Stone=
Stripped Acacia Log=
Stripped Acacia Wood=
Stripped Birch Log=
Stripped Birch Wood=
Stripped Dark Oak Log=
Stripped Dark Oak Wood=
Stripped Jungle Log=
Stripped Jungle Wood=
Stripped Oak Log=
Stripped Oak Wood=
Stripped Spruce Log=
Stripped Spruce Wood=
Stone Bricks=
Sugar=
Sugar Canes=
Sugar canes are a plant which has some uses in crafting. Sugar canes will slowly grow up to 3 blocks when they are next to water and are placed on a grass block, dirt, sand, red sand, podzol or coarse dirt. When a sugar cane is broken, all sugar canes connected above will break as well.=
Sugar canes can only be placed top of other sugar canes and on top of blocks on which they would grow.=
Sugar comes from sugar canes and is used to make sweet foods.=
The stripped trunk of an acacia tree.=
The stripped trunk of a birch tree.=
The stripped trunk of a dark oak tree.=
The stripped trunk of a jungle tree.=
The stripped trunk of an oak tree.=
The stripped trunk of a spruce tree.=
The trunk of a birch tree.=
The trunk of a dark oak tree.=
The trunk of a jungle tree.=
The trunk of a spruce tree.=
The trunk of an acacia.=
The trunk of an oak tree.=
The stripped wood of an acacia tree.=
The stripped wood of a birch tree.=
The stripped wood of a dark oak tree.=
The stripped wood of a jungle tree.=
The stripped wood of an oak tree.=
The stripped wood of a spruce tree.=
This block consists of a couple of loose stones and can't support itself.=
This is a decorative block surrounded by the bark of a tree trunk.=
This is a full block of snow. Snow of this thickness is usually found in areas of extreme cold.=

View File

@ -8,7 +8,7 @@ if mod_screwdriver then
end
-- Register tree trunk (wood) and bark
local function register_tree_trunk(subname, description_trunk, description_bark, longdesc, tile_inner, tile_bark, stripped_variant)
local register_tree_trunk = function(subname, description_trunk, description_bark, longdesc, tile_inner, tile_bark)
minetest.register_node("mcl_core:"..subname, {
description = description_trunk,
_doc_items_longdesc = longdesc,
@ -17,12 +17,11 @@ local function register_tree_trunk(subname, description_trunk, description_bark,
paramtype2 = "facedir",
on_place = mcl_util.rotate_axis,
stack_max = 64,
groups = {handy=1, axey=1, tree=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
groups = {handy=1,axey=1, tree=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
sounds = mcl_sounds.node_sound_wood_defaults(),
on_rotate = on_rotate,
_mcl_blast_resistance = 2,
_mcl_hardness = 2,
_mcl_stripped_variant = stripped_variant,
})
minetest.register_node("mcl_core:"..subname.."_bark", {
@ -32,49 +31,7 @@ local function register_tree_trunk(subname, description_trunk, description_bark,
paramtype2 = "facedir",
on_place = mcl_util.rotate_axis,
stack_max = 64,
groups = {handy=1, axey=1, bark=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
sounds = mcl_sounds.node_sound_wood_defaults(),
is_ground_content = false,
on_rotate = on_rotate,
_mcl_blast_resistance = 2,
_mcl_hardness = 2,
_mcl_stripped_variant = stripped_variant.."_bark",
})
minetest.register_craft({
output = "mcl_core:"..subname.."_bark 3",
recipe = {
{ "mcl_core:"..subname, "mcl_core:"..subname },
{ "mcl_core:"..subname, "mcl_core:"..subname },
}
})
end
-- Register stripped trunk and stripped wood
local function register_stripped_trunk(subname, description_stripped_trunk, description_stripped_bark, longdesc, longdesc_wood, tile_stripped_inner, tile_stripped_bark)
minetest.register_node("mcl_core:"..subname, {
description = description_stripped_trunk,
_doc_items_longdesc = longdesc,
_doc_items_hidden = false,
tiles = {tile_stripped_inner, tile_stripped_inner, tile_stripped_bark},
paramtype2 = "facedir",
on_place = mcl_util.rotate_axis,
stack_max = 64,
groups = {handy=1, axey=1, tree=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
sounds = mcl_sounds.node_sound_wood_defaults(),
on_rotate = on_rotate,
_mcl_blast_resistance = 2,
_mcl_hardness = 2,
})
minetest.register_node("mcl_core:"..subname.."_bark", {
description = description_stripped_bark,
_doc_items_longdesc = longdesc_wood,
tiles = {tile_stripped_bark},
paramtype2 = "facedir",
on_place = mcl_util.rotate_axis,
stack_max = 64,
groups = {handy=1, axey=1, bark=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
groups = {handy=1,axey=1, bark=1, flammable=2, building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=5},
sounds = mcl_sounds.node_sound_wood_defaults(),
is_ground_content = false,
on_rotate = on_rotate,
@ -91,7 +48,7 @@ local function register_stripped_trunk(subname, description_stripped_trunk, desc
})
end
local function register_wooden_planks(subname, description, tiles)
local register_wooden_planks = function(subname, description, tiles)
minetest.register_node("mcl_core:"..subname, {
description = description,
_doc_items_longdesc = doc.sub.items.temp.build,
@ -99,7 +56,7 @@ local function register_wooden_planks(subname, description, tiles)
tiles = tiles,
stack_max = 64,
is_ground_content = false,
groups = {handy=1, axey=1, flammable=3,wood=1,building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=20},
groups = {handy=1,axey=1, flammable=3,wood=1,building_block=1, material_wood=1, fire_encouragement=5, fire_flammability=20},
sounds = mcl_sounds.node_sound_wood_defaults(),
_mcl_blast_resistance = 3,
_mcl_hardness = 2,
@ -113,7 +70,7 @@ local register_leaves = function(subname, description, longdesc, tiles, sapling,
end
local apple_chances = {200, 180, 160, 120, 40}
local stick_chances = {50, 45, 30, 35, 10}
local function get_drops(fortune_level)
local drop = {
max_items = 1,
@ -151,7 +108,7 @@ local register_leaves = function(subname, description, longdesc, tiles, sapling,
tiles = tiles,
paramtype = "light",
stack_max = 64,
groups = {handy=1, shearsy=1, swordy=1, leafdecay=leafdecay_distance, flammable=2, leaves=1, deco_block=1, dig_by_piston=1, fire_encouragement=30, fire_flammability=60},
groups = {handy=1,shearsy=1,swordy=1, leafdecay=leafdecay_distance, flammable=2, leaves=1, deco_block=1, dig_by_piston=1, fire_encouragement=30, fire_flammability=60},
drop = get_drops(0),
_mcl_shears_drop = true,
sounds = mcl_sounds.node_sound_leaves_defaults(),
@ -162,7 +119,7 @@ local register_leaves = function(subname, description, longdesc, tiles, sapling,
})
end
local function register_sapling(subname, description, longdesc, tt_help, texture, selbox)
local register_sapling = function(subname, description, longdesc, tt_help, texture, selbox)
minetest.register_node("mcl_core:"..subname, {
description = description,
_tt_help = tt_help,
@ -182,7 +139,7 @@ local function register_sapling(subname, description, longdesc, tt_help, texture
fixed = selbox
},
stack_max = 64,
groups = {dig_immediate=3, plant=1, sapling=1, non_mycelium_plant=1, attached_node=1, dig_by_water=1, dig_by_piston=1, destroy_by_lava_flow=1, deco_block=1},
groups = {dig_immediate=3, plant=1,sapling=1,non_mycelium_plant=1,attached_node=1,dig_by_water=1,dig_by_piston=1,destroy_by_lava_flow=1,deco_block=1},
sounds = mcl_sounds.node_sound_leaves_defaults(),
on_construct = function(pos)
local meta = minetest.get_meta(pos)
@ -204,19 +161,12 @@ end
---------------------
register_tree_trunk("tree", S("Oak Wood"), S("Oak Bark"), S("The trunk of an oak tree."), "default_tree_top.png", "default_tree.png", "mcl_core:stripped_oak")
register_tree_trunk("darktree", S("Dark Oak Wood"), S("Dark Oak Bark"), S("The trunk of a dark oak tree."), "mcl_core_log_big_oak_top.png", "mcl_core_log_big_oak.png", "mcl_core:stripped_dark_oak")
register_tree_trunk("acaciatree", S("Acacia Wood"), S("Acacia Bark"), S("The trunk of an acacia."), "default_acacia_tree_top.png", "default_acacia_tree.png", "mcl_core:stripped_acacia")
register_tree_trunk("sprucetree", S("Spruce Wood"), S("Spruce Bark"), S("The trunk of a spruce tree."), "mcl_core_log_spruce_top.png", "mcl_core_log_spruce.png", "mcl_core:stripped_spruce")
register_tree_trunk("birchtree", S("Birch Wood"), S("Birch Bark"), S("The trunk of a birch tree."), "mcl_core_log_birch_top.png", "mcl_core_log_birch.png", "mcl_core:stripped_birch")
register_tree_trunk("jungletree", S("Jungle Wood"), S("Jungle Bark"), S("The trunk of a jungle tree."), "default_jungletree_top.png", "default_jungletree.png", "mcl_core:stripped_jungle")
register_stripped_trunk("stripped_oak", S("Stripped Oak Log"), S("Stripped Oak Wood"), S("The stripped trunk of an oak tree."), S("The stripped wood of an oak tree."), "mcl_core_stripped_oak_top.png", "mcl_core_stripped_oak_side.png")
register_stripped_trunk("stripped_acacia", S("Stripped Acacia Log"), S("Stripped Acacia Wood"), S("The stripped trunk of an acacia tree."), S("The stripped wood of an acacia tree."), "mcl_core_stripped_acacia_top.png", "mcl_core_stripped_acacia_side.png")
register_stripped_trunk("stripped_dark_oak", S("Stripped Dark Oak Log"), S("Stripped Dark Oak Wood"), S("The stripped trunk of a dark oak tree."), S("The stripped wood of a dark oak tree."), "mcl_core_stripped_dark_oak_top.png", "mcl_core_stripped_dark_oak_side.png")
register_stripped_trunk("stripped_birch", S("Stripped Birch Log"), S("Stripped Birch Wood"), S("The stripped trunk of a birch tree."), S("The stripped wood of a birch tree."), "mcl_core_stripped_birch_top.png", "mcl_core_stripped_birch_side.png")
register_stripped_trunk("stripped_spruce", S("Stripped Spruce Log"), S("Stripped Spruce Wood"), S("The stripped trunk of a spruce tree."), S("The stripped wood of a spruce tree."), "mcl_core_stripped_spruce_top.png", "mcl_core_stripped_spruce_side.png")
register_stripped_trunk("stripped_jungle", S("Stripped Jungle Log"), S("Stripped Jungle Wood"), S("The stripped trunk of a jungle tree."), S("The stripped wood of a jungle tree."),"mcl_core_stripped_jungle_top.png", "mcl_core_stripped_jungle_side.png")
register_tree_trunk("tree", S("Oak Wood"), S("Oak Bark"), S("The trunk of an oak tree."), "default_tree_top.png", "default_tree.png")
register_tree_trunk("darktree", S("Dark Oak Wood"), S("Dark Oak Bark"), S("The trunk of a dark oak tree."), "mcl_core_log_big_oak_top.png", "mcl_core_log_big_oak.png")
register_tree_trunk("acaciatree", S("Acacia Wood"), S("Acacia Bark"), S("The trunk of an acacia."), "default_acacia_tree_top.png", "default_acacia_tree.png")
register_tree_trunk("sprucetree", S("Spruce Wood"), S("Spruce Bark"), S("The trunk of a spruce tree."), "mcl_core_log_spruce_top.png", "mcl_core_log_spruce.png")
register_tree_trunk("birchtree", S("Birch Wood"), S("Birch Bark"), S("The trunk of a birch tree."), "mcl_core_log_birch_top.png", "mcl_core_log_birch.png")
register_tree_trunk("jungletree", S("Jungle Wood"), S("Jungle Bark"), S("The trunk of a jungle tree."), "default_jungletree_top.png", "default_jungletree.png")
register_wooden_planks("wood", S("Oak Wood Planks"), {"default_wood.png"})
register_wooden_planks("darkwood", S("Dark Oak Wood Planks"), {"mcl_core_planks_big_oak.png"})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 681 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 729 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 733 B

View File

@ -388,11 +388,12 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
{ x=0, y=0, z=-1 },
{ x=0, y=0, z=1 },
}
local floorpos, floor
for n=#neighbors, 1, -1 do
local offset = neighbors[n]
local blockpos = vector.add(stempos, offset)
local floorpos = { x=blockpos.x, y=blockpos.y-1, z=blockpos.z }
local floor = minetest.get_node(floorpos)
floorpos = { x=blockpos.x, y=blockpos.y-1, z=blockpos.z }
floor = minetest.get_node(floorpos)
local block = minetest.get_node(blockpos)
local soilgroup = minetest.get_item_group(floor.name, "soil")
if not ((minetest.get_item_group(floor.name, "grass_block") == 1 or floor.name=="mcl_core:dirt" or soilgroup == 2 or soilgroup == 3) and block.name == "air") then
@ -406,8 +407,6 @@ function mcl_farming:add_gourd(full_unconnected_stem, connected_stem_basename, s
local r = math.random(1, #neighbors)
local offset = neighbors[r]
local blockpos = vector.add(stempos, offset)
local floorpos = { x=blockpos.x, y=blockpos.y-1, z=blockpos.z }
local floor = minetest.get_node(floorpos)
local p2
if offset.x == 1 then
minetest.set_node(stempos, {name=connected_stem_names[1]})

View File

@ -43,19 +43,13 @@ end
-- Checks if player is still allowed to display the minimap
local function update_minimap(player)
local creative = minetest.is_creative_enabled(player:get_player_name())
local newstate=false
local oldstate=player:hud_get_flags().minimap
if creative or has_item_in_hotbar(player, "mcl_maps:filled_map") then
newstate=true
end
if oldstate ~= newstate then
if creative then
player:hud_set_flags({minimap = true, minimap_radar = true})
if creative then
player:hud_set_flags({minimap=true, minimap_radar = true})
else
if has_item_in_hotbar(player, "mcl_maps:filled_map") then
player:hud_set_flags({minimap = true, minimap_radar = false})
else
player:hud_set_flags({minimap = newstate, minimap_radar = false})
player:hud_set_flags({minimap = false, minimap_radar = false})
end
end
end

View File

@ -351,34 +351,6 @@ minetest.register_tool("mcl_tools:shovel_diamond", {
})
-- Axes
local function make_stripped_trunk(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then return end
local node = minetest.get_node(pointed_thing.under)
local nodedef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
if not placer:get_player_control().sneak and nodedef.on_rightclick then
return minetest.item_place(itemstack, placer, pointed_thing)
end
if minetest.is_protected(pointed_thing.under, placer:get_player_name()) then
minetest.record_protection_violation(pointed_thing.under, placer:get_player_name())
return itemstack
end
if nodedef._mcl_stripped_variant == nil then
return itemstack
else
minetest.swap_node(pointed_thing.under, {name=nodedef._mcl_stripped_variant, param2=node.param2})
if not minetest.is_creative_enabled(placer:get_player_name()) then
-- Add wear (as if digging a axey node)
local toolname = itemstack:get_name()
local wear = mcl_autogroup.get_wear(toolname, "axey")
itemstack:add_wear(wear)
end
end
return itemstack
end
minetest.register_tool("mcl_tools:axe_wood", {
description = S("Wooden Axe"),
_doc_items_longdesc = axe_longdesc,
@ -392,7 +364,6 @@ minetest.register_tool("mcl_tools:axe_wood", {
damage_groups = {fleshy=7},
punch_attack_uses = 30,
},
on_place = make_stripped_trunk,
sound = { breaks = "default_tool_breaks" },
_repair_material = "group:wood",
_mcl_toollike_wield = true,
@ -412,7 +383,6 @@ minetest.register_tool("mcl_tools:axe_stone", {
damage_groups = {fleshy=9},
punch_attack_uses = 66,
},
on_place = make_stripped_trunk,
sound = { breaks = "default_tool_breaks" },
_repair_material = "mcl_core:cobble",
_mcl_toollike_wield = true,
@ -433,7 +403,6 @@ minetest.register_tool("mcl_tools:axe_iron", {
damage_groups = {fleshy=9},
punch_attack_uses = 126,
},
on_place = make_stripped_trunk,
sound = { breaks = "default_tool_breaks" },
_repair_material = "mcl_core:iron_ingot",
_mcl_toollike_wield = true,
@ -453,7 +422,6 @@ minetest.register_tool("mcl_tools:axe_gold", {
damage_groups = {fleshy=7},
punch_attack_uses = 17,
},
on_place = make_stripped_trunk,
sound = { breaks = "default_tool_breaks" },
_repair_material = "mcl_core:gold_ingot",
_mcl_toollike_wield = true,
@ -473,7 +441,6 @@ minetest.register_tool("mcl_tools:axe_diamond", {
damage_groups = {fleshy=9},
punch_attack_uses = 781,
},
on_place = make_stripped_trunk,
sound = { breaks = "default_tool_breaks" },
_repair_material = "mcl_core:diamond",
_mcl_toollike_wield = true,

View File

@ -51,22 +51,9 @@ function tsm_railcorridors.get_default_treasure(pr)
-- UNUSED IN MINECLONE 2!
end
-- Almost all spawners spawn cave spiders, but there is a 1 in 1000
-- chance to spawn a pig spawner instead, inspired by multiple bugs
-- in Minecraft that turn spawners in Mineshafts into pig spawners.
-- (Basically any spawner bug in Minecraft generates pig spawners.)
--
-- The Minecraft chance to get a pig spawner here is way lower than
-- 1 in 1000, but because of the small size of Minetest worlds, the
-- Minecraft chance would risk not having a pig spawner in a world.
--
-- The world with the seed “pigs” generates a pig spawner at 3,-8,7
function tsm_railcorridors.on_construct_spawner(pos, pr)
if pr:next(1,1000) == 900 then
mcl_mobspawners.setup_spawner(pos, "mobs_mc:pig", 0, 7)
else
mcl_mobspawners.setup_spawner(pos, "mobs_mc:cave_spider", 0, 7)
end
-- All spawners spawn cave spiders
function tsm_railcorridors.on_construct_spawner(pos)
mcl_mobspawners.setup_spawner(pos, "mobs_mc:cave_spider", 0, 7)
end
-- MineClone 2's treasure function. Gets all treasures for a single chest.

View File

@ -114,7 +114,7 @@ if not tsm_railcorridors.nodes.corridor_woods_function then
end
-- Random Perlin noise generators
local pr, pr_carts, pr_spawner, pr_treasures, pr_deco, webperlin_major, webperlin_minor
local pr, pr_carts, pr_treasures, pr_deco, webperlin_major, webperlin_minor
local function InitRandomizer(seed)
-- Mostly used for corridor gen.
@ -123,8 +123,6 @@ local function InitRandomizer(seed)
pr_deco = PseudoRandom(seed+25)
-- Separate randomizer for carts because spawning carts is very timing-dependent
pr_carts = PseudoRandom(seed-654)
-- Spawner type randomiser
pr_spawner = PseudoRandom(seed+345)
-- Chest contents randomizer
pr_treasures = PseudoRandom(seed+777)
-- Used for cobweb generation, both noises have to reach a high value for cobwebs to appear
@ -753,7 +751,7 @@ local function create_corridor_section(waypoint, axis, sign, up_or_down, up_or_d
if place_cobwebs then
Cube(p, size, {name=tsm_railcorridors.nodes.cobweb}, true)
end
tsm_railcorridors.on_construct_spawner(p, pr_spawner)
tsm_railcorridors.on_construct_spawner(p)
no_spawner = true
end
end

View File

@ -1,206 +0,0 @@
local clamp = function(value, min, max)
assert( min < max )
if value < min then
return min
end
if value > max then
return max
end
return value
end
assert( clamp(000, -100, 100) == 000 )
assert( clamp(999, -100, 100) == 100 )
assert( clamp(999, -999, 999) == 999 )
assert( clamp(998, 999, 1999) == 999 )
assert( clamp(999, 999, 1999) == 999 )
local clamp_s16 = function(value)
-- seems minetest hangs on -32768 and 32767
return clamp(value, -32767, 32766)
end
assert( clamp_s16(000000) == 000000 )
assert( clamp_s16(000001) == 000001 )
assert( clamp_s16(000010) == 000010 )
assert( clamp_s16(000100) == 000100 )
assert( clamp_s16(001000) == 001000 )
assert( clamp_s16(010000) == 010000 )
assert( clamp_s16(100000) == 032766 )
assert( clamp_s16(-00000) == -00000 )
assert( clamp_s16(-00009) == -00009 )
assert( clamp_s16(-00099) == -00099 )
assert( clamp_s16(-00999) == -00999 )
assert( clamp_s16(-09999) == -09999 )
assert( clamp_s16(-99999) == -32767 )
local minetest_find_nodes_in_area = minetest.find_nodes_in_area
minetest.find_nodes_in_area = function(minp, maxp, ...)
if
minp.x >= 32767 or minp.x <= -32768 or
minp.y >= 32767 or minp.y <= -32768 or
minp.z >= 32767 or minp.z <= -32768 or
maxp.x >= 32767 or maxp.x <= -32768 or
maxp.y >= 32767 or maxp.y <= -32768 or
maxp.z >= 32767 or maxp.z <= -32768
then
minetest.log(
"warning",
"find_nodes_in_area() called with coords outside interval (-32768, 32767), clamping arguments: " ..
"minp { x=" .. minp.x .. ", y=" .. minp.y .. " z=" .. minp.z .. " } " ..
"maxp { x=" .. maxp.x .. ", y=" .. maxp.y .. " z=" .. maxp.z .. " } "
)
return minetest_find_nodes_in_area(
{ x=clamp_s16(minp.x), y=clamp_s16(minp.y), z=clamp_s16(minp.z) },
{ x=clamp_s16(maxp.x), y=clamp_s16(maxp.y), z=clamp_s16(maxp.z) },
...
)
else
return minetest_find_nodes_in_area(
minp,
maxp,
...
)
end
end
deep_compare = function(a, b)
local type_a = type(a)
local type_b = type(b)
if type_a ~= type_b then
return false
end
if type_a ~= "table" and type_b ~= "table" then
return a == b
end
for key_a, value_a in pairs(a) do
local value_b = b[key_a]
if not deep_compare(value_a, value_b) then
return false
end
end
for key_b, value_b in pairs(b) do
local value_a = a[key_b]
if not deep_compare(value_b, value_a) then
return false
end
end
return true
end
assert(
deep_compare(
1,
1.0
) == true
)
assert(
deep_compare(
true,
"true"
) == false
)
assert(
deep_compare(
{ a=1, b=-2, c=3.4 },
{ a=1, b=-2, c=3.4 }
) == true
)
assert(
deep_compare(
{ a={ 1, 2, 3 }, b="foo", c=false },
{ a={ 1, 2, 3 }, b="foo", c=false }
) == true
)
assert(
deep_compare(
{ a={ 1, 2, 3 }, b="foo", c=false },
{ a={ 4, 5, 6 }, b="foo", c=false }
) == false
)
assert(
deep_compare(
{ a={ 1, 2, 3 }, b={ c=false } },
{ a={ 1, 2, 3 }, b={ c=false } }
) == true
)
assert(
deep_compare(
{ a={ 1, 2, 3 }, b={ } },
{ a={ 1, 2, 3 }, b={ c=false } }
) == false
)
local test_minetest_find_nodes_in_area_implementation_equivalence = function()
-- If any assertion in this test function fails, the wrapper
-- for minetest.find_nodes_in_area() does not behave like the
-- original function. If you are reading the code because your
-- server crashed, please inform the Mineclonia developers.
local fun_1 = minetest_find_nodes_in_area
local fun_2 = minetest.find_nodes_in_area
for x = -31000, 31000, 15500 do
for y = -31000, 31000, 15500 do
for z = -31000, 31000, 15500 do
for d = 1, 9, 3 do
local minp = { x=x, y=y, z=z }
local maxp = { x=x+d, y=y+d, z=z+d }
minetest.emerge_area(
minp,
maxp,
function(blockpos, action, calls_remaining)
local npos_1, nnum_1 = fun_1(
minp,
maxp,
{ "air", "ignore" }
)
local npos_2, nnum_2 = fun_2(
minp,
maxp,
{ "air", "ignore" }
)
assert(
deep_compare(
npos_1,
npos_2
) == true
)
assert(
deep_compare(
nnum_1,
nnum_2
) == true
)
local ntab_1 = fun_1(
minp,
maxp,
{ "air", "ignore" },
true
)
local ntab_2 = fun_2(
minp,
maxp,
{ "air", "ignore" },
true
)
assert(
deep_compare(
ntab_1,
ntab_2
) == true
)
end
)
end
end
end
end
end
minetest.after( 0, test_minetest_find_nodes_in_area_implementation_equivalence )

View File

@ -1,121 +0,0 @@
local test_minetest_find_nodes_in_area_can_count = function(dtime)
-- This function tests that minetest.find_nodes_in_area() can
-- count nodes correctly. If it fails, the engine can not be
-- trusted to actually count how many nodes of a given type
-- are in a given volume. Yes, *it* is bad if that happens.
--
-- If you are looking at this function because it executes at
-- startup and crashes the game, by far the most stupid thing
-- you could do is disabling it. Only an absolute moron would
-- disable tests that ensure basic functionality still works.
--
-- Experience has taught me that such warnings are mostly not
-- taken seriously by both Minetest mod & core developers. As
-- there are very few situations in which someone would read
-- the code of the function without a crash, you are probably
-- asking yourself how bad it can be. Surely you will want an
-- example of what will break if this test breaks. The answer
-- to this simple question is equally simple and consists of a
-- heartfelt “What the fuck did you say, you stupid fuckwad?”.
--
-- Alrighty then, let's get it on …
local pos = { x=30999, y=30999, z=30999 }
-- You think there is nothing there? Well, here is the thing:
-- With standard settings you can only see map until x=30927,
-- although the renderer can actually render up to x=31007 if
-- you configure it to. Any statements given by minetest core
-- devs that contradict the above assertion are probably lies.
--
-- In any way, this area should be so far out that no one has
-- built here … yet. Now that you know it is possible, I know
-- you want to. How though? I suggest to figure the technique
-- out yourself, then go on and build invisible lag machines.
local radius = 3
local minp = vector.subtract(pos, radius)
local maxp = vector.add(pos, radius)
local nodename = "air"
local c_nodename = minetest.get_content_id(nodename)
-- Why not use minetest.set_node() here? Well, some mods do
-- trigger on every placement of a node in the entire map …
-- and we do not want to crash those mods in this test case.
-- (Voxelmanip does not trigger callbacks so all is well.)
--
-- And now for a funny story: I initially copied the following
-- code from the Minetest developer wiki. Can you spot a typo?
-- <https://dev.minetest.net/index.php?title=minetest.get_content_id&action=edit>
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map(
minp,
maxp
)
local area = VoxelArea:new({
MinEdge=emin,
MaxEdge=emax
})
local data = vm:get_data()
for z = minp.z, maxp.z do
for y = minp.y, maxp.y do
local vi = area:index(minp.x, y, z)
for x = minp.x, maxp.y do
data[vi] = c_nodename
vi = vi + 1
end
end
end
vm:set_data(data)
vm:write_to_map()
local npos, nnum = minetest.find_nodes_in_area(
minp,
maxp,
{ nodename }
)
local nodes_expected = math.pow( 1 + (2 * radius), 3 )
local nodes_counted = nnum[nodename]
local nodes_difference = nodes_expected - nodes_counted
-- Originally, there was an assertion here that made the game
-- crash at startup if Minetest forgot how to count. This was
-- originally intended to avoid buggy engine releases, but it
-- mostly made people upset and hindered debugging. Also, the
-- assertion contained no error message hinting at the reason
-- for the crash, making it exceptionally user-unfriendly. It
-- follows that a game or mod should only assert on behaviour
-- of the Lua code, not the underlying implementation, unless
-- engine bugs are bad enough to permanently corrupt a world.
if ( 0 ~= nodes_difference ) then
minetest.debug(
"minetest.find_nodes_in_area() failed to find " ..
nodes_difference .. " nodes that were placed. " ..
"Downgrading to Minetest 5.4.1 might fix this."
)
end
end
minetest.after( 0, test_minetest_find_nodes_in_area_can_count )
local test_minetest_find_nodes_in_area_crash = function(dtime)
-- And now for our feature presentation, where we call the
-- function “minetest.find_nodes_in_area()” with a position
-- out of bounds! Will it crash? Who knows‽ If it does, the
-- workaround is not working though, so it should be patched.
local pos = { x=32767, y=32767, z=32767 }
-- Note that not all out of bounds values actually crash the
-- function minetest.find_nodes_in_area()“. In fact, the vast
-- majority of out of bounds values do not crash the function.
local radius = 3
local minp = vector.subtract(pos, radius)
local maxp = vector.add(pos, radius)
local nodename = "air"
local npos, nnum = minetest.find_nodes_in_area(
minp,
maxp,
{ nodename }
)
-- That's all, folks!
end
minetest.after( 0, test_minetest_find_nodes_in_area_crash )

View File

@ -19,114 +19,8 @@ end
local pitch, name, node_stand, node_stand_below, node_head, node_feet, pos
local function roundN(n, d)
if type(n) ~= "number" then return n end
local m = 10^d
return math.floor(n * m + 0.5) / m
end
local function close_enough(a,b)
local rt=true
if type(a) == "table" and type(b) == "table" then
for k,v in pairs(a) do
if roundN(v,2) ~= roundN(b[k],2) then
rt=false
break
end
end
else
rt = roundN(a,2) == roundN(b,2)
end
return rt
end
local function props_changed(props,oldprops)
local changed=false
local p={}
for k,v in pairs(props) do
if not close_enough(v,oldprops[k]) then
p[k]=v
changed=true
end
end
return changed,p
end
--test if assert works
assert(true)
assert(not false)
--test data for == and ~=
local test_equal1=42
local test_equal2=42.0
local test_equal3=42.1
assert(test_equal1==test_equal1)
assert(test_equal1==test_equal2)
assert(test_equal1~=test_equal3)
--testdata for roundN
local test_round1=15
local test_round2=15.00199999999
local test_round3=15.00111111
local test_round4=15.00999999
assert(roundN(test_round1,2)==roundN(test_round1,2)) --test again if basic equality works because wth not
assert(roundN(test_round1,2)==roundN(test_round2,2))
assert(roundN(test_round1,2)==roundN(test_round3,2))
assert(roundN(test_round1,2)~=roundN(test_round4,2))
-- tests for close_enough
local test_cb = {-0.35,0,-0.35,0.35,0.8,0.35} --collisionboxes
local test_cb_close = {-0.351213,0,-0.35,0.35,0.8,0.351212}
local test_cb_diff = {-0.35,0,-1.35,0.35,0.8,0.35}
local test_eh = 1.65 --eye height
local test_eh_close = 1.65123123
local test_eh_diff = 1.35
local test_nt = { r = 225, b = 225, a = 225, g = 225 } --nametag
local test_nt_diff = { r = 225, b = 225, a = 0, g = 225 }
assert(close_enough(test_cb,test_cb_close))
assert(not close_enough(test_cb,test_cb_diff))
assert(close_enough(test_eh,test_eh_close))
assert(not close_enough(test_eh,test_eh_diff))
assert(not close_enough(test_nt,test_nt_diff)) --no floats involved here
--tests for props_changed
local test_properties_set1={collisionbox = {-0.35,0,-0.35,0.35,0.8,0.35}, eye_height = 0.65, nametag_color = { r = 225, b = 225, a = 225, g = 225 }}
local test_properties_set2={collisionbox = {-0.35,0,-0.35,0.35,0.8,0.35}, eye_height = 1.35, nametag_color = { r = 225, b = 225, a = 225, g = 225 }}
local test_p1,p=props_changed(test_properties_set1,test_properties_set1)
local test_p2,p=props_changed(test_properties_set1,test_properties_set2)
assert(not test_p1)
assert(test_p2)
-- we still don't really know if lua is lying to us! but at least everything *seems* to be ok
local function set_properties_conditional(player,props)
local changed,p=props_changed(props,player:get_properties())
if changed then
player:set_properties(p)
end
end
local function set_bone_position_conditional(player,b,p,r) --bone,position,rotation
local oldp,oldr=player:get_bone_position(b)
if vector.equals(vector.round(oldp),vector.round(p)) and vector.equals(vector.round(oldr),vector.round(r)) then
return
end
player:set_bone_position(b,p,r)
end
minetest.register_globalstep(function(dtime)
time = time + dtime
-- Update jump status immediately since we need this info in real time.
@ -151,55 +45,55 @@ minetest.register_globalstep(function(dtime)
-- controls right and left arms pitch when shooting a bow or punching
if string.find(player:get_wielded_item():get_name(), "mcl_bows:bow") and controls.RMB and not controls.LMB and not controls.up and not controls.down and not controls.left and not controls.right then
set_bone_position_conditional(player,"Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(pitch+90,-30,pitch * -1 * .35))
set_bone_position_conditional(player,"Arm_Left_Pitch_Control", vector.new(3.5,5.785,0), vector.new(pitch+90,43,pitch * .35))
player:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(pitch+90,-30,pitch * -1 * .35))
player:set_bone_position("Arm_Left_Pitch_Control", vector.new(3.5,5.785,0), vector.new(pitch+90,43,pitch * .35))
elseif controls.LMB and player:get_attach() == nil then
set_bone_position_conditional(player,"Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(pitch,0,0))
set_bone_position_conditional(player,"Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(0,0,0))
player:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(pitch,0,0))
player:set_bone_position("Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(0,0,0))
else
set_bone_position_conditional(player,"Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(0,0,0))
set_bone_position_conditional(player,"Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(0,0,0))
player:set_bone_position("Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(0,0,0))
player:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(0,0,0))
end
if controls.sneak and player:get_attach() == nil then
-- controls head pitch when sneaking
set_bone_position_conditional(player,"Head", vector.new(0,6.3,0), vector.new(pitch+36,0,0))
player:set_bone_position("Head", vector.new(0,6.3,0), vector.new(pitch+36,0,0))
-- sets eye height, and nametag color accordingly
set_properties_conditional(player,{collisionbox = {-0.35,0,-0.35,0.35,1.8,0.35}, eye_height = 1.35, nametag_color = { r = 225, b = 225, a = 0, g = 225 }})
player:set_properties({collisionbox = {-0.35,0,-0.35,0.35,1.8,0.35}, eye_height = 1.35, nametag_color = { r = 225, b = 225, a = 0, g = 225 }})
-- sneaking body conrols
set_bone_position_conditional(player,"Body_Control", vector.new(0,6.3,0), vector.new(0,0,0))
player:set_bone_position("Body_Control", vector.new(0,6.3,0), vector.new(0,0,0))
elseif minetest.get_item_group(mcl_playerinfo[name].node_head, "water") ~= 0 and player:get_attach() == nil and mcl_sprint.is_sprinting(name) == true then
-- set head pitch and yaw when swimming
set_bone_position_conditional(player,"Head", vector.new(0,6.3,0), vector.new(pitch+90-degrees(dir_to_pitch(player_velocity)),yaw - player_vel_yaw * -1,0))
player:set_bone_position("Head", vector.new(0,6.3,0), vector.new(pitch+90-degrees(dir_to_pitch(player_velocity)),yaw - player_vel_yaw * -1,0))
-- sets eye height, and nametag color accordingly
set_properties_conditional(player,{collisionbox = {-0.35,0,-0.35,0.35,0.8,0.35}, eye_height = 0.65, nametag_color = { r = 225, b = 225, a = 225, g = 225 }})
player:set_properties({collisionbox = {-0.35,0,-0.35,0.35,0.8,0.35}, eye_height = 0.65, nametag_color = { r = 225, b = 225, a = 225, g = 225 }})
-- control body bone when swimming
set_bone_position_conditional(player,"Body_Control", vector.new(0,6.3,0), vector.new(degrees(dir_to_pitch(player_velocity)) - 90,player_vel_yaw * -1 - yaw + 180,0))
player:set_bone_position("Body_Control", vector.new(0,6.3,0), vector.new(degrees(dir_to_pitch(player_velocity)) - 90,player_vel_yaw * -1 - yaw + 180,0))
elseif player:get_attach() == nil then
-- sets eye height, and nametag color accordingly
set_properties_conditional(player,{collisionbox = {-0.35,0,-0.35,0.35,1.8,0.35}, eye_height = 1.65, nametag_color = { r = 225, b = 225, a = 225, g = 225 }})
player:set_properties({collisionbox = {-0.35,0,-0.35,0.35,1.8,0.35}, eye_height = 1.65, nametag_color = { r = 225, b = 225, a = 225, g = 225 }})
if player_velocity.x > 0.35 or player_velocity.z > 0.35 or player_velocity.x < -0.35 or player_velocity.z < -0.35 then
if player_vel_yaw * -1 - yaw < 90 or player_vel_yaw * -1 - yaw > 270 then
-- controls head and Body_Control bones while moving backwards
set_bone_position_conditional(player,"Head", vector.new(0,6.3,0), vector.new(pitch,yaw - player_vel_yaw * -1,0))
set_bone_position_conditional(player,"Body_Control", vector.new(0,6.3,0), vector.new(0,player_vel_yaw * -1 - yaw,0))
player:set_bone_position("Head", vector.new(0,6.3,0), vector.new(pitch,yaw - player_vel_yaw * -1,0))
player:set_bone_position("Body_Control", vector.new(0,6.3,0), vector.new(0,player_vel_yaw * -1 - yaw,0))
else
-- controls head and Body_Control bones while moving forwards
set_bone_position_conditional(player,"Head", vector.new(0,6.3,0), vector.new(pitch,yaw - player_vel_yaw * -1 + 180,0))
set_bone_position_conditional(player,"Body_Control", vector.new(0,6.3,0), vector.new(0,player_vel_yaw * -1 - yaw + 180,0))
player:set_bone_position("Head", vector.new(0,6.3,0), vector.new(pitch,yaw - player_vel_yaw * -1 + 180,0))
player:set_bone_position("Body_Control", vector.new(0,6.3,0), vector.new(0,player_vel_yaw * -1 - yaw + 180,0))
end
else
set_bone_position_conditional(player,"Head", vector.new(0,6.3,0), vector.new(pitch,0,0))
set_bone_position_conditional(player,"Body_Control", vector.new(0,6.3,0), vector.new(0,0,0))
player:set_bone_position("Head", vector.new(0,6.3,0), vector.new(pitch,0,0))
player:set_bone_position("Body_Control", vector.new(0,6.3,0), vector.new(0,0,0))
end
else
local attached = player:get_attach(parent)
local attached_yaw = degrees(attached:get_yaw())
set_properties_conditional(player,{collisionbox = {-0.35,0,-0.35,0.35,1.8,0.35}, eye_height = 1.65, nametag_color = { r = 225, b = 225, a = 225, g = 225 }})
set_bone_position_conditional(player,"Head", vector.new(0,6.3,0), vector.new(pitch,degrees(player:get_look_horizontal()) * -1 + attached_yaw,0))
set_bone_position_conditional(player,"Body_Control", vector.new(0,6.3,0), vector.new(0,0,0))
player:set_properties({collisionbox = {-0.35,0,-0.35,0.35,1.8,0.35}, eye_height = 1.65, nametag_color = { r = 225, b = 225, a = 225, g = 225 }})
player:set_bone_position("Head", vector.new(0,6.3,0), vector.new(pitch,degrees(player:get_look_horizontal()) * -1 + attached_yaw,0))
player:set_bone_position("Body_Control", vector.new(0,6.3,0), vector.new(0,0,0))
end
if mcl_playerplus_internal[name].jump_cooldown > 0 then

View File

@ -70,22 +70,8 @@ minetest.register_on_joinplayer(function(player)
local name = player:get_player_name()
wieldview.wielded_item[name] = ""
minetest.after(0, function(player)
-- When a player joins and immediately leaves the game
-- before this function is called by minetest.after(),
-- the player object is invalidated. This results in
-- its methods returning nil (since Minetest 5.2);
-- perhaps surprisingly, the player is not nil.
--
-- Not checking that the position is not nil can lead
-- to a server crash if a client crashes while it is
-- joining. It has been reported that a syntax error
-- in a client side mod was enough to trigger that.
local pos = player:get_pos()
if pos == nil then
return
end
wieldview:update_wielded_item(player)
local itementity = minetest.add_entity(pos, "wieldview:wieldnode")
local itementity = minetest.add_entity(player:get_pos(), "wieldview:wieldnode")
itementity:set_attach(player, "Hand_Right", vector.new(0, 0, 0), vector.new(15, 45, 0))
itementity:get_luaentity().wielder = name
end, player)

View File

@ -91,11 +91,6 @@ flame_sound (Flame sound) bool true
# Form: Image height / Image width
fire_animation_frames (Fire Animation Frames) int 8
# How long to wait between frames of the fire animation in frames per second.
# A higher number means it looks better but also results in a lot of additional network traffic. A low single digit value is recommended for multiplayer.
#(default: 30)
fire_animation_fps (Fire Animation FPS) int 30 0 60
# Whether to animate chests when open / close
animated_chests (Animated chests) bool true