liblevelup/init.lua

180 lines
7.0 KiB
Lua

-- liblevelup mod for Minetest
-- Copyright © 2017-2019 Alex Yst <mailto:copyright@y.st>
-- 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.
-- This software is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- Lesser General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public
-- License along with this program. If not, see
-- <https://www.gnu.org./licenses/>.
dofile(minetest.get_modpath("liblevelup").."/API.lua")
-- This constant tells other mods that depend on this one that the
-- minerals, saplings, seeds, and spores from Minetest Game versions
-- 0.4.0 through 5.4.1, Minimal 0.4.0 through 5.2.0, Development Test
-- 5.3.0 through 5.4.2, Build 0.4.6, and Survival 0.4.6 are properly
-- detected. Each time a new version of the engine is released with
-- corresponding versions of is official subgames, this number will be
-- incremented by one. Normally, it's best to compare using the
-- greater-than-or-equal-to operator. All past versions of the official
-- subgames will remain supported, so it doesn't make sense to require
-- an exact match when determining whether this mod has support for
-- detecting the countables in a given Minetest Game version.
--
-- Version 0.4.0 was the first to support mods, and corresponds to 0 as
-- this mod's detection level for that version. There have been 27
-- versions released since then, all of which are properly detected
-- with the below algorithm, so we're now at detection level 27. (This
-- is Development Test version 5.4.2; this engine version has no
-- corresponding Minetest Game version.)
liblevelup.meta.minetest_game_detection = 27
local debug_table = false
-- Uncomment this line for testing.
--debug_table = dofile(minetest.get_modpath("liblevelup").."/debug.lua")
local function generic_default_is_countable_function(node_string, drops, drop_opts, drop_key)
-- If multiple items are dropped, this is probably something we should
-- count.
if #drops > 1 then
return true
end
local drop_stack = ItemStack(drops[1])
local drop_def = drop_stack:get_definition()
local node_stack = ItemStack(node_string)
local node_def = node_stack:get_definition()
if drop_def.type ~= "node" then
-- If it's not a node and doesn't place as a node, count it.
if drop_def.on_place == minetest.craftitemdef_default.on_place then
return true
-- If it's not a node but does place as one, it's probably a door or a
-- 0.4.7 seed.
--
-- Seeds should be counted if they're dropped by non-farm plants,
-- dropped in multiples, or dropped along with other items. If dropped
-- with other items, they'll be taken care of by an above block.
else
-- Doors can be interacted with, so check for that.
if node_def.on_rightclick then
return false
end
-- Checking for multiples is easy.
if drop_stack:get_count() > 1 then
return true
end
-- Checking for farm plants isn't so easy. What we want to determine is
-- whether the single seed came from a plant that can be grown from
-- that single seed, but there's no way to do this as growth is handled
-- in another function, not handled by a string property of the seed.
-- Instead, we check to see if the plant's drop table seems similar to
-- that of a farm plant, and if it is, assume the seed-like item it
-- dropped was the single seed needed to regrow that same plant.
--
-- Basically, wild grasses tend to drop themselves if not their seed,
-- so only the grass *or* the seed will drop. This should be counted,
-- as the seed cannot be used to regrow the grass. Farm crops can drop
-- multiple items though, and they should all be counted unless only
-- one item drops and that one item is a single seed. This is because
-- that single seed could be converted back into the original farm
-- plant by planting it and waiting for it to grow, so it's not a true
-- drop.
if type(node_def.drop) == "table" and node_def.drop.max_items ~= 1 then
return false
end
return true
end
end
-- This prevents the catching of 0.4.0-style doors.
if node_def.legacy_wallmounted then
return false
end
-- Nodes often get swapped for other nodes when interacted with, while
-- the new nodes drop the original ones for better stacking. This is
-- case with doors, gates, and chests, for example.
if drop_def.on_rightclick then
return false
end
-- Prevent grass from being caught.
if node_def.drawtype ~= "normal" and node_def.drawtype == drop_def.drawtype then
-- This prevents catching of 0.4.15 xpanes. Again, xpanes are a pain.
if node_def.drawtype == "nodebox" then
return false
end
-- We still want to catch mushrooms though.
if node_def.tiles and node_def.tiles[1] == drop_def.tiles[1] then
return true
else
return false
end
end
-- The only way to prevent catching wet-soil-to-dirt drops when dealing
-- with 0.4.7 soil without hard-coding specific node names seems to be
-- to hard-code the soil group, which is far from ideal.
if minetest.get_item_group(node_stack:get_name(), "soil") > minetest.get_item_group(drop_stack:get_name(), "soil") then
return false
end
-- xpanes are such a pain. This check for the "airlike" draw type
-- prevents catching of 0.4.10 xpanes.
if drop_def.drawtype == "airlike" then
return false
end
-- This catches things such as saplings and modern seeds. We don't want
-- to catch single seeds dropped by farm plants though.
if node_def.drawtype ~= drop_def.drawtype then
if drop_stack:get_count() > 1 then
return true
end
if type(node_def.drop) == "table" and node_def.drop.max_items ~= 1 then
return false
end
return true
end
local drop_tiles = drop_def.tiles or drop_def.tile_images or {}
local node_tiles = node_def.tiles or node_def.tile_images or {}
if #drop_tiles == 1 then
-- This catches ice.
if #node_tiles == 1 then
return true
end
-- This catches sand without catching dirt.
for _, tile in next, node_tiles do
if tile:split("^")[1] == drop_tiles[1] then
-- Instead of outright rejecting dirt though, we need to see if the
-- dirt likely converts itself to other forms. That lets us catch dry
-- dirt without catching regular dirt.
for _, def in next, minetest.registered_abms do
for _, node in next, def.nodenames do
if node == drops[1] then
return false
end
end
end
return true
end
end
return true
end
end
if debug_table then
-- For debugging purposes
liblevelup.register.is_countable(function(node_string, drop, drop_opts, drop_key)
local result = generic_default_is_countable_function(node_string, drop, drop_opts, drop_key)
local key = "["..node_string.."]["..drop_key.."]"
if debug_table[key] == nil or debug_table[key] ~= result then
minetest.debug(key.." => "..dump(result == true))
end
return result
end)
else
liblevelup.register.is_countable(generic_default_is_countable_function)
end