1
0
mirror of https://github.com/mt-mods/unifieddyes.git synced 2025-06-28 14:26:21 +02:00

Compare commits

..

10 Commits

Author SHA1 Message Date
409ee441c4 respect protection 2018-08-26 08:59:28 -04:00
ca1ab44e78 add recipe for airbrush 2018-08-26 08:41:04 -04:00
e13d514ff7 allow shift-punch for airbrush form 2018-08-26 08:28:56 -04:00
fa71e3166c allow replacement nodes during airbrushing 2018-08-26 07:23:40 -04:00
414d72d2a6 new punch-to-colorize scheme
using a tool, the airbrush, for the job

point at air/nothing and punch while wielding the airbrush
to open the color selection form.
2018-08-26 07:10:00 -04:00
568168fe1f better handling of the register_on_placenode rotation fix 2018-08-26 07:09:20 -04:00
c005dc358a minor changes to colorwallmounted palette
got rid of the separate brown swatch in the colorwallmounted palette, as
it was being bypassed by the brown-> medium orange translation --
replaced it with light green.

fixed missing colorwallmounted light blue/azure check-and-return in
get_paletteidx()
2018-08-25 02:40:17 -04:00
c7fc48c8d0 fix some broken aliases,
add some corresponding ones (unifieddyes:* vs. dye:*)
2018-08-25 00:38:24 -04:00
de5f73e976 clarify usage of make_colored_itemstack() 2018-08-24 23:53:53 -04:00
0d00a7eae6 workaround for placing nodes with no color info in itemstack 2018-08-24 11:13:42 -04:00
7 changed files with 365 additions and 30 deletions

11
API.md
View File

