796 lines
29 KiB
Lua
796 lines
29 KiB
Lua
-- painting - in-game painting for minetest
|
|
|
|
-- THIS MOD CODE AND TEXTURES LICENSED
|
|
-- <3 TO YOU <3
|
|
-- UNDER TERMS OF WTFPL LICENSE
|
|
|
|
-- 2012, 2013, 2014 obneq aka jin xi
|
|
|
|
-- picture is drawn using a nodebox to draw the canvas
|
|
-- and an entity which has the painting as its texture.
|
|
-- this texture is created by minetests internal image
|
|
-- compositing engine (see tile.cpp).
|
|
|
|
-- Edited by Jasper den Ouden (a few commits now)
|
|
|
|
dofile(minetest.get_modpath("painting").."/crafts.lua")
|
|
|
|
local hexcols = {
|
|
white = "ffffff", yellow = "fff000",
|
|
orange = "ff6c00", red = "ff0000",
|
|
violet = "8a00ff", blue = "000cff",
|
|
green = "0cff00", magenta = "fc00ff",
|
|
cyan = "00ffea", grey = "bebebe",
|
|
dark_grey = "7b7b7b", black = "000000",
|
|
dark_green = "006400", brown="964b00",
|
|
pink = "ffc0cb"
|
|
}
|
|
|
|
local colors = {}
|
|
|
|
local revcolors = {
|
|
"white", "dark_green", "grey", "red", "brown", "cyan", "orange", "violet",
|
|
"dark_grey", "pink", "green", "magenta", "yellow", "black", "blue"
|
|
}
|
|
|
|
local thickness = 0.1
|
|
|
|
-- picture node
|
|
local picbox = {
|
|
type = "fixed",
|
|
fixed = { -0.499, -0.499, 0.499, 0.499, 0.499, 0.499 - thickness }
|
|
}
|
|
local picbox2 = {
|
|
type="fixed",
|
|
fixed={
|
|
{-0.5, -0.5, -0.5, 0.5, -0.5+thickness, 0.5},
|
|
{-0.5, -0.5, -0.5, -0.5, -0.39, 0.5},
|
|
{-0.5, -0.5, -0.5, 0.5, -0.39, -0.5},
|
|
{ 0.5, -0.5, 0.5, -0.5, -0.39, 0.5},
|
|
{ 0.5, -0.5, 0.5, 0.5, -0.39, -0.5}
|
|
}
|
|
}
|
|
|
|
local current_version = "0.1-juli"
|
|
local legacy = {}
|
|
|
|
-- puts the version before the data
|
|
local function get_metastring(data)
|
|
return current_version.."(version)"..data
|
|
end
|
|
|
|
-- Initiate a white grid.
|
|
local function initgrid(res)
|
|
local grid, a, x, y = {}, res-1
|
|
for x = 0, a do
|
|
grid[x] = {}
|
|
for y = 0, a do
|
|
grid[x][y] = colors["white"]
|
|
end
|
|
end
|
|
return grid
|
|
end
|
|
|
|
local function to_imagestring(data, res)
|
|
if not data then
|
|
minetest.log("error", "[painting] missing data")
|
|
return
|
|
end
|
|
local cols = {}
|
|
for y = 0, res - 1 do
|
|
local xs = data[y]
|
|
for x = 0, res - 1 do
|
|
local col = revcolors[xs[x]]
|
|
--if col ~= "white" then
|
|
cols[col] = cols[col] or {}
|
|
cols[col][#cols[col]+1] = {y, x}
|
|
--end
|
|
end
|
|
end
|
|
local t,n = {},1
|
|
local groupopen = "([combine:"..res.."x"..res
|
|
for colour,ps in pairs(cols) do
|
|
t[n] = groupopen
|
|
n = n+1
|
|
for _,p in pairs(ps) do
|
|
local y,x = unpack(p)
|
|
t[n] = ":"..p[1]..","..p[2].."=white.png"
|
|
n = n+1
|
|
end
|
|
t[n] = "^[colorize:#"..hexcols[colour]..")^"
|
|
n = n+1
|
|
end
|
|
n = n-1
|
|
if n == 0 then
|
|
minetest.log("error", "[painting] no texels")
|
|
return "white.png"
|
|
end
|
|
t[n] = t[n]:sub(1,-2)
|
|
return table.concat(t)
|
|
end
|
|
|
|
local function dot(v, w) -- Inproduct.
|
|
return v.x * w.x + v.y * w.y + v.z * w.z
|
|
end
|
|
|
|
local function intersect(pos, dir, origin, normal)
|
|
local t = -(dot(vector.subtract(pos, origin), normal)) / dot(dir, normal)
|
|
return vector.add(pos, vector.multiply(dir, t))
|
|
end
|
|
|
|
local function clamp(x, min,max)
|
|
return math.max(math.min(x, max),min)
|
|
end
|
|
|
|
minetest.register_node("painting:pic", {
|
|
description = "Picture",
|
|
tiles = { "white.png" },
|
|
inventory_image = "painted.png",
|
|
drawtype = "nodebox",
|
|
sunlight_propagates = true,
|
|
paramtype = "light",
|
|
paramtype2 = "facedir",
|
|
node_box = picbox2,
|
|
selection_box = { type="fixed", fixed = {-0.5, -0.5, -0.5, 0.5, -0.39, 0.5} },
|
|
groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 2,
|
|
not_in_creative_inventory=1},
|
|
on_rotate = function(pos) return false end,
|
|
--handle that right below, don't drop anything
|
|
drop = "",
|
|
|
|
after_dig_node = function(pos, _, oldmetadata, digger)
|
|
--find and remove the entity
|
|
for _,o in pairs(minetest.get_objects_inside_radius(pos, 0.5)) do
|
|
if not o:is_player() then
|
|
if o:get_luaentity().name == "painting:picent"
|
|
or o:get_luaentity().name == "painting:picent_notupright" then
|
|
o:remove()
|
|
end
|
|
end
|
|
end
|
|
if not oldmetadata.fields["painting:picturedata"] then return end
|
|
local data = legacy.load_itemmeta(oldmetadata.fields["painting:picturedata"])
|
|
--put picture data back into inventory item
|
|
digger:get_inventory():add_item("main", {
|
|
name = "painting:paintedcanvas",
|
|
count = 1,
|
|
metadata = get_metastring(data)
|
|
})
|
|
end,
|
|
--copy pictures
|
|
on_punch = function(pos, node, player, pointed_thing)
|
|
local meta = minetest.get_meta(pos):to_table()
|
|
if meta == nil then return end
|
|
|
|
if not meta.fields["painting:picturedata"] then return end
|
|
local data = legacy.load_itemmeta(meta.fields["painting:picturedata"])
|
|
if not minetest.deserialize(data) then
|
|
data = minetest.decompress(data)
|
|
minetest.log("action", "tried to copy old data, convert it to new format")
|
|
end
|
|
|
|
--compare resulutions of picture and canvas the player wields
|
|
--if it isn't the same don't copy
|
|
local wname = player:get_wielded_item():get_name()
|
|
local res = tonumber(string.sub(wname, #"painting:canvas_"+1))
|
|
if res == nil then return end
|
|
data_res = minetest.deserialize(data).res
|
|
if data_res == nil then return end
|
|
if res ~= data_res then
|
|
minetest.chat_send_player(player:get_player_name(),
|
|
"not same canvas type!")
|
|
return
|
|
end
|
|
--remove canvas, add picture
|
|
player:get_inventory():remove_item("main", {
|
|
name = wname,
|
|
count = 1,
|
|
})
|
|
player:get_inventory():add_item("main", {
|
|
name = "painting:paintedcanvas",
|
|
count = 1,
|
|
metadata = get_metastring(data)
|
|
})
|
|
end
|
|
})
|
|
|
|
local on_activate = function(self, staticdata)
|
|
local pos = self.object:getpos()
|
|
local ldata = legacy.load_itemmeta(minetest.get_meta(pos):get_string("painting:picturedata"))
|
|
if not ldata then return end
|
|
local data = minetest.deserialize(ldata)
|
|
-- for backwards compatiblity
|
|
if not data then
|
|
data = minetest.deserialize(minetest.decompress(ldata))
|
|
if data then
|
|
minetest.log("action", "loaded old data, converted to new uncompressed")
|
|
end
|
|
end
|
|
-- end backwards compatiblity
|
|
if not data
|
|
or not data.grid then
|
|
return
|
|
end
|
|
|
|
self.object:set_properties({textures = { to_imagestring(data.grid, data.res) }})
|
|
local pos = self.object:getpos()
|
|
local node = minetest.get_node(pos)
|
|
local param2 = node.param2 --wallmounted = first 3 bits
|
|
if node.name == "air" then
|
|
minetest.swap_node(pos, {name="painting:pic"})
|
|
end
|
|
if param2 == 20 then -- if ceiling
|
|
self.object:set_properties({textures = {"white.png", to_imagestring(data.grid, data.res) }})
|
|
end
|
|
if data.version ~= current_version then
|
|
minetest.log("legacy", "[painting] updating placed picture data")
|
|
if data.version == "nopairs" then
|
|
legacy.change_to_wallmounted(pos, self.object:getyaw())
|
|
end
|
|
data.version = current_version
|
|
data = minetest.serialize(data)
|
|
minetest.get_meta(pos):set_string("painting:picturedata", get_metastring(data))
|
|
end
|
|
end
|
|
|
|
-- picture texture entity
|
|
minetest.register_entity("painting:picent", {
|
|
collisionbox = { 0, 0, 0, 0, 0, 0 },
|
|
visual = "upright_sprite",
|
|
textures = { "white.png" },
|
|
|
|
on_activate = on_activate
|
|
})
|
|
|
|
minetest.register_entity("painting:picent_notupright", {
|
|
collisionbox = { 0, 0, 0, 0, 0, 0 },
|
|
visual = "cube",
|
|
visual_size = { x = 1, y = 0},
|
|
textures = { "white.png" },
|
|
|
|
on_activate = on_activate
|
|
})
|
|
|
|
-- Figure where it hits the canvas, in fraction given position and direction.
|
|
local function figure_paint_pos_raw(pos, d,od, ppos, l)
|
|
--get player eye level, see player.h line 129
|
|
local player_eye_h = 1.625
|
|
ppos.y = ppos.y + player_eye_h
|
|
|
|
local normal = { x = d.x, y = 0, z = d.z }
|
|
local p = intersect(ppos, l, pos, normal)
|
|
|
|
local off = -0.5
|
|
pos = vector.add(pos, {x=off*od.x, y=off, z=off*od.z})
|
|
p = vector.subtract(p, pos)
|
|
return math.abs(p.x + p.z), 1 - p.y
|
|
end
|
|
|
|
local dirs = { -- Directions the painting may be.
|
|
[0] = { x = 0, z = 1 },
|
|
[1] = { x = 1, z = 0 },
|
|
[2] = { x = 0, z =-1 },
|
|
[3] = { x =-1, z = 0 }
|
|
}
|
|
-- .. idem .. given self and puncher.
|
|
local function figure_paint_pos(self, puncher)
|
|
local x,y = figure_paint_pos_raw(self.object:getpos(),
|
|
dirs[self.fd], dirs[(self.fd + 1) % 4],
|
|
puncher:getpos(), puncher:get_look_dir())
|
|
return math.floor(self.res*clamp(x, 0, 1)), math.floor(self.res*clamp(y, 0, 1))
|
|
end
|
|
|
|
local function draw_input(self, name, x,y, as_line)
|
|
if x == nil or y == nil then return end
|
|
local x0 = self.x0
|
|
if as_line and x0 then -- Draw line if requested *and* have a previous position.
|
|
local y0 = self.y0
|
|
local line = vector.twoline(x0-x, y0-y) -- This figures how to do the line.
|
|
for _,coord in pairs(line) do
|
|
if self.grid then
|
|
self.grid[x+coord[1]][y+coord[2]] = colors[name]
|
|
end
|
|
end
|
|
else -- Draw just single point.
|
|
if self.grid and self.grid[x] and self.grid[x][y] then
|
|
self.grid[x][y] = colors[name]
|
|
end
|
|
end
|
|
self.x0, self.y0 = x, y -- Update previous position.
|
|
-- Actually update the grid.
|
|
self.object:set_properties{textures = { to_imagestring(self.grid, self.res) }}
|
|
end
|
|
|
|
local paintbox = {
|
|
[0] = { -0.5,-0.5,0,0.5,0.5,0 },
|
|
[1] = { 0,-0.5,-0.5,0,0.5,0.5 }
|
|
}
|
|
|
|
-- Painting as being painted.
|
|
minetest.register_entity("painting:paintent", {
|
|
collisionbox = { 0, 0, 0, 0, 0, 0 },
|
|
visual = "upright_sprite",
|
|
textures = { "white.png" },
|
|
|
|
on_punch = function(self, puncher)
|
|
--check for brush.
|
|
local name = string.sub(puncher:get_wielded_item():get_name(), #"painting:brush_"+1)
|
|
if not colors[name] then -- Not one of the brushes; can't paint.
|
|
return
|
|
end
|
|
|
|
assert(self.object)
|
|
local x,y = figure_paint_pos(self, puncher)
|
|
draw_input(self, name, x,y, puncher:get_player_control().sneak)
|
|
|
|
local wielded = puncher:get_wielded_item() -- Wear down the tool.
|
|
wielded:add_wear(65535/256)
|
|
puncher:set_wielded_item(wielded)
|
|
end,
|
|
|
|
on_activate = function(self, staticdata)
|
|
local data = minetest.deserialize(staticdata)
|
|
-- for backwards compatiblity
|
|
if not data then
|
|
data = minetest.deserialize(minetest.decompress(staticdata))
|
|
if data then
|
|
minetest.log("action", "loaded old data, converted to new uncompressed")
|
|
end
|
|
end
|
|
-- end backwards compatiblity
|
|
if not data then
|
|
return
|
|
end
|
|
self.fd = data.fd
|
|
self.x0, self.y0 = data.x0, data.y0
|
|
self.res = data.res
|
|
self.version = data.version
|
|
self.grid = data.grid
|
|
legacy.fix_grid(self.grid, self.version)
|
|
self.object:set_properties{ textures = { to_imagestring(self.grid, self.res) }}
|
|
if not self.fd then
|
|
return
|
|
end
|
|
self.object:set_properties{ collisionbox = paintbox[self.fd%2] }
|
|
self.object:set_armor_groups{immortal=1}
|
|
end,
|
|
|
|
get_staticdata = function(self)
|
|
return minetest.serialize{fd = self.fd, res = self.res,
|
|
grid = self.grid, x0 = self.x0, y0 = self.y0, version = self.version
|
|
}
|
|
end
|
|
})
|
|
|
|
--paintedcanvas picture inventory item
|
|
minetest.register_craftitem("painting:paintedcanvas", {
|
|
description = "Painted Canvas",
|
|
inventory_image = "painted.png",
|
|
stack_max = 1,
|
|
groups = { snappy = 2, choppy = 2, oddly_breakable_by_hand = 2, not_in_creative_inventory=1 },
|
|
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
-- copied from default:torch
|
|
local under = pointed_thing.under
|
|
local above = pointed_thing.above
|
|
local node = minetest.get_node(under)
|
|
local def = minetest.registered_nodes[node.name]
|
|
if def and def.on_rightclick and
|
|
not (placer and placer:is_player() and
|
|
placer:get_player_control().sneak) then
|
|
return def.on_rightclick(under, node, placer, itemstack,
|
|
pointed_thing) or itemstack
|
|
end
|
|
if def.buildable_to then
|
|
return itemstack
|
|
end
|
|
--place node
|
|
local pos = pointed_thing.above
|
|
if minetest.is_protected(pos, placer:get_player_name()) then
|
|
return
|
|
end
|
|
|
|
-- taken from core.rotate_and_place
|
|
local fdir = minetest.dir_to_facedir(vector.subtract(under, above))
|
|
local iswall = (above.y == under.y)
|
|
local isceiling = not iswall and (above.y < under.y)
|
|
local param2 = fdir
|
|
if iswall then
|
|
local dirs = {9, 18, 7, 12}
|
|
param2 = dirs[fdir+1]
|
|
elseif isceiling then
|
|
param2 = 20
|
|
end
|
|
minetest.item_place_node(ItemStack("painting:pic"), placer, pointed_thing, param2)
|
|
|
|
local dir = vector.subtract(under, above)
|
|
local wallmounted = minetest.dir_to_wallmounted(dir)
|
|
local yaw = {nil, -- y
|
|
nil, -- -y
|
|
math.pi/2, -- x
|
|
3/2*math.pi, -- -x
|
|
0, -- z
|
|
math.pi -- -z
|
|
}
|
|
yaw = yaw[wallmounted+1]
|
|
|
|
--save metadata
|
|
local data = legacy.load_itemmeta(itemstack:get_metadata())
|
|
-- for backwards compatiblity
|
|
if not minetest.deserialize(data) then
|
|
status, data = pcall(minetest.decompress, data)
|
|
if (status and data) then
|
|
minetest.log("action", "tried to save old data"..
|
|
"converted to new uncompressed, save")
|
|
elseif not status then
|
|
minetest.log("error", "loading picture data unsuccessfull")
|
|
end
|
|
end
|
|
-- end backwards compatiblity
|
|
if data == nil then return ItemStack("") end
|
|
minetest.get_meta(pos):set_string("painting:picturedata", get_metastring(data))
|
|
|
|
--add entity
|
|
local off = (0.5 - thickness - 0.01)
|
|
pos.x = pos.x + dir.x * off
|
|
pos.y = pos.y + dir.y * off
|
|
pos.z = pos.z + dir.z * off
|
|
|
|
data = minetest.deserialize(data)
|
|
if data == nil then return ItemStack("") end
|
|
|
|
local img = to_imagestring(data.grid, data.res)
|
|
if wallmounted == 1 then
|
|
local obj = minetest.add_entity(pos, "painting:picent_notupright")
|
|
obj:set_properties{ textures = { img }}
|
|
elseif wallmounted == 0 then
|
|
local obj = minetest.add_entity(pos, "painting:picent_notupright")
|
|
obj:set_properties{ textures = { "white.png", img }}
|
|
else
|
|
local obj = minetest.add_entity(pos, "painting:picent")
|
|
obj:set_properties{ textures = { img }}
|
|
obj:setyaw(yaw)
|
|
end
|
|
|
|
return ItemStack("")
|
|
end
|
|
})
|
|
|
|
--canvas inventory items
|
|
for i = 4,6 do
|
|
minetest.register_craftitem("painting:canvas_"..2^i, {
|
|
description = "Canvas(" .. 2^i .. ")",
|
|
inventory_image = "default_paper.png",
|
|
stack_max = 99,
|
|
})
|
|
end
|
|
|
|
--canvas for drawing
|
|
local canvasbox = {
|
|
type = "fixed",
|
|
fixed = { -0.5, -0.5, 0, 0.5, 0.5, thickness }
|
|
}
|
|
|
|
minetest.register_node("painting:canvasnode", {
|
|
description = "Canvas",
|
|
tiles = { "white.png" },
|
|
inventory_image = "painted.png",
|
|
drawtype = "nodebox",
|
|
sunlight_propagates = true,
|
|
paramtype = "light",
|
|
paramtype2 = "facedir",
|
|
node_box = canvasbox,
|
|
selection_box = canvasbox,
|
|
groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 2,
|
|
not_in_creative_inventory=1},
|
|
|
|
drop = "",
|
|
|
|
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
|
--get data and remove pixels
|
|
local data = {}
|
|
for _,e in pairs(minetest.get_objects_inside_radius(pos, 0.1)) do
|
|
e = e:get_luaentity()
|
|
if e.grid then
|
|
data.grid = e.grid
|
|
data.version = e.version
|
|
data.res = e.res
|
|
e.object:remove()
|
|
break
|
|
end
|
|
end
|
|
|
|
pos.y = pos.y-1
|
|
minetest.get_meta(pos):set_int("has_canvas", 0)
|
|
|
|
if not data.grid then
|
|
return
|
|
end
|
|
legacy.fix_grid(data.grid, data.version)
|
|
digger:get_inventory():add_item("main", {
|
|
name = "painting:paintedcanvas",
|
|
count = 1,
|
|
metadata = get_metastring(minetest.serialize(data))
|
|
})
|
|
end
|
|
})
|
|
|
|
local easelbox = { -- Specifies 3d model.
|
|
type = "fixed",
|
|
fixed = {
|
|
--feet
|
|
{-0.4, -0.5, -0.5, -0.3, -0.4, 0.5 },
|
|
{ 0.3, -0.5, -0.5, 0.4, -0.4, 0.5 },
|
|
--legs
|
|
{-0.4, -0.4, 0.1, -0.3, 1.5, 0.2 },
|
|
{ 0.3, -0.4, 0.1, 0.4, 1.5, 0.2 },
|
|
--shelf
|
|
{-0.5, 0.35, -0.3, 0.5, 0.45, 0.1 }
|
|
}
|
|
}
|
|
|
|
minetest.register_node("painting:easel", {
|
|
description = "Easel",
|
|
tiles = { "default_wood.png" },
|
|
drawtype = "nodebox",
|
|
sunlight_propagates = true,
|
|
paramtype = "light",
|
|
paramtype2 = "facedir",
|
|
node_box = easelbox,
|
|
selection_box = easelbox,
|
|
|
|
groups = { snappy = 2, choppy = 2, oddly_breakable_by_hand = 2 },
|
|
|
|
on_punch = function(pos, node, player)
|
|
local wield_name = player:get_wielded_item():get_name()
|
|
local name, res = string.match(wield_name, "^([^_]+)_([^_]+)")
|
|
if name ~= "painting:canvas" then -- Can only put the canvas on there.
|
|
return
|
|
end
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
pos.y = pos.y+1
|
|
if minetest.get_node(pos).name ~= "air" then
|
|
-- this is not likely going to happen
|
|
return
|
|
end
|
|
local fd = node.param2
|
|
minetest.add_node(pos, { name = "painting:canvasnode", param2 = fd})
|
|
|
|
local dir = dirs[fd]
|
|
pos.x = pos.x - 0.01 * dir.x
|
|
pos.z = pos.z - 0.01 * dir.z
|
|
|
|
local obj = minetest.add_entity(pos, "painting:paintent")
|
|
obj:set_properties{ collisionbox = paintbox[fd%2] }
|
|
obj:set_armor_groups{immortal=1}
|
|
obj:setyaw(math.pi * fd / -2)
|
|
local res = tonumber(res) -- Was still string from matching.
|
|
local ent = obj:get_luaentity()
|
|
ent.grid = initgrid(res)
|
|
ent.version = current_version
|
|
ent.res = res
|
|
ent.fd = fd
|
|
|
|
meta:set_int("has_canvas", 1)
|
|
player:get_inventory():remove_item("main", ItemStack(wield_name))
|
|
end,
|
|
|
|
can_dig = function(pos)
|
|
return minetest.get_meta(pos):get_int("has_canvas") == 0
|
|
end
|
|
})
|
|
|
|
--brushes
|
|
local function table_copy(t)
|
|
local t2 = {}
|
|
for k,v in pairs(t) do
|
|
t2[k] = v
|
|
end
|
|
return t2
|
|
end
|
|
|
|
local brush = {
|
|
wield_image = "",
|
|
tool_capabilities = {
|
|
full_punch_interval = 1.0,
|
|
max_drop_level=0,
|
|
groupcaps = {}
|
|
}
|
|
}
|
|
|
|
local textures = {
|
|
white = "white.png", yellow = "yellow.png",
|
|
orange = "orange.png", red = "red.png",
|
|
violet = "violet.png", blue = "blue.png",
|
|
green = "green.png", magenta = "magenta.png",
|
|
cyan = "cyan.png", grey = "grey.png",
|
|
dark_grey = "darkgrey.png", black = "black.png",
|
|
dark_green = "darkgreen.png", brown="brown.png",
|
|
pink = "pink.png"
|
|
}
|
|
|
|
local vage_revcolours = {} -- colours in pairs order
|
|
for color, _ in pairs(textures) do
|
|
vage_revcolours[#vage_revcolours+1] = color
|
|
local brush_new = table_copy(brush)
|
|
brush_new.description = color:gsub("^%l", string.upper).." brush"
|
|
brush_new.inventory_image = "painting_brush_stem.png^(painting_brush_head.png^[colorize:#"..hexcols[color]..":255)^painting_brush_head.png"
|
|
minetest.register_tool("painting:brush_"..color, brush_new)
|
|
minetest.register_craft{
|
|
output = "painting:brush_"..color,
|
|
recipe = {
|
|
{"dye:"..color},
|
|
{"default:stick"},
|
|
{"default:stick"}
|
|
}
|
|
}
|
|
end
|
|
|
|
for i, color in ipairs(revcolors) do
|
|
colors[color] = i
|
|
end
|
|
|
|
|
|
-- legacy
|
|
|
|
minetest.register_alias("easel", "painting:easel")
|
|
minetest.register_alias("canvas", "painting:canvas_16")
|
|
|
|
-- fixes the colours which were set by pairs
|
|
local function fix_eldest_grid(data)
|
|
if data == nil then
|
|
return
|
|
end
|
|
for y in pairs(data) do
|
|
local xs = data[y]
|
|
for x in pairs(xs) do
|
|
-- it was done in pairs order
|
|
xs[x] = colors[vage_revcolours[xs[x]]]
|
|
end
|
|
end
|
|
return data
|
|
end
|
|
|
|
-- possibly updates grid
|
|
function legacy.fix_grid(grid, version)
|
|
if version == current_version then
|
|
return
|
|
end
|
|
|
|
--[[
|
|
if version == "nopairs" then
|
|
return
|
|
end--]]
|
|
|
|
minetest.log("action", "[painting] updating grid")
|
|
|
|
fix_eldest_grid(grid)
|
|
end
|
|
|
|
-- gets the data from meta
|
|
function legacy.load_itemmeta(data)
|
|
--if not data then
|
|
-- data = current_version.."(version)"..
|
|
local vend = data:find"(version)"
|
|
if not vend then -- the oldest version
|
|
local t = minetest.deserialize(data)
|
|
if t == nil then return end
|
|
if t.version then
|
|
minetest.log("error", "[painting] this musn't happen!")
|
|
end
|
|
minetest.log("action", "[painting] updating painting meta")
|
|
legacy.fix_grid(t.grid)
|
|
return minetest.serialize(t)
|
|
end
|
|
local version = data:sub(1, vend-2)
|
|
data = data:sub(vend+8)
|
|
--if version == current_version then
|
|
return data
|
|
--end
|
|
end
|
|
|
|
|
|
minetest.register_node("painting:pic_legacy_facedir", {
|
|
description = "Picture",
|
|
tiles = { "white.png" },
|
|
inventory_image = "painted.png",
|
|
drawtype = "nodebox",
|
|
sunlight_propagates = true,
|
|
paramtype = "light",
|
|
paramtype2 = "facedir",
|
|
node_box = picbox,
|
|
selection_box = picbox,
|
|
groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 2,
|
|
not_in_creative_inventory=1},
|
|
|
|
--handle that right below, don't drop anything
|
|
drop = "",
|
|
|
|
after_dig_node = function(pos, _, oldmetadata, digger)
|
|
--find and remove the entity
|
|
for _,e in pairs(minetest.get_objects_inside_radius(pos, 0.5)) do
|
|
if e:get_luaentity().name == "painting:picent" then
|
|
e:remove()
|
|
end
|
|
end
|
|
if not oldmetadata.fields["painting:picturedata"] then return end
|
|
local data = legacy.load_itemmeta(oldmetadata.fields["painting:picturedata"])
|
|
--put picture data back into inventory item
|
|
digger:get_inventory():add_item("main", {
|
|
name = "painting:paintedcanvas",
|
|
count = 1,
|
|
metadata = get_metastring(data)
|
|
})
|
|
end,
|
|
--copy pictures
|
|
on_punch = function(pos, node, player, pointed_thing)
|
|
local meta = minetest.get_meta(pos):to_table()
|
|
if meta == nil then return end
|
|
if not meta.fields["painting:picturedata"] then return end
|
|
local data = legacy.load_itemmeta(meta.fields["painting:picturedata"])
|
|
if not minetest.deserialize(data) then
|
|
data = minetest.decompress(data)
|
|
minetest.log("action", "tried to copy old data, convert it to new format")
|
|
end
|
|
|
|
--compare resulutions of picture and canvas the player wields
|
|
--if it isn't the same don't copy
|
|
local wname = player:get_wielded_item():get_name()
|
|
local res = tonumber(string.sub(wname, #"painting:canvas_"+1))
|
|
if res == nil then return end
|
|
data_res = minetest.deserialize(data).res
|
|
if data_res == nil then return end
|
|
if res ~= data_res then
|
|
minetest.chat_send_player(player:get_player_name(),
|
|
"not same canvas type!")
|
|
return
|
|
end
|
|
--remove canvas, add picture
|
|
player:get_inventory():remove_item("main", {
|
|
name = wname,
|
|
count = 1,
|
|
})
|
|
player:get_inventory():add_item("main", {
|
|
name = "painting:paintedcanvas",
|
|
count = 1,
|
|
metadata = get_metastring(data)
|
|
})
|
|
end
|
|
})
|
|
|
|
|
|
function legacy.change_to_wallmounted(pos, yaw)
|
|
local param2 = minetest.get_node(pos).param2
|
|
minetest.set_node(pos, {name="painting:pic_legacy_facedir", param2=param2})
|
|
end
|
|
|
|
--[[ allows using many colours, doesn't work
|
|
function to_imagestring(data, res)
|
|
if not data then
|
|
return
|
|
end
|
|
local t,n = {},1
|
|
local sbc = {}
|
|
for y = 0, res - 1 do
|
|
for x = 0, res - 1 do
|
|
local col = revcolors[data[x][y] ]
|
|
sbc[col] = sbc[col] or {}
|
|
sbc[col][#sbc[col] ] = {x,y}
|
|
end
|
|
end
|
|
for col,ps in pairs(sbc) do
|
|
t[n] = "([combine:"..res.."x"..res..":"
|
|
n = n+1
|
|
for _,p in pairs(ps) do
|
|
t[n] = p[1]..","..p[2].."=white.png:"
|
|
n = n+1
|
|
end
|
|
t[n-1] = string.sub(t[n-1], 1,-2)
|
|
t[n] = "^[colorize:"..col..")^"
|
|
n = n+1
|
|
end
|
|
t[n-1] = string.sub(t[n-1], 1,-2)
|
|
return table.concat(t)
|
|
end--]]
|