Files

203 lines
7.4 KiB
Lua

--[[
Raw Ore Blocks — adds block forms of metal lumps to Luanti
Copyright © 2022-2026, Silver Sandstone <@SilverSandstone@craftodon.social>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
]]
--- Public API functions.
-- @module api
local S = core.get_translator('lumpblocks');
local get_sounds;
if core.get_modpath('default') then
get_sounds = default.node_sound_metal_defaults or default.node_sound_stone_defaults;
elseif core.get_modpath('mcl_sounds') then
get_sounds = mcl_sounds.node_sounds_metal_defaults;
elseif core.get_modpath('rp_sounds') then
get_sounds = rp_sounds.node_sound_defaults;
end;
if not get_sounds then
function get_sounds(sounds)
return sounds or {};
end;
end;
local function update(dest, ...)
for index = 1, select('#', ...) do
local src = select(index, ...);
if src then
for key, value in pairs(src) do
dest[key] = value;
end;
end;
end;
return dest;
end;
--- Registers a raw ore block.
-- @param name [string] The name of the raw ore block to register.
-- @param options [table] A table of options.
-- @param options.lump [string] The name of the lump item.
-- @param options.texture [string] Overrides the node's texture.
-- @param options.light_colour [ColourSpec] The lighter colour of the texture.
-- @param options.dark_colour [ColourSpec] The darker (or only) colour of the texture.
-- @param options.colour [ColourSpec] Alias for `dark_colour`.
-- @param options.colours [ColourSpec[2]] A table of {dark_colour, light_colour}.
-- @param options.description [string] Overrides the node's description.
-- @param options.groups [{string: integer}] Overrides the node's groups.
-- @param options.def [NodeDef] Overrides arbitrary properties of the node's definition.
-- @return [string|nil] The name of the registered node, or nil on failure.
function lumpblocks.register_lump_block(name, options)
if type(name) == 'table' then
options = name;
name = nil;
end;
local lump_name;
local texture;
local dark_colour;
local light_colour;
local description;
local override;
local groups = {};
for key, value in pairs(options) do
if key == 'base_name' or key == 1 then
name = ('lumpblocks:%s_block'):format(value);
elseif key == 'lump' or key == 2 then
lump_name = value;
elseif key == 'name' then
name = value;
elseif key == 'texture' then
texture = value;
elseif key == 'dark_colour' or key == 'colour' then
dark_colour = value;
elseif key == 'light_colour' then
light_colour = value;
elseif key == 'colours' then
dark_colour, light_colour = unpack(value);
elseif key == 'description' then
description = value;
elseif key == 'def' then
override = value;
elseif key == 'groups' then
groups = value;
else
core.log('error', ('Invalid key [%q] in lumpblocks.register_lump_block().'):format(key));
end;
end;
assert(name, 'No block name specified!');
assert(lump_name, 'No lump name specified!');
assert(texture or dark_colour, 'No texture or colour specified!');
local lump_def = core.registered_items[lump_name];
if not lump_def then
return nil;
end;
local def = {};
def.description = description or S('@1 Block', lump_def.description);
def.groups = update({cracky = 3, lump_block = 1}, groups);
def.tiles = {texture or lumpblocks.generate_lumpblock_texture(dark_colour, light_colour)};
def.sounds = update(get_sounds(), options.sounds);
def._doc_items_longdesc = S('A compressed block form of @1 for decoration or efficient storage.', lump_def.description);
update(def, override);
core.register_node(':' .. name, def);
-- Crafting recipes:
core.register_craft(
{
output = name;
recipe =
{
{lump_name, lump_name, lump_name},
{lump_name, lump_name, lump_name},
{lump_name, lump_name, lump_name},
};
});
core.register_craft(
{
type = 'shapeless';
output = lump_name .. ' 9';
recipe = {name};
});
if core.get_modpath('rp_crafting') then
crafting.register_craft(
{
output = name;
items = {lump_name .. ' 9'};
});
crafting.register_craft(
{
output = lump_name .. ' 9';
items = {name};
});
end;
return name;
end;
-- Generates a raw ore block texture in the specified colours.
-- @param dark_colour [ColourSpec] The darker (or only) colour.
-- @param light_colour [ColourSpec|nil] The lighter colour.
-- @return [string] A texture string.
function lumpblocks.generate_lumpblock_texture(dark_colour, light_colour)
assert(dark_colour, 'No colour specified!');
if light_colour then
-- Gradient-based colouring system:
dark_colour = core.colorspec_to_colorstring(dark_colour);
light_colour = core.colorspec_to_colorstring(light_colour);
local mask = 'lumpblocks_lump_block_mask.png';
return ('(%s^[multiply:#00000000^[invert:a^[colorize:%s:255)^(%s^[multiply:%s)'):format(mask, dark_colour, mask, light_colour);
else
-- Multiplication-based colouring system:
local colour = core.colorspec_to_colorstring(dark_colour);
local inverted = lumpblocks.invert_colour(colour);
local base = 'lumpblocks_lump_block.png';
return ('((%s^[invert:rgb)^[multiply:%s^[invert:rgb)^(%s^[multiply:%s^[opacity:127)'):format(base, inverted, base, colour);
end;
end;
--- Inverts a colour in RGB space.
-- @param colour [ColourSpec] The colour to invert.
-- @return [ColourString] The inverted colour.
function lumpblocks.invert_colour(colour)
local bytes = core.colorspec_to_bytes(colour);
local values = {nil, nil, nil, bytes:byte(4)};
for index = 1, 3 do
values[index] = 255 - bytes:byte(index);
end;
return ('#%02X%02X%02X%02X'):format(unpack(values));
end;