@ -13,6 +13,7 @@ minetest.register_node("mymod:colored_node", {
palette = "unifieddyes_palette_extended.png", palette = "unifieddyes_palette_extended.png",
groups = {snappy = 1, cracky = 2, ud_param2_colorable = 1} groups = {snappy = 1, cracky = 2, ud_param2_colorable = 1}
on_construct = unifieddyes.on_construct, on_construct = unifieddyes.on_construct,
airbrush_replacement_node = "mymod:my_other_colored_node"
}) })
``` ```
@ -31,6 +32,8 @@ minetest.register_node("mymod:colored_node", {
`on_construct`: see below. `on_construct`: see below.
`airbrush_replacement_node`: The node to swap in when the airbrush is used on this node. For example, you could `minetest.override_item()` on some default node to add this field, pointing to a colorable node of your own, so that when the default node is painted, it's replaced with yours in the new color.
#### Function calls #### Function calls
**`unifieddyes.fix_rotation(pos, placer, itemstack, pointed_thing)` **`unifieddyes.fix_rotation(pos, placer, itemstack, pointed_thing)`
@ -42,10 +45,6 @@ These two are used to re-orient `wallmounted` nodes after placing. The former al
This serves the same purpose as the `fix_rotation_nsew`, but is used to restrict the node's rotation after it's been hit with the screwdriver. This serves the same purpose as the `fix_rotation_nsew`, but is used to restrict the node's rotation after it's been hit with the screwdriver.
**`unifieddyes.select_node(pointed_thing)`**
Just what it says on the tin. :-) This function returns a position and node definition of whatever is being pointed at.
**`unifieddyes.is_buildable_to(placer_name, ...)`** **`unifieddyes.is_buildable_to(placer_name, ...)`**
Again, another obvious one, returns whether or not the pointed node is `buildable_to` (can be overwritten by another node). Again, another obvious one, returns whether or not the pointed node is `buildable_to` (can be overwritten by another node).
@ -77,6 +76,10 @@ When given a `color` string (in the form of "dye:foo" or "unifieddyes:foo") and
This function, called in your node definition's on_construct, just sets the `palette = "ext"` metadata key for the node after it's been placed. This can then be read in an LBM to determine if this node needs to be converted from the old 89-color palette to the extended 256-color palette. Although it is good practice to call this for any node that uses the 256-color palette, it isn't actually necessary as long as the node has never used the 89-color palette, and won't be subjected to an LBM that changes its color. This function, called in your node definition's on_construct, just sets the `palette = "ext"` metadata key for the node after it's been placed. This can then be read in an LBM to determine if this node needs to be converted from the old 89-color palette to the extended 256-color palette. Although it is good practice to call this for any node that uses the 256-color palette, it isn't actually necessary as long as the node has never used the 89-color palette, and won't be subjected to an LBM that changes its color.
**`unifieddyes.make_colored_itemstack(itemstack, palette, color)`**
Makes a colored itemstack out of the given `itemstack` and `color` (as a dye, e.g. "dye:dark_red_s50", setting the correct index per the `palette` field, which works as described above for `unifieddyes.getpaletteidx()`. Said itemstack is returned as a string suitable for use as the output field of a craft recipe, equal in size to the itemstack passed into the function (e.g. if you give it "mymod:colored_node 7", it'll return a stack of 7 colored items).
#### Tables #### Tables
In addition to the above API calls, Unified Dyes provides several useful tables In addition to the above API calls, Unified Dyes provides several useful tables

384
init.lua
View File

@ -153,6 +153,42 @@ local default_dyes = {
"yellow" "yellow"
} }
unifieddyes.player_current_dye = {}
unifieddyes.player_selected_dye = {}
-- if a node with a palette is placed in the world,
-- but the itemstack used to place it has no palette_index (color byte),
-- create something appropriate to make it officially white.
minetest.register_on_placenode(
function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
local def = minetest.registered_items[newnode.name]
if not def
or not def.palette
or def.after_place_node then
return false
end
if not string.find(itemstack:to_string(), "palette_index") then
local param2 = 0
local color = 0
if def.palette == "unifieddyes_palette_extended.png" then
param2 = 240
color = 240
elseif def.palette == "unifieddyes_palette_colorwallmounted.png" then
param2 = newnode.param2 % 8
elseif def.palette ~= "unifieddyes_palette.png" then -- it's a split palette
param2 = newnode.param2 % 32
end
minetest.swap_node(pos, {name = newnode.name, param2 = param2})
minetest.get_meta(pos):set_int("palette_index", color)
end
end
)
-- just stubs to keep old mods from crashing when expecting auto-coloring -- just stubs to keep old mods from crashing when expecting auto-coloring
-- or getting back the dye on dig. -- or getting back the dye on dig.
@ -168,7 +204,7 @@ function unifieddyes.make_colored_itemstack(item, palette, color)
local paletteidx = unifieddyes.getpaletteidx(color, palette) local paletteidx = unifieddyes.getpaletteidx(color, palette)
local stack = ItemStack(item) local stack = ItemStack(item)
stack:get_meta():set_int("palette_index", paletteidx) stack:get_meta():set_int("palette_index", paletteidx)
return stack:to_string() return stack:to_string(),paletteidx
end end
-- if your node was once 89-color and uses an LBM to convert to the 256-color palette, -- if your node was once 89-color and uses an LBM to convert to the 256-color palette,
@ -195,7 +231,6 @@ local function register_c(craft, hue, sat, val)
end end
local dye = "dye:"..color local dye = "dye:"..color
local recipe = minetest.serialize(craft.recipe) local recipe = minetest.serialize(craft.recipe)
recipe = string.gsub(recipe, "MAIN_DYE", dye) recipe = string.gsub(recipe, "MAIN_DYE", dye)
recipe = string.gsub(recipe, "NEUTRAL_NODE", craft.neutral_node) recipe = string.gsub(recipe, "NEUTRAL_NODE", craft.neutral_node)
@ -235,6 +270,8 @@ function unifieddyes.register_color_craft(craft)
local greys_table = unifieddyes.GREYS local greys_table = unifieddyes.GREYS
if craft.palette == "wallmounted" then if craft.palette == "wallmounted" then
register_c(craft, "green", "", "light_")
register_c(craft, "azure", "", "")
hues_table = unifieddyes.HUES_WALLMOUNTED hues_table = unifieddyes.HUES_WALLMOUNTED
sats_table = {""} sats_table = {""}
vals_table = unifieddyes.VALS vals_table = unifieddyes.VALS
@ -310,19 +347,6 @@ function unifieddyes.fix_after_screwdriver_nsew(pos, node, user, mode, new_param
end end
end end
function unifieddyes.select_node(pointed_thing)
local pos = pointed_thing.under
local node = minetest.get_node_or_nil(pos)
local def = node and minetest.registered_nodes[node.name]
if not def or not def.buildable_to then
pos = pointed_thing.above
node = minetest.get_node_or_nil(pos)
def = node and minetest.registered_nodes[node.name]
end
return def and pos, def
end
function unifieddyes.is_buildable_to(placer_name, ...) function unifieddyes.is_buildable_to(placer_name, ...)
for _, pos in ipairs({...}) do for _, pos in ipairs({...}) do
local node = minetest.get_node_or_nil(pos) local node = minetest.get_node_or_nil(pos)
@ -381,6 +405,7 @@ function unifieddyes.getpaletteidx(color, palette_type)
local aliases = { local aliases = {
["pink"] = "light_red", ["pink"] = "light_red",
["brown"] = "medium_orange", ["brown"] = "medium_orange",
["azure"] = "light_blue"
} }
local grayscale = { local grayscale = {
@ -555,9 +580,10 @@ function unifieddyes.getpaletteidx(color, palette_type)
end end
if palette_type == "wallmounted" then if palette_type == "wallmounted" then
if color == "brown" then return 48,1 if color == "green" and shade == "light" then return 48,3
elseif color == "brown" then return 17,1
elseif color == "pink" then return 56,7 elseif color == "pink" then return 56,7
elseif color == "blue" and shade == "light" then return 40,5 elseif color == "azure" then return 40,5
elseif hues_wallmounted[color] and shades_wallmounted[shade] then elseif hues_wallmounted[color] and shades_wallmounted[shade] then
return (shades_wallmounted[shade] * 64 + hues_wallmounted[color] * 8), hues_wallmounted[color] return (shades_wallmounted[shade] * 64 + hues_wallmounted[color] * 8), hues_wallmounted[color]
end end
@ -569,7 +595,20 @@ function unifieddyes.getpaletteidx(color, palette_type)
color = "red" color = "red"
shade = "light" shade = "light"
end end
if palette_type == true then -- it's colorfacedir if palette_type == true then -- it's colorfacedir, so "split" 89-color palette
-- If using this palette, translate new color names back to old.
if shade == "" then
if color == "spring" then
color = "aqua"
elseif color == "azure" then
color = "skyblue"
elseif color == "rose" then
color = "redviolet"
end
end
if hues[color] and shades[shade] then if hues[color] and shades[shade] then
return (shades[shade] * 32), hues[color] return (shades[shade] * 32), hues[color]
end end
@ -577,10 +616,7 @@ function unifieddyes.getpaletteidx(color, palette_type)
if hues_extended[color] and shades_extended[shade] then if hues_extended[color] and shades_extended[shade] then
return (hues_extended[color] + shades_extended[shade]*24), hues_extended[color] return (hues_extended[color] + shades_extended[shade]*24), hues_extended[color]
end end
else -- it's the 89-color palette else -- it's the regular 89-color palette, do the same translation if needed
-- If using this palette, translate new color names back to old.
if shade == "" then if shade == "" then
if color == "spring" then if color == "spring" then
color = "aqua" color = "aqua"
@ -597,6 +633,294 @@ function unifieddyes.getpaletteidx(color, palette_type)
end end
end end
-- punch-to-recolor using the airbrush
function unifieddyes.on_airbrush(itemstack, player, pointed_thing)
local player_name = player:get_player_name()
local painting_with = nil
if unifieddyes.player_current_dye[player_name] and minetest.registered_items[unifieddyes.player_current_dye[player_name]] then
painting_with = unifieddyes.player_current_dye[player_name]
end
local pos = minetest.get_pointed_thing_position(pointed_thing)
if not pos or player:get_player_control().sneak then
unifieddyes.show_airbrush_form(player)
return
end
if not painting_with then return end
local node = minetest.get_node(pos)
local def = minetest.registered_items[node.name]
if not def then return end
if minetest.is_protected(pos, player_name) then
minetest.chat_send_player(player_name, "Sorry, someone else owns that node.")
return
end
if not def.palette then
minetest.chat_send_player(player_name, "That node can't be colored.")
return
end
local palette = nil
local fdir = 0
if def.palette == "unifieddyes_palette_extended.png" then
palette = "extended"
elseif def.palette == "unifieddyes_palette_colorwallmounted.png" then
palette = "wallmounted"
fdir = node.param2 % 8
elseif def.palette ~= "unifieddyes_palette.png" then
palette = true
fdir = node.param2 % 32
end
local idx, hue = unifieddyes.getpaletteidx(painting_with, palette)
local inv = player:get_inventory()
if (not creative or not creative.is_enabled_for(player_name)) and not inv:contains_item("main", painting_with) then
local suff = ""
if not idx then
suff = " Besides, "..string.sub(painting_with, 5).." can't be applied to that node."
end
minetest.chat_send_player(player_name, "You're in survival mode, and you're out of "..string.sub(painting_with, 5).."."..suff)
return
end
if not idx then
minetest.chat_send_player(player_name, string.sub(painting_with, 5).." can't be applied to that node.")
return
end
local oldidx = node.param2 - fdir
if idx == oldidx then
minetest.chat_send_player(player_name, "That node is already "..string.sub(painting_with, 5)..".")
return
end
local name = def.airbrush_replacement_node or node.name
minetest.swap_node(pos, {name = name, param2 = fdir + idx})
if not creative or not creative.is_enabled_for(player_name) then
inv:remove_item("main", painting_with)
return
end
end
function unifieddyes.show_airbrush_form(player)
if not player then return end
local player_name = player:get_player_name()
local creative = creative and creative.is_enabled_for(player_name)
local inv = player:get_inventory()
local base_form = "size[15,8.5]label[7,-0.25;Select a color:]"
local size="0.75,0.75;"
local hps=0.6
local vps=1.3
local vs=0.3
for v = 0, 6 do
local val = unifieddyes.VALS_EXTENDED[v+1]
local sat = ""
local v2=(v/2)
for hi, h in ipairs(unifieddyes.HUES_EXTENDED) do
local hue = h[1]
local hp=hi-0.5
local r = h[2]
local g = h[3]
local b = h[4]
local factor = 40
if v > 3 then
factor = 75
v2 = (v-2)
end
local r2 = math.max(math.min(r + (4-v)*factor, 255), 0)
local g2 = math.max(math.min(g + (4-v)*factor, 255), 0)
local b2 = math.max(math.min(b + (4-v)*factor, 255), 0)
local color = string.format("%02x", r2)..string.format("%02x", g2)..string.format("%02x", b2)
local dye = "dye:"..val..hue..sat
local overlay = ""
if not creative and inv:contains_item("main", dye) then
overlay = "^unifieddyes_available_overlay.png"
end
if dye == unifieddyes.player_selected_dye[player_name] then
overlay = "^unifieddyes_select_overlay.png"
end
local colorize = minetest.formspec_escape("^[colorize:#"..color..":255")
base_form = base_form.."image_button["..
(hp*hps)..","..(v2*vps+vs)..";"..
size..
"unifieddyes_white_square.png"..colorize..overlay..";"..
val..hue..sat..";]"..
"tooltip["..val..hue..sat..";"..val..hue..sat.."]"
end
if v > 3 then
sat = "_s50"
v2 = (v-1.5)
for hi, h in ipairs(unifieddyes.HUES_EXTENDED) do
local hue = h[1]
local hp=hi-0.5
local r = h[2]
local g = h[3]
local b = h[4]
local factor = 75
local pr = 0.299
local pg = 0.587
local pb = 0.114
local r2 = math.max(math.min(r + (4-v)*factor, 255), 0)
local g2 = math.max(math.min(g + (4-v)*factor, 255), 0)
local b2 = math.max(math.min(b + (4-v)*factor, 255), 0)
local p = math.sqrt(r2*r2*pr + g2*g2*pg + b2*b2*pb)
local r3 = math.floor(p+(r2-p)*0.5)
local g3 = math.floor(p+(g2-p)*0.5)
local b3 = math.floor(p+(b2-p)*0.5)
local color = string.format("%02x", r3)..string.format("%02x", g3)..string.format("%02x", b3)
local dye = "dye:"..val..hue..sat
local overlay = ""
if not creative and inv:contains_item("main", dye) then
overlay = "^unifieddyes_available_overlay.png"
end
if dye == unifieddyes.player_selected_dye[player_name] then
overlay = "^unifieddyes_select_overlay.png"
end
local colorize = minetest.formspec_escape("^[colorize:#"..color..":255")
base_form = base_form.."image_button["..
(hp*hps)..","..(v2*vps+vs)..";"..
size..
"unifieddyes_white_square.png"..colorize..overlay..";"..
val..hue..sat..";]"..
"tooltip["..val..hue..sat..";"..val..hue..sat.."]"
end
end
end
local v2=5
for y = 0, 15 do
local hp=(15-y)+0.5
local grey = string.format("%02x", y*17)..string.format("%02x", y*17)..string.format("%02x", y*17)
local grey2 = "grey_"..y
if y == 0 then grey2 = "black"
elseif y == 4 then grey2 = "dark_grey"
elseif y == 8 then grey2 = "grey"
elseif y == 11 then grey2 = "light_grey"
elseif y == 15 then grey2 = "white"
end
local dye = "dye:"..grey2
local overlay = ""
if not creative and inv:contains_item("main", dye) then
overlay = "^unifieddyes_available_overlay.png"
end
if dye == unifieddyes.player_selected_dye[player_name] then
overlay = "^unifieddyes_select_overlay.png"
end
local colorize = minetest.formspec_escape("^[colorize:#"..grey..":255")
base_form = base_form.."image_button["..
(hp*hps)..","..(v2*vps+vs)..";"..
size..
"unifieddyes_white_square.png"..colorize..overlay..";"..
grey2..";]tooltip["..grey2..";"..grey2.."]"
end
if not creative then
base_form = base_form..
"image[10.3,"..(vps*5+vs)..";"..size..
"unifieddyes_available_overlay.png]"..
"label[11.0,"..(vps*5.1+vs)..";Dyes on hand]"..
"image[12.5,"..(vps*5+vs)..";"..size..
"unifieddyes_select_overlay.png]"..
"label[13.2,"..(vps*5.1+vs)..";Your selection]"
end
base_form = base_form..
"button_exit[11,8;2,1;cancel;Cancel]"..
"button_exit[13,8;2,1;accept;Accept]"
if unifieddyes.player_selected_dye[player_name] then
base_form = base_form..
"label[1,"..(7.5+vs)..";Selected dye: "..
unifieddyes.player_selected_dye[player_name].."]"
end
minetest.show_formspec(player_name, "unifieddyes:dye_select_form", base_form)
end
minetest.register_tool("unifieddyes:airbrush", {
description = S("Dye Airbrush"),
inventory_image = "unifieddyes_airbrush.png",
use_texture_alpha = true,
tool_capabilities = {
full_punch_interval=0.1,
},
range = 12,
on_use = unifieddyes.on_airbrush
})
minetest.register_craft( {
output = "unifieddyes:airbrush",
recipe = {
{ "default:gold_ingot", "", "bucket:bucket_empty" },
{ "", "default:steel_ingot", "" },
{ "", "", "default:steel_ingot" }
},
})
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname == "unifieddyes:dye_select_form" then
local player_name = player:get_player_name()
local s1 = string.sub(minetest.serialize(fields), 11)
local s3 = string.sub(s1,1, string.find(s1, '"')-1)
if s3 == "cancel" then
unifieddyes.player_selected_dye[player_name] = nil
return
elseif s3 == "accept" and unifieddyes.player_selected_dye[player_name] then
local dye = unifieddyes.player_selected_dye[player_name]
unifieddyes.player_current_dye[player_name] = dye
unifieddyes.player_selected_dye[player_name] = nil
minetest.chat_send_player(player_name, "Selected "..string.sub(dye, 5).." for the airbrush.")
return
else
local inv = player:get_inventory()
local creative = creative and creative.is_enabled_for(player_name)
local dye = "dye:"..s3
if minetest.registered_items[dye] and (creative or inv:contains_item("main", dye)) then
unifieddyes.player_selected_dye[player_name] = dye
unifieddyes.show_airbrush_form(player)
end
end
end
end)
-- build a table to convert from classic/89-color palette to extended palette -- build a table to convert from classic/89-color palette to extended palette
-- the first five entries are for the old greyscale - white, light, grey, dark, black -- the first five entries are for the old greyscale - white, light, grey, dark, black
@ -882,6 +1206,8 @@ minetest.register_craft( {
}, },
}) })
-- aliases
minetest.register_alias("dye:light_red", "dye:pink") minetest.register_alias("dye:light_red", "dye:pink")
minetest.register_alias("dye:medium_orange", "dye:brown") minetest.register_alias("dye:medium_orange", "dye:brown")
@ -908,10 +1234,16 @@ minetest.register_alias("unifieddyes:carbon_black", "dye:black")
-- note that technically, lime should be aliased, but can't be (there IS -- note that technically, lime should be aliased, but can't be (there IS
-- lime in the new color table, it's just shifted up a bit) -- lime in the new color table, it's just shifted up a bit)
minetest.register_alias("unifieddyes:aqua", "unifieddyes:spring") minetest.register_alias("unifieddyes:aqua", "dye:spring")
minetest.register_alias("unifieddyes:skyblue", "unifieddyes:azure") minetest.register_alias("dye:aqua", "dye:spring")
minetest.register_alias("unifieddyes:redviolet", "unifieddyes:rose")
minetest.register_alias("unifieddyes:brown", "dye:brown") minetest.register_alias("unifieddyes:skyblue", "dye:azure")
minetest.register_alias("dye:skyblue", "dye:azure")
minetest.register_alias("unifieddyes:redviolet", "dye:rose")
minetest.register_alias("dye:redviolet", "dye:rose")
minetest.register_alias("unifieddyes:brown", "dye:brown")
print(S("[UnifiedDyes] Loaded!")) print(S("[UnifiedDyes] Loaded!"))

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 B

After

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 B