diff --git a/mods/README.md b/mods/README.md index de74ba0..d7f4694 100644 --- a/mods/README.md +++ b/mods/README.md @@ -40,6 +40,7 @@ For information check [../README.md](../README.md) | weather | https://codeberg.org/minenux/minetest-game-minetest | https://codeberg.org/minenux/minetest-game-minetest/commit/eb64ff94f82d726e4a55b20fa7ce30e4a7470cc5 | | | wool | https://codeberg.org/minenux/minetest-mod-wool | https://codeberg.org/minenux/minetest-mod-wool/commit/de642a08e80bfd7a4a1e5629e50458a609dbda3a | [wool/README.md](wool/README.md) | | xpanes | https://codeberg.org/minenux/minetest-game-minetest | https://codeberg.org/minenux/minetest-game-minetest/commit/eb64ff94f82d726e4a55b20fa7ce30e4a7470cc5 | | +| xdecor | https://codeberg.org/minenux/minetest-game-xdecor | https://codeberg.org/minenux/minetest-game-xdecor/commit/542d430537f3537b07bf5c919831160123498a2b | [xdecor/README.md](xdecor/README.md) | The default mod was splitted now sethome and player_api are mods, binoculars from v5 are just separate privilegies for zoom, butterflies and fireflies from v5 can be set diff --git a/mods/xdecor/.gitignore b/mods/xdecor/.gitignore new file mode 100644 index 0000000..ef02689 --- /dev/null +++ b/mods/xdecor/.gitignore @@ -0,0 +1,22 @@ +## Files related to minetest development cycle +/*.patch +# GNU Patch reject file +*.rej + +## Editors and Development environments +*~ +*.swp +*.bak* +*.orig +# Vim +*.vim +# Kate +.*.kate-swp +.swp.* +# Eclipse (LDT) +.project +.settings/ +.buildpath +.metadata +# Idea IDE +.idea/* diff --git a/mods/xdecor/.luacheckrc b/mods/xdecor/.luacheckrc new file mode 100644 index 0000000..8cdd8c3 --- /dev/null +++ b/mods/xdecor/.luacheckrc @@ -0,0 +1,14 @@ +allow_defined_top = true + +read_globals = { + "minetest", + "vector", "ItemStack", + "default", + "stairs", "doors", "xpanes", + "xdecor", "xbg", + table = {fields = {"copy"}}, + string = {fields = {"split"}}, + "unpack", + "stairsplus", + "mesecon" +} diff --git a/mods/xdecor/LICENSE b/mods/xdecor/LICENSE new file mode 100644 index 0000000..938b40e --- /dev/null +++ b/mods/xdecor/LICENSE @@ -0,0 +1,41 @@ +┌──────────────────────────────────────────────────────────────────────┐ +│ Copyright (c) 2015-2021 kilbith │ +│ │ +│ Code: BSD │ +│ Textures: WTFPL (credits: Gambit, kilbith, Cisoun) │ +│ Textures (radio, speaker, hanging candle, rooster) by │ +│ gigomaf (CC BY-NC 3.0) │ +│ Sounds: │ +│ - xdecor_boiling_water.ogg - by Audionautics - CC BY-SA │ +│ freesound.org/people/Audionautics/sounds/133901/ │ +│ - xdecor_enchanting.ogg - by Timbre - CC BY-SA-NC │ +│ freesound.org/people/Timbre/sounds/221683/ │ +│ - xdecor_bouncy.ogg - by Blender Foundation - CC BY 3.0 │ +│ opengameart.org/content/funny-comic-cartoon-bounce-sound │ +└──────────────────────────────────────────────────────────────────────┘ + + +Copyright (c) 1998, Regents of the University of California +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of the University of California, Berkeley nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mods/xdecor/README.md b/mods/xdecor/README.md new file mode 100644 index 0000000..3aea3b6 --- /dev/null +++ b/mods/xdecor/README.md @@ -0,0 +1,18 @@ +## X-Decor ## + +[![ContentDB](https://content.minetest.net/packages/jp/xdecor/shields/downloads/)](https://content.minetest.net/packages/jp/xdecor/) + +A decoration mod meant to be simple and well-featured. +It adds a bunch of cute cubes, various mechanisms and stuff for [cutting](https://forum.minetest.net/viewtopic.php?f=11&t=14085), [enchanting](https://forum.minetest.net/viewtopic.php?f=11&t=14087), cooking, etc. +This mod is a lightweight alternative to HomeDecor and MoreBlocks. + +### Requirements ### + +This mod requires at least version 0.4.16 of Minetest. + +### Credits ### + +Special thanks to Gambit for the textures from the PixelBOX pack for Minetest. +Thanks to all contributors who keep this mod alive. + +![Preview](http://i.imgur.com/AVoyCQy.png) diff --git a/mods/xdecor/depends.txt b/mods/xdecor/depends.txt new file mode 100644 index 0000000..c582a68 --- /dev/null +++ b/mods/xdecor/depends.txt @@ -0,0 +1,10 @@ +default +bucket +doors +farming +stairs +xpanes +fire? +oresplus? +moreblocks? +mesecons? diff --git a/mods/xdecor/description.txt b/mods/xdecor/description.txt new file mode 100644 index 0000000..8738846 --- /dev/null +++ b/mods/xdecor/description.txt @@ -0,0 +1 @@ +HOME decoration mod meant to be simple diff --git a/mods/xdecor/handlers/animations.lua b/mods/xdecor/handlers/animations.lua new file mode 100644 index 0000000..ee55942 --- /dev/null +++ b/mods/xdecor/handlers/animations.lua @@ -0,0 +1,60 @@ +local p_api = minetest.get_modpath("player_api") + +local function top_face(pointed_thing) + if not pointed_thing then return end + return pointed_thing.above.y > pointed_thing.under.y +end + +function xdecor.sit(pos, node, clicker, pointed_thing) + if not top_face(pointed_thing) then return end + local player_name = clicker:get_player_name() + local objs = minetest.get_objects_inside_radius(pos, 0.1) + local vel = clicker:get_player_velocity() + local ctrl = clicker:get_player_control() + local eyey = -7 + + for _, obj in pairs(objs) do + if obj:is_player() and obj:get_player_name() ~= player_name then + return + end + end + + if default.player_attached[player_name] then + pos.y = pos.y - 0.5 + clicker:set_pos(pos) + clicker:set_eye_offset(vector.new(), vector.new()) + clicker:set_physics_override({speed = 1, jump = 1, gravity = 1}) + default.player_attached[player_name] = false + default.player_set_animation(clicker, "stand", 30) + + elseif not default.player_attached[player_name] and node.param2 <= 3 and + not ctrl.sneak and vector.equals(vel, vector.new()) then + if p_api then eyey = 0 end + clicker:set_eye_offset({x = 0, y = eyey, z = 2}, vector.new()) + clicker:set_physics_override({speed = 0, jump = 0, gravity = 1}) + clicker:set_pos(pos) + default.player_attached[player_name] = true + default.player_set_animation(clicker, "sit", 30) + + if node.param2 == 0 then + clicker:set_look_yaw(3.15) + elseif node.param2 == 1 then + clicker:set_look_yaw(7.9) + elseif node.param2 == 2 then + clicker:set_look_yaw(6.28) + elseif node.param2 == 3 then + clicker:set_look_yaw(4.75) + end + end +end + +function xdecor.sit_dig(pos, digger) + for _, player in pairs(minetest.get_objects_inside_radius(pos, 0.1)) do + if player:is_player() and + default.player_attached[player:get_player_name()] then + return false + end + end + + return true +end diff --git a/mods/xdecor/handlers/helpers.lua b/mods/xdecor/handlers/helpers.lua new file mode 100644 index 0000000..dc14b24 --- /dev/null +++ b/mods/xdecor/handlers/helpers.lua @@ -0,0 +1,60 @@ +-- Returns the greatest numeric key in a table. +function xdecor.maxn(T) + local n = 0 + for k in pairs(T) do + if k > n then + n = k + end + end + + return n +end + +-- Returns the length of an hash table. +function xdecor.tablelen(T) + local n = 0 + + for _ in pairs(T) do + n = n + 1 + end + + return n +end + +-- Deep copy of a table. Borrowed from mesecons mod (https://github.com/Jeija/minetest-mod-mesecons). +function xdecor.tablecopy(T) + if type(T) ~= "table" then + return T -- No need to copy. + end + + local new = {} + + for k, v in pairs(T) do + if type(v) == "table" then + new[k] = xdecor.tablecopy(v) + else + new[k] = v + end + end + + return new +end + +function xdecor.stairs_valid_def(def) + return (def.drawtype == "normal" or def.drawtype:sub(1,5) == "glass") and + (def.groups.cracky or def.groups.choppy) and + not def.on_construct and + not def.after_place_node and + not def.on_rightclick and + not def.on_blast and + not def.allow_metadata_inventory_take and + not (def.groups.not_in_creative_inventory == 1) and + not (def.groups.not_cuttable == 1) and + not def.groups.wool and + (def.tiles and type(def.tiles[1]) == "string" and not + def.tiles[1]:find("default_mineral")) and + not def.mesecons and + def.description and + def.description ~= "" and + def.light_source == 0 +end diff --git a/mods/xdecor/handlers/nodeboxes.lua b/mods/xdecor/handlers/nodeboxes.lua new file mode 100644 index 0000000..4a3d8ca --- /dev/null +++ b/mods/xdecor/handlers/nodeboxes.lua @@ -0,0 +1,67 @@ +xdecor.box = { + slab_y = function(height, shift) + return { + -0.5, + -0.5 + (shift or 0), + -0.5, + 0.5, + -0.5 + height + (shift or 0), + 0.5 + } + end, + slab_z = function(depth) + return {-0.5, -0.5, -0.5 + depth, 0.5, 0.5, 0.5} + end, + bar_y = function(radius) + return {-radius, -0.5, -radius, radius, 0.5, radius} + end, + cuboid = function(radius_x, radius_y, radius_z) + return {-radius_x, -radius_y, -radius_z, radius_x, radius_y, radius_z} + end +} + +xdecor.nodebox = { + regular = {type = "regular"}, + null = { + type = "fixed", fixed = {0,0,0,0,0,0} + } +} + +xdecor.pixelbox = function(size, boxes) + local fixed = {} + for _, box in ipairs(boxes) do + -- `unpack` has been changed to `table.unpack` in newest Lua versions. + local x, y, z, w, h, l = unpack(box) + fixed[#fixed + 1] = { + (x / size) - 0.5, + (y / size) - 0.5, + (z / size) - 0.5, + ((x + w) / size) - 0.5, + ((y + h) / size) - 0.5, + ((z + l) / size) - 0.5 + } + end + + return {type = "fixed", fixed = fixed} +end + +local mt = {} + +mt.__index = function(table, key) + local ref = xdecor.box[key] + local ref_type = type(ref) + + if ref_type == "function" then + return function(...) + return {type = "fixed", fixed = ref(...)} + end + elseif ref_type == "table" then + return {type = "fixed", fixed = ref} + elseif ref_type == "nil" then + error(key .. "could not be found among nodebox presets and functions") + end + + error("unexpected datatype " .. tostring(type(ref)) .. " while looking for " .. key) +end + +setmetatable(xdecor.nodebox, mt) diff --git a/mods/xdecor/handlers/registration.lua b/mods/xdecor/handlers/registration.lua new file mode 100644 index 0000000..b16dc4b --- /dev/null +++ b/mods/xdecor/handlers/registration.lua @@ -0,0 +1,137 @@ +xbg = default.gui_bg .. default.gui_bg_img .. default.gui_slots +local default_inventory_size = 32 + +local default_inventory_formspecs = { + ["8"] = [[ size[8,6] + list[context;main;0,0;8,1;] + list[current_player;main;0,2;8,4;] + listring[current_player;main] + listring[context;main] ]] .. + default.get_hotbar_bg(0,2), + + ["16"] = [[ size[8,7] + list[context;main;0,0;8,2;] + list[current_player;main;0,3;8,4;] + listring[current_player;main] + listring[context;main] ]] .. + default.get_hotbar_bg(0,3), + + ["24"] = [[ size[8,8] + list[context;main;0,0;8,3;] + list[current_player;main;0,4;8,4;] + listring[current_player;main] + listring[context;main]" ]] .. + default.get_hotbar_bg(0,4), + + ["32"] = [[ size[8,9] + list[context;main;0,0.3;8,4;] + list[current_player;main;0,4.85;8,1;] + list[current_player;main;0,6.08;8,3;8] + listring[current_player;main] + listring[context;main] ]] .. + default.get_hotbar_bg(0,4.85) +} + +local function get_formspec_by_size(size) + local formspec = default_inventory_formspecs[tostring(size)] + return formspec or default_inventory_formspecs +end + +local default_can_dig = function(pos) + local inv = minetest.get_meta(pos):get_inventory() + return inv:is_empty("main") +end + +local function xdecor_stairs_alternative(nodename, def) + local mod, name = nodename:match("(.*):(.*)") + + for groupname, value in pairs(def.groups) do + if groupname ~= "cracky" and groupname ~= "choppy" and + groupname ~= "flammable" and groupname ~= "crumbly" and + groupname ~= "snappy" then + def.groups.groupname = nil + end + end + + if minetest.get_modpath("moreblocks") then + stairsplus:register_all( + mod, + name, + nodename, + { + description = def.description, + tiles = def.tiles, + groups = def.groups, + sounds = def.sounds, + } + ) + elseif minetest.get_modpath("stairs") then + stairs.register_stair_and_slab(name,nodename, + def.groups, + def.tiles, + ("%s Stair"):format(def.description), + ("%s Slab"):format(def.description), + def.sounds + ) + end + end + +function xdecor.register(name, def) + def.drawtype = def.drawtype or (def.mesh and "mesh") or (def.node_box and "nodebox") + def.sounds = def.sounds or default.node_sound_defaults() + + if not (def.drawtype == "normal" or def.drawtype == "signlike" or + def.drawtype == "plantlike" or def.drawtype == "glasslike_framed" or + def.drawtype == "glasslike_framed_optional") then + def.paramtype2 = def.paramtype2 or "facedir" + end + + if def.sunlight_propagates ~= false and + (def.drawtype == "plantlike" or def.drawtype == "torchlike" or + def.drawtype == "signlike" or def.drawtype == "fencelike") then + def.sunlight_propagates = true + end + + if not def.paramtype and + (def.light_source or def.sunlight_propagates or + def.drawtype == "nodebox" or def.drawtype == "mesh") then + def.paramtype = "light" + end + + local infotext = def.infotext + local inventory = def.inventory + def.inventory = nil + + if inventory then + def.on_construct = def.on_construct or function(pos) + local meta = minetest.get_meta(pos) + if infotext then meta:set_string("infotext", infotext) end + + local size = inventory.size or default_inventory_size + local inv = meta:get_inventory() + + inv:set_size("main", size) + meta:set_string("formspec", + (inventory.formspec or get_formspec_by_size(size)) .. xbg) + end + + def.can_dig = def.can_dig or default_can_dig + + elseif infotext and not def.on_construct then + def.on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("infotext", infotext) + end + end + + minetest.register_node("xdecor:" .. name, def) + + local workbench = minetest.settings:get_bool("enable_xdecor_workbench") + + if workbench == false and + (minetest.get_modpath("moreblocks") or minetest.get_modpath("stairs")) then + if xdecor.stairs_valid_def(def) then + xdecor_stairs_alternative("xdecor:"..name, def) + end + end +end diff --git a/mods/xdecor/init.lua b/mods/xdecor/init.lua new file mode 100644 index 0000000..79d63aa --- /dev/null +++ b/mods/xdecor/init.lua @@ -0,0 +1,58 @@ +--local t = os.clock() + +xdecor = {} +local modpath = minetest.get_modpath("xdecor") + +-- Intllib +local S +if minetest.get_translator ~= nil then + S = minetest.get_translator("xdecor") -- 5.x translation function +else + if minetest.get_modpath("intllib") then + dofile(minetest.get_modpath("intllib") .. "/init.lua") + if intllib.make_gettext_pair then + gettext, ngettext = intllib.make_gettext_pair() -- new gettext method + else + gettext = intllib.Getter() -- old text file method + end + S = gettext + else -- boilerplate function + S = function(str, ...) + local args = {...} + return str:gsub("@%d+", function(match) + return args[tonumber(match:sub(2))] + end) + end + end +end + +xdecor.S = S + +dofile(modpath .. "/handlers/animations.lua") +dofile(modpath .. "/handlers/helpers.lua") +dofile(modpath .. "/handlers/nodeboxes.lua") +dofile(modpath .. "/handlers/registration.lua") + +dofile(modpath .. "/src/nodes.lua") +dofile(modpath .. "/src/recipes.lua") + +local subpart = { + "chess", + "cooking", + "enchanting", + "hive", + "itemframe", + "mailbox", + "mechanisms", + "rope", + "workbench", +} + +for _, name in ipairs(subpart) do + local enable = minetest.settings:get_bool("enable_xdecor_" .. name) + if enable or enable == nil then + dofile(modpath .. "/src/" .. name .. ".lua") + end +end + +--print(string.format("[xdecor] loaded in %.2f ms", (os.clock()-t)*1000)) diff --git a/mods/xdecor/locale/template.txt b/mods/xdecor/locale/template.txt new file mode 100644 index 0000000..4addddd --- /dev/null +++ b/mods/xdecor/locale/template.txt @@ -0,0 +1,155 @@ +# textdomain: xdecor + + +### chess.lua ### + +Black Bishop= +Black King= +Black Knight= +Black Pawn= +Black Queen= +Black Rook= +Chess= +Chess Board= +Dumb AI= +Multiplayer= +New game= +Select a mode:= +Singleplayer= +Someone else plays black pieces!= +Someone else plays white pieces!= +White Bishop= +White King= +White Knight= +White Pawn= +White Queen= +White Rook= + +You can't dig the chessboard, a game has been started. Reset it first if you're a current player, or dig it again in @1= + +You can't reset the chessboard, a game has been started. If you aren't a current player, try again in @1= + +check= + +### cooking.lua ### + +Bowl= +Bowl of soup= +Cauldron= +Cauldron (active)= +Cauldron (active) - Drop foods inside to make a soup= +Cauldron (active) - Use a bowl to eat the soup= +Cauldron (empty)= +Cauldron (idle)= +No room in your inventory to add a bowl of soup.= +No room in your inventory to add a bucket of water.= + +### enchanting.lua ### + +Axe= +Bronze= +Diamond= +Durability= +Efficiency= +Enchanted @1 @2 @3= +Enchantment Table= +Mese= +Pickaxe= +Sharpness= +Shovel= +Steel= +Sword= +Your tool digs faster= +Your tool last longer= +Your weapon inflicts more damages= + +### hive.lua ### + +Artificial Hive= +Bees are busy making honey…= +Honey= + +### itemframe.lua ### + +@1 (owned by @2)= +Item Frame= + +### mailbox.lua ### + +@1's Mailbox= +Last donators= +Mailbox= +Send your goods to@n@1= +The mailbox is full.= + +### mechanisms.lua ### + +Lever= +Stone Pressure Plate= +Wooden Pressure Plate= + +### nodes.lua ### + +Bamboo Frame= +Baricade= +Barrel= +Cactus Brick= +Candle= +Chainlink= +Chair= +Coal Stone Tile= +Cobweb= +Cushion= +Cushion Block= +Desert Stone Tile= +Empty Shelf= +Ender Chest= +Garden Stone Path= +Half Wooden Cabinet= +Hardened Clay= +Iron Light Box= +Ivy= +Japanese Door= +Lantern= +Moon Brick= +Multi Shelf= +Packed Ice= +Painting= +Potted Geranium= +Potted Rose= +Potted Tulip= +Potted Viola= +Potted White Dandelion= +Potted Yellow Dandelion= +Prison Door= +Red Curtain= +Runestone= +Rusty Iron Bars= +Rusty Prison Door= +Screen Door= +Slide Door= +Stone Tile= +Table= +Tatami= +Television= +Trampoline= +Wood Frame= +Wood Framed Glass= +Wooden Cabinet= +Wooden Light Box= +Wooden Tile= +Woodglass Door= + +### rope.lua ### + +Rope= + +### workbench.lua ### + +Back= +Crafting= +Cut= +Hammer= +Repair= +Storage= +Work Bench= diff --git a/mods/xdecor/locale/xdecor.de.tr b/mods/xdecor/locale/xdecor.de.tr new file mode 100644 index 0000000..bdff769 --- /dev/null +++ b/mods/xdecor/locale/xdecor.de.tr @@ -0,0 +1,153 @@ +# textdomain: xdecor + + +### chess.lua ### + +Black Bishop=schwarzer Läufer +Black King=schwarter König +Black Knight=schwarzes Pferd +Black Pawn=schwarzer Bauer +Black Queen=schwarze Dame +Black Rook=schwarzer Turm +Chess=Schach +Chess Board=Schachbrett +Dumb AI=dumme KI +Multiplayer=Mehrspieler +New game=neues Spiel +Select a mode:=Wähle einen Modus: +Singleplayer=Einzelspieler +Someone else plays black pieces!=Jemand anderes spielt Schwarz! +Someone else plays white pieces!=Jemand anderes spielt Weiß! +White Bishop=weißer Läufer +White King=weißer König +White Knight=weißes Pferd +White Pawn=weißer Bauer +White Queen=weiße Dame +White Rook=weißer Turm +You can't dig the chessboard, a game has been started. Reset it first if you're a current player, or dig it again in @1=Das Schachbrett ist während eines Schachspieles nicht abbaubar. Setze das Spiel zurück, falls du ein Mitspieler bist oder versuche es in @1 erneut. +You can't reset the chessboard, a game has been started. If you aren't a current player, try again in @1=Das Schachbrett kann nicht zurückgesetzt werden, da ein Spiel im Gang ist. Versuche es in @1 erneut, falls du kein Mitspieler bist. + +check=Schach + +### cooking.lua ### + +Bowl=Schüssel +Bowl of soup=Suppenschüssel +Cauldron=Kessel +Cauldron (active)=Kessel (aktiv) +Cauldron (active) - Drop foods inside to make a soup=Kessel (aktiv) - Nahrungsmittel einwerfen, um Suppe zu machen. +Cauldron (active) - Use a bowl to eat the soup=Kessel (aktiv) - Benutze eine Schüssel, um die Suppe zu essen +Cauldron (empty)=Kessel (leer) +Cauldron (idle)=Kessel (untätig) +No room in your inventory to add a bowl of soup.=Zu wenig Platz im Inventar für eine Schüssel voll Suppe. +No room in your inventory to add a bucket of water.=Zu wenig Platz im Inventar für einen Eimer Wasser. + +### enchanting.lua ### + +Axe=axt +Bronze=Bronze +Diamond=Diamant +Durability=Haltbarkeit +Efficiency=Effizienz +Enchanted @1 @2 @3=verzauberte(s) @1@2 @3 +Enchantment Table=Zaubertisch +Mese=Mese +Pickaxe=Spitzhacke +Sharpness=Schärfe +Shovel=Schaufel +Steel=Eisen +Sword=Schwert +Your tool digs faster=Dein Werkzeug arbeitet schneller +Your tool last longer=Dein Werkzeug hält länger +Your weapon inflicts more damages=Deine Waffe erzeugt mehr Schaden + +### hive.lua ### + +Artificial Hive=künstlicher Bienenstock +Bees are busy making honey…=Bienen sind beschäftigt, Honig herzustellen. +Honey=Honig + +### itemframe.lua ### + +@1 (owned by @2)=@1 (gehört @2) +Item Frame=Objektrahmen + +### mailbox.lua ### + +@1's Mailbox=Briefkasten von @1 +Last donators=letzte Spender +Mailbox=Briefkasten +Send your goods to@n@1=Sende deine Waren an@n@1 +The mailbox is full.=Der Briefkasten ist voll. + +### mechanisms.lua ### + +Lever=Schalthebel +Stone Pressure Plate=steinerne Druckplatte +Wooden Pressure Plate=hölzerne Druckplatte + +### nodes.lua ### + +Bamboo Frame=Bambusgerüst +Baricade=Barrikade +Barrel=Fass +Cactus Brick=Kaktusstein +Candle=Kerze +Chainlink=Kettenvorhang +Chair=einfacher Stuhl +Coal Stone Tile=Kohle-Stein-Block +Cobweb=Spinnenwebe +Cushion=Sitzkissen +Cushion Block=Sitzkissenblock +Desert Stone Tile=Wüstensteinblock +Empty Shelf=leeres Regal +Ender Chest=Endertruhe +Garden Stone Path=Steingartenweg +Half Wooden Cabinet=halber Holzschrank +Hardened Clay=gehärteter Ton +Iron Light Box=eiseneingefasster Lichtblock +Ivy=Efeu +Japanese Door=japanische Tür +Lantern=Laterne +Moon Brick=Naturziegelwand +Multi Shelf=Mehrzweckregal +Packed Ice=Packeis +Painting=Gemälde +Potted Geranium=Geranien im Topf +Potted Rose=Rosen im Topf +Potted Tulip=Tulpen im Topf +Potted Viola=Veilchen im Topf +Potted White Dandelion=weißer Löwenzahn im Topf +Potted Yellow Dandelion=gelber Löwenzahn im Topf +Prison Door=Verliestür +Red Curtain=roter Vorhang +Runestone=Runensteinblock +Rusty Iron Bars=rostige Eisenstäbe +Rusty Prison Door=rostige Verliestür +Screen Door=französische Glastür +Slide Door=Schiebetür +Stone Tile=steinerner Block +Table=einfacher Tisch +Tatami=Tatamimatte +Television=Fernseher +Trampoline=Trampolin +Wood Frame=hölzerner Zierrahmen +Wood Framed Glass=holzeingefasstes Glas +Wooden Cabinet=Holzschrank +Wooden Light Box=holzeingefasster Lichtblock +Wooden Tile=hölzerner Dekorblock +Woodglass Door=Tür mit Lichtausschnitt + +### rope.lua ### + +Rope=Seil + +### workbench.lua ### + +Back=Zurück +Crafting=Fertigung +Cut=Zuschnitt +Hammer=Hämmerchen +Repair=Reparatur +Storage=Aufbewahrung +Work Bench=Werkbank diff --git a/mods/xdecor/locale/xdecor.fr.tr b/mods/xdecor/locale/xdecor.fr.tr new file mode 100644 index 0000000..52ae158 --- /dev/null +++ b/mods/xdecor/locale/xdecor.fr.tr @@ -0,0 +1,155 @@ +# textdomain: xdecor + + +### chess.lua ### + +Black Bishop=Fou noir +Black King=Roi noir +Black Knight=Cavalier noir +Black Pawn=Pion noir +Black Queen=Reine noire +Black Rook=Tour noire +Chess=Echecs +Chess Board=Echiquier +Dumb AI=IA stupide +Multiplayer=Multijoueur +New game=Nouvelle partie +Select a mode:=Sélectionnez un mode de jeu: +Singleplayer=Solo +Someone else plays black pieces!=Quelqu’un d’autre joue les pièces noires ! +Someone else plays white pieces!=Quelqu’un d’autre joue les pièces blanches ! +White Bishop=Fou blanc +White King=Roi blanc +White Knight=Cavalier blanc +White Pawn=Pion blanc +White Queen=Reine blanche +White Rook=Tour blanche + +You can't dig the chessboard, a game has been started. Reset it first if you're a current player, or dig it again in @1=Vous ne pouvez pas récupérer l’échiquier, une partie à été commencée. Remettez le à zéro si vous c’est votre tour de jouer, ou réessayez dans @1 + +You can't reset the chessboard, a game has been started. If you aren't a current player, try again in @1=Vous ne pouvez pas mettre à zéro l’échiquier, une partie a été commencée. Si ce n’est pas votre tour de jouer, réessayez dans @1 + +check=échec + +### cooking.lua ### + +Bowl=Bol +Bowl of soup=Bol de soupe +Cauldron=Chaudron +Cauldron (active)=Chaudron (actif) +Cauldron (active) - Drop foods inside to make a soup=Chaudron (actif) - Placez des ingrédients à l’intérieur pour faire une soupe +Cauldron (active) - Use a bowl to eat the soup=Chaudron (actif) - Utilisez un bol pour boire la soupe +Cauldron (empty)=Chaudron (vide) +Cauldron (idle)=Chaudron (inactif) +No room in your inventory to add a bowl of soup.=Pas de place dans votre inventaire pour ajouter un bol de soupe. +No room in your inventory to add a bucket of water.=Pas de place dans votre inventaire pour ajouter un seau d’eau. + +### enchanting.lua ### + +Axe=Hache +Bronze=Bronze +Diamond=Diamant +Durability=Durabilité +Efficiency=Efficacité +Enchanted @1 @2 @3=@2 en @1 enchantée @3 +Enchantment Table=Table d’enchantements +Mese=Mese +Pickaxe=Pioche +Sharpness=Tranchant +Shovel=Pelle +Steel=Fer +Sword=Épée +Your tool digs faster=Votre outil creuse plus vite +Your tool last longer=Votre outil dure plus longtemps +Your weapon inflicts more damages=Votre arme inflige plus de dégâts + +### hive.lua ### + +Artificial Hive=Ruche artificielle +Bees are busy making honey…=Les abeilles sont occupées à fabriquer du miel… +Honey=Miel + +### itemframe.lua ### + +@1 (owned by @2)=@1 (propriété de @2) +Item Frame=Cadre + +### mailbox.lua ### + +@1's Mailbox=Boite aux lettres de @1 +Last donators=Derniers donateurs +Mailbox=Boite aux lettres +Send your goods to@n@1=Envoyer vos biens à@n@1 +The mailbox is full.=La boite aux lettres est pleine. + +### mechanisms.lua ### + +Lever=Levier +Stone Pressure Plate=Plaque de pression en pierre +Wooden Pressure Plate=Plaque de pression en bois + +### nodes.lua ### + +Bamboo Frame=Cadre en bambou +Baricade=Barricade +Barrel=Tonneau +Cactus Brick=Brique en cactus +Candle=Bougie +Chainlink=Maillon de chaîne +Chair=Chaise +Coal Stone Tile=Carreau en charbon et pierre +Cobweb=Toile d’araignée +Cushion=Coussin +Cushion Block=Bloc de coussin +Desert Stone Tile=Carreau en pierre du désert +Empty Shelf=Étagère vide +Ender Chest=Coffre de l’End +Garden Stone Path=Chemin de pierres de jardin +Half Wooden Cabinet=Demi meuble en bois +Hardened Clay=Argile durcie +Iron Light Box=Boite lumineuse en fer +Ivy=Lierre +Japanese Door=Porte japonaise +Lantern=Lanterne +Moon Brick=Brique lunaire +Multi Shelf=Étagères multiple +Packed Ice=Glace compactée +Painting=Tableau +Potted Geranium=Géranium en pot +Potted Rose=Rose en pot +Potted Tulip=Tulipe en pot +Potted Viola=Violette en pot +Potted White Dandelion=Pissenlit blanc en pot +Potted Yellow Dandelion=Pissenlit jaune en pot +Prison Door=Porte de prison +Red Curtain=Rideaux rouge +Runestone=Pierre runique +Rusty Iron Bars=Barreaux en fer rouillé +Rusty Prison Door=Barreaux de prison rouillés +Screen Door=Porte avec moustiquaire +Slide Door=Porte coulissante +Stone Tile=Carreau en pierre +Table=Table +Tatami=Tatami +Television=Télévision +Trampoline=Trampoline +Wood Frame=Cadre en bois +Wood Framed Glass=Verre encadré par du bois +Wooden Cabinet=Meuble en bois +Wooden Light Box=Boite lumineuse en bois +Wooden Tile=Carreau en bois +Woodglass Door=Porte vitrée + +### rope.lua ### + +Rope=Corde + +### workbench.lua ### + +Back=Retour +Crafting=Fabrication +Cut=Couper +Hammer=Marteau +Repair=Réparer +Storage=Stockage +Work Bench=Atelier diff --git a/mods/xdecor/locale/xdecor.it.tr b/mods/xdecor/locale/xdecor.it.tr new file mode 100644 index 0000000..f88655b --- /dev/null +++ b/mods/xdecor/locale/xdecor.it.tr @@ -0,0 +1,155 @@ +# textdomain: xdecor +# Author: Salvo 'LtWorf' Tomaselli + +### chess.lua ### + +Black Bishop=Alfiere nero +Black King=Re nero +Black Knight=Cavallo nero +Black Pawn=Pedone nero +Black Queen=Regina nera +Black Rook=Torre nera +Chess=Scacchi +Chess Board=Scacchiera +Dumb AI=AI stupida +Multiplayer=Multigiocatore +New game=Nuova partita +Select a mode:=Selezionare una modalità +Singleplayer=Singolo giocatore +Someone else plays black pieces!=Qualcun altro gioca con il nero! +Someone else plays white pieces!=Qualcun altro gioca con il bianco! +White Bishop=Alfiere bianco +White King=Re bianco +White Knight=Cavallo bianco +White Pawn=Pedone bianco +White Queen=Regina bianca +White Rook=Torre bianca + +You can't dig the chessboard, a game has been started. Reset it first if you're a current player, or dig it again in @1=Non si può scavare la scacchiera, una partita è in corso. Resettarla se si è uno dei giocatori, o riprovare in @1 + +You can't reset the chessboard, a game has been started. If you aren't a current player, try again in @1=Non si può resettare la partita, un gioco è in corso. Se non si è uno dei giocatori, riprovare in @1 + +check=scacco + +### cooking.lua ### + +Bowl=Ciotola +Bowl of soup=Ciotola di zuppa +Cauldron=Calderone +Cauldron (active)=Calderone (attivo) +Cauldron (active) - Drop foods inside to make a soup=Calderone (attivo) - Mettere gli ingredienti all'interno per fare una zuppa. +Cauldron (active) - Use a bowl to eat the soup=Calderone (actif) - Utilizzare una ciotola per mangiare la zuppa +Cauldron (empty)=Calderone (vuoto) +Cauldron (idle)=Calderone (inattivo) +No room in your inventory to add a bowl of soup.=Non c'è spazio nell'inventario per aggiungere una ciotola di zuppa. +No room in your inventory to add a bucket of water.=Non c'è spazio nell'inventario per aggiungere un secchio di acqua. + +### enchanting.lua ### + +Axe=Ascia +Bronze=Bronzo +Diamond=Diamante +Durability=Durabilità +Efficiency=Efficacia +Enchanted @1 @2 @3=@2 su @1 incantesimo @3 +Enchantment Table=Tavolo per migliorie +Mese=Mese +Pickaxe=Piccone +Sharpness=Affilatezza +Shovel=Pala +Steel=Acciaio +Sword=Spada +Your tool digs faster=Il tuo utensile scava più rapidamente +Your tool last longer=Il tuo utensile dura di più +Your weapon inflicts more damages=La tua arma infligge più danno + +### hive.lua ### + +Artificial Hive=Favo artificiale +Bees are busy making honey…=Le api sono occupate a fare il miele… +Honey=Miele + +### itemframe.lua ### + +@1 (owned by @2)=@1 (proprietà di @2) +Item Frame=Teca + +### mailbox.lua ### + +@1's Mailbox=Cassetta delle lettere di @1 +Last donators=Ultimi donatori +Mailbox=Cassetta delle lettere +Send your goods to@n@1=Invia i tuoi item a@n@1 +The mailbox is full.=La cassetta delle lettere è piena + +### mechanisms.lua ### + +Lever=Leva +Stone Pressure Plate=Placca di pressione di pietra +Wooden Pressure Plate=Placca di pressione di legno + +### nodes.lua ### + +Bamboo Frame=Cornice di bambù +Baricade=Barricata +Barrel=Barile +Cactus Brick=Mattone di cactus +Candle=Candela +Chainlink=Cotta di maglia +Chair=Sedia +Coal Stone Tile=Mattonella di pietra di carbone +Cobweb=Ragnatela +Cushion=Cuscino +Cushion Block=Blocco di cuscini +Desert Stone Tile=Mattonella di pietra del deserto +Empty Shelf=Mensola vuota +Ender Chest=Baule ender +Garden Stone Path=Sentiero da giardino in pietra +Half Wooden Cabinet=Stipo di legno a metà +Hardened Clay=Argilla indurita +Iron Light Box=Scatola luminosa di ferro +Ivy=Edera +Japanese Door=Porta giapponese +Lantern=Lanterna +Moon Brick=Mattone lunare +Multi Shelf=Mensole +Packed Ice=Ghiaccio compatto +Painting=Dipinto +Potted Geranium=Geranio in vaso +Potted Rose=Rosa in vaso +Potted Tulip=Tulipano in vaso +Potted Viola=Violetta in vaso +Potted White Dandelion=Soffione bianco in vaso +Potted Yellow Dandelion=Soffione giallo in vaso +Prison Door=Porta di prigione +Red Curtain=Tenda rossa +Runestone=Pietra runica +Rusty Iron Bars=Sbarre di prigione arrugginite +Rusty Prison Door=Porta di prigione arrugginita +Screen Door=Porta a schermo +Slide Door=Porta scorrevole +Stone Tile=Mattonella di pietra +Table=Tavolo +Tatami=Tatami +Television=Televisione +Trampoline=Trampolino +Wood Frame=Cornice in legno +Wood Framed Glass=Cornice in legno con vetro +Wooden Cabinet=Stipo di legno +Wooden Light Box=Mattonella luminosa di legno +Wooden Tile=Mattonella di legno +Woodglass Door=Porta di vetro + +### rope.lua ### + +Rope=Corda + +### workbench.lua ### + +Back=Indietro +Crafting=Fabbricare +Cut=Tagliare +Hammer=Martello +Repair=Riparare +Storage=Conservare +Work Bench=Banco da lavoro diff --git a/mods/xdecor/mod.conf b/mods/xdecor/mod.conf new file mode 100644 index 0000000..5ae1cae --- /dev/null +++ b/mods/xdecor/mod.conf @@ -0,0 +1,5 @@ +name = xdecor +description = HOME decoration mod meant to be simple +depends = default, bucket, doors, farming, stairs, xpanes +optional_depends = fire, oresplus, moreblocks, mesecons +min_minetest_version = 0.4.16 diff --git a/mods/xdecor/screenshot.png b/mods/xdecor/screenshot.png new file mode 100644 index 0000000..ae0c2e1 Binary files /dev/null and b/mods/xdecor/screenshot.png differ diff --git a/mods/xdecor/settingtypes.txt b/mods/xdecor/settingtypes.txt new file mode 100644 index 0000000..f75d75c --- /dev/null +++ b/mods/xdecor/settingtypes.txt @@ -0,0 +1,11 @@ +#For enabling a subpart of X-Decor. + +enable_xdecor_chess (Enable Chess) bool true +enable_xdecor_cooking (Enable Cooking) bool true +enable_xdecor_enchanting (Enable Enchanting) bool true +enable_xdecor_hive (Enable Hive) bool true +enable_xdecor_itemframe (Enable Itemframe) bool true +enable_xdecor_mailbox (Enable Mailbox) bool true +enable_xdecor_mechanisms (Enable Mechanisms) bool true +enable_xdecor_rope (Enable Rope) bool true +enable_xdecor_workbench (Enable Workbench) bool true \ No newline at end of file diff --git a/mods/xdecor/sounds/xdecor_boiling_water.ogg b/mods/xdecor/sounds/xdecor_boiling_water.ogg new file mode 100644 index 0000000..cc1e7a5 Binary files /dev/null and b/mods/xdecor/sounds/xdecor_boiling_water.ogg differ diff --git a/mods/xdecor/sounds/xdecor_bouncy.ogg b/mods/xdecor/sounds/xdecor_bouncy.ogg new file mode 100644 index 0000000..779e825 Binary files /dev/null and b/mods/xdecor/sounds/xdecor_bouncy.ogg differ diff --git a/mods/xdecor/sounds/xdecor_enchanting.ogg b/mods/xdecor/sounds/xdecor_enchanting.ogg new file mode 100644 index 0000000..882e9ee Binary files /dev/null and b/mods/xdecor/sounds/xdecor_enchanting.ogg differ diff --git a/mods/xdecor/src/chess.lua b/mods/xdecor/src/chess.lua new file mode 100644 index 0000000..15c2dc1 --- /dev/null +++ b/mods/xdecor/src/chess.lua @@ -0,0 +1,1484 @@ +local realchess = {} +local S = xdecor.S +local FS = function(...) return minetest.formspec_escape(S(...)) end +local ALPHA_OPAQUE = minetest.features.use_texture_alpha_string_modes and "opaque" or false +screwdriver = screwdriver or {} + +local function index_to_xy(idx) + if not idx then + return nil + end + + idx = idx - 1 + + local x = idx % 8 + local y = (idx - x) / 8 + + return x, y +end + +local function xy_to_index(x, y) + return x + y * 8 + 1 +end + +local function get_square(a, b) + return (a * 8) - (8 - b) +end + +local chat_prefix = minetest.colorize("#FFFF00", "["..S("Chess").."] ") +local letters = {'A','B','C','D','E','F','G','H'} + +local function board_to_table(inv) + local t = {} + for i = 1, 64 do + t[#t + 1] = inv:get_stack("board", i):get_name() + end + + return t +end + +local piece_values = { + pawn = 10, + knight = 30, + bishop = 30, + rook = 50, + queen = 90, + king = 900 +} + +local function get_possible_moves(board, from_idx) + local piece, color = board[from_idx]:match(":(%w+)_(%w+)") + if not piece then return end + local moves = {} + local from_x, from_y = index_to_xy(from_idx) + + for i = 1, 64 do + local stack_name = board[i] + if stack_name:find((color == "black" and "white" or "black")) or + stack_name == "" then + moves[i] = 0 + end + end + + for to_idx in pairs(moves) do + local pieceTo = board[to_idx] + local to_x, to_y = index_to_xy(to_idx) + + -- PAWN + if piece == "pawn" then + if color == "white" then + local pawnWhiteMove = board[xy_to_index(from_x, from_y - 1)] + -- white pawns can go up only + if from_y - 1 == to_y then + if from_x == to_x then + if pieceTo ~= "" then + moves[to_idx] = nil + end + elseif from_x - 1 == to_x or from_x + 1 == to_x then + if not pieceTo:find("black") then + moves[to_idx] = nil + end + else + moves[to_idx] = nil + end + elseif from_y - 2 == to_y then + if pieceTo ~= "" or from_y < 6 or pawnWhiteMove ~= "" then + moves[to_idx] = nil + end + else + moves[to_idx] = nil + end + + --[[ + if x not changed + ensure that destination cell is empty + elseif x changed one unit left or right + ensure the pawn is killing opponent piece + else + move is not legal - abort + ]] + + if from_x == to_x then + if pieceTo ~= "" then + moves[to_idx] = nil + end + elseif from_x - 1 == to_x or from_x + 1 == to_x then + if not pieceTo:find("black") then + moves[to_idx] = nil + end + else + moves[to_idx] = nil + end + + elseif color == "black" then + local pawnBlackMove = board[xy_to_index(from_x, from_y + 1)] + -- black pawns can go down only + if from_y + 1 == to_y then + if from_x == to_x then + if pieceTo ~= "" then + moves[to_idx] = nil + end + elseif from_x - 1 == to_x or from_x + 1 == to_x then + if not pieceTo:find("white") then + moves[to_idx] = nil + end + else + moves[to_idx] = nil + end + elseif from_y + 2 == to_y then + if pieceTo ~= "" or from_y > 1 or pawnBlackMove ~= "" then + moves[to_idx] = nil + end + else + moves[to_idx] = nil + end + + --[[ + if x not changed + ensure that destination cell is empty + elseif x changed one unit left or right + ensure the pawn is killing opponent piece + else + move is not legal - abort + ]] + + if from_x == to_x then + if pieceTo ~= "" then + moves[to_idx] = nil + end + elseif from_x - 1 == to_x or from_x + 1 == to_x then + if not pieceTo:find("white") then + moves[to_idx] = nil + end + else + moves[to_idx] = nil + end + else + moves[to_idx] = nil + end + + -- ROOK + elseif piece == "rook" then + if from_x == to_x then + -- Moving vertically + if from_y < to_y then + -- Moving down + -- Ensure that no piece disturbs the way + for i = from_y + 1, to_y - 1 do + if board[xy_to_index(from_x, i)] ~= "" then + moves[to_idx] = nil + end + end + else + -- Mocing up + -- Ensure that no piece disturbs the way + for i = to_y + 1, from_y - 1 do + if board[xy_to_index(from_x, i)] ~= "" then + moves[to_idx] = nil + end + end + end + elseif from_y == to_y then + -- Mocing horizontally + if from_x < to_x then + -- mocing right + -- ensure that no piece disturbs the way + for i = from_x + 1, to_x - 1 do + if board[xy_to_index(i, from_y)] ~= "" then + moves[to_idx] = nil + end + end + else + -- Mocing left + -- Ensure that no piece disturbs the way + for i = to_x + 1, from_x - 1 do + if board[xy_to_index(i, from_y)] ~= "" then + moves[to_idx] = nil + end + end + end + else + -- Attempt to move arbitrarily -> abort + moves[to_idx] = nil + end + + -- KNIGHT + elseif piece == "knight" then + -- Get relative pos + local dx = from_x - to_x + local dy = from_y - to_y + + -- Get absolute values + if dx < 0 then + dx = -dx + end + + if dy < 0 then + dy = -dy + end + + -- Sort x and y + if dx > dy then + dx, dy = dy, dx + end + + -- Ensure that dx == 1 and dy == 2 + if dx ~= 1 or dy ~= 2 then + moves[to_idx] = nil + end + -- Just ensure that destination cell does not contain friend piece + -- ^ It was done already thus everything ok + + -- BISHOP + elseif piece == "bishop" then + -- Get relative pos + local dx = from_x - to_x + local dy = from_y - to_y + + -- Get absolute values + if dx < 0 then + dx = -dx + end + + if dy < 0 then + dy = -dy + end + + -- Ensure dx and dy are equal + if dx ~= dy then + moves[to_idx] = nil + end + + if from_x < to_x then + if from_y < to_y then + -- Moving right-down + -- Ensure that no piece disturbs the way + for i = 1, dx - 1 do + if board[xy_to_index(from_x + i, from_y + i)] ~= "" then + moves[to_idx] = nil + end + end + else + -- Moving right-up + -- Ensure that no piece disturbs the way + for i = 1, dx - 1 do + if board[xy_to_index(from_x + i, from_y - i)] ~= "" then + moves[to_idx] = nil + end + end + end + else + if from_y < to_y then + -- Moving left-down + -- Ensure that no piece disturbs the way + for i = 1, dx - 1 do + if board[xy_to_index(from_x - i, from_y + i)] ~= "" then + moves[to_idx] = nil + end + end + else + -- Moving left-up + -- ensure that no piece disturbs the way + for i = 1, dx - 1 do + if board[xy_to_index(from_x - i, from_y - i)] ~= "" then + moves[to_idx] = nil + end + end + end + end + + -- QUEEN + elseif piece == "queen" then + local dx = from_x - to_x + local dy = from_y - to_y + + -- Get absolute values + if dx < 0 then + dx = -dx + end + + if dy < 0 then + dy = -dy + end + + -- Ensure valid relative move + if dx ~= 0 and dy ~= 0 and dx ~= dy then + moves[to_idx] = nil + end + + if from_x == to_x then + -- Moving vertically + if from_y < to_y then + -- Moving down + -- Ensure that no piece disturbs the way + for i = from_y + 1, to_y - 1 do + if board[xy_to_index(from_x, i)] ~= "" then + moves[to_idx] = nil + end + end + else + -- Mocing up + -- Ensure that no piece disturbs the way + for i = to_y + 1, from_y - 1 do + if board[xy_to_index(from_x, i)] ~= "" then + moves[to_idx] = nil + end + end + end + elseif from_x < to_x then + if from_y == to_y then + -- Goes right + -- Ensure that no piece disturbs the way + for i = 1, dx - 1 do + if board[xy_to_index(from_x + i, from_y)] ~= "" then + moves[to_idx] = nil + end + end + elseif from_y < to_y then + -- Goes right-down + -- Ensure that no piece disturbs the way + for i = 1, dx - 1 do + if board[xy_to_index(from_x + i, from_y + i)] ~= "" then + moves[to_idx] = nil + end + end + else + -- Goes right-up + -- Ensure that no piece disturbs the way + for i = 1, dx - 1 do + if board[xy_to_index(from_x + i, from_y - i)] ~= "" then + moves[to_idx] = nil + end + end + end + else + if from_y == to_y then + -- Mocing horizontally + if from_x < to_x then + -- mocing right + -- ensure that no piece disturbs the way + for i = from_x + 1, to_x - 1 do + if board[xy_to_index(i, from_y)] ~= "" then + moves[to_idx] = nil + end + end + else + -- Mocing left + -- Ensure that no piece disturbs the way + for i = to_x + 1, from_x - 1 do + if board[xy_to_index(i, from_y)] ~= "" then + moves[to_idx] = nil + end + end + end + elseif from_y < to_y then + -- Goes left-down + -- Ensure that no piece disturbs the way + for i = 1, dx - 1 do + if board[xy_to_index(from_x - i, from_y + i)] ~= "" then + moves[to_idx] = nil + end + end + else + -- Goes left-up + -- Ensure that no piece disturbs the way + for i = 1, dx - 1 do + if board[xy_to_index(from_x - i, from_y - i)] ~= "" then + moves[to_idx] = nil + end + end + end + end + + -- KING + elseif piece == "king" then + local dx = from_x - to_x + local dy = from_y - to_y + + if dx < 0 then + dx = -dx + end + + if dy < 0 then + dy = -dy + end + + if dx > 1 or dy > 1 then + moves[to_idx] = nil + end + end + end + + if not next(moves) then return end + + for i in pairs(moves) do + local stack_name = board[tonumber(i)] + if stack_name ~= "" then + for p, value in pairs(piece_values) do + if stack_name:find(p) then + moves[i] = value + end + end + end + end + + return moves +end + +local function best_move(moves) + local value, choices = 0, {} + + for from, _ in pairs(moves) do + for to, val in pairs(_) do + if val > value then + value = val + choices = {{ + from = from, + to = to + }} + elseif val == value then + choices[#choices + 1] = { + from = from, + to = to + } + end + end + end + + local random = math.random(1, #choices) + local choice_from, choice_to = choices[random].from, choices[random].to + + return tonumber(choice_from), choice_to +end + +local rowDirs = {-1, -1, -1, 0, 0, 1, 1, 1} +local colDirs = {-1, 0, 1, -1, 1, -1, 0, 1} + +local rowDirsKnight = { 2, 1, 2, 1, -2, -1, -2, -1} +local colDirsKnight = {-1, -2, 1, 2, 1, 2, -1, -2} + +local bishopThreats = {true, false, true, false, false, true, false, true} +local rookThreats = {false, true, false, true, true, false, true, false} +local queenThreats = {true, true, true, true, true, true, true, true} +local kingThreats = {true, true, true, true, true, true, true, true} + +local function attacked(color, idx, board) + local threatDetected = false + local kill = color == "white" + local pawnThreats = {kill, false, kill, false, false, not kill, false, not kill} + + for dir = 1, 8 do + if not threatDetected then + local col, row = index_to_xy(idx) + col, row = col + 1, row + 1 + + for step = 1, 8 do + row = row + rowDirs[dir] + col = col + colDirs[dir] + + if row >= 1 and row <= 8 and col >= 1 and col <= 8 then + local square = get_square(row, col) + local square_name = board[square] + local piece, pieceColor = square_name:match(":(%w+)_(%w+)") + + if piece then + if pieceColor ~= color then + if piece == "bishop" and bishopThreats[dir] then + threatDetected = true + elseif piece == "rook" and rookThreats[dir] then + threatDetected = true + elseif piece == "queen" and queenThreats[dir] then + threatDetected = true + else + if step == 1 then + if piece == "pawn" and pawnThreats[dir] then + threatDetected = true + end + if piece == "king" and kingThreats[dir] then + threatDetected = true + end + end + end + end + break + end + end + end + + local colK, rowK = index_to_xy(idx) + colK, rowK = colK + 1, rowK + 1 + rowK = rowK + rowDirsKnight[dir] + colK = colK + colDirsKnight[dir] + + if rowK >= 1 and rowK <= 8 and colK >= 1 and colK <= 8 then + local square = get_square(rowK, colK) + local square_name = board[square] + local piece, pieceColor = square_name:match(":(%w+)_(%w+)") + + if piece and pieceColor ~= color and piece == "knight" then + threatDetected = true + end + end + end + end + + return threatDetected +end + +local function locate_kings(board) + local Bidx, Widx + for i = 1, 64 do + local piece, color = board[i]:match(":(%w+)_(%w+)") + if piece == "king" then + if color == "black" then + Bidx = i + else + Widx = i + end + end + end + + return Bidx, Widx +end + +local pieces = { + "realchess:rook_black_1", + "realchess:knight_black_1", + "realchess:bishop_black_1", + "realchess:queen_black", + "realchess:king_black", + "realchess:bishop_black_2", + "realchess:knight_black_2", + "realchess:rook_black_2", + "realchess:pawn_black_1", + "realchess:pawn_black_2", + "realchess:pawn_black_3", + "realchess:pawn_black_4", + "realchess:pawn_black_5", + "realchess:pawn_black_6", + "realchess:pawn_black_7", + "realchess:pawn_black_8", + '','','','','','','','','','','','','','','','', + '','','','','','','','','','','','','','','','', + "realchess:pawn_white_1", + "realchess:pawn_white_2", + "realchess:pawn_white_3", + "realchess:pawn_white_4", + "realchess:pawn_white_5", + "realchess:pawn_white_6", + "realchess:pawn_white_7", + "realchess:pawn_white_8", + "realchess:rook_white_1", + "realchess:knight_white_1", + "realchess:bishop_white_1", + "realchess:queen_white", + "realchess:king_white", + "realchess:bishop_white_2", + "realchess:knight_white_2", + "realchess:rook_white_2" +} + +local pieces_str, x = "", 0 +for i = 1, #pieces do + local p = pieces[i]:match(":(%w+_%w+)") + if pieces[i]:find(":(%w+)_(%w+)") and not pieces_str:find(p) then + pieces_str = pieces_str .. x .. "=" .. p .. ".png," + x = x + 1 + end +end +pieces_str = pieces_str .. "69=mailbox_blank16.png" + +local fs_init = [[ + size[4,1.2;] + no_prepend[] + ]] + .."label[0,0;"..FS("Select a mode:").."]" + .."button[0,0.5;2,1;single;"..FS("Singleplayer").."]" + .."button[2,0.5;2,1;multi;"..FS("Multiplayer").."]" + +local fs = [[ + size[14.7,10;] + no_prepend[] + bgcolor[#080808BB;true] + background[0,0;14.7,10;chess_bg.png] + list[context;board;0.3,1;8,8;] + listcolors[#00000000;#00000000;#00000000;#30434C;#FFF] + tableoptions[background=#00000000;highlight=#00000000;border=false] + ]] + .."button[10.5,8.5;2,2;new;"..FS("New game").."]" + .."tablecolumns[image," .. pieces_str .. + ";text;color;text;color;text;image," .. pieces_str .. "]" + +local function update_formspec(meta) + local black_king_attacked = meta:get_string("blackAttacked") == "true" + local white_king_attacked = meta:get_string("whiteAttacked") == "true" + + local playerWhite = meta:get_string("playerWhite") + local playerBlack = meta:get_string("playerBlack") + + local moves = meta:get_string("moves") + local eaten_img = meta:get_string("eaten_img") + local lastMove = meta:get_string("lastMove") + local turnBlack = minetest.colorize("#000001", (lastMove == "white" and playerBlack ~= "") and + playerBlack .. "..." or playerBlack) + local turnWhite = minetest.colorize("#000001", (lastMove == "black" and playerWhite ~= "") and + playerWhite .. "..." or playerWhite) + local check_s = minetest.colorize("#FF0000", "\\["..FS("check").."\\]") + + local formspec = fs .. + "label[1.9,0.3;" .. turnBlack .. (black_king_attacked and " " .. check_s or "") .. "]" .. + "label[1.9,9.15;" .. turnWhite .. (white_king_attacked and " " .. check_s or "") .. "]" .. + "table[8.9,1.05;5.07,3.75;moves;" .. moves:sub(1,-2) .. ";1]" .. + eaten_img + + meta:set_string("formspec", formspec) +end + +local function get_moves_list(meta, pieceFrom, pieceTo, pieceTo_s, from_idx, to_idx) + local from_x, from_y = index_to_xy(from_idx) + local to_x, to_y = index_to_xy(to_idx) + local moves = meta:get_string("moves") + local pieceFrom_s = pieceFrom:match(":(%w+_%w+)") + local pieceFrom_si_id = pieces_str:match("(%d+)=" .. pieceFrom_s) + local pieceTo_si_id = pieceTo_s ~= "" and pieces_str:match("(%d+)=" .. pieceTo_s) or "" + + local coordFrom = letters[from_x + 1] .. math.abs(from_y - 8) + local coordTo = letters[to_x + 1] .. math.abs(to_y - 8) + + local new_moves = pieceFrom_si_id .. "," .. + coordFrom .. "," .. + (pieceTo ~= "" and "#33FF33" or "#FFFFFF") .. ", > ,#FFFFFF," .. + coordTo .. "," .. + (pieceTo ~= "" and pieceTo_si_id or "69") .. "," .. + moves + + meta:set_string("moves", new_moves) +end + +local function get_eaten_list(meta, pieceTo, pieceTo_s) + local eaten = meta:get_string("eaten") + if pieceTo ~= "" then + eaten = eaten .. pieceTo_s .. "," + end + + meta:set_string("eaten", eaten) + + local eaten_t = string.split(eaten, ",") + local eaten_img = "" + + local a, b = 0, 0 + for i = 1, #eaten_t do + local is_white = eaten_t[i]:sub(-5,-1) == "white" + local X = (is_white and a or b) % 4 + local Y = ((is_white and a or b) % 16 - X) / 4 + + if is_white then + a = a + 1 + else + b = b + 1 + end + + eaten_img = eaten_img .. + "image[" .. ((X + (is_white and 11.67 or 8.8)) - (X * 0.45)) .. "," .. + ((Y + 5.56) - (Y * 0.2)) .. ";1,1;" .. eaten_t[i] .. ".png]" + end + + meta:set_string("eaten_img", eaten_img) +end + +function realchess.init(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + + meta:set_string("formspec", fs_init) + meta:set_string("infotext", S("Chess Board")) + meta:set_string("playerBlack", "") + meta:set_string("playerWhite", "") + meta:set_string("lastMove", "") + meta:set_string("blackAttacked", "") + meta:set_string("whiteAttacked", "") + + meta:set_int("lastMoveTime", 0) + meta:set_int("castlingBlackL", 1) + meta:set_int("castlingBlackR", 1) + meta:set_int("castlingWhiteL", 1) + meta:set_int("castlingWhiteR", 1) + + meta:set_string("moves", "") + meta:set_string("eaten", "") + meta:set_string("mode", "") + + inv:set_list("board", pieces) + inv:set_size("board", 64) +end + +function realchess.move(pos, from_list, from_index, to_list, to_index, _, player) + if from_list ~= "board" and to_list ~= "board" then + return 0 + end + + local meta = minetest.get_meta(pos) + local playerName = player:get_player_name() + local inv = meta:get_inventory() + local pieceFrom = inv:get_stack(from_list, from_index):get_name() + local pieceTo = inv:get_stack(to_list, to_index):get_name() + local lastMove = meta:get_string("lastMove") + local playerWhite = meta:get_string("playerWhite") + local playerBlack = meta:get_string("playerBlack") + local thisMove -- Will replace lastMove when move is legal + + if pieceFrom:find("white") then + if playerWhite ~= "" and playerWhite ~= playerName then + minetest.chat_send_player(playerName, chat_prefix .. S("Someone else plays white pieces!")) + return 0 + end + + if lastMove ~= "" and lastMove ~= "black" then + return 0 + end + + if pieceTo:find("white") then + -- Don't replace pieces of same color + return 0 + end + + playerWhite = playerName + thisMove = "white" + + elseif pieceFrom:find("black") then + if playerBlack ~= "" and playerBlack ~= playerName then + minetest.chat_send_player(playerName, chat_prefix .. S("Someone else plays black pieces!")) + return 0 + end + + if lastMove ~= "" and lastMove ~= "white" then + return 0 + end + + if pieceTo:find("black") then + -- Don't replace pieces of same color + return 0 + end + + playerBlack = playerName + thisMove = "black" + end + + -- MOVE LOGIC + + local from_x, from_y = index_to_xy(from_index) + local to_x, to_y = index_to_xy(to_index) + + -- PAWN + if pieceFrom:sub(11,14) == "pawn" then + if thisMove == "white" then + local pawnWhiteMove = inv:get_stack(from_list, xy_to_index(from_x, from_y - 1)):get_name() + -- white pawns can go up only + if from_y - 1 == to_y then + if from_x == to_x then + if pieceTo ~= "" then + return 0 + elseif to_index >= 1 and to_index <= 8 then + inv:set_stack(from_list, from_index, "realchess:queen_white") + end + elseif from_x - 1 == to_x or from_x + 1 == to_x then + if not pieceTo:find("black") then + return 0 + elseif to_index >= 1 and to_index <= 8 then + inv:set_stack(from_list, from_index, "realchess:queen_white") + end + else + return 0 + end + elseif from_y - 2 == to_y then + if pieceTo ~= "" or from_y < 6 or pawnWhiteMove ~= "" then + return 0 + end + else + return 0 + end + + --[[ + if x not changed + ensure that destination cell is empty + elseif x changed one unit left or right + ensure the pawn is killing opponent piece + else + move is not legal - abort + ]] + + if from_x == to_x then + if pieceTo ~= "" then + return 0 + end + elseif from_x - 1 == to_x or from_x + 1 == to_x then + if not pieceTo:find("black") then + return 0 + end + else + return 0 + end + + elseif thisMove == "black" then + local pawnBlackMove = inv:get_stack(from_list, xy_to_index(from_x, from_y + 1)):get_name() + -- black pawns can go down only + if from_y + 1 == to_y then + if from_x == to_x then + if pieceTo ~= "" then + return 0 + elseif to_index >= 57 and to_index <= 64 then + inv:set_stack(from_list, from_index, "realchess:queen_black") + end + elseif from_x - 1 == to_x or from_x + 1 == to_x then + if not pieceTo:find("white") then + return 0 + elseif to_index >= 57 and to_index <= 64 then + inv:set_stack(from_list, from_index, "realchess:queen_black") + end + else + return 0 + end + elseif from_y + 2 == to_y then + if pieceTo ~= "" or from_y > 1 or pawnBlackMove ~= "" then + return 0 + end + else + return 0 + end + + --[[ + if x not changed + ensure that destination cell is empty + elseif x changed one unit left or right + ensure the pawn is killing opponent piece + else + move is not legal - abort + ]] + + if from_x == to_x then + if pieceTo ~= "" then + return 0 + end + elseif from_x - 1 == to_x or from_x + 1 == to_x then + if not pieceTo:find("white") then + return 0 + end + else + return 0 + end + else + return 0 + end + + -- ROOK + elseif pieceFrom:sub(11,14) == "rook" then + if from_x == to_x then + -- Moving vertically + if from_y < to_y then + -- Moving down + -- Ensure that no piece disturbs the way + for i = from_y + 1, to_y - 1 do + if inv:get_stack(from_list, xy_to_index(from_x, i)):get_name() ~= "" then + return 0 + end + end + else + -- Mocing up + -- Ensure that no piece disturbs the way + for i = to_y + 1, from_y - 1 do + if inv:get_stack(from_list, xy_to_index(from_x, i)):get_name() ~= "" then + return 0 + end + end + end + elseif from_y == to_y then + -- Mocing horizontally + if from_x < to_x then + -- mocing right + -- ensure that no piece disturbs the way + for i = from_x + 1, to_x - 1 do + if inv:get_stack(from_list, xy_to_index(i, from_y)):get_name() ~= "" then + return 0 + end + end + else + -- Mocing left + -- Ensure that no piece disturbs the way + for i = to_x + 1, from_x - 1 do + if inv:get_stack(from_list, xy_to_index(i, from_y)):get_name() ~= "" then + return 0 + end + end + end + else + -- Attempt to move arbitrarily -> abort + return 0 + end + + if thisMove == "white" or thisMove == "black" then + if pieceFrom:sub(-1) == "1" then + meta:set_int("castlingWhiteL", 0) + elseif pieceFrom:sub(-1) == "2" then + meta:set_int("castlingWhiteR", 0) + end + end + + -- KNIGHT + elseif pieceFrom:sub(11,16) == "knight" then + -- Get relative pos + local dx = from_x - to_x + local dy = from_y - to_y + + -- Get absolute values + if dx < 0 then dx = -dx end + if dy < 0 then dy = -dy end + + -- Sort x and y + if dx > dy then dx, dy = dy, dx end + + -- Ensure that dx == 1 and dy == 2 + if dx ~= 1 or dy ~= 2 then + return 0 + end + -- Just ensure that destination cell does not contain friend piece + -- ^ It was done already thus everything ok + + -- BISHOP + elseif pieceFrom:sub(11,16) == "bishop" then + -- Get relative pos + local dx = from_x - to_x + local dy = from_y - to_y + + -- Get absolute values + if dx < 0 then dx = -dx end + if dy < 0 then dy = -dy end + + -- Ensure dx and dy are equal + if dx ~= dy then return 0 end + + if from_x < to_x then + if from_y < to_y then + -- Moving right-down + -- Ensure that no piece disturbs the way + for i = 1, dx - 1 do + if inv:get_stack( + from_list, xy_to_index(from_x + i, from_y + i)):get_name() ~= "" then + return 0 + end + end + else + -- Moving right-up + -- Ensure that no piece disturbs the way + for i = 1, dx - 1 do + if inv:get_stack( + from_list, xy_to_index(from_x + i, from_y - i)):get_name() ~= "" then + return 0 + end + end + end + else + if from_y < to_y then + -- Moving left-down + -- Ensure that no piece disturbs the way + for i = 1, dx - 1 do + if inv:get_stack( + from_list, xy_to_index(from_x - i, from_y + i)):get_name() ~= "" then + return 0 + end + end + else + -- Moving left-up + -- ensure that no piece disturbs the way + for i = 1, dx - 1 do + if inv:get_stack( + from_list, xy_to_index(from_x - i, from_y - i)):get_name() ~= "" then + return 0 + end + end + end + end + + -- QUEEN + elseif pieceFrom:sub(11,15) == "queen" then + local dx = from_x - to_x + local dy = from_y - to_y + + -- Get absolute values + if dx < 0 then dx = -dx end + if dy < 0 then dy = -dy end + + -- Ensure valid relative move + if dx ~= 0 and dy ~= 0 and dx ~= dy then + return 0 + end + + if from_x == to_x then + if from_y < to_y then + -- Goes down + -- Ensure that no piece disturbs the way + for i = from_y + 1, to_y - 1 do + if inv:get_stack(from_list, xy_to_index(from_x, i)):get_name() ~= "" then + return 0 + end + end + else + -- Goes up + -- Ensure that no piece disturbs the way + for i = to_y + 1, from_y - 1 do + if inv:get_stack(from_list, xy_to_index(from_x, i)):get_name() ~= "" then + return 0 + end + end + end + elseif from_x < to_x then + if from_y == to_y then + -- Goes right + -- Ensure that no piece disturbs the way + for i = from_x + 1, to_x - 1 do + if inv:get_stack(from_list, xy_to_index(i, from_y)):get_name() ~= "" then + return 0 + end + end + elseif from_y < to_y then + -- Goes right-down + -- Ensure that no piece disturbs the way + for i = 1, dx - 1 do + if inv:get_stack( + from_list, xy_to_index(from_x + i, from_y + i)):get_name() ~= "" then + return 0 + end + end + else + -- Goes right-up + -- Ensure that no piece disturbs the way + for i = 1, dx - 1 do + if inv:get_stack( + from_list, xy_to_index(from_x + i, from_y - i)):get_name() ~= "" then + return 0 + end + end + end + else + if from_y == to_y then + -- Goes left + -- Ensure that no piece disturbs the way and destination cell does + for i = to_x + 1, from_x - 1 do + if inv:get_stack(from_list, xy_to_index(i, from_y)):get_name() ~= "" then + return 0 + end + end + elseif from_y < to_y then + -- Goes left-down + -- Ensure that no piece disturbs the way + for i = 1, dx - 1 do + if inv:get_stack( + from_list, xy_to_index(from_x - i, from_y + i)):get_name() ~= "" then + return 0 + end + end + else + -- Goes left-up + -- Ensure that no piece disturbs the way + for i = 1, dx - 1 do + if inv:get_stack( + from_list, xy_to_index(from_x - i, from_y - i)):get_name() ~= "" then + return 0 + end + end + end + end + + -- KING + elseif pieceFrom:sub(11,14) == "king" then + local dx = from_x - to_x + local dy = from_y - to_y + local check = true + + if thisMove == "white" then + if from_y == 7 and to_y == 7 then + if to_x == 2 then + local castlingWhiteL = meta:get_int("castlingWhiteL") + local idx57 = inv:get_stack(from_list, 57):get_name() + + if castlingWhiteL == 1 and idx57 == "realchess:rook_white_1" then + for i = 58, from_index - 1 do + if inv:get_stack(from_list, i):get_name() ~= "" then + return 0 + end + end + + inv:set_stack(from_list, 57, "") + inv:set_stack(from_list, 60, "realchess:rook_white_1") + check = false + end + elseif to_x == 6 then + local castlingWhiteR = meta:get_int("castlingWhiteR") + local idx64 = inv:get_stack(from_list, 64):get_name() + + if castlingWhiteR == 1 and idx64 == "realchess:rook_white_2" then + for i = from_index + 1, 63 do + if inv:get_stack(from_list, i):get_name() ~= "" then + return 0 + end + end + + inv:set_stack(from_list, 62, "realchess:rook_white_2") + inv:set_stack(from_list, 64, "") + check = false + end + end + end + elseif thisMove == "black" then + if from_y == 0 and to_y == 0 then + if to_x == 2 then + local castlingBlackL = meta:get_int("castlingBlackL") + local idx1 = inv:get_stack(from_list, 1):get_name() + + if castlingBlackL == 1 and idx1 == "realchess:rook_black_1" then + for i = 2, from_index - 1 do + if inv:get_stack(from_list, i):get_name() ~= "" then + return 0 + end + end + + inv:set_stack(from_list, 1, "") + inv:set_stack(from_list, 4, "realchess:rook_black_1") + check = false + end + elseif to_x == 6 then + local castlingBlackR = meta:get_int("castlingBlackR") + local idx8 = inv:get_stack(from_list, 8):get_name() + + if castlingBlackR == 1 and idx8 == "realchess:rook_black_2" then + for i = from_index + 1, 7 do + if inv:get_stack(from_list, i):get_name() ~= "" then + return 0 + end + end + + inv:set_stack(from_list, 6, "realchess:rook_black_2") + inv:set_stack(from_list, 8, "") + check = false + end + end + end + end + + if check then + if dx < 0 then + dx = -dx + end + + if dy < 0 then + dy = -dy + end + + if dx > 1 or dy > 1 then + return 0 + end + end + + if thisMove == "white" then + meta:set_int("castlingWhiteL", 0) + meta:set_int("castlingWhiteR", 0) + + elseif thisMove == "black" then + meta:set_int("castlingBlackL", 0) + meta:set_int("castlingBlackR", 0) + end + end + + local board = board_to_table(inv) + board[to_index] = board[from_index] + board[from_index] = "" + + local black_king_idx, white_king_idx = locate_kings(board) + if not black_king_idx or not white_king_idx then + return 0 + end + local blackAttacked = attacked("black", black_king_idx, board) + local whiteAttacked = attacked("white", white_king_idx, board) + + if blackAttacked then + if thisMove == "black" then + --[(*)[ and meta:get_string("blackAttacked") == "true" ]] then + return 0 + else + meta:set_string("blackAttacked", "true") + end + else + meta:set_string("blackAttacked", "") + end + + if whiteAttacked then + if thisMove == "white" then + --[(*)[ and meta:get_string("whiteAttacked") == "true" ]] then + return 0 + else + meta:set_string("whiteAttacked", "true") + end + else + meta:set_string("whiteAttacked", "") + end + + --(*) Allow a piece to move and put its king in check. Maybe not in the chess rules though? + + lastMove = thisMove + meta:set_string("lastMove", lastMove) + meta:set_int("lastMoveTime", minetest.get_gametime()) + + if meta:get_string("playerWhite") == "" then + meta:set_string("playerWhite", playerWhite) + elseif meta:get_string("playerBlack") == "" then + meta:set_string("playerBlack", playerBlack) + end + + local pieceTo_s = pieceTo ~= "" and pieceTo:match(":(%w+_%w+)") or "" + get_moves_list(meta, pieceFrom, pieceTo, pieceTo_s, from_index, to_index) + get_eaten_list(meta, pieceTo, pieceTo_s) + + return 1 +end + +local function ai_move(inv, meta) + local board_t = board_to_table(inv) + local lastMove = meta:get_string("lastMove") + + if lastMove == "white" then + update_formspec(meta) + local moves = {} + + for i = 1, 64 do + local possibleMoves = get_possible_moves(board_t, i) + local stack_name = inv:get_stack("board", i):get_name() + + if stack_name:find("black") then + moves[tostring(i)] = possibleMoves + end + end + + local choice_from, choice_to = best_move(moves) + + local pieceFrom = inv:get_stack("board", choice_from):get_name() + local pieceTo = inv:get_stack("board", choice_to):get_name() + local pieceTo_s = pieceTo ~= "" and pieceTo:match(":(%w+_%w+)") or "" + + local board = board_to_table(inv) + local black_king_idx = locate_kings(board) + local blackAttacked = attacked("black", black_king_idx, board) + local kingSafe = true + local bestMoveSaveFrom, bestMoveSaveTo + + if blackAttacked then + kingSafe = false + meta:set_string("blackAttacked", "true") + local save_moves = {} + + for from_idx, _ in pairs(moves) do + for to_idx, value in pairs(_) do + from_idx = tonumber(from_idx) + local from_idx_bak, to_idx_bak = board[from_idx], board[to_idx] + board[to_idx] = board[from_idx] + board[from_idx] = "" + black_king_idx = locate_kings(board) + + if black_king_idx then + blackAttacked = attacked("black", black_king_idx, board) + if not blackAttacked then + save_moves[from_idx] = save_moves[from_idx] or {} + save_moves[from_idx][to_idx] = value + end + end + + board[from_idx], board[to_idx] = from_idx_bak, to_idx_bak + end + end + + if next(save_moves) then + bestMoveSaveFrom, bestMoveSaveTo = best_move(save_moves) + end + end + + minetest.after(1.0, function() + local lastMoveTime = meta:get_int("lastMoveTime") + if lastMoveTime > 0 then + if not kingSafe then + if bestMoveSaveTo then + inv:set_stack("board", bestMoveSaveTo, board[bestMoveSaveFrom]) + inv:set_stack("board", bestMoveSaveFrom, "") + meta:set_string("blackAttacked", "") + else + return + end + else + if pieceFrom:find("pawn") and choice_to >= 57 and choice_to <= 64 then + inv:set_stack("board", choice_to, "realchess:queen_black") + else + inv:set_stack("board", choice_to, pieceFrom) + end + + inv:set_stack("board", choice_from, "") + end + + board = board_to_table(inv) + local _, white_king_idx = locate_kings(board) + local whiteAttacked = attacked("white", white_king_idx, board) + + if whiteAttacked then + meta:set_string("whiteAttacked", "true") + end + + if meta:get_string("playerBlack") == "" then + meta:set_string("playerBlack", S("Dumb AI")) + end + + meta:set_string("lastMove", "black") + meta:set_int("lastMoveTime", minetest.get_gametime()) + + get_moves_list(meta, pieceFrom, pieceTo, pieceTo_s, choice_from, choice_to) + get_eaten_list(meta, pieceTo, pieceTo_s) + + update_formspec(meta) + end + end) + else + update_formspec(meta) + end +end + +function realchess.on_move(pos, from_list, from_index) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + inv:set_stack(from_list, from_index, "") + + if meta:get_string("mode") == "single" then + ai_move(inv, meta) + end + + return false +end + +local function timeout_format(timeout_limit) + local time_remaining = timeout_limit - minetest.get_gametime() + local minutes = math.floor(time_remaining / 60) + local seconds = time_remaining % 60 + + if minutes == 0 then + return seconds .. " sec." + end + + return minutes .. " min. " .. seconds .. " sec." +end + +function realchess.fields(pos, _, fields, sender) + local playerName = sender:get_player_name() + local meta = minetest.get_meta(pos) + local timeout_limit = meta:get_int("lastMoveTime") + 300 + local playerWhite = meta:get_string("playerWhite") + local playerBlack = meta:get_string("playerBlack") + local lastMoveTime = meta:get_int("lastMoveTime") + if fields.quit then return end + + if fields.single or fields.multi then + meta:set_string("mode", (fields.single and "single" or "multi")) + update_formspec(meta) + return + end + + -- Timeout is 5 min. by default for resetting the game (non-players only) + if fields.new then + if (playerWhite == playerName or playerBlack == playerName) then + realchess.init(pos) + + elseif lastMoveTime > 0 then + if minetest.get_gametime() >= timeout_limit and + (playerWhite ~= playerName or playerBlack ~= playerName) then + realchess.init(pos) + else + minetest.chat_send_player(playerName, chat_prefix .. + S("You can't reset the chessboard, a game has been started. " .. + "If you aren't a current player, try again in @1", + timeout_format(timeout_limit))) + end + end + end +end + +function realchess.dig(pos, player) + if not player then + return false + end + + local meta = minetest.get_meta(pos) + local playerName = player:get_player_name() + local timeout_limit = meta:get_int("lastMoveTime") + 300 + local lastMoveTime = meta:get_int("lastMoveTime") + + -- Timeout is 5 min. by default for digging the chessboard (non-players only) + return (lastMoveTime == 0 and minetest.get_gametime() > timeout_limit) or + minetest.chat_send_player(playerName, chat_prefix .. + S("You can't dig the chessboard, a game has been started. " .. + "Reset it first if you're a current player, or dig it again in @1", + timeout_format(timeout_limit))) +end + +minetest.register_node(":realchess:chessboard", { + description = S("Chess Board"), + drawtype = "nodebox", + paramtype = "light", + paramtype2 = "facedir", + inventory_image = "chessboard_top.png", + wield_image = "chessboard_top.png", + tiles = {"chessboard_top.png", "chessboard_top.png", "chessboard_sides.png"}, + use_texture_alpha = ALPHA_OPAQUE, + groups = {choppy=3, oddly_breakable_by_hand=2, flammable=3}, + sounds = default.node_sound_wood_defaults(), + node_box = {type = "fixed", fixed = {-.375, -.5, -.375, .375, -.4375, .375}}, + sunlight_propagates = true, + on_rotate = screwdriver.rotate_simple, + can_dig = realchess.dig, + on_construct = realchess.init, + on_receive_fields = realchess.fields, + allow_metadata_inventory_move = realchess.move, + on_metadata_inventory_move = realchess.on_move, + allow_metadata_inventory_take = function() return 0 end +}) + +local function register_piece(name, white_desc, black_desc, count) + for _, color in pairs({"black", "white"}) do + if not count then + minetest.register_craftitem(":realchess:" .. name .. "_" .. color, { + description = (color == "black") and black_desc or white_desc, + inventory_image = name .. "_" .. color .. ".png", + stack_max = 1, + groups = {not_in_creative_inventory=1} + }) + else + for i = 1, count do + minetest.register_craftitem(":realchess:" .. name .. "_" .. color .. "_" .. i, { + description = (color == "black") and black_desc or white_desc, + inventory_image = name .. "_" .. color .. ".png", + stack_max = 1, + groups = {not_in_creative_inventory=1} + }) + end + end + end +end + +register_piece("pawn", S("White Pawn"), S("Black Pawn"), 8) +register_piece("rook", S("White Rook"), S("Black Rook"), 2) +register_piece("knight", S("White Knight"), S("Black Knight"), 2) +register_piece("bishop", S("White Bishop"), S("Black Bishop"), 2) +register_piece("queen", S("White Queen"), S("Black Queen")) +register_piece("king", S("White King"), S("Black King")) + +-- Recipes + +minetest.register_craft({ + output = "realchess:chessboard", + recipe = { + {"dye:black", "dye:white", "dye:black"}, + {"stairs:slab_wood", "stairs:slab_wood", "stairs:slab_wood"} + } +}) diff --git a/mods/xdecor/src/cooking.lua b/mods/xdecor/src/cooking.lua new file mode 100644 index 0000000..3dae2f4 --- /dev/null +++ b/mods/xdecor/src/cooking.lua @@ -0,0 +1,267 @@ +local cauldron, sounds = {}, {} +local S = xdecor.S + +-- Add more ingredients here that make a soup. +local ingredients_list = { + "apple", "mushroom", "honey", "pumpkin", "egg", "bread", "meat", + "chicken", "carrot", "potato", "melon", "rhubarb", "cucumber", + "corn", "beans", "berries", "grapes", "tomato", "wheat" +} + +cauldron.cbox = { + {0, 0, 0, 16, 16, 0}, + {0, 0, 16, 16, 16, 0}, + {0, 0, 0, 0, 16, 16}, + {16, 0, 0, 0, 16, 16}, + {0, 0, 0, 16, 8, 16} +} + +function cauldron.stop_sound(pos) + local spos = minetest.hash_node_position(pos) + if sounds[spos] then + minetest.sound_stop(sounds[spos]) + end +end + +function cauldron.idle_construct(pos) + local timer = minetest.get_node_timer(pos) + timer:start(10.0) + cauldron.stop_sound(pos) +end + +function cauldron.boiling_construct(pos) + local spos = minetest.hash_node_position(pos) + sounds[spos] = minetest.sound_play("xdecor_boiling_water", { + pos = pos, + max_hear_distance = 5, + gain = 0.8, + loop = true + }) + + local meta = minetest.get_meta(pos) + meta:set_string("infotext", S("Cauldron (active) - Drop foods inside to make a soup")) + + local timer = minetest.get_node_timer(pos) + timer:start(5.0) +end + +function cauldron.filling(pos, node, clicker, itemstack) + local inv = clicker:get_inventory() + local wield_item = clicker:get_wielded_item():get_name() + + if wield_item:sub(1,7) == "bucket:" then + if wield_item:sub(-6) == "_empty" and not (node.name:sub(-6) == "_empty") then + if itemstack:get_count() > 1 then + if inv:room_for_item("main", "bucket:bucket_water 1") then + itemstack:take_item() + inv:add_item("main", "bucket:bucket_water 1") + else + minetest.chat_send_player(clicker:get_player_name(), + S("No room in your inventory to add a bucket of water.")) + return itemstack + end + else + itemstack:replace("bucket:bucket_water") + end + minetest.set_node(pos, {name = "xdecor:cauldron_empty", param2 = node.param2}) + + elseif wield_item:sub(-6) == "_water" and node.name:sub(-6) == "_empty" then + minetest.set_node(pos, {name = "xdecor:cauldron_idle", param2 = node.param2}) + itemstack:replace("bucket:bucket_empty") + end + + return itemstack + end +end + +function cauldron.idle_timer(pos) + local below_node = {x = pos.x, y = pos.y - 1, z = pos.z} + if not minetest.get_node(below_node).name:find("fire") then + return true + end + + local node = minetest.get_node(pos) + minetest.set_node(pos, {name = "xdecor:cauldron_boiling", param2 = node.param2}) + return true +end + +-- Ugly hack to determine if an item has the function `minetest.item_eat` in its definition. +local function eatable(itemstring) + local item = itemstring:match("[%w_:]+") + local on_use_def = minetest.registered_items[item].on_use + if not on_use_def then return end + + return string.format("%q", string.dump(on_use_def)):find("item_eat") +end + +function cauldron.boiling_timer(pos) + local node = minetest.get_node(pos) + local objs = minetest.get_objects_inside_radius(pos, 0.5) + + if not next(objs) then + return true + end + + local ingredients = {} + for _, obj in pairs(objs) do + if obj and not obj:is_player() and obj:get_luaentity().itemstring then + local itemstring = obj:get_luaentity().itemstring + local food = itemstring:match(":([%w_]+)") + + for _, ingredient in ipairs(ingredients_list) do + if food and (eatable(itemstring) or food:find(ingredient)) then + ingredients[#ingredients + 1] = food + break + end + end + end + end + + if #ingredients >= 2 then + for _, obj in pairs(objs) do + obj:remove() + end + + minetest.set_node(pos, {name = "xdecor:cauldron_soup", param2 = node.param2}) + end + + local node_under = {x = pos.x, y = pos.y - 1, z = pos.z} + + if not minetest.get_node(node_under).name:find("fire") then + minetest.set_node(pos, {name = "xdecor:cauldron_idle", param2 = node.param2}) + end + + return true +end + +function cauldron.take_soup(pos, node, clicker, itemstack) + local inv = clicker:get_inventory() + local wield_item = clicker:get_wielded_item() + local item_name = wield_item:get_name() + + if item_name == "xdecor:bowl" or item_name == "farming:bowl" then + if wield_item:get_count() > 1 then + if inv:room_for_item("main", "xdecor:bowl_soup 1") then + itemstack:take_item() + inv:add_item("main", "xdecor:bowl_soup 1") + else + minetest.chat_send_player(clicker:get_player_name(), + S("No room in your inventory to add a bowl of soup.")) + return itemstack + end + else + itemstack:replace("xdecor:bowl_soup 1") + end + + minetest.set_node(pos, {name = "xdecor:cauldron_empty", param2 = node.param2}) + end + + return itemstack +end + +xdecor.register("cauldron_empty", { + description = S("Cauldron"), + groups = {cracky=2, oddly_breakable_by_hand=1}, + on_rotate = screwdriver.rotate_simple, + tiles = {"xdecor_cauldron_top_empty.png", "xdecor_cauldron_sides.png"}, + infotext = S("Cauldron (empty)"), + collision_box = xdecor.pixelbox(16, cauldron.cbox), + on_rightclick = cauldron.filling, + on_construct = function(pos) + cauldron.stop_sound(pos) + end, +}) + +xdecor.register("cauldron_idle", { + description = S("Cauldron (idle)"), + groups = {cracky=2, oddly_breakable_by_hand=1, not_in_creative_inventory=1}, + on_rotate = screwdriver.rotate_simple, + tiles = {"xdecor_cauldron_top_idle.png", "xdecor_cauldron_sides.png"}, + drop = "xdecor:cauldron_empty", + infotext = S("Cauldron (idle)"), + collision_box = xdecor.pixelbox(16, cauldron.cbox), + on_rightclick = cauldron.filling, + on_construct = cauldron.idle_construct, + on_timer = cauldron.idle_timer, +}) + +xdecor.register("cauldron_boiling", { + description = S("Cauldron (active)"), + groups = {cracky=2, oddly_breakable_by_hand=1, not_in_creative_inventory=1}, + on_rotate = screwdriver.rotate_simple, + drop = "xdecor:cauldron_empty", + infotext = S("Cauldron (active) - Drop foods inside to make a soup"), + damage_per_second = 2, + tiles = { + { + name = "xdecor_cauldron_top_anim_boiling_water.png", + animation = {type = "vertical_frames", length = 3.0} + }, + "xdecor_cauldron_sides.png" + }, + collision_box = xdecor.pixelbox(16, cauldron.cbox), + on_rightclick = cauldron.filling, + on_construct = cauldron.boiling_construct, + on_timer = cauldron.boiling_timer, + on_destruct = function(pos) + cauldron.stop_sound(pos) + end, +}) + +xdecor.register("cauldron_soup", { + description = S("Cauldron (active)"), + groups = {cracky = 2, oddly_breakable_by_hand = 1, not_in_creative_inventory = 1}, + on_rotate = screwdriver.rotate_simple, + drop = "xdecor:cauldron_empty", + infotext = S("Cauldron (active) - Use a bowl to eat the soup"), + damage_per_second = 2, + tiles = { + { + name = "xdecor_cauldron_top_anim_soup.png", + animation = {type = "vertical_frames", length = 3.0} + }, + "xdecor_cauldron_sides.png" + }, + collision_box = xdecor.pixelbox(16, cauldron.cbox), + on_rightclick = cauldron.take_soup, + on_destruct = function(pos) + cauldron.stop_sound(pos) + end, +}) + +-- Craft items + +minetest.register_craftitem("xdecor:bowl", { + description = S("Bowl"), + inventory_image = "xdecor_bowl.png", + wield_image = "xdecor_bowl.png", + groups = {food_bowl = 1, flammable = 2}, +}) + +minetest.register_craftitem("xdecor:bowl_soup", { + description = S("Bowl of soup"), + inventory_image = "xdecor_bowl_soup.png", + wield_image = "xdecor_bowl_soup.png", + groups = {not_in_creative_inventory=1}, + stack_max = 1, + on_use = minetest.item_eat(30, "xdecor:bowl") +}) + +-- Recipes + +minetest.register_craft({ + output = "xdecor:bowl 3", + recipe = { + {"group:wood", "", "group:wood"}, + {"", "group:wood", ""} + } +}) + +minetest.register_craft({ + output = "xdecor:cauldron_empty", + recipe = { + {"default:iron_lump", "", "default:iron_lump"}, + {"default:iron_lump", "", "default:iron_lump"}, + {"default:iron_lump", "default:iron_lump", "default:iron_lump"} + } +}) diff --git a/mods/xdecor/src/enchanting.lua b/mods/xdecor/src/enchanting.lua new file mode 100644 index 0000000..508d42e --- /dev/null +++ b/mods/xdecor/src/enchanting.lua @@ -0,0 +1,336 @@ +screwdriver = screwdriver or {} +local S = xdecor.S +local FS = function(...) return minetest.formspec_escape(S(...)) end +local ceil, abs, random = math.ceil, math.abs, math.random +local reg_tools = minetest.registered_tools + +-- Cost in Mese crystal(s) for enchanting. +local mese_cost = 1 + +-- Force of the enchantments. +local enchanting = { + uses = 1.2, -- Durability + times = 0.1, -- Efficiency + damages = 1, -- Sharpness +} + +local function cap(str) return + str:gsub("^%l", string.upper) +end + +local function to_percent(orig_value, final_value) + return abs(ceil(((final_value - orig_value) / orig_value) * 100)) +end + +function enchanting:get_tooltip(enchant, orig_caps, fleshy) + local bonus = {durable = 0, efficiency = 0, damages = 0} + + if orig_caps then + bonus.durable = to_percent(orig_caps.uses, orig_caps.uses * enchanting.uses) + local sum_caps_times = 0 + for i=1, #orig_caps.times do + sum_caps_times = sum_caps_times + orig_caps.times[i] + end + local average_caps_time = sum_caps_times / #orig_caps.times + bonus.efficiency = to_percent(average_caps_time, average_caps_time - + enchanting.times) + end + + if fleshy then + bonus.damages = to_percent(fleshy, fleshy + enchanting.damages) + end + + local specs = { -- not finished, to complete + durable = {"#00baff", " (+" .. bonus.durable .. "%)"}, + fast = {"#74ff49", " (+" .. bonus.efficiency .. "%)"}, + sharp = {"#ffff00", " (+" .. bonus.damages .. "%)"}, + } + + local enchant_loc = { + fast = S("Efficiency"), + durable = S("Durability"), + sharp = S("Sharpness"), + } + + return minetest.colorize and minetest.colorize(specs[enchant][1], + "\n" .. enchant_loc[enchant] .. specs[enchant][2]) or + "\n" .. enchant_loc[enchant] .. specs[enchant][2] +end + +local enchant_buttons = { + "image_button[3.9,0.85;4,0.92;bg_btn.png;fast;"..FS("Efficiency").."]" .. + "image_button[3.9,1.77;4,1.12;bg_btn.png;durable;"..FS("Durability").."]", + "image_button[3.9,2.9;4,0.92;bg_btn.png;sharp;"..FS("Sharpness").."]", +} + +function enchanting.formspec(pos, num) + local meta = minetest.get_meta(pos) + local formspec = [[ + size[9,8.6;] + no_prepend[] + bgcolor[#080808BB;true] + listcolors[#00000069;#5A5A5A;#141318;#30434C;#FFF] + background9[0,0;9,9;ench_ui.png;6] + list[context;tool;0.9,2.9;1,1;] + list[context;mese;2,2.9;1,1;] + list[current_player;main;0.55,4.5;8,4;] + listring[current_player;main] + listring[context;tool] + listring[current_player;main] + listring[context;mese] + image[2,2.9;1,1;mese_layout.png] + ]] + .."tooltip[sharp;"..FS("Your weapon inflicts more damages").."]" + .."tooltip[durable;"..FS("Your tool last longer").."]" + .."tooltip[fast;"..FS("Your tool digs faster").."]" + ..default.gui_slots .. default.get_hotbar_bg(0.55, 4.5) + + formspec = formspec .. (enchant_buttons[num] or "") + meta:set_string("formspec", formspec) +end + +function enchanting.on_put(pos, listname, _, stack) + if listname == "tool" then + local stackname = stack:get_name() + local tool_groups = { + "axe, pick, shovel", + "sword", + } + + for idx, tools in ipairs(tool_groups) do + if tools:find(stackname:match(":(%w+)")) then + enchanting.formspec(pos, idx) + end + end + end +end + +function enchanting.fields(pos, _, fields, sender) + if not next(fields) or fields.quit then return end + local inv = minetest.get_meta(pos):get_inventory() + local tool = inv:get_stack("tool", 1) + local mese = inv:get_stack("mese", 1) + local orig_wear = tool:get_wear() + local mod, name = tool:get_name():match("(.*):(.*)") + local enchanted_tool = (mod or "") .. ":enchanted_" .. (name or "") .. "_" .. next(fields) + + if mese:get_count() >= mese_cost and reg_tools[enchanted_tool] then + minetest.sound_play("xdecor_enchanting", { + to_player = sender:get_player_name(), + gain = 0.8 + }) + + tool:replace(enchanted_tool) + tool:add_wear(orig_wear) + mese:take_item(mese_cost) + inv:set_stack("mese", 1, mese) + inv:set_stack("tool", 1, tool) + end +end + +function enchanting.dig(pos) + local inv = minetest.get_meta(pos):get_inventory() + return inv:is_empty("tool") and inv:is_empty("mese") +end + +local function allowed(tool) + if not tool then return end + + for item in pairs(reg_tools) do + if item:find("enchanted_" .. tool) then + return true + end + end +end + +function enchanting.put(_, listname, _, stack) + local stackname = stack:get_name() + if listname == "mese" and (stackname == "default:mese_crystal" or + stackname == "imese:industrial_mese_crystal") then + return stack:get_count() + elseif listname == "tool" and allowed(stackname:match("[^:]+$")) then + return 1 + end + + return 0 +end + +function enchanting.on_take(pos, listname) + if listname == "tool" then + enchanting.formspec(pos) + end +end + +function enchanting.construct(pos) + local meta = minetest.get_meta(pos) + meta:set_string("infotext", S("Enchantment Table")) + enchanting.formspec(pos) + + local inv = meta:get_inventory() + inv:set_size("tool", 1) + inv:set_size("mese", 1) + + minetest.add_entity({x = pos.x, y = pos.y + 0.85, z = pos.z}, "xdecor:book_open") + local timer = minetest.get_node_timer(pos) + timer:start(0.5) +end + +function enchanting.destruct(pos) + for _, obj in pairs(minetest.get_objects_inside_radius(pos, 0.9)) do + if obj and obj:get_luaentity() and + obj:get_luaentity().name == "xdecor:book_open" then + obj:remove() + break + end + end +end + +function enchanting.timer(pos) + local minp = {x = pos.x - 2, y = pos.y, z = pos.z - 2} + local maxp = {x = pos.x + 2, y = pos.y + 1, z = pos.z + 2} + + local bookshelves = minetest.find_nodes_in_area(minp, maxp, "default:bookshelf") + if #bookshelves == 0 then + return true + end + + local bookshelf_pos = bookshelves[random(1, #bookshelves)] + local x = pos.x - bookshelf_pos.x + local y = bookshelf_pos.y - pos.y + local z = pos.z - bookshelf_pos.z + + if tostring(x .. z):find(2) then + minetest.add_particle({ + pos = bookshelf_pos, + velocity = {x = x, y = 2 - y, z = z}, + acceleration = {x = 0, y = -2.2, z = 0}, + expirationtime = 1, + size = 1.5, + glow = 5, + texture = "xdecor_glyph" .. random(1,18) .. ".png" + }) + end + + return true +end + +xdecor.register("enchantment_table", { + description = S("Enchantment Table"), + tiles = { + "xdecor_enchantment_top.png", "xdecor_enchantment_bottom.png", + "xdecor_enchantment_side.png", "xdecor_enchantment_side.png", + "xdecor_enchantment_side.png", "xdecor_enchantment_side.png" + }, + groups = {cracky = 1, level = 1}, + light_source = 6, + sounds = default.node_sound_stone_defaults(), + on_rotate = screwdriver.rotate_simple, + can_dig = enchanting.dig, + on_timer = enchanting.timer, + on_construct = enchanting.construct, + on_destruct = enchanting.destruct, + on_receive_fields = enchanting.fields, + on_metadata_inventory_put = enchanting.on_put, + on_metadata_inventory_take = enchanting.on_take, + allow_metadata_inventory_put = enchanting.put, + allow_metadata_inventory_move = function() + return 0 + end, +}) + +minetest.register_entity("xdecor:book_open", { + visual = "sprite", + visual_size = {x=0.75, y=0.75}, + collisionbox = {0}, + physical = false, + textures = {"xdecor_book_open.png"}, + static_save = false, +}) + +minetest.register_lbm({ + label = "recreate book entity", + name = "xdecor:create_book_entity", + nodenames = {"xdecor:enchantment_table"}, + run_at_every_load = true, + action = function(pos, node) + local objs = minetest.get_objects_inside_radius(pos, 0.9) + + for _, obj in ipairs(objs) do + local e = obj:get_luaentity() + if e and e.name == "xdecor:book_open" then + return + end + end + + minetest.add_entity({x = pos.x, y = pos.y + 0.85, z = pos.z}, "xdecor:book_open") + end, +}) + +function enchanting:register_tools(mod, def) + for tool in pairs(def.tools) do + for material in def.materials:gmatch("[%w_]+") do + for enchant in def.tools[tool].enchants:gmatch("[%w_]+") do + local original_tool = reg_tools[mod .. ":" .. tool .. "_" .. material] + if not original_tool then break end + local original_toolcaps = original_tool.tool_capabilities + + if original_toolcaps then + local original_damage_groups = original_toolcaps.damage_groups + local original_groupcaps = original_toolcaps.groupcaps + local groupcaps = table.copy(original_groupcaps) + local fleshy = original_damage_groups.fleshy + local full_punch_interval = original_toolcaps.full_punch_interval + local max_drop_level = original_toolcaps.max_drop_level + local group = next(original_groupcaps) + + if enchant == "durable" then + groupcaps[group].uses = ceil(original_groupcaps[group].uses * + enchanting.uses) + elseif enchant == "fast" then + for i, time in pairs(original_groupcaps[group].times) do + groupcaps[group].times[i] = time - enchanting.times + end + elseif enchant == "sharp" then + fleshy = fleshy + enchanting.damages + end + + minetest.register_tool(":" .. mod .. ":enchanted_" .. tool .. "_" .. material .. "_" .. enchant, { + description = S("Enchanted @1 @2 @3", + def.material_desc[material] or cap(material), def.tools[tool].desc or cap(tool), + self:get_tooltip(enchant, original_groupcaps[group], fleshy)), + inventory_image = original_tool.inventory_image .. "^[colorize:violet:50", + wield_image = original_tool.wield_image, + groups = {not_in_creative_inventory = 1}, + tool_capabilities = { + groupcaps = groupcaps, damage_groups = {fleshy = fleshy}, + full_punch_interval = full_punch_interval, + max_drop_level = max_drop_level + } + }) + end + end + end + end +end + +enchanting:register_tools("default", { + materials = "steel, bronze, mese, diamond", + material_desc = {steel = S("Steel"), bronze = S("Bronze"), mese = S("Mese"), diamond = S("Diamond")}, + tools = { + axe = {enchants = "durable, fast", desc = S("Axe")}, + pick = {enchants = "durable, fast", desc = S("Pickaxe")}, + shovel = {enchants = "durable, fast", desc = S("Shovel")}, + sword = {enchants = "sharp", desc = S("Sword")} + }, +}) + +-- Recipes + +minetest.register_craft({ + output = "xdecor:enchantment_table", + recipe = { + {"", "default:book", ""}, + {"default:diamond", "default:obsidian", "default:diamond"}, + {"default:obsidian", "default:obsidian", "default:obsidian"} + } +}) diff --git a/mods/xdecor/src/hive.lua b/mods/xdecor/src/hive.lua new file mode 100644 index 0000000..9aae303 --- /dev/null +++ b/mods/xdecor/src/hive.lua @@ -0,0 +1,108 @@ +local hive = {} +local S = xdecor.S +local FS = function(...) return minetest.formspec_escape(S(...)) end +local honey_max = 16 + +function hive.construct(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + + local formspec = "size[8,6;]" + .."label[0.5,0;"..FS("Bees are busy making honey…").."]" + ..[[ image[6,1;1,1;hive_bee.png] + image[5,1;1,1;hive_layout.png] + list[context;honey;5,1;1,1;] + list[current_player;main;0,2.35;8,4;] + listring[current_player;main] + listring[context;honey] ]] .. + xbg .. default.get_hotbar_bg(0,2.35) + + meta:set_string("formspec", formspec) + meta:set_string("infotext", S("Artificial Hive")) + inv:set_size("honey", 1) + + local timer = minetest.get_node_timer(pos) + timer:start(math.random(64, 128)) +end + +function hive.timer(pos) + local time = (minetest.get_timeofday() or 0) * 24000 + if time < 5500 or time > 18500 then + return true + end + + local inv = minetest.get_meta(pos):get_inventory() + local honeystack = inv:get_stack("honey", 1) + local honey = honeystack:get_count() + + local radius = 4 + local minp = vector.add(pos, -radius) + local maxp = vector.add(pos, radius) + local flowers = minetest.find_nodes_in_area_under_air(minp, maxp, "group:flower") + + if #flowers > 2 and honey < honey_max then + inv:add_item("honey", "xdecor:honey") + elseif honey == honey_max then + local timer = minetest.get_node_timer(pos) + timer:stop() + return true + end + + return true +end + +xdecor.register("hive", { + description = S("Artificial Hive"), + tiles = {"xdecor_hive_top.png", "xdecor_hive_top.png", + "xdecor_hive_side.png", "xdecor_hive_side.png", + "xdecor_hive_side.png", "xdecor_hive_front.png"}, + groups = {choppy=3, oddly_breakable_by_hand=2, flammable=1}, + on_construct = hive.construct, + on_timer = hive.timer, + + can_dig = function(pos) + local inv = minetest.get_meta(pos):get_inventory() + return inv:is_empty("honey") + end, + + on_punch = function(_, _, puncher) + puncher:set_hp(puncher:get_hp() - 2) + end, + + allow_metadata_inventory_put = function() + return 0 + end, + + on_metadata_inventory_take = function(pos, _, _, stack) + if stack:get_count() == honey_max then + local timer = minetest.get_node_timer(pos) + timer:start(math.random(64, 128)) + end + end +}) + +-- Craft items + +minetest.register_craftitem("xdecor:honey", { + description = S("Honey"), + inventory_image = "xdecor_honey.png", + wield_image = "xdecor_honey.png", + on_use = minetest.item_eat(2), + groups = { + food_honey = 1, + food_sugar = 1, + flammable = 2, + not_in_creative_inventory = 1, + }, +}) + +-- Recipes + +minetest.register_craft({ + output = "xdecor:hive", + recipe = { + {"group:stick", "group:stick", "group:stick"}, + {"default:paper", "default:paper", "default:paper"}, + {"group:stick", "group:stick", "group:stick"} + } +}) diff --git a/mods/xdecor/src/itemframe.lua b/mods/xdecor/src/itemframe.lua new file mode 100644 index 0000000..9465501 --- /dev/null +++ b/mods/xdecor/src/itemframe.lua @@ -0,0 +1,186 @@ +local itemframe, tmp = {}, {} +local S = xdecor.S +screwdriver = screwdriver or {} + +local function remove_item(pos, node) + local objs = minetest.get_objects_inside_radius(pos, 0.5) + if not objs then return end + + for _, obj in pairs(objs) do + local ent = obj:get_luaentity() + if obj and ent and ent.name == "xdecor:f_item" then + obj:remove() break + end + end +end + +local facedir = { + [0] = {x = 0, y = 0, z = 1}, + {x = 1, y = 0, z = 0}, + {x = 0, y = 0, z = -1}, + {x = -1, y = 0, z = 0} +} + +local function update_item(pos, node) + remove_item(pos, node) + local meta = minetest.get_meta(pos) + local itemstring = meta:get_string("item") + local posad = facedir[node.param2] + if not posad or itemstring == "" then return end + + pos = vector.add(pos, vector.multiply(posad, 6.5/16)) + tmp.nodename = node.name + tmp.texture = ItemStack(itemstring):get_name() + + local entity = minetest.add_entity(pos, "xdecor:f_item") + local yaw = (math.pi * 2) - node.param2 * (math.pi / 2) + entity:set_yaw(yaw) + + local timer = minetest.get_node_timer(pos) + timer:start(15.0) +end + +local function drop_item(pos, node) + local meta = minetest.get_meta(pos) + local item = meta:get_string("item") + if item == "" then return end + + minetest.add_item(pos, item) + meta:set_string("item", "") + remove_item(pos, node) + + local timer = minetest.get_node_timer(pos) + timer:stop() +end + +function itemframe.after_place(pos, placer, itemstack) + local meta = minetest.get_meta(pos) + local name = placer:get_player_name() + meta:set_string("owner", name) + meta:set_string("infotext", S("@1 (owned by @2)", S("Item Frame"), name)) +end + +function itemframe.timer(pos) + local node = minetest.get_node(pos) + local meta = minetest.get_meta(pos) + local num = #minetest.get_objects_inside_radius(pos, 0.5) + + if num == 0 and meta:get_string("item") ~= "" then + update_item(pos, node) + end + + return true +end + +function itemframe.rightclick(pos, node, clicker, itemstack) + local meta = minetest.get_meta(pos) + local player_name = clicker:get_player_name() + local owner = meta:get_string("owner") + local admin = minetest.check_player_privs(player_name, "protection_bypass") + + if not admin and (player_name ~= owner or not itemstack) then + return itemstack + end + + drop_item(pos, node) + local itemstring = itemstack:take_item():to_string() + meta:set_string("item", itemstring) + update_item(pos, node) + if itemstring == "" then + meta:set_string("infotext", S("@1 (owned by @2)", S("Item Frame"), owner)) + else + meta:set_string("infotext", S("@1 (owned by @2)", itemstring, owner)) + end + return itemstack +end + +function itemframe.punch(pos, node, puncher) + local meta = minetest.get_meta(pos) + local player_name = puncher:get_player_name() + local owner = meta:get_string("owner") + local admin = minetest.check_player_privs(player_name, "protection_bypass") + + if admin and player_name == owner then + drop_item(pos, node) + end +end + +function itemframe.dig(pos, player) + if not player then return end + local meta = minetest.get_meta(pos) + local player_name = player and player:get_player_name() + local owner = meta:get_string("owner") + local admin = minetest.check_player_privs(player_name, "protection_bypass") + + return admin or player_name == owner +end + +xdecor.register("itemframe", { + description = S("Item Frame"), + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3}, + sounds = default.node_sound_wood_defaults(), + on_rotate = screwdriver.disallow, + sunlight_propagates = true, + inventory_image = "xdecor_itemframe.png", + node_box = xdecor.nodebox.slab_z(0.9375), + tiles = { + "xdecor_wood.png", "xdecor_wood.png", "xdecor_wood.png", + "xdecor_wood.png", "xdecor_wood.png", "xdecor_itemframe.png" + }, + after_place_node = itemframe.after_place, + on_timer = itemframe.timer, + on_rightclick = itemframe.rightclick, + on_punch = itemframe.punch, + can_dig = itemframe.dig, + after_destruct = remove_item +}) + +minetest.register_entity("xdecor:f_item", { + visual = "wielditem", + visual_size = {x = 0.33, y = 0.33}, + collisionbox = {0}, + physical = false, + textures = {"air"}, + on_activate = function(self, staticdata) + local pos = self.object:get_pos() + if minetest.get_node(pos).name ~= "xdecor:itemframe" then + self.object:remove() + end + + if tmp.nodename and tmp.texture then + self.nodename = tmp.nodename + tmp.nodename = nil + self.texture = tmp.texture + tmp.texture = nil + elseif staticdata and staticdata ~= "" then + local data = staticdata:split(";") + if data and data[1] and data[2] then + self.nodename = data[1] + self.texture = data[2] + end + end + if self.texture then + self.object:set_properties({ + textures = {self.texture} + }) + end + end, + get_staticdata = function(self) + if self.nodename and self.texture then + return self.nodename .. ";" .. self.texture + end + + return "" + end +}) + +-- Recipes + +minetest.register_craft({ + output = "xdecor:itemframe", + recipe = { + {"group:stick", "group:stick", "group:stick"}, + {"group:stick", "default:paper", "group:stick"}, + {"group:stick", "group:stick", "group:stick"} + } +}) diff --git a/mods/xdecor/src/mailbox.lua b/mods/xdecor/src/mailbox.lua new file mode 100644 index 0000000..8d7439c --- /dev/null +++ b/mods/xdecor/src/mailbox.lua @@ -0,0 +1,192 @@ +local mailbox = {} +screwdriver = screwdriver or {} +local S = xdecor.S +local FS = function(...) return minetest.formspec_escape(S(...)) end + +local function get_img(img) + if not img then return end + local img_name = img:match("(.*)%.png") + + if img_name then + return img_name .. ".png" + end +end + +local function img_col(stack) + local def = minetest.registered_items[stack] + if not def then + return "" + end + + if def.inventory_image ~= "" then + local img = get_img(def.inventory_image) + if img then + return img + end + end + + if def.tiles then + local tile, img = def.tiles[1] + if type(tile) == "table" then + img = get_img(tile.name) + elseif type(tile) == "string" then + img = get_img(tile) + end + + if img then + return img + end + end + + return "" +end + +function mailbox:formspec(pos, owner, is_owner) + local spos = pos.x .. "," .. pos.y .. "," .. pos.z + local meta = minetest.get_meta(pos) + local giver, img = "", "" + + if is_owner then + for i = 1, 7 do + local giving = meta:get_string("giver" .. i) + if giving ~= "" then + local stack = meta:get_string("stack" .. i) + local giver_name = giving:sub(1,12) + local stack_name = stack:match("[%w_:]+") + local stack_count = stack:match("%s(%d+)") or 1 + + giver = giver .. "#FFFF00," .. giver_name .. "," .. i .. + ",#FFFFFF,x " .. stack_count .. "," + + img = img .. i .. "=" .. + img_col(stack_name) .. "^\\[resize:16x16," + end + end + + return "size[9.5,9]" + .."label[0,0;"..FS("Mailbox").."]" + .."label[6,0;"..FS("Last donators").."]" + ..[[ box[6,0.72;3.3,3.5;#555555] + listring[current_player;main] + list[current_player;main;0.75,5.25;8,4;] + tableoptions[background=#00000000;highlight=#00000000;border=false] ]] .. + "tablecolumns[color;text;image," .. img .. "0;color;text]" .. + "table[6,0.75;3.3,4;givers;" .. giver .. "]" .. + "list[nodemeta:" .. spos .. ";mailbox;0,0.75;6,4;]" .. + "listring[nodemeta:" .. spos .. ";mailbox]" .. + xbg .. default.get_hotbar_bg(0.75, 5.25) + end + + return "size[8,5]" .. + "list[current_player;main;0,1.25;8,4;]" .. + "label[0,0;"..FS("Send your goods to\n@1", + (minetest.colorize and + minetest.colorize("#FFFF00", owner) or owner)) .. "]" .. + "list[nodemeta:" .. spos .. ";drop;3.5,0;1,1;]" .. + xbg .. default.get_hotbar_bg(0, 1.25) +end + +function mailbox.dig(pos, player) + local meta = minetest.get_meta(pos) + local owner = meta:get_string("owner") + local player_name = player and player:get_player_name() + local inv = meta:get_inventory() + + return inv:is_empty("mailbox") and player_name == owner +end + +function mailbox.after_place_node(pos, placer) + local meta = minetest.get_meta(pos) + local player_name = placer:get_player_name() + + meta:set_string("owner", player_name) + meta:set_string("infotext", S("@1's Mailbox", player_name)) + + local inv = meta:get_inventory() + inv:set_size("mailbox", 6 * 4) + inv:set_size("drop", 1) +end + +function mailbox.rightclick(pos, node, clicker, itemstack, pointed_thing) + local meta = minetest.get_meta(pos) + local player = clicker:get_player_name() + local owner = meta:get_string("owner") + + minetest.show_formspec(player, "xdecor:mailbox", + mailbox:formspec(pos, owner, (player == owner))) + + return itemstack +end + +function mailbox.put(pos, listname, _, stack, player) + if listname == "drop" then + local inv = minetest.get_meta(pos):get_inventory() + if inv:room_for_item("mailbox", stack) then + return -1 + else + minetest.chat_send_player(player:get_player_name(), + S("The mailbox is full.")) + end + end + + return 0 +end + +function mailbox.on_put(pos, listname, _, stack, player) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + + if listname == "drop" and inv:room_for_item("mailbox", stack) then + inv:set_list("drop", {}) + inv:add_item("mailbox", stack) + + for i = 7, 2, -1 do + meta:set_string("giver" .. i, meta:get_string("giver" .. (i - 1))) + meta:set_string("stack" .. i, meta:get_string("stack" .. (i - 1))) + end + + meta:set_string("giver1", player:get_player_name()) + meta:set_string("stack1", stack:to_string()) + end +end + +function mailbox.allow_take(pos, listname, index, stack, player) + local meta = minetest.get_meta(pos) + + if player:get_player_name() ~= meta:get_string("owner") then + return 0 + end + + return stack:get_count() +end + +function mailbox.allow_move(pos) + return 0 +end + +xdecor.register("mailbox", { + description = S("Mailbox"), + tiles = {"xdecor_mailbox_top.png", "xdecor_mailbox_bottom.png", + "xdecor_mailbox_side.png", "xdecor_mailbox_side.png", + "xdecor_mailbox.png", "xdecor_mailbox.png"}, + groups = {cracky = 3, oddly_breakable_by_hand = 1}, + on_rotate = screwdriver.rotate_simple, + can_dig = mailbox.dig, + on_rightclick = mailbox.rightclick, + allow_metadata_inventory_take = mailbox.allow_take, + allow_metadata_inventory_move = mailbox.allow_move, + on_metadata_inventory_put = mailbox.on_put, + allow_metadata_inventory_put = mailbox.put, + after_place_node = mailbox.after_place_node +}) + +-- Recipes + +minetest.register_craft({ + output = "xdecor:mailbox", + recipe = { + {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, + {"dye:red", "default:paper", "dye:red"}, + {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"} + } +}) diff --git a/mods/xdecor/src/mechanisms.lua b/mods/xdecor/src/mechanisms.lua new file mode 100644 index 0000000..d9d723e --- /dev/null +++ b/mods/xdecor/src/mechanisms.lua @@ -0,0 +1,153 @@ +-- Thanks to sofar for helping with that code. + +local plate = {} +screwdriver = screwdriver or {} + +local S = xdecor.S +local ALPHA_OPAQUE = minetest.features.use_texture_alpha_string_modes and "opaque" or false + +local function door_toggle(pos_actuator, pos_door, player) + local player_name = player:get_player_name() + local actuator = minetest.get_node(pos_actuator) + local door = doors.get(pos_door) + if not door then return end + + if actuator.name:sub(-4) == "_off" then + minetest.set_node(pos_actuator, + {name = actuator.name:gsub("_off", "_on"), param2 = actuator.param2}) + end + door:open(player) + + minetest.after(2, function() + if minetest.get_node(pos_actuator).name:sub(-3) == "_on" then + minetest.set_node(pos_actuator, + {name = actuator.name, param2 = actuator.param2}) + end + -- Re-get player object (or nil) because 'player' could + -- be an invalid object at this time (player left) + door:close(minetest.get_player_by_name(player_name)) + end) +end + +function plate.construct(pos) + local timer = minetest.get_node_timer(pos) + timer:start(0.1) +end + +function plate.timer(pos) + local objs = minetest.get_objects_inside_radius(pos, 0.8) + if not next(objs) or not doors.get then return true end + + local minp = {x = pos.x - 2, y = pos.y, z = pos.z - 2} + local maxp = {x = pos.x + 2, y = pos.y, z = pos.z + 2} + local doors = minetest.find_nodes_in_area(minp, maxp, "group:door") + + for _, player in pairs(objs) do + if player:is_player() then + for i = 1, #doors do + door_toggle(pos, doors[i], player) + end + break + end + end + + return true +end + +function plate.register(material, desc, def) + xdecor.register("pressure_" .. material .. "_off", { + description = def.description or (desc .. " Pressure Plate"), + tiles = {"xdecor_pressure_" .. material .. ".png"}, + use_texture_alpha = ALPHA_OPAQUE, + drawtype = "nodebox", + node_box = xdecor.pixelbox(16, {{1, 0, 1, 14, 1, 14}}), + groups = def.groups, + sounds = def.sounds, + sunlight_propagates = true, + on_rotate = screwdriver.rotate_simple, + on_construct = plate.construct, + on_timer = plate.timer + }) + xdecor.register("pressure_" .. material .. "_on", { + tiles = {"xdecor_pressure_" .. material .. ".png"}, + use_texture_alpha = ALPHA_OPAQUE, + drawtype = "nodebox", + node_box = xdecor.pixelbox(16, {{1, 0, 1, 14, 0.4, 14}}), + groups = def.groups, + sounds = def.sounds, + drop = "xdecor:pressure_" .. material .. "_off", + sunlight_propagates = true, + on_rotate = screwdriver.rotate_simple + }) +end + +plate.register("wood", "Wooden", { + sounds = default.node_sound_wood_defaults(), + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 2}, + description = S("Wooden Pressure Plate"), +}) + +plate.register("stone", "Stone", { + sounds = default.node_sound_stone_defaults(), + groups = {cracky = 3, oddly_breakable_by_hand = 2}, + description = S("Stone Pressure Plate"), +}) + +xdecor.register("lever_off", { + description = S("Lever"), + tiles = {"xdecor_lever_off.png"}, + use_texture_alpha = ALPHA_OPAQUE, + drawtype = "nodebox", + node_box = xdecor.pixelbox(16, {{2, 1, 15, 12, 14, 1}}), + groups = {cracky = 3, oddly_breakable_by_hand = 2}, + sounds = default.node_sound_stone_defaults(), + sunlight_propagates = true, + on_rotate = screwdriver.rotate_simple, + + on_rightclick = function(pos, node, clicker, itemstack) + if not doors.get then return itemstack end + local minp = {x = pos.x - 2, y = pos.y - 1, z = pos.z - 2} + local maxp = {x = pos.x + 2, y = pos.y + 1, z = pos.z + 2} + local doors = minetest.find_nodes_in_area(minp, maxp, "group:door") + + for i = 1, #doors do + door_toggle(pos, doors[i], clicker) + end + + return itemstack + end +}) + +xdecor.register("lever_on", { + tiles = {"xdecor_lever_on.png"}, + use_texture_alpha = ALPHA_OPAQUE, + drawtype = "nodebox", + node_box = xdecor.pixelbox(16, {{2, 1, 15, 12, 14, 1}}), + groups = {cracky = 3, oddly_breakable_by_hand = 2, not_in_creative_inventory = 1}, + sounds = default.node_sound_stone_defaults(), + sunlight_propagates = true, + on_rotate = screwdriver.rotate_simple, + drop = "xdecor:lever_off" +}) + +-- Recipes + +minetest.register_craft({ + output = "xdecor:pressure_stone_off", + type = "shapeless", + recipe = {"group:stone", "group:stone"} +}) + +minetest.register_craft({ + output = "xdecor:pressure_wood_off", + type = "shapeless", + recipe = {"group:wood", "group:wood"} +}) + +minetest.register_craft({ + output = "xdecor:lever_off", + recipe = { + {"group:stick"}, + {"group:stone"} + } +}) diff --git a/mods/xdecor/src/nodes.lua b/mods/xdecor/src/nodes.lua new file mode 100644 index 0000000..cecb04e --- /dev/null +++ b/mods/xdecor/src/nodes.lua @@ -0,0 +1,644 @@ +screwdriver = screwdriver or {} +local S = xdecor.S +local ALPHA_CLIP = minetest.features.use_texture_alpha_string_modes and "clip" or true +local ALPHA_OPAQUE = minetest.features.use_texture_alpha_string_modes and "opaque" or false + +local function register_pane(name, desc, def) + xpanes.register_pane(name, { + description = desc, + tiles = {"xdecor_" .. name .. ".png"}, + drawtype = "airlike", + paramtype = "light", + textures = {"xdecor_" .. name .. ".png", "" ,"xdecor_" .. name .. ".png"}, + inventory_image = "xdecor_" .. name .. ".png", + wield_image = "xdecor_" .. name .. ".png", + groups = def.groups, + sounds = def.sounds or default.node_sound_defaults(), + recipe = def.recipe + }) +end + +register_pane("bamboo_frame", S("Bamboo Frame"), { + groups = {choppy = 3, oddly_breakable_by_hand = 2, pane = 1, flammable = 2}, + recipe = { + {"default:papyrus", "default:papyrus", "default:papyrus"}, + {"default:papyrus", "farming:cotton", "default:papyrus"}, + {"default:papyrus", "default:papyrus", "default:papyrus"} + } +}) + +register_pane("chainlink", S("Chainlink"), { + groups = {cracky = 3, oddly_breakable_by_hand = 2, pane = 1}, + recipe = { + {"default:steel_ingot", "", "default:steel_ingot"}, + {"", "default:steel_ingot", ""}, + {"default:steel_ingot", "", "default:steel_ingot"} + } +}) + +register_pane("rusty_bar", S("Rusty Iron Bars"), { + sounds = default.node_sound_stone_defaults(), + groups = {cracky = 2, pane = 1}, + recipe = { + {"", "default:dirt", ""}, + {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, + {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"} + } +}) + +register_pane("wood_frame", S("Wood Frame"), { + sounds = default.node_sound_wood_defaults(), + groups = {choppy = 2, pane = 1, flammable = 2}, + recipe = { + {"group:wood", "group:stick", "group:wood"}, + {"group:stick", "group:stick", "group:stick"}, + {"group:wood", "group:stick", "group:wood"} + } +}) + +xdecor.register("baricade", { + description = S("Baricade"), + drawtype = "plantlike", + paramtype2 = "facedir", + inventory_image = "xdecor_baricade.png", + tiles = {"xdecor_baricade.png"}, + groups = {choppy = 2, oddly_breakable_by_hand = 1, flammable = 2}, + damage_per_second = 4, + selection_box = xdecor.nodebox.slab_y(0.3), + collision_box = xdecor.pixelbox(2, {{0, 0, 1, 2, 2, 0}}) +}) + +xdecor.register("barrel", { + description = S("Barrel"), + tiles = {"xdecor_barrel_top.png", "xdecor_barrel_top.png", "xdecor_barrel_sides.png"}, + on_place = minetest.rotate_node, + groups = {choppy = 2, oddly_breakable_by_hand = 1, flammable = 2}, + sounds = default.node_sound_wood_defaults() +}) + +local function register_storage(name, desc, def) + xdecor.register(name, { + description = desc, + inventory = {size = def.inv_size or 24}, + infotext = desc, + tiles = def.tiles, + use_texture_alpha = ALPHA_OPAQUE, + node_box = def.node_box, + on_rotate = def.on_rotate, + on_place = def.on_place, + groups = def.groups or {choppy = 2, oddly_breakable_by_hand = 1, flammable = 2}, + sounds = default.node_sound_wood_defaults() + }) +end + +register_storage("cabinet", S("Wooden Cabinet"), { + on_rotate = screwdriver.rotate_simple, + tiles = { + "xdecor_cabinet_sides.png", "xdecor_cabinet_sides.png", + "xdecor_cabinet_sides.png", "xdecor_cabinet_sides.png", + "xdecor_cabinet_sides.png", "xdecor_cabinet_front.png" + } +}) + +register_storage("cabinet_half", S("Half Wooden Cabinet"), { + inv_size = 8, + node_box = xdecor.nodebox.slab_y(0.5, 0.5), + on_rotate = screwdriver.rotate_simple, + tiles = { + "xdecor_cabinet_sides.png", "xdecor_cabinet_sides.png", + "xdecor_half_cabinet_sides.png", "xdecor_half_cabinet_sides.png", + "xdecor_half_cabinet_sides.png", "xdecor_half_cabinet_front.png" + } +}) + +if minetest.get_modpath("moreblocks") then + minetest.register_alias("xdecor:empty_shelf", "moreblocks:empty_shelf") +else + register_storage("empty_shelf", S("Empty Shelf"), { + on_rotate = screwdriver.rotate_simple, + tiles = { + "default_wood.png", "default_wood.png", "default_wood.png", + "default_wood.png", "default_wood.png^xdecor_empty_shelf.png" + } + }) +end + +register_storage("multishelf", S("Multi Shelf"), { + on_rotate = screwdriver.rotate_simple, + tiles = { + "default_wood.png", "default_wood.png", "default_wood.png", + "default_wood.png", "default_wood.png^xdecor_multishelf.png" + }, +}) + +xdecor.register("candle", { + description = S("Candle"), + light_source = 12, + drawtype = "torchlike", + inventory_image = "xdecor_candle_inv.png", + wield_image = "xdecor_candle_wield.png", + paramtype2 = "wallmounted", + walkable = false, + groups = {dig_immediate = 3, attached_node = 1}, + tiles = { + { + name = "xdecor_candle_floor.png", + animation = {type="vertical_frames", length = 1.5} + }, + { + name = "xdecor_candle_hanging.png", + animation = {type="vertical_frames", length = 1.5} + }, + { + name = "xdecor_candle_wall.png", + animation = {type="vertical_frames", length = 1.5} + } + }, + selection_box = { + type = "wallmounted", + wall_top = {-0.25, -0.3, -0.25, 0.25, 0.5, 0.25}, + wall_bottom = {-0.25, -0.5, -0.25, 0.25, 0.1, 0.25}, + wall_side = {-0.5, -0.35, -0.15, -0.15, 0.4, 0.15} + } +}) + +xdecor.register("chair", { + description = S("Chair"), + tiles = {"xdecor_wood.png"}, + sounds = default.node_sound_wood_defaults(), + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 2}, + on_rotate = screwdriver.rotate_simple, + node_box = xdecor.pixelbox(16, { + {3, 0, 11, 2, 16, 2}, + {11, 0, 11, 2, 16, 2}, + {5, 9, 11.5, 6, 6, 1}, + {3, 0, 3, 2, 6, 2}, + {11, 0, 3, 2, 6, 2}, + {3, 6, 3, 10, 2, 8} + }), + can_dig = xdecor.sit_dig, + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + pos.y = pos.y + 0 -- Sitting position + xdecor.sit(pos, node, clicker, pointed_thing) + return itemstack + end +}) + +xdecor.register("cobweb", { + description = S("Cobweb"), + drawtype = "plantlike", + tiles = {"xdecor_cobweb.png"}, + inventory_image = "xdecor_cobweb.png", + liquid_viscosity = 8, + liquidtype = "source", + liquid_alternative_flowing = "xdecor:cobweb", + liquid_alternative_source = "xdecor:cobweb", + liquid_renewable = false, + liquid_range = 0, + walkable = false, + selection_box = {type = "regular"}, + groups = {snappy = 3, liquid = 3, flammable = 3}, + sounds = default.node_sound_leaves_defaults() +}) + +local curtain_colors = { + red = S("Red Curtain"), +} + +for c, desc in pairs(curtain_colors) do + xdecor.register("curtain_" .. c, { + description = desc, + walkable = false, + tiles = {"wool_white.png"}, + color = c, + inventory_image = "wool_white.png^[colorize:" .. c .. + ":170^xdecor_curtain_open_overlay.png^[makealpha:255,126,126", + wield_image = "wool_white.png^[colorize:" .. c .. ":170", + drawtype = "signlike", + paramtype2 = "colorwallmounted", + groups = {dig_immediate = 3, flammable = 3}, + selection_box = {type = "wallmounted"}, + on_rightclick = function(pos, node, _, itemstack) + minetest.set_node(pos, {name = "xdecor:curtain_open_" .. c, param2 = node.param2}) + return itemstack + end + }) + + xdecor.register("curtain_open_" .. c, { + tiles = {"wool_white.png^xdecor_curtain_open_overlay.png^[makealpha:255,126,126"}, + color = c, + drawtype = "signlike", + paramtype2 = "colorwallmounted", + walkable = false, + groups = {dig_immediate = 3, flammable = 3, not_in_creative_inventory = 1}, + selection_box = {type="wallmounted"}, + drop = "xdecor:curtain_" .. c, + on_rightclick = function(pos, node, _, itemstack) + minetest.set_node(pos, {name="xdecor:curtain_" .. c, param2 = node.param2}) + return itemstack + end + }) + + minetest.register_craft({ + output = "xdecor:curtain_" .. c .. " 4", + recipe = { + {"", "wool:" .. c, ""}, + {"", "wool:" .. c, ""} + } + }) +end + +xdecor.register("cushion", { + description = S("Cushion"), + tiles = {"xdecor_cushion.png"}, + groups = {snappy = 3, flammable = 3, fall_damage_add_percent = -50}, + on_place = minetest.rotate_node, + node_box = xdecor.nodebox.slab_y(0.5), + can_dig = xdecor.sit_dig, + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + pos.y = pos.y + 0 -- Sitting position + xdecor.sit(pos, node, clicker, pointed_thing) + return itemstack + end +}) + +xdecor.register("cushion_block", { + description = S("Cushion Block"), + tiles = {"xdecor_cushion.png"}, + groups = {snappy = 3, flammable = 3, fall_damage_add_percent = -75, not_in_creative_inventory = 1} +}) + +local function door_access(name) + return name:find("prison") +end + +local xdecor_doors = { + japanese = { + recipe = { + {"group:wood", "default:paper"}, + {"default:paper", "group:wood"}, + {"group:wood", "default:paper"} + }, + desc = S("Japanese Door"), + }, + prison = { + recipe = { + {"xpanes:bar_flat", "xpanes:bar_flat",}, + {"xpanes:bar_flat", "xpanes:bar_flat",}, + {"xpanes:bar_flat", "xpanes:bar_flat"} + }, + desc = S("Prison Door"), + }, + rusty_prison = { + recipe = { + {"xpanes:rusty_bar_flat", "xpanes:rusty_bar_flat",}, + {"xpanes:rusty_bar_flat", "xpanes:rusty_bar_flat",}, + {"xpanes:rusty_bar_flat", "xpanes:rusty_bar_flat"} + }, + desc = S("Rusty Prison Door"), + }, + screen = { + recipe = { + {"group:wood", "group:wood"}, + {"xpanes:chainlink_flat", "xpanes:chainlink_flat"}, + {"group:wood", "group:wood"} + }, + desc = S("Screen Door"), + }, + slide = { + recipe = { + {"default:paper", "default:paper"}, + {"default:paper", "default:paper"}, + {"group:wood", "group:wood"} + }, + desc = S("Slide Door"), + }, + woodglass = { + recipe = { + {"default:glass", "default:glass"}, + {"group:wood", "group:wood"}, + {"group:wood", "group:wood"} + }, + desc = S("Woodglass Door"), + }, +} + +local mesecons_register + +if minetest.global_exists("mesecon") then + mesecons_register = { effector = { + action_on = function(pos, node) + local door = doors.get(pos) + if door then + door:open() + end + end, + action_off = function(pos, node) + local door = doors.get(pos) + if door then + door:close() + end + end, + rules = mesecon.rules.pplate + }} +end + +for name, def in pairs(xdecor_doors) do + if not doors.register then break end + doors.register(name .. "_door", { + tiles = { + {name = "xdecor_" .. name .. "_door.png", backface_culling = true} + }, + description = def.desc, + inventory_image = "xdecor_" .. name .. "_door_inv.png", + protected = door_access(name), + groups = {choppy = 2, cracky = 2, oddly_breakable_by_hand = 1, door = 1}, + recipe = def.recipe, + mesecons = mesecons_register, + }) +end + +xdecor.register("enderchest", { + description = S("Ender Chest"), + tiles = { + "xdecor_enderchest_top.png", "xdecor_enderchest_top.png", + "xdecor_enderchest_side.png", "xdecor_enderchest_side.png", + "xdecor_enderchest_side.png", "xdecor_enderchest_front.png" + }, + groups = {cracky = 1, choppy = 1}, + sounds = default.node_sound_stone_defaults(), + on_rotate = screwdriver.rotate_simple, + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", [[ size[8,9] + list[current_player;enderchest;0,0;8,4;] + list[current_player;main;0,5;8,4;] + listring[current_player;enderchest] + listring[current_player;main] ]] + .. xbg .. default.get_hotbar_bg(0,5)) + + meta:set_string("infotext", S("Ender Chest")) + end +}) + +minetest.register_on_joinplayer(function(player) + local inv = player:get_inventory() + inv:set_size("enderchest", 8*4) +end) + +xdecor.register("ivy", { + description = S("Ivy"), + drawtype = "signlike", + walkable = false, + climbable = true, + groups = {snappy = 3, flora = 1, attached_node = 1, plant = 1, flammable = 3}, + paramtype2 = "wallmounted", + selection_box = {type="wallmounted"}, + tiles = {"xdecor_ivy.png"}, + inventory_image = "xdecor_ivy.png", + wield_image = "xdecor_ivy.png", + sounds = default.node_sound_leaves_defaults() +}) + +xdecor.register("rooster", { + description = S("Rooster"), + drawtype = "torchlike", + inventory_image = "xdecor_rooster.png", + walkable = false, + groups = {snappy = 3, attached_node = 1}, + tiles = {"xdecor_rooster.png"}, +}) + +xdecor.register("lantern", { + description = S("Lantern"), + light_source = 13, + drawtype = "plantlike", + inventory_image = "xdecor_lantern_inv.png", + wield_image = "xdecor_lantern_inv.png", + paramtype2 = "wallmounted", + walkable = false, + groups = {snappy = 3, attached_node = 1}, + tiles = { + { + name = "xdecor_lantern.png", + animation = {type="vertical_frames", length = 1.5} + } + }, + selection_box = xdecor.pixelbox(16, {{4, 0, 4, 8, 16, 8}}) +}) + +local xdecor_lightbox = { + iron = S("Iron Light Box"), + wooden = S("Wooden Light Box"), + wooden2 = S("Wooden Light Box 2"), +} + +for l, desc in pairs(xdecor_lightbox) do + xdecor.register(l .. "_lightbox", { + description = desc, + tiles = {"xdecor_" .. l .. "_lightbox.png"}, + groups = {cracky = 3, choppy = 3, oddly_breakable_by_hand = 2}, + light_source = 13, + sounds = default.node_sound_glass_defaults() + }) +end + +local xdecor_potted = { + dandelion_white = S("Potted White Dandelion"), + dandelion_yellow = S("Potted Yellow Dandelion"), + geranium = S("Potted Geranium"), + rose = S("Potted Rose"), + tulip = S("Potted Tulip"), + viola = S("Potted Viola"), +} + +for f, desc in pairs(xdecor_potted) do + xdecor.register("potted_" .. f, { + description = desc, + walkable = false, + groups = {snappy = 3, flammable = 3, plant = 1, flower = 1}, + tiles = {"xdecor_" .. f .. "_pot.png"}, + inventory_image = "xdecor_" .. f .. "_pot.png", + drawtype = "plantlike", + sounds = default.node_sound_leaves_defaults(), + selection_box = xdecor.nodebox.slab_y(0.3) + }) + + minetest.register_craft({ + output = "xdecor:potted_" .. f, + recipe = { + {"default:clay_brick", "flowers:" .. f, "default:clay_brick"}, + {"", "default:clay_brick", ""} + } + }) +end + +local painting_box = { + type = "wallmounted", + wall_top = {-0.4375, 0.4375, -0.3125, 0.4375, 0.5, 0.3125}, + wall_bottom = {-0.4375, -0.5, -0.3125, 0.4375, -0.4375, 0.3125}, + wall_side = {-0.5, -0.3125, -0.4375, -0.4375, 0.3125, 0.4375} +} + +xdecor.register("painting_1", { + description = S("Painting"), + tiles = {"xdecor_painting_1.png"}, + use_texture_alpha = ALPHA_OPAQUE, + inventory_image = "xdecor_painting_empty.png", + wield_image = "xdecor_painting_empty.png", + paramtype2 = "wallmounted", + sunlight_propagates = true, + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 2, attached_node = 1}, + sounds = default.node_sound_wood_defaults(), + node_box = painting_box, + node_placement_prediction = "", + on_place = function(itemstack, placer, pointed_thing) + local num = math.random(4) + local leftover = minetest.item_place_node( + ItemStack("xdecor:painting_" .. num), placer, pointed_thing) + + if leftover:get_count() == 0 and + not minetest.setting_getbool("creative_mode") then + itemstack:take_item() + end + + return itemstack + end +}) + +for i = 2, 4 do + xdecor.register("painting_" .. i, { + tiles = {"xdecor_painting_" .. i .. ".png"}, + use_texture_alpha = ALPHA_OPAQUE, + paramtype2 = "wallmounted", + drop = "xdecor:painting_1", + sunlight_propagates = true, + groups = { + choppy = 3, + oddly_breakable_by_hand = 2, + flammable = 2, + attached_node = 1, + not_in_creative_inventory = 1 + }, + sounds = default.node_sound_wood_defaults(), + node_box = painting_box + }) +end + +xdecor.register("stonepath", { + description = S("Garden Stone Path"), + tiles = {"default_stone.png"}, + groups = {snappy = 3}, + on_rotate = screwdriver.rotate_simple, + sounds = default.node_sound_stone_defaults(), + sunlight_propagates = true, + node_box = xdecor.pixelbox(16, { + {8, 0, 8, 6, .5, 6}, {1, 0, 1, 6, .5, 6}, + {1, 0, 10, 5, .5, 5}, {10, 0, 2, 4, .5, 4} + }), + selection_box = xdecor.nodebox.slab_y(0.05) +}) + +local function register_hard_node(name, desc, def) + if def == nil then def = { groups = {cracky=1}, sounds = default.node_sound_stone_defaults() } end + xdecor.register(name, { + description = desc, + tiles = {"xdecor_" .. name .. ".png"}, + groups = def.groups or {cracky = 1}, + sounds = def.sounds or default.node_sound_stone_defaults() + }) +end + +register_hard_node("cactusbrick", S("Cactus Brick"), { groups = {cracky = 1}, sounds = default.node_sound_stone_defaults() }) +register_hard_node("coalstone_tile", S("Coal Stone Tile"), { groups = {cracky = 1}, sounds = default.node_sound_stone_defaults() }) +register_hard_node("desertstone_tile", S("Desert Stone Tile"), { groups = {cracky = 1}, sounds = default.node_sound_stone_defaults() }) +register_hard_node("hard_clay", S("Hardened Clay"), { groups = {cracky = 1}, sounds = default.node_sound_stone_defaults() }) +register_hard_node("moonbrick", S("Moon Brick"), { groups = {cracky = 1}, sounds = default.node_sound_stone_defaults() }) +register_hard_node("stone_tile", S("Stone Tile"), { groups = {cracky = 1}, sounds = default.node_sound_stone_defaults() }) +register_hard_node("stone_rune", S("Runestone"), { groups = {cracky = 1}, sounds = default.node_sound_stone_defaults() }) + +register_hard_node("packed_ice", S("Packed Ice"), { + groups = {cracky = 1, puts_out_fire = 1, slippery = 3}, + sounds = default.node_sound_glass_defaults() +}) + +register_hard_node("wood_tile", S("Wooden Tile"), { + groups = {choppy = 1, wood = 1, flammable = 2}, + sounds = default.node_sound_wood_defaults() +}) + +xdecor.register("table", { + description = S("Table"), + tiles = {"xdecor_wood.png"}, + groups = {choppy = 2, oddly_breakable_by_hand = 1, flammable = 2}, + sounds = default.node_sound_wood_defaults(), + node_box = xdecor.pixelbox(16, { + {0, 14, 0, 16, 2, 16}, {5.5, 0, 5.5, 5, 14, 6} + }) +}) + +xdecor.register("tatami", { + description = S("Tatami"), + tiles = {"xdecor_tatami.png"}, + wield_image = "xdecor_tatami.png", + groups = {snappy = 3, flammable = 3}, + sunlight_propagates = true, + node_box = xdecor.nodebox.slab_y(0.0625) +}) + +xdecor.register("trampoline", { + description = S("Trampoline"), + tiles = {"xdecor_trampoline.png", "mailbox_blank16.png", "xdecor_trampoline_sides.png"}, + use_texture_alpha = ALPHA_CLIP, + groups = {cracky = 3, oddly_breakable_by_hand = 1, fall_damage_add_percent = -80, bouncy = 90}, + node_box = xdecor.nodebox.slab_y(0.5), + sounds = { + footstep = { + name = "xdecor_bouncy", + gain = 0.8 + } + } +}) + +xdecor.register("tv", { + description = S("Television"), + light_source = 11, + groups = {cracky = 3, oddly_breakable_by_hand = 2}, + on_rotate = screwdriver.rotate_simple, + tiles = { + "xdecor_television_left.png^[transformR270", + "xdecor_television_left.png^[transformR90", + "xdecor_television_left.png^[transformFX", + "xdecor_television_left.png", "xdecor_television_back.png", + { + name = "xdecor_television_front_animated.png", + animation = {type = "vertical_frames", length = 80.0} + } + } +}) + +xdecor.register("woodframed_glass", { + description = S("Wood Framed Glass"), + drawtype = "glasslike_framed", + sunlight_propagates = true, + tiles = {"xdecor_woodframed_glass.png", "xdecor_woodframed_glass_detail.png"}, + use_texture_alpha = ALPHA_CLIP, + groups = {cracky = 2, oddly_breakable_by_hand = 1}, + sounds = default.node_sound_glass_defaults() +}) + +for _, v in ipairs({"radio", "speaker"}) do + xdecor.register(v, { + description = v:gsub("^%l", string.upper), + on_rotate = screwdriver.rotate_simple, + tiles = { + "xdecor_" .. v .. "_top.png", + "xdecor_" .. v .. "_side.png", + "xdecor_" .. v .. "_side.png", + "xdecor_" .. v .. "_side.png", + "xdecor_" .. v .. "_back.png", + "xdecor_" .. v .. "_front.png", + }, + groups = {cracky = 2, not_cuttable = 1}, + }) +end diff --git a/mods/xdecor/src/recipes.lua b/mods/xdecor/src/recipes.lua new file mode 100644 index 0000000..10fd33a --- /dev/null +++ b/mods/xdecor/src/recipes.lua @@ -0,0 +1,299 @@ +minetest.register_craft({ + output = "xdecor:baricade", + recipe = { + {"group:stick", "", "group:stick"}, + {"", "default:steel_ingot", ""}, + {"group:stick", "", "group:stick"} + } +}) + +minetest.register_craft({ + output = "xdecor:barrel", + recipe = { + {"group:wood", "group:wood", "group:wood"}, + {"default:iron_lump", "", "default:iron_lump"}, + {"group:wood", "group:wood", "group:wood"} + } +}) + +minetest.register_craft({ + output = "xdecor:candle", + recipe = { + {"default:torch"} + } +}) + +minetest.register_craft({ + output = "xdecor:cabinet", + recipe = { + {"group:wood", "group:wood", "group:wood"}, + {"doors:trapdoor", "", "doors:trapdoor"}, + {"group:wood", "group:wood", "group:wood"} + } +}) + +minetest.register_craft({ + output = "xdecor:cabinet_half 2", + recipe = { + {"xdecor:cabinet"} + } +}) + +minetest.register_craft({ + output = "xdecor:cactusbrick", + recipe = { + {"default:brick", "default:cactus"} + } +}) + +minetest.register_craft({ + output = "xdecor:chair", + recipe = { + {"group:stick", "", ""}, + {"group:stick", "group:stick", "group:stick"}, + {"group:stick", "", "group:stick"} + } +}) + +minetest.register_craft({ + output = "xdecor:coalstone_tile 4", + recipe = { + {"default:coalblock", "default:stone"}, + {"default:stone", "default:coalblock"} + } +}) + +minetest.register_craft({ + output = "xdecor:cobweb", + recipe = { + {"farming:string", "", "farming:string"}, + {"", "farming:string", ""}, + {"farming:string", "", "farming:string"} + } +}) + +minetest.register_craft({ + output = "xdecor:cushion 3", + recipe = { + {"wool:red", "wool:red", "wool:red"} + } +}) + +minetest.register_craft({ + output = "xdecor:cushion_block", + recipe = { + {"xdecor:cushion"}, + {"xdecor:cushion"} + } +}) + +minetest.register_craft({ + output = "xdecor:desertstone_tile", + recipe = { + {"default:desert_cobble", "default:desert_cobble"}, + {"default:desert_cobble", "default:desert_cobble"} + } +}) + +if not minetest.get_modpath("moreblocks") then + minetest.register_craft({ + output = "xdecor:empty_shelf", + recipe = { + {"group:wood", "group:wood", "group:wood"}, + {"", "", ""}, + {"group:wood", "group:wood", "group:wood"} + } + }) +end + +minetest.register_craft({ + output = "xdecor:enderchest", + recipe = { + {"", "default:obsidian", ""}, + {"default:obsidian", "default:chest", "default:obsidian"}, + {"", "default:obsidian", ""} + } +}) + +minetest.register_craft({ + output = "xdecor:hard_clay", + recipe = { + {"default:clay", "default:clay"}, + {"default:clay", "default:clay"} + } +}) + +minetest.register_craft({ + output = "xdecor:iron_lightbox", + recipe = { + {"xpanes:bar_flat", "default:torch", "xpanes:bar_flat"}, + {"xpanes:bar_flat", "default:glass", "xpanes:bar_flat"}, + {"xpanes:bar_flat", "default:torch", "xpanes:bar_flat"} + } +}) + +minetest.register_craft({ + output = "xdecor:ivy 4", + recipe = { + {"group:leaves"}, + {"group:leaves"} + } +}) + +minetest.register_craft({ + output = "xdecor:lantern", + recipe = { + {"default:iron_lump"}, + {"default:torch"}, + {"default:iron_lump"} + } +}) + +minetest.register_craft({ + output = "xdecor:moonbrick", + recipe = { + {"default:brick", "default:stone"} + } +}) + +minetest.register_craft({ + output = "xdecor:multishelf", + recipe = { + {"group:wood", "group:wood", "group:wood"}, + {"group:vessel", "group:book", "group:vessel"}, + {"group:wood", "group:wood", "group:wood"} + } +}) + +minetest.register_craft({ + output = "xdecor:packed_ice", + recipe = { + {"default:ice", "default:ice"}, + {"default:ice", "default:ice"} + } +}) + +minetest.register_craft({ + output = "xdecor:painting_1", + recipe = { + {"default:sign_wall_wood", "group:dye"} + } +}) + +minetest.register_craft({ + output = "xdecor:radio", + type = "shapeless", + recipe = {"xdecor:speaker", "xdecor:speaker"} +}) + +minetest.register_craft({ + output = "xdecor:rooster", + recipe = { + {"default:gold_ingot", "", "default:gold_ingot"}, + {"", "default:gold_ingot", ""}, + {"default:gold_ingot", "", "default:gold_ingot"} + } +}) + +minetest.register_craft({ + output = "xdecor:speaker", + recipe = { + {"default:gold_ingot", "default:copper_ingot", "default:gold_ingot"}, + {"default:copper_ingot", "", "default:copper_ingot"}, + {"default:gold_ingot", "default:copper_ingot", "default:gold_ingot"} + } +}) + +minetest.register_craft({ + output = "xdecor:stone_tile 2", + recipe = { + {"default:cobble", "default:cobble"}, + {"default:cobble", "default:cobble"} + } +}) + +minetest.register_craft({ + output = "xdecor:stone_rune 4", + recipe = { + {"default:stone", "default:stone", "default:stone"}, + {"default:stone", "", "default:stone"}, + {"default:stone", "default:stone", "default:stone"} + } +}) + +minetest.register_craft({ + output = "xdecor:stonepath 16", + recipe = { + {"stairs:slab_cobble", "", "stairs:slab_cobble"}, + {"", "stairs:slab_cobble", ""}, + {"stairs:slab_cobble", "", "stairs:slab_cobble"} + } +}) + +minetest.register_craft({ + output = "xdecor:table", + recipe = { + {"stairs:slab_wood", "stairs:slab_wood", "stairs:slab_wood"}, + {"", "group:stick", ""}, + {"", "group:stick", ""} + } +}) + +minetest.register_craft({ + output = "xdecor:tatami", + recipe = { + {"farming:wheat", "farming:wheat", "farming:wheat"} + } +}) + +minetest.register_craft({ + output = "xdecor:trampoline", + recipe = { + {"farming:string", "farming:string", "farming:string"}, + {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, + {"default:steel_ingot", "", "default:steel_ingot"} + } +}) + +minetest.register_craft({ + output = "xdecor:tv", + recipe = { + {"default:steel_ingot", "default:copper_ingot", "default:steel_ingot"}, + {"default:steel_ingot", "default:glass", "default:steel_ingot"}, + {"default:steel_ingot", "default:copper_ingot", "default:steel_ingot"} + } +}) + +minetest.register_craft({ + output = "xdecor:woodframed_glass", + recipe = { + {"group:stick", "group:stick", "group:stick"}, + {"group:stick", "default:glass", "group:stick"}, + {"group:stick", "group:stick", "group:stick"} + } +}) + +minetest.register_craft({ + output = "xdecor:wood_tile 2", + recipe = { + {"", "group:wood", ""}, + {"group:wood", "", "group:wood"}, + {"", "group:wood", ""} + } +}) + +minetest.register_craft({ + output = "xdecor:wooden_lightbox", + recipe = { + {"group:stick", "default:torch", "group:stick"}, + {"group:stick", "default:glass", "group:stick"}, + {"group:stick", "default:torch", "group:stick"} + } +}) + +minetest.register_craft({ + output = "xdecor:wooden2_lightbox", + type = "shapeless", + recipe = {"xdecor:wooden_lightbox"}, +}) + diff --git a/mods/xdecor/src/rope.lua b/mods/xdecor/src/rope.lua new file mode 100644 index 0000000..2a28bdd --- /dev/null +++ b/mods/xdecor/src/rope.lua @@ -0,0 +1,75 @@ +local rope = {} +local S = xdecor.S + +-- Code by Mirko K. (modified by Temperest, Wulfsdad and kilbith) (License: GPL). +function rope.place(itemstack, placer, pointed_thing) + if pointed_thing.type == "node" then + local pos = pointed_thing.above + local oldnode = minetest.get_node(pos) + local stackname = itemstack:get_name() + + if minetest.is_protected(pos, placer:get_player_name()) then + return itemstack + end + + while oldnode.name == "air" and not itemstack:is_empty() do + local newnode = {name = stackname, param1 = 0} + minetest.set_node(pos, newnode) + itemstack:take_item() + pos.y = pos.y - 1 + oldnode = minetest.get_node(pos) + end + end + + return itemstack +end + +function rope.remove(pos, oldnode, digger, rope_name) + local num = 0 + local below = {x = pos.x, y = pos.y, z = pos.z} + local digger_inv = digger:get_inventory() + + while minetest.get_node(below).name == rope_name do + minetest.remove_node(below) + below.y = below.y - 1 + num = num + 1 + end + + if num == 0 then return end + digger_inv:add_item("main", rope_name.." "..num) + + return true +end + +xdecor.register("rope", { + description = S("Rope"), + drawtype = "plantlike", + walkable = false, + climbable = true, + groups = {snappy = 3, flammable = 3}, + tiles = {"xdecor_rope.png"}, + inventory_image = "xdecor_rope_inv.png", + wield_image = "xdecor_rope_inv.png", + selection_box = xdecor.pixelbox(8, {{3, 0, 3, 2, 8, 2}}), + on_place = rope.place, + + on_punch = function(pos, node, puncher, pointed_thing) + local player_name = puncher:get_player_name() + + if not minetest.is_protected(pos, player_name) or + minetest.get_player_privs(player_name).protection_bypass then + rope.remove(pos, node, puncher, "xdecor:rope") + end + end +}) + +-- Recipes + +minetest.register_craft({ + output = "xdecor:rope", + recipe = { + {"farming:string"}, + {"farming:string"}, + {"farming:string"} + } +}) diff --git a/mods/xdecor/src/workbench.lua b/mods/xdecor/src/workbench.lua new file mode 100644 index 0000000..09d28de --- /dev/null +++ b/mods/xdecor/src/workbench.lua @@ -0,0 +1,365 @@ +local workbench = {} +local nodes = {} + +screwdriver = screwdriver or {} +local min, ceil = math.min, math.ceil +local S = xdecor.S +local FS = function(...) return minetest.formspec_escape(S(...)) end +local ar_api = minetest.get_modpath("3d_armor") or false + +-- Nodes allowed to be cut +-- Only the regular, solid blocks without metas or explosivity can be cut +for node, def in pairs(minetest.registered_nodes) do + if xdecor.stairs_valid_def(def) then + nodes[#nodes + 1] = node + end +end + +-- Nodeboxes definitions +workbench.defs = { + -- Name YieldX YZ WH L + {"nanoslab", 16, { 0, 0, 0, 8, 1, 8 }}, + {"micropanel", 16, { 0, 0, 0, 16, 1, 8 }}, + {"microslab", 8, { 0, 0, 0, 16, 1, 16 }}, + {"thinstair", 8, { 0, 7, 0, 16, 1, 8 }, + { 0, 15, 8, 16, 1, 8 }}, + {"cube", 4, { 0, 0, 0, 8, 8, 8 }}, + {"panel", 4, { 0, 0, 0, 16, 8, 8 }}, + {"slab", 2, nil }, + {"doublepanel", 2, { 0, 0, 0, 16, 8, 8 }, + { 0, 8, 8, 16, 8, 8 }}, + {"halfstair", 2, { 0, 0, 0, 8, 8, 16 }, + { 0, 8, 8, 8, 8, 8 }}, + {"stair_outer", 1, nil }, + {"stair", 1, nil }, + {"stair_inner", 1, nil } +} + +local repairable_tools = {"pick", "axe", "shovel"} + +if ar_api then repairable_tools = {"pick", "axe", "shovel", "sword", "hoe", "armor", "shield"} +else repairable_tools = {"pick", "axe", "shovel", "hoe"} end + +local custom_repairable = {} +function xdecor:register_repairable(item) + custom_repairable[item] = true +end + +-- Tools allowed to be repaired +function workbench:repairable(stack) + if custom_repairable[stack] then return true end + + for _, t in ipairs(repairable_tools) do + if stack:find(t) then + return true + end + end +end + +-- method to allow other mods to check if an item is repairable +function xdecor:is_repairable(stack) + return workbench:repairable(stack) +end + +function workbench:get_output(inv, input, name) + local output = {} + for i = 1, #self.defs do + local nbox = self.defs[i] + local count = min(nbox[2] * input:get_count(), input:get_stack_max()) + local item = name .. "_" .. nbox[1] + + item = nbox[3] and item or "stairs:" .. nbox[1] .. "_" .. name:match(":(.*)") + output[i] = item .. " " .. count + end + + inv:set_list("forms", output) +end + +local main_fs = "label[0.9,1.23;"..FS("Cut").."]" + .."label[0.9,2.23;"..FS("Repair").."]" + ..[[ box[-0.05,1;2.05,0.9;#555555] + box[-0.05,2;2.05,0.9;#555555] ]] + .."button[0,0;2,1;craft;"..FS("Crafting").."]" + .."button[2,0;2,1;storage;"..FS("Storage").."]" + ..[[ image[3,1;1,1;gui_arrow.png] + image[0,1;1,1;worktable_saw.png] + image[0,2;1,1;worktable_anvil.png] + image[3,2;1,1;hammer_layout.png] + list[context;input;2,1;1,1;] + list[context;tool;2,2;1,1;] + list[context;hammer;3,2;1,1;] + list[context;forms;4,0;4,3;] + listring[current_player;main] + listring[context;tool] + listring[current_player;main] + listring[context;hammer] + listring[current_player;main] + listring[context;forms] + listring[current_player;main] + listring[context;input] +]] + +local crafting_fs = "image[5,1;1,1;gui_furnace_arrow_bg.png^[transformR270]" + .."button[0,0;1.5,1;back;< "..FS("Back").."]" + ..[[ list[current_player;craft;2,0;3,3;] + list[current_player;craftpreview;6,1;1,1;] + listring[current_player;main] + listring[current_player;craft] +]] + +local storage_fs = "list[context;storage;0,1;8,2;]" + .."button[0,0;1.5,1;back;< "..FS("Back").."]" + ..[[listring[context;storage] + listring[current_player;main] +]] + +local formspecs = { + -- Main formspec + main_fs, + + -- Crafting formspec + crafting_fs, + + -- Storage formspec + storage_fs, +} + +function workbench:set_formspec(meta, id) + meta:set_string("formspec", + "size[8,7;]list[current_player;main;0,3.25;8,4;]" .. + formspecs[id] .. xbg .. default.get_hotbar_bg(0,3.25)) +end + +function workbench.construct(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + + inv:set_size("tool", 1) + inv:set_size("input", 1) + inv:set_size("hammer", 1) + inv:set_size("forms", 4*3) + inv:set_size("storage", 8*2) + + meta:set_string("infotext", S("Work Bench")) + workbench:set_formspec(meta, 1) +end + +function workbench.fields(pos, _, fields) + if fields.quit then return end + + local meta = minetest.get_meta(pos) + local id = fields.back and 1 or fields.craft and 2 or fields.storage and 3 + if not id then return end + + workbench:set_formspec(meta, id) +end + +function workbench.dig(pos) + local inv = minetest.get_meta(pos):get_inventory() + return inv:is_empty("input") and inv:is_empty("hammer") and + inv:is_empty("tool") and inv:is_empty("storage") +end + +function workbench.timer(pos) + local timer = minetest.get_node_timer(pos) + local inv = minetest.get_meta(pos):get_inventory() + local tool = inv:get_stack("tool", 1) + local hammer = inv:get_stack("hammer", 1) + + if tool:is_empty() or hammer:is_empty() or tool:get_wear() == 0 then + timer:stop() + return + end + + -- Tool's wearing range: 0-65535; 0 = new condition + tool:add_wear(-500) + hammer:add_wear(700) + + inv:set_stack("tool", 1, tool) + inv:set_stack("hammer", 1, hammer) + + return true +end + +function workbench.allow_put(pos, listname, index, stack, player) + local stackname = stack:get_name() + if (listname == "tool" and stack:get_wear() > 0 and + workbench:repairable(stackname)) or + (listname == "input" and minetest.registered_nodes[stackname .. "_cube"]) or + (listname == "hammer" and stackname == "xdecor:hammer") or + listname == "storage" then + return stack:get_count() + end + + return 0 +end + +function workbench.on_put(pos, listname, index, stack, player) + local inv = minetest.get_meta(pos):get_inventory() + if listname == "input" then + local input = inv:get_stack("input", 1) + workbench:get_output(inv, input, stack:get_name()) + elseif listname == "tool" or listname == "hammer" then + local timer = minetest.get_node_timer(pos) + timer:start(3.0) + end +end + +function workbench.allow_move(pos, from_list, from_index, to_list, to_index, count, player) + return (to_list == "storage" and from_list ~= "forms") and count or 0 +end + +function workbench.on_move(pos, from_list, from_index, to_list, to_index, count, player) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local from_stack = inv:get_stack(from_list, from_index) + local to_stack = inv:get_stack(to_list, to_index) + + workbench.on_take(pos, from_list, from_index, from_stack, player) + workbench.on_put(pos, to_list, to_index, to_stack, player) +end + +function workbench.allow_take(pos, listname, index, stack, player) + return stack:get_count() +end + +function workbench.on_take(pos, listname, index, stack, player) + local inv = minetest.get_meta(pos):get_inventory() + local input = inv:get_stack("input", 1) + local inputname = input:get_name() + local stackname = stack:get_name() + + if listname == "input" then + if stackname == inputname and minetest.registered_nodes[inputname .. "_cube"] then + workbench:get_output(inv, input, stackname) + else + inv:set_list("forms", {}) + end + elseif listname == "forms" then + local fromstack = inv:get_stack(listname, index) + if not fromstack:is_empty() and fromstack:get_name() ~= stackname then + local player_inv = player:get_inventory() + if player_inv:room_for_item("main", fromstack) then + player_inv:add_item("main", fromstack) + end + end + + input:take_item(ceil(stack:get_count() / workbench.defs[index][2])) + inv:set_stack("input", 1, input) + workbench:get_output(inv, input, inputname) + end +end + +xdecor.register("workbench", { + description = S("Work Bench"), + groups = {cracky = 2, choppy = 2, oddly_breakable_by_hand = 1}, + sounds = default.node_sound_wood_defaults(), + tiles = { + "xdecor_workbench_top.png","xdecor_workbench_top.png", + "xdecor_workbench_sides.png", "xdecor_workbench_sides.png", + "xdecor_workbench_front.png", "xdecor_workbench_front.png" + }, + on_rotate = screwdriver.rotate_simple, + can_dig = workbench.dig, + on_timer = workbench.timer, + on_construct = workbench.construct, + on_receive_fields = workbench.fields, + on_metadata_inventory_put = workbench.on_put, + on_metadata_inventory_take = workbench.on_take, + on_metadata_inventory_move = workbench.on_move, + allow_metadata_inventory_put = workbench.allow_put, + allow_metadata_inventory_take = workbench.allow_take, + allow_metadata_inventory_move = workbench.allow_move +}) + +for _, d in ipairs(workbench.defs) do +for i = 1, #nodes do + local node = nodes[i] + local mod_name, item_name = node:match("^(.-):(.*)") + local def = minetest.registered_nodes[node] + + if item_name and d[3] then + local groups = {} + local tiles + groups.not_in_creative_inventory = 1 + + for k, v in pairs(def.groups) do + if k ~= "wood" and k ~= "stone" and k ~= "level" then + groups[k] = v + end + end + + if def.tiles then + if #def.tiles > 1 and (def.drawtype:sub(1,5) ~= "glass") then + tiles = def.tiles + else + tiles = {def.tiles[1]} + end + else + tiles = {def.tile_images[1]} + end + + --TODO: Translation support for Stairs/Slab + if not minetest.registered_nodes["stairs:slab_" .. item_name] then + stairs.register_stair_and_slab(item_name, node, + groups, tiles, def.description .. " Stair", + def.description .. " Slab", def.sounds) + end + + minetest.register_node(":" .. node .. "_" .. d[1], { + --TODO: Translation support + description = def.description .. " " .. d[1]:gsub("^%l", string.upper), + paramtype = "light", + paramtype2 = "facedir", + drawtype = "nodebox", + sounds = def.sounds, + tiles = tiles, + use_texture_alpha = def.use_texture_alpha, + groups = groups, + -- `unpack` has been changed to `table.unpack` in newest Lua versions + node_box = xdecor.pixelbox(16, {unpack(d, 3)}), + sunlight_propagates = true, + on_place = minetest.rotate_node + }) + + elseif item_name and mod_name then + minetest.register_alias_force( + ("%s:%s_innerstair"):format(mod_name, item_name), + ("stairs:stair_inner_%s"):format(item_name) + ) + minetest.register_alias_force( + ("%s:%s_outerstair"):format(mod_name, item_name), + ("stairs:stair_outer_%s"):format(item_name) + ) + end +end +end + +-- Craft items + +minetest.register_tool("xdecor:hammer", { + description = S("Hammer"), + inventory_image = "xdecor_hammer.png", + wield_image = "xdecor_hammer.png", + on_use = function() do + return end + end +}) + +-- Recipes + +minetest.register_craft({ + output = "xdecor:hammer", + recipe = { + {"default:steel_ingot", "group:stick", "default:steel_ingot"}, + {"", "group:stick", ""} + } +}) + +minetest.register_craft({ + output = "xdecor:workbench", + recipe = { + {"group:wood", "group:wood"}, + {"group:wood", "group:wood"} + } +}) diff --git a/mods/xdecor/textures/bg_btn.png b/mods/xdecor/textures/bg_btn.png new file mode 100644 index 0000000..5815572 Binary files /dev/null and b/mods/xdecor/textures/bg_btn.png differ diff --git a/mods/xdecor/textures/bishop_black.png b/mods/xdecor/textures/bishop_black.png new file mode 100644 index 0000000..388a622 Binary files /dev/null and b/mods/xdecor/textures/bishop_black.png differ diff --git a/mods/xdecor/textures/bishop_white.png b/mods/xdecor/textures/bishop_white.png new file mode 100644 index 0000000..2819a58 Binary files /dev/null and b/mods/xdecor/textures/bishop_white.png differ diff --git a/mods/xdecor/textures/chess_bg.png b/mods/xdecor/textures/chess_bg.png new file mode 100644 index 0000000..41ee603 Binary files /dev/null and b/mods/xdecor/textures/chess_bg.png differ diff --git a/mods/xdecor/textures/chessboard_sides.png b/mods/xdecor/textures/chessboard_sides.png new file mode 100644 index 0000000..1498b1d Binary files /dev/null and b/mods/xdecor/textures/chessboard_sides.png differ diff --git a/mods/xdecor/textures/chessboard_top.png b/mods/xdecor/textures/chessboard_top.png new file mode 100644 index 0000000..d6db051 Binary files /dev/null and b/mods/xdecor/textures/chessboard_top.png differ diff --git a/mods/xdecor/textures/ench_ui.png b/mods/xdecor/textures/ench_ui.png new file mode 100644 index 0000000..8a2f4a0 Binary files /dev/null and b/mods/xdecor/textures/ench_ui.png differ diff --git a/mods/xdecor/textures/gui_arrow.png b/mods/xdecor/textures/gui_arrow.png new file mode 100644 index 0000000..df1bbdb Binary files /dev/null and b/mods/xdecor/textures/gui_arrow.png differ diff --git a/mods/xdecor/textures/hammer_layout.png b/mods/xdecor/textures/hammer_layout.png new file mode 100644 index 0000000..355ceab Binary files /dev/null and b/mods/xdecor/textures/hammer_layout.png differ diff --git a/mods/xdecor/textures/hive_bee.png b/mods/xdecor/textures/hive_bee.png new file mode 100644 index 0000000..e221f1f Binary files /dev/null and b/mods/xdecor/textures/hive_bee.png differ diff --git a/mods/xdecor/textures/hive_layout.png b/mods/xdecor/textures/hive_layout.png new file mode 100644 index 0000000..27794f4 Binary files /dev/null and b/mods/xdecor/textures/hive_layout.png differ diff --git a/mods/xdecor/textures/king_black.png b/mods/xdecor/textures/king_black.png new file mode 100644 index 0000000..06cfc30 Binary files /dev/null and b/mods/xdecor/textures/king_black.png differ diff --git a/mods/xdecor/textures/king_white.png b/mods/xdecor/textures/king_white.png new file mode 100644 index 0000000..60621c4 Binary files /dev/null and b/mods/xdecor/textures/king_white.png differ diff --git a/mods/xdecor/textures/knight_black.png b/mods/xdecor/textures/knight_black.png new file mode 100644 index 0000000..44de5f1 Binary files /dev/null and b/mods/xdecor/textures/knight_black.png differ diff --git a/mods/xdecor/textures/knight_white.png b/mods/xdecor/textures/knight_white.png new file mode 100644 index 0000000..1de460f Binary files /dev/null and b/mods/xdecor/textures/knight_white.png differ diff --git a/mods/xdecor/textures/mailbox_blank16.png b/mods/xdecor/textures/mailbox_blank16.png new file mode 100644 index 0000000..017d4f9 Binary files /dev/null and b/mods/xdecor/textures/mailbox_blank16.png differ diff --git a/mods/xdecor/textures/mese_layout.png b/mods/xdecor/textures/mese_layout.png new file mode 100644 index 0000000..154a6bc Binary files /dev/null and b/mods/xdecor/textures/mese_layout.png differ diff --git a/mods/xdecor/textures/pawn_black.png b/mods/xdecor/textures/pawn_black.png new file mode 100644 index 0000000..7cb5fc8 Binary files /dev/null and b/mods/xdecor/textures/pawn_black.png differ diff --git a/mods/xdecor/textures/pawn_white.png b/mods/xdecor/textures/pawn_white.png new file mode 100644 index 0000000..f7a8dec Binary files /dev/null and b/mods/xdecor/textures/pawn_white.png differ diff --git a/mods/xdecor/textures/queen_black.png b/mods/xdecor/textures/queen_black.png new file mode 100644 index 0000000..d59e312 Binary files /dev/null and b/mods/xdecor/textures/queen_black.png differ diff --git a/mods/xdecor/textures/queen_white.png b/mods/xdecor/textures/queen_white.png new file mode 100644 index 0000000..d923f05 Binary files /dev/null and b/mods/xdecor/textures/queen_white.png differ diff --git a/mods/xdecor/textures/rook_black.png b/mods/xdecor/textures/rook_black.png new file mode 100644 index 0000000..fa87141 Binary files /dev/null and b/mods/xdecor/textures/rook_black.png differ diff --git a/mods/xdecor/textures/rook_white.png b/mods/xdecor/textures/rook_white.png new file mode 100644 index 0000000..6703452 Binary files /dev/null and b/mods/xdecor/textures/rook_white.png differ diff --git a/mods/xdecor/textures/worktable_anvil.png b/mods/xdecor/textures/worktable_anvil.png new file mode 100644 index 0000000..afca15e Binary files /dev/null and b/mods/xdecor/textures/worktable_anvil.png differ diff --git a/mods/xdecor/textures/worktable_saw.png b/mods/xdecor/textures/worktable_saw.png new file mode 100644 index 0000000..73246ca Binary files /dev/null and b/mods/xdecor/textures/worktable_saw.png differ diff --git a/mods/xdecor/textures/xdecor_bamboo_frame.png b/mods/xdecor/textures/xdecor_bamboo_frame.png new file mode 100644 index 0000000..6a0d863 Binary files /dev/null and b/mods/xdecor/textures/xdecor_bamboo_frame.png differ diff --git a/mods/xdecor/textures/xdecor_baricade.png b/mods/xdecor/textures/xdecor_baricade.png new file mode 100644 index 0000000..87109bb Binary files /dev/null and b/mods/xdecor/textures/xdecor_baricade.png differ diff --git a/mods/xdecor/textures/xdecor_barrel_sides.png b/mods/xdecor/textures/xdecor_barrel_sides.png new file mode 100644 index 0000000..4172b81 Binary files /dev/null and b/mods/xdecor/textures/xdecor_barrel_sides.png differ diff --git a/mods/xdecor/textures/xdecor_barrel_top.png b/mods/xdecor/textures/xdecor_barrel_top.png new file mode 100644 index 0000000..014b00a Binary files /dev/null and b/mods/xdecor/textures/xdecor_barrel_top.png differ diff --git a/mods/xdecor/textures/xdecor_book_open.png b/mods/xdecor/textures/xdecor_book_open.png new file mode 100644 index 0000000..206b11c Binary files /dev/null and b/mods/xdecor/textures/xdecor_book_open.png differ diff --git a/mods/xdecor/textures/xdecor_bowl.png b/mods/xdecor/textures/xdecor_bowl.png new file mode 100644 index 0000000..9197da9 Binary files /dev/null and b/mods/xdecor/textures/xdecor_bowl.png differ diff --git a/mods/xdecor/textures/xdecor_bowl_soup.png b/mods/xdecor/textures/xdecor_bowl_soup.png new file mode 100644 index 0000000..54d87ae Binary files /dev/null and b/mods/xdecor/textures/xdecor_bowl_soup.png differ diff --git a/mods/xdecor/textures/xdecor_cabinet_front.png b/mods/xdecor/textures/xdecor_cabinet_front.png new file mode 100644 index 0000000..6380968 Binary files /dev/null and b/mods/xdecor/textures/xdecor_cabinet_front.png differ diff --git a/mods/xdecor/textures/xdecor_cabinet_sides.png b/mods/xdecor/textures/xdecor_cabinet_sides.png new file mode 100644 index 0000000..32ab257 Binary files /dev/null and b/mods/xdecor/textures/xdecor_cabinet_sides.png differ diff --git a/mods/xdecor/textures/xdecor_cactusbrick.png b/mods/xdecor/textures/xdecor_cactusbrick.png new file mode 100644 index 0000000..4856f09 Binary files /dev/null and b/mods/xdecor/textures/xdecor_cactusbrick.png differ diff --git a/mods/xdecor/textures/xdecor_candle_floor.png b/mods/xdecor/textures/xdecor_candle_floor.png new file mode 100644 index 0000000..c1bc4e3 Binary files /dev/null and b/mods/xdecor/textures/xdecor_candle_floor.png differ diff --git a/mods/xdecor/textures/xdecor_candle_hanging.png b/mods/xdecor/textures/xdecor_candle_hanging.png new file mode 100644 index 0000000..b8595a7 Binary files /dev/null and b/mods/xdecor/textures/xdecor_candle_hanging.png differ diff --git a/mods/xdecor/textures/xdecor_candle_inv.png b/mods/xdecor/textures/xdecor_candle_inv.png new file mode 100644 index 0000000..90a479e Binary files /dev/null and b/mods/xdecor/textures/xdecor_candle_inv.png differ diff --git a/mods/xdecor/textures/xdecor_candle_wall.png b/mods/xdecor/textures/xdecor_candle_wall.png new file mode 100644 index 0000000..b8a4b50 Binary files /dev/null and b/mods/xdecor/textures/xdecor_candle_wall.png differ diff --git a/mods/xdecor/textures/xdecor_candle_wield.png b/mods/xdecor/textures/xdecor_candle_wield.png new file mode 100644 index 0000000..60bdede Binary files /dev/null and b/mods/xdecor/textures/xdecor_candle_wield.png differ diff --git a/mods/xdecor/textures/xdecor_cauldron_sides.png b/mods/xdecor/textures/xdecor_cauldron_sides.png new file mode 100644 index 0000000..6644edb Binary files /dev/null and b/mods/xdecor/textures/xdecor_cauldron_sides.png differ diff --git a/mods/xdecor/textures/xdecor_cauldron_top_anim_boiling_water.png b/mods/xdecor/textures/xdecor_cauldron_top_anim_boiling_water.png new file mode 100644 index 0000000..48584d5 Binary files /dev/null and b/mods/xdecor/textures/xdecor_cauldron_top_anim_boiling_water.png differ diff --git a/mods/xdecor/textures/xdecor_cauldron_top_anim_soup.png b/mods/xdecor/textures/xdecor_cauldron_top_anim_soup.png new file mode 100644 index 0000000..f6d5258 Binary files /dev/null and b/mods/xdecor/textures/xdecor_cauldron_top_anim_soup.png differ diff --git a/mods/xdecor/textures/xdecor_cauldron_top_empty.png b/mods/xdecor/textures/xdecor_cauldron_top_empty.png new file mode 100644 index 0000000..5cdf5fd Binary files /dev/null and b/mods/xdecor/textures/xdecor_cauldron_top_empty.png differ diff --git a/mods/xdecor/textures/xdecor_cauldron_top_idle.png b/mods/xdecor/textures/xdecor_cauldron_top_idle.png new file mode 100644 index 0000000..69ec2ab Binary files /dev/null and b/mods/xdecor/textures/xdecor_cauldron_top_idle.png differ diff --git a/mods/xdecor/textures/xdecor_chainlink.png b/mods/xdecor/textures/xdecor_chainlink.png new file mode 100644 index 0000000..1aba3c0 Binary files /dev/null and b/mods/xdecor/textures/xdecor_chainlink.png differ diff --git a/mods/xdecor/textures/xdecor_coalstone_tile.png b/mods/xdecor/textures/xdecor_coalstone_tile.png new file mode 100644 index 0000000..3122db0 Binary files /dev/null and b/mods/xdecor/textures/xdecor_coalstone_tile.png differ diff --git a/mods/xdecor/textures/xdecor_cobweb.png b/mods/xdecor/textures/xdecor_cobweb.png new file mode 100644 index 0000000..bb1ecea Binary files /dev/null and b/mods/xdecor/textures/xdecor_cobweb.png differ diff --git a/mods/xdecor/textures/xdecor_curtain_open_overlay.png b/mods/xdecor/textures/xdecor_curtain_open_overlay.png new file mode 100644 index 0000000..e6eea41 Binary files /dev/null and b/mods/xdecor/textures/xdecor_curtain_open_overlay.png differ diff --git a/mods/xdecor/textures/xdecor_cushion.png b/mods/xdecor/textures/xdecor_cushion.png new file mode 100644 index 0000000..ad4674c Binary files /dev/null and b/mods/xdecor/textures/xdecor_cushion.png differ diff --git a/mods/xdecor/textures/xdecor_dandelion_white_pot.png b/mods/xdecor/textures/xdecor_dandelion_white_pot.png new file mode 100644 index 0000000..ccb91ee Binary files /dev/null and b/mods/xdecor/textures/xdecor_dandelion_white_pot.png differ diff --git a/mods/xdecor/textures/xdecor_dandelion_yellow_pot.png b/mods/xdecor/textures/xdecor_dandelion_yellow_pot.png new file mode 100644 index 0000000..f303475 Binary files /dev/null and b/mods/xdecor/textures/xdecor_dandelion_yellow_pot.png differ diff --git a/mods/xdecor/textures/xdecor_desertstone_tile.png b/mods/xdecor/textures/xdecor_desertstone_tile.png new file mode 100644 index 0000000..094437f Binary files /dev/null and b/mods/xdecor/textures/xdecor_desertstone_tile.png differ diff --git a/mods/xdecor/textures/xdecor_empty_shelf.png b/mods/xdecor/textures/xdecor_empty_shelf.png new file mode 100644 index 0000000..a8363c0 Binary files /dev/null and b/mods/xdecor/textures/xdecor_empty_shelf.png differ diff --git a/mods/xdecor/textures/xdecor_enchantment_bottom.png b/mods/xdecor/textures/xdecor_enchantment_bottom.png new file mode 100644 index 0000000..65a8639 Binary files /dev/null and b/mods/xdecor/textures/xdecor_enchantment_bottom.png differ diff --git a/mods/xdecor/textures/xdecor_enchantment_side.png b/mods/xdecor/textures/xdecor_enchantment_side.png new file mode 100644 index 0000000..9bbd5a2 Binary files /dev/null and b/mods/xdecor/textures/xdecor_enchantment_side.png differ diff --git a/mods/xdecor/textures/xdecor_enchantment_top.png b/mods/xdecor/textures/xdecor_enchantment_top.png new file mode 100644 index 0000000..cc79b35 Binary files /dev/null and b/mods/xdecor/textures/xdecor_enchantment_top.png differ diff --git a/mods/xdecor/textures/xdecor_enderchest_front.png b/mods/xdecor/textures/xdecor_enderchest_front.png new file mode 100644 index 0000000..e7286ce Binary files /dev/null and b/mods/xdecor/textures/xdecor_enderchest_front.png differ diff --git a/mods/xdecor/textures/xdecor_enderchest_side.png b/mods/xdecor/textures/xdecor_enderchest_side.png new file mode 100644 index 0000000..4691247 Binary files /dev/null and b/mods/xdecor/textures/xdecor_enderchest_side.png differ diff --git a/mods/xdecor/textures/xdecor_enderchest_top.png b/mods/xdecor/textures/xdecor_enderchest_top.png new file mode 100644 index 0000000..1f6676c Binary files /dev/null and b/mods/xdecor/textures/xdecor_enderchest_top.png differ diff --git a/mods/xdecor/textures/xdecor_geranium_pot.png b/mods/xdecor/textures/xdecor_geranium_pot.png new file mode 100644 index 0000000..0a68204 Binary files /dev/null and b/mods/xdecor/textures/xdecor_geranium_pot.png differ diff --git a/mods/xdecor/textures/xdecor_glyph1.png b/mods/xdecor/textures/xdecor_glyph1.png new file mode 100644 index 0000000..645abac Binary files /dev/null and b/mods/xdecor/textures/xdecor_glyph1.png differ diff --git a/mods/xdecor/textures/xdecor_glyph10.png b/mods/xdecor/textures/xdecor_glyph10.png new file mode 100644 index 0000000..06bd074 Binary files /dev/null and b/mods/xdecor/textures/xdecor_glyph10.png differ diff --git a/mods/xdecor/textures/xdecor_glyph11.png b/mods/xdecor/textures/xdecor_glyph11.png new file mode 100644 index 0000000..532d25c Binary files /dev/null and b/mods/xdecor/textures/xdecor_glyph11.png differ diff --git a/mods/xdecor/textures/xdecor_glyph12.png b/mods/xdecor/textures/xdecor_glyph12.png new file mode 100644 index 0000000..1f6be21 Binary files /dev/null and b/mods/xdecor/textures/xdecor_glyph12.png differ diff --git a/mods/xdecor/textures/xdecor_glyph13.png b/mods/xdecor/textures/xdecor_glyph13.png new file mode 100644 index 0000000..4678f7f Binary files /dev/null and b/mods/xdecor/textures/xdecor_glyph13.png differ diff --git a/mods/xdecor/textures/xdecor_glyph14.png b/mods/xdecor/textures/xdecor_glyph14.png new file mode 100644 index 0000000..bf095bb Binary files /dev/null and b/mods/xdecor/textures/xdecor_glyph14.png differ diff --git a/mods/xdecor/textures/xdecor_glyph15.png b/mods/xdecor/textures/xdecor_glyph15.png new file mode 100644 index 0000000..27199bb Binary files /dev/null and b/mods/xdecor/textures/xdecor_glyph15.png differ diff --git a/mods/xdecor/textures/xdecor_glyph16.png b/mods/xdecor/textures/xdecor_glyph16.png new file mode 100644 index 0000000..27e1807 Binary files /dev/null and b/mods/xdecor/textures/xdecor_glyph16.png differ diff --git a/mods/xdecor/textures/xdecor_glyph17.png b/mods/xdecor/textures/xdecor_glyph17.png new file mode 100644 index 0000000..7ed2bd4 Binary files /dev/null and b/mods/xdecor/textures/xdecor_glyph17.png differ diff --git a/mods/xdecor/textures/xdecor_glyph18.png b/mods/xdecor/textures/xdecor_glyph18.png new file mode 100644 index 0000000..f03b73a Binary files /dev/null and b/mods/xdecor/textures/xdecor_glyph18.png differ diff --git a/mods/xdecor/textures/xdecor_glyph2.png b/mods/xdecor/textures/xdecor_glyph2.png new file mode 100644 index 0000000..81b2061 Binary files /dev/null and b/mods/xdecor/textures/xdecor_glyph2.png differ diff --git a/mods/xdecor/textures/xdecor_glyph3.png b/mods/xdecor/textures/xdecor_glyph3.png new file mode 100644 index 0000000..24b8cf4 Binary files /dev/null and b/mods/xdecor/textures/xdecor_glyph3.png differ diff --git a/mods/xdecor/textures/xdecor_glyph4.png b/mods/xdecor/textures/xdecor_glyph4.png new file mode 100644 index 0000000..dc1909b Binary files /dev/null and b/mods/xdecor/textures/xdecor_glyph4.png differ diff --git a/mods/xdecor/textures/xdecor_glyph5.png b/mods/xdecor/textures/xdecor_glyph5.png new file mode 100644 index 0000000..1473ea4 Binary files /dev/null and b/mods/xdecor/textures/xdecor_glyph5.png differ diff --git a/mods/xdecor/textures/xdecor_glyph6.png b/mods/xdecor/textures/xdecor_glyph6.png new file mode 100644 index 0000000..45c0c9a Binary files /dev/null and b/mods/xdecor/textures/xdecor_glyph6.png differ diff --git a/mods/xdecor/textures/xdecor_glyph7.png b/mods/xdecor/textures/xdecor_glyph7.png new file mode 100644 index 0000000..5708623 Binary files /dev/null and b/mods/xdecor/textures/xdecor_glyph7.png differ diff --git a/mods/xdecor/textures/xdecor_glyph8.png b/mods/xdecor/textures/xdecor_glyph8.png new file mode 100644 index 0000000..c5ae1c3 Binary files /dev/null and b/mods/xdecor/textures/xdecor_glyph8.png differ diff --git a/mods/xdecor/textures/xdecor_glyph9.png b/mods/xdecor/textures/xdecor_glyph9.png new file mode 100644 index 0000000..148b03d Binary files /dev/null and b/mods/xdecor/textures/xdecor_glyph9.png differ diff --git a/mods/xdecor/textures/xdecor_half_cabinet_front.png b/mods/xdecor/textures/xdecor_half_cabinet_front.png new file mode 100644 index 0000000..ea9c389 Binary files /dev/null and b/mods/xdecor/textures/xdecor_half_cabinet_front.png differ diff --git a/mods/xdecor/textures/xdecor_half_cabinet_sides.png b/mods/xdecor/textures/xdecor_half_cabinet_sides.png new file mode 100644 index 0000000..6f274b8 Binary files /dev/null and b/mods/xdecor/textures/xdecor_half_cabinet_sides.png differ diff --git a/mods/xdecor/textures/xdecor_hammer.png b/mods/xdecor/textures/xdecor_hammer.png new file mode 100644 index 0000000..17b9856 Binary files /dev/null and b/mods/xdecor/textures/xdecor_hammer.png differ diff --git a/mods/xdecor/textures/xdecor_hard_clay.png b/mods/xdecor/textures/xdecor_hard_clay.png new file mode 100644 index 0000000..8abe666 Binary files /dev/null and b/mods/xdecor/textures/xdecor_hard_clay.png differ diff --git a/mods/xdecor/textures/xdecor_hive_front.png b/mods/xdecor/textures/xdecor_hive_front.png new file mode 100644 index 0000000..4515551 Binary files /dev/null and b/mods/xdecor/textures/xdecor_hive_front.png differ diff --git a/mods/xdecor/textures/xdecor_hive_side.png b/mods/xdecor/textures/xdecor_hive_side.png new file mode 100644 index 0000000..7fd26ad Binary files /dev/null and b/mods/xdecor/textures/xdecor_hive_side.png differ diff --git a/mods/xdecor/textures/xdecor_hive_top.png b/mods/xdecor/textures/xdecor_hive_top.png new file mode 100644 index 0000000..43203e1 Binary files /dev/null and b/mods/xdecor/textures/xdecor_hive_top.png differ diff --git a/mods/xdecor/textures/xdecor_honey.png b/mods/xdecor/textures/xdecor_honey.png new file mode 100644 index 0000000..04c404c Binary files /dev/null and b/mods/xdecor/textures/xdecor_honey.png differ diff --git a/mods/xdecor/textures/xdecor_iron_lightbox.png b/mods/xdecor/textures/xdecor_iron_lightbox.png new file mode 100644 index 0000000..45146f9 Binary files /dev/null and b/mods/xdecor/textures/xdecor_iron_lightbox.png differ diff --git a/mods/xdecor/textures/xdecor_itemframe.png b/mods/xdecor/textures/xdecor_itemframe.png new file mode 100644 index 0000000..088ba15 Binary files /dev/null and b/mods/xdecor/textures/xdecor_itemframe.png differ diff --git a/mods/xdecor/textures/xdecor_ivy.png b/mods/xdecor/textures/xdecor_ivy.png new file mode 100644 index 0000000..b85e112 Binary files /dev/null and b/mods/xdecor/textures/xdecor_ivy.png differ diff --git a/mods/xdecor/textures/xdecor_japanese_door.png b/mods/xdecor/textures/xdecor_japanese_door.png new file mode 100644 index 0000000..35f77ec Binary files /dev/null and b/mods/xdecor/textures/xdecor_japanese_door.png differ diff --git a/mods/xdecor/textures/xdecor_japanese_door_inv.png b/mods/xdecor/textures/xdecor_japanese_door_inv.png new file mode 100644 index 0000000..4d3ec64 Binary files /dev/null and b/mods/xdecor/textures/xdecor_japanese_door_inv.png differ diff --git a/mods/xdecor/textures/xdecor_lantern.png b/mods/xdecor/textures/xdecor_lantern.png new file mode 100644 index 0000000..18c9ce2 Binary files /dev/null and b/mods/xdecor/textures/xdecor_lantern.png differ diff --git a/mods/xdecor/textures/xdecor_lantern_inv.png b/mods/xdecor/textures/xdecor_lantern_inv.png new file mode 100644 index 0000000..71cef66 Binary files /dev/null and b/mods/xdecor/textures/xdecor_lantern_inv.png differ diff --git a/mods/xdecor/textures/xdecor_lever_off.png b/mods/xdecor/textures/xdecor_lever_off.png new file mode 100644 index 0000000..6d8bb49 Binary files /dev/null and b/mods/xdecor/textures/xdecor_lever_off.png differ diff --git a/mods/xdecor/textures/xdecor_lever_on.png b/mods/xdecor/textures/xdecor_lever_on.png new file mode 100644 index 0000000..c64d27f Binary files /dev/null and b/mods/xdecor/textures/xdecor_lever_on.png differ diff --git a/mods/xdecor/textures/xdecor_mailbox.png b/mods/xdecor/textures/xdecor_mailbox.png new file mode 100644 index 0000000..8289884 Binary files /dev/null and b/mods/xdecor/textures/xdecor_mailbox.png differ diff --git a/mods/xdecor/textures/xdecor_mailbox_bottom.png b/mods/xdecor/textures/xdecor_mailbox_bottom.png new file mode 100644 index 0000000..b613863 Binary files /dev/null and b/mods/xdecor/textures/xdecor_mailbox_bottom.png differ diff --git a/mods/xdecor/textures/xdecor_mailbox_side.png b/mods/xdecor/textures/xdecor_mailbox_side.png new file mode 100644 index 0000000..44b2a2f Binary files /dev/null and b/mods/xdecor/textures/xdecor_mailbox_side.png differ diff --git a/mods/xdecor/textures/xdecor_mailbox_top.png b/mods/xdecor/textures/xdecor_mailbox_top.png new file mode 100644 index 0000000..3584c53 Binary files /dev/null and b/mods/xdecor/textures/xdecor_mailbox_top.png differ diff --git a/mods/xdecor/textures/xdecor_moonbrick.png b/mods/xdecor/textures/xdecor_moonbrick.png new file mode 100644 index 0000000..efdac14 Binary files /dev/null and b/mods/xdecor/textures/xdecor_moonbrick.png differ diff --git a/mods/xdecor/textures/xdecor_multishelf.png b/mods/xdecor/textures/xdecor_multishelf.png new file mode 100644 index 0000000..0a5e10e Binary files /dev/null and b/mods/xdecor/textures/xdecor_multishelf.png differ diff --git a/mods/xdecor/textures/xdecor_packed_ice.png b/mods/xdecor/textures/xdecor_packed_ice.png new file mode 100644 index 0000000..8c44eaf Binary files /dev/null and b/mods/xdecor/textures/xdecor_packed_ice.png differ diff --git a/mods/xdecor/textures/xdecor_painting_1.png b/mods/xdecor/textures/xdecor_painting_1.png new file mode 100644 index 0000000..7609c2b Binary files /dev/null and b/mods/xdecor/textures/xdecor_painting_1.png differ diff --git a/mods/xdecor/textures/xdecor_painting_2.png b/mods/xdecor/textures/xdecor_painting_2.png new file mode 100644 index 0000000..8a9cf4a Binary files /dev/null and b/mods/xdecor/textures/xdecor_painting_2.png differ diff --git a/mods/xdecor/textures/xdecor_painting_3.png b/mods/xdecor/textures/xdecor_painting_3.png new file mode 100644 index 0000000..d094d3d Binary files /dev/null and b/mods/xdecor/textures/xdecor_painting_3.png differ diff --git a/mods/xdecor/textures/xdecor_painting_4.png b/mods/xdecor/textures/xdecor_painting_4.png new file mode 100644 index 0000000..5ccb141 Binary files /dev/null and b/mods/xdecor/textures/xdecor_painting_4.png differ diff --git a/mods/xdecor/textures/xdecor_painting_empty.png b/mods/xdecor/textures/xdecor_painting_empty.png new file mode 100644 index 0000000..216429a Binary files /dev/null and b/mods/xdecor/textures/xdecor_painting_empty.png differ diff --git a/mods/xdecor/textures/xdecor_pressure_stone.png b/mods/xdecor/textures/xdecor_pressure_stone.png new file mode 100644 index 0000000..faf3ae0 Binary files /dev/null and b/mods/xdecor/textures/xdecor_pressure_stone.png differ diff --git a/mods/xdecor/textures/xdecor_pressure_wood.png b/mods/xdecor/textures/xdecor_pressure_wood.png new file mode 100644 index 0000000..504113a Binary files /dev/null and b/mods/xdecor/textures/xdecor_pressure_wood.png differ diff --git a/mods/xdecor/textures/xdecor_prison_door.png b/mods/xdecor/textures/xdecor_prison_door.png new file mode 100644 index 0000000..2f7e66f Binary files /dev/null and b/mods/xdecor/textures/xdecor_prison_door.png differ diff --git a/mods/xdecor/textures/xdecor_prison_door_inv.png b/mods/xdecor/textures/xdecor_prison_door_inv.png new file mode 100644 index 0000000..0751caf Binary files /dev/null and b/mods/xdecor/textures/xdecor_prison_door_inv.png differ diff --git a/mods/xdecor/textures/xdecor_radio_back.png b/mods/xdecor/textures/xdecor_radio_back.png new file mode 100644 index 0000000..35ee768 Binary files /dev/null and b/mods/xdecor/textures/xdecor_radio_back.png differ diff --git a/mods/xdecor/textures/xdecor_radio_front.png b/mods/xdecor/textures/xdecor_radio_front.png new file mode 100644 index 0000000..6300aa8 Binary files /dev/null and b/mods/xdecor/textures/xdecor_radio_front.png differ diff --git a/mods/xdecor/textures/xdecor_radio_side.png b/mods/xdecor/textures/xdecor_radio_side.png new file mode 100644 index 0000000..cf60740 Binary files /dev/null and b/mods/xdecor/textures/xdecor_radio_side.png differ diff --git a/mods/xdecor/textures/xdecor_radio_top.png b/mods/xdecor/textures/xdecor_radio_top.png new file mode 100644 index 0000000..fe5f88a Binary files /dev/null and b/mods/xdecor/textures/xdecor_radio_top.png differ diff --git a/mods/xdecor/textures/xdecor_rooster.png b/mods/xdecor/textures/xdecor_rooster.png new file mode 100644 index 0000000..b68a173 Binary files /dev/null and b/mods/xdecor/textures/xdecor_rooster.png differ diff --git a/mods/xdecor/textures/xdecor_rope.png b/mods/xdecor/textures/xdecor_rope.png new file mode 100644 index 0000000..bcfaba2 Binary files /dev/null and b/mods/xdecor/textures/xdecor_rope.png differ diff --git a/mods/xdecor/textures/xdecor_rope_inv.png b/mods/xdecor/textures/xdecor_rope_inv.png new file mode 100644 index 0000000..51a24a8 Binary files /dev/null and b/mods/xdecor/textures/xdecor_rope_inv.png differ diff --git a/mods/xdecor/textures/xdecor_rope_wield.png b/mods/xdecor/textures/xdecor_rope_wield.png new file mode 100644 index 0000000..3ca8fef Binary files /dev/null and b/mods/xdecor/textures/xdecor_rope_wield.png differ diff --git a/mods/xdecor/textures/xdecor_rose_pot.png b/mods/xdecor/textures/xdecor_rose_pot.png new file mode 100644 index 0000000..12923ac Binary files /dev/null and b/mods/xdecor/textures/xdecor_rose_pot.png differ diff --git a/mods/xdecor/textures/xdecor_rusty_bar.png b/mods/xdecor/textures/xdecor_rusty_bar.png new file mode 100644 index 0000000..d2d5866 Binary files /dev/null and b/mods/xdecor/textures/xdecor_rusty_bar.png differ diff --git a/mods/xdecor/textures/xdecor_rusty_prison_door.png b/mods/xdecor/textures/xdecor_rusty_prison_door.png new file mode 100644 index 0000000..3b1dd1a Binary files /dev/null and b/mods/xdecor/textures/xdecor_rusty_prison_door.png differ diff --git a/mods/xdecor/textures/xdecor_rusty_prison_door_inv.png b/mods/xdecor/textures/xdecor_rusty_prison_door_inv.png new file mode 100644 index 0000000..486486b Binary files /dev/null and b/mods/xdecor/textures/xdecor_rusty_prison_door_inv.png differ diff --git a/mods/xdecor/textures/xdecor_screen_door.png b/mods/xdecor/textures/xdecor_screen_door.png new file mode 100644 index 0000000..a00ebb3 Binary files /dev/null and b/mods/xdecor/textures/xdecor_screen_door.png differ diff --git a/mods/xdecor/textures/xdecor_screen_door_inv.png b/mods/xdecor/textures/xdecor_screen_door_inv.png new file mode 100644 index 0000000..6c9633e Binary files /dev/null and b/mods/xdecor/textures/xdecor_screen_door_inv.png differ diff --git a/mods/xdecor/textures/xdecor_slide_door.png b/mods/xdecor/textures/xdecor_slide_door.png new file mode 100644 index 0000000..1810ccd Binary files /dev/null and b/mods/xdecor/textures/xdecor_slide_door.png differ diff --git a/mods/xdecor/textures/xdecor_slide_door_inv.png b/mods/xdecor/textures/xdecor_slide_door_inv.png new file mode 100644 index 0000000..4ea2154 Binary files /dev/null and b/mods/xdecor/textures/xdecor_slide_door_inv.png differ diff --git a/mods/xdecor/textures/xdecor_speaker_back.png b/mods/xdecor/textures/xdecor_speaker_back.png new file mode 100644 index 0000000..7b28936 Binary files /dev/null and b/mods/xdecor/textures/xdecor_speaker_back.png differ diff --git a/mods/xdecor/textures/xdecor_speaker_front.png b/mods/xdecor/textures/xdecor_speaker_front.png new file mode 100644 index 0000000..b19b835 Binary files /dev/null and b/mods/xdecor/textures/xdecor_speaker_front.png differ diff --git a/mods/xdecor/textures/xdecor_speaker_side.png b/mods/xdecor/textures/xdecor_speaker_side.png new file mode 100644 index 0000000..7b28936 Binary files /dev/null and b/mods/xdecor/textures/xdecor_speaker_side.png differ diff --git a/mods/xdecor/textures/xdecor_speaker_top.png b/mods/xdecor/textures/xdecor_speaker_top.png new file mode 100644 index 0000000..b45f3f1 Binary files /dev/null and b/mods/xdecor/textures/xdecor_speaker_top.png differ diff --git a/mods/xdecor/textures/xdecor_stone_rune.png b/mods/xdecor/textures/xdecor_stone_rune.png new file mode 100644 index 0000000..319a2df Binary files /dev/null and b/mods/xdecor/textures/xdecor_stone_rune.png differ diff --git a/mods/xdecor/textures/xdecor_stone_tile.png b/mods/xdecor/textures/xdecor_stone_tile.png new file mode 100644 index 0000000..4346783 Binary files /dev/null and b/mods/xdecor/textures/xdecor_stone_tile.png differ diff --git a/mods/xdecor/textures/xdecor_tatami.png b/mods/xdecor/textures/xdecor_tatami.png new file mode 100644 index 0000000..e1998f7 Binary files /dev/null and b/mods/xdecor/textures/xdecor_tatami.png differ diff --git a/mods/xdecor/textures/xdecor_television_back.png b/mods/xdecor/textures/xdecor_television_back.png new file mode 100644 index 0000000..761b1c7 Binary files /dev/null and b/mods/xdecor/textures/xdecor_television_back.png differ diff --git a/mods/xdecor/textures/xdecor_television_front_animated.png b/mods/xdecor/textures/xdecor_television_front_animated.png new file mode 100644 index 0000000..ae5df4f Binary files /dev/null and b/mods/xdecor/textures/xdecor_television_front_animated.png differ diff --git a/mods/xdecor/textures/xdecor_television_left.png b/mods/xdecor/textures/xdecor_television_left.png new file mode 100644 index 0000000..65444fb Binary files /dev/null and b/mods/xdecor/textures/xdecor_television_left.png differ diff --git a/mods/xdecor/textures/xdecor_trampoline.png b/mods/xdecor/textures/xdecor_trampoline.png new file mode 100644 index 0000000..a8536c2 Binary files /dev/null and b/mods/xdecor/textures/xdecor_trampoline.png differ diff --git a/mods/xdecor/textures/xdecor_trampoline_sides.png b/mods/xdecor/textures/xdecor_trampoline_sides.png new file mode 100644 index 0000000..497a86a Binary files /dev/null and b/mods/xdecor/textures/xdecor_trampoline_sides.png differ diff --git a/mods/xdecor/textures/xdecor_tulip_pot.png b/mods/xdecor/textures/xdecor_tulip_pot.png new file mode 100644 index 0000000..d339ef6 Binary files /dev/null and b/mods/xdecor/textures/xdecor_tulip_pot.png differ diff --git a/mods/xdecor/textures/xdecor_viola_pot.png b/mods/xdecor/textures/xdecor_viola_pot.png new file mode 100644 index 0000000..7549c4c Binary files /dev/null and b/mods/xdecor/textures/xdecor_viola_pot.png differ diff --git a/mods/xdecor/textures/xdecor_wood.png b/mods/xdecor/textures/xdecor_wood.png new file mode 100644 index 0000000..426e5bf Binary files /dev/null and b/mods/xdecor/textures/xdecor_wood.png differ diff --git a/mods/xdecor/textures/xdecor_wood_frame.png b/mods/xdecor/textures/xdecor_wood_frame.png new file mode 100644 index 0000000..f528f5a Binary files /dev/null and b/mods/xdecor/textures/xdecor_wood_frame.png differ diff --git a/mods/xdecor/textures/xdecor_wood_tile.png b/mods/xdecor/textures/xdecor_wood_tile.png new file mode 100644 index 0000000..272df2c Binary files /dev/null and b/mods/xdecor/textures/xdecor_wood_tile.png differ diff --git a/mods/xdecor/textures/xdecor_wooden2_lightbox.png b/mods/xdecor/textures/xdecor_wooden2_lightbox.png new file mode 100644 index 0000000..a53ad96 Binary files /dev/null and b/mods/xdecor/textures/xdecor_wooden2_lightbox.png differ diff --git a/mods/xdecor/textures/xdecor_wooden_lightbox.png b/mods/xdecor/textures/xdecor_wooden_lightbox.png new file mode 100644 index 0000000..c5a6b52 Binary files /dev/null and b/mods/xdecor/textures/xdecor_wooden_lightbox.png differ diff --git a/mods/xdecor/textures/xdecor_woodframed_glass.png b/mods/xdecor/textures/xdecor_woodframed_glass.png new file mode 100644 index 0000000..9fd6ea8 Binary files /dev/null and b/mods/xdecor/textures/xdecor_woodframed_glass.png differ diff --git a/mods/xdecor/textures/xdecor_woodframed_glass_detail.png b/mods/xdecor/textures/xdecor_woodframed_glass_detail.png new file mode 100644 index 0000000..9b5d141 Binary files /dev/null and b/mods/xdecor/textures/xdecor_woodframed_glass_detail.png differ diff --git a/mods/xdecor/textures/xdecor_woodglass_door.png b/mods/xdecor/textures/xdecor_woodglass_door.png new file mode 100644 index 0000000..51209e2 Binary files /dev/null and b/mods/xdecor/textures/xdecor_woodglass_door.png differ diff --git a/mods/xdecor/textures/xdecor_woodglass_door_inv.png b/mods/xdecor/textures/xdecor_woodglass_door_inv.png new file mode 100644 index 0000000..e5b3293 Binary files /dev/null and b/mods/xdecor/textures/xdecor_woodglass_door_inv.png differ diff --git a/mods/xdecor/textures/xdecor_workbench_front.png b/mods/xdecor/textures/xdecor_workbench_front.png new file mode 100644 index 0000000..3ef7236 Binary files /dev/null and b/mods/xdecor/textures/xdecor_workbench_front.png differ diff --git a/mods/xdecor/textures/xdecor_workbench_sides.png b/mods/xdecor/textures/xdecor_workbench_sides.png new file mode 100644 index 0000000..24521ad Binary files /dev/null and b/mods/xdecor/textures/xdecor_workbench_sides.png differ diff --git a/mods/xdecor/textures/xdecor_workbench_top.png b/mods/xdecor/textures/xdecor_workbench_top.png new file mode 100644 index 0000000..852a83d Binary files /dev/null and b/mods/xdecor/textures/xdecor_workbench_top.png differ