diff --git a/mods/ENTITIES/mcl_paintings/init.lua b/mods/ENTITIES/mcl_paintings/init.lua new file mode 100644 index 000000000..df29395b6 --- /dev/null +++ b/mods/ENTITIES/mcl_paintings/init.lua @@ -0,0 +1,276 @@ +mcl_paintings = {} + +dofile(minetest.get_modpath(minetest.get_current_modname()).."/paintings.lua") + +local S = minetest.get_translator("mcl_paintings") + +local wood = "[combine:16x16:-192,0=mcl_paintings_paintings.png" + +-- Check if there's a painting for provided painting size. +-- If yes, returns the arguments. +-- If not, returns the next smaller available painting. +local shrink_painting = function(x, y) + if x > 4 or y > 4 then + return nil + end + local xstart = x + local painting + while not painting do + painting = mcl_paintings.paintings[y] and mcl_paintings.paintings[y][x] + if type(painting) == "table" then + break + elseif type(painting) == "number" then + x = painting + painting = nil + else + x = xstart + y = y - 1 + end + if y < 1 then + return nil + end + end + if type(painting) == "table" then + return x, y + end +end + +local get_painting = function(x, y, motive) + local painting = mcl_paintings.paintings[y] and mcl_paintings.paintings[y][x] and mcl_paintings.paintings[y][x][motive] + if not painting then + return nil + end + local px, py = -painting.cx, -painting.cy + local sx, sy = 16*x, 16*y + return "[combine:"..sx.."x"..sy..":"..px..","..py.."=mcl_paintings_paintings.png" +end + +local get_random_painting = function(x, y) + if not mcl_paintings.paintings[y] or not mcl_paintings.paintings[y][x] then + return nil + end + local max = #mcl_paintings.paintings[y][x] + if max < 1 then + return nil + end + local r = math.random(1, max) + return get_painting(x, y, r), r +end + +local size_to_minmax = function(size) + local min, max + if size == 2 then + min = -0.5 + max = 1.5 + elseif size == 3 then + min = -1.5 + max = 1.5 + elseif size == 4 then + min = -1.5 + max = 2.5 + else + min = -0.5 + max = 0.5 + end + return min, max +end + +local size_to_minmax_entity = function(size) + return -size/2, size/2 +end + +local set_entity = function(object) + local ent = object:get_luaentity() + local wallm = ent._facing + local xsize = ent._xsize + local ysize = ent._ysize + local exmin, exmax = size_to_minmax_entity(xsize) + local eymin, eymax = size_to_minmax_entity(ysize) + local visual_size = { x=xsize-0.0001, y=ysize-0.0001, z=1/32 } + if not ent._xsize or not ent._ysize or not ent._motive then + minetest.log("error", "[mcl_paintings] Painting loaded with missing painting values!") + return + end + local painting = get_painting(xsize, ysize, ent._motive) + if not painting then + minetest.log("error", "[mcl_paintings] No painting found for size " + ..xsize..","..ysize..", motive number "..ent._motive.."!") + return + end + if wallm == 4 or wallm == 5 then + object:set_properties({ + selectionbox = { exmin, eymin, -1/64, exmax, eymax, 1/64 }, + visual_size = visual_size, + textures = { wood, wood, wood, wood, painting, wood }, + }) + else + object:set_properties({ + selectionbox = { -1/64, eymin, exmin, 1/64, eymax, exmax }, + visual_size = visual_size, + textures = { wood, wood, wood, wood, painting, wood }, + }) + end + local dir = minetest.wallmounted_to_dir(wallm) + if not dir then + return + end + object:set_yaw(minetest.dir_to_yaw(dir)) +end + +minetest.register_entity("mcl_paintings:painting", { + visual = "cube", + visual_size = { x=0.999, y=0.999, z=1/32 }, + selectionbox = { -1/64, -0.5, -0.5, 1/64, 0.5, 0.5 }, + physical = false, + collide_with_objects = false, + textures = { wood, wood, wood, wood, wood, wood }, + hp_max = 1, + + _motive = 0, + _pos = nil, + _facing = 2, + _xsize = 1, + _ysize = 1, + on_activate = function(self, staticdata) + if staticdata and staticdata ~= "" then + local data = minetest.deserialize(staticdata) + if data then + self._facing = data._facing + self._pos = data._pos + self._motive = data._motive + self._xsize = data._xsize + self._ysize = data._ysize + end + end + set_entity(self.object) + end, + get_staticdata = function(self) + local data = { + _facing = self._facing, + _pos = self._pos, + _motive = self._motive, + _xsize = self._xsize, + _ysize = self._ysize, + } + return minetest.serialize(data) + end, + on_death = function(self, killer) + -- Drop as item on death + if not minetest.settings:get_bool("creative_mode") then + local pos = self._pos + if not pos then + pos = self.object:get_pos() + end + minetest.add_item(pos, "mcl_paintings:painting") + end + end, +}) + +minetest.register_craftitem("mcl_paintings:painting", { + description = S("Painting"), + inventory_image = "mcl_paintings_painting.png", + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + local dir = vector.subtract(pointed_thing.above, pointed_thing.under) + dir = vector.normalize(dir) + if dir.y ~= 0 then + -- Ceiling/floor paintings are not supported + return itemstack + end + local wallm = minetest.dir_to_wallmounted(dir) + if wallm then + local ppos = pointed_thing.above + local xmax + local ymax = 4 + local xmaxes = {} + local ymaxed = false + local negative = dir.x < 0 or dir.z > 0 + -- Check maximum possible painting size + local t + for y=0,3 do + for x=0,3 do + local k = x + if negative then + k = -k + end + if dir.z ~= 0 then + t = {x=k,y=y,z=0} + else + t = {x=0,y=y,z=k} + end + local unode = minetest.get_node(vector.add(pointed_thing.under, t)) + local anode = minetest.get_node(vector.add(ppos, t)) + local udef = minetest.registered_nodes[unode.name] + local adef = minetest.registered_nodes[anode.name] + if (not (udef and udef.walkable)) or (not adef or adef.walkable) then + xmaxes[y+1] = x + if x == 0 and not ymaxed then + ymax = y + ymaxed = true + end + break + end + end + if not xmaxes[y] then + xmaxes[y] = 4 + end + end + xmax = math.max(unpack(xmaxes)) + + local xsize, ysize = xmax, ymax + xsize, ysize = shrink_painting(xsize, ysize) + if not xsize then + return itemstack + end + local _, exmax = size_to_minmax_entity(xsize) + local _, eymax = size_to_minmax_entity(ysize) + local pposa = vector.subtract(ppos, vector.multiply(dir, 0.5-2/64)) + local pexmax + local peymax = eymax - 0.5 + if negative then + pexmax = -exmax + 0.5 + else + pexmax = exmax - 0.5 + end + if dir.z ~= 0 then + pposa = vector.add(pposa, {x=pexmax, y=peymax, z=0}) + else + pposa = vector.add(pposa, {x=0, y=peymax, z=pexmax}) + end + local painting, pid = get_random_painting(xsize, ysize) + if not painting then + minetest.log("error", "[mcl_paintings] No painting found for size "..xsize..","..ysize.."!") + return itemstack + end + local staticdata = { + _facing = wallm, + _pos = ppos, + _motive = pid, + _xsize = xsize, + _ysize = ysize, + } + local obj = minetest.add_entity(pposa, "mcl_paintings:painting", minetest.serialize(staticdata)) + if not obj then + return itemstack + end + else + return itemstack + end + if not minetest.settings:get_bool("creative_mode") then + itemstack:take_item() + end + return itemstack + end, +}) + +minetest.register_craft({ + output = "mcl_paintings:painting", + recipe = { + { "mcl_core:stick", "mcl_core:stick", "mcl_core:stick" }, + { "mcl_core:stick", "group:wool", "mcl_core:stick" }, + { "mcl_core:stick", "mcl_core:stick", "mcl_core:stick" }, + } +}) + diff --git a/mods/ENTITIES/mcl_paintings/locale/mcl_paintings.de.tr b/mods/ENTITIES/mcl_paintings/locale/mcl_paintings.de.tr new file mode 100644 index 000000000..983877251 --- /dev/null +++ b/mods/ENTITIES/mcl_paintings/locale/mcl_paintings.de.tr @@ -0,0 +1,2 @@ +# textdomain:mcl_paintings +Painting=Gemälde diff --git a/mods/ENTITIES/mcl_paintings/locale/template.txt b/mods/ENTITIES/mcl_paintings/locale/template.txt new file mode 100644 index 000000000..73abae1e8 --- /dev/null +++ b/mods/ENTITIES/mcl_paintings/locale/template.txt @@ -0,0 +1,2 @@ +# textdomain:mcl_paintings +Painting= diff --git a/mods/ENTITIES/mcl_paintings/mod.conf b/mods/ENTITIES/mcl_paintings/mod.conf new file mode 100644 index 000000000..ea1d61c3d --- /dev/null +++ b/mods/ENTITIES/mcl_paintings/mod.conf @@ -0,0 +1 @@ +name = mcl_paintings diff --git a/mods/ENTITIES/mcl_paintings/paintings.lua b/mods/ENTITIES/mcl_paintings/paintings.lua new file mode 100644 index 000000000..d606306c2 --- /dev/null +++ b/mods/ENTITIES/mcl_paintings/paintings.lua @@ -0,0 +1,55 @@ +local TS = 16 -- texture size + +mcl_paintings.paintings = { + [1] = { + [1] = { + { cx = 0, cy = 0 }, + { cx = TS, cy = 0 }, + { cx = 2*TS, cy = 0 }, + { cx = 3*TS, cy = 0 }, + { cx = 4*TS, cy = 0 }, + { cx = 5*TS, cy = 0 }, + { cx = 6*TS, cy = 0 }, + }, + [2] = { + { cx = 0, cy = 2*TS }, + { cx = 2*TS, cy = 2*TS }, + { cx = 4*TS, cy = 2*TS }, + { cx = 6*TS, cy = 2*TS }, + { cx = 8*TS, cy = 2*TS }, + }, + [3] = 2, + [4] = 2, + }, + [2] = { + [1] = { + { cx = 0, cy = 4*TS }, + { cx = TS, cy = 4*TS }, + }, + [2] = { + { cx = 0, cy = 8*TS }, + { cx = 2*TS, cy = 8*TS }, + { cx = 4*TS, cy = 8*TS }, + { cx = 6*TS, cy = 8*TS }, + { cx = 8*TS, cy = 8*TS }, + { cx = 10*TS, cy = 8*TS }, + }, + [3] = 2, + [4] = { + { cx = 0, cy = 6*TS }, + }, + }, + [3] = { + [4] = { + { cx = 12*TS, cy = 4*TS }, + { cx = 12*TS, cy = 7*TS }, + }, + }, + [4] = { + [4] = { + { cx = 0, cy = 12*TS }, + { cx = 4*TS, cy = 12*TS }, + { cx = 8*TS, cy = 12*TS }, + }, + }, +} diff --git a/mods/ENTITIES/mcl_paintings/textures/mcl_paintings_painting.png b/mods/ENTITIES/mcl_paintings/textures/mcl_paintings_painting.png new file mode 100644 index 000000000..afaaa935d Binary files /dev/null and b/mods/ENTITIES/mcl_paintings/textures/mcl_paintings_painting.png differ diff --git a/mods/ENTITIES/mcl_paintings/textures/mcl_paintings_paintings.png b/mods/ENTITIES/mcl_paintings/textures/mcl_paintings_paintings.png new file mode 100644 index 000000000..0a8462d12 Binary files /dev/null and b/mods/ENTITIES/mcl_paintings/textures/mcl_paintings_paintings.png differ