From e9c446c42cb45b87c975c75b9a7911197e7f6094 Mon Sep 17 00:00:00 2001 From: Jaidyn Ann Date: Sun, 2 Sep 2018 14:53:31 +0000 Subject: [PATCH] Init --- mods/default/mapgen.lua | 4 +- .../default_torch_on_ceiling_animated.png | Bin 916 -> 586 bytes .../textures/default_torch_on_floor.png | Bin 214 -> 206 bytes .../default_torch_on_floor_animated.png | Bin 830 -> 540 bytes mods/default/trees.lua | 16 +- mods/fishing/bobber.lua | 299 ++++ mods/fishing/crafting.lua | 69 + mods/fishing/depends.txt | 2 + mods/fishing/fishes.lua | 30 + mods/fishing/init.lua | 309 ++++ mods/fishing/settings.txt | 8 + mods/fishing/sounds/SoundLicense.txt | 4 + mods/fishing/sounds/fishing_bobber1.ogg | Bin 0 -> 15470 bytes mods/fishing/sounds/fishing_bobber2.ogg | Bin 0 -> 19963 bytes .../textures/alternates/fishing_bobber.png | Bin 0 -> 217 bytes .../textures/alternates/fishing_pole.png | Bin 0 -> 295 bytes mods/fishing/textures/fishing_bobber.png | Bin 0 -> 238 bytes .../fishing/textures/fishing_bobber_ready.png | Bin 0 -> 222 bytes mods/fishing/textures/fishing_fish.png | Bin 0 -> 196 bytes mods/fishing/textures/fishing_fish_cooked.png | Bin 0 -> 209 bytes mods/fishing/textures/fishing_pole.png | Bin 0 -> 206 bytes mods/fishing/textures/fishing_pole_back.png | Bin 0 -> 142 bytes mods/fishing/textures/fishing_pole_bottom.png | Bin 0 -> 181 bytes mods/fishing/textures/fishing_pole_deco.png | Bin 0 -> 354 bytes mods/fishing/textures/fishing_pole_front.png | Bin 0 -> 180 bytes mods/fishing/textures/fishing_pole_on_use.png | Bin 0 -> 151 bytes mods/fishing/textures/fishing_pole_simple.png | Bin 0 -> 303 bytes mods/fishing/textures/fishing_pole_top.png | Bin 0 -> 142 bytes mods/fishing/textures/fishing_sushi.png | Bin 0 -> 590 bytes mods/fishing/textures/fishing_worm.png | Bin 0 -> 203 bytes .../textures/old/fishing_pole_wield.png | Bin 0 -> 269 bytes mods/fishing/worm.lua | 118 ++ mods/irc/.gitignore | 2 + mods/irc/.gitmodules | 3 + mods/irc/.luacheckrc | 14 + mods/irc/API.md | 90 + mods/irc/LICENSE.txt | 22 + mods/irc/README.md | 181 ++ mods/irc/botcmds.lua | 175 ++ mods/irc/callback.lua | 41 + mods/irc/chatcmds.lua | 134 ++ mods/irc/config.lua | 56 + mods/irc/description.txt | 4 + mods/irc/hooks.lua | 258 +++ mods/irc/init.lua | 218 +++ mods/irc/irc/LICENSE.txt | 26 + mods/irc/irc/README.markdown | 19 + mods/irc/irc/asyncoperations.lua | 92 + mods/irc/irc/doc/irc.luadoc | 198 ++ mods/irc/irc/handlers.lua | 277 +++ mods/irc/irc/init.lua | 257 +++ mods/irc/irc/messages.lua | 207 +++ mods/irc/irc/push-luadoc.sh | 19 + mods/irc/irc/set.lua | 52 + mods/irc/irc/util.lua | 120 ++ mods/irc/messages.lua | 17 + mods/irc/mod.conf | 1 + mods/irc/player_part.lua | 69 + mods/irc/settingtypes.txt | 75 + mods/point/init.lua | 26 + mods/poudlard/aliases.lua | 224 +++ mods/poudlard/depends.txt | 3 + mods/poudlard/init.lua | 1589 +++++++++++++++++ mods/poudlard/locale/es.txt | 194 ++ mods/poudlard/locale/fr.txt | 180 ++ mods/poudlard/locale/pt.txt | 198 ++ mods/poudlard/locale/template.txt | 198 ++ mods/poudlard/nodes.lua | 354 ++++ mods/poudlard/poudecor/LICENSE | 699 ++++++++ mods/poudlard/poudecor/README | 46 + mods/poudlard/poudecor/armchair.lua | 90 + mods/poudlard/poudecor/copyright.txt | 8 + mods/poudlard/poudecor/crafts.lua | 102 ++ mods/poudlard/poudecor/curtain.lua | 81 + mods/poudlard/poudecor/furniture_recipes.lua | 15 + mods/poudlard/poudecor/listnodes.sh | 13 + mods/poudlard/poudecor/locale/es.txt | 194 ++ mods/poudlard/poudecor/locale/fr.txt | 180 ++ mods/poudlard/poudecor/locale/pt.txt | 198 ++ mods/poudlard/poudecor/locale/template.txt | 198 ++ mods/poudlard/poudecor/nightstand.lua | 154 ++ mods/poudlard/poudecor/torch.lua | 61 + mods/poudlard/readme.txt | 9 + mods/poudlard/registration.lua | 225 +++ .../textures/3dforniture_inv_torch_wall.png | Bin 0 -> 2618 bytes mods/poudlard/textures/Thumbs.db | Bin 0 -> 35840 bytes .../forniture_armchair_lat1_black.png | Bin 0 -> 476 bytes .../textures/forniture_armchair_lat1_blue.png | Bin 0 -> 408 bytes .../forniture_armchair_lat1_dark_green.png | Bin 0 -> 422 bytes .../textures/forniture_armchair_lat1_red.png | Bin 0 -> 433 bytes .../forniture_armchair_lat1_violet.png | Bin 0 -> 422 bytes .../forniture_armchair_lat1_yellow.png | Bin 0 -> 429 bytes .../forniture_armchair_lat2_black.png | Bin 0 -> 442 bytes .../textures/forniture_armchair_lat2_blue.png | Bin 0 -> 375 bytes .../forniture_armchair_lat2_dark_green.png | Bin 0 -> 391 bytes .../textures/forniture_armchair_lat2_red.png | Bin 0 -> 395 bytes .../forniture_armchair_lat2_violet.png | Bin 0 -> 391 bytes .../forniture_armchair_lat2_yellow.png | Bin 0 -> 401 bytes .../textures/forniture_armchair_top_black.png | Bin 0 -> 481 bytes .../textures/forniture_armchair_top_blue.png | Bin 0 -> 398 bytes .../forniture_armchair_top_dark_green.png | Bin 0 -> 409 bytes .../textures/forniture_armchair_top_red.png | Bin 0 -> 446 bytes .../forniture_armchair_top_violet.png | Bin 0 -> 409 bytes .../forniture_armchair_top_yellow.png | Bin 0 -> 416 bytes .../textures/forniture_torch_wall_anim.png | Bin 0 -> 2794 bytes .../textures/forniture_torch_wall_i.png | Bin 0 -> 1061 bytes .../textures/forniture_torch_wall_s.png | Bin 0 -> 1061 bytes .../textures/homedecor_curtain_black.png | Bin 0 -> 288 bytes .../textures/homedecor_curtain_blue.png | Bin 0 -> 332 bytes .../textures/homedecor_curtain_dark_green.png | Bin 0 -> 320 bytes .../textures/homedecor_curtain_dark_grey.png | Bin 0 -> 360 bytes .../textures/homedecor_curtain_green.png | Bin 0 -> 400 bytes .../textures/homedecor_curtain_orange.png | Bin 0 -> 355 bytes .../textures/homedecor_curtain_pink.png | Bin 0 -> 980 bytes .../textures/homedecor_curtain_red.png | Bin 0 -> 581 bytes .../textures/homedecor_curtain_violet.png | Bin 0 -> 275 bytes .../textures/homedecor_curtain_white.png | Bin 0 -> 447 bytes .../textures/homedecor_curtain_yellow.png | Bin 0 -> 349 bytes ...cor_nightstand_mahogany_2_drawer_front.png | Bin 0 -> 725 bytes .../homedecor_nightstand_mahogany_back.png | Bin 0 -> 565 bytes .../homedecor_nightstand_mahogany_bottom.png | Bin 0 -> 688 bytes .../homedecor_nightstand_mahogany_left.png | Bin 0 -> 697 bytes .../homedecor_nightstand_mahogany_right.png | Bin 0 -> 708 bytes .../homedecor_nightstand_mahogany_top.png | Bin 0 -> 678 bytes ...omedecor_nightstand_oak_2_drawer_front.png | Bin 0 -> 747 bytes .../homedecor_nightstand_oak_back.png | Bin 0 -> 696 bytes .../homedecor_nightstand_oak_bottom.png | Bin 0 -> 735 bytes .../homedecor_nightstand_oak_left.png | Bin 0 -> 758 bytes .../homedecor_nightstand_oak_right.png | Bin 0 -> 754 bytes .../textures/homedecor_nightstand_oak_top.png | Bin 0 -> 730 bytes .../poudlard/textures/poudlard_blackblock.png | Bin 0 -> 487 bytes .../textures/poudlard_cactuschecker.png | Bin 0 -> 826 bytes .../textures/poudlard_cactuschecker_2.png | Bin 0 -> 829 bytes .../textures/poudlard_circlestonebrick.png | Bin 0 -> 646 bytes .../poudlard/textures/poudlard_cleanglass.png | Bin 0 -> 249 bytes .../textures/poudlard_coalchecker.png | Bin 0 -> 902 bytes .../textures/poudlard_coalchecker_2.png | Bin 0 -> 900 bytes mods/poudlard/textures/poudlard_coalglass.png | Bin 0 -> 245 bytes mods/poudlard/textures/poudlard_coalstone.png | Bin 0 -> 545 bytes .../textures/poudlard_emptybookshelf.png | Bin 0 -> 675 bytes mods/poudlard/textures/poudlard_glowglass.png | Bin 0 -> 265 bytes .../poudlard_horizontaljungletree.png | Bin 0 -> 808 bytes .../textures/poudlard_horizontaltree.png | Bin 0 -> 756 bytes .../textures/poudlard_ironchecker.png | Bin 0 -> 884 bytes .../textures/poudlard_ironchecker_2.png | Bin 0 -> 889 bytes mods/poudlard/textures/poudlard_ironglass.png | Bin 0 -> 248 bytes mods/poudlard/textures/poudlard_ironstone.png | Bin 0 -> 555 bytes .../textures/poudlard_ironstonebrick.png | Bin 0 -> 741 bytes .../textures/poudlard_junglestick.png | Bin 0 -> 215 bytes .../poudlard/textures/poudlard_junglewood.png | Bin 0 -> 362 bytes .../textures/poudlard_junglewood_fence.png | Bin 0 -> 392 bytes .../poudlard/textures/poudlard_plankstone.png | Bin 0 -> 598 bytes .../textures/poudlard_plankstone_2.png | Bin 0 -> 604 bytes mods/poudlard/textures/poudlard_poudstone.png | Bin 0 -> 815 bytes mods/poudlard/textures/poudlard_poudwood.png | Bin 0 -> 234 bytes mods/poudlard/textures/poudlard_redblock.png | Bin 0 -> 433 bytes mods/poudlard/textures/poudlard_rope.png | Bin 0 -> 517 bytes .../textures/poudlard_secretbookshelf.png | Bin 0 -> 624 bytes .../textures/poudlard_splitstonesquare.png | Bin 0 -> 734 bytes .../poudlard_splitstonesquare_top.png | Bin 0 -> 752 bytes .../poudlard/textures/poudlard_stonebrick.png | Bin 0 -> 650 bytes .../textures/poudlard_stonesquare.png | Bin 0 -> 700 bytes mods/poudlard/textures/poudlard_sweeper.png | Bin 0 -> 477 bytes mods/poudlard/textures/poudlard_trapglass.png | Bin 0 -> 261 bytes mods/poudlard/textures/poudlard_trapstone.png | Bin 0 -> 817 bytes mods/poudlard/textures/poudlard_wood_tile.png | Bin 0 -> 598 bytes .../textures/poudlard_wood_tile_center.png | Bin 0 -> 545 bytes .../textures/poudlard_wood_tile_full.png | Bin 0 -> 594 bytes mods/poudlard/textures/texte déposé.txt | 1 + .../textures/default_chest_front.png | Bin 421 -> 146 bytes .../textures/default_chest_inside.png | Bin 0 -> 102 bytes .../protector/textures/default_chest_lock.png | Bin 0 -> 171 bytes .../protector/textures/default_chest_side.png | Bin 375 -> 140 bytes mods/protector/textures/default_chest_top.png | Bin 418 -> 138 bytes mods/skins.tar.gz | Bin 0 -> 25137 bytes mods/skinsdb/meta/character_17.txt | 3 + mods/skinsdb/meta/character_18.txt | 3 + mods/skinsdb/meta/character_19.txt | 3 + mods/skinsdb/meta/character_20.txt | 3 + mods/skinsdb/meta/character_21.txt | 3 + mods/skinsdb/meta/character_22.txt | 3 + mods/skinsdb/meta/character_23.txt | 3 + mods/skinsdb/textures/character_17.png | Bin 0 -> 417 bytes .../skinsdb/textures/character_17_preview.png | Bin 0 -> 514 bytes mods/skinsdb/textures/character_18.png | Bin 0 -> 473 bytes .../skinsdb/textures/character_18_preview.png | Bin 0 -> 536 bytes mods/skinsdb/textures/character_22.png | Bin 0 -> 323 bytes .../skinsdb/textures/character_22_preview.png | Bin 0 -> 440 bytes .../character_placeholder_preview.png | Bin 258 -> 203 bytes mods/stairs/README.txt | 29 +- mods/stairs/README.txt.diff | 29 - mods/stairs/depends.txt | 1 - mods/stairs/init.lua | 246 ++- mods/stairs/license.txt | 1 + mods/stairs/models/stairs_stair_inner.obj | 161 ++ mods/stairs/models/stairs_stair_outer.obj | 136 ++ todo/TODO.md | 3 + 197 files changed, 9278 insertions(+), 75 deletions(-) create mode 100644 mods/fishing/bobber.lua create mode 100644 mods/fishing/crafting.lua create mode 100644 mods/fishing/depends.txt create mode 100644 mods/fishing/fishes.lua create mode 100644 mods/fishing/init.lua create mode 100644 mods/fishing/settings.txt create mode 100644 mods/fishing/sounds/SoundLicense.txt create mode 100644 mods/fishing/sounds/fishing_bobber1.ogg create mode 100644 mods/fishing/sounds/fishing_bobber2.ogg create mode 100644 mods/fishing/textures/alternates/fishing_bobber.png create mode 100644 mods/fishing/textures/alternates/fishing_pole.png create mode 100644 mods/fishing/textures/fishing_bobber.png create mode 100644 mods/fishing/textures/fishing_bobber_ready.png create mode 100644 mods/fishing/textures/fishing_fish.png create mode 100644 mods/fishing/textures/fishing_fish_cooked.png create mode 100644 mods/fishing/textures/fishing_pole.png create mode 100644 mods/fishing/textures/fishing_pole_back.png create mode 100644 mods/fishing/textures/fishing_pole_bottom.png create mode 100644 mods/fishing/textures/fishing_pole_deco.png create mode 100644 mods/fishing/textures/fishing_pole_front.png create mode 100644 mods/fishing/textures/fishing_pole_on_use.png create mode 100644 mods/fishing/textures/fishing_pole_simple.png create mode 100644 mods/fishing/textures/fishing_pole_top.png create mode 100644 mods/fishing/textures/fishing_sushi.png create mode 100644 mods/fishing/textures/fishing_worm.png create mode 100644 mods/fishing/textures/old/fishing_pole_wield.png create mode 100644 mods/fishing/worm.lua create mode 100644 mods/irc/.gitignore create mode 100644 mods/irc/.gitmodules create mode 100644 mods/irc/.luacheckrc create mode 100644 mods/irc/API.md create mode 100644 mods/irc/LICENSE.txt create mode 100644 mods/irc/README.md create mode 100644 mods/irc/botcmds.lua create mode 100644 mods/irc/callback.lua create mode 100644 mods/irc/chatcmds.lua create mode 100644 mods/irc/config.lua create mode 100644 mods/irc/description.txt create mode 100644 mods/irc/hooks.lua create mode 100644 mods/irc/init.lua create mode 100644 mods/irc/irc/LICENSE.txt create mode 100644 mods/irc/irc/README.markdown create mode 100644 mods/irc/irc/asyncoperations.lua create mode 100644 mods/irc/irc/doc/irc.luadoc create mode 100644 mods/irc/irc/handlers.lua create mode 100644 mods/irc/irc/init.lua create mode 100644 mods/irc/irc/messages.lua create mode 100755 mods/irc/irc/push-luadoc.sh create mode 100644 mods/irc/irc/set.lua create mode 100644 mods/irc/irc/util.lua create mode 100644 mods/irc/messages.lua create mode 100644 mods/irc/mod.conf create mode 100644 mods/irc/player_part.lua create mode 100644 mods/irc/settingtypes.txt create mode 100644 mods/point/init.lua create mode 100644 mods/poudlard/aliases.lua create mode 100644 mods/poudlard/depends.txt create mode 100644 mods/poudlard/init.lua create mode 100644 mods/poudlard/locale/es.txt create mode 100644 mods/poudlard/locale/fr.txt create mode 100644 mods/poudlard/locale/pt.txt create mode 100644 mods/poudlard/locale/template.txt create mode 100644 mods/poudlard/nodes.lua create mode 100644 mods/poudlard/poudecor/LICENSE create mode 100644 mods/poudlard/poudecor/README create mode 100644 mods/poudlard/poudecor/armchair.lua create mode 100644 mods/poudlard/poudecor/copyright.txt create mode 100644 mods/poudlard/poudecor/crafts.lua create mode 100644 mods/poudlard/poudecor/curtain.lua create mode 100644 mods/poudlard/poudecor/furniture_recipes.lua create mode 100644 mods/poudlard/poudecor/listnodes.sh create mode 100644 mods/poudlard/poudecor/locale/es.txt create mode 100644 mods/poudlard/poudecor/locale/fr.txt create mode 100644 mods/poudlard/poudecor/locale/pt.txt create mode 100644 mods/poudlard/poudecor/locale/template.txt create mode 100644 mods/poudlard/poudecor/nightstand.lua create mode 100644 mods/poudlard/poudecor/torch.lua create mode 100644 mods/poudlard/readme.txt create mode 100644 mods/poudlard/registration.lua create mode 100644 mods/poudlard/textures/3dforniture_inv_torch_wall.png create mode 100644 mods/poudlard/textures/Thumbs.db create mode 100644 mods/poudlard/textures/forniture_armchair_lat1_black.png create mode 100644 mods/poudlard/textures/forniture_armchair_lat1_blue.png create mode 100644 mods/poudlard/textures/forniture_armchair_lat1_dark_green.png create mode 100644 mods/poudlard/textures/forniture_armchair_lat1_red.png create mode 100644 mods/poudlard/textures/forniture_armchair_lat1_violet.png create mode 100644 mods/poudlard/textures/forniture_armchair_lat1_yellow.png create mode 100644 mods/poudlard/textures/forniture_armchair_lat2_black.png create mode 100644 mods/poudlard/textures/forniture_armchair_lat2_blue.png create mode 100644 mods/poudlard/textures/forniture_armchair_lat2_dark_green.png create mode 100644 mods/poudlard/textures/forniture_armchair_lat2_red.png create mode 100644 mods/poudlard/textures/forniture_armchair_lat2_violet.png create mode 100644 mods/poudlard/textures/forniture_armchair_lat2_yellow.png create mode 100644 mods/poudlard/textures/forniture_armchair_top_black.png create mode 100644 mods/poudlard/textures/forniture_armchair_top_blue.png create mode 100644 mods/poudlard/textures/forniture_armchair_top_dark_green.png create mode 100644 mods/poudlard/textures/forniture_armchair_top_red.png create mode 100644 mods/poudlard/textures/forniture_armchair_top_violet.png create mode 100644 mods/poudlard/textures/forniture_armchair_top_yellow.png create mode 100644 mods/poudlard/textures/forniture_torch_wall_anim.png create mode 100644 mods/poudlard/textures/forniture_torch_wall_i.png create mode 100644 mods/poudlard/textures/forniture_torch_wall_s.png create mode 100644 mods/poudlard/textures/homedecor_curtain_black.png create mode 100644 mods/poudlard/textures/homedecor_curtain_blue.png create mode 100644 mods/poudlard/textures/homedecor_curtain_dark_green.png create mode 100644 mods/poudlard/textures/homedecor_curtain_dark_grey.png create mode 100644 mods/poudlard/textures/homedecor_curtain_green.png create mode 100644 mods/poudlard/textures/homedecor_curtain_orange.png create mode 100644 mods/poudlard/textures/homedecor_curtain_pink.png create mode 100644 mods/poudlard/textures/homedecor_curtain_red.png create mode 100644 mods/poudlard/textures/homedecor_curtain_violet.png create mode 100644 mods/poudlard/textures/homedecor_curtain_white.png create mode 100644 mods/poudlard/textures/homedecor_curtain_yellow.png create mode 100644 mods/poudlard/textures/homedecor_nightstand_mahogany_2_drawer_front.png create mode 100644 mods/poudlard/textures/homedecor_nightstand_mahogany_back.png create mode 100644 mods/poudlard/textures/homedecor_nightstand_mahogany_bottom.png create mode 100644 mods/poudlard/textures/homedecor_nightstand_mahogany_left.png create mode 100644 mods/poudlard/textures/homedecor_nightstand_mahogany_right.png create mode 100644 mods/poudlard/textures/homedecor_nightstand_mahogany_top.png create mode 100644 mods/poudlard/textures/homedecor_nightstand_oak_2_drawer_front.png create mode 100644 mods/poudlard/textures/homedecor_nightstand_oak_back.png create mode 100644 mods/poudlard/textures/homedecor_nightstand_oak_bottom.png create mode 100644 mods/poudlard/textures/homedecor_nightstand_oak_left.png create mode 100644 mods/poudlard/textures/homedecor_nightstand_oak_right.png create mode 100644 mods/poudlard/textures/homedecor_nightstand_oak_top.png create mode 100644 mods/poudlard/textures/poudlard_blackblock.png create mode 100644 mods/poudlard/textures/poudlard_cactuschecker.png create mode 100644 mods/poudlard/textures/poudlard_cactuschecker_2.png create mode 100644 mods/poudlard/textures/poudlard_circlestonebrick.png create mode 100644 mods/poudlard/textures/poudlard_cleanglass.png create mode 100644 mods/poudlard/textures/poudlard_coalchecker.png create mode 100644 mods/poudlard/textures/poudlard_coalchecker_2.png create mode 100644 mods/poudlard/textures/poudlard_coalglass.png create mode 100644 mods/poudlard/textures/poudlard_coalstone.png create mode 100644 mods/poudlard/textures/poudlard_emptybookshelf.png create mode 100644 mods/poudlard/textures/poudlard_glowglass.png create mode 100644 mods/poudlard/textures/poudlard_horizontaljungletree.png create mode 100644 mods/poudlard/textures/poudlard_horizontaltree.png create mode 100644 mods/poudlard/textures/poudlard_ironchecker.png create mode 100644 mods/poudlard/textures/poudlard_ironchecker_2.png create mode 100644 mods/poudlard/textures/poudlard_ironglass.png create mode 100644 mods/poudlard/textures/poudlard_ironstone.png create mode 100644 mods/poudlard/textures/poudlard_ironstonebrick.png create mode 100644 mods/poudlard/textures/poudlard_junglestick.png create mode 100644 mods/poudlard/textures/poudlard_junglewood.png create mode 100644 mods/poudlard/textures/poudlard_junglewood_fence.png create mode 100644 mods/poudlard/textures/poudlard_plankstone.png create mode 100644 mods/poudlard/textures/poudlard_plankstone_2.png create mode 100644 mods/poudlard/textures/poudlard_poudstone.png create mode 100644 mods/poudlard/textures/poudlard_poudwood.png create mode 100644 mods/poudlard/textures/poudlard_redblock.png create mode 100644 mods/poudlard/textures/poudlard_rope.png create mode 100644 mods/poudlard/textures/poudlard_secretbookshelf.png create mode 100644 mods/poudlard/textures/poudlard_splitstonesquare.png create mode 100644 mods/poudlard/textures/poudlard_splitstonesquare_top.png create mode 100644 mods/poudlard/textures/poudlard_stonebrick.png create mode 100644 mods/poudlard/textures/poudlard_stonesquare.png create mode 100644 mods/poudlard/textures/poudlard_sweeper.png create mode 100644 mods/poudlard/textures/poudlard_trapglass.png create mode 100644 mods/poudlard/textures/poudlard_trapstone.png create mode 100644 mods/poudlard/textures/poudlard_wood_tile.png create mode 100644 mods/poudlard/textures/poudlard_wood_tile_center.png create mode 100644 mods/poudlard/textures/poudlard_wood_tile_full.png create mode 100644 mods/poudlard/textures/texte déposé.txt create mode 100644 mods/protector/textures/default_chest_inside.png create mode 100644 mods/protector/textures/default_chest_lock.png create mode 100644 mods/skins.tar.gz create mode 100644 mods/skinsdb/meta/character_17.txt create mode 100644 mods/skinsdb/meta/character_18.txt create mode 100644 mods/skinsdb/meta/character_19.txt create mode 100644 mods/skinsdb/meta/character_20.txt create mode 100644 mods/skinsdb/meta/character_21.txt create mode 100644 mods/skinsdb/meta/character_22.txt create mode 100644 mods/skinsdb/meta/character_23.txt create mode 100644 mods/skinsdb/textures/character_17.png create mode 100644 mods/skinsdb/textures/character_17_preview.png create mode 100644 mods/skinsdb/textures/character_18.png create mode 100644 mods/skinsdb/textures/character_18_preview.png create mode 100644 mods/skinsdb/textures/character_22.png create mode 100644 mods/skinsdb/textures/character_22_preview.png delete mode 100644 mods/stairs/README.txt.diff create mode 100644 mods/stairs/models/stairs_stair_inner.obj create mode 100644 mods/stairs/models/stairs_stair_outer.obj diff --git a/mods/default/mapgen.lua b/mods/default/mapgen.lua index 1fc2dc3..11ac9c6 100644 --- a/mods/default/mapgen.lua +++ b/mods/default/mapgen.lua @@ -23,8 +23,8 @@ minetest.register_alias("mapgen_sandstone", "default:sandstone") minetest.register_alias("mapgen_tree", "default:tree") minetest.register_alias("mapgen_leaves", "default:leaves") minetest.register_alias("mapgen_apple", "default:apple") -minetest.register_alias("mapgen_jungletree", "default:jungletree") -minetest.register_alias("mapgen_jungleleaves", "default:jungleleaves") +minetest.register_alias("mapgen_jungletree", "default:jungle_tree") +minetest.register_alias("mapgen_jungleleaves", "default:jungle_leaves") minetest.register_alias("mapgen_junglegrass", "default:junglegrass") minetest.register_alias("mapgen_pine_tree", "default:pine_tree") minetest.register_alias("mapgen_pine_needles", "default:pine_needles") diff --git a/mods/default/textures/default_torch_on_ceiling_animated.png b/mods/default/textures/default_torch_on_ceiling_animated.png index 3a8b5ad9547fcb4c9ad7aba659c503e4dc832c34..4c6d1f885239d93aaf2d2606c949953f18816c4a 100644 GIT binary patch delta 180 zcmbQjeu_o2Gr-TCmrII^fq{Y7)59eQNV5TP0tYjYqec0jP-RV zd%pw48B2ovf*Bm1-ADs*lDyqr7&=&GJwQ4NJR*x37`TN&n2}-D90{Nxdx@v7EBhm6 zVFp>PZO!IRKp`bh7sn8d^T`Pb2}wx|jf<2FLN9PGv)V0TaB#(`z^Nr+oD6dh={sh6 Tt!M?RX7F_Nb6MwVef9Kk9pa1{>0d!JMQvg8b*k%9#0iH=jK~z}7-IrHSf-w|^>sCNO1pP#i z4T6G#h>Cmfz4zXG@4fX;OT6N|SG^!4rI%06Y4Sd4PFwcBo*Ar^BqSLK(h;P|0i+_3 z<#l@&2zhjE(UL(e^!Te;{8wg7d?cd}J!7B5N6?`je<3BOx@p?8ZG=t6Z+QZU;X}^O z?xKNo?c1a!N9{!v-0RjTa9{ES5XA>wQb;pI$&E6bg0bN~3I?9I5(wb~LH;{aP%`6E zQQ*vhp2aGz1Y-L5U_BRvc50N%I~ zh~i@ke|)Gcq~xF%=0~nhO~G6(R{~LdFz^A#;jpU#d}!w>@YnH05Yk5tvr@9_u$t-o zutQJT7gqv7e7u~4k4`!sR&0t10^9-gkwE7o0?Nt#^1#dnQW8+Y1>8Ccn{0gZ1Q5fA z9DGQj77Klk?zipW{D4i?6KJ05;l7mxn;U7#N{In_W}5&kzj7rI#RvRvZIhJjnc%*y z?60SwRNVh<_y>H1kAK03QU&piFh6`9PVf=m_xc|c7BHhyqHp#900004nJ za0`PlBg3pY5H=O_D9UZ46>?fHd>c~LeZWsjv*Y^W6x~lZ4MA|zW8}jiO*y^ zZkHsXX$zfC$!R9=Rkilb u4x88=e2@`-a?z^odAmz*hkl)Olk>_CrGGCrRA>XOVeoYIb6Mw<&;$TDvqvZZ literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!M}SX=E08u+5=n5<(3TT?d}UIG zhtB&4Yo0w^eDCa{o5yB9In%d)LH)gbrI!}Q1dEEN_z0!=q; zSp4bdjg|{NBBCzB3D4Zc6I_K8Qj|0l96VY%w0G$q3SeVc*~6$U_PI6+Xbyv?tDnm{ Hr-UW|3$8^U diff --git a/mods/default/textures/default_torch_on_floor_animated.png b/mods/default/textures/default_torch_on_floor_animated.png index ad51c03a86e53571ba9eba8e6557b6cb13c6bc81..7daf78d129dd4817c0bd1d1d2129ac6c81738b8b 100644 GIT binary patch delta 178 zcmdnTHit#CGr-TCmrII^fq{Y7)59eQNV5TP0tYjYB)})cb)!xRWBrN4 zwj4ll#*!evUYh7ML)50H)mkH}&M25w;xW@MN(M*=9wUgGKN%KnI1 zm_b(m*vrFbfkKL&E{-7@=aUl}8aEXgObupRW@L0g#MqcwO(N8C)ucErMlA`gz%|@k RQ-F#YJYD@<);T3K0RZXFmWd? zBq4!7gy8P(?(X{WtXSNe1yxyP`t8n{d0o}F`gLncug!~o6e({Sg|iR&Dz4BPx^@yx zl_a#)Br0lH)RAbY=RaymG**#lX)Ymv?@vHi!j1cteiwAQH>*7B@>F!%ntBc?1}G> z4w3T6B041p4bVFB@$@0B(5C7TTKdnicrvPccHmqMM7EV1DL+2=zJgvU_CUWLko zs~b_ae;H5=$pIAc0iGA3?o%0YU-F~SC#a#TC=WHiw_hwGh&E#oPfX7$=TQ(TkDnX~ z(3qE0<1{$@^xhh&A-ceMJd@C=IS;C2 zhJ?jK;%1P9xlpcoJpQ}g4;Ht?8LJb8)nh`jAw6Y4VS6jnJhXr3;}`iBFOjHj8)pCj N002ovPDHLkV1g@o%clSU diff --git a/mods/default/trees.lua b/mods/default/trees.lua index b2687c9..2eae060 100644 --- a/mods/default/trees.lua +++ b/mods/default/trees.lua @@ -542,16 +542,18 @@ minetest.register_alias("trees:wood_conifer", "default:pine_wood") minetest.register_alias("trees:sapling_conifer", "default:pine_sapling") minetest.register_alias("trees:leaves_conifer", "default:pine_needles") -minetest.register_alias("trees:tree_palm", "default:jungletree") -minetest.register_alias("trees:leaves_palm", "default:jungleleaves") -minetest.register_alias("trees:sapling_palm", "default:junglesapling") -minetest.register_alias("trees:wood_palm", "default:junglewood") +minetest.register_alias("trees:tree_palm", "default:jungle_tree") +minetest.register_alias("default:jungleleaves", "default:jungle_leaves") +minetest.register_alias("default:junglewood", "default:jungle_wood") +minetest.register_alias("trees:leaves_palm", "default:jungle_leaves") +minetest.register_alias("trees:sapling_palm", "default:jungle_sapling") +minetest.register_alias("trees:wood_palm", "default:jungle_wood") minetest.register_alias("trees:tree_mangrove", "default:aspen_tree") minetest.register_alias("trees:leaves_mangrove", "default:aspen_leaves") minetest.register_alias("trees:sapling_mangrove", "default:aspen_sapling") minetest.register_alias("trees:wood_mangrove", "default:aspen_wood") -minetest.register_alias("trees:leaves_red", "default:jungleleaves") -minetest.register_alias("trees:leaves_yellow", "default:jungleleaves") -minetest.register_alias("trees:leaves_green", "default:jungleleaves") +minetest.register_alias("trees:leaves_red", "default:jungle_leaves") +minetest.register_alias("trees:leaves_yellow", "default:jungle_leaves") +minetest.register_alias("trees:leaves_green", "default:jungle_leaves") diff --git a/mods/fishing/bobber.lua b/mods/fishing/bobber.lua new file mode 100644 index 0000000..66e7092 --- /dev/null +++ b/mods/fishing/bobber.lua @@ -0,0 +1,299 @@ +----------------------------------------------------------------------------------------------- +-- Fishing - Mossmanikin's version - Bobber 0.1.0 +-- License (code & textures): WTFPL +-- Contains code from: fishing (original), mobs, throwing +-- Supports: animal_clownfish, animal_fish_blue_white, animal_rat, mobs +----------------------------------------------------------------------------------------------- +-- 0.0625 (= 1 pixel on 16x16 texture) +-- 0.125 +-- 0.1875 +-- 0.25 +-- 0.3125 +-- 0.375 +-- 0.4375 +-- 0.5 (= 8 pixels on 16x16 texture) +-- 0.5625 (= 9 pixels on 16x16 texture) +-- 0.625 +-- 0.6875 +-- 0.75 +-- 0.8125 +-- 0.875 +-- 0.9375 +-- 1.0 (= 16 pixels on 16x16 texture) + +minetest.register_node("fishing:bobber_box", { + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { +-- { left , bottom , front , right , top , back } + {-0.0625, -0.6875, -0.0625, 0.0625, -0.5625, 0.0625}, + } + }, + tiles = {"fishing_bobber.png"}, + groups = {not_in_creative_inventory=1}, +}) + +minetest.register_node("fishing:bobber_box_ready", { + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { +-- { left , bottom , front , right , top , back } + {-0.0625, -0.6875, -0.0625, 0.0625, -0.5625, 0.0625}, + } + }, + tiles = {"fishing_bobber_ready.png"}, + groups = {not_in_creative_inventory=1}, +}) + +local FISHING_BOBBER_ENTITY={ + hp_max = 605, + water_damage = 1, + physical = true, + timer = 0, + env_damage_timer = 0, + visual = "wielditem", + visual_size = {x=0.5, y=0.5, z=0.5}, + textures = {"fishing:bobber_box"}, + -- { left , bottom , front , right , top , back } + collisionbox = {-0.125 , -0.5625, -0.125 , 0.125 , -0.3125, 0.125 }, + view_range = 7, +-- DESTROY BOBBER WHEN PUNCHING IT + on_punch = function (self, puncher, time_from_last_punch, tool_capabilities, dir) + local player = puncher:get_player_name() + if MESSAGES == true then + --minetest.chat_send_all("Your fish escaped.") + minetest.chat_send_player(player, "Your fish escaped.", false) + end + minetest.sound_play("fishing_bobber1", { + pos = self.object:getpos(), + gain = 0.5, + }) + self.object:remove() + end, +-- WHEN RIGHTCLICKING THE BOBBER THE FOLLOWING HAPPENS (CLICK AT THE RIGHT TIME WHILE HOLDING A FISHING POLE) + on_rightclick = function (self, clicker) + local item = clicker:get_wielded_item() + local player = clicker:get_player_name() + if item:get_name() == "fishing:pole" then + local inv = clicker:get_inventory() + local room_fish = inv:room_for_item("main", {name="fishing:fish_raw", count=1, wear=0, metadata=""}) + if self.object:get_hp() <= 300 then + if math.random(1, 100) < FISH_CHANCE then + local chance = math.random(1, 84) + if chance <= 60 then + if room_fish then + inv:add_item("main", {name="fishing:fish_raw", count=1, wear=0, metadata=""}) + if MESSAGES == true then + --minetest.chat_send_all("You caught a Fish.") + minetest.chat_send_player(player, "You caught a Fish.", false) + end + end + elseif chance <= 70 then + if minetest.get_modpath("animal_clownfish") ~= nil then + if inv:room_for_item("main", {name="animal_clownfish:clownfish", count=1, wear=0, metadata=""}) then + inv:add_item("main", {name="animal_clownfish:clownfish", count=1, wear=0, metadata=""}) + if MESSAGES == true then + --minetest.chat_send_all("You caught a Clownfish.") + minetest.chat_send_player(player, "You caught a Clownfish.", false) + end + end + else + if room_fish then + inv:add_item("main", {name="fishing:fish_raw", count=1, wear=0, metadata=""}) + if MESSAGES == true then + --minetest.chat_send_all("You caught a Fish.") + minetest.chat_send_player(player, "You caught a Fish.", false) + end + end + end + elseif chance <= 80 then + if minetest.get_modpath("animal_fish_blue_white") ~= nil then + if inv:room_for_item("main", {name="animal_fish_blue_white:fish_blue_white", count=1, wear=0, metadata=""}) then + inv:add_item("main", {name="animal_fish_blue_white:fish_blue_white", count=1, wear=0, metadata=""}) + if MESSAGES == true then + --minetest.chat_send_all("You caught a Blue white fish.") + minetest.chat_send_player(player, "You caught a Blue white fish.", false) + end + end + else + if room_fish then + inv:add_item("main", {name="fishing:fish_raw", count=1, wear=0, metadata=""}) + if MESSAGES == true then + --minetest.chat_send_all("You caught a Fish.") + minetest.chat_send_player(player, "You caught a Fish.", false) + end + end + end + elseif chance == 81 then + if inv:room_for_item("main", {name="default:stick", count=1, wear=0, metadata=""}) then + inv:add_item("main", {name="default:stick", count=1, wear=0, metadata=""}) + if MESSAGES == true then + --minetest.chat_send_all("You caught a Stick.") + minetest.chat_send_player(player, "You caught a Stick.", false) + end + end + elseif chance == 82 then + if minetest.get_modpath("mobs") ~= nil then + if inv:room_for_item("main", {name="mobs:rat", count=1, wear=0, metadata=""}) then + inv:add_item("main", {name="mobs:rat", count=1, wear=0, metadata=""}) + if MESSAGES == true then + --minetest.chat_send_all("You caught a Rat.") + minetest.chat_send_player(player, "You caught a Rat.", false) + end + end + elseif minetest.get_modpath("animal_rat") ~= nil then + if inv:room_for_item("main", {name="animal_rat:rat", count=1, wear=0, metadata=""}) then + inv:add_item("main", {name="animal_rat:rat", count=1, wear=0, metadata=""}) + if MESSAGES == true then + --minetest.chat_send_all("You caught a Rat.") + minetest.chat_send_player(player, "You caught a Rat.", false) + end + end + else + if inv:room_for_item("main", {name="rat", count=1, wear=0, metadata=""}) then + inv:add_item("main", {name="rat", count=1, wear=0, metadata=""}) + if MESSAGES == true then + --minetest.chat_send_all("You caught a Rat.") + minetest.chat_send_player(player, "You caught a Rat.", false) + end + end + end + end + elseif chance == 83 then + if minetest.get_modpath("flowers_plus") ~= nil then + if inv:room_for_item("main", {name="flowers:seaweed", count=1, wear=0, metadata=""}) then + inv:add_item("main", {name="flowers:seaweed", count=1, wear=0, metadata=""}) + if MESSAGES == true then + --minetest.chat_send_all("You caught a Clownfish.") + minetest.chat_send_player(player, "You caught some Seaweed.", false) + end + end + else + if room_fish then + inv:add_item("main", {name="fishing:fish_raw", count=1, wear=0, metadata=""}) + if MESSAGES == true then + --minetest.chat_send_all("You caught a Fish.") + minetest.chat_send_player(player, "You caught a Fish.", false) + end + end + end + elseif chance == 84 then + if minetest.get_modpath("seaplants") ~= nil then + if inv:room_for_item("main", {name="seaplants:leavysnackgreen", count=1, wear=0, metadata=""}) then + inv:add_item("main", {name="seaplants:leavysnackgreen", count=1, wear=0, metadata=""}) + if MESSAGES == true then + --minetest.chat_send_all("You caught a Clownfish.") + minetest.chat_send_player(player, "You caught a Leavy Snack.", false) + end + end + else + if room_fish then + inv:add_item("main", {name="fishing:fish_raw", count=1, wear=0, metadata=""}) + if MESSAGES == true then + --minetest.chat_send_all("You caught a Fish.") + minetest.chat_send_player(player, "You caught a Fish.", false) + end + end + end + else + if MESSAGES == true then + --minetest.chat_send_all("Your fish escaped.") + minetest.chat_send_player(player, "Your fish escaped.", false) + end + end + else + if MESSAGES == true then + --minetest.chat_send_all("Your fish escaped.") + minetest.chat_send_player(player, "Your fish escaped.", false) + end + end + else + if MESSAGES == true then + --minetest.chat_send_all("Your fish escaped.") + minetest.chat_send_player(player, "Your fish escaped.", false) + end + end + minetest.sound_play("fishing_bobber1", { + pos = self.object:getpos(), + gain = 0.5, + }) + self.object:remove() + end, +-- AS SOON AS THE BOBBER IS PLACED IT WILL ACT LIKE + on_step = function(self, dtime) + local pos = self.object:getpos() + if BOBBER_CHECK_RADIUS > 0 then + local objs = minetest.env:get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, BOBBER_CHECK_RADIUS) + for k, obj in pairs(objs) do + if obj:get_luaentity() ~= nil then + if obj:get_luaentity().name == "fishing:bobber_entity" then + if obj:get_luaentity() ~= self then + self.object:remove() + end + end + end + end + end + if math.random(1, 4) == 1 then + self.object:setyaw(self.object:getyaw()+((math.random(0,360)-180)/180*math.pi)) + end + for _,player in pairs(minetest.get_connected_players()) do + local s = self.object:getpos() + local p = player:getpos() + local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5 + if dist > self.view_range then + minetest.sound_play("fishing_bobber1", { + pos = self.object:getpos(), + gain = 0.5, + }) + self.object:remove() + end + end + local do_env_damage = function(self) + self.object:set_hp(self.object:get_hp()-self.water_damage) + --local pos = self.object:getpos() + if self.object:get_hp() == 600 then + self.object:moveto({x=pos.x,y=pos.y-0.03125,z=pos.z}) + elseif self.object:get_hp() == 595 then + self.object:moveto({x=pos.x,y=pos.y+0.03125,z=pos.z}) + elseif self.object:get_hp() == 590 then + self.object:moveto({x=pos.x,y=pos.y+0.03125,z=pos.z}) + elseif self.object:get_hp() == 585 then + self.object:moveto({x=pos.x,y=pos.y-0.03125,z=pos.z}) + self.object:set_hp(self.object:get_hp()-(math.random(1, 200))) + elseif self.object:get_hp() == 300 then + minetest.sound_play("fishing_bobber1", { + pos = self.object:getpos(), + gain = 0.5, + }) + if BOBBER_COLOR_CHANGE == true then + self.object:set_properties({ + textures = {"fishing:bobber_box_ready"}, + }) + end + self.object:moveto({x=pos.x,y=pos.y-0.0625,z=pos.z}) + elseif self.object:get_hp() == 295 then + self.object:moveto({x=pos.x,y=pos.y+0.0625,z=pos.z}) + elseif self.object:get_hp() == 290 then + self.object:moveto({x=pos.x,y=pos.y+0.0625,z=pos.z}) + elseif self.object:get_hp() == 285 then + self.object:moveto({x=pos.x,y=pos.y-0.0625,z=pos.z}) + elseif self.object:get_hp() < 284 then + self.object:moveto({x=pos.x+(0.001*(math.random(-8, 8))),y=pos.y,z=pos.z+(0.001*(math.random(-8, 8)))}) + elseif self.object:get_hp() == 0 then + minetest.sound_play("fishing_bobber1", { + pos = self.object:getpos(), + gain = 0.5, + }) + self.object:remove() + end + end + do_env_damage(self) + end, +} + +minetest.register_entity("fishing:bobber_entity", FISHING_BOBBER_ENTITY) + + diff --git a/mods/fishing/crafting.lua b/mods/fishing/crafting.lua new file mode 100644 index 0000000..348181f --- /dev/null +++ b/mods/fishing/crafting.lua @@ -0,0 +1,69 @@ +----------------------------------------------------------------------------------------------- +-- Fishing - Mossmanikin's version - Recipes 0.0.5 +----------------------------------------------------------------------------------------------- +-- original by wulfsdad (http://forum.minetest.net/viewtopic.php?id=4375) +-- this version by Mossmanikin +-- License (code & textures): WTFPL +-- Contains code from: animal_clownfish, animal_fish_blue_white, fishing (original), stoneage +-- Looked at code from: +-- Dependencies: default, farming +-- Supports: animal_clownfish, animal_fish_blue_white, animal_rat, mobs +----------------------------------------------------------------------------------------------- + +----------------------------------------------------------------------------------------------- +-- Fishing Pole +----------------------------------------------------------------------------------------------- +-- mc style +minetest.register_craft({ + output = "fishing:pole", + recipe = { + {"", "", "default:stick" }, + {"", "default:stick", "farming:string"}, + {"default:stick", "", "farming:string"}, + } +}) + +minetest.register_craft({ + output = "fishing:pole", + recipe = { + {"", "", "default:stick" }, + {"", "default:stick", "moreblocks:rope"}, + {"default:stick", "", "moreblocks:rope"}, + } +}) + +minetest.register_craft({ + output = "fishing:pole", + recipe = { + {"", "", "default:stick" }, + {"", "default:stick", "ropes:rope" }, + {"default:stick", "", "ropes:rope" }, + } +}) + + +----------------------------------------------------------------------------------------------- +-- Fish +----------------------------------------------------------------------------------------------- +minetest.register_craft({ + type = "cooking", + output = "fishing:fish", + recipe = "fishing:fish_raw", + cooktime = 2, +}) + +----------------------------------------------------------------------------------------------- +-- Sushi +----------------------------------------------------------------------------------------------- +minetest.register_craft({ + type = "shapeless", + output = "fishing:sushi", + recipe = {"fishing:fish_raw","flowers:seaweed"}, +}) + +minetest.register_craft({ + type = "shapeless", + output = "fishing:sushi", + recipe = {"fishing:fish_raw","seaplants:leavysnackgreen"}, +}) + diff --git a/mods/fishing/depends.txt b/mods/fishing/depends.txt new file mode 100644 index 0000000..3d9111b --- /dev/null +++ b/mods/fishing/depends.txt @@ -0,0 +1,2 @@ +default +farming diff --git a/mods/fishing/fishes.lua b/mods/fishing/fishes.lua new file mode 100644 index 0000000..0816886 --- /dev/null +++ b/mods/fishing/fishes.lua @@ -0,0 +1,30 @@ +----------------------------------------------------------------------------------------------- +-- Fish +----------------------------------------------------------------------------------------------- +minetest.register_craftitem("fishing:fish_raw", { + description = "Fish", + groups = {}, + inventory_image = "fishing_fish.png", + on_use = minetest.item_eat(2), +}) + +----------------------------------------------------------------------------------------------- +-- Roasted Fish +----------------------------------------------------------------------------------------------- +minetest.register_craftitem("fishing:fish", { + description = "Roasted Fish", + groups = {}, + inventory_image = "fishing_fish_cooked.png", + on_use = minetest.item_eat(4), +}) + +----------------------------------------------------------------------------------------------- +-- Sushi +----------------------------------------------------------------------------------------------- +minetest.register_craftitem("fishing:sushi", { + description = "Sushi (Hoso Maki)", + groups = {}, + inventory_image = "fishing_sushi.png", + on_use = minetest.item_eat(8), +}) + diff --git a/mods/fishing/init.lua b/mods/fishing/init.lua new file mode 100644 index 0000000..b76cff7 --- /dev/null +++ b/mods/fishing/init.lua @@ -0,0 +1,309 @@ +----------------------------------------------------------------------------------------------- +local title = "Fishing - Mossmanikin's version" +local version = "0.1.2-LGN" +local mname = "fishing" +----------------------------------------------------------------------------------------------- +-- original by wulfsdad (http://forum.minetest.net/viewtopic.php?id=4375) +-- this version by Mossmanikin +-- License (code & textures): WTFPL (exception below) +-- except for: "fishing_fish_cooked.png" contributed by Tirifto, +-- released into public domain under CC0. +-- Contains code from: animal_clownfish, animal_fish_blue_white, fishing (original), stoneage +-- Looked at code from: default, farming +-- Dependencies: default +-- Supports: animal_clownfish, animal_fish_blue_white, animal_rat, mobs +----------------------------------------------------------------------------------------------- + +-- todo: item wear done +-- automatic re-baiting option done +-- different types of fish, sort of +-- add sound done +-- bobber done +-- change rainworms filling inv & make 'em disappear done + +-- placable fishing rod for decoration done +-- make bobber move slowly while fish on hook done +-- catch bigger fish with smaller +-- change color of bobber when fish on hook done + +----------------------------------------------------------------------------------------------- + +dofile(minetest.get_modpath("fishing").."/settings.txt") +dofile(minetest.get_modpath("fishing").."/bobber.lua") +dofile(minetest.get_modpath("fishing").."/crafting.lua") +dofile(minetest.get_modpath("fishing").."/fishes.lua") +dofile(minetest.get_modpath("fishing").."/worm.lua") + +----------------------------------------------------------------------------------------------- +-- Fishing Pole +----------------------------------------------------------------------------------------------- + +local function rod_wear(itemstack, user, pointed_thing, uses) + itemstack:add_wear(65535/(uses-1)) + return itemstack +end + +minetest.register_tool("fishing:pole", { + + description = "Fishing Pole", + groups = {}, + inventory_image = "fishing_pole.png", + wield_image = "fishing_pole.png^[transformFXR270", + stack_max = 1, + liquids_pointable = true, + on_use = function (itemstack, user, pointed_thing) + if pointed_thing and pointed_thing.under then + local pt = pointed_thing + local node = minetest.env:get_node(pt.under) + if string.find(node.name, "default:water") then + local player = user:get_player_name() + local inv = user:get_inventory() + if inv:get_stack("main", user:get_wield_index()+1):get_name() == "fishing:bait_worm" then + inv:remove_item("main", "fishing:bait_worm") + minetest.sound_play("fishing_bobber2", { + pos = pt.under, + gain = 0.5, + }) + minetest.env:add_entity({interval = 1,x=pt.under.x, y=pt.under.y+1, z=pt.under.z}, "fishing:bobber_entity") + + if WEAR_OUT == true then + return rod_wear(itemstack, user, pointed_thing, 30) + else + return {name="fishing:pole", count=1, wear=0, metadata=""} + end + end + end + end + return nil + end, + on_place = function(itemstack, placer, pointed_thing) + local pt = pointed_thing + if minetest.get_node(pt.under).name~="default:water_source" and minetest.get_node(pt.under).name~="default:water_flowing" then + local wear = itemstack:get_wear() + local direction = minetest.dir_to_facedir(placer:get_look_dir()) + local meta1 = minetest.env:get_meta({x=pt.under.x, y=pt.under.y , z=pt.under.z}) + local meta2 = minetest.env:get_meta({x=pt.under.x, y=pt.under.y+1, z=pt.under.z}) + minetest.set_node({x=pt.under.x, y=pt.under.y+1, z=pt.under.z}, {name="fishing:pole_deco", param2=direction}) + meta1:set_int("wear", wear) + meta2:set_int("wear", wear) + itemstack:take_item() + end + return itemstack + end, +}) + +if SIMPLE_DECO_FISHING_POLE == true then +minetest.register_node("fishing:pole_deco", { + description = "Fishing Pole", + drawtype = "nodebox", + paramtype = "light", + paramtype2 = "facedir", + tiles = { + "fishing_pole_top.png", "fishing_pole_bottom.png", "fishing_pole.png", "fishing_pole.png^[transformFX", "fishing_pole_front.png", "fishing_pole_back.png", + }, + groups = { + snappy=3, + flammable=2, + not_in_creative_inventory=1 + }, + node_box = { + type = "fixed", + fixed = { + {-0.5/3, -1.5/3, -1.5/3, 0.5/3, -0.5/3, -0.5/3},{-0.5/3, -0.5/3, -0.5/3, 0.5/3, 0.5/3, 0.5/3},{-0.5/3, 0.5/3, 0.5/3, 0.5/3, 1.5/3, 1.5/3},{-0.5/3, -1.5/3, 0.5/3, 0.5/3, 0.5/3, 1.5/3}, + } + }, + selection_box = { + type = "fixed", + fixed = { + {-0.5/3, -1.5/3, -1.5/3, 0.5/3, -0.5/3, -0.5/3},{-0.5/3, -0.5/3, -0.5/3, 0.5/3, 0.5/3, 0.5/3},{-0.5/3, 0.5/3, 0.5/3, 0.5/3, 1.5/3, 1.5/3},{-0.5/3, -1.5/3, 0.5/3, 0.5/3, 0.5/3, 1.5/3}, + } + }, + sounds = default.node_sound_wood_defaults(), + on_dig = function(pos, node, digger) + if digger:is_player() and digger:get_inventory() then + local meta = minetest.env:get_meta(pos) + local wear_out = meta:get_int("wear") + digger:get_inventory():add_item("main", {name="fishing:pole", count=1, wear=wear_out, metadata=""}) + end + minetest.remove_node(pos) + end, +}) + +else +minetest.register_node("fishing:pole_deco", { + description = "Fishing Pole", + inventory_image = "fishing_pole.png", + wield_image = "fishing_pole.png^[transformFXR270", + drawtype = "nodebox", + paramtype = "light", + paramtype2 = "facedir", + tiles = { + "fishing_pole_top.png", + "fishing_pole_bottom.png", + "fishing_pole_deco.png", -- right + "fishing_pole_deco.png^[transformFX", -- left + "fishing_pole_back.png", + "fishing_pole_front.png" + }, + node_box = { + type = "fixed", +-- { left , bottom , front , right , top , back } + fixed = { + {-1/32 , -1/16 , 14/16 , 1/32 , 6/16 , 15/16}, + {-1/32 , -3/16 , 13/16 , 1/32 , -1/16 , 14/16}, + {-1/32 , -4/16 , 12/16 , 1/32 , -3/16 , 13/16}, + {-1/32 , -5/16 , 11/16 , 1/32 , -4/16 , 12/16}, + {-1/32 , -6/16 , 9/16 , 1/32 , -5/16 , 11/16}, + {-1/32 , -5/16 , 9/16 , 1/32 , -4/16 , 10/16}, + -- stick + {-1/32 , 6/16 , 12/16 , 1/32 , 7/16 , 15/16}, -- top + {-1/32 , 5/16 , 11/16 , 1/32 , 7/16 , 12/16}, + {-1/32 , 5/16 , 10/16 , 1/32 , 6/16 , 11/16}, + {-1/32 , 4/16 , 9/16 , 1/32 , 6/16 , 10/16}, + {-1/32 , 3/16 , 8/16 , 1/32 , 5/16 , 9/16}, + {-1/32 , 2/16 , 7/16 , 1/32 , 4/16 , 8/16}, + {-1/32 , 1/16 , 6/16 , 1/32 , 3/16 , 7/16}, + {-1/32 , 0 , 5/16 , 1/32 , 2/16 , 6/16}, + {-1/32 , -2/16 , 4/16 , 1/32 , 1/16 , 5/16}, + {-1/32 , -3/16 , 3/16 , 1/32 , 0 , 4/16}, + {-1/32 , -5/16 , 2/16 , 1/32 , -1/16 , 3/16}, + {-1/32 , -7/16 , 1/16 , 1/32 , -3/16 , 2/16}, + {-1/32 , -1/2 , 0 , 1/32 , -5/16 , 1/16}, -- bottom + } + }, + selection_box = { + type = "fixed", + fixed = { + {-1/16 , -1/2 , 0 , 1/16 , 1/2 , 1 }, + } + }, + groups = { + snappy=3, + flammable=2, + not_in_creative_inventory=1 + }, + sounds = default.node_sound_wood_defaults(), + on_dig = function(pos, node, digger) + if digger:is_player() and digger:get_inventory() then + local meta = minetest.env:get_meta(pos) + local wear_out = meta:get_int("wear") + digger:get_inventory():add_item("main", {name="fishing:pole", count=1, wear=wear_out, metadata=""}) + end + minetest.remove_node(pos) + end, +}) + +end +----------------------------------------------------------------------------------------------- +-- GETTING WORMS +----------------------------------------------------------------------------------------------- +-- get worms from digging in dirt: +if NEW_WORM_SOURCE == false then + +minetest.register_node(":default:dirt", { + description = "Dirt", + tiles = {"default_dirt.png"}, + is_ground_content = true, + groups = {crumbly=3}, + sounds = default.node_sound_dirt_defaults(), + after_dig_node = function (pos, oldnode, oldmetadata, digger) + if math.random(1, 100) < WORM_CHANCE then + local tool_in_use = digger:get_wielded_item():get_name() + if tool_in_use == "" or tool_in_use == "default:dirt" then + minetest.env:add_entity({x = pos.x, y = pos.y+0.4, z = pos.z}, "fishing:bait_worm_entity") + --local inv = digger:get_inventory() + --if inv:room_for_item("main", {name="fishing:bait_worm", count=1, wear=0, metadata=""}) then + --inv:add_item("main", {name="fishing:bait_worm", count=1, wear=0, metadata=""}) + --end + end + end + end, +}) + +else +-- get worms from digging with hoes: + +-- turns nodes with group soil=1 into soil +local function hoe_on_use(itemstack, user, pointed_thing, uses) + local pt = pointed_thing + -- check if pointing at a node + if not pt then + return + end + if pt.type ~= "node" then + return + end + + local under = minetest.get_node(pt.under) + local p = {x=pt.under.x, y=pt.under.y+1, z=pt.under.z} + local above = minetest.get_node(p) + + -- return if any of the nodes is not registered + if not minetest.registered_nodes[under.name] then + return + end + if not minetest.registered_nodes[above.name] then + return + end + + -- check if the node above the pointed thing is air + if above.name ~= "air" then + return + end + + -- check if pointing at dirt + if minetest.get_item_group(under.name, "soil") ~= 1 then + return + end + + -- turn the node into soil, play sound, get worm and wear out item + minetest.set_node(pt.under, {name="farming:soil"}) + minetest.sound_play("default_dig_crumbly", { + pos = pt.under, + gain = 0.5, + }) + --local inv = user:get_inventory() + if math.random(1, 100) < WORM_CHANCE then + minetest.env:add_entity({x=pt.under.x, y=pt.under.y+0.4, z=pt.under.z}, "fishing:bait_worm_entity") + --if inv:room_for_item("main", {name="fishing:bait_worm", count=1, wear=0, metadata=""}) then + --inv:add_item("main", {name="fishing:bait_worm", count=1, wear=0, metadata=""}) + --end + end + itemstack:add_wear(65535/(uses-1)) + return itemstack +end + +-- didn't change the hoes, just here because hoe_on_use is local +minetest.register_tool(":farming:hoe_wood", { + description = "Wooden Hoe", + inventory_image = "farming_tool_woodhoe.png", + on_use = function(itemstack, user, pointed_thing) + return hoe_on_use(itemstack, user, pointed_thing, 30) + end, +}) +minetest.register_tool(":farming:hoe_stone", { + description = "Stone Hoe", + inventory_image = "farming_tool_stonehoe.png", + on_use = function(itemstack, user, pointed_thing) + return hoe_on_use(itemstack, user, pointed_thing, 90) + end, +}) +minetest.register_tool(":farming:hoe_steel", { + description = "Steel Hoe", + inventory_image = "farming_tool_steelhoe.png", + on_use = function(itemstack, user, pointed_thing) + return hoe_on_use(itemstack, user, pointed_thing, 200) + end, +}) +minetest.register_tool(":farming:hoe_bronze", { + description = "Bronze Hoe", + inventory_image = "farming_tool_bronzehoe.png", + on_use = function(itemstack, user, pointed_thing) + return hoe_on_use(itemstack, user, pointed_thing, 220) + end, +}) + +end +----------------------------------------------------------------------------------------------- +print("[Mod] "..title.." ["..version.."] ["..mname.."] Loaded...") +----------------------------------------------------------------------------------------------- diff --git a/mods/fishing/settings.txt b/mods/fishing/settings.txt new file mode 100644 index 0000000..4bbb1a4 --- /dev/null +++ b/mods/fishing/settings.txt @@ -0,0 +1,8 @@ +MESSAGES = true +FISH_CHANCE = 70 +NEW_WORM_SOURCE = false +WORM_CHANCE = 60 +WEAR_OUT = true +BOBBER_CHECK_RADIUS = 5 +BOBBER_COLOR_CHANGE = true +SIMPLE_DECO_FISHING_POLE = true diff --git a/mods/fishing/sounds/SoundLicense.txt b/mods/fishing/sounds/SoundLicense.txt new file mode 100644 index 0000000..1f137b0 --- /dev/null +++ b/mods/fishing/sounds/SoundLicense.txt @@ -0,0 +1,4 @@ +These sounds are used for the Mod for Minetest; Fishing - Mossmanikin's version. +The included sounds are http://creativecommons.org/licenses/by-nc-sa/3.0/ + +--"fishing_bobber1" & "fishing_bobber2" sampled from "01260 water swimming splashing 1.wav", Attribution Noncommercial License, Robinhood76, http://www.freesound.org/people/Robinhood76/sounds/79657/ \ No newline at end of file diff --git a/mods/fishing/sounds/fishing_bobber1.ogg b/mods/fishing/sounds/fishing_bobber1.ogg new file mode 100644 index 0000000000000000000000000000000000000000..6c86a0cb8a47feb1ef0dd498ee8a30f0760900ce GIT binary patch literal 15470 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 literal 0 HcmV?d00001 diff --git a/mods/fishing/sounds/fishing_bobber2.ogg b/mods/fishing/sounds/fishing_bobber2.ogg new file mode 100644 index 0000000000000000000000000000000000000000..932cf0bf38c879ec892534389bd8d07bbf60e4e6 GIT binary patch literal 19963 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%0DH3G?V&w!t<3w!lvI6;>1s;*b z3=DjSK$uZf!>a)(C{^MbQ4*Y=R#Ki=l*$m0n3-3i=jR%tP-d)Ws%L0m@TF)WP*td> zi(`m|e{#YBrc;Ma{wE*4ab;1*!%H1{eODLED(U{eBtgX4<6_4eu{;h}wh5~xm-RQ^ zXgDlseE0xE7qg(q^e0kIb4wVETSLMV&hj5|)4aJ;Xto!lvI6;>1s;*b z3=G^rh1>#+YnAtw0tKZ?Tq8N0kgxl*{3J1lgxAI=rpmYd{nfnxtTeF&rNxCGQ-VxOI16rzf|bGVbUDS nz*U;W#5eu5gvLc4BM}C(vj6L`Ty0;0nJQ2>bZyaD*B`wAlAkxwy;=0c8iYNP%Wo}cJ@EEq-_;GyVOaaO6 cmNz^MAIx~=T(XLP0xe?jboFyt=akR{09#5+CjbBd literal 0 HcmV?d00001 diff --git a/mods/fishing/textures/fishing_bobber_ready.png b/mods/fishing/textures/fishing_bobber_ready.png new file mode 100644 index 0000000000000000000000000000000000000000..2a37b4e9d3fda27d6a21626451d224ac1967f193 GIT binary patch literal 222 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6;>1s;*b z3=DjSK$uZf!>a)(C{^MbQ4*Y=R#Ki=l*$m0n3-3i=jR%tP-d)Ws%L0m@TF)WP*s$t zi(`m|fAWw2|LvKr@))=h58t@5DC5{t!C0A_3MtGDk5m{p#LZw-dFc}5Bg=eZtL&Qo z#v2WXm*!bWI0SMiE!8MGyU@={!Q6C_N~%Ho4Uxz74j3dpb7BL6HtFelh6X@jq%-sC|NFX%|Mu@$ k%gfBA;nV%M{|q}rO{&PQBQlpi0S#yHboFyt=akR{0C=rEQ~&?~ literal 0 HcmV?d00001 diff --git a/mods/fishing/textures/fishing_fish_cooked.png b/mods/fishing/textures/fishing_fish_cooked.png new file mode 100644 index 0000000000000000000000000000000000000000..f572d30e8549dab1b43ca7e6089d66bef550cdbb GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_|S3?zjfeX0ghoCO|{#S9GGLLkg|>2BR0pdfpR zr>`sfLk>1>GoB6&7geB;N`Oy@E07ix6ciQ~784Vbk&sYUR#sP5)(~Tl4{&Tx4eG1S z`~Uy{skk{W!A1o61p{di2u*nv0i+m{yxm>6<*y$(0OTlmx;Tb#$R;Nw#2;M{Vc30e o;pVxC$9kCBzNN9V^<^?L_}^sbUF3Kx1gMt5)78&qol`;+06jZ2$^ZZW literal 0 HcmV?d00001 diff --git a/mods/fishing/textures/fishing_pole.png b/mods/fishing/textures/fishing_pole.png new file mode 100644 index 0000000000000000000000000000000000000000..824675124943e766a909c07a7399f1ee292d27c7 GIT binary patch literal 206 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_`5A|IT2?*ZZ@dAqwXtOvpQmEtl$5zYdS$YKTt zZb1-ctWSxb2oz*5@$_|NzsteN&!^D1_jMvrDB9D-F@)oK@}K|z?U{{E@Lc$}eznSx z14kOzN~X3*=-sbAet_dLW3Xmw_?ZLe&-Y(o3_f}O{P_2ZQ3?=}Ka{Kx-I0UHx3vIVCg!0GAO%4nJ z@ErzW#^d=bQh~}eM74nJ z@ErzW#^d=bQh~}eM7HdQGEO!zeAoUa^ZzUhe(svhedLsT=mc*+ z2E$`%-~RE=F>iJFebgoO_cGA~K0n!v{_gNP`(fJ|u|vo1@q0J^iGElo_P{=3?_AC) v(v?gbl()*Jv(~*iDN=F3{$q^QxjIJ6Vn1bb9@YOq&oOwq`njxgN@xNA2^)qL literal 0 HcmV?d00001 diff --git a/mods/fishing/textures/fishing_pole_front.png b/mods/fishing/textures/fishing_pole_front.png new file mode 100644 index 0000000000000000000000000000000000000000..ec2b8f919d701cbb641a1817c6426a070b9bbb52 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_`5A|IT2?*ZZ@dAqwX{0G4WdzViJif|TqL>4nJ z@ErzW#^d=bQh~}eM7a=MQGLx3@ohykB0@K*g@^&xr%)&!2Y)U}yLpES4V} S_^K6X7=x#)pUXO@geCwBj6Agf literal 0 HcmV?d00001 diff --git a/mods/fishing/textures/fishing_pole_on_use.png b/mods/fishing/textures/fishing_pole_on_use.png new file mode 100644 index 0000000000000000000000000000000000000000..33414b500a0efd4e193824c902906acb02d94687 GIT binary patch literal 151 zcmeAS@N?(olHy`uVBq!ia0vp^%plCc1|-8Yw(bW~Y)RhkE)45IaDJt@3{Zr#z$3Dl zfq`2Pgc<8o;wJ(H*-JcqUD@xlOR#BcFm2Qq01Byix;Tb#Tu=V-|G)j=|Ns9>8vWTS o(DU{6b!Q16Fa5@z%Fp!-=Yz#}nr)rE0jQqA)78&qol`;+07j%O+W-In literal 0 HcmV?d00001 diff --git a/mods/fishing/textures/fishing_pole_simple.png b/mods/fishing/textures/fishing_pole_simple.png new file mode 100644 index 0000000000000000000000000000000000000000..afa5b1927e2338ff948463a853db013b56bb61c7 GIT binary patch literal 303 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6;>1s;*b z3=G`-Aj~-FC-YLEpj3%#L`iUdT1k0gQ7S_~VrE{6o}X)oLYc9ish**M!Iz?iKvknZfwG`Sf98ul;W3%M;b8*v1k*z%qU!C!=?rJwN^W0qV$<6q99@R4&q#DltH<*2qd2R-? z%+=O^(q4rLM!kc{GnfArB`x|@6GcevcSei7sb0*N)44$rjF6*2UngIHZW}5&2 literal 0 HcmV?d00001 diff --git a/mods/fishing/textures/fishing_pole_top.png b/mods/fishing/textures/fishing_pole_top.png new file mode 100644 index 0000000000000000000000000000000000000000..e72a946419cdb3468067b6489e2e38d6c43853a5 GIT binary patch literal 142 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_`5A|IT2?*ZZ@dAqwX{0G4WdzViJif|TqL>4nJ z@ErzW#^d=bQh~}eM82LG$hs-Yl3Q2pqIEHXsPfloP;;CQzKbSlB-{BuV eJQfVLDh!scEIJ#dmOTL~WAJqKb6Mw<&;$U`DkoL| literal 0 HcmV?d00001 diff --git a/mods/fishing/textures/fishing_sushi.png b/mods/fishing/textures/fishing_sushi.png new file mode 100644 index 0000000000000000000000000000000000000000..c64cecaf9680957127cf84bb7c8b9e13f1709418 GIT binary patch literal 590 zcmV-U0N2bPDNB8 zb~7$DE-^4L^m3s900GKLL_t(IPo%15J!iqXUcQ6e$^$K$PTY;YP0i@Uq`yywY%-Z5b8I_FxC z2ZMb9wwJ*y%n(V(kzG^V{kQ2QfVWyBRV{F^_l%3LZ#X~eb9&Mypeu~4)0aR)fb#kh zz3x*!zH9UOLx=s%ItN=TTzos`$N5`MUbna*O%6eZ0M)xI9KL!^e}9+u0|DDy=IGG| z{fFzEeL3Ri_xFTM%^y&|w?VV9L+@pS!(Nlt{VID~t9&}`iWnWb?FNb!^9S5nTc%K} z;4RJ5e6lSdyBzmhbY470wRIwvj_Er7fc#vE{6d**wTP8X5lcIS?dWgqhyWPLI9755 zV7Ba0SzN%$rLl7<)P#X#L{RJ)vLPVCKr==}$au39Yjb4E1&nk8#rXpW##E6#isdFS z9NRxaX|YPK;xSXoqYHgCVG_{7+|p!}K@4G_+ryHUBx%m?2Z5Pe835lswYKWVm z0Ftl>s$rsz;kYpR&V$RyFk^nw1QDls8XBk3wrN@#Qw|L(gI*9i-Q2|38PF!=9X cxaw;E0v%FoFoaZPkpKVy07*qoM6N<$f;Y1T2mk;8 literal 0 HcmV?d00001 diff --git a/mods/fishing/textures/fishing_worm.png b/mods/fishing/textures/fishing_worm.png new file mode 100644 index 0000000000000000000000000000000000000000..9be4dd7b2850b426581712750e33d5a98ff44479 GIT binary patch literal 203 zcmeAS@N?(olHy`uVBq!ia0vp^tRT$61|)m))t&+=wj^(N7l!=|3m7J?S=+q{D8gCb z5n0T@z%2;EjP)t;6M=&4C7!;n?04Cvx!JhhPUBbx6pHY4aSY+Oo_b~@Z&QGX!^O`X zt-Qq%0k;C`o+q#zHd0ZUlCvmVVB3WW7iOd!lvI6;>1s;*b z3=G_YAk0{w5SQ7HGG>Qaoge+ytmRt9 z$j8U$lF4?nFOgy6EXQ@u*Le7uComq7Xv(v`=5R!m?S_ePE`#1#7s&>HV@GC=%wyRM zhO;(GC1@P|I6va71Y3hi6OTiGcFjuRdEy=$MQ=KEZ8AEcz|g(pbmpUXHu6A6F?hQA KxvX self.view_range then + self.object:remove() + end + end + -- move in world + local look_whats_up = function(self) + self.object:set_hp(self.object:get_hp()-self.damage_over_time) -- creature is getting older + if n.name == "air" then -- fall when in air + self.object:moveto({x=pos.x,y=pos.y-0.5,z=pos.z}) + self.object:set_hp(self.object:get_hp()-75) + + --if n.name == "snappy" then -- fall when leaves or similar + elseif minetest.get_item_group(n.name, "snappy") ~= 0 then + self.object:moveto({x=pos.x+(0.001*(math.random(-32, 32))),y=pos.y-(0.001*(math.random(0, 64))),z=pos.z+(0.001*(math.random(-32, 32)))}) + + + elseif string.find(n.name, "default:water") then -- sink when in water + self.object:moveto({x=pos.x,y=pos.y-0.25,z=pos.z}) + self.object:set_hp(self.object:get_hp()-37) + + elseif minetest.get_item_group(n.name, "soil") ~= 0 then + if minetest.get_item_group(minetest.env:get_node({x=pos.x,y=pos.y-0.1,z=pos.z}).name, "soil") == 0 and self.object:get_hp() > 200 then + self.object:set_hp(199) + elseif self.object:get_hp() > 200 then -- leave dirt to see whats going on + self.object:moveto({x=pos.x+(0.001*(math.random(-2, 2))),y=pos.y+0.003,z=pos.z+(0.001*(math.random(-2, 2)))}) + elseif self.object:get_hp() < 199 then -- no rain here, let's get outa here + self.object:moveto({x=pos.x+(0.001*(math.random(-2, 2))),y=pos.y-0.001,z=pos.z+(0.001*(math.random(-2, 2)))}) + elseif self.object:get_hp() == 0 then + self.object:remove() + end + else -- check if there's dirt anywhere (not finished) + local check_group = minetest.get_item_group + local goal_01 = check_group(minetest.env:get_node({x = pos.x + 1, y = pos.y-0.4, z = pos.z }).name, "soil") + local goal_02 = check_group(minetest.env:get_node({x = pos.x, y = pos.y-0.4, z = pos.z + 1}).name, "soil") + local goal_03 = check_group(minetest.env:get_node({x = pos.x - 1, y = pos.y-0.4, z = pos.z }).name, "soil") + local goal_04 = check_group(minetest.env:get_node({x = pos.x, y = pos.y-0.4, z = pos.z - 1}).name, "soil") + + local goal_1a = check_group(minetest.env:get_node({x = pos.x + 1, y = pos.y+0.6, z = pos.z }).name, "soil") + local goal_2a = check_group(minetest.env:get_node({x = pos.x, y = pos.y+0.6, z = pos.z + 1}).name, "soil") + local goal_3a = check_group(minetest.env:get_node({x = pos.x - 1, y = pos.y+0.6, z = pos.z }).name, "soil") + local goal_4a = check_group(minetest.env:get_node({x = pos.x, y = pos.y+0.6, z = pos.z - 1}).name, "soil") + -- if there's dirt nearby, go there + if goal_01 ~= 0 or goal_1a ~= 0 then + self.object:moveto({x=pos.x+0.002,y=pos.y,z=pos.z+(0.001*(math.random(-2, 2)))}) + elseif goal_02 ~= 0 or goal_2a ~= 0 then + self.object:moveto({x=pos.x+(0.001*(math.random(-2, 2))),y=pos.y,z=pos.z+0.002}) + elseif goal_03 ~= 0 or goal_3a ~= 0 then + self.object:moveto({x=pos.x-0.002,y=pos.y,z=pos.z+(0.001*(math.random(-2, 2)))}) + elseif goal_04 ~= 0 or goal_4a ~= 0 then + self.object:moveto({x=pos.x+(0.001*(math.random(-2, 2))),y=pos.y,z=pos.z-0.002}) + else -- I'm lost, no dirt + self.object:moveto({x=pos.x+(0.001*(math.random(-8, 8))),y=pos.y,z=pos.z+(0.001*(math.random(-8, 8)))}) + end + end + end + look_whats_up(self) + end, +}) \ No newline at end of file diff --git a/mods/irc/.gitignore b/mods/irc/.gitignore new file mode 100644 index 0000000..5236e1e --- /dev/null +++ b/mods/irc/.gitignore @@ -0,0 +1,2 @@ +*~ + diff --git a/mods/irc/.gitmodules b/mods/irc/.gitmodules new file mode 100644 index 0000000..e56fee3 --- /dev/null +++ b/mods/irc/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/LuaIRC"] + path = irc + url = https://github.com/ShadowNinja/LuaIRC.git diff --git a/mods/irc/.luacheckrc b/mods/irc/.luacheckrc new file mode 100644 index 0000000..7453628 --- /dev/null +++ b/mods/irc/.luacheckrc @@ -0,0 +1,14 @@ + +allow_defined_top = true + +read_globals = { + "minetest", +} + +exclude_files = { + "irc/*", +} + +globals = { + "irc", +} diff --git a/mods/irc/API.md b/mods/irc/API.md new file mode 100644 index 0000000..5de2c04 --- /dev/null +++ b/mods/irc/API.md @@ -0,0 +1,90 @@ +IRC Mod API +=========== + +This file documents the Minetest IRC mod API. + +Basics +------ + +In order to allow your mod to interface with this mod, you must add `irc` +to your mod's `depends.txt` file. + + +Reference +--------- + +irc.say([name,] message) +Sends to either the channel (if is nil or not specified), +or to the given user (if is specified). +Example: + irc.say("Hello, Channel!") + irc.say("john1234", "How are you?") + +irc.register_bot_command(name, cmdDef) + Registers a new bot command named . + When an user sends a private message to the bot with the command name, the + command's function is called. + Here's the format of a command definition (): + cmdDef = { + params = " ...", -- A description of the command's parameters + description = "My command", -- A description of what the command does. (one-liner) + func = function(user, args) + -- This function gets called when the command is invoked. + -- is a user table for the user that ran the command. + -- (See the LuaIRC documentation for details.) + -- It contains fields such as 'nick' and 'ident' + -- is a string of arguments to the command (may be "") + -- This function should return boolean success and a message. + end, + }; + Example: + irc.register_bot_command("hello", { + params = "", + description = "Greet user", + func = function(user, param) + return true, "Hello!" + end, + }); + +irc.joined_players[name] + This table holds the players who are currently on the channel (may be less + than the players in the game). It is modified by the /part and /join chat + commands. + Example: + if irc.joined_players["joe"] then + -- Joe is talking on IRC + end + +irc.register_hook(name, func) + Registers a function to be called when an event happens. is the name + of the event, and is the function to be called. See HOOKS below + for more information + Example: + irc.register_hook("OnSend", function(line) + print("SEND: "..line) + end) + +This mod also supplies some utility functions: + +string.expandvars(string, vars) + Expands all occurrences of the pattern "$(varname)" with the value of + 'varname' in the table. Variable names not found on the table + are left verbatim in the string. + Example: + local tpl = "$(foo) $(bar) $(baz)" + local s = tpl:expandvars({foo=1, bar="Hello"}) + assert(s == "1 Hello $(baz)") + +In addition, all the configuration options decribed in `README.txt` are +available to other mods, though they should be considered read-only. Do +not modify these settings at runtime or you might crash the server! + + +Hooks +----- + +The `irc.register_hook` function can register functions to be called +when some events happen. The events supported are the same as the LuaIRC +ones with a few added (mostly for internal use). +See src/LuaIRC/doc/irc.luadoc for more information. + diff --git a/mods/irc/LICENSE.txt b/mods/irc/LICENSE.txt new file mode 100644 index 0000000..b184032 --- /dev/null +++ b/mods/irc/LICENSE.txt @@ -0,0 +1,22 @@ +Copyright (c) 2013, Diego Martinez (kaeza) +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. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER OR 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/irc/README.md b/mods/irc/README.md new file mode 100644 index 0000000..99e0dcc --- /dev/null +++ b/mods/irc/README.md @@ -0,0 +1,181 @@ + +IRC Mod for Minetest +==================== + +Introduction +------------ + +This mod is just a glue between IRC and Minetest. It provides two-way + communication between the in-game chat, and an arbitrary IRC channel. + +The forum topic is [here][forum]. + +[forum]: https://forum.minetest.net/viewtopic.php?f=11&t=3905 + + +Installing +---------- + +Quick one line install for Linux: + + cd && git clone --recursive https://github.com/minetest-mods/irc.git + +Please change `` to fit your installation of Minetest. +For more information, see [the wiki][wiki]. + +The IRC mod's git repository uses submodules, therefore you will have to run +`git submodule init` when first installing the mod (unless you used +`--recursive` as above), and `git submodule update` every time that a submodule +is updated. These steps can be combined into `git submodule update --init`. + +You'll need to install LuaSocket. You can do so with your package manager on +many distributions, for example: + + # # On Arch Linux: + # pacman -S lua51-socket + # # On Debian/Ubuntu: + # # Debian/Ubuntu's LuaSocket packages are broken, so use LuaRocks. + # apt-get install luarocks + # luarocks install luasocket + +You will also need to add IRC to your trusted mods if you haven't disabled mod +security. Here's an example configuration line: + + secure.trusted_mods = irc + +[wiki]: https://wiki.minetest.net/Installing_mods + + +Settings +-------- + +All settings are changed in `minetest.conf`. If any of these settings +are not set, the default value is used. + +* `irc.server` (string): + The address of the IRC server to connect to. + +* `irc.channel` (string): + The IRC channel to join. + +* `irc.interval` (number, default 2.0): + This prevents the server from flooding. It should be at + least 2.0 but can be higher. After four messages this much + time must pass between folowing messages. + +* `irc.nick` (string): + Nickname the server uses when it connects to IRC. + +* `irc.password` (string, default nil): + Password to use when connecting to the server. + +* `irc.NSPass` (string, default nil): + NickServ password. Don't set this if you use SASL authentication. + +* `irc.sasl.pass` (string, default nil): + SASL password, same as nickserv password. + You should use this instead of NickServ authentication + if the server supports it. + +* `irc.sasl.user` (string, default `irc.nick`): + The SASL username. This should normaly be set to your + NickServ account name. + +* `irc.debug` (boolean, default false): + Whether to output debug information. + +* `irc.disable_auto_connect` (boolean, default false): + If false, the bot is connected by default. If true, a player with + the 'irc_admin' privilege has to use the `/irc_connect` command to + connect to the server. + +* `irc.disable_auto_join` (boolean, default false): + If false, players join the channel automatically upon entering the + game. If true, each user must manually use the `/join` command to + join the channel. In any case, the players may use the `/part` + command to opt-out of being in the channel. + +* `irc.send_join_part` (boolean, default true): + Determines whether to send player join and part messages to the channel. + + +Usage +----- + +Once the game is connected to the IRC channel, chatting in-game will send +messages to the channel, and will be visible by anyone. Also, messages sent +to the channel will be visible in-game. + +Messages that begin with `[off]` from in-game or IRC are not sent to the +other side. + +This mod also adds a few chat commands: + +* `/irc_msg `: + Send a private message to a IRC user. + +* `/join`: + Join the IRC chat. + +* `/part`: + Part the IRC chat. + +* `/irc_connect`: + Connect the bot manually to the IRC network. + +* `/irc_disconnect`: + Disconnect the bot manually from the IRC network (this does not + shutdown the game). + +* `/irc_reconnect`: + Equivalent to `/irc_disconnect` followed by `/irc_connect`. + +You can also send private messages from IRC to in-game players +by sending a private message to the bot (set with the `irc.nick` +option above), in the following format: + + @playername message + +For example, if there's a player named `mtuser`, you can send him/her +a private message from IRC with: + + /msg server_nick @mtuser Hello! + +The bot also supports some basic commands, which are invoked by saying +the bot name followed by either a colon or a comma and the command, or +sending a private message to it. For example: `ServerBot: help whereis`. + +* `help []`: + Prints help about a command, or a list of supported commands if no + command is given. + +* `uptime`: + Prints the server's running time. + +* `whereis `: + Prints the coordinates of the given player. + +* `players`: + Lists players currently in the server. + + +Thanks +------ + +I'd like to thank the users who supported this mod both on the Minetest +Forums and on the `#minetest` channel. In no particular order: + +0gb.us, ShadowNinja, Shaun/kizeren, RAPHAEL, DARGON, Calinou, Exio, +vortexlabs/mrtux, marveidemanis, marktraceur, jmf/john\_minetest, +sdzen/Muadtralk, VanessaE, PilzAdam, sfan5, celeron55, KikaRz, +OldCoder, RealBadAngel, and all the people who commented in the +forum topic. Thanks to you all! + + +License +------- + +See `LICENSE.txt` for details. + +The files in the `irc` directory are part of the LuaIRC project. +See `irc/LICENSE.txt` for details. diff --git a/mods/irc/botcmds.lua b/mods/irc/botcmds.lua new file mode 100644 index 0000000..ba0d025 --- /dev/null +++ b/mods/irc/botcmds.lua @@ -0,0 +1,175 @@ + +irc.bot_commands = {} + +-- From RFC1459: +-- "Because of IRC’s scandanavian origin, the characters {}| are +-- considered to be the lower case equivalents of the characters +-- []\, respectively." +local irctolower = { ["["]="{", ["\\"]="|", ["]"]="}" } + +local function irclower(s) + return (s:lower():gsub("[%[%]\\]", irctolower)) +end + +local function nickequals(nick1, nick2) + return irclower(nick1) == irclower(nick2) +end + +function irc.check_botcmd(msg) + local prefix = irc.config.command_prefix + local nick = irc.conn.nick + local text = msg.args[2] + local nickpart = text:sub(1, #nick) + local suffix = text:sub(#nick+1, #nick+2) + + -- First check for a nick prefix + if nickequals(nickpart, nick) + and (suffix == ": " or suffix == ", ") then + irc.bot_command(msg, text:sub(#nick + 3)) + return true + -- Then check for the configured prefix + elseif prefix and text:sub(1, #prefix):lower() == prefix:lower() then + irc.bot_command(msg, text:sub(#prefix + 1)) + return true + end + return false +end + + +function irc.bot_command(msg, text) + -- Remove leading whitespace + text = text:match("^%s*(.*)") + if text:sub(1, 1) == "@" then + local _, _, player_to, message = text:find("^.([^%s]+)%s(.+)$") + if not player_to then + return + elseif not minetest.get_player_by_name(player_to) then + irc.reply("User '"..player_to.."' is not in the game.") + return + elseif not irc.joined_players[player_to] then + irc.reply("User '"..player_to.."' is not using IRC.") + return + end + minetest.chat_send_player(player_to, + "PM from "..msg.user.nick.."@IRC: "..message, false) + irc.reply("Message sent!") + return + end + local pos = text:find(" ", 1, true) + local cmd, args + if pos then + cmd = text:sub(1, pos - 1) + args = text:sub(pos + 1) + else + cmd = text + args = "" + end + + if not irc.bot_commands[cmd] then + irc.reply("Unknown command '"..cmd.."'. Try 'help'." + .." Or use @playername to send a private message") + return + end + + local _, message = irc.bot_commands[cmd].func(msg.user, args) + if message then + irc.reply(message) + end +end + + +function irc.register_bot_command(name, def) + if (not def.func) or (type(def.func) ~= "function") then + error("Erroneous bot command definition. def.func missing.", 2) + elseif name:sub(1, 1) == "@" then + error("Erroneous bot command name. Command name begins with '@'.", 2) + end + irc.bot_commands[name] = def +end + + +irc.register_bot_command("help", { + params = "", + description = "Get help about a command", + func = function(_, args) + if args == "" then + local cmdlist = { } + for name in pairs(irc.bot_commands) do + cmdlist[#cmdlist+1] = name + end + return true, "Available commands: "..table.concat(cmdlist, ", ") + .." -- Use 'help ' to get" + .." help about a specific command." + end + + local cmd = irc.bot_commands[args] + if not cmd then + return false, "Unknown command '"..args.."'." + end + + return true, ("Usage: %s%s %s -- %s"):format( + irc.config.command_prefix or "", + args, + cmd.params or "", + cmd.description or "") + end +}) + + +irc.register_bot_command("list", { + params = "", + description = "List available commands.", + func = function() + return false, "The `list` command has been merged into `help`." + .." Use `help` with no arguments to get a list." + end +}) + + +irc.register_bot_command("whereis", { + params = "", + description = "Tell the location of ", + func = function(_, args) + if args == "" then + return false, "Player name required." + end + local player = minetest.get_player_by_name(args) + if not player then + return false, "There is no player named '"..args.."'" + end + local fmt = "Player %s is at (%.2f,%.2f,%.2f)" + local pos = player:getpos() + return true, fmt:format(args, pos.x, pos.y, pos.z) + end +}) + + +local starttime = os.time() +irc.register_bot_command("uptime", { + description = "Tell how much time the server has been up", + func = function() + local cur_time = os.time() + local diff = os.difftime(cur_time, starttime) + local fmt = "Server has been running for %d:%02d:%02d" + return true, fmt:format( + math.floor(diff / 60 / 60), + math.floor(diff / 60) % 60, + math.floor(diff) % 60 + ) + end +}) + + +irc.register_bot_command("players", { + description = "List the players on the server", + func = function() + local players = minetest.get_connected_players() + local names = {} + for _, player in pairs(players) do + table.insert(names, player:get_player_name()) + end + return true, "Connected players: " + ..table.concat(names, ", ") + end +}) + diff --git a/mods/irc/callback.lua b/mods/irc/callback.lua new file mode 100644 index 0000000..29667ba --- /dev/null +++ b/mods/irc/callback.lua @@ -0,0 +1,41 @@ +-- This file is licensed under the terms of the BSD 2-clause license. +-- See LICENSE.txt for details. + + +minetest.register_on_joinplayer(function(player) + local name = player:get_player_name() + if irc.connected and irc.config.send_join_part then + irc.say("*** "..name.." joined the game") + end +end) + + +minetest.register_on_leaveplayer(function(player, timed_out) + local name = player:get_player_name() + if irc.connected and irc.config.send_join_part then + irc.say("*** "..name.." left the game".. + (timed_out and " (Timed out)" or "")) + end +end) + + +minetest.register_on_chat_message(function(name, message) + if not irc.connected + or message:sub(1, 1) == "/" + or message:sub(1, 5) == "[off]" + or not irc.joined_players[name] + or (not minetest.check_player_privs(name, {shout=true})) then + return + end + local nl = message:find("\n", 1, true) + if nl then + message = message:sub(1, nl - 1) + end + irc.say(irc.playerMessage(name, core.strip_colors(message))) +end) + + +minetest.register_on_shutdown(function() + irc.disconnect("Game shutting down.") +end) + diff --git a/mods/irc/chatcmds.lua b/mods/irc/chatcmds.lua new file mode 100644 index 0000000..34283d7 --- /dev/null +++ b/mods/irc/chatcmds.lua @@ -0,0 +1,134 @@ +-- This file is licensed under the terms of the BSD 2-clause license. +-- See LICENSE.txt for details. + +-- Note: This file does NOT conatin every chat command, only general ones. +-- Feature-specific commands (like /join) are in their own files. + + +minetest.register_chatcommand("irc_msg", { + params = " ", + description = "Send a private message to an IRC user", + privs = {shout=true}, + func = function(name, param) + if not irc.connected then + return false, "Not connected to IRC. Use /irc_connect to connect." + end + local found, _, toname, message = param:find("^([^%s]+)%s(.+)") + if not found then + return false, "Invalid usage, see /help irc_msg." + end + local toname_l = toname:lower() + local validNick = false + local hint = "They have to be in the channel" + for nick in pairs(irc.conn.channels[irc.config.channel].users) do + if nick:lower() == toname_l then + validNick = true + break + end + end + if toname_l:find("serv$") or toname_l:find("bot$") then + hint = "it looks like a bot or service" + validNick = false + end + if not validNick then + return false, "You can not message that user. ("..hint..")" + end + irc.say(toname, irc.playerMessage(name, message)) + return true, "Message sent!" + end +}) + + +minetest.register_chatcommand("irc_names", { + params = "", + description = "List the users in IRC.", + func = function() + if not irc.connected then + return false, "Not connected to IRC. Use /irc_connect to connect." + end + local users = { } + for nick in pairs(irc.conn.channels[irc.config.channel].users) do + table.insert(users, nick) + end + return true, "Users in IRC: "..table.concat(users, ", ") + end +}) + + +minetest.register_chatcommand("irc_connect", { + description = "Connect to the IRC server.", + privs = {irc_admin=true}, + func = function(name) + if irc.connected then + return false, "You are already connected to IRC." + end + minetest.chat_send_player(name, "IRC: Connecting...") + irc.connect() + end +}) + + +minetest.register_chatcommand("irc_disconnect", { + params = "[message]", + description = "Disconnect from the IRC server.", + privs = {irc_admin=true}, + func = function(name, param) + if not irc.connected then + return false, "Not connected to IRC. Use /irc_connect to connect." + end + if param == "" then + param = "Manual disconnect by "..name + end + irc.disconnect(param) + end +}) + + +minetest.register_chatcommand("irc_reconnect", { + description = "Reconnect to the IRC server.", + privs = {irc_admin=true}, + func = function(name) + if not irc.connected then + return false, "Not connected to IRC. Use /irc_connect to connect." + end + minetest.chat_send_player(name, "IRC: Reconnecting...") + irc.disconnect("Reconnecting...") + irc.connect() + end +}) + + +minetest.register_chatcommand("irc_quote", { + params = "", + description = "Send a raw command to the IRC server.", + privs = {irc_admin=true}, + func = function(name, param) + if not irc.connected then + return false, "Not connected to IRC. Use /irc_connect to connect." + end + irc.queue(param) + minetest.chat_send_player(name, "Command sent!") + end +}) + + +local oldme = minetest.chatcommands["me"].func +-- luacheck: ignore +minetest.chatcommands["me"].func = function(name, param, ...) + irc.say(("* %s %s"):format(name, param)) + return oldme(name, param, ...) +end + +if irc.config.send_kicks and minetest.chatcommands["kick"] then + local oldkick = minetest.chatcommands["kick"].func + -- luacheck: ignore + minetest.chatcommands["kick"].func = function(name, param, ...) + local plname, reason = param:match("^(%S+)%s*(.*)$") + if not plname then + return false, "Usage: /kick player [reason]" + end + irc.say(("*** Kicked %s.%s"):format(name, + reason~="" and " Reason: "..reason or "")) + return oldkick(name, param, ...) + end +end diff --git a/mods/irc/config.lua b/mods/irc/config.lua new file mode 100644 index 0000000..c629e47 --- /dev/null +++ b/mods/irc/config.lua @@ -0,0 +1,56 @@ +-- This file is licensed under the terms of the BSD 2-clause license. +-- See LICENSE.txt for details. + + +irc.config = {} + +local function setting(stype, name, default, required) + local value + if stype == "bool" then + value = minetest.setting_getbool("irc."..name) + elseif stype == "string" then + value = minetest.setting_get("irc."..name) + elseif stype == "number" then + value = tonumber(minetest.setting_get("irc."..name)) + end + if value == nil then + if required then + error("Required configuration option irc.".. + name.." missing.") + end + value = default + end + irc.config[name] = value +end + +------------------------- +-- BASIC USER SETTINGS -- +------------------------- + +setting("string", "nick", nil, true) -- Nickname +setting("string", "server", nil, true) -- Server address to connect to +setting("number", "port", 6667) -- Server port to connect to +setting("string", "NSPass") -- NickServ password +setting("string", "sasl.user", irc.config.nick) -- SASL username +setting("string", "username", "Minetest") -- Username/ident +setting("string", "realname", "Minetest") -- Real name/GECOS +setting("string", "sasl.pass") -- SASL password +setting("string", "channel", nil, true) -- Channel to join +setting("string", "key") -- Key for the channel +setting("bool", "send_join_part", true) -- Whether to send player join and part messages to the channel +setting("bool", "send_kicks", false) -- Whether to send player kicked messages to the channel + +----------------------- +-- ADVANCED SETTINGS -- +----------------------- + +setting("string", "password") -- Server password +setting("bool", "secure", false) -- Enable a TLS connection, requires LuaSEC +setting("number", "timeout", 60) -- Underlying socket timeout in seconds. +setting("number", "reconnect", 600) -- Time between reconnection attempts, in seconds. +setting("string", "command_prefix") -- Prefix to use for bot commands +setting("bool", "debug", false) -- Enable debug output +setting("bool", "enable_player_part", true) -- Whether to enable players joining and parting the channel +setting("bool", "auto_join", true) -- Whether to automatically show players in the channel when they join +setting("bool", "auto_connect", true) -- Whether to automatically connect to the server on mod load + diff --git a/mods/irc/description.txt b/mods/irc/description.txt new file mode 100644 index 0000000..58ba37a --- /dev/null +++ b/mods/irc/description.txt @@ -0,0 +1,4 @@ +This mod is just a glue between IRC and Minetest. + +It provides two-way communication between the +in-game chat, and an arbitrary IRC channel. diff --git a/mods/irc/hooks.lua b/mods/irc/hooks.lua new file mode 100644 index 0000000..0ac3597 --- /dev/null +++ b/mods/irc/hooks.lua @@ -0,0 +1,258 @@ +-- This file is licensed under the terms of the BSD 2-clause license. +-- See LICENSE.txt for details. + +local ie = ... + +-- MIME is part of LuaSocket +local b64e = ie.require("mime").b64 + +irc.hooks = {} +irc.registered_hooks = {} + + +local stripped_chars = "[\2\31]" + +local function normalize(text) + -- Strip colors + text = text:gsub("\3[0-9][0-9,]*", "") + + return text:gsub(stripped_chars, "") +end + + +function irc.doHook(conn) + for name, hook in pairs(irc.registered_hooks) do + for _, func in pairs(hook) do + conn:hook(name, func) + end + end +end + + +function irc.register_hook(name, func) + irc.registered_hooks[name] = irc.registered_hooks[name] or {} + table.insert(irc.registered_hooks[name], func) +end + + +function irc.hooks.raw(line) + if irc.config.debug then + print("RECV: "..line) + end +end + + +function irc.hooks.send(line) + if irc.config.debug then + print("SEND: "..line) + end +end + + +function irc.hooks.chat(msg) + local channel, text = msg.args[1], msg.args[2] + if text:sub(1, 1) == string.char(1) then + irc.conn:invoke("OnCTCP", msg) + return + end + + if channel == irc.conn.nick then + irc.last_from = msg.user.nick + irc.conn:invoke("PrivateMessage", msg) + else + irc.last_from = channel + irc.conn:invoke("OnChannelChat", msg) + end +end + + +local function get_core_version() + local status = minetest.get_server_status() + local start_pos = select(2, status:find("version=", 1, true)) + local end_pos = status:find(",", start_pos, true) + return status:sub(start_pos + 1, end_pos - 1) +end + + +function irc.hooks.ctcp(msg) + local text = msg.args[2]:sub(2, -2) -- Remove ^C + local args = text:split(' ') + local command = args[1]:upper() + + local function reply(s) + irc.queue(irc.msgs.notice(msg.user.nick, + ("\1%s %s\1"):format(command, s))) + end + + if command == "ACTION" and msg.args[1] == irc.config.channel then + local action = text:sub(8, -1) + irc.sendLocal(("* %s@IRC %s"):format(msg.user.nick, action)) + elseif command == "VERSION" then + reply(("Minetest version %s, IRC mod version %s.") + :format(get_core_version(), irc.version)) + elseif command == "PING" then + reply(args[2]) + elseif command == "TIME" then + reply(os.date()) + end +end + + +function irc.hooks.channelChat(msg) + local text = normalize(msg.args[2]) + + irc.check_botcmd(msg) + + -- Don't let a user impersonate someone else by using the nick "IRC" + local fake = msg.user.nick:lower():match("^[il|]rc$") + if fake then + irc.sendLocal("<"..msg.user.nick.."@IRC> "..text) + return + end + + -- Support multiple servers in a channel better by converting: + -- " message" into " message" + -- " *** player joined/left the game" into "*** player joined/left server" + -- and " * player orders a pizza" into "* player@server orders a pizza" + local foundchat, _, chatnick, chatmessage = + text:find("^<([^>]+)> (.*)$") + local foundjoin, _, joinnick = + text:find("^%*%*%* ([^%s]+) joined the game$") + local foundleave, _, leavenick = + text:find("^%*%*%* ([^%s]+) left the game$") + local foundaction, _, actionnick, actionmessage = + text:find("^%* ([^%s]+) (.*)$") + + if text:sub(1, 5) == "[off]" then + return + elseif foundchat then + irc.sendLocal(("<%s@%s> %s") + :format(chatnick, msg.user.nick, chatmessage)) + elseif foundjoin then + irc.sendLocal(("*** %s joined %s") + :format(joinnick, msg.user.nick)) + elseif foundleave then + irc.sendLocal(("*** %s left %s") + :format(leavenick, msg.user.nick)) + elseif foundaction then + irc.sendLocal(("* %s@%s %s") + :format(actionnick, msg.user.nick, actionmessage)) + else + irc.sendLocal(("<%s@IRC> %s"):format(msg.user.nick, text)) + end +end + + +function irc.hooks.pm(msg) + -- Trim prefix if it is found + local text = msg.args[2] + local prefix = irc.config.command_prefix + if prefix and text:sub(1, #prefix) == prefix then + text = text:sub(#prefix + 1) + end + irc.bot_command(msg, text) +end + + +function irc.hooks.kick(channel, target, prefix, reason) + if target == irc.conn.nick then + minetest.chat_send_all("IRC: kicked from "..channel.." by "..prefix.nick..".") + irc.disconnect("Kicked") + else + irc.sendLocal(("-!- %s was kicked from %s by %s [%s]") + :format(target, channel, prefix.nick, reason)) + end +end + + +function irc.hooks.notice(user, target, message) + if user.nick and target == irc.config.channel then + irc.sendLocal("-"..user.nick.."@IRC- "..message) + end +end + + +function irc.hooks.mode(user, target, modes, ...) + local by = "" + if user.nick then + by = " by "..user.nick + end + local options = "" + if select("#", ...) > 0 then + options = " " + end + options = options .. table.concat({...}, " ") + minetest.chat_send_all(("-!- mode/%s [%s%s]%s") + :format(target, modes, options, by)) +end + + +function irc.hooks.nick(user, newNick) + irc.sendLocal(("-!- %s is now known as %s") + :format(user.nick, newNick)) +end + + +function irc.hooks.join(user, channel) + irc.sendLocal(("-!- %s joined %s") + :format(user.nick, channel)) +end + + +function irc.hooks.part(user, channel, reason) + reason = reason or "" + irc.sendLocal(("-!- %s has left %s [%s]") + :format(user.nick, channel, reason)) +end + + +function irc.hooks.quit(user, reason) + irc.sendLocal(("-!- %s has quit [%s]") + :format(user.nick, reason)) +end + + +function irc.hooks.disconnect(_, isError) + irc.connected = false + if isError then + minetest.log("error", "IRC: Error: Disconnected, reconnecting in one minute.") + minetest.chat_send_all("IRC: Error: Disconnected, reconnecting in one minute.") + minetest.after(60, irc.connect, irc) + else + minetest.log("action", "IRC: Disconnected.") + minetest.chat_send_all("IRC: Disconnected.") + end +end + + +function irc.hooks.preregister(conn) + if not (irc.config["sasl.user"] and irc.config["sasl.pass"]) then return end + local authString = b64e( + ("%s\x00%s\x00%s"):format( + irc.config["sasl.user"], + irc.config["sasl.user"], + irc.config["sasl.pass"]) + ) + conn:send("CAP REQ sasl") + conn:send("AUTHENTICATE PLAIN") + conn:send("AUTHENTICATE "..authString) + conn:send("CAP END") +end + + +irc.register_hook("PreRegister", irc.hooks.preregister) +irc.register_hook("OnRaw", irc.hooks.raw) +irc.register_hook("OnSend", irc.hooks.send) +irc.register_hook("DoPrivmsg", irc.hooks.chat) +irc.register_hook("OnPart", irc.hooks.part) +irc.register_hook("OnKick", irc.hooks.kick) +irc.register_hook("OnJoin", irc.hooks.join) +irc.register_hook("OnQuit", irc.hooks.quit) +irc.register_hook("NickChange", irc.hooks.nick) +irc.register_hook("OnCTCP", irc.hooks.ctcp) +irc.register_hook("PrivateMessage", irc.hooks.pm) +irc.register_hook("OnNotice", irc.hooks.notice) +irc.register_hook("OnChannelChat", irc.hooks.channelChat) +irc.register_hook("OnModeChange", irc.hooks.mode) +irc.register_hook("OnDisconnect", irc.hooks.disconnect) + diff --git a/mods/irc/init.lua b/mods/irc/init.lua new file mode 100644 index 0000000..67dec28 --- /dev/null +++ b/mods/irc/init.lua @@ -0,0 +1,218 @@ +-- This file is licensed under the terms of the BSD 2-clause license. +-- See LICENSE.txt for details. + +local modpath = minetest.get_modpath(minetest.get_current_modname()) + +-- Handle mod security if needed +local ie, req_ie = _G, minetest.request_insecure_environment +if req_ie then ie = req_ie() end +if not ie then + error("The IRC mod requires access to insecure functions in order ".. + "to work. Please add the irc mod to your secure.trusted_mods ".. + "setting or disable the irc mod.") +end + +ie.package.path = + -- To find LuaIRC's init.lua + modpath.."/?/init.lua;" + -- For LuaIRC to find its files + ..modpath.."/?.lua;" + ..ie.package.path + +-- The build of Lua that Minetest comes with only looks for libraries under +-- /usr/local/share and /usr/local/lib but LuaSocket is often installed under +-- /usr/share and /usr/lib. +if not rawget(_G, "jit") and package.config:sub(1, 1) == "/" then + ie.package.path = ie.package.path.. + ";/usr/share/lua/5.1/?.lua".. + ";/usr/share/lua/5.1/?/init.lua" + ie.package.cpath = ie.package.cpath.. + ";/usr/lib/lua/5.1/?.so" +end + +-- Temporarily set require so that LuaIRC can access it +local old_require = require +require = ie.require + +-- Silence warnings about `module` in `ltn12`. +local old_module = rawget(_G, "module") +rawset(_G, "module", ie.module) + +local lib = ie.require("irc") + +irc = { + version = "0.2.0", + connected = false, + cur_time = 0, + message_buffer = {}, + recent_message_count = 0, + joined_players = {}, + modpath = modpath, + lib = lib, +} + +-- Compatibility +rawset(_G, "mt_irc", irc) + +local getinfo = debug.getinfo +local warned = { } + +local function warn_deprecated(k) + local info = getinfo(3) + local loc = info.source..":"..info.currentline + if warned[loc] then return end + warned[loc] = true + print("COLON: "..tostring(k)) + minetest.log("warning", "Deprecated use of colon notation when calling" + .." method `"..tostring(k).."` at "..loc) +end + +-- This is a hack. +setmetatable(irc, { + __newindex = function(t, k, v) + if type(v) == "function" then + local f = v + v = function(me, ...) + if rawequal(me, t) then + warn_deprecated(k) + return f(...) + else + return f(me, ...) + end + end + end + rawset(t, k, v) + end, +}) + +dofile(modpath.."/config.lua") +dofile(modpath.."/messages.lua") +loadfile(modpath.."/hooks.lua")(ie) +dofile(modpath.."/callback.lua") +dofile(modpath.."/chatcmds.lua") +dofile(modpath.."/botcmds.lua") + +-- Restore old (safe) functions +require = old_require +rawset(_G, "module", old_module) + +if irc.config.enable_player_part then + dofile(modpath.."/player_part.lua") +else + setmetatable(irc.joined_players, {__index = function() return true end}) +end + +minetest.register_privilege("irc_admin", { + description = "Allow IRC administrative tasks to be performed.", + give_to_singleplayer = true +}) + +local stepnum = 0 + +minetest.register_globalstep(function(dtime) return irc.step(dtime) end) + +function irc.step() + if stepnum == 3 then + if irc.config.auto_connect then + irc.connect() + end + end + stepnum = stepnum + 1 + + if not irc.connected then return end + + -- Hooks will manage incoming messages and errors + local good, err = xpcall(function() irc.conn:think() end, debug.traceback) + if not good then + print(err) + return + end +end + + +function irc.connect() + if irc.connected then + minetest.log("error", "IRC: Ignoring attempt to connect when already connected.") + return + end + irc.conn = irc.lib.new({ + nick = irc.config.nick, + username = irc.config.username, + realname = irc.config.realname, + }) + irc.doHook(irc.conn) + + -- We need to swap the `require` function again since + -- LuaIRC `require`s `ssl` if `irc.secure` is true. + old_require = require + require = ie.require + + local good, message = pcall(function() + irc.conn:connect({ + host = irc.config.server, + port = irc.config.port, + password = irc.config.password, + timeout = irc.config.timeout, + reconnect = irc.config.reconnect, + secure = irc.config.secure + }) + end) + + require = old_require + + if not good then + minetest.log("error", ("IRC: Connection error: %s: %s -- Reconnecting in %d seconds...") + :format(irc.config.server, message, irc.config.reconnect)) + minetest.after(irc.config.reconnect, function() irc.connect() end) + return + end + + if irc.config.NSPass then + irc.conn:queue(irc.msgs.privmsg( + "NickServ", "IDENTIFY "..irc.config.NSPass)) + end + + irc.conn:join(irc.config.channel, irc.config.key) + irc.connected = true + minetest.log("action", "IRC: Connected!") + minetest.chat_send_all("IRC: Connected!") +end + + +function irc.disconnect(message) + if irc.connected then + --The OnDisconnect hook will clear irc.connected and print a disconnect message + irc.conn:disconnect(message) + end +end + + +function irc.say(to, message) + if not message then + message = to + to = irc.config.channel + end + to = to or irc.config.channel + + irc.queue(irc.msgs.privmsg(to, message)) +end + + +function irc.reply(message) + if not irc.last_from then + return + end + message = message:gsub("[\r\n%z]", " \\n ") + irc.say(irc.last_from, message) +end + +function irc.send(msg) + if not irc.connected then return end + irc.conn:send(msg) +end + +function irc.queue(msg) + if not irc.connected then return end + irc.conn:queue(msg) +end + diff --git a/mods/irc/irc/LICENSE.txt b/mods/irc/irc/LICENSE.txt new file mode 100644 index 0000000..0a68ca1 --- /dev/null +++ b/mods/irc/irc/LICENSE.txt @@ -0,0 +1,26 @@ +--[[ + Lua IRC library + + Copyright (c) 2010 Jakob Ovrum + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE.]] + diff --git a/mods/irc/irc/README.markdown b/mods/irc/irc/README.markdown new file mode 100644 index 0000000..8cff1d2 --- /dev/null +++ b/mods/irc/irc/README.markdown @@ -0,0 +1,19 @@ +[![Build Status](https://travis-ci.org/JakobOvrum/LuaIRC.svg?branch=master)](https://travis-ci.org/JakobOvrum/LuaIRC) +LuaIRC +============ + +IRC client library for Lua. + +Dependencies +------------- + + * [LuaSocket](http://w3.impa.br/~diego/software/luasocket/) + +**Only required if you want to make use of the TLS support** + + * [LuaSec](http://www.inf.puc-rio.br/~brunoos/luasec/) + +Documentation +------------- +Documentation can be automatically generated by passing irc.luadoc (in doc/) to [LuaDoc](http://luadoc.luaforge.net/), or pre-generated documentation can be found in the 'gh-pages' branch, which can also be browsed [online](http://jakobovrum.github.com/LuaIRC/doc/modules/irc.html). + diff --git a/mods/irc/irc/asyncoperations.lua b/mods/irc/irc/asyncoperations.lua new file mode 100644 index 0000000..7531b28 --- /dev/null +++ b/mods/irc/irc/asyncoperations.lua @@ -0,0 +1,92 @@ +local msgs = require("irc.messages") + +local meta = {} + +function meta:send(msg, ...) + if type(msg) == "table" then + msg = msg:toRFC1459() + else + if select("#", ...) > 0 then + msg = msg:format(...) + end + end + self:invoke("OnSend", msg) + + local bytes, err = self.socket:send(msg .. "\r\n") + + if not bytes and err ~= "timeout" and err ~= "wantwrite" then + self:invoke("OnDisconnect", err, true) + self:shutdown() + error(err, errlevel) + end +end + +function meta:queue(msg) + table.insert(self.messageQueue, msg) +end + +local function verify(str, errLevel) + if str:find("^:") or str:find("%s%z") then + error(("malformed parameter '%s' to irc command"):format(str), errLevel) + end + + return str +end + +function meta:sendChat(target, msg) + -- Split the message into segments if it includes newlines. + for line in msg:gmatch("([^\r\n]+)") do + self:queue(msgs.privmsg(verify(target, 3), line)) + end +end + +function meta:sendNotice(target, msg) + -- Split the message into segments if it includes newlines. + for line in msg:gmatch("([^\r\n]+)") do + self:queue(msgs.notice(verify(target, 3), line)) + end +end + +function meta:join(channel, key) + self:queue(msgs.join( + verify(channel, 3), + key and verify(key, 3) or nil)) +end + +function meta:part(channel, reason) + channel = verify(channel, 3) + self:queue(msgs.part(channel, reason)) + if self.track_users then + self.channels[channel] = nil + end +end + +function meta:trackUsers(b) + self.track_users = b + if not b then + for k,v in pairs(self.channels) do + self.channels[k] = nil + end + end +end + +function meta:setMode(t) + local target = t.target or self.nick + local mode = "" + local add, rem = t.add, t.remove + + assert(add or rem, "table contains neither 'add' nor 'remove'") + + if add then + mode = table.concat{"+", verify(add, 3)} + end + + if rem then + mode = table.concat{mode, "-", verify(rem, 3)} + end + + self:queue(msgs.mode(verify(target, 3), mode)) +end + +return meta + diff --git a/mods/irc/irc/doc/irc.luadoc b/mods/irc/irc/doc/irc.luadoc new file mode 100644 index 0000000..c33a0b1 --- /dev/null +++ b/mods/irc/irc/doc/irc.luadoc @@ -0,0 +1,198 @@ +--- LuaIRC is a low-level IRC library for Lua. +-- All functions raise Lua exceptions on error. +-- +-- Use new to create a new Connection object.
+-- Example:

+-- +--require "irc"
+--local sleep = require "socket".sleep
+--
+--local s = irc.new{nick = "example"}
+--
+--s:hook("OnChat", function(user, channel, message)
+-- print(("[%s] %s: %s"):format(channel, user.nick, message))
+--end)
+--
+--s:connect("irc.example.net")
+--s:join("#example")
+--
+--while true do
+-- s:think()
+-- sleep(0.5)
+--end
+--
+ +module "irc" + +--- Create a new Connection object. Use irc:connect to connect to a server. +-- @param user Table with fields nick, username and realname. +-- The nick field is required. +-- +-- @return Returns a new Connection object. +-- @see Connection +function new(user) + +--- Hook a function to an event. +-- @param name Name of event. +-- @param id Unique tag. +-- @param f Callback function. [defaults to id] +-- @see Hooks +function irc:hook(name, id, f) + +--- Remove previous hooked callback. +-- @param name Name of event. +-- @param id Unique tag. +function irc:unhook(name, id) + +--- Connect irc to an IRC server. +-- @param host Host address. +-- @param port Server port. [default 6667] +function irc:connect(host, port) + +-- @param table Table of connection details +-- @see ConnectOptions +function irc:connect(table) + +--- Disconnect irc from the server. +-- @param message Quit message. +function irc:disconnect(message) + +--- Handle incoming data for irc, and invoke previously hooked callbacks based on new server input. +-- You should call this in some kind of main loop, or at least often enough to not time out. +function irc:think() + +--- Look up user info. +-- @param nick Nick of user to query. +-- @return Table with fields userinfo, node, channels and account. +function irc:whois(nick) + +--- Look up topic. +-- Use this to invoke the hooks OnTopic and OnTopicInfo at any time. +-- @param channel Channel to query. +function irc:topic(channel) + +--- Send a IRC message to the server. +-- @param msg Message or raw line to send, excluding newline characters. +-- @param ... Format parameters for msg, with string.format semantics. [optional] +function irc:send(msg, ...) + +--- Queue Message to be sent to the server. +-- @param msg Message to be sent. +function irc:queue(msg) + +--- Send a message to a channel or user. +-- @param target Nick or channel to send to. +-- @param message Message text. +function irc:sendChat(target, message) + +--- Send a notice to a channel or user. +-- @param target Nick or channel to send to. +-- @param message Notice text. +function irc:sendNotice(target, message) + +--- Join a channel. +-- @param channel Channel to join. +-- @param key Channel key. [optional] +function irc:join(channel, key) + +--- Leave a channel. +-- @param channel Channel to leave. +function irc:part(channel) + +--- Turn user information tracking on or off. User tracking is enabled by default. +-- @param b Boolean whether or not to track user information. +function irc:trackUsers(b) + +--- Add/remove modes for a channel or nick. +-- @param t Table with fields target, nick, add and/or rem. target or nick +-- specifies the user or channel to add/remove modes. add is a list of modes to add to the user or channel. +-- rem is a list of modes to remove from the user or channel. +-- @usage Example which sets +m (moderated) for #channel:
+-- irc:setMode{target = "#channel", add = "m"} +function irc:setMode(t) + +--internal +function irc:invoke(name, ...) +function irc:handle(msg) +function irc:shutdown() + +--- Table with connection information. +-- @name ConnectOptions +-- @class table +-- @field host Server host name. +-- @field port Server port. [defaults to 6667] +-- @field timeout Connect timeout. [defaults to 30] +-- @field password Server password. +-- @field secure Boolean to enable TLS connection, pass a params table (described, [luasec]) to control +-- [luasec]: http://www.inf.puc-rio.br/~brunoos/luasec/reference.html + +--- Class representing a connection. +-- @name Connection +-- @class table +-- @field authed Boolean indicating whether the connection has completed registration. +-- @field connected Whether the connection is currently connected. +-- @field motd The server's message of the day. Can be nil. +-- @field nick The current nickname. +-- @field realname The real name sent to the server. +-- @field username The username/ident sent to the server. +-- @field socket Raw socket used by the library. +-- @field supports What the server claims to support in it's ISUPPORT message. + +--- Class representing an IRC message. +-- @name Message +-- @class table +-- @field args A list of the command arguments +-- @field command The IRC command +-- @field prefix The prefix of the message +-- @field raw A raw IRC line for this message +-- @field tags A table of IRCv3 tags +-- @field user A User object describing the sender of the message +-- Fields may be missing. +-- Messages have the following methods: +--
    +--
  • toRFC1459() - Returns the message serialized in RFC 1459 format.
  • +--
+ +--- List of hooks you can use with irc:hook. +-- The parameter list describes the parameters passed to the callback function. +--
    +--
  • PreRegister() - Usefull for requesting capabilities.
  • +--
  • OnRaw(line) - Any non false/nil return value assumes line handled and will not be further processed.
  • +--
  • OnSend(line)
  • +--
  • OnDisconnect(message, errorOccurred)
  • +--
  • OnChat(user, channel, message)
  • +--
  • OnNotice(user, channel, message)
  • +--
  • OnJoin(user, channel)*
  • +--
  • OnPart(user, channel)*
  • +--
  • OnQuit(user, message)
  • +--
  • NickChange(user, newnick, channel)*†
  • +--
  • NameList(channel, names)
  • +--
  • OnTopic(channel, topic)
  • +--
  • OnTopicInfo(channel, creator, timeCreated)
  • +--
  • OnKick(channel, nick, kicker, reason)* (kicker is a user table)
  • +--
  • OnUserMode(modes)
  • +--
  • OnChannelMode(user, channel, modes)
  • +--
  • OnModeChange(user, target, modes, ...)* ('...' contains mode options such as banmasks)
  • +--
  • OnCapabilityList(caps)
  • +--
  • OnCapabilityAvailable(cap, value) Called only when a capability becomes available or changes.
  • +--
  • OnCapabilitySet(cap, enabled)*
  • +--
  • DoX(msg)* - 'X' is any IRC command or numeric with the first letter capitalized (eg, DoPing and Do001)
  • +--
+-- * Event also invoked for yourself. +-- † Channel passed only when user tracking is enabled +-- @name Hooks +-- @class table + +--- Table with information about a user. +--
    +--
  • server - Server name.
  • +--
  • nick - User nickname.
  • +--
  • username - User username.
  • +--
  • host - User hostname.
  • +--
  • realname - User real name.
  • +--
  • access - User access, available in channel-oriented callbacks. A table containing boolean fields for each access mode that the server supports. Eg: 'o', and 'v'.
  • +--
+-- Fields may be missing. To fill them in, enable user tracking and use irc:whois. +-- @name User +-- @class table + diff --git a/mods/irc/irc/handlers.lua b/mods/irc/irc/handlers.lua new file mode 100644 index 0000000..f01936f --- /dev/null +++ b/mods/irc/irc/handlers.lua @@ -0,0 +1,277 @@ +local util = require("irc.util") +local msgs = require("irc.messages") +local Message = msgs.Message + +local handlers = {} + +handlers["PING"] = function(conn, msg) + conn:send(Message({command="PONG", args=msg.args})) +end + +local function requestWanted(conn, wanted) + local args = {} + for cap, value in pairs(wanted) do + if type(value) == "string" then + cap = cap .. "=" .. value + end + if not conn.capabilities[cap] then + table.insert(args, cap) + end + end + conn:queue(Message({ + command = "CAP", + args = {"REQ", table.concat(args, " ")} + }) + ) +end + +handlers["CAP"] = function(conn, msg) + local cmd = msg.args[2] + if not cmd then + return + end + if cmd == "LS" then + local list = msg.args[3] + local last = false + if list == "*" then + list = msg.args[4] + else + last = true + end + local avail = conn.availableCapabilities + local wanted = conn.wantedCapabilities + for item in list:gmatch("(%S+)") do + local eq = item:find("=", 1, true) + local k, v + if eq then + k, v = item:sub(1, eq - 1), item:sub(eq + 1) + else + k, v = item, true + end + if not avail[k] or avail[k] ~= v then + wanted[k] = conn:invoke("OnCapabilityAvailable", k, v) + end + avail[k] = v + end + if last then + if next(wanted) then + requestWanted(conn, wanted) + end + conn:invoke("OnCapabilityList", conn.availableCapabilities) + end + elseif cmd == "ACK" then + for item in msg.args[3]:gmatch("(%S+)") do + local enabled = (item:sub(1, 1) ~= "-") + local name = enabled and item or item:sub(2) + conn:invoke("OnCapabilitySet", name, enabled) + conn.capabilities[name] = enabled + end + end +end + +handlers["001"] = function(conn, msg) + conn.authed = true + conn.nick = msg.args[1] +end + +handlers["PRIVMSG"] = function(conn, msg) + conn:invoke("OnChat", msg.user, msg.args[1], msg.args[2]) +end + +handlers["NOTICE"] = function(conn, msg) + conn:invoke("OnNotice", msg.user, msg.args[1], msg.args[2]) +end + +handlers["JOIN"] = function(conn, msg) + local channel = msg.args[1] + if conn.track_users then + if msg.user.nick == conn.nick then + conn.channels[channel] = {users = {}} + else + conn.channels[channel].users[msg.user.nick] = msg.user + end + end + + conn:invoke("OnJoin", msg.user, msg.args[1]) +end + +handlers["PART"] = function(conn, msg) + local channel = msg.args[1] + if conn.track_users then + if msg.user.nick == conn.nick then + conn.channels[channel] = nil + else + conn.channels[channel].users[msg.user.nick] = nil + end + end + conn:invoke("OnPart", msg.user, msg.args[1], msg.args[2]) +end + +handlers["QUIT"] = function(conn, msg) + if conn.track_users then + for chanName, chan in pairs(conn.channels) do + chan.users[msg.user.nick] = nil + end + end + conn:invoke("OnQuit", msg.user, msg.args[1], msg.args[2]) +end + +handlers["NICK"] = function(conn, msg) + local newNick = msg.args[1] + if conn.track_users then + for chanName, chan in pairs(conn.channels) do + local users = chan.users + local oldinfo = users[msg.user.nick] + if oldinfo then + users[newNick] = oldinfo + users[msg.user.nick] = nil + conn:invoke("NickChange", msg.user, newNick, chanName) + end + end + else + conn:invoke("NickChange", msg.user, newNick) + end + if msg.user.nick == conn.nick then + conn.nick = newNick + end +end + +local function needNewNick(conn, msg) + local newnick = conn.nickGenerator(msg.args[2]) + conn:queue(irc.msgs.nick(newnick)) +end + +-- ERR_ERRONEUSNICKNAME (Misspelt but remains for historical reasons) +handlers["432"] = needNewNick + +-- ERR_NICKNAMEINUSE +handlers["433"] = needNewNick + +-- ERR_UNAVAILRESOURCE +handlers["437"] = function(conn, msg) + if not conn.authed then + needNewNick(conn, msg) + end +end + +-- RPL_ISUPPORT +handlers["005"] = function(conn, msg) + local arglen = #msg.args + -- Skip first and last parameters (nick and info) + for i = 2, arglen - 1 do + local item = msg.args[i] + local pos = item:find("=") + if pos then + conn.supports[item:sub(1, pos - 1)] = item:sub(pos + 1) + else + conn.supports[item] = true + end + end +end + +-- RPL_MOTDSTART +handlers["375"] = function(conn, msg) + conn.motd = "" +end + +-- RPL_MOTD +handlers["372"] = function(conn, msg) + -- MOTD lines have a "- " prefix, strip it. + conn.motd = conn.motd .. msg.args[2]:sub(3) .. '\n' +end + +-- NAMES list +handlers["353"] = function(conn, msg) + local chanType = msg.args[2] + local channel = msg.args[3] + local names = msg.args[4] + if conn.track_users then + conn.channels[channel] = conn.channels[channel] or {users = {}, type = chanType} + + local users = conn.channels[channel].users + for nick in names:gmatch("(%S+)") do + local access, name = util.parseNick(conn, nick) + users[name] = {access = access} + end + end +end + +-- End of NAMES list +handlers["366"] = function(conn, msg) + if conn.track_users then + conn:invoke("NameList", msg.args[2], msg.args[3]) + end +end + +-- No topic +handlers["331"] = function(conn, msg) + conn:invoke("OnTopic", msg.args[2], nil) +end + +handlers["TOPIC"] = function(conn, msg) + conn:invoke("OnTopic", msg.args[1], msg.args[2]) +end + +handlers["332"] = function(conn, msg) + conn:invoke("OnTopic", msg.args[2], msg.args[3]) +end + +-- Topic creation info +handlers["333"] = function(conn, msg) + conn:invoke("OnTopicInfo", msg.args[2], msg.args[3], tonumber(msg.args[4])) +end + +handlers["KICK"] = function(conn, msg) + conn:invoke("OnKick", msg.args[1], msg.args[2], msg.user, msg.args[3]) +end + +-- RPL_UMODEIS +-- To answer a query about a client's own mode, RPL_UMODEIS is sent back +handlers["221"] = function(conn, msg) + conn:invoke("OnUserMode", msg.args[2]) +end + +-- RPL_CHANNELMODEIS +-- The result from common irc servers differs from that defined by the rfc +handlers["324"] = function(conn, msg) + conn:invoke("OnChannelMode", msg.args[2], msg.args[3]) +end + +handlers["MODE"] = function(conn, msg) + local target = msg.args[1] + local modes = msg.args[2] + local optList = {} + for i = 3, #msg.args do + table.insert(optList, msg.args[i]) + end + if conn.track_users and target ~= conn.nick then + local add = true + local argNum = 1 + util.updatePrefixModes(conn) + for c in modes:gmatch(".") do + if c == "+" then add = true + elseif c == "-" then add = false + elseif conn.modeprefix[c] then + local nick = optList[argNum] + argNum = argNum + 1 + local user = conn.channels[target].users[nick] + user.access = user.access or {} + local access = user.access + access[c] = add + if c == "o" then access.op = add + elseif c == "v" then access.voice = add + end + end + end + end + conn:invoke("OnModeChange", msg.user, target, modes, unpack(optList)) +end + +handlers["ERROR"] = function(conn, msg) + conn:invoke("OnDisconnect", msg.args[1], true) + conn:shutdown() + error(msg.args[1], 3) +end + +return handlers + diff --git a/mods/irc/irc/init.lua b/mods/irc/irc/init.lua new file mode 100644 index 0000000..194b692 --- /dev/null +++ b/mods/irc/irc/init.lua @@ -0,0 +1,257 @@ +local socket = require("socket") +local util = require("irc.util") +local handlers = require("irc.handlers") +local msgs = require("irc.messages") +local Message = msgs.Message + +local meta = {} +meta.__index = meta + + +for k, v in pairs(require("irc.asyncoperations")) do + meta[k] = v +end + +local meta_preconnect = {} +function meta_preconnect.__index(o, k) + local v = rawget(meta_preconnect, k) + + if v == nil and meta[k] ~= nil then + error(("field '%s' is not accessible before connecting"):format(k), 2) + end + return v +end + +meta.connected = true +meta_preconnect.connected = false + +function new(data) + local o = { + nick = assert(data.nick, "Field 'nick' is required"); + username = data.username or "lua"; + realname = data.realname or "Lua owns"; + nickGenerator = data.nickGenerator or util.defaultNickGenerator; + hooks = {}; + track_users = true; + supports = {}; + messageQueue = {}; + lastThought = 0; + recentMessages = 0; + availableCapabilities = {}; + wantedCapabilities = {}; + capabilities = {}; + } + assert(util.checkNick(o.nick), "Erroneous nickname passed to irc.new") + return setmetatable(o, meta_preconnect) +end + +function meta:hook(name, id, f) + f = f or id + self.hooks[name] = self.hooks[name] or {} + self.hooks[name][id] = f + return id or f +end +meta_preconnect.hook = meta.hook + + +function meta:unhook(name, id) + local hooks = self.hooks[name] + + assert(hooks, "no hooks exist for this event") + assert(hooks[id], "hook ID not found") + + hooks[id] = nil +end +meta_preconnect.unhook = meta.unhook + +function meta:invoke(name, ...) + local hooks = self.hooks[name] + if hooks then + for id, f in pairs(hooks) do + local ret = f(...) + if ret then + return ret + end + end + end +end + +function meta_preconnect:connect(_host, _port) + local host, port, password, secure, timeout + + if type(_host) == "table" then + host = _host.host + port = _host.port + timeout = _host.timeout + password = _host.password + secure = _host.secure + else + host = _host + port = _port + end + + host = host or error("host name required to connect", 2) + port = port or 6667 + + local s = socket.tcp() + + s:settimeout(timeout or 30) + assert(s:connect(host, port)) + + if secure then + local work, ssl = pcall(require, "ssl") + if not work then + error("LuaSec required for secure connections", 2) + end + + local params + if type(secure) == "table" then + params = secure + else + params = {mode = "client", protocol = "tlsv1"} + end + + s = ssl.wrap(s, params) + local success, errmsg = s:dohandshake() + if not success then + error(("could not make secure connection: %s"):format(errmsg), 2) + end + end + + self.socket = s + setmetatable(self, meta) + + self:invoke("PreRegister", self) + + if password then + self:queue(Message({command="PASS", args={password}})) + end + + self:queue(msgs.nick(self.nick)) + self:queue(Message({command="USER", args={self.username, "0", "*", self.realname}})) + + self.channels = {} + + s:settimeout(0) + + repeat + self:think() + socket.sleep(0.1) + until self.authed +end + +function meta:disconnect(message) + message = message or "Bye!" + + self:invoke("OnDisconnect", message, false) + self:send(msgs.quit(message)) + + self:shutdown() +end + +function meta:shutdown() + self.socket:close() + setmetatable(self, meta_preconnect) +end + +local function getline(self, errlevel) + local line, err = self.socket:receive("*l") + + if not line and err ~= "timeout" and err ~= "wantread" then + self:invoke("OnDisconnect", err, true) + self:shutdown() + error(err, errlevel) + end + + return line +end + +function meta:think() + while true do + local line = getline(self, 3) + if line and #line > 0 then + if not self:invoke("OnRaw", line) then + self:handle(Message({raw=line})) + end + else + break + end + end + + -- Handle outgoing message queue + local diff = socket.gettime() - self.lastThought + self.recentMessages = self.recentMessages - (diff * 2) + if self.recentMessages < 0 then + self.recentMessages = 0 + end + for i = 1, #self.messageQueue do + if self.recentMessages > 4 then + break + end + self:send(table.remove(self.messageQueue, 1)) + self.recentMessages = self.recentMessages + 1 + end + self.lastThought = socket.gettime() +end + +function meta:handle(msg) + local handler = handlers[msg.command] + if handler then + handler(self, msg) + end + self:invoke("Do" .. util.capitalize(msg.command), msg) +end + +local whoisHandlers = { + ["311"] = "userinfo"; + ["312"] = "node"; + ["319"] = "channels"; + ["330"] = "account"; -- Freenode + ["307"] = "registered"; -- Unreal +} + +function meta:whois(nick) + self:send(msgs.whois(nick)) + + local result = {} + + while true do + local line = getline(self, 3) + if line then + local msg = Message({raw=line}) + + local handler = whoisHandlers[msg.command] + if handler then + result[handler] = msg.args + elseif msg.command == "318" then + break + else + self:handle(msg) + end + end + end + + if result.account then + result.account = result.account[3] + elseif result.registered then + result.account = result.registered[2] + end + + return result +end + +function meta:topic(channel) + self:queue(msgs.topic(channel)) +end + +return { + new = new; + + Message = Message; + msgs = msgs; + + color = util.color; + bold = util.bold; + underline = util.underline; +} + diff --git a/mods/irc/irc/messages.lua b/mods/irc/irc/messages.lua new file mode 100644 index 0000000..48aa687 --- /dev/null +++ b/mods/irc/irc/messages.lua @@ -0,0 +1,207 @@ + +-- Module table +local m = {} + +local msg_meta = {} +msg_meta.__index = msg_meta + +local function Message(opts) + opts = opts or {} + setmetatable(opts, msg_meta) + if opts.raw then + opts:fromRFC1459(opts.raw) + end + return opts +end + +m.Message = Message + +local tag_escapes = { + [";"] = "\\:", + [" "] = "\\s", + ["\0"] = "\\0", + ["\\"] = "\\\\", + ["\r"] = "\\r", + ["\n"] = "\\n", +} + +local tag_unescapes = {} +for x, y in pairs(tag_escapes) do tag_unescapes[y] = x end + +function msg_meta:toRFC1459() + local s = "" + + if self.tags then + s = s.."@" + for key, value in pairs(self.tags) do + s = s..key + if value ~= true then + value = value:gsub("[; %z\\\r\n]", tag_escapes) + s = s.."="..value + end + s = s..";" + end + -- Strip trailing semicolon + s = s:sub(1, -2) + s = s.." " + end + + s = s..self.command + + local argnum = #self.args + for i = 1, argnum do + local arg = self.args[i] + local startsWithColon = (arg:sub(1, 1) == ":") + local hasSpace = arg:find(" ") + if i == argnum and (hasSpace or startsWithColon) then + s = s.." :" + else + assert(not hasSpace and not startsWithColon, + "Message arguments can not be " + .."serialized to RFC1459 format") + s = s.." " + end + s = s..arg + end + + return s +end + +local function parsePrefix(prefix) + local user = {} + user.nick, user.username, user.host = prefix:match("^(.+)!(.+)@(.+)$") + if not user.nick and prefix:find(".", 1, true) then + user.server = prefix + end + return user +end + +function msg_meta:fromRFC1459(line) + -- IRCv3 tags + if line:sub(1, 1) == "@" then + self.tags = {} + local space = line:find(" ", 1, true) + -- For each semicolon-delimited section from after + -- the @ character to before the space character. + for tag in line:sub(2, space - 1):gmatch("([^;]+)") do + local eq = tag:find("=", 1, true) + if eq then + self.tags[tag:sub(1, eq - 1)] = + tag:sub(eq + 1):gsub("\\([:s0\\rn])", tag_unescapes) + else + self.tags[tag] = true + end + end + line = line:sub(space + 1) + end + + if line:sub(1, 1) == ":" then + local space = line:find(" ", 1, true) + self.prefix = line:sub(2, space - 1) + self.user = parsePrefix(self.prefix) + line = line:sub(space + 1) + end + + local pos + self.command, pos = line:match("(%S+)()") + line = line:sub(pos) + + self.args = self.args or {} + for pos, param in line:gmatch("()(%S+)") do + if param:sub(1, 1) == ":" then + param = line:sub(pos + 1) + table.insert(self.args, param) + break + end + table.insert(self.args, param) + end +end + +function m.privmsg(to, text) + return Message({command="PRIVMSG", args={to, text}}) +end + +function m.notice(to, text) + return Message({command="NOTICE", args={to, text}}) +end + +function m.action(to, text) + return Message({command="PRIVMSG", args={to, ("\x01ACTION %s\x01"):format(text)}}) +end + +function m.ctcp(command, to, args) + s = "\x01"..command + if args then + s = ' '..args + end + s = s..'\x01' + return Message({command="PRIVMSG", args={to, s}}) +end + +function m.kick(channel, target, reason) + return Message({command="KICK", args={channel, target, reason}}) +end + +function m.join(channel, key) + return Message({command="JOIN", args={channel, key}}) +end + +function m.part(channel, reason) + return Message({command="PART", args={channel, reason}}) +end + +function m.quit(reason) + return Message({command="QUIT", args={reason}}) +end + +function m.kill(target, reason) + return Message({command="KILL", args={target, reason}}) +end + +function m.kline(time, mask, reason, operreason) + local args = nil + if time then + args = {time, mask, reason..'|'..operreason} + else + args = {mask, reason..'|'..operreason} + end + return Message({command="KLINE", args=args}) +end + +function m.whois(nick, server) + local args = nil + if server then + args = {server, nick} + else + args = {nick} + end + return Message({command="WHOIS", args=args}) +end + +function m.topic(channel, text) + return Message({command="TOPIC", args={channel, text}}) +end + +function m.invite(channel, target) + return Message({command="INVITE", args={channel, target}}) +end + +function m.nick(nick) + return Message({command="NICK", args={nick}}) +end + +function m.mode(target, modes) + -- We have to split the modes parameter because the mode string and + -- each parameter are seperate arguments (The first command is incorrect) + -- MODE foo :+ov Nick1 Nick2 + -- MODE foo +ov Nick1 Nick2 + local mt = util.split(modes) + return Message({command="MODE", args={target, unpack(mt)}}) +end + +function m.cap(cmd, ...) + return Message({command="CAP", args={cmd, ...}}) +end + +return m + diff --git a/mods/irc/irc/push-luadoc.sh b/mods/irc/irc/push-luadoc.sh new file mode 100755 index 0000000..6f77ff2 --- /dev/null +++ b/mods/irc/irc/push-luadoc.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +if [ "$TRAVIS_REPO_SLUG" == "JakobOvrum/LuaIRC" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_BRANCH" == "master" ]; then + + echo -e "Generating luadoc...\n" + + git config --global user.email "travis@travis-ci.org" + git config --global user.name "travis-ci" + git clone --quiet --branch=gh-pages https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG} gh-pages > /dev/null + + cd gh-pages + git rm -rf ./doc + sh ./generate.sh + git add -f ./doc + git commit -m "Lastest documentation on successful travis build $TRAVIS_BUILD_NUMBER auto-pushed to gh-pages" + git push -fq origin gh-pages > /dev/null + + echo -e "Published luadoc to gh-pages.\n" +fi diff --git a/mods/irc/irc/set.lua b/mods/irc/irc/set.lua new file mode 100644 index 0000000..a4c6881 --- /dev/null +++ b/mods/irc/irc/set.lua @@ -0,0 +1,52 @@ +local select = require("socket").select + +local m = {} +local set = {} +set.__index = set + +function m.new(t) + t.connections = {} + t.sockets = {} + return setmetatable(t, set) +end + +function set:add(connection) + local socket = connection.socket + insert(self.sockets, socket) + + self.connections[socket] = connection + insert(self.connections, connection) +end + +function set:remove(connection) + local socket = connection.socket + self.connections[socket] = nil + for k, s in ipairs(self.sockets) do + if socket == s then + remove(self.sockets, k) + remove(self.connections, k) + break + end + end +end + +function set:select() + local read, write, err = select(self.sockets, nil, self.timeout) + + if read then + for k, socket in ipairs(read) do + read[k] = self.connections[socket] + end + end + + return read, err +end + +-- Select - but if it times out, it returns all connections. +function set:poll() + local read, err = self:select() + return err == "timeout" and self.connections or read +end + +return m + diff --git a/mods/irc/irc/util.lua b/mods/irc/irc/util.lua new file mode 100644 index 0000000..5916857 --- /dev/null +++ b/mods/irc/irc/util.lua @@ -0,0 +1,120 @@ + +-- Module table +local m = {} + +function m.updatePrefixModes(conn) + if conn.prefixmode and conn.modeprefix then + return + end + conn.prefixmode = {} + conn.modeprefix = {} + if conn.supports.PREFIX then + local modes, prefixes = conn.supports.PREFIX:match("%(([^%)]*)%)(.*)") + for i = 1, #modes do + conn.prefixmode[prefixes:sub(i, i)] = modes:sub(i, i) + conn.modeprefix[ modes:sub(i, i)] = prefixes:sub(i, i) + end + else + conn.prefixmode['@'] = 'o' + conn.prefixmode['+'] = 'v' + conn.modeprefix['o'] = '@' + conn.modeprefix['v'] = '+' + end +end + +function m.parseNick(conn, nick) + local access = {} + m.updatePrefixModes(conn) + local namestart = 1 + for i = 1, #nick - 1 do + local c = nick:sub(i, i) + if conn.prefixmode[c] then + access[conn.prefixmode[c]] = true + else + namestart = i + break + end + end + access.op = access.o + access.voice = access.v + local name = nick:sub(namestart) + return access, name +end + +-- mIRC markup scheme (de-facto standard) +m.color = { + black = 1, + blue = 2, + green = 3, + red = 4, + lightred = 5, + purple = 6, + brown = 7, + yellow = 8, + lightgreen = 9, + navy = 10, + cyan = 11, + lightblue = 12, + violet = 13, + gray = 14, + lightgray = 15, + white = 16 +} + +local colByte = string.char(3) +setmetatable(m.color, {__call = function(_, text, colornum) + colornum = (type(colornum) == "string" and + assert(color[colornum], "Invalid color '"..colornum.."'") or + colornum) + return table.concat{colByte, tostring(colornum), text, colByte} +end}) + +local boldByte = string.char(2) +function m.bold(text) + return boldByte..text..boldByte +end + +local underlineByte = string.char(31) +function m.underline(text) + return underlineByte..text..underlineByte +end + +function m.checkNick(nick) + return nick:find("^[a-zA-Z_%-%[|%]%^{|}`][a-zA-Z0-9_%-%[|%]%^{|}`]*$") ~= nil +end + +function m.defaultNickGenerator(nick) + -- LuaBot -> LuaCot -> LuaCou -> ... + -- We change a random character rather than appending to the + -- nickname as otherwise the new nick could exceed the ircd's + -- maximum nickname length. + local randindex = math.random(1, #nick) + local randchar = string.sub(nick, randindex, randindex) + local b = string.byte(randchar) + b = b + 1 + if b < 65 or b > 125 then + b = 65 + end + -- Get the halves before and after the changed character + local first = string.sub(nick, 1, randindex - 1) + local last = string.sub(nick, randindex + 1, #nick) + nick = first .. string.char(b) .. last -- Insert the new charachter + return nick +end + +function m.capitalize(text) + -- Converts first character to upercase and the rest to lowercase. + -- "PING" -> "Ping" | "hello" -> "Hello" | "123" -> "123" + return text:sub(1, 1):upper()..text:sub(2):lower() +end + +function m.split(str, sep) + local t = {} + for s in str:gmatch("%S+") do + table.insert(t, s) + end + return t +end + +return m + diff --git a/mods/irc/messages.lua b/mods/irc/messages.lua new file mode 100644 index 0000000..83e4f7f --- /dev/null +++ b/mods/irc/messages.lua @@ -0,0 +1,17 @@ +-- This file is licensed under the terms of the BSD 2-clause license. +-- See LICENSE.txt for details. + +irc.msgs = irc.lib.msgs + +function irc.logChat(message) + minetest.log("action", "IRC CHAT: "..message) +end + +function irc.sendLocal(message) + minetest.chat_send_all(message) + irc.logChat(message) +end + +function irc.playerMessage(name, message) + return ("<%s> %s"):format(name, message) +end diff --git a/mods/irc/mod.conf b/mods/irc/mod.conf new file mode 100644 index 0000000..ba3caea --- /dev/null +++ b/mods/irc/mod.conf @@ -0,0 +1 @@ +name = irc diff --git a/mods/irc/player_part.lua b/mods/irc/player_part.lua new file mode 100644 index 0000000..e703316 --- /dev/null +++ b/mods/irc/player_part.lua @@ -0,0 +1,69 @@ +-- This file is licensed under the terms of the BSD 2-clause license. +-- See LICENSE.txt for details. + + +function irc.player_part(name) + if not irc.joined_players[name] then + return false, "You are not in the channel" + end + irc.joined_players[name] = nil + return true, "You left the channel" +end + +function irc.player_join(name) + if irc.joined_players[name] then + return false, "You are already in the channel" + end + irc.joined_players[name] = true + return true, "You joined the channel" +end + + +minetest.register_chatcommand("join", { + description = "Join the IRC channel", + privs = {shout=true}, + func = function(name) + return irc.player_join(name) + end +}) + +minetest.register_chatcommand("part", { + description = "Part the IRC channel", + privs = {shout=true}, + func = function(name) + return irc.player_part(name) + end +}) + +minetest.register_chatcommand("who", { + description = "Tell who is currently on the channel", + privs = {}, + func = function() + local out, n = { }, 0 + for plname in pairs(irc.joined_players) do + n = n + 1 + out[n] = plname + end + table.sort(out) + return true, "Players in channel: "..table.concat(out, ", ") + end +}) + + +minetest.register_on_joinplayer(function(player) + local name = player:get_player_name() + irc.joined_players[name] = irc.config.auto_join +end) + + +minetest.register_on_leaveplayer(function(player) + local name = player:get_player_name() + irc.joined_players[name] = nil +end) + +function irc.sendLocal(message) + for name, _ in pairs(irc.joined_players) do + minetest.chat_send_player(name, message) + end + irc.logChat(message) +end diff --git a/mods/irc/settingtypes.txt b/mods/irc/settingtypes.txt new file mode 100644 index 0000000..0814167 --- /dev/null +++ b/mods/irc/settingtypes.txt @@ -0,0 +1,75 @@ + +[Basic] + +# Whether to automatically connect to the server on mod load. +# If false, you must use /irc_connect to connect. +irc.auto_connect (Auto-connect on load) bool true + +# Nickname for the bot. May only contain characters A-Z, 0-9 +# '{', '}', '[', ']', '|', '^', '-', or '_'. +irc.nick (Bot nickname) string Minetest + +# Server to connect to. +irc.server (IRC server) string irc.freenode.net + +# Server port. +# The standard IRC protocol port is 6667 for regular servers, +# or 6697 for SSL-enabled servers. +# If unsure, leave at 6667. +irc.port (IRC server port) int 6667 1 65535 + +# Channel the bot joins after connecting. +irc.channel (Channel to join) string ##mt-irc-mod + +[Authentication] + +# Password for authenticating to NickServ. +# Leave empty to not authenticate with NickServ. +irc.NSPass (NickServ password) string + +# IRC server password. +# Leave empty for no password. +irc.password (Server password) string + +# Password for joining the channel. +# Leave empty if your channel is not protected. +irc.key (Channel key) string + +# Enable TLS connection. +# Requires LuaSEC . +irc.secure (Use TLS) bool false + +# Username for SASL authentication. +# Leave empty to use the nickname. +irc.sasl.user (SASL username) string + +# Password for SASL authentication. +# Leave empty to not authenticate via SASL. +irc.sasl.pass (SASL password) string + +[Advanced] + +# Enable this to make the bot send messages when players join +# or leave the game server. +irc.send_join_part (Send join and part messages) bool true + +# Enable this to make the bot send messages when players are kicked. +irc.send_kicks (Send kick messages) bool false + +# Underlying socket timeout in seconds. +irc.timeout (Timeout) int 60 1 + +# Time between reconnection attempts, in seconds. +irc.reconnect (Reconnect delay) int 600 1 + +# Prefix to use for bot commands. +irc.command_prefix (Command prefix) string + +# Enable debug output. +irc.debug (Debug mode) bool false + +# Whether to enable players joining and parting the channel. +irc.enable_player_part (Allow player join/part) bool true + +# Whether to automatically show players in the channel when they join. +irc.auto_join (Auto join players) bool true diff --git a/mods/point/init.lua b/mods/point/init.lua new file mode 100644 index 0000000..b56ea3b --- /dev/null +++ b/mods/point/init.lua @@ -0,0 +1,26 @@ +minetest.register_chatcommand("pointing", { + description = "Print what you're pointing at", + func = function(name) + local player = minetest.get_player_by_name(name) + local pos = vector.round(player:getpos()) + if player then + if minetest.settings:get_bool("enable_damage") then + player:set_hp(0) + lightning.strike(pos) + return true + else + for _, callback in pairs(core.registered_on_respawnplayers) do + if callback(player) then + return true + end + end + + -- There doesn't seem to be a way to get a default spawn pos from the lua API + return false, "No static_spawnpoint defined" + end + else + -- Show error message if used when not logged in, eg: from IRC mod + return false, "You need to be online to be killed!" + end + end +}) diff --git a/mods/poudlard/aliases.lua b/mods/poudlard/aliases.lua new file mode 100644 index 0000000..a3a942f --- /dev/null +++ b/mods/poudlard/aliases.lua @@ -0,0 +1,224 @@ +--Poudlard by Perlipop , code from moreblcoks/stairs+ by Calinou +--Alliases compatibility ======= RENOMMAGE POUDLARD ========== +-- Compatibility aliases de moreblocks/stairsplus vers poudlard pour les items de chaque fonction et +-- pour poudstone + poudwood + +minetest.register_alias("moreblocks:poudwood", "poudlard:poudwood") +minetest.register_alias("default:poudstone", "poudlard:poudstone") +minetest.register_alias("poudwood", "poudlard:poudwood") +minetest.register_alias("poudstone", "poudlard:poudstone") +minetest.register_alias("redblock", "poudlard:redblock") +minetest.register_alias("blackblock", "poudlard:blackblock") + + +--RENAMING MOREBLOCKS ET STAIRS+ VERS POUDLARD + + +local function register_poudlard_alias(modname, origname, newname) + minetest.register_alias(modname.. ":slab_" ..origname, "poudlard:slab_" ..newname) + minetest.register_alias(modname.. ":slab_" ..origname.. "_inverted", "poudlard:slab_" ..newname.. "_inverted") + minetest.register_alias(modname.. ":slab_" ..origname.. "_wall", "poudlard:slab_" ..newname.. "_wall") + minetest.register_alias(modname.. ":slab_" ..origname.. "_quarter", "poudlard:slab_" ..newname.. "_quarter") + minetest.register_alias(modname.. ":slab_" ..origname.. "_quarter_inverted", "poudlard:slab_" ..newname.. "_quarter_inverted") + minetest.register_alias(modname.. ":slab_" ..origname.. "_quarter_wall", "poudlard:slab_" ..newname.. "_quarter_wall") + minetest.register_alias(modname.. ":slab_" ..origname.. "_three_quarter", "poudlard:slab_" ..newname.. "_three_quarter") + minetest.register_alias(modname.. ":slab_" ..origname.. "_three_quarter_inverted", "poudlard:slab_" ..newname.. "_three_quarter_inverted") + minetest.register_alias(modname.. ":slab_" ..origname.. "_three_quarter_wall", "poudlard:slab_" ..newname.. "_three_quarter_wall") + minetest.register_alias(modname.. ":stair_" ..origname, "poudlard:stair_" ..newname) + minetest.register_alias(modname.. ":stair_" ..origname.. "_inverted", "poudlard:stair_" ..newname.. "_inverted") + minetest.register_alias(modname.. ":stair_" ..origname.. "_wall", "poudlard:stair_" ..newname.. "_wall") + minetest.register_alias(modname.. ":stair_" ..origname.. "_wall_half", "poudlard:stair_" ..newname.. "_wall_half") + minetest.register_alias(modname.. ":stair_" ..origname.. "_wall_half_inverted", "poudlard:stair_" ..newname.. "_wall_half_inverted") + minetest.register_alias(modname.. ":stair_" ..origname.. "_half", "poudlard:stair_" ..newname.. "_half") + minetest.register_alias(modname.. ":stair_" ..origname.. "_half_inverted", "poudlard:stair_" ..newname.. "_half_inverted") + minetest.register_alias(modname.. ":stair_" ..origname.. "_right_half", "poudlard:stair_" ..newname.. "_right_half") + minetest.register_alias(modname.. ":stair_" ..origname.. "_right_half_inverted", "poudlard:stair_" ..newname.. "_right_half_inverted") + minetest.register_alias(modname.. ":stair_" ..origname.. "_wall_half", "poudlard:stair_" ..newname.. "_wall_half") + minetest.register_alias(modname.. ":stair_" ..origname.. "_wall_half_inverted", "poudlard:stair_" ..newname.. "_wall_half_inverted") + minetest.register_alias(modname.. ":stair_" ..origname.. "_inner", "poudlard:stair_" ..newname.. "_inner") + minetest.register_alias(modname.. ":stair_" ..origname.. "_inner_inverted", "poudlard:stair_" ..newname.. "_inner_inverted") + minetest.register_alias(modname.. ":stair_" ..origname.. "_outer", "poudlard:stair_" ..newname.. "_outer") + minetest.register_alias(modname.. ":stair_" ..origname.. "_outer_inverted", "poudlard:stair_" ..newname.. "_outer_inverted") + minetest.register_alias(modname.. ":panel_" ..origname.. "_bottom", "poudlard:panel_" ..newname.. "_bottom") + minetest.register_alias(modname.. ":panel_" ..origname.. "_top", "poudlard:panel_" ..newname.. "_top") + minetest.register_alias(modname.. ":panel_" ..origname.. "_vertical", "poudlard:panel_" ..newname.. "_vertical") + minetest.register_alias(modname.. ":micro_" ..origname.. "_bottom", "poudlard:micro_" ..newname.. "_bottom") + minetest.register_alias(modname.. ":micro_" ..origname.. "_top", "poudlard:micro_" ..newname.. "_top") +end +register_poudlard_alias("stairsplus", "poudwood","poudwood") +register_poudlard_alias("stairsplus", "poudstone","poudstone") +register_poudlard_alias("stairsplus", "redblock","redblock") +register_poudlard_alias("stairsplus", "blackblock","blackblock") +register_poudlard_alias("stairsplus", "stone", "stone") +register_poudlard_alias("stairsplus", "wood", "wood") +register_poudlard_alias("stairsplus", "cobble", "cobble") +register_poudlard_alias("stairsplus", "brick", "brick") +register_poudlard_alias("stairsplus", "sandstone", "sandstone") +register_poudlard_alias("stairsplus", "glass", "glass") +register_poudlard_alias("stairsplus", "tree", "tree") +register_poudlard_alias("stairsplus", "jungletree", "jungletree") +register_poudlard_alias("stairsplus", "desert_stone", "desert_stone") +register_poudlard_alias("stairsplus", "steelblock", "steelblock") +register_poudlard_alias("stairsplus", "mossycobble", "mossycobble") + +register_poudlard_alias("moreblocks", "poudwood","poudwood") +register_poudlard_alias("moreblocks", "poudstone","poudstone") +register_poudlard_alias("moreblocks", "redblock","redblock") +register_poudlard_alias("moreblocks", "blackblock","blackblock") +register_poudlard_alias("moreblocks", "plankstone", "plankstone") +register_poudlard_alias("moreblocks", "coalstone", "coalstone") +register_poudlard_alias("moreblocks", "junglewood", "junglewood") +register_poudlard_alias("moreblocks", "stonebrick", "stonebrick") +register_poudlard_alias("moreblocks", "circlestonebrick", "circlestonebricks") +register_poudlard_alias("moreblocks", "ironstone", "ironstone") +register_poudlard_alias("moreblocks", "coalglass", "coalglass") +register_poudlard_alias("moreblocks", "ironglass", "ironglass") +register_poudlard_alias("moreblocks", "glowglass", "glowglass") +register_poudlard_alias("moreblocks", "superglowglass", "superglowglass") +register_poudlard_alias("moreblocks", "coalchecker", "coalchecker") +register_poudlard_alias("moreblocks", "ironchecker", "ironchecker") +register_poudlard_alias("moreblocks", "cactuschecker", "cactuschecker") +register_poudlard_alias("moreblocks", "ironstonebrick", "ironstonebricks") +register_poudlard_alias("moreblocks", "stonesquare", "stone_tile") +register_poudlard_alias("moreblocks", "splitstonesquare", "split_stone_tile") +register_poudlard_alias("moreblocks", "woodtile", "wood_tile") +register_poudlard_alias("moreblocks", "woodtile_centered", "wood_tile_centered") +register_poudlard_alias("moreblocks", "woodtile_full", "wood_tile_full") + +-- + +minetest.register_alias("moreblocks:stone_bricks", "default:stonebrick") +minetest.register_alias("moreblocks:stonebrick", "default:stonebrick") + +minetest.register_alias("stonebrick", "default:stonebrick") +minetest.register_alias("stonebricks", "default:stonebrick") +minetest.register_alias("stone_brick", "default:stonebrick") +minetest.register_alias("stone_bricks", "default:stonebrick") + +minetest.register_alias("stonesquare", "poudlard:stone_tile") +minetest.register_alias("moreblocks:stonesquare", "poudlard:stone_tile") + +minetest.register_alias("stonesquares", "poudlard:stone_tile") +minetest.register_alias("stone_square", "poudlard:stone_tile") +minetest.register_alias("stone_squares", "poudlard:stone_tile") + +minetest.register_alias("splitstonesquare", "poudlard:split_stone_tile") +minetest.register_alias("moreblocks:splitstonesquare", "poudlard:split_stone_tile") +minetest.register_alias("splitstonesquares", "poudlard:split_stone_tile") +minetest.register_alias("split_stone_square", "poudlard:split_stone_tile") +minetest.register_alias("split_stone_squares", "poudlard:split_stone_tile") +minetest.register_alias("split_stonesquare", "poudlard:split_stone_tile") +minetest.register_alias("split_stonesquares", "poudlard:split_stone_tile") + +minetest.register_alias("moreblocks:circlestonebrick", "poudlard:circlestonebricks") + + +minetest.register_alias("coalstone", "poudlard:coalstone") +minetest.register_alias("ironstone", "poudlard:ironstonebricks") +minetest.register_alias("coalglass", "poudlard:coalglass") +minetest.register_alias("ironglass", "poudlard:ironglass") +minetest.register_alias("superglowglass", "poudlard:superglowglass") +minetest.register_alias("plankstone", "poudlard:plankstone") +minetest.register_alias("cactuschecker", "poudlard:cactuschecker") +minetest.register_alias("coalchecker", "poudlard:coalchecker") +minetest.register_alias("ironchecker", "poudlard:ironchecker") + + + +minetest.register_alias("moreblocks:junglewood","poudlard:junglewood") + +minetest.register_alias("moreblocks:circle_stone_bricks","poudlard:circlestonebricks") + +minetest.register_alias("moreblocks:plankstone","poudlard:plankstone") + +minetest.register_alias("moreblocks:ironglass","poudlard:ironglass") + +minetest.register_alias("moreblocks:coalglass","poudlard:coalglass") + +minetest.register_alias("moreblocks:cleanglass","poudlard:cleanglass") + +minetest.register_alias("moreblocks:cactuschecker","poudlard:cactuschecker") + +minetest.register_alias("moreblocks:emptybookshelf","poudlard:emptybookshelf") + +minetest.register_alias("moreblocks:coalstone","poudlard:coalstone") + +minetest.register_alias("moreblocks:ironstone","poudlard:ironstone") + +minetest.register_alias("moreblocks:ironstonebrick","poudlard:ironstonebricks") + +minetest.register_alias("moreblocks:coalchecker","poudlard:coalchecker") + +minetest.register_alias("moreblocks:ironchecker","poudlard:ironchecker") + +minetest.register_alias("moreblocks:trapstone","poudlard:trapstone") + +minetest.register_alias("moreblocks:trapglass","poudlard:trapglass") + +minetest.register_alias("moreblocks:fence_junglewood","poudlard:fence_junglewood") + +minetest.register_alias("moreblocks:horizontaltree","poudlard:horizontaltree") + +minetest.register_alias("moreblocks:allfacestree","poudlard:allfacestree") + +minetest.register_alias("moreblocks:superglowglass","poudlard:superglowglass") + +minetest.register_alias("moreblocks:rope","poudlard:rope") + +minetest.register_alias("moreblocks:wood_tile","poudlard:wood_tile") + +minetest.register_alias("moreblocks:wood_tile_full","poudlard:wood_tile_full") + +minetest.register_alias("moreblocks:wood_tile_center","poudlard:wood_tile_center") + +-- Items + +minetest.register_alias("moreblocks:sweeper","poudlard:sweeper") +minetest.register_alias("moreblocks:junglestick","poudlard:junglestick") + +-- Additional default aliases + +minetest.register_alias("woodpick", "default:pick_wood") +minetest.register_alias("woodenpick", "default:pick_wood") +minetest.register_alias("stonepick", "default:pick_stone") +minetest.register_alias("steelpick", "default:pick_steel") +minetest.register_alias("ironpick", "default:pick_steel") +minetest.register_alias("mesepick", "default:pick_mese") + +minetest.register_alias("woodaxe", "default:axe_wood") +minetest.register_alias("woodenaxe", "default:axe_wood") +minetest.register_alias("stoneaxe", "default:axe_stone") +minetest.register_alias("steelaxe", "default:axe_steel") +minetest.register_alias("ironaxe", "default:axe_steel") + +minetest.register_alias("woodshovel", "default:shovel_wood") +minetest.register_alias("woodenshovel", "default:shovel_wood") +minetest.register_alias("stoneshovel", "default:shovel_stone") +minetest.register_alias("steelshovel", "default:shovel_steel") +minetest.register_alias("ironshovel", "default:shovel_steel") + +minetest.register_alias("woodsword", "default:sword_wood") +minetest.register_alias("woodensword", "default:sword_wood") +minetest.register_alias("stonesword", "default:sword_stone") +minetest.register_alias("steelsword", "default:sword_steel") +minetest.register_alias("ironsword", "default:sword_steel") + +minetest.register_alias("grass", "default:dirt_with_grass") +minetest.register_alias("grassblock", "default:dirt_with_grass") +minetest.register_alias("grass_block", "default:dirt_with_grass") + +minetest.register_alias("grassfootsteps", "default:dirt_with_grass_footsteps") +minetest.register_alias("grass_footsteps", "default:dirt_with_grass_footsteps") + +minetest.register_alias("stick", "default:stick") +minetest.register_alias("sign", "default:sign_wall") +minetest.register_alias("fence", "default:fence_wood") +minetest.register_alias("coal", "default:coal_lump") +minetest.register_alias("iron", "default:iron_lump") +minetest.register_alias("clay", "default:clay_lump") +minetest.register_alias("steel", "default:steel_ingot") +minetest.register_alias("steel_block", "default:steelblock") + + + + diff --git a/mods/poudlard/depends.txt b/mods/poudlard/depends.txt new file mode 100644 index 0000000..d1b3fb8 --- /dev/null +++ b/mods/poudlard/depends.txt @@ -0,0 +1,3 @@ +default + + diff --git a/mods/poudlard/init.lua b/mods/poudlard/init.lua new file mode 100644 index 0000000..2158ba3 --- /dev/null +++ b/mods/poudlard/init.lua @@ -0,0 +1,1589 @@ +-- Minetest 0.4 mod: default +-- See README.txt for licensing and other information. + +-- The API documentation in here was moved into doc/lua_api.txt +-- Perlipop:code imported from moreblocks by Calinou +-- Load translation library if intllib is installed + +local S +if (minetest.get_modpath("intllib")) then + dofile(minetest.get_modpath("intllib").."/intllib.lua") + S = intllib.Getter(minetest.get_current_modname()) + else + S = function ( s ) return s end +end + +dofile(minetest.get_modpath("poudlard").."/poudecor/nightstand.lua") +dofile(minetest.get_modpath("poudlard").."/poudecor/armchair.lua") +dofile(minetest.get_modpath("poudlard").."/poudecor/torch.lua") +dofile(minetest.get_modpath("poudlard").."/poudecor/curtain.lua") +dofile(minetest.get_modpath("poudlard").."/poudecor/crafts.lua") +dofile(minetest.get_modpath("poudlard").."/poudecor/furniture_recipes.lua") + + +--Construction Blocks +-- Stairs/Slabs/Panels/Microblocks -- code imported from the Stairs+ & moreblocks mods. :) + +poudlard = {} + +-- Node will be called :stair_ + +function poudlard.register_stair(modname, subname, recipeitem, groups, images, description, drop) + minetest.register_node(modname .. ":stair_" .. subname, { + description = description, + drawtype = "nodebox", + tiles = images, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + {-0.5, 0, 0, 0.5, 0.5, 0.5}, + }, + }, + selection_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + {-0.5, 0, 0, 0.5, 0.5, 0.5}, + }, + }, + sounds = default.node_sound_stone_defaults(), + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + + local p0 = pointed_thing.under + local p1 = pointed_thing.above + if p0.y-1 == p1.y then + local fakestack = ItemStack(modname .. ":stair_" .. subname.. "_inverted") + local ret = minetest.item_place(fakestack, placer, pointed_thing) + if ret:is_empty() then + itemstack:take_item() + return itemstack + end + end + + -- Otherwise place regularly + return minetest.item_place(itemstack, placer, pointed_thing) + end, + }) + + minetest.register_node(":stairs:stair_" .. subname, { + description = description, + drawtype = "nodebox", + tiles = images, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = {cracky=3, not_in_creative_inventory=1}, + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + {-0.5, 0, 0, 0.5, 0.5, 0.5}, + }, + }, + selection_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + {-0.5, 0, 0, 0.5, 0.5, 0.5}, + }, + }, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_node(modname .. ":stair_" .. subname .. "_inverted", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":stair_" .. drop, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = { + {-0.5, 0, -0.5, 0.5, 0.5, 0.5}, + {-0.5, -0.5, 0, 0.5, 0, 0.5}, + }, + }, + selection_box = { + type = "fixed", + fixed = { + {-0.5, 0, -0.5, 0.5, 0.5, 0.5}, + {-0.5, -0.5, 0, 0.5, 0, 0.5}, + }, + }, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_node(modname .. ":stair_" .. subname .. "_half", { + description = description, + drawtype = "nodebox", + tiles = images, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0, 0, 0.5}, + {-0.5, 0, 0, 0, 0.5, 0.5}, + }, + }, + selection_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0, 0, 0.5}, + {-0.5, 0, 0, 0, 0.5, 0.5}, + }, + }, + sounds = default.node_sound_stone_defaults(), + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + + local p0 = pointed_thing.under + local p1 = pointed_thing.above + if p0.y-1 == p1.y then + local fakestack = ItemStack(modname .. ":stair_" .. subname.. "_half_inverted") + local ret = minetest.item_place(fakestack, placer, pointed_thing) + if ret:is_empty() then + itemstack:take_item() + return itemstack + end + end + + -- Otherwise place regularly + return minetest.item_place(itemstack, placer, pointed_thing) + end, + }) + + minetest.register_node(modname .. ":stair_" .. subname .. "_half_inverted", { + description = description, + drawtype = "nodebox", + tiles = images, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = { + {-0.5, 0, -0.5, 0, 0.5, 0.5}, + {-0.5, -0.5, 0, 0, 0, 0.5}, + }, + }, + selection_box = { + type = "fixed", + fixed = { + {-0.5, 0, -0.5, 0, 0.5, 0.5}, + {-0.5, -0.5, 0, 0, 0, 0.5}, + }, + }, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_node(modname .. ":stair_" .. subname .. "_right_half", { + description = description, + drawtype = "nodebox", + tiles = images, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = { + {0, -0.5, -0.5, 0.5, 0, 0.5}, + {0, 0, 0, 0.5, 0.5, 0.5}, + }, + }, + selection_box = { + type = "fixed", + fixed = { + {0, -0.5, -0.5, 0.5, 0, 0.5}, + {0, 0, 0, 0.5, 0.5, 0.5}, + }, + }, + sounds = default.node_sound_stone_defaults(), + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + + local p0 = pointed_thing.under + local p1 = pointed_thing.above + if p0.y-1 == p1.y then + local fakestack = ItemStack(modname .. ":stair_" .. subname.. "_right_half_inverted") + local ret = minetest.item_place(fakestack, placer, pointed_thing) + if ret:is_empty() then + itemstack:take_item() + return itemstack + end + end + + -- Otherwise place regularly + return minetest.item_place(itemstack, placer, pointed_thing) + end, + }) + + minetest.register_node(modname .. ":stair_" .. subname .. "_right_half_inverted", { + description = description, + drawtype = "nodebox", + tiles = images, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = { + {0, 0, -0.5, 0.5, 0.5, 0.5}, + {0, -0.5, 0, 0.5, 0, 0.5}, + }, + }, + selection_box = { + type = "fixed", + fixed = { + {0, 0, -0.5, 0.5, 0.5, 0.5}, + {0, -0.5, 0, 0.5, 0, 0.5}, + }, + }, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_node(modname .. ":stair_" .. subname .. "_wall", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":stair_" .. drop, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, 0, 0.5, 0.5, 0.5}, + {-0.5, -0.5, -0.5, 0, 0.5, 0}, + }, + }, + selection_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, 0, 0.5, 0.5, 0.5}, + {-0.5, -0.5, -0.5, 0, 0.5, 0}, + }, + }, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_node(modname .. ":stair_" .. subname .. "_wall_half", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":stair_" .. drop .. "_wall_half", + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, 0, 0.5, 0, 0.5}, + {-0.5, -0.5, -0.5, 0, 0, 0}, + }, + }, + selection_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, 0, 0.5, 0, 0.5}, + {-0.5, -0.5, -0.5, 0, 0, 0}, + }, + }, + sounds = default.node_sound_stone_defaults(), + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + + local p0 = pointed_thing.under + local p1 = pointed_thing.above + if p0.y-1 == p1.y then + local fakestack = ItemStack(modname .. ":stair_" .. subname.. "_wall_half_inverted") + local ret = minetest.item_place(fakestack, placer, pointed_thing) + if ret:is_empty() then + itemstack:take_item() + return itemstack + end + end + + -- Otherwise place regularly + return minetest.item_place(itemstack, placer, pointed_thing) + end, + }) + + minetest.register_node(modname .. ":stair_" .. subname .. "_wall_half_inverted", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":stair_" .. drop .. "_wall_half", + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = { + {-0.5, 0, 0, 0.5, 0.5, 0.5}, + {-0.5, 0, -0.5, 0, 0.5, 0}, + }, + }, + selection_box = { + type = "fixed", + fixed = { + {-0.5, 0, 0, 0.5, 0.5, 0.5}, + {-0.5, 0, -0.5, 0, 0.5, 0}, + }, + }, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_node(modname .. ":stair_" .. subname .. "_inner", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":stair_" .. drop .. "_inner", + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = true, + sunlight_propagates = true, + groups = groups, + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + {-0.5, 0, 0, 0.5, 0.5, 0.5}, + {-0.5, 0, -0.5, 0, 0.5, 0}, + }, + }, + selection_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + {-0.5, 0, 0, 0.5, 0.5, 0.5}, + {-0.5, 0, -0.5, 0, 0.5, 0}, + }, + }, + sounds = default.node_sound_stone_defaults(), + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + + local p0 = pointed_thing.under + local p1 = pointed_thing.above + if p0.y-1 == p1.y then + local fakestack = ItemStack(modname .. ":stair_" .. subname.. "_inner_inverted") + local ret = minetest.item_place(fakestack, placer, pointed_thing) + if ret:is_empty() then + itemstack:take_item() + return itemstack + end + end + + -- Otherwise place regularly + return minetest.item_place(itemstack, placer, pointed_thing) + end, + }) + + minetest.register_node(modname .. ":stair_" .. subname .. "_outer", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":stair_" .. drop .. "_outer", + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + {-0.5, 0, 0, 0, 0.5, 0.5}, + }, + }, + selection_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + {-0.5, 0, 0, 0, 0.5, 0.5}, + }, + }, + sounds = default.node_sound_stone_defaults(), + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + + local p0 = pointed_thing.under + local p1 = pointed_thing.above + if p0.y-1 == p1.y then + local fakestack = ItemStack(modname .. ":stair_" .. subname.. "_outer_inverted") + local ret = minetest.item_place(fakestack, placer, pointed_thing) + if ret:is_empty() then + itemstack:take_item() + return itemstack + end + end + + -- Otherwise place regularly + return minetest.item_place(itemstack, placer, pointed_thing) + end, + }) + + minetest.register_node(modname .. ":stair_" .. subname .. "_inner_inverted", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":stair_" .. drop .. "_inner", + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = { + {-0.5, 0, -0.5, 0.5, 0.5, 0.5}, + {-0.5, -0.5, 0, 0.5, 0, 0.5}, + {-0.5, -0.5, -0.5, 0, 0, 0}, + }, + }, + selection_box = { + type = "fixed", + fixed = { + {-0.5, 0, -0.5, 0.5, 0.5, 0.5}, + {-0.5, -0.5, 0, 0.5, 0, 0.5}, + {-0.5, -0.5, -0.5, 0, 0, 0}, + }, + }, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_node(modname .. ":stair_" .. subname .. "_outer_inverted", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":stair_" .. drop .. "_outer", + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = { + {-0.5, 0, -0.5, 0.5, 0.5, 0.5}, + {-0.5, -0.5, 0, 0, 0, 0.5}, + }, + }, + selection_box = { + type = "fixed", + fixed = { + {-0.5, 0, -0.5, 0.5, 0.5, 0.5}, + {-0.5, -0.5, 0, 0, 0, 0.5}, + }, + }, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. " 8", + recipe = { + {recipeitem, "", ""}, + {recipeitem, recipeitem, ""}, + {recipeitem, recipeitem, recipeitem}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. " 8", + recipe = { + {"", "", recipeitem}, + {"", recipeitem, recipeitem}, + {recipeitem, recipeitem, recipeitem}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_wall 8", + recipe = { + {recipeitem, recipeitem, recipeitem}, + {recipeitem, recipeitem, ""}, + {recipeitem, "", ""}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_wall 8", + recipe = { + {recipeitem, recipeitem, recipeitem}, + {"", recipeitem, recipeitem}, + {"", "", recipeitem}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_wall 2", + recipe = { + {modname .. ":stair_" .. subname, modname .. ":stair_" .. subname}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_wall 2", + recipe = { + {modname .. ":stair_" .. subname .. "_inverted", modname .. ":stair_" .. subname .. "_inverted"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. " 2", + recipe = { + {modname .. ":stair_" .. subname .. "_wall"}, + {modname .. ":stair_" .. subname .. "_wall"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_inner 1", + recipe = { + {modname .. ":micro_" .. subname .. "_bottom", modname .. ":stair_" .. subname}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_inner 1", + recipe = { + {modname .. ":stair_" .. subname .. "_wall_half"}, + {modname .. ":slab_" .. subname}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_outer 1", + recipe = { + {modname .. ":micro_" .. subname .. "_bottom"}, + {modname .. ":slab_" .. subname}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_half 1", + recipe = { + {modname .. ":micro_" .. subname .. "_bottom"}, + {modname .. ":panel_" .. subname .. "_bottom"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_half_inverted 1", + recipe = { + {modname .. ":stair_" .. subname .. "_half 1"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_half 1", + recipe = { + {modname .. ":stair_" .. subname .. "_half_inverted 1"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_right_half 2", + recipe = { + {modname .. ":stair_" .. subname .. "_half", modname .. ":stair_" .. subname .. "_half"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_half 2", + recipe = { + {modname .. ":stair_" .. subname .. "_right_half", modname .. ":stair_" .. subname .. "_right_half"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_right_half_inverted 1", + recipe = { + {modname .. ":stair_" .. subname .. "_right_half"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_right_half 1", + recipe = { + {modname .. ":stair_" .. subname .. "_right_half_inverted"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_half_inverted 2", + recipe = { + {modname .. ":stair_" .. subname .. "_right_half_inverted", modname .. ":stair_" .. subname .. "_right_half_inverted"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_right_half_inverted 2", + recipe = { + {modname .. ":stair_" .. subname .. "_half_inverted", modname .. ":stair_" .. subname .. "_half_inverted"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_inner_inverted 1", + recipe = { + {modname .. ":stair_" .. subname .. "_inner"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_outer_inverted 1", + recipe = { + {modname .. ":stair_" .. subname .. "_outer"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_inner 1", + recipe = { + {modname .. ":stair_" .. subname .. "_inner_inverted"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_outer 1", + recipe = { + {modname .. ":stair_" .. subname .. "_outer_inverted"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_wall_half 2", + recipe = { + {modname .. ":stair_" .. subname .. "_wall"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_wall 1", + recipe = { + {modname .. ":stair_" .. subname .. "_wall_half"}, + {modname .. ":stair_" .. subname .. "_wall_half"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_wall_half_inverted 1", + recipe = { + {modname .. ":stair_" .. subname .. "_wall_half"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_wall_half 1", + recipe = { + {modname .. ":stair_" .. subname .. "_wall_half_inverted"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. "_inverted 1", + recipe = { + {modname .. ":stair_" .. subname}, + }, + }) + + minetest.register_craft({ + output = modname .. ":stair_" .. subname .. " 1", + recipe = { + {modname .. ":stair_" .. subname .. "_inverted"}, + }, + }) + + minetest.register_craft({ + type = "cooking", + output = modname .. ":stair_" .. subname .. "_stone", + recipe = modname .. ":stair_" .. subname .. "_cobble", + }) + + minetest.register_craft({ + type = "cooking", + output = modname .. ":stair_" .. subname .. "_stone_wall", + recipe = modname .. ":stair_" .. subname .. "_cobble_wall", + }) + + minetest.register_craft({ + type = "cooking", + output = modname .. ":stair_" .. subname .. "_stone_wall_half", + recipe = modname .. ":stair_" .. subname .. "_cobble_wall_half", + }) +end + +-- Node will be called slab_ + +function poudlard.register_slab(modname, subname, recipeitem, groups, images, description, drop, paramtype2) + minetest.register_node(modname .. ":slab_" .. subname, { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":slab_" .. drop, + paramtype = "light", + paramtype2 = paramtype2, + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + }, + sounds = default.node_sound_stone_defaults(), + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + + -- If it's being placed on an another similar one, replace it with + -- a full block + local slabpos = nil + local slabnode = nil + local p1 = pointed_thing.above + p1 = {x = p1.x, y = p1.y - 1, z = p1.z} + local n1 = minetest.env:get_node(p1) + if n1.name == modname .. ":slab_" .. subname then + slabpos = p1 + slabnode = n1 + end + if slabpos then + -- Remove the slab at slabpos + minetest.env:remove_node(slabpos) + -- Make a fake stack of a single item and try to place it + local fakestack = ItemStack(recipeitem) + pointed_thing.above = slabpos + fakestack = minetest.item_place(fakestack, placer, pointed_thing) + -- If the item was taken from the fake stack, decrement original + if not fakestack or fakestack:is_empty() then + itemstack:take_item(1) + -- Else put old node back + else + minetest.env:set_node(slabpos, slabnode) + end + return itemstack + end + + if n1.name == modname .. ":slab_" .. subname .. "_quarter" then + slabpos = p1 + slabnode = n1 + end + if slabpos then + -- Remove the slab at slabpos + minetest.env:remove_node(slabpos) + -- Make a fake stack of a single item and try to place it + local fakestack = ItemStack(modname .. ":slab_" .. subname .. "_three_quarter") + pointed_thing.above = slabpos + fakestack = minetest.item_place(fakestack, placer, pointed_thing) + -- If the item was taken from the fake stack, decrement original + if not fakestack or fakestack:is_empty() then + itemstack:take_item(1) + -- Else put old node back + else + minetest.env:set_node(slabpos, slabnode) + end + return itemstack + end + + -- Otherwise place regularly + return minetest.item_place(itemstack, placer, pointed_thing) + end, + }) + + minetest.register_node(":stairs:slab_" .. subname, { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":slab_" .. drop, + paramtype = "light", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + }, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_node(modname .. ":slab_" .. subname .. "_inverted", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":slab_" .. drop .. "_inverted", + paramtype = "light", + paramtype2 = paramtype2, + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = {-0.5, 0, -0.5, 0.5, 0.5, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, 0, -0.5, 0.5, 0.5, 0.5}, + }, + sounds = default.node_sound_stone_defaults(), + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + + -- If it's being placed on an another similar one, replace it with + -- a full block + local slabpos = nil + local slabnode = nil + local p1 = pointed_thing.above + p1 = {x = p1.x, y = p1.y + 1, z = p1.z} + local n1 = minetest.env:get_node(p1) + if n1.name == modname .. ":slab_" .. subname .. "_inverted" then + slabpos = p1 + slabnode = n1 + end + if slabpos then + -- Remove the slab at slabpos + minetest.env:remove_node(slabpos) + -- Make a fake stack of a single item and try to place it + local fakestack = ItemStack(recipeitem) + pointed_thing.above = slabpos + fakestack = minetest.item_place(fakestack, placer, pointed_thing) + -- If the item was taken from the fake stack, decrement original + if not fakestack or fakestack:is_empty() then + itemstack:take_item(1) + -- Else put old node back + else + minetest.env:set_node(slabpos, slabnode) + end + return itemstack + end + + if n1.name == modname .. ":slab_" .. subname .. "_quarter_inverted" then + slabpos = p1 + slabnode = n1 + end + if slabpos then + -- Remove the slab at slabpos + minetest.env:remove_node(slabpos) + -- Make a fake stack of a single item and try to place it + local fakestack = ItemStack(modname .. ":slab_" .. subname .. "_three_quarter_inverted") + pointed_thing.above = slabpos + fakestack = minetest.item_place(fakestack, placer, pointed_thing) + -- If the item was taken from the fake stack, decrement original + if not fakestack or fakestack:is_empty() then + itemstack:take_item(1) + -- Else put old node back + else + minetest.env:set_node(slabpos, slabnode) + end + return itemstack + end + + -- Otherwise place regularly + return minetest.item_place(itemstack, placer, pointed_thing) + end, + }) + + minetest.register_node(modname .. ":slab_" .. subname .. "_wall", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":slab_" .. drop .. "_wall", + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, 0, 0.5, 0.5, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, 0, 0.5, 0.5, 0.5}, + }, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_node(modname .. ":slab_" .. subname .. "_quarter_wall", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":slab_" .. drop .. "_quarter_wall", + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, 0.25, 0.5, 0.5, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, 0.25, 0.5, 0.5, 0.5}, + }, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_node(modname .. ":slab_" .. subname .. "_three_quarter_wall", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":slab_" .. drop .. "_three_quarter_wall", + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.25, 0.5, 0.5, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.25, 0.5, 0.5, 0.5}, + }, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_node(modname .. ":slab_" .. subname .. "_quarter", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":slab_" .. drop .. "_quarter", + paramtype = "light", + paramtype2 = paramtype2, + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, -0.25, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, -0.25, 0.5}, + }, + sounds = default.node_sound_stone_defaults(), + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + + -- If it's being placed on an another similar one, replace it with + -- a full block + local slabpos = nil + local slabnode = nil + local p1 = pointed_thing.above + p1 = {x = p1.x, y = p1.y - 1, z = p1.z} + local n1 = minetest.env:get_node(p1) + if n1.name == modname .. ":slab_" .. subname .. "_quarter" then + slabpos = p1 + slabnode = n1 + end + if slabpos then + -- Remove the slab at slabpos + minetest.env:remove_node(slabpos) + -- Make a fake stack of a single item and try to place it + local fakestack = ItemStack(modname .. ":slab_" .. subname) + pointed_thing.above = slabpos + fakestack = minetest.item_place(fakestack, placer, pointed_thing) + -- If the item was taken from the fake stack, decrement original + if not fakestack or fakestack:is_empty() then + itemstack:take_item(1) + -- Else put old node back + else + minetest.env:set_node(slabpos, slabnode) + end + return itemstack + end + + if n1.name == modname .. ":slab_" .. subname then + slabpos = p1 + slabnode = n1 + end + if slabpos then + -- Remove the slab at slabpos + minetest.env:remove_node(slabpos) + -- Make a fake stack of a single item and try to place it + local fakestack = ItemStack(modname .. ":slab_" .. subname .. "_three_quarter") + pointed_thing.above = slabpos + fakestack = minetest.item_place(fakestack, placer, pointed_thing) + -- If the item was taken from the fake stack, decrement original + if not fakestack or fakestack:is_empty() then + itemstack:take_item(1) + -- Else put old node back + else + minetest.env:set_node(slabpos, slabnode) + end + return itemstack + end + + if n1.name == modname .. ":slab_" .. subname .. "_three_quarter" then + slabpos = p1 + slabnode = n1 + end + if slabpos then + -- Remove the slab at slabpos + minetest.env:remove_node(slabpos) + -- Make a fake stack of a single item and try to place it + local fakestack = ItemStack(recipeitem) + pointed_thing.above = slabpos + fakestack = minetest.item_place(fakestack, placer, pointed_thing) + -- If the item was taken from the fake stack, decrement original + if not fakestack or fakestack:is_empty() then + itemstack:take_item(1) + -- Else put old node back + else + minetest.env:set_node(slabpos, slabnode) + end + return itemstack + end + + -- Otherwise place regularly + return minetest.item_place(itemstack, placer, pointed_thing) + end, + }) + + minetest.register_node(modname .. ":slab_" .. subname .. "_quarter_inverted", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":slab_" .. drop .. "_quarter", + paramtype = "light", + paramtype2 = paramtype2, + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = {-0.5, 0.25, -0.5, 0.5, 0.5, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, 0.25, -0.5, 0.5, 0.5, 0.5}, + }, + sounds = default.node_sound_stone_defaults(), + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + + -- If it's being placed on an another similar one, replace it with + -- a full block + local slabpos = nil + local slabnode = nil + local p1 = pointed_thing.above + p1 = {x = p1.x, y = p1.y + 1, z = p1.z} + local n1 = minetest.env:get_node(p1) + if n1.name == modname .. ":slab_" .. subname .. "_quarter_inverted" then + slabpos = p1 + slabnode = n1 + end + if slabpos then + -- Remove the slab at slabpos + minetest.env:remove_node(slabpos) + -- Make a fake stack of a single item and try to place it + local fakestack = ItemStack(modname .. ":slab_" .. subname .. "_inverted") + pointed_thing.above = slabpos + fakestack = minetest.item_place(fakestack, placer, pointed_thing) + -- If the item was taken from the fake stack, decrement original + if not fakestack or fakestack:is_empty() then + itemstack:take_item(1) + -- Else put old node back + else + minetest.env:set_node(slabpos, slabnode) + end + return itemstack + end + + if n1.name == modname .. ":slab_" .. subname .. "_inverted" then + slabpos = p1 + slabnode = n1 + end + if slabpos then + -- Remove the slab at slabpos + minetest.env:remove_node(slabpos) + -- Make a fake stack of a single item and try to place it + local fakestack = ItemStack(modname .. ":slab_" .. subname .. "_three_quarter_inverted") + pointed_thing.above = slabpos + fakestack = minetest.item_place(fakestack, placer, pointed_thing) + -- If the item was taken from the fake stack, decrement original + if not fakestack or fakestack:is_empty() then + itemstack:take_item(1) + -- Else put old node back + else + minetest.env:set_node(slabpos, slabnode) + end + return itemstack + end + + if n1.name == modname .. ":slab_" .. subname .. "_three_quarter_inverted" then + slabpos = p1 + slabnode = n1 + end + if slabpos then + -- Remove the slab at slabpos + minetest.env:remove_node(slabpos) + -- Make a fake stack of a single item and try to place it + local fakestack = ItemStack(recipeitem) + pointed_thing.above = slabpos + fakestack = minetest.item_place(fakestack, placer, pointed_thing) + -- If the item was taken from the fake stack, decrement original + if not fakestack or fakestack:is_empty() then + itemstack:take_item(1) + -- Else put old node back + else + minetest.env:set_node(slabpos, slabnode) + end + return itemstack + end + + -- Otherwise place regularly + return minetest.item_place(itemstack, placer, pointed_thing) + end, + }) + + minetest.register_node(modname .. ":slab_" .. subname .. "_three_quarter", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":slab_" .. drop .. "_three_quarter", + paramtype = "light", + paramtype2 = paramtype2, + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0.25, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0.25, 0.5}, + }, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_node(modname .. ":slab_" .. subname .. "_three_quarter_inverted", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":slab_" .. drop .. "_three_quarter", + paramtype = "light", + paramtype2 = paramtype2, + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = {-0.5, -0.25, -0.5, 0.5, 0.5, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.25, -0.5, 0.5, 0.5, 0.5}, + }, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_craft({ + output = modname .. ":slab_" .. subname .. " 6", + recipe = { + {recipeitem, recipeitem, recipeitem}, + }, + }) + + minetest.register_craft({ + output = modname .. ":slab_" .. subname .. "_wall 6", + recipe = { + {recipeitem}, + {recipeitem}, + {recipeitem}, + }, + }) + + minetest.register_craft({ + output = modname .. ":slab_" .. subname .. "_inverted 1", + recipe = { + {modname .. ":slab_" .. subname}, + }, + }) + + minetest.register_craft({ + output = modname .. ":slab_" .. subname .. " 1", + recipe = { + {modname .. ":slab_" .. subname .. "_inverted"}, + }, + }) + + minetest.register_craft({ + output = recipeitem, + recipe = { + {modname .. ":slab_" .. subname}, + {modname .. ":slab_" .. subname}, + }, + }) + + minetest.register_craft({ + output = recipeitem, + recipe = { + {modname .. ":slab_" .. subname .. "_inverted"}, + {modname .. ":slab_" .. subname .. "_inverted"}, + }, + }) + + minetest.register_craft({ + output = recipeitem, + recipe = { + {modname .. ":slab_" .. subname .. "_wall", modname .. ":slab_" .. subname .. "_wall"}, + }, + }) + + minetest.register_craft({ + output = recipeitem, + recipe = { + {modname .. ":slab_" .. subname}, + {modname .. ":slab_" .. subname}, + }, + }) + + minetest.register_craft({ + output = modname .. ":slab_" .. subname .. "_quarter 6", + recipe = { + {modname .. ":slab_" .. subname, modname .. ":slab_" .. subname, modname .. ":slab_" .. subname}, + }, + }) + + minetest.register_craft({ + output = modname .. ":slab_" .. subname .. "_quarter_inverted 1", + recipe = { + {modname .. ":slab_" .. subname .. "_quarter"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":slab_" .. subname .. "_quarter 1", + recipe = { + {modname .. ":slab_" .. subname .. "_quarter_inverted"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":slab_" .. subname .. "_three_quarter_inverted 1", + recipe = { + {modname .. ":slab_" .. subname .. "_three_quarter"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":slab_" .. subname .. "_three_quarter 1", + recipe = { + {modname .. ":slab_" .. subname .. "_three_quarter_inverted"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":slab_" .. subname .. "_three_quarter 1", + recipe = { + {modname .. ":slab_" .. subname .. "_quarter"}, + {modname .. ":slab_" .. subname .. "_quarter"}, + {modname .. ":slab_" .. subname .. "_quarter"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":slab_" .. subname .. "_quarter 6", + recipe = { + {modname .. ":slab_" .. subname .. "_three_quarter"}, + {modname .. ":slab_" .. subname .. "_three_quarter"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":slab_" .. subname .. "_quarter_wall 6", + recipe = { + {modname .. ":slab_" .. subname .. "_wall"}, + {modname .. ":slab_" .. subname .. "_wall"}, + {modname .. ":slab_" .. subname .. "_wall"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":slab_" .. subname .. "_three_quarter_wall 1", + recipe = { + {modname .. ":slab_" .. subname .. "_quarter_wall", modname .. ":slab_" .. subname .. "_quarter_wall", modname .. ":slab_" .. subname .. "_quarter_wall"}, + }, + }) + +end + +-- Node will be called panel_ + +function poudlard.register_panel(modname, subname, recipeitem, groups, images, description, drop) + minetest.register_node(modname .. ":panel_" .. subname .. "_bottom", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":panel_" .. drop .. "_bottom", + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, 0, 0.5, 0, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, 0, 0.5, 0, 0.5}, + }, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_node(modname .. ":panel_" .. subname .. "_top", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":panel_" .. drop .. "_bottom", + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = {-0.5, 0, 0, 0.5, 0.5, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, 0, 0, 0.5, 0.5, 0.5}, + }, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_node(modname .. ":panel_" .. subname .. "_vertical", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":panel_" .. drop .. "_bottom", + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, 0, 0, 0.5, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, 0, 0, 0.5, 0.5}, + }, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_craft({ + output = modname .. ":panel_" .. subname .. "_bottom 8", + recipe = { + {recipeitem, recipeitem}, + }, + }) + + minetest.register_craft({ + output = modname .. ":panel_" .. subname .. "_vertical 8", + recipe = { + {recipeitem}, + {recipeitem}, + }, + }) + + minetest.register_craft({ + output = modname .. ":panel_" .. subname .. "_top 1", + recipe = { + {modname .. ":panel_" .. subname .. "_bottom"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":panel_" .. subname .. "_bottom 1", + recipe = { + {modname .. ":panel_" .. subname .. "_top"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":panel_" .. subname .. "_vertical 2", + recipe = { + {modname .. ":panel_" .. subname .. "_bottom"}, + {modname .. ":panel_" .. subname .. "_bottom"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":panel_" .. subname .. "_bottom 2", + recipe = { + {modname .. ":panel_" .. subname .. "_vertical", modname .. ":panel_" .. subname .. "_vertical"}, + }, + }) +end + +-- Node will be called micro_ + +function poudlard.register_micro(modname, subname, recipeitem, groups, images, description, drop) + minetest.register_node(modname .. ":micro_" .. subname .. "_bottom", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":micro_" .. drop .. "_bottom", + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, 0, 0, 0, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, 0, 0, 0, 0.5}, + }, + sounds = default.node_sound_stone_defaults(), + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + + local p0 = pointed_thing.under + local p1 = pointed_thing.above + if p0.y-1 == p1.y then + local fakestack = ItemStack(modname .. ":micro_" .. subname.. "_top") + local ret = minetest.item_place(fakestack, placer, pointed_thing) + if ret:is_empty() then + itemstack:take_item() + return itemstack + end + end + + -- Otherwise place regularly + return minetest.item_place(itemstack, placer, pointed_thing) + end, + }) + + minetest.register_node(modname .. ":micro_" .. subname .. "_top", { + description = description, + drawtype = "nodebox", + tiles = images, + drop = modname .. ":micro_" .. drop .. "_top", + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = true, + groups = groups, + node_box = { + type = "fixed", + fixed = {-0.5, 0, 0, 0, 0.5, 0.5}, + }, + selection_box = { + type = "fixed", + fixed = {-0.5, 0, 0, 0, 0.5, 0.5}, + }, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_craft({ + output = modname .. ":micro_" .. subname .. "_bottom 8", + recipe = { + {"default:stick"}, + {recipeitem}, + }, + }) + + minetest.register_craft({ + output = modname .. ":micro_" .. subname .. "_top 1", + recipe = { + {modname .. ":micro_" .. subname .. "_bottom"}, + }, + }) + + minetest.register_craft({ + output = modname .. ":micro_" .. subname .. "_bottom 1", + recipe = { + {modname .. ":micro_" .. subname .. "_top"}, + }, + }) +end + +dofile(minetest.get_modpath("poudlard").."/nodes.lua") +dofile(minetest.get_modpath("poudlard").."/registration.lua") +dofile(minetest.get_modpath("poudlard").."/aliases.lua") + + +-- REDEFINITION default:wood =facedir + +minetest.register_node(":default:wood", { + description = "Wooden Planks", + tiles = {"default_wood.png"}, + paramtype2 = "facedir", + groups = {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3,wood=1}, + sounds = default.node_sound_wood_defaults(), +}) + +-- RESPAWN def + +minetest.register_on_respawnplayer(function(player) + player:setpos({x=0, y=17, z=0}) + return true +end) diff --git a/mods/poudlard/locale/es.txt b/mods/poudlard/locale/es.txt new file mode 100644 index 0000000..0baac0b --- /dev/null +++ b/mods/poudlard/locale/es.txt @@ -0,0 +1,194 @@ + +# +# Language: Español +# Author: Diego Martínez +# + +### kitchen_cabinet.lua ### +Kitchen Cabinet = Gabinete de Cocina +## 1: Player name, 2: position +%s moves stuff in kitchen cabinet at %s = %s mueve cosas en gabinete de cocina en %s +%s moves stuff to kitchen cabinet at %s = %s mueve cosas al gabinete de cocina en %s +%s takes stuff from kitchen cabinet at %s = %s toma cosas del gabinete de cocina en %s +Half-height Kitchen Cabinet (on ceiling) = Gabinete de cocina de media altura (en techo) +Under-sink cabinet = Gabinete con Lavabo +Kitchen Cabinet with sink = Gabinete de cocina con lavabo + +### door_models.lua ### +Mahogany Closet Door = Puerta de Armario de Caoba +Oak Closet Door = Puerta de Armario de Roble +Fancy Wood/Glass Door = Puerta de Madera y Cristal de Lujo +Glass Office Door = Puerta de Oficina de Cristal +Glass and Wood, Mahogany-colored = Cristal y Madera, color Caoba +Glass and Wood, Oak-colored = Cristal y Madera, color Roble +Glass and Wood, White = Cristal y Madera, color Blanco +Plain Wooden Door = Puerta Simple de Madera +left = izquierda +right = derecha +## 1: Side the doors opens to +(Top Half, %s-opening) = (Parte Superior, abre a la %s) +(%s-opening) = (abre a la %s) + +### door_nodes.lua ### +Not enough vertical space to place a door! = ¡No hay suficiente espacio vertical para colocar una puerta! + +### crafts.lua ### +Brass Ingot = Lingote de Latón +Bucket of white paint = Cubo de Pintura Blanca +Legs for Small Utility table = Patas de Mesa Utilitaria Pequeña +Plastic sheet = Lámina de Plástico +Silicon lump = Terrón de Silicio +Simple Integrated Circuit = Circuito Integrado Simple +Small Wooden Drawer = Cajón Pequeño de Madera +Terracotta Roof Tile = Teja de Terracota +Titanium Dioxide = Dióxido de Titanio +Uncooked Terracotta Base = Base de Terracota sin Cocer +Unprocessed Plastic base = Base de Plástico sin Procesar + +### fences.lua ### +Barbed Wire Fence = Cerca de Alambre de Púas +Barbed Wire Fence Gate = Portón de Cerca de Alambre de Púas +Brass Fence/railing = Cerca/Barandilla de Latón +Brass Fence/railing with sign = Cerca/Barandilla de Latón con Letrero +Chainlink Fence = Cerca de Cadenas +Chainlink Fence Gate = Portón de Cerca de Cadenas +Chainlink Fence Gate (open) = Portón de Cerca de Cadenas (Abierto) +Unpainted Picket Fence = Cerca de Piquete sin pintar +Unpainted Picket Fence Gate = Portón de Cerca de Piquete sin pintar +White Picket Fence = Cerca de Piquete blanca +White Picket Fence Gate = Portón de Cerca de Piquete blanca +Wooden Privacy Fence = Cerca privada de madera +Wrought Iron Fence/railing = Cerca/Barandilla de Hierro Forjado +Wrought Iron Fence/railing with sign = Cerca/Barandilla de Hierro Forjado con Letrero +want to simply place the wielded item like usual. = solo se desea colocar el objeto empuñado normalmente. + +### furniture_medieval.lua ### +Bars = Barras +Binding Bars = Barras de Unión +Chains = Cadenas +Wall Torch = Antorcha de Pared + +### furniture_bathroom.lua ### +Toilet = Inodoro +Sink = Lavabo +Taps = Grifo +Shower Tray = Piso de Ducha +Shower Head = Ducha + +### init.lua ### +Loaded! = ¡Cargado! +Asphalt Shingles = Tejas de Asfalto +Black Plastic Flower Pot = Florero de Plástico Negro +Brass Pole = Poste de Latón +Brass Table Legs = Patas de Mesa de Latón +red = rojas +green = verdes +blue = azules +white = blancas +pink = rosas +violet = violetas +## 1: Color name +Curtains (%s) = Cortinas (%s) +Drop-Ceiling Tile = Cielorraso +Glass Skylight = Claraboya de Cristal +Glass Table (Small, Round) = Mesa de Cristal (Pequeña, Redonda) +Glass Table (Small, Square) = Mesa de Cristal (Pequeña, Cuadrada) +Green Plastic Flower Pot = Florero de Plástico Negro +Large Area Rug = Manta Grande +Large Glass Table Piece = Pieza de Mesa de Cristal Grande +Large Stereo Speaker = Altavoz de Estéreo Grande +Legs for Utility Table = Patas de Mesa Utilitaria +Projection Screen Material = Material de Pantalla de Proyección +Small Surround Speaker = Pequeño Altavoz Envolvente +Small Throw Rug = Manta Pequeña +Stereo Receiver = Receptor Estéreo +Terracotta Flower Pot = Florero de Terracota +Terracotta Roofing = Tejado de Terracota +Textured Ceiling Paint = Pintura Texturada para Techo +Utility Table = Mesa Utilitaria +Utility table mk2 = Mesa Utilitaria mk2 +Wooden Shutter (Black) = Obturador de Madera (Negro) +Wooden Shutter (Dark Grey) = Obturador de Madera (Gris Oscuro) +Wooden Shutter (Forest Green) = Obturador de Madera (Verde Bosque) +Wooden Shutter (Grey) = Obturador de Madera (Gris) +Wooden Shutter (Light Blue) = Obturador de Madera (Azul Claro) +Wooden Shutter (Purple) = Obturador de Madera (Púrpura) +Wooden Shutter (Red) = Obturador de Madera (Rojo) +Wooden Shutter (Unpainted Mahogany) = Obturador de Madera (Caoba sin Pintar) +Wooden Shutter (Unpainted Oak) = Obturador de Madera (Roble sin Pintar) +Wooden Shutter (White) = Obturador de Madera (Blanco) +Wooden Shutter (Yellow) = Obturador de Madera (Amarillo) +Wooden Tabletop piece = Pieza de Mesa de Madera +Wooden Tabletop (Small, Round) = Pieza de Mesa de Madera (Pequeña, Redonda) +Wooden Tabletop (Small, Square) = Pieza de Mesa de Madera (Pequeña, Cuadrada) +Wood Shingles = Tejas de Madera +Wrought Iron Pole = Poste de Hierro Forjado +someone = alguien +## 1: Player name +Sorry, %s owns that spot. = Lo siento, %s es dueño de ése lugar. + +### lighting.lua ### +White Glowlight (small cube) = Luz Blanca (cubo pequeño) +White Glowlight (small cube, on ceiling) = Luz Blanca (cubo pequeño, en techo) +White Glowlight (thick) = Luz Blanca (Gruesa) +White Glowlight (thick, on wall) = Luz Blanca (Gruesa, en pared) +White Glowlight (thin) = Luz Blanca (Fina) +White Glowlight (thin, on wall) = Luz Blanca (Fina, en pared) +Yellow Glowlight (small cube) = Luz Amarilla (cubo pequeño) +Yellow Glowlight (small cube, on ceiling) = Luz Amarilla (cubo pequeño, en techo) +Yellow Glowlight (thick) = Luz Amarilla (Gruesa) +Yellow Glowlight (thick, on wall) = Luz Amarilla (Gruesa, en pared) +Yellow Glowlight (thin) = Luz Amarilla (Fina) +Yellow Glowlight (thin, on wall) = Luz Amarilla (Fina, en pared) + +### locked.lua ### +## 1: Item description, 2: Owner name +%s (owned by %s) = %s (propiedad de %s) +## 1: Player name, 2: Item description, 3: Owner name, 4: Position +%s tried to access a %s belonging to %s at %s = %s ha intentado acceder un(a) %s propiedad de %s en %s +## 1: Item description +%s (Locked) = %s (Cerrado) +Locked Cabinet = Gabinete Cerrado +Locked Nightstand = Mesa de Noche Cerrada +Locked Fridge = Refri Cerrado +Locked Oven = Estufa Cerrada + +### nightstands.lua ### +Mahogany Nightstand with One Drawer = Mesa de Noche de Caoba, un Cajón +Mahogany Nightstand with Two Drawers = Mesa de Noche de Caoba, dos Cajones +Oak Nightstand with One Drawer = Mesa de Noche de Roble, un Cajón +Oak Nightstand with Two Drawers = Mesa de Noche de Roble, dos Cajones +## 1: Player name, 2: position +%s moves stuff in nightstand at %s = %s mueve cosas en mesa de noche en %s +%s moves stuff to nightstand at %s = %s mueve cosas hacia mesa de noche en %s +%s takes stuff from nightstand at %s = %s mueve cosas desde mesa de noche en %s +One-drawer Nightstand = Mesa de Noche de un Cajón +Two-drawer Nightstand = Mesa de Noche de dos Cajones + +### oven.lua ### +Oven = Estufa +## 1: Item name +Could not insert '%s' = No se pudo insertar '%s' +## 1: Percentage +Oven active: %d%% = Estufa activa: %d%% +Oven out of fuel = Estufa sin combustible +Oven is empty = Estufavacía + +### refrigerator.lua ### +Refrigerator = Refrigerador +## 1: Player name, 2: position +%s moves stuff in refrigerator at %s = %s mueve cosas en refrigerador en %s +%s moves stuff to refrigerator at %s = %s mueve cosas hacia refrigerador en %s +%s takes stuff from refrigerator at %s = %s mueve cosas desde refrigerador en %s +Not enough vertical space to place a refrigerator! = ¡No hay suficiente espacio vertical para colocar un refrigerador! + +### television.lua ### +Small CRT Television = Pequeña Televisión CRT + +### signs_lib.lua ### +%s wrote "%s" to sign at %s = %s ha escrito "%s" en el letrero en %s +Reading cached character database. = Leyendo base de datos de catacteres. +Font seems to have changed. Rebuilding cache. = La fuente parece haber cambiado. Reconstruyendo información guardada. +Could not find font line height in cached DB. Trying brute force. = No se pudo encontrar la altura de línea en la base de datos. Intentando con fuerza bruta. +Registered %s and %s = Registrados %s y %s +signs loaded = letreros cargados diff --git a/mods/poudlard/locale/fr.txt b/mods/poudlard/locale/fr.txt new file mode 100644 index 0000000..2a17a28 --- /dev/null +++ b/mods/poudlard/locale/fr.txt @@ -0,0 +1,180 @@ + +# +# Language: Français +# Author: Calinou +# + +### kitchen_cabinet.lua ### +Kitchen Cabinet = Meuble de cuisine +## 1: Player name, 2: position +%s moves stuff in kitchen cabinet at %s = %s déplace des objets dans un meuble de cuisine à %s +%s moves stuff to kitchen cabinet at %s = %s édplace des objets vers un meuble de cuisine à %s +%s takes stuff from kitchen cabinet at %s = %s prend des objets d'un meuble de cuisine à %s +Half-height Kitchen Cabinet (on ceiling) = Meuble de cuisine réduit en hauteur (sur le plafond) +Under-sink cabinet = Meuble sous évier +Kitchen Cabinet with sink = Meuble de cuisine avec lavabo + +### door_models.lua ### +Mahogany Closet Door = Porte en bois d'acajou +Oak Closet Door = Porte en bois de chêne +Fancy Wood/Glass Door = Porte artistique en bois et verre +Glass Office Door = Porte en verre +Glass and Wood, Mahogany-colored = Porte couleur acajou en bois et verre +Glass and Wood, Oak-colored = Porte couleur chêne en bois et verre +Glass and Wood, White = Porte blanche en bois et verre +Plain Wooden Door = Porte en bois simple +left = gauche +right = droite +## 1: Side the doors opens to +(Top Half, %s-opening) = (partie supérieur, charnière à %s) +(%s-opening) = (charnière à %s) + +### door_nodes.lua ### +Not enough vertical space to place a door! = Pas assez d'espace vertical pour placer une porte ! + +### crafts.lua ### +Brass Ingot = Lingot de laiton +Bucket of white paint = Seau de peinture blanche +Legs for Small Utility table = Pieds pour table basse +Plastic sheet = Bout de plastique +Silicon lump = Silicone +Simple Integrated Circuit = Circuit intégré simple +Small Wooden Drawer = Petit tiroir en bois +Terracotta Roof Tile = Tuile de toit en terre cuite +Titanium Dioxide = Dioxide de titane +Uncooked Terracotta Base = Base de terre non cuite +Unprocessed Plastic base = Base de plastique non transformée + +### fences.lua ### +Barbed Wire Fence = Barrière en fil barbelé +Barbed Wire Fence Gate = Porte de barrière en fil barbelé +Brass Fence/railing = Barrière en laiton +Brass Fence/railing with sign = Barrière en laiton avec pancarte +Chainlink Fence = Grillage +Chainlink Fence Gate = Porte de grillage +Chainlink Fence Gate (open) = Porte de grillage (ouverte) +Unpainted Picket Fence = Barrière en piquets non peinte +Unpainted Picket Fence Gate = Porte de barrière en piquets non peinte +White Picket Fence = Barrière en piquets blanche +White Picket Fence Gate = Porte de barrière en piquets blanche +Wooden Privacy Fence = Barrière en bois +Wrought Iron Fence/railing = Barrière en fer forgé +Wrought Iron Fence/railing with sign = Barrière en fer forgé avec pancarte +want to simply place the wielded item like usual. = veut simplement placer l'objet comme d'habitude. + +### init.lua ### +Loaded! = Chargé ! +Asphalt Shingles = Bardeaux d'asphalte +Black Plastic Flower Pot = Pot de fleur en plastique noir +Brass Pole = Barre en laiton +Brass Table Legs = Pieds de table en laiton +red = rouges +green = vertes +blue = bleues +white = blanches +pink = roses +violet = violettes +## 1: Color name +Curtains (%s) = Volets (%s) +Drop-Ceiling Tile = Dalle suspendue au plafond +Glass Skylight = Verre +Glass Table (Small, Round) = Table en verre (petite, ronde) +Glass Table (Small, Square) = Table en verre (petite, carrée) +Green Plastic Flower Pot = Pot de fleur en plastique vert +Large Area Rug = Grande couverture +Large Glass Table Piece = Grand bout de verre de table +Large Stereo Speaker = Grand haut-parleur stéréo +Legs for Utility Table = Pieds pour table basse +Projection Screen Material = Matériel pour projecteur +Small Surround Speaker = Petit haut-parleur surround +Small Throw Rug = Petite couverture +Stereo Receiver = Récepteur stéréo +Terracotta Flower Pot = Pot de fleur en terre cuite +Terracotta Roofing = Tuile en terre cuite +Textured Ceiling Paint = Papier peint avec motif pour plafond +Utility Table = Table basse +Utility table mk2 = Table basse MK2 +Wooden Shutter (Black) = Volet en bois (noir) +Wooden Shutter (Dark Grey) = Volet en bois (gris foncé) +Wooden Shutter (Forest Green) = Volet en bois (vert foncé) +Wooden Shutter (Grey) = Volet en bois (gris) +Wooden Shutter (Light Blue) = Volet en bois (bleu clair) +Wooden Shutter (Purple) = Volet en bois (violet) +Wooden Shutter (Red) = Volet en bois (rouge) +Wooden Shutter (Unpainted Mahogany) = Volet en bois (acajou non peint) +Wooden Shutter (Unpainted Oak) = Volet en bois (chêne non peint) +Wooden Shutter (White) = Volet en bois (blanc) +Wooden Shutter (Yellow) = Volet en bois (jaune) +Wooden Tabletop piece = Bout de dessus de table +Wooden Tabletop (Small, Round) = Dessus de table (petit, rond) +Wooden Tabletop (Small, Square) = Dessus de table (petit, carré) +Wood Shingles = Bardeaux de bois +Wrought Iron Pole = Barre de fer forgé +someone = quelqu'un +## 1: Player name +Sorry, %s owns that spot. = Désolé, %s est propriétaire de cette zone. + +### lighting.lua ### +White Glowlight (small cube) = Lampe blanche (petit cube) +White Glowlight (small cube, on ceiling) = Lampe blanche (petit cube, sur le plafond) +White Glowlight (thick) = Lampe blanche (épaisse) +White Glowlight (thick, on wall) = Lampe blanche (épaisse, sur le mur) +White Glowlight (thin) = Lampe blanche (fine) +White Glowlight (thin, on wall) = Lampe blanche (fine, sur le mur) +Yellow Glowlight (small cube) = Lampe jaune (petit cube) +Yellow Glowlight (small cube, on ceiling) = Lampe jaune (petit cube, sur le plafond) +Yellow Glowlight (thick) = Lampe jaune (épaisse) +Yellow Glowlight (thick, on wall) = Lampe jaune (épaisse, sur le mur) +Yellow Glowlight (thin) = Lampe jaune (fine) +Yellow Glowlight (thin, on wall) = Lampe jaune (fine, sur le mur) + +### locked.lua ### +## 1: Item description, 2: Owner name +%s (owned by %s) = %s (propriété de %s) +## 1: Player name, 2: Item description, 3: Owner name, 4: Position +%s tried to access a %s belonging to %s at %s = %s a essayé d'accéder à %s qui est propriété de %s à %s +## 1: Item description +%s (Locked) = %s (verrouillé) +Locked Cabinet = Meuble verrouillé +Locked Nightstand = Table de chevet verrouillée +Locked Fridge = Réfrégirateur verrouillé +Locked Oven = Four verrouillé + +### nightstands.lua ### +Mahogany Nightstand with One Drawer = Table de chevet en acajou avec un tiroir +Mahogany Nightstand with Two Drawers = Table de chevet en acajou avec deux tiroirs +Oak Nightstand with One Drawer = Table de chevet en chêne avec un tiroir +Oak Nightstand with Two Drawers = Table de chevet en chêne avec deux tiroirs +## 1: Player name, 2: position +%s moves stuff in nightstand at %s = %s déplace des objets dans une table de chevet à %s +%s moves stuff to nightstand at %s = %s déplace des objets vers une table de chevet à %s +%s takes stuff from nightstand at %s = %s prend des objets d'une table de chevet à %s +One-drawer Nightstand = Table de chevet avec un tiroir +Two-drawer Nightstand = Table de chevet avec deux tiroirs + +### oven.lua ### +Oven = Four +## 1: Item name +Could not insert '%s' = Ne peut insérer '%s' +## 1: Percentage +Oven active: %d%% = Four actif : %d%% +Oven out of fuel = Four sans carburant +Oven is empty = Four vide + +### refrigerator.lua ### +Refrigerator = Réfrégirateur +## 1: Player name, 2: position +%s moves stuff in refrigerator at %s = %s déplace des objets dans un réfrégirateur à %s +%s moves stuff to refrigerator at %s = %s déplace des objets vers un réfrégirateur à %s +%s takes stuff from refrigerator at %s = %s prend des objets d'un réfrégirateur à %s +Not enough vertical space to place a refrigerator! = Pas assez d'espace vertical pour placer un réfrégirateur ! + +### television.lua ### +Small CRT Television = Petite télévision à tube cathodique + +### signs_lib.lua ### +E: character map file not found = E: fichier de table de caractère non trouvé +## 1: Full String, 2: pos in string, 3: current char at pos +W: unknown symbol in '%s' at %d (probably %s) = A: symbole inconnu dans '%s' dans %d (probablement %s) +%s wrote "%s" to sign at %s = +signs loaded = diff --git a/mods/poudlard/locale/pt.txt b/mods/poudlard/locale/pt.txt new file mode 100644 index 0000000..bd8e435 --- /dev/null +++ b/mods/poudlard/locale/pt.txt @@ -0,0 +1,198 @@ + +# Brazilian Portuguese translation of homedecor +# Last update: 2013/11/10 +# Last translator: Aracnus + +### Special strings ### + +### kitchen_cabinet.lua ### +Kitchen Cabinet = Armário de cozinha +## 1: Player name, 2: position +%s moves stuff in kitchen cabinet at %s = %s moveu itens no armário de cozinha em %s +%s moves stuff to kitchen cabinet at %s = %s moveu itens para o armário de cozinha em %s +%s takes stuff from kitchen cabinet at %s = %s retirou itens do armário de cozinha em %s +Half-height Kitchen Cabinet (on ceiling) = Meio armário de cozinha (no teto) +Under-sink cabinet = Armário sob a pia +Kitchen Cabinet with sink = Armário de cozinha com pia + +### door_models.lua ### +Mahogany Closet Door = Porta do armário de mogno +Oak Closet Door = Porta do armário de carvalho +Fancy Wood/Glass Door = Porta de madeira/vidro trabalhada +Glass Office Door = Porta de escritório de vidro +Glass and Wood, Mahogany-colored = Vidro e madeira (mogno) +Glass and Wood, Oak-colored = Vidro e madeira (carvalho) +Glass and Wood, White = Vidro e madeira (branca) +Plain Wooden Door = Porta de madeira simples +left = esquerda +right = direita +## 1: Side the doors opens to +(Top Half, %s-opening) = (Metade superior, abre para %s) +(%s-opening) = (abre para %s) + + +### door_nodes.lua ### +Not enough vertical space to place a door! = Não existe espaço vertical suficiente para colocar uma porta. + +### crafts.lua ### +Brass Ingot = Lingote de bronze +Bucket of white paint = Balde de tinta branca +Legs for Small Utility table = Pernas para mesa pequena +Plastic sheet = Folha de plástico +Silicon lump = Massa de silício +Simple Integrated Circuit = Circuito integrado simples +Small Wooden Drawer = Gaveta pequena de madeira +Terracotta Roof Tile = Telha de terracota +Titanium Dioxide = Dióxido de titânio +Uncooked Terracotta Base = Base bruta de terracota +Unprocessed Plastic base = Base de plástico não processada + +### door_models.lua ### + +### door_nodes.lua ### + +### fences.lua ### +Barbed Wire Fence = Cerca de arame farpado +Barbed Wire Fence Gate = Portão da cerca de arame farpado +Brass Fence/railing = Cerca/corrimão de bronze +Brass Fence/railing with sign = Cerca/corrimão de bronze, com placa +Chainlink Fence = Cerca de tela de arame +Chainlink Fence Gate = Portão da cerca de tela de arame +Chainlink Fence Gate (open) = Portão da cerca de tela de arame (aberto) +Unpainted Picket Fence = Cerca de tábuas não pintada +Unpainted Picket Fence Gate = Portão da cerca de madeira não pintado +White Picket Fence = Cerca de madeira branca +White Picket Fence Gate = Portão da cerca de madeira branco +Wooden Privacy Fence = Cerca fechada de mandeira +Wrought Iron Fence/railing = Cerca/corrimão de ferro forjado +Wrought Iron Fence/railing with sign = Cerca/corrimão de ferro forjado, com placa +want to simply place the wielded item like usual. = quer somente colocar o item empunhado normalmente. + +### furniture_medieval.lua ### +Bars = Barras +Binding Bars = Barras do canto +Chains = Correntes +Wall Torch = Tocha de parede + +### furniture_bathroom.lua ### +Toilet = Vaso sanitário +Sink = Pia +Taps = Torneira +Shower Tray = Ralo do chuveiro +Shower Head = Chuveiro + +### init.lua ### +Loaded! = Carregado! +Asphalt Shingles = Telhas de asfalto +Black Plastic Flower Pot = Vaso de flor de plástico preto +Brass Pole = Poste de bronze +Brass Table Legs = Pernas da mesa de bronze +red = vermelho +green = verde +blue = azul +white = branco +pink = rosa +violet = violeta +## 1: Color name +Curtains (%s) = Cortina (%s) +Drop-Ceiling Tile = Placa de teto +Glass Skylight = Claraboia de vidro +Glass Table (Small, Round) = Mesa de vidro (pequena, redonda) +Glass Table (Small, Square) = Mesa de vidro (pequena, quadrada) +Green Plastic Flower Pot = Vaso de flor de plástico verde +Large Area Rug = Tapete grande +Large Glass Table Piece = Pedaço da mesa grande de vidro +Large Stereo Speaker = Auto-falante grande +Legs for Utility Table = Pernas para mesa +Projection Screen Material = Material de tela de projeção +Small Surround Speaker = Auto-falante pequeno +Small Throw Rug = Tapete pequeno +Stereo Receiver = Aparelho de som +Terracotta Flower Pot = Vaso de flor de terracota +Terracotta Roofing = Telhado de terracota +Textured Ceiling Paint = Pintura texturizada do teto +Utility Table = Mesa de trabalho +Utility table mk2 = Mesa de trabalho mk2 +Wooden Shutter (Black) = Persiana de madeira (preta) +Wooden Shutter (Dark Grey) = Persiana de madeira (cinza escura) +Wooden Shutter (Forest Green) = Persiana de madeira (verde) +Wooden Shutter (Grey) = Persiana de madeira (cinza) +Wooden Shutter (Light Blue) = Persiana de madeira (azul clara) +Wooden Shutter (Purple) = Persiana de madeira (roxa) +Wooden Shutter (Red) = Persiana de madeira (vermelha) +Wooden Shutter (Unpainted Mahogany) = Persiana de madeira (mogno) +Wooden Shutter (Unpainted Oak) = Persiana de madeira (carvalho) +Wooden Shutter (White) = Persiana de madeira (branca) +Wooden Shutter (Yellow) = Persiana de madeira (amarela) +Wooden Tabletop piece = Pedaço do tampo da mesa +Wooden Tabletop (Small, Round) = Tampo da mesa (pequeno, arredondado) +Wooden Tabletop (Small, Square) = Tampo da mesa (pequeno, quadrado) +Wood Shingles = Telhas de madeira +Wrought Iron Pole = Poste de ferro forjado +someone = alguém +## 1: Player name +Sorry, %s owns that spot. = Desculpe, mas esse local pertence a %s. + +### lighting.lua ### +White Glowlight (small cube) = Arandela branca (cubo pequeno) +White Glowlight (small cube, on ceiling) = Arandela branca (cubo pequeno, na parede) +White Glowlight (thick) = Arandela branca (grossa) +White Glowlight (thick, on wall) = Arandela branca (grossa, na parede) +White Glowlight (thin) = Arandela branca (fina) +White Glowlight (thin, on wall) = Arandela branca (fina, na parede) +Yellow Glowlight (small cube) = Arandela amarela (cubo pequeno) +Yellow Glowlight (small cube, on ceiling) = Arandela amarela (cubo pequeno, na parede) +Yellow Glowlight (thick) = Arandela amarela (grossa) +Yellow Glowlight (thick, on wall) = Arandela amarela (grossa, na parede) +Yellow Glowlight (thin) = Arandela amarela (fina) +Yellow Glowlight (thin, on wall) = Arandela amarela (fina, na parede) + +### locked.lua ### +## 1: Item description, 2: Owner name +%s (owned by %s) = %s (pertence a %s) +## 1: Player name, 2: Item description, 3: Owner name, 4: Position +%s tried to access a %s belonging to %s at %s = %s tentou acessar %s pertencente a %s em %s +## 1: Item description +%s (Locked) = %s (trancado) +Locked Cabinet = Armário trancado +Locked Nightstand = Criado-mudo trancado + +### nightstands.lua ### +Mahogany Nightstand with One Drawer = Criado-mudo de mogno, com uma gaveta +Mahogany Nightstand with Two Drawers = Criado-mudo de mogno, com duas gavetas +Oak Nightstand with One Drawer = Criado-mudo de carvalho, com uma gaveta +Oak Nightstand with Two Drawers = Criado-mudo de carvalho, com duas gavetas +## 1: Player name, 2: position +%s moves stuff in nightstand at %s = %s moveu item(ns) no criado-mudo em %s +%s moves stuff to nightstand at %s = %s moveu item(ns) para o criado-mudo em %s +%s takes stuff from nightstand at %s = %s tirou item(ns) do criado-mudo em %s +One-drawer Nightstand = Criado-mudo com uma gaveta +Two-drawer Nightstand = Criado-mudo com duas gavetas + +### oven.lua ### +Oven = Forno +## 1: Item name +Could not insert '%s' = Não foi possível inserir '%s' +## 1: Percentage +Oven active: %d%% = Forno ativo: %d%% +Oven out of fuel = O forno está sem combustível +Oven is empty = O forno está vazio + +### refrigerator.lua ### +Refrigerator = Geladeira +## 1: Player name, 2: position +%s moves stuff in refrigerator at %s = %s moveu item(ns) na geladeira em %s +%s moves stuff to refrigerator at %s = %s moveu item(ns) para a geladeira em %s +%s takes stuff from refrigerator at %s = %s tirou item(ns) da geladeira em %s +Not enough vertical space to place a refrigerator! = Não existe espaço vertical suficiente para adicionar uma geladeira. + +### television.lua ### +Small CRT Television = TV de tubo pequena + +### signs_lib.lua ### +%s wrote "%s" to sign at %s = %s escreveu "%s" na placa em %s +Reading cached character database. = Lendo banco de dados de caracteres no cache. +Font seems to have changed. Rebuilding cache. = Aparentemente as fontes foram alteradas. Reconstruindo o cache. +Could not find font line height in cached DB. Trying brute force. = Não foi possível encontrar a altura da linha da fonte no cache do BD. Tentando na marra. +Registered %s and %s = %s e %s registrados +signs loaded = placas carregadas diff --git a/mods/poudlard/locale/template.txt b/mods/poudlard/locale/template.txt new file mode 100644 index 0000000..fd1b64b --- /dev/null +++ b/mods/poudlard/locale/template.txt @@ -0,0 +1,198 @@ + +########################## +# Template language file # +########################## + +### Special strings ### + +### kitchen_cabinet.lua ### +Kitchen Cabinet = +## 1: Player name, 2: position +%s moves stuff in kitchen cabinet at %s = +%s moves stuff to kitchen cabinet at %s = +%s takes stuff from kitchen cabinet at %s = +Half-height Kitchen Cabinet (on ceiling) = +Under-sink cabinet = +Kitchen Cabinet with sink = + +### door_models.lua ### +Mahogany Closet Door = +Oak Closet Door = +Fancy Wood/Glass Door = +Glass Office Door = +Glass and Wood, Mahogany-colored = +Glass and Wood, Oak-colored = +Glass and Wood, White = +Plain Wooden Door = +left = +right = +## 1: Side the doors opens to +(Top Half, %s-opening) = +(%s-opening) = + + +### door_nodes.lua ### +Not enough vertical space to place a door! = + +### crafts.lua ### +Brass Ingot = +Bucket of white paint = +Legs for Small Utility table = +Plastic sheet = +Silicon lump = +Simple Integrated Circuit = +Small Wooden Drawer = +Terracotta Roof Tile = +Titanium Dioxide = +Uncooked Terracotta Base = +Unprocessed Plastic base = + +### door_models.lua ### + +### door_nodes.lua ### + +### fences.lua ### +Barbed Wire Fence = +Barbed Wire Fence Gate = +Brass Fence/railing = +Brass Fence/railing with sign = +Chainlink Fence = +Chainlink Fence Gate = +Chainlink Fence Gate (open) = +Unpainted Picket Fence = +Unpainted Picket Fence Gate = +White Picket Fence = +White Picket Fence Gate = +Wooden Privacy Fence = +Wrought Iron Fence/railing = +Wrought Iron Fence/railing with sign = +want to simply place the wielded item like usual. = + +### furniture_medieval.lua ### +Bars = +Binding Bars = +Chains = +Wall Torch = + +### furniture_bathroom.lua ### +Toilet = +Sink = +Taps = +Shower Tray = +Shower Head = + +### init.lua ### +Loaded! = +Asphalt Shingles = +Black Plastic Flower Pot = +Brass Pole = +Brass Table Legs = +red = +green = +blue = +white = +pink = +violet = +## 1: Color name +Curtains (%s) = +Drop-Ceiling Tile = +Glass Skylight = +Glass Table (Small, Round) = +Glass Table (Small, Square) = +Green Plastic Flower Pot = +Large Area Rug = +Large Glass Table Piece = +Large Stereo Speaker = +Legs for Utility Table = +Projection Screen Material = +Small Surround Speaker = +Small Throw Rug = +Stereo Receiver = +Terracotta Flower Pot = +Terracotta Roofing = +Textured Ceiling Paint = +Utility Table = +Utility table mk2 = +Wooden Shutter (Black) = +Wooden Shutter (Dark Grey) = +Wooden Shutter (Forest Green) = +Wooden Shutter (Grey) = +Wooden Shutter (Light Blue) = +Wooden Shutter (Purple) = +Wooden Shutter (Red) = +Wooden Shutter (Unpainted Mahogany) = +Wooden Shutter (Unpainted Oak) = +Wooden Shutter (White) = +Wooden Shutter (Yellow) = +Wooden Tabletop piece = +Wooden Tabletop (Small, Round) = +Wooden Tabletop (Small, Square) = +Wood Shingles = +Wrought Iron Pole = +someone = +## 1: Player name +Sorry, %s owns that spot. = + +### lighting.lua ### +White Glowlight (small cube) = +White Glowlight (small cube, on ceiling) = +White Glowlight (thick) = +White Glowlight (thick, on wall) = +White Glowlight (thin) = +White Glowlight (thin, on wall) = +Yellow Glowlight (small cube) = +Yellow Glowlight (small cube, on ceiling) = +Yellow Glowlight (thick) = +Yellow Glowlight (thick, on wall) = +Yellow Glowlight (thin) = +Yellow Glowlight (thin, on wall) = + +### locked.lua ### +## 1: Item description, 2: Owner name +%s (owned by %s) = +## 1: Player name, 2: Item description, 3: Owner name, 4: Position +%s tried to access a %s belonging to %s at %s = +## 1: Item description +%s (Locked) = +Locked Cabinet = +Locked Nightstand = + +### nightstands.lua ### +Mahogany Nightstand with One Drawer = +Mahogany Nightstand with Two Drawers = +Oak Nightstand with One Drawer = +Oak Nightstand with Two Drawers = +## 1: Player name, 2: position +%s moves stuff in nightstand at %s = +%s moves stuff to nightstand at %s = +%s takes stuff from nightstand at %s = +One-drawer Nightstand = +Two-drawer Nightstand = + +### oven.lua ### +Oven = +## 1: Item name +Could not insert '%s' = +## 1: Percentage +Oven active: %d%% = +Oven out of fuel = +Oven is empty = + +### refrigerator.lua ### +Refrigerator = +## 1: Player name, 2: position +%s moves stuff in refrigerator at %s = +%s moves stuff to refrigerator at %s = +%s takes stuff from refrigerator at %s = +Not enough vertical space to place a refrigerator! = + +### television.lua ### +Small CRT Television = + +### signs_lib.lua ### +%s wrote "%s" to sign at %s = +Reading cached character database. = +Font seems to have changed. Rebuilding cache. = +Could not find font line height in cached DB. Trying brute force. = +Registered %s and %s = +signs loaded = diff --git a/mods/poudlard/nodes.lua b/mods/poudlard/nodes.lua new file mode 100644 index 0000000..fdab600 --- /dev/null +++ b/mods/poudlard/nodes.lua @@ -0,0 +1,354 @@ +--Poudlard mod by Perlipop +--Code imported from moreblocks by Calinou + + +-- Blocks +minetest.register_node("poudlard:poudstone", { + description = "Poudstone", + tiles = {"poudlard_poudstone.png"}, + is_ground_content = true, + groups = {cracky=3, stone=2}, + sounds = default.node_sound_stone_defaults(), +}) + + +minetest.register_node("poudlard:poudwood", { + description = "Poudlard Wooden Planks", + tiles = {"poudlard_poudwood.png"}, + is_ground_content = true, + groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,flammable=3}, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_node("poudlard:redblock", { + description = "Red block", + tiles = {"poudlard_redblock.png"}, + is_ground_content = true, + groups = {cracky=3, stone=2}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("poudlard:blackblock", { + description = "black block", + tiles = {"poudlard_blackblock.png"}, + is_ground_content = true, + groups = {cracky=3, stone=2}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("poudlard:junglewood", { + description = "Jungle Wooden Planks", + tiles = {"poudlard_junglewood.png"}, + paramtype2 = "facedir", + is_ground_content = true, + groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,flammable=3}, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_node("poudlard:stonebrick", { + description = "Stone Bricks", + tiles = {"poudlard_stonebrick.png"}, + is_ground_content = true, + groups = {cracky=3}, + sounds = default.node_sound_stone_defaults(), +}) + + +minetest.register_node("poudlard:circlestonebricks", { + description = "Circle Stone Bricks", + tiles = {"poudlard_circlestonebrick.png"}, + is_ground_content = true, + groups = {cracky=3}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("poudlard:ironstonebricks", { + description = "Iron Stone Bricks", + tiles = {"poudlard_ironstonebrick.png"}, + is_ground_content = true, + groups = {cracky=3}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("poudlard:stone_tile", { + description = "Stonesquare", + tiles = {"poudlard_stonesquare.png"}, + is_ground_content = true, + groups = {cracky=3}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("poudlard:split_stone_tile", { + description = "Split Stonesquare", + tiles = {"poudlard_splitstonesquare_top.png", "poudlard_splitstonesquare.png"}, + is_ground_content = true, + groups = {cracky=3}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("poudlard:plankstone", { + description = "Plankstone", + tiles = { + "poudlard_plankstone.png", + "poudlard_plankstone.png", + "poudlard_plankstone.png", + "poudlard_plankstone.png", + "poudlard_plankstone_2.png", + "poudlard_plankstone_2.png", + }, + is_ground_content = true, + groups = {cracky=3}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("poudlard:ironglass", { + description = "Iron Glass", + drawtype = "glasslike", + tiles = {"poudlard_ironglass.png"}, + inventory_image = minetest.inventorycube("poudlard_ironglass.png"), + paramtype = "light", + sunlight_propagates = true, + is_ground_content = true, + groups = {snappy=2,cracky=3,oddly_breakable_by_hand=3}, + sounds = default.node_sound_glass_defaults(), +}) + +minetest.register_node("poudlard:coalglass", { + description = "Coal Glass", + drawtype = "glasslike", + tiles = {"poudlard_coalglass.png"}, + inventory_image = minetest.inventorycube("poudlard_coalglass.png"), + paramtype = "light", + sunlight_propagates = true, + is_ground_content = true, + groups = {snappy=2,cracky=3,oddly_breakable_by_hand=3}, + sounds = default.node_sound_glass_defaults(), +}) + +minetest.register_node("poudlard:cleanglass", { + description = "Clean Glass", + drawtype = "glasslike", + tiles = {"poudlard_cleanglass.png"}, + inventory_image = minetest.inventorycube("poudlard_cleanglass.png"), + paramtype = "light", + sunlight_propagates = true, + is_ground_content = true, + groups = {snappy=2,cracky=3,oddly_breakable_by_hand=3}, + sounds = default.node_sound_glass_defaults(), +}) + + +minetest.register_node("poudlard:cactuschecker", { + description = "Cactus Checker", + tiles = { + "poudlard_cactuschecker.png", + "poudlard_cactuschecker.png", + "poudlard_cactuschecker.png", + "poudlard_cactuschecker.png", + "poudlard_cactuschecker_2.png", + "poudlard_cactuschecker_2.png", + }, + is_ground_content = true, + groups = {cracky=3}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("poudlard:emptybookshelf", { + description = "Empty Bookshelf", + tiles = {"default_wood.png", "default_wood.png", "poudlard_emptybookshelf.png"}, + is_ground_content = true, + groups = {snappy=2,choppy=3,oddly_breakable_by_hand=2,flammable=3}, + sounds = default.node_sound_wood_defaults(), +}) + + +minetest.register_node("poudlard:coalstone", { + description = "Coal Stone", + tiles = {"poudlard_coalstone.png"}, + is_ground_content = true, + groups = {cracky=3}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("poudlard:ironstone", { + description = "Iron Stone", + tiles = {"poudlard_ironstone.png"}, + is_ground_content = true, + groups = {cracky=3}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("poudlard:coalchecker", { + description = "Coal Checker", + tiles = { + "poudlard_coalchecker.png", + "poudlard_coalchecker.png", + "poudlard_coalchecker.png", + "poudlard_coalchecker.png", + "poudlard_coalchecker_2.png", + "poudlard_coalchecker_2.png", + }, + is_ground_content = true, + groups = {cracky=3}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("poudlard:ironchecker", { + description = "Iron Checker", + tiles = { + "poudlard_ironchecker.png", + "poudlard_ironchecker.png", + "poudlard_ironchecker.png", + "poudlard_ironchecker.png", + "poudlard_ironchecker_2.png", + "poudlard_ironchecker_2.png", + }, + is_ground_content = true, + groups = {cracky=3}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("poudlard:trapstone", { + description = "Trapstone", + tiles = {"poudlard_trapstone.png"}, + walkable = false, + is_ground_content = true, + groups = {cracky=3}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("poudlard:trapglass", { + description = "Trapglass", + drawtype = "glasslike", + tiles = {"poudlard_trapglass.png"}, + inventory_image = minetest.inventorycube("poudlard_trapglass.png"), + paramtype = "light", + sunlight_propagates = true, + walkable = false, + is_ground_content = true, + groups = {snappy=2,cracky=3,oddly_breakable_by_hand=3}, + sounds = default.node_sound_glass_defaults(), +}) + +minetest.register_node("poudlard:fence_junglewood", { + description = "Jungle Wood Fence", + drawtype = "fencelike", + tiles = {"poudlard_junglewood.png"}, + inventory_image = "poudlard_junglewood_fence.png", + wield_image = "poudlard_junglewood_fence.png", + paramtype = "light", + is_ground_content = true, + selection_box = { + type = "fixed", + fixed = {-1/7, -1/2, -1/7, 1/7, 1/2, 1/7}, + }, + groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,flammable=2}, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_node("poudlard:horizontaltree", { + description = "Horizontal Tree", + tiles = {"default_tree.png", "default_tree.png", "poudlard_horizontaltree.png", + "poudlard_horizontaltree.png", "default_tree_top.png", "default_tree_top.png"}, + paramtype2 = "facedir", + groups = {tree=1,snappy=1,choppy=2,oddly_breakable_by_hand=1,flammable=2}, + sounds = default.node_sound_wood_defaults(), + furnace_burntime = 30, +}) + + +minetest.register_node("poudlard:allfacestree", { + description = "All-faces Tree", + tiles = {"default_tree_top.png"}, + groups = {tree=1,snappy=1,choppy=2,oddly_breakable_by_hand=1,flammable=2}, + sounds = default.node_sound_wood_defaults(), + furnace_burntime = 30, +}) + +minetest.register_node("poudlard:alltree", { + description = "All-faces Tree", + tiles = {"default_tree.png"}, + groups = {tree=1,snappy=1,choppy=2,oddly_breakable_by_hand=1,flammable=2}, + sounds = default.node_sound_wood_defaults(), + furnace_burntime = 30, +}) + +minetest.register_node("poudlard:superglowglass", { + description = "Super Glowglass", + drawtype = "glasslike", + tiles = {"poudlard_glowglass.png"}, + inventory_image = minetest.inventorycube("poudlard_glowglass.png"), + paramtype = "light", + sunlight_propagates = true, + light_source = 15, + is_ground_content = true, + groups = {snappy=2,cracky=3,oddly_breakable_by_hand=3}, + sounds = default.node_sound_glass_defaults(), +}) + +minetest.register_node("poudlard:rope", { + description = "Rope", + drawtype = "signlike", + tiles = {"poudlard_rope.png"}, + inventory_image = "poudlard_rope.png", + wield_image = "poudlard_rope.png", + paramtype = "light", + paramtype2 = "wallmounted", + is_ground_content = true, + walkable = false, + climbable = true, + selection_box = { + type = "wallmounted", + }, + groups = {snappy=3,flammable=2}, + sounds = default.node_sound_leaves_defaults(), +}) + +minetest.register_node("poudlard:wood_tile", { + description = "Wooden Tile", + tiles = {"poudlard_wood_tile.png", "poudlard_wood_tile.png", "poudlard_wood_tile.png", "poudlard_wood_tile.png", "poudlard_wood_tile.png^[transformR90", "poudlard_wood_tile.png^[transformR90"}, + inventory_image = {"poudlard_wood_tile.png", "poudlard_wood_tile.png"}, + paramtype2 = "facedir", + groups = {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3}, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_node("poudlard:wood_tile_full", { + description = "Full Wooden Tile", + tiles = {"poudlard_wood_tile_full.png", "poudlard_wood_tile_full.png", "poudlard_wood_tile_full.png", + "poudlard_wood_tile_full.png", "poudlard_wood_tile_full.png^[transformR90", "poudlard_wood_tile_full.png^[transformR90"}, + inventory_image = {"poudlard_wood_tile_full.png", "poudlard_wood_tile_full.png"}, + paramtype2 = "facedir", + groups = {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3}, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_node("poudlard:wood_tile_center", { + description = "Centered Wooden Tile", + tiles = {"poudlard_wood_tile_center.png", "poudlard_wood_tile_center.png", "poudlard_wood_tile_center.png", "poudlard_wood_tile_center.png", "poudlard_wood_tile_center.png^[transformR90", "poudlard_wood_tile_center.png^[transformR90"}, + inventory_image = {"poudlard_wood_tile_center.png", "poudlard_wood_tile_center.png"}, + paramtype2 = "facedir", + groups = {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3}, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_node("poudlard:secretbookshelf", { + description = "Secret_bookshelf", + tiles = {"default_wood.png", "default_wood.png","poudlard_secretbookshelf.png"}, + walkable = false, + is_ground_content = true, + groups = {cracky=3}, + sounds = default.node_sound_stone_defaults(), +}) + +-- Items + +minetest.register_craftitem("poudlard:sweeper", { + description = "Sweeper", + inventory_image = "poudlard_sweeper.png", +}) + +minetest.register_craftitem("poudlard:junglestick", { + description = "Jungle Stick", + inventory_image = "poudlard_junglestick.png", +}) diff --git a/mods/poudlard/poudecor/LICENSE b/mods/poudlard/poudecor/LICENSE new file mode 100644 index 0000000..d234873 --- /dev/null +++ b/mods/poudlard/poudecor/LICENSE @@ -0,0 +1,699 @@ +For the Code: + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. + + +---------- + +For the textures and everything else: + + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2004 Sam Hocevar + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. + + This license is commonly known as "WTFPL". + diff --git a/mods/poudlard/poudecor/README b/mods/poudlard/poudecor/README new file mode 100644 index 0000000..74fe5f4 --- /dev/null +++ b/mods/poudlard/poudecor/README @@ -0,0 +1,46 @@ +This is what I consider to be a fairly feature-filled home decor mod. +It supplies a bunch of stuff found in most homes, like flower pots, home +electronics, brass and wrought-iron tables, and lots more! + +All items can be accessed either by crafting various other items +together, or with the usual /give commands. To get a list of the actual +node names, just go into the homedecor/ folder and run the listnodes.sh +Bash script. Note that a few of the listed nodes are kinda useless by +themselves (like the various parts of the folding doors). + +All of the images used for the recipes in the forum post tracking this +mod are included in the crafting-guide/ folder. + +Most stuff can be made from materials found through a game world. Some +stuff can only be crafted by using materials from another mod (look for +the orange highlights). Currently, this mod can use materials from +moreores, mesecons, wool, and unifieddyes if present. You can still use +the usual /give commands to get the items that depend on these mods if +you don't use them installed. + +This mod is still a work-in-progress, but should be complete enough not +to irritate anyone. :-) Namely, dressers still need to be fleshed out, +many items can be used as fuel but the burn times need tuning, and I +need to tune the cook time and fuel usage on the four smelted items. + +This mod was put together using a recent git pull, and requires a +build/pull dated June 17, 2012 or later. Most stuff should work fine on +older builds as well, but a few nodes in this mod require Nodebox +support, a feature added to Minetest on that date. It will NOT work +with Minetest v0.3 (that version doesn't support mods). + +Much of the code (especially for the doors) plus the bucket were taken +from the files which come with Minetest and altered to suit. Many +thanks to Jeija for coming up with an elegant cylinder using nodeboxes; +see his 'irregular' mods). His code is used herein (you can guess where +:-) ). + +Dependencies: none (just the game's default stuff) + +Recommends: buckets, flowers, unifieddyes, junglegrass, moreores, +mesecons, wool + +The distribution archive also supplies a copy of Ironzorg's Flowers mod +and of my Unified Dyes mod, since this mod provides more stuff when +those two are present. You can remove these if you want - they're only +needed if you want to craft the various dyed/colored items. diff --git a/mods/poudlard/poudecor/armchair.lua b/mods/poudlard/poudecor/armchair.lua new file mode 100644 index 0000000..4bd1aef --- /dev/null +++ b/mods/poudlard/poudecor/armchair.lua @@ -0,0 +1,90 @@ + +-- Test + + +local chaircolors = { + { "black", "Black" }, + { "yellow", "Yellow" }, + { "red", "Red" }, + { "violet", "Violet" }, + { "blue", "Blue" }, + { "dark_green", "Dark Green" }, +} + +for i in ipairs(chaircolors) do + color = chaircolors[i][1] + name = chaircolors[i][2] + minetest.register_node("poudlard:armchair_"..color, { + description = "Armchair ("..name..")", + tiles = { + "forniture_armchair_top_"..color..".png", + "forniture_armchair_top_"..color..".png", + "forniture_armchair_lat1_"..color..".png", + "forniture_armchair_lat1_"..color..".png", + "forniture_armchair_lat2_"..color..".png", + "forniture_armchair_lat2_"..color..".png", + }, + drawtype = "nodebox", + sunlight_propagates = true, + paramtype = "light", + paramtype2 = "facedir", + node_box = { + type = "fixed", + fixed = { + { -0.50, -0.50, -0.45, -0.30, 0.05, 0.30 }, + { -0.45, -0.50, -0.50, -0.35, 0.05, -0.45 }, + { -0.45, 0.05, -0.45, -0.35, 0.10, 0.15 }, + { 0.30, -0.50, -0.45, 0.50, 0.05, 0.30 }, + { 0.35, -0.50, -0.50, 0.45, 0.05, -0.45 }, + { 0.35, 0.05, -0.45, 0.45, 0.10, 0.15 }, + { -0.50, -0.50, 0.30, 0.50, 0.45, 0.50 }, + { -0.45, 0.45, 0.35, 0.45, 0.50, 0.45 }, + { -0.30, -0.45, -0.35, 0.30, -0.10, 0.30 }, + { -0.30, -0.45, -0.40, 0.30, -0.15, -0.35 }, + { -0.50, 0.05, 0.15, -0.30, 0.45, 0.30 }, + { -0.45, 0.10, 0.10, -0.35, 0.45, 0.15 }, + { -0.45, 0.45, 0.15, -0.35, 0.50, 0.35 }, + { 0.30, 0.05, 0.15, 0.50, 0.45, 0.30 }, + { 0.35, 0.10, 0.10, 0.45, 0.45, 0.15 }, + { 0.35, 0.45, 0.15, 0.45, 0.50, 0.35 }, + }, + }, + groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2}, + }) + + minetest.register_craft({ + output = "poudlard:armchair_"..color.." 2", + recipe = { + { "wool:"..color,""}, + { "default:wood","default:wood" }, + { "wool:"..color,"wool:"..color }, + }, + }) + +end + + +-- Aliases + +minetest.register_alias("poudecor:armchair", "poudecor:armchair_black") +minetest.register_alias('armchair', 'poudlard:armchair') + +-- Aliases for 3homedecor. + +minetest.register_alias("homedecor:armchair_black", "poudecor:armchair_black") +minetest.register_alias("homedecor:armchair_yellow", "poudecor:armchair_yellow") +minetest.register_alias("homedecor:armchair_violet", "poudecor:armchair_violet") +minetest.register_alias("homedecor:armchair_red", "poudecor:armchair_red") +minetest.register_alias("homedecor:armchair_dark_green", "poudecor:armchair_dark_green") +minetest.register_alias("homedecor:armchair_blue", "poudecor:armchair_blue") + +-- Aliases for poudlard +minetest.register_alias("poudecor:armchair_black", "poudlard:armchair_black") +minetest.register_alias("poudecor:armchair_yellow", "poudlard:armchair_yellow") +minetest.register_alias("poudecor:armchair_violet", "poudlard:armchair_violet") +minetest.register_alias("poudecor:armchair_red", "poudlard:armchair_red") +minetest.register_alias("poudecor:armchair_dark_green", "poudlard:armchair_dark_green") +minetest.register_alias("poudecor:armchair_blue", "poudlard:armchair_blue") + + + diff --git a/mods/poudlard/poudecor/copyright.txt b/mods/poudlard/poudecor/copyright.txt new file mode 100644 index 0000000..9a65224 --- /dev/null +++ b/mods/poudlard/poudecor/copyright.txt @@ -0,0 +1,8 @@ +Very light version of "homedecor" by Perlipop + raccordable images for curtains +Most code and all textures by Vanessa Ezekowitz. + + +Some code copied and modified from the game's default mods (especially +doors) and ironzorg's flowers mod. + +Licenses: For the lua code, GPL. For all images and everything else, WTFPL. diff --git a/mods/poudlard/poudecor/crafts.lua b/mods/poudlard/poudecor/crafts.lua new file mode 100644 index 0000000..338fd67 --- /dev/null +++ b/mods/poudlard/poudecor/crafts.lua @@ -0,0 +1,102 @@ +-- Crafting for homedecor mod (includes folding) by Vanessa Ezekowitz +-- 2012-06-12 +-- +-- Mostly my own code; overall template borrowed from game default +-- +-- License: GPL +-- + +-- Load translation library if intllib is installed + +local S +if (minetest.get_modpath("intllib")) then + dofile(minetest.get_modpath("intllib").."/intllib.lua") + S = intllib.Getter(minetest.get_current_modname()) + else + S = function ( s ) return s end +end + + + + +-- Nightstand ----------------------------- + +minetest.register_craft( { + output = "poudlard:nightstand_1", + recipe = { + { "moreblocks:emptybookshelf" }, + { "moreblocks:emptybookshelf" }, + { "default:wood" }, + }, +}) + + +minetest.register_craft({ + type = "fuel", + recipe = "poudlard:nightstand_1", + burntime = 30, +}) + + +minetest.register_craft( { + type = "shapeless", + output = "poudlard:nightstand_2", + recipe = { + "moreblocks:emptybookshelf", + "moreblocks:emptybookshelf", + "default:junglewood", + }, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "poudlard:nightstand_2", + burntime = 30, +}) +-- + + + + +-- Curtains --------------------------------- + +local curtaincolors = { + "red", + "orange", + "green", + "dark_green", + "yellow", + "blue", + "white", + "dark_grey", + "black", + "violet" +} + +for c in ipairs(curtaincolors) do + local color = curtaincolors[c] + minetest.register_craft( { + output = "poudlard:curtain_"..color.." 3", + recipe = { + { "wool:"..color, "", ""}, + { "wool:"..color, "", ""}, + { "wool:"..color, "", ""}, + }, + }) +end + + +-- + +-- + +-- +-- +-- + +-- + +-- + + + diff --git a/mods/poudlard/poudecor/curtain.lua b/mods/poudlard/poudecor/curtain.lua new file mode 100644 index 0000000..e34bf10 --- /dev/null +++ b/mods/poudlard/poudecor/curtain.lua @@ -0,0 +1,81 @@ +-- Various misc. nodes + +-- Load translation library if intllib is installed + +local S +if (minetest.get_modpath("intllib")) then + dofile(minetest.get_modpath("intllib").."/intllib.lua") + S = intllib.Getter(minetest.get_current_modname()) + else + S = function ( s ) return s end +end + +-- + +local curtaincolors = { + "red", + "green", + "blue", + "white", + "orange", + "dark_green", + "yellow", + "dark_grey", + "black", + "violet" + +} + +for c in ipairs(curtaincolors) do + local color = curtaincolors[c] + local color_d = S(curtaincolors[c]) + + minetest.register_node("poudlard:curtain_"..color, { + description = S("Curtains (%s)"):format(color_d), + tiles = { "homedecor_curtain_"..color..".png" }, + inventory_image = "homedecor_curtain_"..color..".png", + wield_image = "homedecor_curtain_"..color..".png", + drawtype = 'signlike', + sunlight_propagates = true, + paramtype = "light", + paramtype2 = "facedir", + walkable = false, + groups = { snappy = 3 }, + sounds = default.node_sound_leaves_defaults(), + paramtype2 = 'wallmounted', + selection_box = { + type = "wallmounted", + --wall_side = = + }, + }) + if color_d ~= color then + minetest.register_alias("poudlard:curtain_"..color_d, "poudlard:curtain_"..color) + end +end + + +-------------- Alias for homedecor + +minetest.register_alias("homedecor:curtain_yellow", "poudecor:curtain_yellow") +minetest.register_alias("homedecor:curtain_violet", "poudecor:curtain_violet") +minetest.register_alias("homedecor:curtain_red", "poudecor:curtain_red") +minetest.register_alias("homedecor:curtain_dark_green", "poudecor:curtain_dark_green") +minetest.register_alias("homedecor:curtain_green", "poudecor:curtain_green") +minetest.register_alias("homedecor:curtain_blue", "poudecor:curtain_blue") +minetest.register_alias("homedecor:curtain_white", "poudecor:curtain_white") +minetest.register_alias("homedecor:curtain_orange", "poudecor:curtain_orange") +minetest.register_alias("homedecor:curtain_dark_grey", "poudecor:curtain_dark_grey") +minetest.register_alias("homedecor:curtain_black", "poudecor:curtain_black") + +-------------- Alias for poudecort + +minetest.register_alias("poudecor:curtain_yellow", "poudlard:curtain_yellow") +minetest.register_alias("poudecor:curtain_violet", "poudlard:curtain_violet") +minetest.register_alias("poudecor:curtain_red", "poudlard:curtain_red") +minetest.register_alias("poudecor:curtain_dark_green", "poudlard:curtain_dark_green") +minetest.register_alias("poudecor:curtain_green", "poudlard:curtain_green") +minetest.register_alias("poudecor:curtain_blue", "poudlard:curtain_blue") +minetest.register_alias("poudecor:curtain_white", "poudlard:curtain_white") +minetest.register_alias("poudecor:curtain_orange", "poudlard:curtain_orange") +minetest.register_alias("poudecor:curtain_dark_grey", "poudlard:curtain_dark_grey") +minetest.register_alias("poudecor:curtain_black", "poudlard:curtain_black") diff --git a/mods/poudlard/poudecor/furniture_recipes.lua b/mods/poudlard/poudecor/furniture_recipes.lua new file mode 100644 index 0000000..2f88f41 --- /dev/null +++ b/mods/poudlard/poudecor/furniture_recipes.lua @@ -0,0 +1,15 @@ + +minetest.register_craft({ + type = "fuel", + recipe = "poudlard:armchair", + burntime = 30, +}) + + +minetest.register_craft({ + output = "poudlard:torch_wall 10", + recipe = { + { "default:coal_lump" }, + { "default:steel_ingot" }, + }, +}) diff --git a/mods/poudlard/poudecor/listnodes.sh b/mods/poudlard/poudecor/listnodes.sh new file mode 100644 index 0000000..2332080 --- /dev/null +++ b/mods/poudlard/poudecor/listnodes.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +echo "Node listing as of "`date` > nodes.txt + +for i in *.lua; do + echo -e "\nIn $i:\n" >> nodes.txt + cat $i | grep "minetest.register_node(" | \ + sed "s/minetest.register_node(.homedecor:/homedecor:/; s/., {//" | \ + sort >> nodes.txt +done + +less nodes.txt +rm -f nodes.txt diff --git a/mods/poudlard/poudecor/locale/es.txt b/mods/poudlard/poudecor/locale/es.txt new file mode 100644 index 0000000..0baac0b --- /dev/null +++ b/mods/poudlard/poudecor/locale/es.txt @@ -0,0 +1,194 @@ + +# +# Language: Español +# Author: Diego Martínez +# + +### kitchen_cabinet.lua ### +Kitchen Cabinet = Gabinete de Cocina +## 1: Player name, 2: position +%s moves stuff in kitchen cabinet at %s = %s mueve cosas en gabinete de cocina en %s +%s moves stuff to kitchen cabinet at %s = %s mueve cosas al gabinete de cocina en %s +%s takes stuff from kitchen cabinet at %s = %s toma cosas del gabinete de cocina en %s +Half-height Kitchen Cabinet (on ceiling) = Gabinete de cocina de media altura (en techo) +Under-sink cabinet = Gabinete con Lavabo +Kitchen Cabinet with sink = Gabinete de cocina con lavabo + +### door_models.lua ### +Mahogany Closet Door = Puerta de Armario de Caoba +Oak Closet Door = Puerta de Armario de Roble +Fancy Wood/Glass Door = Puerta de Madera y Cristal de Lujo +Glass Office Door = Puerta de Oficina de Cristal +Glass and Wood, Mahogany-colored = Cristal y Madera, color Caoba +Glass and Wood, Oak-colored = Cristal y Madera, color Roble +Glass and Wood, White = Cristal y Madera, color Blanco +Plain Wooden Door = Puerta Simple de Madera +left = izquierda +right = derecha +## 1: Side the doors opens to +(Top Half, %s-opening) = (Parte Superior, abre a la %s) +(%s-opening) = (abre a la %s) + +### door_nodes.lua ### +Not enough vertical space to place a door! = ¡No hay suficiente espacio vertical para colocar una puerta! + +### crafts.lua ### +Brass Ingot = Lingote de Latón +Bucket of white paint = Cubo de Pintura Blanca +Legs for Small Utility table = Patas de Mesa Utilitaria Pequeña +Plastic sheet = Lámina de Plástico +Silicon lump = Terrón de Silicio +Simple Integrated Circuit = Circuito Integrado Simple +Small Wooden Drawer = Cajón Pequeño de Madera +Terracotta Roof Tile = Teja de Terracota +Titanium Dioxide = Dióxido de Titanio +Uncooked Terracotta Base = Base de Terracota sin Cocer +Unprocessed Plastic base = Base de Plástico sin Procesar + +### fences.lua ### +Barbed Wire Fence = Cerca de Alambre de Púas +Barbed Wire Fence Gate = Portón de Cerca de Alambre de Púas +Brass Fence/railing = Cerca/Barandilla de Latón +Brass Fence/railing with sign = Cerca/Barandilla de Latón con Letrero +Chainlink Fence = Cerca de Cadenas +Chainlink Fence Gate = Portón de Cerca de Cadenas +Chainlink Fence Gate (open) = Portón de Cerca de Cadenas (Abierto) +Unpainted Picket Fence = Cerca de Piquete sin pintar +Unpainted Picket Fence Gate = Portón de Cerca de Piquete sin pintar +White Picket Fence = Cerca de Piquete blanca +White Picket Fence Gate = Portón de Cerca de Piquete blanca +Wooden Privacy Fence = Cerca privada de madera +Wrought Iron Fence/railing = Cerca/Barandilla de Hierro Forjado +Wrought Iron Fence/railing with sign = Cerca/Barandilla de Hierro Forjado con Letrero +want to simply place the wielded item like usual. = solo se desea colocar el objeto empuñado normalmente. + +### furniture_medieval.lua ### +Bars = Barras +Binding Bars = Barras de Unión +Chains = Cadenas +Wall Torch = Antorcha de Pared + +### furniture_bathroom.lua ### +Toilet = Inodoro +Sink = Lavabo +Taps = Grifo +Shower Tray = Piso de Ducha +Shower Head = Ducha + +### init.lua ### +Loaded! = ¡Cargado! +Asphalt Shingles = Tejas de Asfalto +Black Plastic Flower Pot = Florero de Plástico Negro +Brass Pole = Poste de Latón +Brass Table Legs = Patas de Mesa de Latón +red = rojas +green = verdes +blue = azules +white = blancas +pink = rosas +violet = violetas +## 1: Color name +Curtains (%s) = Cortinas (%s) +Drop-Ceiling Tile = Cielorraso +Glass Skylight = Claraboya de Cristal +Glass Table (Small, Round) = Mesa de Cristal (Pequeña, Redonda) +Glass Table (Small, Square) = Mesa de Cristal (Pequeña, Cuadrada) +Green Plastic Flower Pot = Florero de Plástico Negro +Large Area Rug = Manta Grande +Large Glass Table Piece = Pieza de Mesa de Cristal Grande +Large Stereo Speaker = Altavoz de Estéreo Grande +Legs for Utility Table = Patas de Mesa Utilitaria +Projection Screen Material = Material de Pantalla de Proyección +Small Surround Speaker = Pequeño Altavoz Envolvente +Small Throw Rug = Manta Pequeña +Stereo Receiver = Receptor Estéreo +Terracotta Flower Pot = Florero de Terracota +Terracotta Roofing = Tejado de Terracota +Textured Ceiling Paint = Pintura Texturada para Techo +Utility Table = Mesa Utilitaria +Utility table mk2 = Mesa Utilitaria mk2 +Wooden Shutter (Black) = Obturador de Madera (Negro) +Wooden Shutter (Dark Grey) = Obturador de Madera (Gris Oscuro) +Wooden Shutter (Forest Green) = Obturador de Madera (Verde Bosque) +Wooden Shutter (Grey) = Obturador de Madera (Gris) +Wooden Shutter (Light Blue) = Obturador de Madera (Azul Claro) +Wooden Shutter (Purple) = Obturador de Madera (Púrpura) +Wooden Shutter (Red) = Obturador de Madera (Rojo) +Wooden Shutter (Unpainted Mahogany) = Obturador de Madera (Caoba sin Pintar) +Wooden Shutter (Unpainted Oak) = Obturador de Madera (Roble sin Pintar) +Wooden Shutter (White) = Obturador de Madera (Blanco) +Wooden Shutter (Yellow) = Obturador de Madera (Amarillo) +Wooden Tabletop piece = Pieza de Mesa de Madera +Wooden Tabletop (Small, Round) = Pieza de Mesa de Madera (Pequeña, Redonda) +Wooden Tabletop (Small, Square) = Pieza de Mesa de Madera (Pequeña, Cuadrada) +Wood Shingles = Tejas de Madera +Wrought Iron Pole = Poste de Hierro Forjado +someone = alguien +## 1: Player name +Sorry, %s owns that spot. = Lo siento, %s es dueño de ése lugar. + +### lighting.lua ### +White Glowlight (small cube) = Luz Blanca (cubo pequeño) +White Glowlight (small cube, on ceiling) = Luz Blanca (cubo pequeño, en techo) +White Glowlight (thick) = Luz Blanca (Gruesa) +White Glowlight (thick, on wall) = Luz Blanca (Gruesa, en pared) +White Glowlight (thin) = Luz Blanca (Fina) +White Glowlight (thin, on wall) = Luz Blanca (Fina, en pared) +Yellow Glowlight (small cube) = Luz Amarilla (cubo pequeño) +Yellow Glowlight (small cube, on ceiling) = Luz Amarilla (cubo pequeño, en techo) +Yellow Glowlight (thick) = Luz Amarilla (Gruesa) +Yellow Glowlight (thick, on wall) = Luz Amarilla (Gruesa, en pared) +Yellow Glowlight (thin) = Luz Amarilla (Fina) +Yellow Glowlight (thin, on wall) = Luz Amarilla (Fina, en pared) + +### locked.lua ### +## 1: Item description, 2: Owner name +%s (owned by %s) = %s (propiedad de %s) +## 1: Player name, 2: Item description, 3: Owner name, 4: Position +%s tried to access a %s belonging to %s at %s = %s ha intentado acceder un(a) %s propiedad de %s en %s +## 1: Item description +%s (Locked) = %s (Cerrado) +Locked Cabinet = Gabinete Cerrado +Locked Nightstand = Mesa de Noche Cerrada +Locked Fridge = Refri Cerrado +Locked Oven = Estufa Cerrada + +### nightstands.lua ### +Mahogany Nightstand with One Drawer = Mesa de Noche de Caoba, un Cajón +Mahogany Nightstand with Two Drawers = Mesa de Noche de Caoba, dos Cajones +Oak Nightstand with One Drawer = Mesa de Noche de Roble, un Cajón +Oak Nightstand with Two Drawers = Mesa de Noche de Roble, dos Cajones +## 1: Player name, 2: position +%s moves stuff in nightstand at %s = %s mueve cosas en mesa de noche en %s +%s moves stuff to nightstand at %s = %s mueve cosas hacia mesa de noche en %s +%s takes stuff from nightstand at %s = %s mueve cosas desde mesa de noche en %s +One-drawer Nightstand = Mesa de Noche de un Cajón +Two-drawer Nightstand = Mesa de Noche de dos Cajones + +### oven.lua ### +Oven = Estufa +## 1: Item name +Could not insert '%s' = No se pudo insertar '%s' +## 1: Percentage +Oven active: %d%% = Estufa activa: %d%% +Oven out of fuel = Estufa sin combustible +Oven is empty = Estufavacía + +### refrigerator.lua ### +Refrigerator = Refrigerador +## 1: Player name, 2: position +%s moves stuff in refrigerator at %s = %s mueve cosas en refrigerador en %s +%s moves stuff to refrigerator at %s = %s mueve cosas hacia refrigerador en %s +%s takes stuff from refrigerator at %s = %s mueve cosas desde refrigerador en %s +Not enough vertical space to place a refrigerator! = ¡No hay suficiente espacio vertical para colocar un refrigerador! + +### television.lua ### +Small CRT Television = Pequeña Televisión CRT + +### signs_lib.lua ### +%s wrote "%s" to sign at %s = %s ha escrito "%s" en el letrero en %s +Reading cached character database. = Leyendo base de datos de catacteres. +Font seems to have changed. Rebuilding cache. = La fuente parece haber cambiado. Reconstruyendo información guardada. +Could not find font line height in cached DB. Trying brute force. = No se pudo encontrar la altura de línea en la base de datos. Intentando con fuerza bruta. +Registered %s and %s = Registrados %s y %s +signs loaded = letreros cargados diff --git a/mods/poudlard/poudecor/locale/fr.txt b/mods/poudlard/poudecor/locale/fr.txt new file mode 100644 index 0000000..2a17a28 --- /dev/null +++ b/mods/poudlard/poudecor/locale/fr.txt @@ -0,0 +1,180 @@ + +# +# Language: Français +# Author: Calinou +# + +### kitchen_cabinet.lua ### +Kitchen Cabinet = Meuble de cuisine +## 1: Player name, 2: position +%s moves stuff in kitchen cabinet at %s = %s déplace des objets dans un meuble de cuisine à %s +%s moves stuff to kitchen cabinet at %s = %s édplace des objets vers un meuble de cuisine à %s +%s takes stuff from kitchen cabinet at %s = %s prend des objets d'un meuble de cuisine à %s +Half-height Kitchen Cabinet (on ceiling) = Meuble de cuisine réduit en hauteur (sur le plafond) +Under-sink cabinet = Meuble sous évier +Kitchen Cabinet with sink = Meuble de cuisine avec lavabo + +### door_models.lua ### +Mahogany Closet Door = Porte en bois d'acajou +Oak Closet Door = Porte en bois de chêne +Fancy Wood/Glass Door = Porte artistique en bois et verre +Glass Office Door = Porte en verre +Glass and Wood, Mahogany-colored = Porte couleur acajou en bois et verre +Glass and Wood, Oak-colored = Porte couleur chêne en bois et verre +Glass and Wood, White = Porte blanche en bois et verre +Plain Wooden Door = Porte en bois simple +left = gauche +right = droite +## 1: Side the doors opens to +(Top Half, %s-opening) = (partie supérieur, charnière à %s) +(%s-opening) = (charnière à %s) + +### door_nodes.lua ### +Not enough vertical space to place a door! = Pas assez d'espace vertical pour placer une porte ! + +### crafts.lua ### +Brass Ingot = Lingot de laiton +Bucket of white paint = Seau de peinture blanche +Legs for Small Utility table = Pieds pour table basse +Plastic sheet = Bout de plastique +Silicon lump = Silicone +Simple Integrated Circuit = Circuit intégré simple +Small Wooden Drawer = Petit tiroir en bois +Terracotta Roof Tile = Tuile de toit en terre cuite +Titanium Dioxide = Dioxide de titane +Uncooked Terracotta Base = Base de terre non cuite +Unprocessed Plastic base = Base de plastique non transformée + +### fences.lua ### +Barbed Wire Fence = Barrière en fil barbelé +Barbed Wire Fence Gate = Porte de barrière en fil barbelé +Brass Fence/railing = Barrière en laiton +Brass Fence/railing with sign = Barrière en laiton avec pancarte +Chainlink Fence = Grillage +Chainlink Fence Gate = Porte de grillage +Chainlink Fence Gate (open) = Porte de grillage (ouverte) +Unpainted Picket Fence = Barrière en piquets non peinte +Unpainted Picket Fence Gate = Porte de barrière en piquets non peinte +White Picket Fence = Barrière en piquets blanche +White Picket Fence Gate = Porte de barrière en piquets blanche +Wooden Privacy Fence = Barrière en bois +Wrought Iron Fence/railing = Barrière en fer forgé +Wrought Iron Fence/railing with sign = Barrière en fer forgé avec pancarte +want to simply place the wielded item like usual. = veut simplement placer l'objet comme d'habitude. + +### init.lua ### +Loaded! = Chargé ! +Asphalt Shingles = Bardeaux d'asphalte +Black Plastic Flower Pot = Pot de fleur en plastique noir +Brass Pole = Barre en laiton +Brass Table Legs = Pieds de table en laiton +red = rouges +green = vertes +blue = bleues +white = blanches +pink = roses +violet = violettes +## 1: Color name +Curtains (%s) = Volets (%s) +Drop-Ceiling Tile = Dalle suspendue au plafond +Glass Skylight = Verre +Glass Table (Small, Round) = Table en verre (petite, ronde) +Glass Table (Small, Square) = Table en verre (petite, carrée) +Green Plastic Flower Pot = Pot de fleur en plastique vert +Large Area Rug = Grande couverture +Large Glass Table Piece = Grand bout de verre de table +Large Stereo Speaker = Grand haut-parleur stéréo +Legs for Utility Table = Pieds pour table basse +Projection Screen Material = Matériel pour projecteur +Small Surround Speaker = Petit haut-parleur surround +Small Throw Rug = Petite couverture +Stereo Receiver = Récepteur stéréo +Terracotta Flower Pot = Pot de fleur en terre cuite +Terracotta Roofing = Tuile en terre cuite +Textured Ceiling Paint = Papier peint avec motif pour plafond +Utility Table = Table basse +Utility table mk2 = Table basse MK2 +Wooden Shutter (Black) = Volet en bois (noir) +Wooden Shutter (Dark Grey) = Volet en bois (gris foncé) +Wooden Shutter (Forest Green) = Volet en bois (vert foncé) +Wooden Shutter (Grey) = Volet en bois (gris) +Wooden Shutter (Light Blue) = Volet en bois (bleu clair) +Wooden Shutter (Purple) = Volet en bois (violet) +Wooden Shutter (Red) = Volet en bois (rouge) +Wooden Shutter (Unpainted Mahogany) = Volet en bois (acajou non peint) +Wooden Shutter (Unpainted Oak) = Volet en bois (chêne non peint) +Wooden Shutter (White) = Volet en bois (blanc) +Wooden Shutter (Yellow) = Volet en bois (jaune) +Wooden Tabletop piece = Bout de dessus de table +Wooden Tabletop (Small, Round) = Dessus de table (petit, rond) +Wooden Tabletop (Small, Square) = Dessus de table (petit, carré) +Wood Shingles = Bardeaux de bois +Wrought Iron Pole = Barre de fer forgé +someone = quelqu'un +## 1: Player name +Sorry, %s owns that spot. = Désolé, %s est propriétaire de cette zone. + +### lighting.lua ### +White Glowlight (small cube) = Lampe blanche (petit cube) +White Glowlight (small cube, on ceiling) = Lampe blanche (petit cube, sur le plafond) +White Glowlight (thick) = Lampe blanche (épaisse) +White Glowlight (thick, on wall) = Lampe blanche (épaisse, sur le mur) +White Glowlight (thin) = Lampe blanche (fine) +White Glowlight (thin, on wall) = Lampe blanche (fine, sur le mur) +Yellow Glowlight (small cube) = Lampe jaune (petit cube) +Yellow Glowlight (small cube, on ceiling) = Lampe jaune (petit cube, sur le plafond) +Yellow Glowlight (thick) = Lampe jaune (épaisse) +Yellow Glowlight (thick, on wall) = Lampe jaune (épaisse, sur le mur) +Yellow Glowlight (thin) = Lampe jaune (fine) +Yellow Glowlight (thin, on wall) = Lampe jaune (fine, sur le mur) + +### locked.lua ### +## 1: Item description, 2: Owner name +%s (owned by %s) = %s (propriété de %s) +## 1: Player name, 2: Item description, 3: Owner name, 4: Position +%s tried to access a %s belonging to %s at %s = %s a essayé d'accéder à %s qui est propriété de %s à %s +## 1: Item description +%s (Locked) = %s (verrouillé) +Locked Cabinet = Meuble verrouillé +Locked Nightstand = Table de chevet verrouillée +Locked Fridge = Réfrégirateur verrouillé +Locked Oven = Four verrouillé + +### nightstands.lua ### +Mahogany Nightstand with One Drawer = Table de chevet en acajou avec un tiroir +Mahogany Nightstand with Two Drawers = Table de chevet en acajou avec deux tiroirs +Oak Nightstand with One Drawer = Table de chevet en chêne avec un tiroir +Oak Nightstand with Two Drawers = Table de chevet en chêne avec deux tiroirs +## 1: Player name, 2: position +%s moves stuff in nightstand at %s = %s déplace des objets dans une table de chevet à %s +%s moves stuff to nightstand at %s = %s déplace des objets vers une table de chevet à %s +%s takes stuff from nightstand at %s = %s prend des objets d'une table de chevet à %s +One-drawer Nightstand = Table de chevet avec un tiroir +Two-drawer Nightstand = Table de chevet avec deux tiroirs + +### oven.lua ### +Oven = Four +## 1: Item name +Could not insert '%s' = Ne peut insérer '%s' +## 1: Percentage +Oven active: %d%% = Four actif : %d%% +Oven out of fuel = Four sans carburant +Oven is empty = Four vide + +### refrigerator.lua ### +Refrigerator = Réfrégirateur +## 1: Player name, 2: position +%s moves stuff in refrigerator at %s = %s déplace des objets dans un réfrégirateur à %s +%s moves stuff to refrigerator at %s = %s déplace des objets vers un réfrégirateur à %s +%s takes stuff from refrigerator at %s = %s prend des objets d'un réfrégirateur à %s +Not enough vertical space to place a refrigerator! = Pas assez d'espace vertical pour placer un réfrégirateur ! + +### television.lua ### +Small CRT Television = Petite télévision à tube cathodique + +### signs_lib.lua ### +E: character map file not found = E: fichier de table de caractère non trouvé +## 1: Full String, 2: pos in string, 3: current char at pos +W: unknown symbol in '%s' at %d (probably %s) = A: symbole inconnu dans '%s' dans %d (probablement %s) +%s wrote "%s" to sign at %s = +signs loaded = diff --git a/mods/poudlard/poudecor/locale/pt.txt b/mods/poudlard/poudecor/locale/pt.txt new file mode 100644 index 0000000..bd8e435 --- /dev/null +++ b/mods/poudlard/poudecor/locale/pt.txt @@ -0,0 +1,198 @@ + +# Brazilian Portuguese translation of homedecor +# Last update: 2013/11/10 +# Last translator: Aracnus + +### Special strings ### + +### kitchen_cabinet.lua ### +Kitchen Cabinet = Armário de cozinha +## 1: Player name, 2: position +%s moves stuff in kitchen cabinet at %s = %s moveu itens no armário de cozinha em %s +%s moves stuff to kitchen cabinet at %s = %s moveu itens para o armário de cozinha em %s +%s takes stuff from kitchen cabinet at %s = %s retirou itens do armário de cozinha em %s +Half-height Kitchen Cabinet (on ceiling) = Meio armário de cozinha (no teto) +Under-sink cabinet = Armário sob a pia +Kitchen Cabinet with sink = Armário de cozinha com pia + +### door_models.lua ### +Mahogany Closet Door = Porta do armário de mogno +Oak Closet Door = Porta do armário de carvalho +Fancy Wood/Glass Door = Porta de madeira/vidro trabalhada +Glass Office Door = Porta de escritório de vidro +Glass and Wood, Mahogany-colored = Vidro e madeira (mogno) +Glass and Wood, Oak-colored = Vidro e madeira (carvalho) +Glass and Wood, White = Vidro e madeira (branca) +Plain Wooden Door = Porta de madeira simples +left = esquerda +right = direita +## 1: Side the doors opens to +(Top Half, %s-opening) = (Metade superior, abre para %s) +(%s-opening) = (abre para %s) + + +### door_nodes.lua ### +Not enough vertical space to place a door! = Não existe espaço vertical suficiente para colocar uma porta. + +### crafts.lua ### +Brass Ingot = Lingote de bronze +Bucket of white paint = Balde de tinta branca +Legs for Small Utility table = Pernas para mesa pequena +Plastic sheet = Folha de plástico +Silicon lump = Massa de silício +Simple Integrated Circuit = Circuito integrado simples +Small Wooden Drawer = Gaveta pequena de madeira +Terracotta Roof Tile = Telha de terracota +Titanium Dioxide = Dióxido de titânio +Uncooked Terracotta Base = Base bruta de terracota +Unprocessed Plastic base = Base de plástico não processada + +### door_models.lua ### + +### door_nodes.lua ### + +### fences.lua ### +Barbed Wire Fence = Cerca de arame farpado +Barbed Wire Fence Gate = Portão da cerca de arame farpado +Brass Fence/railing = Cerca/corrimão de bronze +Brass Fence/railing with sign = Cerca/corrimão de bronze, com placa +Chainlink Fence = Cerca de tela de arame +Chainlink Fence Gate = Portão da cerca de tela de arame +Chainlink Fence Gate (open) = Portão da cerca de tela de arame (aberto) +Unpainted Picket Fence = Cerca de tábuas não pintada +Unpainted Picket Fence Gate = Portão da cerca de madeira não pintado +White Picket Fence = Cerca de madeira branca +White Picket Fence Gate = Portão da cerca de madeira branco +Wooden Privacy Fence = Cerca fechada de mandeira +Wrought Iron Fence/railing = Cerca/corrimão de ferro forjado +Wrought Iron Fence/railing with sign = Cerca/corrimão de ferro forjado, com placa +want to simply place the wielded item like usual. = quer somente colocar o item empunhado normalmente. + +### furniture_medieval.lua ### +Bars = Barras +Binding Bars = Barras do canto +Chains = Correntes +Wall Torch = Tocha de parede + +### furniture_bathroom.lua ### +Toilet = Vaso sanitário +Sink = Pia +Taps = Torneira +Shower Tray = Ralo do chuveiro +Shower Head = Chuveiro + +### init.lua ### +Loaded! = Carregado! +Asphalt Shingles = Telhas de asfalto +Black Plastic Flower Pot = Vaso de flor de plástico preto +Brass Pole = Poste de bronze +Brass Table Legs = Pernas da mesa de bronze +red = vermelho +green = verde +blue = azul +white = branco +pink = rosa +violet = violeta +## 1: Color name +Curtains (%s) = Cortina (%s) +Drop-Ceiling Tile = Placa de teto +Glass Skylight = Claraboia de vidro +Glass Table (Small, Round) = Mesa de vidro (pequena, redonda) +Glass Table (Small, Square) = Mesa de vidro (pequena, quadrada) +Green Plastic Flower Pot = Vaso de flor de plástico verde +Large Area Rug = Tapete grande +Large Glass Table Piece = Pedaço da mesa grande de vidro +Large Stereo Speaker = Auto-falante grande +Legs for Utility Table = Pernas para mesa +Projection Screen Material = Material de tela de projeção +Small Surround Speaker = Auto-falante pequeno +Small Throw Rug = Tapete pequeno +Stereo Receiver = Aparelho de som +Terracotta Flower Pot = Vaso de flor de terracota +Terracotta Roofing = Telhado de terracota +Textured Ceiling Paint = Pintura texturizada do teto +Utility Table = Mesa de trabalho +Utility table mk2 = Mesa de trabalho mk2 +Wooden Shutter (Black) = Persiana de madeira (preta) +Wooden Shutter (Dark Grey) = Persiana de madeira (cinza escura) +Wooden Shutter (Forest Green) = Persiana de madeira (verde) +Wooden Shutter (Grey) = Persiana de madeira (cinza) +Wooden Shutter (Light Blue) = Persiana de madeira (azul clara) +Wooden Shutter (Purple) = Persiana de madeira (roxa) +Wooden Shutter (Red) = Persiana de madeira (vermelha) +Wooden Shutter (Unpainted Mahogany) = Persiana de madeira (mogno) +Wooden Shutter (Unpainted Oak) = Persiana de madeira (carvalho) +Wooden Shutter (White) = Persiana de madeira (branca) +Wooden Shutter (Yellow) = Persiana de madeira (amarela) +Wooden Tabletop piece = Pedaço do tampo da mesa +Wooden Tabletop (Small, Round) = Tampo da mesa (pequeno, arredondado) +Wooden Tabletop (Small, Square) = Tampo da mesa (pequeno, quadrado) +Wood Shingles = Telhas de madeira +Wrought Iron Pole = Poste de ferro forjado +someone = alguém +## 1: Player name +Sorry, %s owns that spot. = Desculpe, mas esse local pertence a %s. + +### lighting.lua ### +White Glowlight (small cube) = Arandela branca (cubo pequeno) +White Glowlight (small cube, on ceiling) = Arandela branca (cubo pequeno, na parede) +White Glowlight (thick) = Arandela branca (grossa) +White Glowlight (thick, on wall) = Arandela branca (grossa, na parede) +White Glowlight (thin) = Arandela branca (fina) +White Glowlight (thin, on wall) = Arandela branca (fina, na parede) +Yellow Glowlight (small cube) = Arandela amarela (cubo pequeno) +Yellow Glowlight (small cube, on ceiling) = Arandela amarela (cubo pequeno, na parede) +Yellow Glowlight (thick) = Arandela amarela (grossa) +Yellow Glowlight (thick, on wall) = Arandela amarela (grossa, na parede) +Yellow Glowlight (thin) = Arandela amarela (fina) +Yellow Glowlight (thin, on wall) = Arandela amarela (fina, na parede) + +### locked.lua ### +## 1: Item description, 2: Owner name +%s (owned by %s) = %s (pertence a %s) +## 1: Player name, 2: Item description, 3: Owner name, 4: Position +%s tried to access a %s belonging to %s at %s = %s tentou acessar %s pertencente a %s em %s +## 1: Item description +%s (Locked) = %s (trancado) +Locked Cabinet = Armário trancado +Locked Nightstand = Criado-mudo trancado + +### nightstands.lua ### +Mahogany Nightstand with One Drawer = Criado-mudo de mogno, com uma gaveta +Mahogany Nightstand with Two Drawers = Criado-mudo de mogno, com duas gavetas +Oak Nightstand with One Drawer = Criado-mudo de carvalho, com uma gaveta +Oak Nightstand with Two Drawers = Criado-mudo de carvalho, com duas gavetas +## 1: Player name, 2: position +%s moves stuff in nightstand at %s = %s moveu item(ns) no criado-mudo em %s +%s moves stuff to nightstand at %s = %s moveu item(ns) para o criado-mudo em %s +%s takes stuff from nightstand at %s = %s tirou item(ns) do criado-mudo em %s +One-drawer Nightstand = Criado-mudo com uma gaveta +Two-drawer Nightstand = Criado-mudo com duas gavetas + +### oven.lua ### +Oven = Forno +## 1: Item name +Could not insert '%s' = Não foi possível inserir '%s' +## 1: Percentage +Oven active: %d%% = Forno ativo: %d%% +Oven out of fuel = O forno está sem combustível +Oven is empty = O forno está vazio + +### refrigerator.lua ### +Refrigerator = Geladeira +## 1: Player name, 2: position +%s moves stuff in refrigerator at %s = %s moveu item(ns) na geladeira em %s +%s moves stuff to refrigerator at %s = %s moveu item(ns) para a geladeira em %s +%s takes stuff from refrigerator at %s = %s tirou item(ns) da geladeira em %s +Not enough vertical space to place a refrigerator! = Não existe espaço vertical suficiente para adicionar uma geladeira. + +### television.lua ### +Small CRT Television = TV de tubo pequena + +### signs_lib.lua ### +%s wrote "%s" to sign at %s = %s escreveu "%s" na placa em %s +Reading cached character database. = Lendo banco de dados de caracteres no cache. +Font seems to have changed. Rebuilding cache. = Aparentemente as fontes foram alteradas. Reconstruindo o cache. +Could not find font line height in cached DB. Trying brute force. = Não foi possível encontrar a altura da linha da fonte no cache do BD. Tentando na marra. +Registered %s and %s = %s e %s registrados +signs loaded = placas carregadas diff --git a/mods/poudlard/poudecor/locale/template.txt b/mods/poudlard/poudecor/locale/template.txt new file mode 100644 index 0000000..fd1b64b --- /dev/null +++ b/mods/poudlard/poudecor/locale/template.txt @@ -0,0 +1,198 @@ + +########################## +# Template language file # +########################## + +### Special strings ### + +### kitchen_cabinet.lua ### +Kitchen Cabinet = +## 1: Player name, 2: position +%s moves stuff in kitchen cabinet at %s = +%s moves stuff to kitchen cabinet at %s = +%s takes stuff from kitchen cabinet at %s = +Half-height Kitchen Cabinet (on ceiling) = +Under-sink cabinet = +Kitchen Cabinet with sink = + +### door_models.lua ### +Mahogany Closet Door = +Oak Closet Door = +Fancy Wood/Glass Door = +Glass Office Door = +Glass and Wood, Mahogany-colored = +Glass and Wood, Oak-colored = +Glass and Wood, White = +Plain Wooden Door = +left = +right = +## 1: Side the doors opens to +(Top Half, %s-opening) = +(%s-opening) = + + +### door_nodes.lua ### +Not enough vertical space to place a door! = + +### crafts.lua ### +Brass Ingot = +Bucket of white paint = +Legs for Small Utility table = +Plastic sheet = +Silicon lump = +Simple Integrated Circuit = +Small Wooden Drawer = +Terracotta Roof Tile = +Titanium Dioxide = +Uncooked Terracotta Base = +Unprocessed Plastic base = + +### door_models.lua ### + +### door_nodes.lua ### + +### fences.lua ### +Barbed Wire Fence = +Barbed Wire Fence Gate = +Brass Fence/railing = +Brass Fence/railing with sign = +Chainlink Fence = +Chainlink Fence Gate = +Chainlink Fence Gate (open) = +Unpainted Picket Fence = +Unpainted Picket Fence Gate = +White Picket Fence = +White Picket Fence Gate = +Wooden Privacy Fence = +Wrought Iron Fence/railing = +Wrought Iron Fence/railing with sign = +want to simply place the wielded item like usual. = + +### furniture_medieval.lua ### +Bars = +Binding Bars = +Chains = +Wall Torch = + +### furniture_bathroom.lua ### +Toilet = +Sink = +Taps = +Shower Tray = +Shower Head = + +### init.lua ### +Loaded! = +Asphalt Shingles = +Black Plastic Flower Pot = +Brass Pole = +Brass Table Legs = +red = +green = +blue = +white = +pink = +violet = +## 1: Color name +Curtains (%s) = +Drop-Ceiling Tile = +Glass Skylight = +Glass Table (Small, Round) = +Glass Table (Small, Square) = +Green Plastic Flower Pot = +Large Area Rug = +Large Glass Table Piece = +Large Stereo Speaker = +Legs for Utility Table = +Projection Screen Material = +Small Surround Speaker = +Small Throw Rug = +Stereo Receiver = +Terracotta Flower Pot = +Terracotta Roofing = +Textured Ceiling Paint = +Utility Table = +Utility table mk2 = +Wooden Shutter (Black) = +Wooden Shutter (Dark Grey) = +Wooden Shutter (Forest Green) = +Wooden Shutter (Grey) = +Wooden Shutter (Light Blue) = +Wooden Shutter (Purple) = +Wooden Shutter (Red) = +Wooden Shutter (Unpainted Mahogany) = +Wooden Shutter (Unpainted Oak) = +Wooden Shutter (White) = +Wooden Shutter (Yellow) = +Wooden Tabletop piece = +Wooden Tabletop (Small, Round) = +Wooden Tabletop (Small, Square) = +Wood Shingles = +Wrought Iron Pole = +someone = +## 1: Player name +Sorry, %s owns that spot. = + +### lighting.lua ### +White Glowlight (small cube) = +White Glowlight (small cube, on ceiling) = +White Glowlight (thick) = +White Glowlight (thick, on wall) = +White Glowlight (thin) = +White Glowlight (thin, on wall) = +Yellow Glowlight (small cube) = +Yellow Glowlight (small cube, on ceiling) = +Yellow Glowlight (thick) = +Yellow Glowlight (thick, on wall) = +Yellow Glowlight (thin) = +Yellow Glowlight (thin, on wall) = + +### locked.lua ### +## 1: Item description, 2: Owner name +%s (owned by %s) = +## 1: Player name, 2: Item description, 3: Owner name, 4: Position +%s tried to access a %s belonging to %s at %s = +## 1: Item description +%s (Locked) = +Locked Cabinet = +Locked Nightstand = + +### nightstands.lua ### +Mahogany Nightstand with One Drawer = +Mahogany Nightstand with Two Drawers = +Oak Nightstand with One Drawer = +Oak Nightstand with Two Drawers = +## 1: Player name, 2: position +%s moves stuff in nightstand at %s = +%s moves stuff to nightstand at %s = +%s takes stuff from nightstand at %s = +One-drawer Nightstand = +Two-drawer Nightstand = + +### oven.lua ### +Oven = +## 1: Item name +Could not insert '%s' = +## 1: Percentage +Oven active: %d%% = +Oven out of fuel = +Oven is empty = + +### refrigerator.lua ### +Refrigerator = +## 1: Player name, 2: position +%s moves stuff in refrigerator at %s = +%s moves stuff to refrigerator at %s = +%s takes stuff from refrigerator at %s = +Not enough vertical space to place a refrigerator! = + +### television.lua ### +Small CRT Television = + +### signs_lib.lua ### +%s wrote "%s" to sign at %s = +Reading cached character database. = +Font seems to have changed. Rebuilding cache. = +Could not find font line height in cached DB. Trying brute force. = +Registered %s and %s = +signs loaded = diff --git a/mods/poudlard/poudecor/nightstand.lua b/mods/poudlard/poudecor/nightstand.lua new file mode 100644 index 0000000..29c9c06 --- /dev/null +++ b/mods/poudlard/poudecor/nightstand.lua @@ -0,0 +1,154 @@ +-- This file supplies nightstands +-- Load translation library if intllib is installed + +local S +if (minetest.get_modpath("intllib")) then + dofile(minetest.get_modpath("intllib").."/intllib.lua") + S = intllib.Getter(minetest.get_current_modname()) + else + S = function ( s ) return s end +end + + +-- OAK NIGHTSTAND + +minetest.register_node('poudlard:nightstand_1', { + drawtype = "nodebox", + description = S("Oak Nightstand with Two Drawers"), + tiles = { 'homedecor_nightstand_oak_top.png', + 'homedecor_nightstand_oak_bottom.png', + 'homedecor_nightstand_oak_right.png', + 'homedecor_nightstand_oak_left.png', + 'homedecor_nightstand_oak_back.png', + 'homedecor_nightstand_oak_2_drawer_front.png'}, + sunlight_propagates = false, + paramtype = "light", + paramtype2 = "facedir", + walkable = true, + selection_box = { + type = "fixed", + fixed = { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 } + }, + node_box = { + type = "fixed", + fixed = { + { -8/16, -8/16, -30/64, 8/16, 8/16, 8/16 }, -- main body + { -7/16, 1/16, -32/64, 7/16, 7/16, -29/64 }, -- top drawer face + { -7/16, -7/16, -32/64, 7/16, -1/16, -29/64 }, -- bottom drawer face + + } + }, + groups = { snappy = 3 }, + sounds = default.node_sound_wood_defaults(), + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", + "size[8,7]".. + "list[current_name;main;0,0;8,2;]".. + "list[current_player;main;0,3;8,4;]") + meta:set_string("infotext", S("Two-drawer Nightstand")) + local inv = meta:get_inventory() + inv:set_size("main", 16) + end, + can_dig = function(pos,player) + local meta = minetest.get_meta(pos); + local inv = meta:get_inventory() + return inv:is_empty("main") + end, + on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) + minetest.log("action", S("%s moves stuff in nightstand at %s"):format( + player:get_player_name(), + minetest.pos_to_string(pos) + )) + end, + on_metadata_inventory_put = function(pos, listname, index, stack, player) + minetest.log("action", S("%s moves stuff to nightstand at %s"):format( + player:get_player_name(), + minetest.pos_to_string(pos) + )) + end, + on_metadata_inventory_take = function(pos, listname, index, stack, player) + minetest.log("action", S("%s takes stuff from nightstand at %s"):format( + player:get_player_name(), + minetest.pos_to_string(pos) + )) + end, +}) + + +--MAHOGANY NIGHSTAND ----------------------- + +minetest.register_node('poudlard:nightstand_2', { + drawtype = "nodebox", + description = S("Mahogany Nightstand with Two Drawers"), + tiles = { 'homedecor_nightstand_mahogany_top.png', + 'homedecor_nightstand_mahogany_bottom.png', + 'homedecor_nightstand_mahogany_right.png', + 'homedecor_nightstand_mahogany_left.png', + 'homedecor_nightstand_mahogany_back.png', + 'homedecor_nightstand_mahogany_2_drawer_front.png'}, + sunlight_propagates = false, + paramtype = "light", + paramtype2 = "facedir", + walkable = true, + selection_box = { + type = "fixed", + fixed = { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 } + }, + node_box = { + type = "fixed", + fixed = { + { -8/16, -8/16, -30/64, 8/16, 8/16, 8/16 }, -- main body + { -7/16, 1/16, -32/64, 7/16, 7/16, -29/64 }, -- top drawer face + { -7/16, -7/16, -32/64, 7/16, -1/16, -29/64 }, -- bottom drawer face + + } + }, + groups = { snappy = 3 }, + sounds = default.node_sound_wood_defaults(), + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", + "size[8,7]".. + "list[current_name;main;0,0;8,2;]".. + "list[current_player;main;0,3;8,4;]") + meta:set_string("infotext", S("Two-drawer Nightstand")) + local inv = meta:get_inventory() + inv:set_size("main", 16) + end, + can_dig = function(pos,player) + local meta = minetest.get_meta(pos); + local inv = meta:get_inventory() + return inv:is_empty("main") + end, + on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) + minetest.log("action", S("%s moves stuff in nightstand at %s"):format( + player:get_player_name(), + minetest.pos_to_string(pos) + )) + end, + on_metadata_inventory_put = function(pos, listname, index, stack, player) + minetest.log("action", S("%s moves stuff to nightstand at %s"):format( + player:get_player_name(), + minetest.pos_to_string(pos) + )) + end, + on_metadata_inventory_take = function(pos, listname, index, stack, player) + minetest.log("action", S("%s takes stuff from nightstand at %s"):format( + player:get_player_name(), + minetest.pos_to_string(pos) + )) + end, +}) + + + +-------Alias for homedecor +minetest.register_alias("homedecor:nightstand_oak_two_drawers", "poudecor:nightstand_1") +minetest.register_alias("homedecor:nightstand_mahogany_two_drawerst", "poudecor:nightstand_2") + + +-------Alias for Poudlard +minetest.register_alias("poudecor:nightstand_1", "poudlard:nightstand_1") +minetest.register_alias("poudecor:nightstand_2", "poudlard:nightstand_2") + diff --git a/mods/poudlard/poudecor/torch.lua b/mods/poudlard/poudecor/torch.lua new file mode 100644 index 0000000..0edb1b1 --- /dev/null +++ b/mods/poudlard/poudecor/torch.lua @@ -0,0 +1,61 @@ + +-- Load translation library if intllib is installed + +local S +if (minetest.get_modpath("intllib")) then + dofile(minetest.get_modpath("intllib").."/intllib.lua") + S = intllib.Getter(minetest.get_current_modname()) + else + S = function ( s ) return s end +end + + + +minetest.register_node("poudlard:torch_wall", { + description = S("Wall Torch"), + drawtype = "nodebox", + tiles = { + "forniture_torch_wall_s.png", + "forniture_torch_wall_i.png", + { + name="forniture_torch_wall_anim.png", + animation={ + type="vertical_frames", + aspect_w=40, + aspect_h=40, + length=1.0, + }, + }, + }, + inventory_image="3dforniture_inv_torch_wall.png", + paramtype = "light", + paramtype2 = "facedir", + node_box = { + type = "fixed", + fixed = { + { -0.05, -0.45, 0.45, 0.05, -0.35, 0.50, }, + { -0.05, -0.35, 0.40, 0.05, -0.25, 0.50, }, + { -0.05, -0.25, 0.35, 0.05, -0.15, 0.45, }, + { -0.05, -0.15, 0.30, 0.05, -0.05, 0.40, }, + { -0.05, -0.05, 0.25, 0.05, 0.00, 0.35, }, + { -0.10, 0.00, 0.20, 0.10, 0.05, 0.40, }, + { -0.15, 0.05, 0.15, 0.15, 0.15, 0.45, }, + { -0.10, 0.15, 0.20, 0.10, 0.25, 0.40, }, + { -0.05, 0.25, 0.25, 0.05, 0.35, 0.35, }, + }, + }, + sunlight_propagates = true, + walkable = false, + light_source = 14, + selection_box = { + type = "fixed", + fixed = { -0.15, -0.45, 0.15, 0.15,0.35, 0.5 }, + }, + groups = {cracky=2}, +}) + + +minetest.register_alias("homedecor:torch_wall", "poudecor:torch_wall") + +minetest.register_alias("poudecor:torch_wall", "poudlard:torch_wall") + diff --git a/mods/poudlard/readme.txt b/mods/poudlard/readme.txt new file mode 100644 index 0000000..eddcd94 --- /dev/null +++ b/mods/poudlard/readme.txt @@ -0,0 +1,9 @@ +All code and textures from +- moreblocks and stairsplus by Calinou +- "homedecor" by Vanessa Ezekowitz. + +Just a matter of more light versions by Perlipop. ++ raccordable images for curtains + + +Licenses: For the lua code, GPL. For all images and everything else, WTFPL. diff --git a/mods/poudlard/registration.lua b/mods/poudlard/registration.lua new file mode 100644 index 0000000..e5ed958 --- /dev/null +++ b/mods/poudlard/registration.lua @@ -0,0 +1,225 @@ + + +-- Nodes will be called :{stair,slab,panel,micro}_ +function poudlard.register_stair_and_slab_and_panel_and_micro(modname, subname, recipeitem, groups, images, desc_stair, desc_slab, desc_panel, desc_micro, drop) + poudlard.register_stair(modname, subname, recipeitem, groups, images, desc_stair, drop) + poudlard.register_slab(modname, subname, recipeitem, groups, images, desc_slab, drop) + poudlard.register_panel(modname, subname, recipeitem, groups, images, desc_panel, drop) + poudlard.register_micro(modname, subname, recipeitem, groups, images, desc_micro, drop) +end + + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "poudstone", "poudlard:poudstone", + {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3, not_in_creative_inventory=0}, + {"poudlard_poudstone.png"}, + "Poudlard stone Stairs", + "Poudlard stone Slab", + "Poudlard stone Panel", + "Poudlard stone Microblock", + "poudstone") + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "poudwood", "poudlard:poudwood", + {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3, not_in_creative_inventory=0}, + {"poudlard_poudwood.png"}, + "Poudlard Wood Stairs", + "Poudlard Wood Slab", + "POudlard Wood Panel", + "Poudlard Wood Microblock", + "poudwood") + + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "redblock", "poudlard:redblock", + {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3, not_in_creative_inventory=0}, + {"poudlard_redblock.png"}, + "redblock Stairs", + "redblock Slab", + "redblock Panel", + "redblock Microblock", + "redblock") + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "blackblock", "poudlard:blackblock", + {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3, not_in_creative_inventory=0}, + {"poudlard_blackblock.png"}, + "blackblock Stairs", + "blackblock Slab", + "blackblock Panel", + "blackblock Microblock", + "blackblock") + + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "wood", "default:wood", + {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3}, + {"default_wood.png"}, + "Wooden Stairs", + "Wooden Slab", + "Wooden Panel", + "Wooden Microblock", + "wood", + "facedir") + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "stone", "default:stone", + {cracky=3}, + {"default_stone.png"}, + "Stone Stairs", + "Stone Slab", + "Stone Panel", + "Stone Microblock", + "cobble", + "none") + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "cobble", "default:cobble", + {cracky=3}, + {"default_cobble.png"}, + "Cobblestone Stairs", + "Cobblestone Slab", + "Cobblestone Panel", + "Cobblestone Microblock", + "cobble", + "none") + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "mossycobble", "default:mossycobble", + {cracky=3}, + {"default_mossycobble.png"}, + "Mossy Cobblestone Stairs", + "Mossy Cobblestone Slab", + "Mossy Cobblestone Panel", + "Mossy Cobblestone Microblock", + "mossycobble", + "none") + + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "sandstone", "default:sandstone", + {crumbly=2,cracky=2}, + {"default_sandstone.png"}, + "Sandstone Stairs", + "Sandstone Slab", + "Sandstone Panel", + "Sandstone Microblock", + "sandstone", + "none") + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "steelblock", "default:steelblock", + {snappy=1,bendy=2,cracky=1,melty=2,level=2}, + {"default_steel_block.png"}, + "Steel Block Stairs", + "Steel Block Slab", + "Steel Block Panel", + "Steel Microblock", + "steelblock", + "none") + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "desert_stone", "default:desert_stone", + {cracky=3}, + {"default_desert_stone.png"}, + "Desert Stone Stairs", + "Desert Stone Slab", + "Desert Stone Panel", + "Desert Stone Microblock", + "desert_stone", + "none") + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "glass", "default:glass", + {snappy=2,cracky=3,oddly_breakable_by_hand=3}, + {"default_glass.png"}, + "Glass Stairs", + "Glass Slab", + "Glass Panel", + "Glass Microblock", + "glass", + "none") + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "tree", "default:tree", + {tree=1,snappy=1,choppy=2,oddly_breakable_by_hand=1,flammable=2}, + {"default_tree.png"}, + "Tree Stairs", + "Tree Slab", + "Tree Panel", + "Tree Microblock", + "tree", + "none") + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "jungletree", "default:jungletree", + {tree=1,snappy=1,choppy=2,oddly_breakable_by_hand=1,flammable=2}, + {"default_jungletree_top.png", "default_jungletree_top.png", "default_jungletree.png"}, + "Jungle Tree Stairs", + "Jungle Tree Slab", + "Jungle Tree Panel", + "Jungle Tree Microblock", + "jungletree", + "none") + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "stonebrick", "default:stonebrick", + {cracky=3, not_in_creative_inventory=1}, + {"default_stone_brick.png"}, + "Stone Bricks Stairs", + "Stone Bricks Slab", + "Stone Bricks Panel", + "Stone Bricks Microblock", + "stonebrick") + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "ironstonebricks", "poudlard:ironstonebricks", + {cracky=3, not_in_creative_inventory=0}, + {"poudlard_ironstonebrick.png"}, + "Iron Stone Bricks Stairs", + "Iron Stone Bricks Slab", + "Iron Stone Bricks Panel", + "Iron Stone Bricks Microblock", + "ironstonebricks") + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "stone_tile", "poudlard:stone_tile", + {cracky=3, not_in_creative_inventory=0}, + {"poudlard_stonesquare.png"}, + "Stonesquare Stairs", + "Stonesquare Slab", + "Stonesquare Panel", + "Stonesquare Microblock", + "stone_tile") + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "split_stone_tile", "poudlard:split_stone_tile", + {cracky=3}, + {"poudlard_splitstonesquare_top.png", "poudlard_splitstonesquare.png"}, + "Split Stonesquare Stairs", + "Split Stonesquare Slab", + "Split Stonesquare Panel", + "Split Stonesquare Microblock", + "split_stone_tile") + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "junglewood", "poudlard:junglewood", + {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3, not_in_creative_inventory01}, + {"poudlard_junglewood.png"}, + "Jungle Wood Stairs", + "Jungle Wood Slab", + "Jungle Wood Panel", + "Jungle Wood Microblock", + "junglewood") + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "circlestonebricks", "poudlard:circlestonebricks", + {cracky=3, not_in_creative_inventory=0}, + {"poudlard_circlestonebrick.png"}, + "Circle Stone Brick Stairs", + "Circle Stone Brick Slab", + "Cricle Stone Brick Panel", + "Circle Stone Brick Microblock", + "circlestonebricks") + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "plankstone", "poudlard:plankstone", + {cracky=3, not_in_creative_inventory=0}, + {"poudlard_plankstone.png"}, + "Plankstone Stairs", + "Plankstone Slab", + "Plankstone Panel", + "Plankstone Microblock", + "plankstone") + + + +poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "ironstone", "poudlard:ironstone", + {cracky=3, not_in_creative_inventory=0}, + {"poudlard_ironstone.png"}, + "Iron Stone Stairs", + "Iron Stone Slab", + "Iron Stone Panel", + "Iron Stone Microblock", + "ironstone") + + diff --git a/mods/poudlard/textures/3dforniture_inv_torch_wall.png b/mods/poudlard/textures/3dforniture_inv_torch_wall.png new file mode 100644 index 0000000000000000000000000000000000000000..4537b2ecf5cc569911259b65d5f20592152deef3 GIT binary patch literal 2618 zcmd^B2V0W~8vINl((8!}p?N6MA_@vYTtgA1mw=$O0KrI6K;URWL85Go5CK7|NRhIr zl(2vbQdOiyDN7S6OAkrt327YnJ8qt5W`4jt^S(oLw7)7Yq96hQfVkB)3+F>e{f|e% zhg#T_w0>w1oT;5D0MwC1dA?8p00WM;E>{xoN7lW>eYE+X zKX$drr=E1Ng{(aJ-fC?kv?lkohwD|rp3I^rjD1^Ux#9AHztl{wGPC;(r^uWctTuKN zB%nL;2wFS6XE#2W3l_ZlGmVzNg|q9f%{5|%DY4voVeW|HK?|_eiNSctMc*5p~x}Hse^v) z6nyk_8=j3(ViPR)<4kEKx{G1I?Mx_cQ1o}2HF;gwwR|Od0dyrnmOmV^+Ni{8v*R?M zr}e`ADN^Ai%kW#>+1;Ux4za}yMZuaVe^G;8ZZ23dp0AL9o)q#cLuxWjjX5AE=$Bf) ze`+{Eo%@T}QkKxy5E~X2fx-B#KY{PL$!=O6WoO&5i`01Iu5`4pfQgzx0)j2v9uC;* zP}vFvZ?@>uv*h=>F7RiM7eDh^$3S?`RW>S=mO5dq=3s8E3ab}07bDG~V)q^%VUv#0 zpIyw(z;ink_zPD1V_IA9B&$Nf}N%j8}|!P4E>g$oxan-t~sAP-LQ_qPUUL+vRp1 z9vQ9 z0=W^Egd(~pqywhBUR^* z$MJYP-pbmV^Bv5ZfN-b4{25SEVuD~1j7FpF?d_eNon2jB9UL5NZEc;LoDNGt{*qk> z07rmGXM6O)|2F_M3w9C!pc7UWrY`PXtz!X^vNw(kVgA1H^-j3Y&uNj*e=!gvm1apF zM5A7tO;4YUIuqrP7pD-Ya1v2SC|o~yjy3u?Q;_+9g=9wK?lM}ne}540mMwW?kMy^t zw)RJ*)EN`c-0p0JYm?zkLrs;TLxz`osy~#SG!1(7mz-i)XUAVsv{K^&O_p2rNV_N{ zq&o!gJ9Ww2OZZ2WP24R1CX#i-ea`dheV@3vF#`xH-2i#96d939K*54l#^&(GLKTeubNv|lPD60N96W?EF^>S}dX8LaYF(>v%>YI-Z~ok@yjM;Xl9B0zlL z?}7A`bNKolU)N|EhSNj_c;pN7$-mEx4WvcKDBB4SJj?Q`i74lEGA`AOX8;Z!Ot-`H z6l_uy9^I9|6*>Pm@M{n<}m8Y>&r0s3z;@dZ~ zn`}VpsRfEB0`2z#_SDWt27atJB&t_)8oag!ZCD=xJY^;AXT~?m@-wL8_+CGLQ*bR(kd{m+Se;43Qk+nud5) z>5W*N=b+pY&jL0Q2j$O16GLWfppA{$BcLzuV~9=_K=oo!k>rx7$aq z{)~ymIO=Tt(`4%YhJ&&o>X-L-z5PZoRn^T+lhe&>e}H{`8`HncC#sZa zzLp4{ZGGW#4d-QIg2=1SnayD#m#iDO-HC4$ZFrWoBZgHzXsub;6N zp1MDp`gu-A0c{^0kp6Xs6Vg71k3>@<9A3bP;Fq5jM@LrJ8FItt>|eeas5VY6p#%-f z*{3L<>?mxM;E2t4YCd{D{rT8@;-yVBHA}Q1HQRIi82+5()T^**O+6o{y5X4{-k&~l zGjc-(dan(}sI)qx*-<)Msx&Dm^*-4h9ZYJVjm-ta$$jU`fS{%Se@;G$2fhl*}FfDmuF@wSm)zhURewHOg*3ES-O*NYO0VO}+ z$7K7dX5=4EhLk_enbvjsbv|^7=@bpUAO0&CGy2NPul&Q%hZw1QZC?k6SN;8o#L^4I zvkuC9^<7Qf{hmUN?b1pMmxyga&ed-0DwS9>1Lt)qs9Ul;;OZjY=E&O!=|^N`!y5vQ zVY(%EQSV+6;BAoIU(L1ZaW8D}2rK}X*i$1E%=$|nH+A`5^Qk7@!cP6c!1QnGaRO#v6Lwc} YsapG$-xfpk@b3XuSL`j`nPDFO7iQj}wEzGB literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/Thumbs.db b/mods/poudlard/textures/Thumbs.db new file mode 100644 index 0000000000000000000000000000000000000000..895ac10d8c2720cb03e304a571e4f82699c637dc GIT binary patch literal 35840 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 literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/forniture_armchair_lat1_black.png b/mods/poudlard/textures/forniture_armchair_lat1_black.png new file mode 100644 index 0000000000000000000000000000000000000000..37f04ea6051aec29c594484a6acf5f7a9d6ad184 GIT binary patch literal 476 zcmV<20VDp2P)xJv})&IVmYALqkI{GBPVGD>pYcDk>^SNJt_gB04%c zBO@a`JUlKgE+;1^FE1}YKR+!kEkHm(J3BipEG#xQHeE83vH$=8)=5M`R2b6*!2@DM zQ49dU)b3i{Z{yj?{SVd|Sf=XK%E1}$7JolnzTCRsBhC@%DQw=?Qkxqkzedb{)N^#2{_53u4*PelA0E~6lv zX;@X|v{u0$KpMU8R`*;ar)^N!kgYFIi(ztWF#H2L6&|+R^<)G90000^GBuwyEr%^IlQ1ZIC@qLBE{iTHekmz@ zDJF9!Gnz9nkT5l%H79i^D}pO8jxQ{QEGT#=Dt{_2iY_aGD=?8TF_tmH+HKkZ007EK zL_t&-(+$mqVZ%TS06-PPiS3x-8ASWf*WLmLhugN<=ftXh_aac|Hq%T>iD)2U7;j%m zx0m4huzhVR1haI4b)uL*x|IVQ_R!{i|4IAlgjf{llh5z{_~ksB64ZgHcd}$=j_*{W zg{Zrb8@jMv(N0Prlp+~5^)q1F9--N2nZ+#2YMA1h8Gty2?w;d=(XS6ckeq4qXrsWDyZx5D-EO z3sw&gM+^*F4-Z8Q40sh4I0*@E6BA$&5ljsYISL9<4h}vG3rP$NSPu_M4Gm%u5or<< z=WIo|0002YNkljhn}1VS-U<}zfH#7luOK81o zUQlv4UsJy-s?Mc<1I!z0K$dMZ$5sk3qZw7@{~Dz<0P>~Rg~JlFL_2i~Q%T(9JA3n7 bM}y@LK*1u5=mpsR00000NkvXXu0mjfNN9<& literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/forniture_armchair_lat1_violet.png b/mods/poudlard/textures/forniture_armchair_lat1_violet.png new file mode 100644 index 0000000000000000000000000000000000000000..ddc2701f0a84833150c756b96c116df63b874faa GIT binary patch literal 422 zcmV;X0a^ZuP)iD)2U7;j%m zx0m4hw0&(V1haI4b)uL*x|IVQ_R!{i|4#e)j93)tlP~Z6_~ksB64ZgHcd}$=j_*{W zg{Zrb8@jMv(N0Prlp+&-X)K3oEs1R{i*7EBZ!eB;FOP9Ak#jJUbTO88F_(8ToO?5!d^Dhb zHKBktqk%T1f;XmvH>rgQ- zmJ1zX0002UNkl|QHzy0R zSp~IRwR{%#14r+`+on>_tF3Qxy9ubUm&mxp;I(RmhP}4&i;b90hZ~41Z(}(go?3PD z0T}bW_@f^1_eFOvF94PH3h6&V>BKR-Vc6B8E~7ehlsK|w(p z8X6Q76doQPHa0dE78X1_JU2HtKtMn>H8m|QEgc;l7#J8E8yhJpDIg#qC@3g7IXNmS zDl021IyyQrF)=hWG$tk{Gcz+JBqS#%Cn6#u92^`kFE1Y-A2KpBAt50yE-ob{B``2B zBO@a$EG!$TNUHz<0MAK8K~xyi1;K@313?S`Fc(t_Ju@7$?fsXl1k_I3 zmXB^d5=(rR>UsUFF*@v<*9hfsTX;MQfy+SutR1H1^~ZeoOMoRL3x~2 k1Pr}4awu(jPB~Hd2Q$?oz-&TJm;e9(07*qoM6N<$f}Q%2R{#J2 literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/forniture_armchair_lat2_blue.png b/mods/poudlard/textures/forniture_armchair_lat2_blue.png new file mode 100644 index 0000000000000000000000000000000000000000..ffbd8a4de494f4e56b53055c9ca5bc79038f4e11 GIT binary patch literal 375 zcmV--0f_#IP)#XlDQb0K7>=K~xyi4b3%z1ThQ*Kpia%gW0mw{r^wi#ub#HZr7IC z;ZEi;M30sC!FYFG>pdW~Jj}0?&@-7nR9YGPz^gIwYcFVm1%8Iz;%e7?guF95)0JoX%&Enndns0Jw^(lIt?06=@C&FH7C4cXh_~)6tjofE10a&1<+{J`HM+O_GV@B4x^-EU>>%+VM}+ zdzmLRxRd_2Zs9YQ@R=k43Rg|TrKKt3@CClP$Lu{9t7Bt?-b=L@iOGym0BBW3=h`=t lptAzu=psjN^<20*{sY_s8gEz@#PI+C002ovPDHLkV1o3(l`Q}O literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/forniture_armchair_lat2_red.png b/mods/poudlard/textures/forniture_armchair_lat2_red.png new file mode 100644 index 0000000000000000000000000000000000000000..8f17f0b10e764b66d7fd44ceaa79b0243589a403 GIT binary patch literal 395 zcmV;60d)R}P)9t8z!5)vZ@1}FyyAO!_(6B98A2v`pfS`QB* z1_mz(2r35$Vi6HS3kzuy5(^b!AV3xR2b6*!39DDK@0$}!T~4i zzT@@(Kam8yF6WZCxhh*C0^DZ4HVap?bH2!-mY3-H$Bsi3d?Db&09+oxU)l1VgiTqIAaO9K06 zpdEiiz2$jAgDdK9ZFYBKzPm|oK;fdXKQ&in?7zS__mI4$Y-OyB&{{4Q0x_8p3IMID p=v>-Ha_g)>IJ(HuY8e(Tj{jK$8(~!5^KJkD002ovPDHLkV1iPkfwKSr literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/forniture_armchair_lat2_violet.png b/mods/poudlard/textures/forniture_armchair_lat2_violet.png new file mode 100644 index 0000000000000000000000000000000000000000..1ee129c1fbe8e6f0d17df0a992278de487bc2479 GIT binary patch literal 391 zcmV;20eJq2P)z;%e7?guF95)0QZ^i-QwNtns0Jw^(lIt?06=@C&E@~C4X<0_~)6tjofE10a&1<+{J`HM+O_GV@B4x^-EU>*#+VD@* zdzmLRxRd_2Zs9YQ@R=k43Rg|TrKKt3@CClR$Lu{9t7Bt?-b=L@iOGym0BBW3=h}CY lptAzu=psjN^<20*{sY^Z8gI1OEBF8a002ovPDHLkV1i@>oH76a literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/forniture_armchair_lat2_yellow.png b/mods/poudlard/textures/forniture_armchair_lat2_yellow.png new file mode 100644 index 0000000000000000000000000000000000000000..b5abd0e9446d8c00b97f50c0670b1bdc12b4d50a GIT binary patch literal 401 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}a)3{WYi^iIakN@#jCy&TdUc{^ zU9x6Fs&;dRc59|idzNlzj&66JUT?mBUx9vqq5i}ogUQ8))5;8|mmAHgHlAB!vY^g% zVZG_%2D7D2=F6JRSGHQL>9AbaX}O`>dUK!kj)}JWXEXhSb>MZ!PKnF;Y7dO2k}dP zm*?a+GQWGhZB}TXfob`IryFZ8ZVSIV@2+H3ooCKuLtl+AN;@|3KmWcoW54oe);Si- ze*WpIb4z@=LG@VV=`+_p7j5UewF_UTNg?07Q7O*Y1^}BtNfTA tC^y|Gij8?!!8B)r>$6**w?w7=Vov_VKUdelXA{sf44$rjF6*2UngBV%pgsTq literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/forniture_armchair_top_black.png b/mods/poudlard/textures/forniture_armchair_top_black.png new file mode 100644 index 0000000000000000000000000000000000000000..e4f91466b51cd8da41f7b69901fb2489217b8398 GIT binary patch literal 481 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU&(80G|+7 zb#--XYwL`RjQIHY;^JacQ&U4jLtS0nh=_=soE#$~BLf42^z?KyGc$dCeG?NCD=VwC zw6vt8q?ni(V`F1;b8{~*uh`hw(9lpzOG|fm_pGd}Z|}Ic zI3FJ$J3G68fB;WV&xC{oe}8`m2L~G)8xIc;M@L6nTU$3bH$Oi=XJ=6sc z@bK`Updbqii@?A@Utiy_urMblr^zm7z5pG6+tbA{MB*~*K~|^34gw4ZT)D5PdaAxF zd-wZ)yCL(8qoMDu7CIH&ljJO}mz;f+eSOVjGq=XP?IGdjo44Kn=E=v>=K0QRj_@}L z`}^v43~t#LHLClY=9X*gNok$-uih_L8Se8}z-YoP(RcSW_2k?y-nNZ+yHsCq{jRFS zDR(3#{MW|+xMLrl&9&LV_g~7~d>4nlOcUdboS(k}b9T)8puD++;ZsR&=K8{jt#Y1o zne;ktEi4c|eSeGc0ujGtj!B;OQcjF#Ebm0$dsUsaJN?D@&{@N~WXd zX3$4z(NJ;IGFZzmQoJ)+%u{pJEl{{cXwWcJz%Eg{NNUk8QMoZz#yw%qGFZtiPqr~v z$S+gAKV#20UClsb&oEWPI$zB&RKYb{%vG?r6951J#7RU!R2b6@&4ob&K@b4I1rlQK zb}p;^mk86qfR1^|h|ImCp$LThu&r7*wr$vif!153h;QKXiAA3+ES6SDI0;aq;9kcrV_pO#(UXEG3r#j1u}uOcKB zCij%7eREgU;T;UNl6GSA=b?Tq(SxhFrgG+f5t*9?(5gzPjLljgbil05dYAvp#6Ni;nlpE5%pm{(0LDo~K~xyi4b6p> z0znW3z&^uaS=aGt`S~Y!1W>OCU7RCxf+`z}kdL?BvZ=wWH38{z3Oe8ASROUIi=(Z` z(8I4*_wTQQjqp75(yV{UhT%X~nk%knI~wp<;-(#m^2jd+Qf*SKXR2yqtR zkyxmf;bT6kjFM?`51GnuQULAK8(Hn&3ftBze!3bqa+#ODu2B!w-Ayea1IkETtaxQd zA6j-*`CPlWKqP~{7H|n!($=?1;wwV9r>>mhUf}-$5~LnSPu_O4GpRu9$*m>q#Yeo z4h~Tc4w)MpS`QD785x=z8&(ewUl0&?6&0`_AEq50ml_(47#Ncp8hjNMoEsZw5)ywF z7M~m(f)^Kf6%}g|5@Zn(Vi6H_6cl$_4i5M7g6BCFS7+nw$X%Z5W85xin8HN`Z zffg2S6BDO3uHOIv0MkiCK~xyi4b6pN!$1rGK(%SZU^`&OXOy)6a_uc}z>V%TqH#GR zp|>FQb(vPmSmg_*Gpvi2Q_CRxS0amGCYgXU%vvLmStE{J zC6snAyjvuZhCR-KHOzW2!*wpZgE-B2Fu;5<#%(LEV<(<_F~oi{$#5*QWhkLyC!Ap> zn`$blY%8p2DW+>Gt7IskUnZDxEw*zlxOXqUZ!EEADWt%j%p(8*0LDo~K~xyi4b6p> z0znW3z&^uaS=aGt`S~Y!1W>OCU7RCxf+`z}kdL?BvZ=wWH38{z3Oe8ASROUIi=(Z` z(8I4*_wTQQjqp75(yV{UhT%X~nk%knI~wp<;-(#m^2jd+Qf*SKXR2yqtR zkyxmf;bT6kjFM?`51GnuQULAK8(Hn&3ftBze!3bqa+#ODu2B!w-Ayea1IkETtaxQd zA6j-*`CPlWKqP~{7H|n!($=?1;wwV9r>>mhUf}-$5~LnQI(sf9SKh&ir_Ik1a6vyMBskv+MRJ-(Jdzn4J2m_fjp zL&2Ix!ktUQo=wD{P{yHD#-dfnqgThISjeSY$fjJ%sbR~iWX!8&%&ce4u4>M&ZO^c8 z(Y1I3S*mgX000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*%17aJ;;Omg3`=u%AJV!L zD&UH&EF4`E{U{Ia_PYj4g~$$nCn%R{c^h{pivgwF^UT*aFycRzd=cK;)5h-r0000< KMNUMnLSTZ7o~*F| literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/forniture_torch_wall_anim.png b/mods/poudlard/textures/forniture_torch_wall_anim.png new file mode 100644 index 0000000000000000000000000000000000000000..f9c47290e38f641201c72017aa4cd12528fddfea GIT binary patch literal 2794 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 literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/forniture_torch_wall_i.png b/mods/poudlard/textures/forniture_torch_wall_i.png new file mode 100644 index 0000000000000000000000000000000000000000..75665e1d70bb685266e061273ed2db45f165280f GIT binary patch literal 1061 zcmXYwX;2eq7{^~cTB}mAhqc;6u%P9LK$1>*-909pd41Ne&`2h`k_-R)3b%&HO$*pPqjMO&MaB zu2~8Ih&35?Y?N^ivSeX&Z%kWZk77|CPT~OcwJw_vECyh~AZ_LJXDg6DBk||EEpWyM zFQI=`F87)c3>DKF;k|J(TuH$3U^SD-(~ABs29A&zsuPOje-C^8Zf$*mmNUucr$csH zSzoN{?J}mKCQP9@$4-&Uc5{StUO z{*T60xn3jeTGta!ZQrWCTe>>etIy9?!fO~!SMdr@JedfpF~k+IGTN=%n~3mgOTcJ z6s2SsDAK4WNVnS#r}84zOn;}py^2dnBeX`_&h1pVP-QV_+p8V$a;gNyn-6%sPIF0! zHjtbUQw3c@0+*x+kb@q<(Q4bCGTKbJwzwImgBQtgtwvewkT&h2ylz@cP!!FwHWQ)E z%oK`^W}4+3K`)aglnEs&r2=D&I7!)fj?Qv9GQ^0uZy-q{F$@BQbF?cmD-bzy5sn zY!@T49e@A3u{(3qU}kFO@(F5PMk?L;$<TO?y&Wf<(xE@WTV~&82sCAe%O1Cce17 zqx-_=--3bD)hgM>5nSiC^&cH$z9;B!@KwD+dRcZjZZIH z9JBLvaQ;;5z9a5nj<2xcndPN#o&(puywblp`bD9v?3Z5~{PZjE%gtLKg}3CD}T!u+g)30A|GELpS%rzo1MMY`)Xamp=0lTF)}_E6%!LfANIWR($O;) czaN{M9BsJ1Z|IIQ!bf`#OnORpR^zYv5C21>mH+?% literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/forniture_torch_wall_s.png b/mods/poudlard/textures/forniture_torch_wall_s.png new file mode 100644 index 0000000000000000000000000000000000000000..34be06937530e34bea3b1e82602fbecea774e79a GIT binary patch literal 1061 zcmV+=1ls$FP)vH^S(O&yE^~TPl8b;>ysk< z=4@S1FtC|YhHOLXizDoi81j4$|Kwl)*<3q1L^L%#hi^lzn@E{qI6OTvtu&#%}R}5MET5F{Ifgv#yk0$A(Uo7`lBrW z%su?EByeL$Nl#QnM^8FPTQ);gonbRkP)xItDvx3~MMX{j%|o@QQzFW|IKOt z#{mD%VWEXz_tR`QJxckqH2=+G{GTV2gjO;$HAX`+Lqb0P*j_U`KZs!`l5|V@hz@UI zK>yfaM@dfqxhj)!ZR7XowK|nu0K0G=&H&IelH8nI-Q&Uq@QdU-0H8nL=R8mt?Q9V69IXO8} zQc^cJH#9UfP*6}iJ3CcXRW>#@R8&+^QBgQJI8X>+{r~_08%ab#R2b6%5CQN00OHrx z%Bz-CLs6Hk$lKxO;{fF1&C0YQQjB#yE zN=HR39Rd^$3IQPisGW^(Y)(uj9~J`#5e5hj0J5i^j&N&GNh=!<6$BCmBLKX!rkjCi zW@A?>83_{%AY1^&y|k%{cV%f}StuL}B3pj|)6dDad2@SbWMNoff}pj#0M^;szKDHv zcxrWnrNPY7)Bxq><-?GKc5-})leo>?-roS=<>lI>l81VQkD|iS+~(f^;N9KJu%nTN fl%cW5+veWb_lbSZdX`MR00000NkvXXu0mjfCg-|k literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/homedecor_curtain_black.png b/mods/poudlard/textures/homedecor_curtain_black.png new file mode 100644 index 0000000000000000000000000000000000000000..6d6bf93322a313cd84ef7d4512f17a3a472343f8 GIT binary patch literal 288 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP)w-C39*c$moKskoBo-U3d8s|#`1H}#-a5!y}Tl9T@ zn$qtDTW>~xRp*on>G*7;oODj}r3K$zK|#Td*QAme7!)`eYKw0Lr2TritIF$?kJKUA zb;hoZ?_TOKPFRyQ-OK33uD|N5-}}XgsANA_efV7ZiJe=o{kOT^Udxyt#=H09c@OIl z?ur>ZlJB?MsYJd%Ba=LVKQL{YF~g0QcYhxCdw)*8tZMtelB)858!qqu{QUCEzpu_; feG>Zq+{XE z)7O>#F1HY$l>WbK5AOhlUVFMYhG?8Go#>e7tjObXpXbk-MP7T|@@^`-$C`4^)ALxQ zmlej*Y`bUq>8GdHU4AKCv^!Q<{<3 zv`>0zt=zg{iHfJEL(VJ(zXpW8UAAJ=S1$9petZ W--5pPnD+p^&EVPFvK8Lj4b z>8nFz?9KPA@P7T(@Ku@7j@nA8)lc7D^gWUKMqE;8Q`QBC*mtQxyR5apcI@7)bx`;1 z9{;xgzwO=zFW=|?`^w7qm+eYl{odj~_ZPB|J;(NK@uymMqys(1;OXk;vd$@?2>`?l BfAIhS literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/homedecor_curtain_dark_grey.png b/mods/poudlard/textures/homedecor_curtain_dark_grey.png new file mode 100644 index 0000000000000000000000000000000000000000..6ba8dc54b525fdb03e6d056e0564f4d3ca94f879 GIT binary patch literal 360 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP)w-C1}*Fx6wvOuA)o-U3d8s|$VI<8|j!aeujzuq$N8Rdev*lk#KJ2 zOsTb64542uY`*=MPWIUOec7I^D#mAd8g^%&IHU3-)5A#V&fn)MXTSdrRX5%m=4N6% zm(QVYW@W56!_{3b-bzi`x{;^el+V-Xygldh_4Lq_o_DuitDJYduw&~2_m&9egyXwU vx68iQlP}w|yXMBncb^hZ?>-3^_{Z=sUf1MZSHezU05EvE`njxgN@xNAz>}GS literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/homedecor_curtain_green.png b/mods/poudlard/textures/homedecor_curtain_green.png new file mode 100644 index 0000000000000000000000000000000000000000..ead824563b9cae921b86bfa13b0aa40f3b39752b GIT binary patch literal 400 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP)w-C39L7kBLI|c?uSx*J;#=> znv#`mRl8O+++&th`TEeJ*uqYx3#(OKk0ex?X0Iyq?LTP8&MY-)*R3;b!J)CXrfSLz z{O3U20mCDq7y(i)xCoSsFe zpE4EvzjG}uEi^P#f?-0v8HWU$@~h8r*#`}b=khW$G^K^b*1S9Z^zvs(cEFgU$KRRr~+E{a$-nGi&|anbr9_4IZrgezJY}J$3ncRr6~q kUe$hjxbgczxIi7_Zb9Q8k8Wv60>h5M)78&qol`;+0EiNyG5`Po literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/homedecor_curtain_orange.png b/mods/poudlard/textures/homedecor_curtain_orange.png new file mode 100644 index 0000000000000000000000000000000000000000..23985ef2a4c9ed8badd9c988dd138bd65809ab46 GIT binary patch literal 355 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!Yk*IPYlE|DlZ$Gzt6Hm@TARCi zhr4>Gheo%jMz5DfpSR`&Z_SB5T9bXXrub=3^VgmppffW-XLg{@oFLtK!MY1W^cIEc zFA3AX_UiKopn;qP9+AZi4BWyX%*Zfnjs#GUy~NYkmHjTapty?GIcrOMpwLE77sn8Z z%e;NjeTNNrn5SOZ6gNdi`|iE}D_+|t87O#i%;rvx;yae6){uUsz(yw`sl|O~_t%5E zp^sW>8Cv!iz7BpjW&g>FBXz2GjxWoReO>DPVyeGI=&KiN7av$`HP=c#{Qlz4%J1!# zwhD^A+c;C~PR3LBYU^~1>tV|^HeOb~z#PxL%692F8H491pT87a`K@!uj<~>2A!l>< xxvT;U!c%u4%tL1f?(`}CNd7$leo#Azu-F2G$ zhOqB-o$Y_7=6s>scbe^cpxJGa>wTg5fvendmGytA+;Eihf2H4Zm-~yb+H#caa+=s~ zllq9Q*>RTTd7uA@v*>)F-folskGK7YvFd!I;B=V#gRAFvoZoeo|A(>LZ zbCvFXrQULw_=K(5ZN^@pqPg{brvHtz^?|41ahCasuJ?tjd#BxVmfU!m-FKMifS}xVnBjY!?tG#4fU4etpy7j}_=cvZ*lv;bfT!Vin%{Yv`Gu?bf2#O^s`Y=S+;o=ngQ)O&q5p@k@OGZ$beZ#g zq}_9v?R%r+b(!IFm)>@m*KLsWe5T)Zn(=p^|Btlte52rWm+g0<;C7k&g{mq z0C&X5Ei5S~BNq~{Ke=>}m;lGcy{xh(BpMY3!W^Yya*+UwdR{>;s~8gv2B#JqNpY0` zaBgc=Kra*r00PUZrAvmQ0Ig)IUAL_e3jqob2m?xoqX0&>%VktNA*K!q3=tnlh{^!7 zuv}wWQ#&5R#i<}iS(3^CGQ>ruuv<|*x&)}g$;q#O05~}@yS25yQaT;JSi^*VfB-Z# zFgLhqsjgPTsCI?7%fJA{HZ#V!ZD?l2w!(vfvx2nO&vy+Q{*Gn<00002mT#ipm8Fidk|B=|Djxl?(-?ECr=h zIk^l4g%TB&9A)KnIfV)}jRIxmJVnJq1*IYdr93620w7xns8TUsL7`Yhr9@S=LPMie zMWtLttwdS5LPf1uNvT*#rAQfQxI($AYBta=dHG^xCxkdw<%R4fBJ0O(T%g)$YjQf1{*Wz`ZTl}vg08@-W{z|eW;>Eak7 zaapuCbkZRQ5r+G_c57?za8^)J6u3UK=ltLGn{M7;w=QqS-PZ6+c9CC>Z#VaP$dk7B zHFxIw*{|YewJ0MeodHuqMmu( zrv(~)%z;*hO1t)*(8w~6Z1PeUXbCO7V)guO%woIKf-5CT z5wg$~w$c-}))%og6tS;qy5SF0$ywkLS{Fr zOjrjL>hN@N4B@ygditVZlYxNi#p_Ks8rE!VQ0ZY!S?j>Qgh5@0HDen?$3_PAw_Ww$ zAIJ14UiR2|Fd<%Tl0}Bbai2p0^Y2`D;r}>!eBv_app5{WHC9G#TtVq`mU!WF>vK=n&!c+?{_Jvy(JVJQQMR Q1GPp#m>&oxVX6B;NZ;6%*n~g!otG6y}j7j z*ucQR-{0T9zP`l7#KFPAySuy8)YQt#%E!mY$jHdU!^73p)z;S5+1c6A(b3Dx%f`mW zzrVkJ8j&#o007rXL_t&-(+$msVS_Lb0KiY&Z7{tH5UBUxf4bxrILQ2d6WM{OF)0G!=ScM=F{l+?X-;VCWpAoex@cHOHHSemj76`e pZe3h?BG7PQvrxt^$M0Zg`~$ZAAK><|BRl{A002ovPDHLkV1nji@gD#H literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/homedecor_curtain_yellow.png b/mods/poudlard/textures/homedecor_curtain_yellow.png new file mode 100644 index 0000000000000000000000000000000000000000..37565407774c3208ba5f52305337bf90d116f1e2 GIT binary patch literal 349 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!Q-Dv1YiF%WcfCqagKA%sYJaoZ z#1^$lZR%6n)u(l;Pw�*`qP5S94Ck=DZ1-^CxO8oUFBIiuRIe+DoVFtemB@YL4!j zxw_Xxtz?0waTa()7Bet#3xhBt!>l{|NpOw9Gq5c=r*dE_vB^5No}W@M$CIY37%c-_j88Gk$Ey) zFBa{o^_ZH^Q@ug_p}DI3SNV`tnNE`P%dIc5&C6gqR@yu9kVcM{k0Y;M&6mBqI8Qc4 zSg*Tq@@>h7jk}@+Y_E&4Ua@w+Jng|(g*z)>>^fsvoqu_C*Dd2@lZ9^FX*>4yt$H?p t`wh7}zoOR3sW$IBd25Q>x6_6{+0BzV4}~_~@dmn_!PC{xWt~$(695BihcN&E literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/homedecor_nightstand_mahogany_2_drawer_front.png b/mods/poudlard/textures/homedecor_nightstand_mahogany_2_drawer_front.png new file mode 100644 index 0000000000000000000000000000000000000000..c27b60e14f0f0210c8e8fc9ab7df4fb7c3e0c2c5 GIT binary patch literal 725 zcmV;`0xJE9P)GnP$(Q`KP+uXHB=`YWI!%` zP&a>5J$_R>SwSspM>SVEBV9!=S2`zRLoi%EELJ`!UOz5gMlw+}9b7#sRyQPEHzZLq zC0aZtVL~rnK`vQ4DQrqOTr?tLL@sqqH&-|(Ml2dxG9gqe9#bhDWJNGsH6&Ci9A!W+ zPbC{^K`&i6C1pc1EFc_PK{ro1F?LTvRz5UnOg?W;KZI67k7Gr3RzV>b6GAd7Q9Chr zS3z1tHeEtDbWAunCm>xzH;-jQEF>I;Q#yKDKx0TdXiq*=Kr&uPIDcC~W}FlI9*0JpJ+d9Q9gcLKy_C^V@5k>NjzjsJYq^Zj$%S?Qb2@YLU&q2Ye+X)F(GzM zIDb$%b4xc|G9qkGK6zO`V@o?;LpWwmJXkLtHm%=V0002cNklrIaoWH4;5PL1()cI)ZutE(5r~`ceFIMaPmv&Nz2OMV9?4Ba<{QIx3cw$ z>WWA%+JQWs)jW{YOf*HM+1k`R+oP%IV}U}fh-cLx_k3#vPq7>rTf z5x`)C>JC{315|ftGiai^qn{zVzrVG$v$M06fw8||rN0vZ)-hHii7JYU00000NkvXX Hu0mjf7Zdhw literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/homedecor_nightstand_mahogany_back.png b/mods/poudlard/textures/homedecor_nightstand_mahogany_back.png new file mode 100644 index 0000000000000000000000000000000000000000..d7a4017cfd34e563df3a718f7ef7944f47956bdf GIT binary patch literal 565 zcmV-50?Pe~P)%p79X}))KqDGd zLpD-8E<`IHMK2{pE+SDrGeIdGNHr=^IxR#nB26_bKqwkQEg(rVB{LZnGa3~^CL2X6 z8&p3sL@XjrH77$W9Y`=FOg1b(AQ?+Elf8mSwuHY zHYYkD7)?1VQ9Lm>92ZkPFH}M_R6sIOJTEvO7&jdkLn#|TB^p5~8$Tl%Q$904A{kRb zGlZP^wg3PC=Sf6CR2b70j^%p8AQ(oOySuhs-DOFmiw6P(^1=OI%;?|qoL7+Y`NOSe z9m!EklhMk5$YCK*;U9!ew{K^ql892HbA9#b$KS~DJ1JTGTVJ7h&RW=c3* zKQww(K3Fy)e^ozCBpY>3Iek|>Z%{pbRzGr1IA%yVTRSIOHza0AHe^ROS~et2CmT^Q z9auarR5~tZMlx$mH)29COClL&Nj6a}9bG*wbx=82I3`gm9Z@VDY)v?KR6S)!HA^KK zO(+{gAQ)6J9#bqGZcaFFPdQO08&ohJMj#kdE*)e8wtIvvMRU`G%H zqa?Lhx9Og^?ltU+v2-H)AR_H{Q$mgbMn`&&*rg(3j?z2e@|k?8{302;k4lWD) z<7=(P^H0S>u~K=4VXdn6_m?VrZ||P`37rpr;QN0+LkGW(ML;2>-`6y)U+od%5bYo5 WickJSm>U`Z0000~BMCmUKeBu_0JTs9&}9~ny}8BZ!3R4^VzA{k338D2UjUpga6AsJmcC1N@xhEqCv zQ95f#H-1qze^xzpP&a%~HdH4ZWJEAeBpYr>G)5p8gjG0MIxBQhJd<5LSu!D9H6m6k z9%DWyTr?tJIwod9EOSmbc1}2XP&ZjMA%9RgfmS(@TRU@0HNaF(F(sB6LkQR4E*WSUP=EH%}!SOC%dyI3$Z%J8?`kSS%h;C>&fhBwsfpST7!b zRXK)NI*C|29HPPd0002|NklpGIx<;i%JDgPXupUu(-C7VaS2zY+fuoBBT_0F zC&jxsTo*cDzm-a-bCfM)?;oE)RV__Ze_k}ndXTKw4@iAGJ;(X8`}UsG@1M{jq}vq) fp_^$Fk|S^b>c&#GJ2Ta!H*85bWI!%#O*mmdF;*%bU^*sbJSJE&AWI(`RxTb`F(92_ zKW<7ie^NP(Up-tfAYnQsSTG)eQ#W^1J$+C&hE+OTIV5*cH)cO9W8(TXkN+lRYAs0g)6;?AIf>=IwPB>mVCR{fpO(z>u zDIH257)l`+T{$IOH6UU-B!*Ese^5DZPdQ;hF?vxtTRksyOgMj5J#I)eRxKWNP&Za7 z9)3|aaY;32Lot$EJYzm5Rx2K3JSTHbH+N4rSTrD!TRVJEHkMsJP$wLAO*m919F18$ zeNi`rRXA8KAYnZzP$(Q&Fd$eg9*bE!bWJvfSUOE48&oMAOC%dyI3!#$AaP7JTr?nD zH6&g)B!5*oST7!jSUZMSI*(HFmjD0&{z*hZR2b6@##5WaP!IsnS=+X4d%Lb}TS=Ov z(Y-Uje*1F11LJOoz1QC5@E#P4?&9IMq$Aq(eNE(#te z5fb{?rljk^jahK@VRmvoMqBwZqDWpC92R&$*yXEAp`glg0mep!1);WGON2@*aw$}T z{-MPk)3lb_hPk|E7y%fVt5jH8$_4$p9`Q#`V1B=x&BqQ!q*jY6)pPJ%bc)y_5wS{i z1DAKNZ|T&P#F(TXr>>)L`%r)X$zEXnW>eF&W}?Qq!L@&t{Z$cll1R}20000i;9 literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/homedecor_nightstand_mahogany_top.png b/mods/poudlard/textures/homedecor_nightstand_mahogany_top.png new file mode 100644 index 0000000000000000000000000000000000000000..e09931c239bb29c7678d9029871b46fa3e991f42 GIT binary patch literal 678 zcmV;X0$KfuP)uH;Y+4WkN4?O*dLNBx64-eN;JTLostpH*HNfbWb)^E+lnLIbS;| zRxTo3G$d9tBvv#eRW&13G9z6%B~UCNi&Z^-R6ci3Id@MxgjharOgW5NJbP0)Tr?(h zOg3vsH()#{S}r78G$mRvBwRNpbxt>6I3{~iJ7-5RV?!@tJu7`vIb1v@OeG#nDjtJT zJB3+0dr&)oQ#hDkKzC0!k6k~8S2}}OJ6bX%Wk4%dHY89jAdFl*U^^&+RXR~AA7(=? zmR~-OUOrngC0aHlQ7s=*FCv3hJ5nqncThQ0EFe}bB8yx-ja@y3;amy;0090;L_t&- z(+$nVx`I#?K;eD6ySuyF?rsqg6={$>XTSgGGFjh0Tfl^w&{SxGiLSA1n4Ou02pW@| zj&#sJ;%Us82k2m8xlkSETO)#pwo4ZM>J>@$k5CW z&4c_tab4B-T{tn#f|=S%6>?;IljI1T!RnxRL z2-d3Vw^}N3{dbqVK=F1w8jpWJgO0v`zCNIBS)yp$w%Go&EZegG0eZ?#H@#y}ZU6uP M07*qoM6N<$f?_xPB>(^b literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/homedecor_nightstand_oak_2_drawer_front.png b/mods/poudlard/textures/homedecor_nightstand_oak_2_drawer_front.png new file mode 100644 index 0000000000000000000000000000000000000000..fa28b7389d2bd13fb82f28674be51cf4dbbe0ea6 GIT binary patch literal 747 zcmVy zQk#HJmw7^=aXy`aPLXRwvWr@{m}aAOK&*gKk8nhmV>^{$Ik}Etp>;y8hE|<$KCpsO zp?5`)T{n|pJF|{oyOCi|K{d0HZk2glxRZ3kp?jHuUbvfZyP|WOdtj=JXAfASGt~alYCmCi(y(&Jj}9!pnzYmlxm)RUu#!G!l!quk!Y8K zU3O=cHpN3zWXFIi%aJr#!vX5-E zl5Vz>ai@!5q>5p%mTJqXgsF~WsEA^`nRmjdcd(3V=gE|=i)gKhXR3x|qJm$zo^aQ? zhrXC;vx{55rFF5FZK{c6sE1<9uz$IbV7Z}n!m4_mZa%`8X}gnUp>RH(Y&&a0B~btX z0MtoDK~xyiW0=%FDMl(rVp6E&~^Xf`B!J6l?qS=+eyhGkc=GpK1O%Sj9I@$v}EC~#*m7c!`;X2^<)3-Aky zh$+c)vT!hHqq>8Mp##+&TnxIX?#N^?Ky`->gCVLrj2QG#-7%G+aO%{F6Q@j>GLeyC d>Qu$4QvjQ>S05sOg{A-i002ovPDHLkV1fujVMG7` literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/homedecor_nightstand_oak_back.png b/mods/poudlard/textures/homedecor_nightstand_oak_back.png new file mode 100644 index 0000000000000000000000000000000000000000..6fd4dedd5c67197a64ffb2ef6076bc01a905ec30 GIT binary patch literal 696 zcmV;p0!RIcP)a#1#qc2kysUwB+RbWu2xep{J@W0QPYd|*3!U_Nk9IFfu= zn}lYLby0m}L4##QmVaM(T{(npNP1sAXhk%RbW>a0Rc%wK~xyi70gwaf>0Dd;WORc-QAsbjva`IIEtc_H6q@k4v zbbI|b@vbgewswh2^;IA}vsA!m(Q4TDwB3vV`Ti`u;-TCcoj>&^%Rs)~i!y6)gN+1@ zKTzTS@hDLY>gnMT=S0dtT2~JogZjdLwLXUY2Q*rpn2aoAl`A#bx%vfHKUxSN8>m7B znc12LFUK*F4-HiZ`p9rJ3MAag7O3JQWzz^caj&q{>>lOEiQlBtoHGf;y**3rFV1P@ eN@gZGHSq`X^ibO|P~n^a0000LyOQwfgsfALl zkY=rpV31}wpLa>EkYb~FORI-nt%p>VWICUAK(>)zs*7B}pmDU5X1ADZn0r>3c~Pf{ zT(po~vy^JNoodCVdaH#~pm#^8fK#uJTak26sfSXjgIKGBT8~{fpm$4*T{oF~SiG2I zv6E(%Y(1TIKb3AkqI^)9b3CAWN5iIepnONPm1&rBK)ID@iCQ;{T{VSRGr*s5x|wE{ zaXglBKbv<)m2NtvgHU}-F_vmPeNHi;bv%z+HSe=Z#lxeR{#J30ZBwb zR2b6*!GnUsP!IsXJ=?Zz+pcXZP1}^Q-+uYcK-pS$E;^6PJ4-ZerF;9q5guDuJq^2; zXNQN}eFHr(Uctagg{;h=(p^$YJ_uF_L4xy27gs3Q21miMhKZZ?InoyLBC=!xcti6T z+K2~uiV{_of+I~k(5h2a!%}STELw`7$71KYUZ0jCdWXMOGvH7VgiMwz+3W?^qF0OO;@A-W0<1KZY zipS4DRU4wH{(g&mJKP{;)eMWQ>4AX2jWm#?-Rnx4Q@;^_@SX?gt RZbbk9002ovPDHLkV1g1bNumG% literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/homedecor_nightstand_oak_left.png b/mods/poudlard/textures/homedecor_nightstand_oak_left.png new file mode 100644 index 0000000000000000000000000000000000000000..1edc06e6ae678c23e4bc23097adbbf982a519755 GIT binary patch literal 758 zcmV_Hon_CgdaHj$%cgM1s&lM> zQI=ynxsG9)V>_#bQ>uMLnQ}&eE)O|XJd!kT5&vwygiV!4uI zp?grmoNm^#eaoe6!klcSdqt*uK*^?VqkdJ$p>WTudXH#3s)tgKV>qgRM~hoEmTWwo zc0!C{HG@_)zM5g9dPJ3DIjn|FkY6{UcRsR?R-<}AsDMj{R5gcDHKTJttbIU|UpbXu zIl`ZAyqICanqjw&Se$G;zL;s9cuTpMXq|9AsC`AVi(8>{KA~|wxsqC%Wjni;WyYau z$)j$$kYUK3aK4yfxs_q2eM+i;N1b&(yOUeHlV!`Ocb#fJ(X4xwVL6&-JISSP&#QN) zdO*aXX~Lgs!kB52VL6>{KBjj-p>RHk}wp0QF`IZznR7gaRx{SJeZrh;yUp=qUiMYED&!l7}zn`)|kMAWl?!kT5f zmSvM+JFJFH$f0nfdPK>lZqKWFm18-OUpKOjR-<}AsDMkMcRq(yHHT3(qjNy4eL$LF zJGYKloNPS2m|?b+VWogp$)j$*m}$bFZl8Nm$enPxl3K!;X|RS=nrAz?l4GiWN1<~* znq@n=m0_lRN~(ZIzL;U1bw0b3TasTnm0vl+nqkSMZp)~5#-VDET{pXvWznpAp>aOX zt9QbjWu0n1rg}h?VL6gvIl`Z6oo+s+cR-wHJjRIJooStH zJIJMQ$)<4tbK|N2009C?L_t&-(*?l;V#ELt0Klzn+qP}HJ=@ONjFa7GcLuu54%>?D z*x|lSr_JfjJur52%b6TuCApD6i?Ris1~Q$T;o%4=tuZC$1gim&kSt0QABpJ4R>9au zxtoJggiL~nLpSvIusRpptgA0EjF?I>FgV1HvxWA8PZOSrZ zvo7eJ%I7N~KBm`3>}}e$b(pwH9rm*9kMTf%B(uIPm!qdkevRw5QR5h#0|Hi&sxMhMm?f?J)07*qoM6N<$f}Uq#jQ{`u literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/homedecor_nightstand_oak_top.png b/mods/poudlard/textures/homedecor_nightstand_oak_top.png new file mode 100644 index 0000000000000000000000000000000000000000..019cf93beffed44c2fc25024af5ae31fbb52cab3 GIT binary patch literal 730 zcmV<00ww*4P)6oXSI-EwvuJhuYSg% zYrK?Ts(weBX+y1oOP*;%%B^{)eoL=~RLiP#*tUtpplP#*Sd(f%rFu!1W<#NJLz;3# znQ%h5kYL1~YngOHx{_s)Wk8u}LAsS+!JcQ7Wj~H#J=V5_(XM{jwSvT;bj_)9#GrD@ zrFO52RJD>_j9WdVdPJIVM5lg7tA$dGSUsV3MxJIvzno^el3%5FM!uSBp>RgFkYS*5 zM8uFDi*=#J#34+j!N_mSl?H#qQY{P_}tCb$# zbV7y+36(Q&8iYGU4C+J`#7pS2kJ+Q~52Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyf1 z6gv(yKu>1?00C!7L_t(2&plF0vg05O)E7vqvdAfN|Fb0v144R>p0O7$pd|H2&7aRF zBFxO)f4`r*R}~R4GZC$|L_}3p^|~$*5h5a@s``GvV+@osb3_o4nPsM`GBeIXM47qw zuBxhvh|F~Ndyu>Dy(26`;7GaF;5>fSpu z_5FU&IUyZ?Gm8jRKp3uOMnoneV~na|X5bJJUa*shcsw4N38Uqvo0(PBT5GMXwIC@X z#u)#|sH&=DriiSynE56EF>9@=T5F9lZey&f_TH!lF*tLl!`;z?esOm*Q`I?VRb}R! z6Pvz6rK&JDA`IIR5iFC_o~002ovPDHLkV1iPF!TbOK literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/poudlard_cactuschecker.png b/mods/poudlard/textures/poudlard_cactuschecker.png new file mode 100644 index 0000000000000000000000000000000000000000..0e55b0a6a834fbbaddf99c13ce017a73bb5c42bb GIT binary patch literal 826 zcmV-A1I7G_P)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RW3e+XWoP@mIgnHl^hY zQW!~D@j!%$WE;VYiP0F%jvi+8U*O`h+qUemEW7OFX{X&>ym<0xG?9xL5KPnrmXVB6 zx1>J?*jYxqmi61#!x!(L=lOi{Jnv89-o1N+y}dp8eBRjDm@Cm0hLJ#(Yp<^f!%#Ar z)NZ%k9>2{zHh`g>ogL@TpLck8CEz_Z$jFEx9ejizk>%j=fu~QO3d2ws zhP=WQ()gFDsVVh(-TwZ*R;wkD#`pLbbuL}HC69UFJw!*DLP-eP6HFbKpSmEO6`VTRg-J4hSYEC)H{- zgTcW1`Z|A{cKjHh)9?3%VJM0s*=&{{Fo7j}K`=c%Et}2S+uO6eyv(Oqz#$%zOeSq_ zZ;PTxp-|vCo{4!`V-@0*yIkjv%#2Tmvud#=5K5&!@I07*qoM6N<$ Eg2(5D&Hw-a literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/poudlard_cactuschecker_2.png b/mods/poudlard/textures/poudlard_cactuschecker_2.png new file mode 100644 index 0000000000000000000000000000000000000000..9f37170f8a1ae00c0609264709533b3ed753eea2 GIT binary patch literal 829 zcmV-D1H$}?P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00N~+L_t(I%PrGAZ(C&;hwy zCW_=1#ZE0Hu~g@UICkCSFdPrhbpLNX_jTRR6ZlD@gXj2yM}tSADAH=RwA*bD79P;Y zDE{MC>y~b}D-1&m3kyO|&_oW0BuQd#Z%?n+Ge1AiHm+lUK0y#D7K^T3yXMuaS3-*z zLj^N*yIsv@Q$C;9>-G2st9X;h-!zCgc44oOA5pSNy`}=B949Yj<~7Hk%b$!XNk+EqcA4AP8)4Z;PUcgH)DGigxAb zir24S8yOi9$Fb1%kg1N4YPD)KHO^unm$?<2A`;pf8tuAcqO(gy@m00000NkvXX Hu0mjfhi7<# literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/poudlard_circlestonebrick.png b/mods/poudlard/textures/poudlard_circlestonebrick.png new file mode 100644 index 0000000000000000000000000000000000000000..03bbcbbdeb28053c2f933504c676f6710e0f9a6b GIT binary patch literal 646 zcmV;10(t$3P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyf3 z4ly*d8<27U00IU{L_t(I%Wad*QX4T4gg=EX+bdbxQvh?q1qsLSLLrqrwjmUU#Owvb zYW1@wRh}GVFBK|toSJEMPq)){rhMbv9r*tnb066DxO;Z;4b4}BXAl1Xe0|38%uL}bNJ)IT?`z7lf3g|-sAmz-b zi%S415n)!>XkEW8iI8$00S-u|iWFi_RCE~qIZ2$vTZ=(@%^hxdM@eyH2KI{>uS zXsxM?(fdYWV6;X={?TfTVK$rb^z<|y)>(`9o=Pc2h;d{PQo__V0N#6IN&sw!p*XUa zv2I)D#uOKKaCP+=5h2FN_VpEjxiQ6suImsHWVa*cOo)-q zW&^2f9Zf|vZ#Qz#*m)09V(MH&-+SIyi1DApR-5N%QcTFZm%Z=C gFCJs!f0a_=FIr9=rkkkTGXMYp07*qoM6N<$g0~4nJa0`JjyPv#}l(B76cywvy7WEC;+@4v1FQO;!`BQVma66x)%fZZz?QN5K zqWUB6s-LI~|D0ueJS-tEZ1Z=~4yK@63uMHW%0#F=yY`odm0`xR4c8uUGhS@aP&l?s qNWgcAa@2}7n*R@4eA#p@J6=>OP%!7o%q>7iFnGH9xvXPx#32;bRa{vGf6951U69E94oEQKA00(qQO+^RW3@~8FWQhbVF}# zZDnqB07G(RVRU6=Aa`kWXdp*PO;A^X4i^9b0`o~kK~y-)J(Igi^jrW%SB@u{t082@ zh<8C49T7pM5o`oSA4Rb6O{{za8=t_^Qe`SZ3-K~3#JOLHnu*6u=J*#Mzt!$Gti|5O z+1c4|tyZH@DBw5_=jZ1LArL|kMG=RGhuF4_X_|b0e{*?xiEZ2TdOZN-@T5`rM$^74{Kqd`8O$8}xy_V#cbhkCt^ zVHgN0B~nV_I7VwtDwX=n@9%F+)5NkYwAMsX#BeyITCMW)^TXuiBvNaQ=Xt!ny&2PfGaL>PLI`}{$MZatQXCu{u(r0w;^HD7 zA0K2g8H&XsT5Iz8JgruX)zwu-qYU69fS~6t5rIk4q+H_cXx-Fnwp~7Z1Vg2%gxOVgTVkH1VIomGc$wM8r!x>l7w6? zhwuAXmWAuOEG#S_=H}+e<#N<&H7b<~)6>&9j)PK)ZnukRnmjx_kR%DSv$G6`L&7iw zpxtgGlO&-~D3HlyxWB*W>+1_CCCkgp3{p`uaMe*Xt2Q5pf*< zO?qo35-rO@DTS1hFbo-uMqFK85r!dQ7$T+Q^YatW^9X`~g@pyQ))b3H c^7%af0TZix2Sj_%X8-^I07*qoM6N<$f^1xs(*OVf literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/poudlard_coalchecker_2.png b/mods/poudlard/textures/poudlard_coalchecker_2.png new file mode 100644 index 0000000000000000000000000000000000000000..ab1522ee9e401ca9b020c9b7b497525048d1dd28 GIT binary patch literal 900 zcmV-~1AF|5P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00QhuL_t(I%T<#*Px@>a#(z9{ z+HfdP&_b;y8W9tf=-}XD!dG#1_A9vfMO<_@ad2@^6G#1Pf+lj7LyA@?rC|FGCM55E z-B+&D9VwT~q3`?Hw$0+=B1cC@NGWMHoAi1;?(gpjf&d`|v)PPtxs2<&2qD-AVzSU~u`Pdpyy>+1_CCAC_OgM$OA z)hd={VcRyErlG1TLI_OLBnSes*(|!Q6FEIS4HZQp3`4>&8WHL#o(;=J9a&mIQ z_4PHmT#m_P!p+UiT#XO{QLR>4U0r2uZEdb%I-Mefz_x9ko}O?V2g|Z36bkdhd_Mn2 zP%4!ejYiaJHAtHX{~`;W!QeLI~twFkm{J^7i&d5Cqt^ zO*9(CFbvx5Hq~mCbUMw)#|N=kjPZDkX_~a#?Y~y`_xHouY&P%u`1tsLHZCqM7>~y& zio$d{>pVU_QmIr(CX@XB{t|{E!{Ly2yG^Ur;`#X* z*LA7a>!eaCq^|39yIq!-ml=&lc%DZj65;jr6)7eCe*e#_l&Gr8#>NJXMgvt@2L;>ntrT zv9hwl`T037FE1n#3D(!w+1c5_G)+344v9p9tE;Q|tO3MiGQl)W04kLVuIrM?WXNW- zbh}*)!{Fb)e>55mbX^BP(=;-f45?HKp(qN2!GL11$lcu?p68)y8UVxLkcWo{Mxzmi zVbE+gaU6$6qd~9N`^zVtPLt2)xxKw*dwUxxCAMv&C2AQb+tZ%_0000`sfZ60P$34;^W({BQWBuiW)N}Tg^b5rw57@Uhz6H8K46v{J8 zG8EiBeFMT9`NV;Wl001;Lo7}w=VWF5I^V#0DIDQivKp;cnD+s>WyTNLBu`9qOuVopluAEu6{1-oD!MPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyl9 z4Gt5zD|Jf%00E&%L_t(I%XN}VuBt!~hQB6EMo$VmDQ zOn2~{+?w^H>VK80>)I)$h@uF9aU6NS-#F(O#}NQ)EsMp1Y5AU5L{LhhwMImEJRT%T z!ufm#Ktw3ZGBjzezs_p2**JhSO#_4Zd>+uFC}Oo*0nl|F0Da#F#_>3gq-jc?=Q!uW z5NmDtpi)9FOpw!s^% zHE|S0+-|o&3;?v&f%fb50$?_q0bq=wD2h)C%jFWSbzmSOfmKyiVYo3SfOK7lQi`~3 z+mN|227sn%02qdWBuV)B`60`)(Ch(3gxI5ctpG()gt(>){4ny>I)LYKosI00000NkvXXu0mjfNqqC< literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/poudlard_emptybookshelf.png b/mods/poudlard/textures/poudlard_emptybookshelf.png new file mode 100644 index 0000000000000000000000000000000000000000..56fc713431c0bfc10e50377d7e450b9eb8dc2daf GIT binary patch literal 675 zcmV;U0$lxxP)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RW3iZBcG-!rS+fycEy^ z5%{{q=ov}82N7h&id}4hg3D(uk@e}T)Q)NEfORo#TMET+*>ZSKR)Xv-4AAwffmN61zuoFzyC) zSM|{FH{{C{ze$mKqq`dcS+ydxkf$kml>%UgYKK@i8+={?P&NUXFP68|=SN5VSsT66 zGkS<|763(yIGYiS5NM;YvLW|@rh$=$wuXTKJLt$07g5xbSi#+i1-7Wm7Z?0@4&J=` z%HiRCvh3!*XZ#!2Igm2BhjU}HVu2mTou5(YM@1AUvJ7kDTQbx69JyJ1>CD*5Ow`+zSjQ4-n6fpYNQUoFeN6jIez~Z^9+rbA71rbr+s|l~VZjQGa4?%8QL70(Y)*K0-AbW|YuPgg)9%e3m_DAhHyMaQIC9V-A&iT2y zsd*&~&PAz-C8;S2<(VZJ3hti10pX2&;y^_yo-U3d7N?W{{9p0Ho>}aG#`WVJ-h8YA zOF8=E)Y!ZjH*x>7e}C-dtpEDI{tG{4t%*CdN^Ex9fB)={JC=O6H$B8J*fC|6Q=v}4 zb%vlMhVm;mdJCOQlw3tkC)?#Nnz%xzTR)qb;iZ1+Z0B1C-vRAo@O1TaS?83{1OVV( BR}cUI literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/poudlard_horizontaljungletree.png b/mods/poudlard/textures/poudlard_horizontaljungletree.png new file mode 100644 index 0000000000000000000000000000000000000000..75a21b87da5570b824ad25ffbd608760b724d5dd GIT binary patch literal 808 zcmV+@1K0eCP)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RX1sV)E9=hf>g8%>mx=BPqR4C5{ z!Oe1;MgRcdUD!neu?U1fHm)owvEq)LLo#WS*0*LRd4XR01bv7+RF0XR>+wuFlg_lx zk0V>ewrmN3kmP!~z8Rwbc(S245Ue|S2WTFxx17-*FqEaOV zwN1+)4O!&QZf}3`3|oU}75n}?Pvg}xG<0w<^8BlLEpGyUBXWk^o!;o-cszMZxm@NU zi)P~5?^_=0?zF9*+ckGwdwrkMG_%bnMmB1-&3``o%jJBv2rS1iy@#{g;QFtRQk6QM zTZV&l>sh@a-hfrHz(|2_UOfST-A4BVhY(kz5&d|!V0qOu$Avmb!cd>3GB%zj$qh%)l@WAvuA~(R6 zmh@hj2L9z>tlQeIO^Pk8AeS%%6%;}wF>4zd@*GFQ`prdn{QM_uir{WB%{eWAH*}vo zA1_036GjcaJpJ=~jSEmiq!E#%VU`zI;b))zYi^}edSZ1f6amiO0B$sFNBn>Jc zWEmj;sXAsAfC6-nNMCc4MJ5D99k&@=Q^!#|x{66% zQt<3xSC$l_qmql9u4!Jca(;Zm19)4F>PNd^kConHKr|&CA`<-a27whxF}UePx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyf3 z3@i}@_xwiy00MMLL_t(I%Qccsa@;l;1slKz5Fj}tDV9?edzH#M7s&lDl7%a=D~e_~ zBtd}q$wHM~FW#zOtKWWk?yWVHQYaKgD;l8abQBusNq2zZ192(`Dv5d&1L1 zE`{DZ>wZvcqu0)54yZqV|Fxf`68DJKnh*v)y;EuU}rN zbQB8Ev|6CSkx$N25v?)C;GIQMDJ+l3Su?$LoLH9Iiil;L9A~Yp>qc#jF^r7C;haV^ zlva`X;<=20|F0A)bk!-j@b9vcb0!P}^BfqwL)?H>pp_<-hP?f=km*dp5zj(gBm27Z z^fGh3TzGwbM%BiCoZN0Z_uJp(a-x;u`8p$E^1N8b{jp)YVoL>Y9go{iUQZtWfl`Xv zKLYys^9y6}gfI|uLY7D5y)4w$34Y+q*UwDB(@+4UlrT!MADPiRN^2OSd3#^Tr6AYK zgoq#tVoL1sVBZg>X(Xq_eT$?cAxg6b$2fSp2Ok1b3PNj?oLS<5v%+zlD5coq4L1l+ z*AcEG#uy%ZB=<@=5|>f1S|RHm$+b{&!?;55LKsJCIa$_&KfnFJXhRr2BFpsz;D`w) zg7n_7T4TJ%D1{T@_I@YjN=gTV7K}EOe6rS#9}LE5tToiyk^8zs?X=zjXnPx#32;bRa{vGf6951U69E94oEQKA00(qQO+^RW30qPbDbP< zdwaX-_xltI1suoW{QMj#B>-U<(r7fu<#K46#%i_V^74{wHp_fI2SB#lZECgJkNDqc z+cvgslS-w~G>vYzORv|X-EIRQgdmkl5yvrGNs=%gkI{7<*L8{G7|-)qE|=uh(IcT8)E)1LpHNnx-8GX^UySn*Vk8+Qk2VOf*@eES^?mB9#Sbqp-`Y&t@85nLJ$Nf zr6`q3Xqtvn3fFZR4u^ERT`H9dnM{T#iZD$R@%;R}iJ}O@FpyGme}9kXd7PY_FdB`x zxVXSHO@bgm2tlXQq1WrtY&JPQK1P0heG!Hs>-CzCj}L?poSvRCnM@cA1|&(s=jSJe zVUQ#V!{LxjCd2jh_0Rv9ril;&r4+VpBZL5;P$+P8bcB==(=>5i7sD|AfVWyLDwPWI zcTXwh-)SBm9#}4yESF29lze}Gv$M0qVzHo7sgNWIySuwsmc@Tyr+mtXn(>_g0000< KMNUMnLSTXn|AjCB literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/poudlard_ironchecker_2.png b/mods/poudlard/textures/poudlard_ironchecker_2.png new file mode 100644 index 0000000000000000000000000000000000000000..417badfc4cb8ba3afefdf778677baa7089d42cb9 GIT binary patch literal 889 zcmV-<1BU#GP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00QAjL_t(I%RSQHO8RgZ$MN^R z+jLHyYoaX)49uXAI_RM8pwmt|=#sjMF2FnJCck?jAg4kpIdlHmT-$yJ@$)%; zKJeo6JksOiV-kiTv)K&8FnD@;LQxd@{XWCtkn{6%k|aS0K^(_4n@#5PIYJ0_cXtu4 z>*D)9LI}bzBuNrJKR@w(pPii@7K;U@X%fdVaU3H_66JE4{r!F3-`^3suA?XlnM?*v z)0ofaIF5s9n)tqtWmyac1EMHG2!ZRmq*5t{!y(0D5fMcZ>2!L)aO&rHqmW64WDA(85sH#emBqT|~+1VMIrctd{$>;Mpj>FZ}73Ff7 zAP6`;Jtc}FWLXA4bUGcX)hb(CTa3qJBuOHQA|y$|^E_Iu7L&<@N~J=rR$EC5g#tnd zM5EDQHk;u%4vj{GTrS6CGC@(4Kcb>w7zV1U^85QsDwSe7o$`Ma*L4ZQkhixt;y7k| zdwUfcjYf1j9SVg4A0HoNG8uv(z_Kh{*Zq^;-rgqvPb7q()oP(A3Sk%`gy8u2m@o{H zWtk|7Xf~TvDisEU!QW001S?)Po8{r*fp)u1KA$IwB9bJ*_kCQ~<@@`a=jUhU^Eusa z7sD`648y>6U5dpbzVGAvK9VHy`ud8ZD62k%5M(kLwzs$G^?IaIDO6QOOs7*U%VM!u zAW0JSdYyxV1J>5o5JI5qI&mD6PN&J`asX(WhUa;InTv~yq}%PXv9ZDC<|c=ShjhDL zG)=>{Z7we_v2B~LuP?IMEGH)?tDgb>I`sfZ60P$Nj?F_-Nry6$r9Iy66gHf+|;}h2Ir#G#FEq$h4Rdj z3TaA0vwuM+ugfB8nlBd%RPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyl9 z4Gl0bVORP900FB>L_t(I%Vm>Gj;k;bMUO3yO!z2<6~GFz&}=Sam?erDgRn`WOoDsR zvPItW1YxPF&b_xR&gXLwLLj9CVB0o6pAR7fLI?nO?-OF!b5EyJN&{dVM^t=7aWUdPM6LT~ec!Vz tOS+R%qVD&5njBMzOB5f>zi(hq_X~K^71_R@tpET3002ovPDHLkV1oN&>YxAs literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/poudlard_ironstonebrick.png b/mods/poudlard/textures/poudlard_ironstonebrick.png new file mode 100644 index 0000000000000000000000000000000000000000..1b0ed5ce744d78fe6b364eeabd2fe3d7e4cfd9fb GIT binary patch literal 741 zcmVPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyf3 z3@s!}UkN1u00L!6L_t(I%T<$0Z_`i^g}-}i5@aWF^909b5hRu=RgqX!EKrg77r-Au z2=?6|fha5Bryx~TSrrP~Ql(YwJZvXvVz*7_UI!_W07ByV9xJX3 zz`N~_EJ?)c+qY^Aq9NUGkHKifpXmi?4ZtLhu?sd*2>fmbAp}RQWBR>-y}fT38bx8b z$c;<}rBcdDDf&^AqDsktz+0;sF#-q_(H}ZCVK{J=j&#tS8;}}$0G#*b70*ujc zh}NLcX#o&MsaThnQ?i*1*=!cmv|z^2&gW-9HpYwR&lYv zfWmd}@agjx=0>Yk%ZyJ?>GT6?Ge4V}$o0WeMT8qN8K$8mDy1N1`NB#HS4 X!sHfNhu^{p00000NkvXXu0mjf@Rd2@ literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/poudlard_junglestick.png b/mods/poudlard/textures/poudlard_junglestick.png new file mode 100644 index 0000000000000000000000000000000000000000..afe589227ce7277a7c8a133df4669fc714a20dc5 GIT binary patch literal 215 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=85sDEfH31!Z9ZwBAbW|YuPgfw}C?8o-U3d7N?UF zB#IQyyM3>p*ZZzsVt#AL+3)x2oCK3q+&@oy%`fR`#4tT=5zm3;GZ!$nm^?OZkT`3> zs}N=!#_VyiCy`<0tUw+GcVlKC5bkm8dv=hKp@`9^(s+U81fUfRp00i_>zopr01(_k Aa{vGU literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/poudlard_junglewood.png b/mods/poudlard/textures/poudlard_junglewood.png new file mode 100644 index 0000000000000000000000000000000000000000..ebc64858d592ef7a88f3a7725cdfd24ea590ee0e GIT binary patch literal 362 zcmV-w0hRuVP)Px#32;bRa{vGi!vFvd!vV){sAK>D00(qQO+^RX1sV?tDaJr5X8-^I{7FPXR4C7N zQo(8hK@5FcqX!Q~krm2<%R&V~aK(eaQ1I$^3jK~Ey$OX{=Cl;Lh_Z({%+Tr~n1&O;C}KB~Rm8OcDX;_quFEFN=xRR2x8Z2DHk?*7<&~D_wEx>}i5( zBvV#G&Em(v2NoKXt0BXsLvfOnEGr1%&_{6&ZnOQL70(Y)*K0-AbW|YuPgfBL)%k?u3{JlP3!pdyk!B++;r943JviO_frUNF11_lN-zrW6Q zjE<66o@-Dlq4(q4YxBczpUX>pdFm?pZvVd{0T1&($CAV&llmLP} z`~L?(py1=fY#!hG|B7dl(vpq{Bqst@1xytItGsPg_}g_&VnFA!O|jGE9Cx=H4${h`hG~~Y-G)Ow>G(@tQGgy`+Ha7b!Z_<{Ol$4OT^X19E#q1)63BOz0CzJ@} zENfEQ`0z|DTWw`v5>G?L!&jHLYn;1P_E7QhHg0}HlQT}Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyl9 z4G}cad(OT900GuXL_t(I%YBkRZ__{+ho6hj_SsGji79C$5J`tn6{HNnj8usM1~yg( zz6xK255Q+Yl~|CNKpiTPN|azDRFpdS;>1ag!HwIHHoxWWJ>C7@Klg}dPns4$2mye# zmZb%Nxs~kPZg5qubk<@SD#_i4FGRZ21EXrO#b97 zPfk!OAj=FEOQ=+J;qiXEdbrnVZyH!@@s%QqLaen_8<{aoXAAB%HJ|}FNzzRN-*pg( zDmy?J1njh0oSiyrk0xdeKoB;ny;NR}CVeCrufvT27V}F}DTE+11}xZ% z8loToz~lu7kGgD=^n8W+^%;{F)nTsOvXzUqoWl(UZ(j7bW_bJVBd$}!_neB4df;O6 zf>620qrs3MY-|i_rF!6Ur}wmqGh@o?5G3CYkzWQWklsidfYy3#KOT>{r8Vb29OQ$J z-T>tNhhzG^CIDySj5tXyD~cije#Qxt=>oYz^lBUZUb7mU$qTxz7HPT;Q51zJuT~md zhv1;t9mlf>pcEMV*EW-jz3v#d1z82Aye9x&si{qHTSw<9=aZP}D{e0hU`^MAX kBj&|y?M!*Kl9$<%f9LMP1+z^R@Bjb+07*qoM6N<$f`_pI?EnA( literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/poudlard_plankstone_2.png b/mods/poudlard/textures/poudlard_plankstone_2.png new file mode 100644 index 0000000000000000000000000000000000000000..52656b003f1cae7f91c8a581620f3564844f0f72 GIT binary patch literal 604 zcmV-i0;BzjP)q!6r0qIFZ zK~y-)b(1@96G0S(zwypKytZdM@RAV8R2GE7O{fti%738YcTrO!(IC-5Ljw|#zy*$_ zNGK~5BQmR1=dUfZXA5L*QUHcm8H0XzuL9q7VAX#s47YurgS@!Z^}xOj z6Lt}J4dOT^2m&UP3HtUH3q(rMZo0^`(<5?|(hNIWZTz_WUCm%J;n!%yv?u`Zd>??! z7)()CEo>5+VTW;|>x7;kkpKCLDayL4FmUTrJbQZIx=sV%bL#!Jn=Ym(2?Lkc=Yzer z){g1tICXFHl0?}4T37rcNkt}?BmWR!@wnq zBBCg&<*KzNj$=NLJ~8NbIfUG#NK=$(tr0??lmb90MV4g*UV~m&aTp3Yoh=YTkY$D} ztCZGiRf1XCJ8ADG8Yi0Eq%?fbK`BKXcL`e|VHjeqrPEO~L`Cd%72`zn_T$ez*^3uv q$97)M_S6SZ%$D>X+&lQy0saHDWX{5if~8jg0000PF2xsgH#pi^b>*BZ0EPM>K*r!PgKi$PV|5)(5yB%hl<7Qn*NthaBgQaj4`|! zy+c*;{Rq{M)V3z^U21!z%WTdUorIRabXD^8#Tm2NH4X}!B1f&@`T>dC;&ZK7z@n^* z&2g(SG(@m!D0UU|&5i-!_<>8W(%pTI3HZ#y!!4HQJk>OGgObW)@5;|ZMP3u;rTwU=Me+}sG@)X&hp<8DGCQb z!K!6ZR&@O~0KKbcy#D3DqVCpzQ{zDpA{Ik>$Mn=8`aq z8TLA0VUe#nOCr*;WLA_IV{o279$L4UJ{e$dlu`0Lv4Ba?G<$x(v1Ve3WCz{J*D`<8;cOAI98fYwofF#35Z5^g1!lufM&<^P4M0h+uensgH_f8$l)yTh%9Dc;5!V$jK}j=qyPokOFVsD+3&LOa~MmgHSd=M z3MG2FIEHXsSM52-d)R=7Ia7f-;sx6#c8()@6Iy2lT~&O9 Z|KLhd<=_nhoj}VNJYD@<);T3K0RX`h7J literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/poudlard_redblock.png b/mods/poudlard/textures/poudlard_redblock.png new file mode 100644 index 0000000000000000000000000000000000000000..48031b8e79e551887e4b657698e1c6f35ce50ac4 GIT binary patch literal 433 zcmV;i0Z#sjP)8y*nGhnz!nUXro*5$5nHPF`!j^`XnVePJyps`VD7dm+PIr9c%FGji zo|cA&K*?9uT00000NkvXXu0mjfiaWCU literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/poudlard_rope.png b/mods/poudlard/textures/poudlard_rope.png new file mode 100644 index 0000000000000000000000000000000000000000..55967a6bcdb72c6a516c3a602d539698804c6c90 GIT binary patch literal 517 zcmV+g0{Z=lP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2ipt- z3n>{-5Zq}1000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0004CNklZfrW!0(Y_%dtq>~pM1SzH9;H2W>GdR2W0zN|@!UyQ!;^JOA zdFvn=sM?!J+FXu9K}7y3@f$x5zw>=?4#3gsfl7b9@^ONAvl7o-Uy&djsr2PI&=*A1 zs{y;uiii!kd+^a~J76+H|3$>snMmzNp9>IprUKyY224^2>Rf=&+bKkeo50gYTp>up zZ}}J)UAV7e`~+b;L~dWAX06BibwcS>gFep(FrK-2k|1~5LD*8!xUv}lWK5Z?hR0$h z=-7mMm6%qrv9_br;`St^3R3(E*~Dm3Xlv+N4tj9${^TRJio43s(d5k}0l=&&Q|tt; zE+AJ?sC*$&+Ry+1GZ7V}$QTMR^aM<#0xTbjgV3RcEbc0b)VeDvlumUO{MH~+Z9oDsi$N_$ zQ9?=2B5g>5xqMvyxpPPiDK3J)>3QLKKj3+}TXTL&D69Xfn3NF#uxfhQGED+Qq&8S| zpkEev3M$I7M0t_QgU*#i1sK2|E_reQ?tKej7bc)bCR$`|Efb5TV$l=;63CR4^Igle z!gg0Lsrr(tXVdSA=kWfj8n3GH%NM_2dFk#tP8{;5TnzwcT~h!Ojq;8o z9|Qml-9D!wha031z%&3L7EL{QJoRiot1asQ-V88OVSIb!BS*P+1Avo1#I{)d-0{?z zMJvTpySPvtY>S(w4&Y-?=NVs9dkX**EzYMv;5c5OB4HK7VhnveT1`kCLK6KJD%@uF@ z)xiY-lYy&WeuinSs680_3P4M$*NX)J?~V@nrSzTh!fAPPCb)=I+~1f7Fu50!^8krI zO@`J-LhB>$*?jLAid)5BymPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyn) z4iX9(QYIV#0013nR9JLFZ*6U5Zgc_CX>@2HM@dakWG-a~0006t zNklGq7TCc(!E?f6>tj{!Xe=q%teB z#Ov#8o~8+73{_Pjr9^AZvMhM-0ZKiDfcKslBQZwmx<(Jfz{|@E-g~O5V&8ZE0_L1q z*R=rL-QCf39oAYtK0c5sCAMt?DCl)vb3UH|Fvf6mbAyx;=NtgmT8`sDYmKg|iWno? zwqcAR##nx~*0L-M<2Z6Uoya*OgrI2}a?Xt7h*V0IB7oMKrfHB;avTRrDbD9JDJ6su zgb)xy;Jv@RODUnX##&pb=A4mI5@Y1rzkAH@T5>-{9o2Fr!CdP5Z7{mAXH!((( zQbkG#0b>k(-(#(1nkG_8%=3&6A@KS6N#FN4=Wx!kt}8+a_I>9#jxs#&{lz-1nWpJ- z-nI>`HK)^wx~|KVQ%YRtb7f(z#e0vGl9UoTXS6Yf=jUgts$yMNLI^0OP)cEpDZ!fO zxkyq;s49%BsCGy#xvE?NQFwq+d0;zr;1=#&z5U89s@7zQ36 zABizyjQP*9zmif)b7kx%fhy8IOp)*b9;MR_TuU3>5>g&OhL8Ql5+;2u4{x4NGbXG`N28I z@9!^lU1N-)>pGgIK`+a~+uIv$+w$=6K;QSw^Gw^e|E=@B@5SD$Q&m;*4}ltHLbT;y Q6951J07*qoM6N<$f?BOa00000 literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/poudlard_splitstonesquare_top.png b/mods/poudlard/textures/poudlard_splitstonesquare_top.png new file mode 100644 index 0000000000000000000000000000000000000000..76e39dfb7c1c0f1bff033677cb1de2eec6083582 GIT binary patch literal 752 zcmVPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyn) z5ECu4`z%ZV0013nR9JLFZ*6U5Zgc_CX>@2HM@dakWG-a~0006< zNklxq61DR4{Sr&jDy(~+brrEn+Utc4oq^c?athH?0hEfWt zwI;^MJkO+*h%utICg)69mU!bl-3ODSoZ zhLjRQ2to)5A@JT`{-u;qN@1feaz+vwd}S#V`y27-NVr z?zvlQS(b&mt`R~ojw3Nf;KF<91fh%XQY%oJUm=v8e^!c ziVyPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyf3 z4l@csOz&F&00Ih0L_t(I%T<%jPa825#D6BMP1fGpX>LK4N>$ECAle&;{{QE4EDU~g6t%7S ze))}?#R6+BUE5NQ$23n*09b25sZ^*G-g}&L0Q_1kC~j|mGy6EB>v}?n2!ftWIKXc< zIOkA#uasi7UZYU_UH_pF_DrgZ(P)%p10q6*abP`C3X~$m$bSgizNe_h6$&-51L&&a zcs|E_KRg0pvJVGLr&9`}D{7>{ z9vMt}$Rm7x*;1AzWm%#t4G4R{)``GaOY!;SWav8uMGa~Bd3}wkG#3}=JUl)E3?$mr zNx`8o#K^Yq-}Py#u;g)h@0ri%v|R_X=Wey)F)OG| z@?^PMCk3@JY2Heu*k+ax!eH#D%VS=)+jki-Mk68=&N;mIgb)cK4u=QCw&iZQB8154 z=~oaTgn$6PX()=(h%ed5r=}r=QE+a`;^u}!&}yUUyN*o=)H#u}*$j1lb|z(64iSEf k!w(O!ee(lkFgLc5fAzW#hp;TLg#Z8m07*qoM6N<$f(i5%y#N3J literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/poudlard_stonesquare.png b/mods/poudlard/textures/poudlard_stonesquare.png new file mode 100644 index 0000000000000000000000000000000000000000..20b070e6faea7c81d26ecdb092c9f25e82282521 GIT binary patch literal 700 zcmV;t0z>_YP)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RW3$(y`0I2mC zBOwG*N~Dx%ng%`3GoPQIgb*;sux%Uv0!u0U{{B|LG)-KuSDbVF{QMwu&Uo(uD!pkM zhG77}TFc>ZKuSs5wg5Qi*!LZ+HQE?MN(t{h)>=|Z^=9WB>$pJ#*=YGG_Gz~fDdhltfX&SWmo|F>PG~t{B;BYw9$DF2#QVQF)(f2*xdz4b7lqjX3 zt+j01hB1cA)vC`o2eN&GC5TbULBiwnZt$&pFq%j4={pB&9^(_w}|X zVBdFy5IE=X-qUp*LWrtFKH~@>a5|j;7{?LsJ?pySy|2-|yu8%8`1ttv`!}q$mFk?M zlv4c*A&^pXKA&mZmdoWr(==FXxn8eyU58%RmGAFw#&P8B?Ty>*#^do|9LN90dD}Le ibL5Px#24YJ`L;yknA^-`QWtw~d000SaNLh0L01m_e01m_fl`9S#00007bV*G`2ipt- z5Hu-<*33u%00CV|L_t(I%gvI{N&-<7hrfH(nHZfB6VV_H!c8qAXcgkJrwDt5h{9D5 zP!Mip!IxbQFQ=yX>BoLufJfWzY* z1yCqvRX&#?pUaGTgMNbTy#xTEkOUxXX#lKkm^|7~Q@vsqzPLS5njWBBs_|KAk11k-0xnL3;)*^6jh?8aMa;e}K=T&%M Til*yj00000NkvXXu0mjf=7PK< literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/poudlard_trapglass.png b/mods/poudlard/textures/poudlard_trapglass.png new file mode 100644 index 0000000000000000000000000000000000000000..e0d1c268328654606f9a5c1ac449a7d0379bc1fa GIT binary patch literal 261 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6T^O7g zlo&W?rp~GXif|TqL>4nJa0`Jjnu<@WmUOkqk9zq9i*-|}oZyFVSFd`DTew48d_`D~7@ z3W%F0@65MaTt+5E^8B32#;XGC?2*TQf4BdWzCdgS$TVTqjSYfq%=rxKBo3$_Z;?CY z-e+@6k~xC+pjgL`MO^c>+0~>vPi^|K$&6wD5x*x}vf5&R4r1_h^>bP0l+XkKnr2cC literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/poudlard_trapstone.png b/mods/poudlard/textures/poudlard_trapstone.png new file mode 100644 index 0000000000000000000000000000000000000000..05a253145800da25e85b4c0b78fee2e7a664d1e8 GIT binary patch literal 817 zcmV-11J3-3P)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RW39*0H1Gx%YbR^YtD2487%0s*N?qO#EPM1Azcx$p+XSe1iXf<|lvqb}^mi zy_pLs^#7G~I5ulv3AqWm%?_9v&WIjC;MFBuSQK zWm%@{2x^B0H7!e06>;yM@IydWuvNUx7&Ri5JF&#Ip>^nRaJ!$s;ZV{ zIhjm$yPaWRG#b6zY^+LNraQ>pD$S+qUyO@AZ0Vn#OTFo8=&mIRL=- z{kyxn^Ye4h^ZNb%X0v&EdNNIubDkv0YPE7*x2h`3QsC(+W$ZnrbTAk|2q~qCqL`-X zd7i4OyWP$-&GmYXF@Al0JsOtq>sR;wURM-lKA%sg(=ZJ4JXaJ2LP!Wnl0?%qUDpl6 za2)6SVuf5+^Zj-Z1Scma7~|*XXCZ`P7}0LSOu0L4}u`i^YM5r%kpS6ilQh8f+&h?+g`8N!{KnbTq=rkb#*0466*I` zZ_J%er><*Bk_^KD0AP%L-*+76=H|vQ49l`6lga1L1kLB0IR5_WQ|Iz>@7J$rHp@>> v>1xHBMtuB$mto{MZN^sH?L(^tOjG#}wcu^<`6p)U00000NkvXXu0mjfow;}E literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/poudlard_wood_tile.png b/mods/poudlard/textures/poudlard_wood_tile.png new file mode 100644 index 0000000000000000000000000000000000000000..c05a56f4d3be3359e3755013a0bfd9acd2dd8a64 GIT binary patch literal 598 zcmV-c0;&CpP)VGd000McNliru-2w^_It?&47vTT^0pm$T zK~y-)eUrOx6G0e-zwyp^_F|hViWNg)i^dTVija5!E)^vOqT`u(4|oJbhlE5GB?X0P zh{S^8L|%J#XFcAbSYP5e$*E?F|I9h(KO^40e(C`PHN5v!-U9-+sOabg*P&#vb(fKX zNBaqxakOKJod+n@U@|TF{VxOH-K!x0XQOj&LZ(-iih!^wG1lRQBhnHY0)*iCQExqX zIOy#X0B9|VLxo?IAQZmxn8IPLqrcw)Isp7iC%Xhq=@Hc&lY-1XQBxw%M(0FH zdnc$BlBmJMy<~kig@Zs5$B>Q<@?M9@OS4fFDiDG{;~BXv>LT5=aXjp`ay+R%idbd_|1uX+&EkOvVGd000McNliru-2xgBBmyN82nPTF0j^0z zK~y-)eUrV56Hye!e=qZ9=gXu}+zkW;Qzdb?NF#!+V6ojcTiE#j_*Ynotyqax7J{w1 zZlMV*8wdy@^W6E!Oy*f6FPk?RJEj^)XOkIqh}X|gECthfypxnBs*xN(ZWpA9YD|L8Kgp$GKfkzQJm~V` z?T?kTb%NHKN^3w+E-M}lBZ9EKQ6-)}8R~6gO6_pxAVMW2?NE{z4zAlG{yJk(EZN zjL4JJ^X2DB3|x;#2#+L9q2;0hy<8Cb0qBx6&p5v*fU9eQqkhMl{mb{?NpgoYS8GO> ztjGZf{DAS`rnNWH^kif`yuS~yV^%XdD}v_jvp26!IGx8U1*3kiaYgHe(|OFNFSE^I jnemJIIsXs!QwR79+~L4}>Aka000000NkvXXu0mjf(kSuw literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/poudlard_wood_tile_full.png b/mods/poudlard/textures/poudlard_wood_tile_full.png new file mode 100644 index 0000000000000000000000000000000000000000..0c28e92cd655363807df718c313fb59917be0763 GIT binary patch literal 594 zcmV-Y0pF2XskIMF-si8WAQDlbS1A0005;NklEe*ITKec;RQzx@gb0A{wEfwXN0 zwC}(=5fK3l0397af1KvEJw+|GcdmQCKfb=sz~wxBI1RP#-fai)$92)`TiNNuplfL+ zZS+bfhyZjlrGbcx(~0}~_%QkRd(l+#%Wa9l-BVq1J%}+l;QD<%#54uRRdGB69uvzT_5z!)n(%&85A32OhZ`0p!18^X1!* gqxC@W4#=hb1HN1wdnO6|`v3p{07*qoM6N<$f=KcbivR!s literal 0 HcmV?d00001 diff --git a/mods/poudlard/textures/texte déposé.txt b/mods/poudlard/textures/texte déposé.txt new file mode 100644 index 0000000..c9b84b4 --- /dev/null +++ b/mods/poudlard/textures/texte déposé.txt @@ -0,0 +1 @@ +moreblocks_plankstone \ No newline at end of file diff --git a/mods/protector/textures/default_chest_front.png b/mods/protector/textures/default_chest_front.png index f4132794d52be74ba00fc1a05fd403fac4ae7277..5fe430ad67f5f2e0ca4317289de4af238653d8c4 100644 GIT binary patch literal 146 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_`5A|IT2?*XJZ3p^r=85p>QL70(Y)*K0-AbW|Y zuPggqc1~s<5y?{F$3P)NPZ!4!j_b*1K3xBGzJYav0T8^<;#|lPx9>ZjQsK{g);zL4 lFRT)B#7Y=NtT#xqGVGbp9a?Vt;RaAMgQu&X%Q~loCIDXCCx`$5 literal 421 zcmV;W0b2fvP)i&K4LJ(h4fd|)}Lf=h&H zLXT)Oby_pmu656)Y`~XZu7*#Kb4!G4MT>1goOVBpWiV}2FKSRK-QC@|u%qC!dc~Y& zzLs61d_{+CM1p2Nz__cUqocE{p6j=Mc6N54fmoDxPm^{|mw8KwZcBJ!K5tn$lWaGU zYBh#mEPz=jWJ@J{RU=tkP^|y}0J2F$K~xwSZNWui!!Q5@z?Cd!Guz>$%=G_{wfA%e z*WN;vk})QQ^Dw*s2*+GX-?@VoV&4O(j+y0L)b(z6#|Hp~%T?|vrG%)s;vZGT7RJ8U z#VjTn08d=l*A4O8LORI+u!*?S_Wowm^QL|PkSL}3czbz1*uCfhoSi3%jH8!XCQkrD zoBe59D|pj90$3wagb+2UuA>0}i+V2Kwbn6Cv;e?#`SbNTmmlSx#8izWM; P00000NkvXXu0mjfwQRVu diff --git a/mods/protector/textures/default_chest_inside.png b/mods/protector/textures/default_chest_inside.png new file mode 100644 index 0000000000000000000000000000000000000000..5f7b6b13270890618c6a6332eee1c6c721b91f1b GIT binary patch literal 102 zcmeAS@N?(olHy`uVBq!ia0vp^0zj<5!2~3yyw0Buq;x%9978NlCvUkPo}j=vVadU` z_{Ppg7lT!aA;@D3{h6xK;WWK5B?*(dP@O1TaS?83{1OQEB B9=-qo literal 0 HcmV?d00001 diff --git a/mods/protector/textures/default_chest_lock.png b/mods/protector/textures/default_chest_lock.png new file mode 100644 index 0000000000000000000000000000000000000000..fe7ab587978ecd725dc9c973b6074695578f02b0 GIT binary patch literal 171 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_`5A|IT2?*ZZ@dAqwX{0G4WdzViJif|TqL>4nJ za0`PlBg3pY5H=O_Pgu?0%8ig=Spk@3R!r%IEHXsPd@YE`mgg1tQ!n~;Dr|F zLXNn7-}#gZf8MjcW7TrDSONs@&70G7fl>Itg~qcQ4Ejff>Jkpt^aIUc@O1TaS?83{ F1OV)cG;9C> literal 0 HcmV?d00001 diff --git a/mods/protector/textures/default_chest_side.png b/mods/protector/textures/default_chest_side.png index 44a65a43d3c3f2ba44bceb519a0696e1ba441800..c66fa7e0cd867e65d1c6d45221eb45daf2de1134 100644 GIT binary patch literal 140 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_`5A|IT2?*XJZ3p^r=85p>QL70(Y)*K0-AbW|Y zuPggqc1~tq4w3x2w?H9nPZ!4!j_b*1K3xBGzJYav0T8^<;#|lPx9>ZjQsK{g){jaJ f3?DF9^fECh?c_CD_M?CWsExtX)z4*}Q$iB}pdBVE literal 375 zcmV--0f_#IP)n`5knO{RcJoOVB!a5-&MFKSRK;In$zuXoa@aHD)h zf@VK%ST=rFCF{3-pn+J3ZcC(oM}}W4WJ@JsV)uan0065=L_t&-(`C+A5`!=dMbXH@ z-MB%3P}BSV*B6mr?&lfJ= zdsUum4#6X1C?EZJP^f8bSOa-|wF`=iC+qn|{rj V3gJ4$MZo|7002ovPDHLkV1iD9pBn%G diff --git a/mods/protector/textures/default_chest_top.png b/mods/protector/textures/default_chest_top.png index 1fbdbb94c966b39145bb0f06d30619afb5ba81f8..1a3c787661eeb1c73f0e7b2a5bb7713b42d207de 100644 GIT binary patch literal 138 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_`5A|IT2?*XJZ3p^r=85p>QL70(Y)*K0-AbW|Y zuPggqc1~s<^W8#86M;gSo-U3d9M_Z2e7OGWd;{wS10Z;z#kr6pZr}I5#!g0dh1e$6 dG&L&*hSq27{a5&}lmay|c)I$ztaD0e0st>|B!K_` literal 418 zcmV;T0bTxyP)nsh*fXFYILEX|{8#G7NJgI1=1NtAU-k#a-k;In$zuXoa@aJiCM zwU1VxfK#S~QIT*zdtp40Y&wEtIDB0)iDE8wS1oK%C}&9`>$iThkYbm5Q>TGSifA}x zPAvL-GKl~H0J}*T^13?f3z@BBeJ!TX$7^M7Dv;V5Xr&G90(|D|=Fb>@h zfFN=yBb)iwm}C#&LacSpY}TvQmm2^avRwQ|ob#T9z5_UlSeIf}MX9v90yq~+D|MT7 zPn1^xI%m?YrASJ-lNEqh*=LNUX_C0j`WryWInQk-nNJh52Qcm;62xsJ8QUHJ1ke6? z-W8!j^kMAf)4=R*X8+q)c0kn>r;gfe_Q+w!YS1S)Bpeg M07*qoM6N<$f@c=8ZU6uP diff --git a/mods/skins.tar.gz b/mods/skins.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..6506b15078a5162b1fcff59cba08275b3462f668 GIT binary patch literal 25137 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 literal 0 HcmV?d00001 diff --git a/mods/skinsdb/meta/character_17.txt b/mods/skinsdb/meta/character_17.txt new file mode 100644 index 0000000..ed04a21 --- /dev/null +++ b/mods/skinsdb/meta/character_17.txt @@ -0,0 +1,3 @@ +Hikari Kamijou +Tirifto +FAL 1.3 diff --git a/mods/skinsdb/meta/character_18.txt b/mods/skinsdb/meta/character_18.txt new file mode 100644 index 0000000..dbea15b --- /dev/null +++ b/mods/skinsdb/meta/character_18.txt @@ -0,0 +1,3 @@ +Kiki the Cyber Squirrel (Krita) +Tirifto +FAL 1.3 diff --git a/mods/skinsdb/meta/character_19.txt b/mods/skinsdb/meta/character_19.txt new file mode 100644 index 0000000..b28b04f --- /dev/null +++ b/mods/skinsdb/meta/character_19.txt @@ -0,0 +1,3 @@ + + + diff --git a/mods/skinsdb/meta/character_20.txt b/mods/skinsdb/meta/character_20.txt new file mode 100644 index 0000000..b28b04f --- /dev/null +++ b/mods/skinsdb/meta/character_20.txt @@ -0,0 +1,3 @@ + + + diff --git a/mods/skinsdb/meta/character_21.txt b/mods/skinsdb/meta/character_21.txt new file mode 100644 index 0000000..b28b04f --- /dev/null +++ b/mods/skinsdb/meta/character_21.txt @@ -0,0 +1,3 @@ + + + diff --git a/mods/skinsdb/meta/character_22.txt b/mods/skinsdb/meta/character_22.txt new file mode 100644 index 0000000..6b76454 --- /dev/null +++ b/mods/skinsdb/meta/character_22.txt @@ -0,0 +1,3 @@ +Diaspora Girl (diaspora*) +Tirifto +FAL 1.3 diff --git a/mods/skinsdb/meta/character_23.txt b/mods/skinsdb/meta/character_23.txt new file mode 100644 index 0000000..b28b04f --- /dev/null +++ b/mods/skinsdb/meta/character_23.txt @@ -0,0 +1,3 @@ + + + diff --git a/mods/skinsdb/textures/character_17.png b/mods/skinsdb/textures/character_17.png new file mode 100644 index 0000000000000000000000000000000000000000..41e565d5f9f7249887a91cdd13fdc66788048b5d GIT binary patch literal 417 zcmV;S0bc%zP)fFxS1k!Ea~c}=vFbniad~4XhsrM%FUVj zbUl-xLV$Lv`Y*QbK5TPBaF7#o#8Ltv&i?}U3&=755jX}3QM-6QYKMIunnL6q$TfzC zJb3jkl?gZ}Jc=Nfr#>p9{zy)yBFRvfh>@o!_#I?Yr2krEcIujxz z(tDzFSZ6`_{{X@|xni|m^J3vP!!6MXIAISknCqW|?Fl@9<;EQlL7xtA^$v!u5eVPe zXQQ}cjjC0*8v)MyQA)0ODeZTE2#BOqU{fiJH)$4tOt~qev{(X_w`o}xb=1s)vQ*&f zaDrMoK^?4NR#%HxfDez1Ow-p!plWzpUYQ8InFV1?x1oEuaC-0s8CBw*3IY7L00000 LNkvXXu0mjf4z#qY literal 0 HcmV?d00001 diff --git a/mods/skinsdb/textures/character_17_preview.png b/mods/skinsdb/textures/character_17_preview.png new file mode 100644 index 0000000000000000000000000000000000000000..b540effb56944ce63763b5918b195c2c55d08e5e GIT binary patch literal 514 zcmV+d0{#7oP)5lcZCxucn)>JtJV6R*5XmFK7>hg?Cp(PC&-{bQ`NQQQ zQ}Hnel|m5!aCUbO0O$@pv0k}_bwVo;E_@7YRgn*CRfG%we;knU{wY&8?XkY+N%?v; z2Rfi`PdHf85CD)ja*1|r*TJNI3mKo`2>{6JG&0A>TF{AbvT;+7)v~&;Eoq3nkrMVugQJol$_}hnGbWO?TFuDDtla~Z4wI8@*TKvA6;wQV+AYWCAaCSgyN+<7 zJHXTyRQtT9wm{yUN5*^peDgp%Zp^;=CuDqn0*yb)I0Ijsi72a^t{3IG5A07*qoM6N<$ Ef{GB*oB#j- literal 0 HcmV?d00001 diff --git a/mods/skinsdb/textures/character_18.png b/mods/skinsdb/textures/character_18.png new file mode 100644 index 0000000000000000000000000000000000000000..62b9954c61e93848a9d5e7f49d1a270c4337db17 GIT binary patch literal 473 zcmV;~0Ve*5P)|IO5-k^lez0d!JMQvg8b*k%9#0cJ@= zK~y-)wUfU~#4r@cbBp434>h4T7IZ&4h@+#U!hyFL2TPm`Lc{wnEZ64o+-?#4FHM?; zJK^q}?)#wM5uh$;Tv;UFNP;Q^>YgL5D)8c2%7E11ZOsF4F;Bqgf_2f%e!kXqD-&>jmw?d)Nv7GdUn6VW znZhf>Z_EChy)_XyVSbM5*@cf?boa3f1IB}>n^b*v()1d}7#`rKtqN;8R{ZUmfWqDnVLL?F(Q!uY& zd&?YwoOam3hP|wd<(and2_R0Pm~Fg|;ngZaZ@eLlzzS1Lkfvi7gw92G&XlE}S1E+D zn>ItyL-FSE%I9{)WV!=bEH=RQppYVfv=_*t{t5s5iZITZH@Ud)`Yr>%e5@2g8l8Ls P00000NkvXXu0mjfrdQt= literal 0 HcmV?d00001 diff --git a/mods/skinsdb/textures/character_18_preview.png b/mods/skinsdb/textures/character_18_preview.png new file mode 100644 index 0000000000000000000000000000000000000000..9181847e479e7d733f7b24fbf9a24a5fb423a205 GIT binary patch literal 536 zcmV+z0_XjSP)vQ>y^mg>-8iBAR_7Kx-Ny_oD=6fIK=tn_o^sQj!lj2!Y7p#6C0I(<)W4oXcJipDTkh6?xC({LXx3^>h z*L4Xgz@CD4ji6Dh8iSjiu1@fIbFUG+9v`4ltHSd<_`wqGdIil+7tUa)5m@ZxP`h;Q z9;2d#1$72Pm|_{{oWxldN4Q)r0{}eF(+IU1h?S4qh44I?E)eEOMT~2o+DZ`_)u{#~ zC2IuhAXCU$zmhIO%#pgVmV&f@!MIFG3EDEL1oQbkk-)a?Wa0000HYaZfQtAOdA+A6g2)MYoL_|c?)YKde z^(rbV4)5H2_tNS6SI$0t`t<$#_y7O@H@Eun2&j&+B*-tA!Qt7BG$7}cr;B5V#p&b( z2Bu_6ZYW-^TE}XpzIX0N z?T$N}XErpwN!i1tlYVZF&pswLHb(`9i<6Ag{aQ9!H#F37u`FD$*m=?7#e!~546~Yq zWo2z;Wt$ROTpL{$7gV=Sa#40M6k}~_a=SHKBym|{_=e|O6vSAK7diw4cveqV&~gY? zn4-}Z&uBD3ZArp;w>?}UqML;ua`mt-72{%BEE(CjaG`>Q!-YMa3@7ffFld`BPu}}9 R=N-^j44$rjF6*2UngBI3bgBRV literal 0 HcmV?d00001 diff --git a/mods/skinsdb/textures/character_22_preview.png b/mods/skinsdb/textures/character_22_preview.png new file mode 100644 index 0000000000000000000000000000000000000000..4e8c11ff9f4e3baca6b9d4dd476de4c7fc53b9d6 GIT binary patch literal 440 zcmV;p0Z0CcP)`9WGQ{4yn>&obSYg$yLHdzBw!P3%4l^- zj3e7gO5Gpm0U_P1%h9=4f5I3;9a`(k5k(O;vMdvId%zdbN}$sP0Ix4k2Ynlcwj+un zvMk#Xf#-R+;Rw(3*lafEDFB#VUI3t!!gXDgQs<{oN0KCHtx1xkbza!J5Cnng$~nHf z?|&DDi}$w!33;AVmSt;jp6A%{4Fz^er{)IZX)8VU%hj6YY7M~T<`&0s zXv6~tw7&1N-EIL$(-eR(3;`;CLs`A~zHg+IrYH)tM^O~Uj@!3}0x4xRt}EzToi+i0J48>7jU_`@|2Li}1bXc4gdhjj2JRdWL5b90000 (LGPL 2.1) and +celeron55, Perttu Ahola (LGPL 2.1) +Various Minetest developers and contributors (LGPL 2.1) + +Authors of media (models) +------------------------- +Jean-Patrick G. (kilbith) (CC BY-SA 3.0): + stairs_stair.obj +GreenXenith (CC BY-SA 3.0) + stairs_stair_inner.obj stairs_stair_outer.obj + + diff --git a/mods/stairs/README.txt.diff b/mods/stairs/README.txt.diff deleted file mode 100644 index 96fab35..0000000 --- a/mods/stairs/README.txt.diff +++ /dev/null @@ -1,29 +0,0 @@ -1,16c1,11 -< Minetest Game mod: stairs -< ========================= -< See license.txt for license information. -< -< Authors of source code -< ---------------------- -< Originally by Kahrl (LGPL 2.1) and -< celeron55, Perttu Ahola (LGPL 2.1) -< Various Minetest developers and contributors (LGPL 2.1) -< -< Authors of media (models) -< ------------------------- -< Jean-Patrick G. (kilbith) (CC BY-SA 3.0): -< stairs_stair.obj -< -< ---- -> Stairs -> ===================================================================== -> Main: Kahrl & celeron55, various -> Lisc: LGPL 2.1 -> 3Dmo: CC BY-SA 3.0 -> killbith -> stairs_stair.obj -> GreenXenith -> stairs_stair_inner.obj -> stairs_stair_outer.obj -> Link: https://github.com/minetest/minetest_game diff --git a/mods/stairs/depends.txt b/mods/stairs/depends.txt index d77ba25..4ad96d5 100644 --- a/mods/stairs/depends.txt +++ b/mods/stairs/depends.txt @@ -1,2 +1 @@ default -farming diff --git a/mods/stairs/init.lua b/mods/stairs/init.lua index 90172ef..74c9c9c 100644 --- a/mods/stairs/init.lua +++ b/mods/stairs/init.lua @@ -46,12 +46,24 @@ end -- Node will be called stairs:stair_ function stairs.register_stair(subname, recipeitem, groups, images, description, sounds) + local stair_images = {} + for i, image in ipairs(images) do + if type(image) == "string" then + stair_images[i] = { + name = image, + backface_culling = true, + } + elseif image.backface_culling == nil then -- override using any other value + stair_images[i] = table.copy(image) + stair_images[i].backface_culling = true + end + end groups.stair = 1 minetest.register_node(":stairs:stair_" .. subname, { description = description, drawtype = "mesh", mesh = "stairs_stair.obj", - tiles = images, + tiles = stair_images, paramtype = "light", paramtype2 = "facedir", is_ground_content = false, @@ -89,16 +101,7 @@ function stairs.register_stair(subname, recipeitem, groups, images, description, end if recipeitem then - minetest.register_craft({ - output = 'stairs:stair_' .. subname .. ' 8', - recipe = { - {recipeitem, "", ""}, - {recipeitem, recipeitem, ""}, - {recipeitem, recipeitem, recipeitem}, - }, - }) - - -- Flipped recipe for the silly minecrafters + -- Recipe matches appearence in inventory minetest.register_craft({ output = 'stairs:stair_' .. subname .. ' 8', recipe = { @@ -108,6 +111,15 @@ function stairs.register_stair(subname, recipeitem, groups, images, description, }, }) + -- Use stairs to craft full blocks again (1:1) + minetest.register_craft({ + output = recipeitem .. ' 3', + recipe = { + {'stairs:stair_' .. subname, 'stairs:stair_' .. subname}, + {'stairs:stair_' .. subname, 'stairs:stair_' .. subname}, + }, + }) + -- Fuel local baseburntime = minetest.get_craft_result({ method = "fuel", @@ -216,6 +228,15 @@ function stairs.register_slab(subname, recipeitem, groups, images, description, }, }) + -- Use 2 slabs to craft a full block again (1:1) + minetest.register_craft({ + output = recipeitem, + recipe = { + {'stairs:slab_' .. subname}, + {'stairs:slab_' .. subname}, + }, + }) + -- Fuel local baseburntime = minetest.get_craft_result({ method = "fuel", @@ -255,17 +276,170 @@ if replace then }) end +-- Register stairs. +-- Node will be called stairs:stair_inner_ + +function stairs.register_stair_inner(subname, recipeitem, groups, images, description, sounds) + local stair_images = {} + for i, image in ipairs(images) do + if type(image) == "string" then + stair_images[i] = { + name = image, + backface_culling = true, + } + elseif image.backface_culling == nil then -- override using any other value + stair_images[i] = table.copy(image) + stair_images[i].backface_culling = true + end + end + groups.stair = 1 + minetest.register_node(":stairs:stair_inner_" .. subname, { + description = description .. " Inner", + drawtype = "mesh", + mesh = "stairs_stair_inner.obj", + tiles = stair_images, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + groups = groups, + sounds = sounds, + selection_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + {-0.5, 0, 0, 0.5, 0.5, 0.5}, + {-0.5, 0, -0.5, 0, 0.5, 0}, + }, + }, + collision_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + {-0.5, 0, 0, 0.5, 0.5, 0.5}, + {-0.5, 0, -0.5, 0, 0.5, 0}, + }, + }, + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + + return rotate_and_place(itemstack, placer, pointed_thing) + end, + }) + + if recipeitem then + minetest.register_craft({ + output = 'stairs:stair_inner_' .. subname .. ' 7', + recipe = { + { "", recipeitem, ""}, + { recipeitem, "", recipeitem}, + {recipeitem, recipeitem, recipeitem}, + }, + }) + + -- Fuel + local baseburntime = minetest.get_craft_result({ + method = "fuel", + width = 1, + items = {recipeitem} + }).time + if baseburntime > 0 then + minetest.register_craft({ + type = "fuel", + recipe = 'stairs:stair_inner_' .. subname, + burntime = math.floor(baseburntime * 0.875), + }) + end + end +end + +-- Register stairs. +-- Node will be called stairs:stair_outer_ + +function stairs.register_stair_outer(subname, recipeitem, groups, images, description, sounds) + local stair_images = {} + for i, image in ipairs(images) do + if type(image) == "string" then + stair_images[i] = { + name = image, + backface_culling = true, + } + elseif image.backface_culling == nil then -- override using any other value + stair_images[i] = table.copy(image) + stair_images[i].backface_culling = true + end + end + groups.stair = 1 + minetest.register_node(":stairs:stair_outer_" .. subname, { + description = description .. " Outer", + drawtype = "mesh", + mesh = "stairs_stair_outer.obj", + tiles = stair_images, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + groups = groups, + sounds = sounds, + selection_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + {-0.5, 0, 0, 0, 0.5, 0.5}, + }, + }, + collision_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + {-0.5, 0, 0, 0, 0.5, 0.5}, + }, + }, + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + + return rotate_and_place(itemstack, placer, pointed_thing) + end, + }) + + if recipeitem then + minetest.register_craft({ + output = 'stairs:stair_outer_' .. subname .. ' 6', + recipe = { + { "", "", ""}, + { "", recipeitem, ""}, + {recipeitem, recipeitem, recipeitem}, + }, + }) + + -- Fuel + local baseburntime = minetest.get_craft_result({ + method = "fuel", + width = 1, + items = {recipeitem} + }).time + if baseburntime > 0 then + minetest.register_craft({ + type = "fuel", + recipe = 'stairs:stair_outer_' .. subname, + burntime = math.floor(baseburntime * 0.625), + }) + end + end +end -- Stair/slab registration function. -- Nodes will be called stairs:{stair,slab}_ -function stairs.register_stair_and_slab(subname, recipeitem, - groups, images, desc_stair, desc_slab, sounds) +function stairs.register_stair_and_slab(subname, recipeitem, groups, images, desc_stair, desc_slab, sounds) stairs.register_stair(subname, recipeitem, groups, images, desc_stair, sounds) + stairs.register_stair_inner(subname, recipeitem, groups, images, desc_stair, sounds) + stairs.register_stair_outer(subname, recipeitem, groups, images, desc_stair, sounds) stairs.register_slab(subname, recipeitem, groups, images, desc_slab, sounds) end - -- Register default stairs and slabs stairs.register_stair_and_slab( @@ -340,7 +514,7 @@ stairs.register_stair_and_slab( stairs.register_stair_and_slab( "mossycobble", - nil, + "default:mossycobble", {cracky = 3}, {"default_mossycobble.png"}, "Mossy Cobblestone Stair", @@ -538,16 +712,6 @@ stairs.register_stair_and_slab( default.node_sound_stone_defaults() ) -stairs.register_stair_and_slab( - "straw", - "farming:straw", - {snappy = 3, flammable = 4}, - {"farming_straw.png"}, - "Straw Stair", - "Straw Slab", - default.node_sound_leaves_defaults() -) - stairs.register_stair_and_slab( "steelblock", "default:steelblock", @@ -558,6 +722,16 @@ stairs.register_stair_and_slab( default.node_sound_metal_defaults() ) +stairs.register_stair_and_slab( + "tinblock", + "default:tinblock", + {cracky = 1, level = 2}, + {"default_tin_block.png"}, + "Tin Block Stair", + "Tin Block Slab", + default.node_sound_metal_defaults() +) + stairs.register_stair_and_slab( "copperblock", "default:copperblock", @@ -611,3 +785,25 @@ stairs.register_stair_and_slab( dig = {name = "default_snow_footstep", gain = 0.2} }) ) + + +-- Important aliases for bloody stairsplus + +function stairs.register_plus_alias(blk) + minetest.register_alias("stairsplus:stair_" .. blk, "stairs:stair_" .. blk) + minetest.register_alias("stairsplus:slab_" .. blk, "stairs:slab_" .. blk) + minetest.register_alias("stairsplus:wall_" .. blk, "stairs:wall_" .. blk) + minetest.register_alias("stairsplus:panel_" .. blk, "stairs:panel_" .. blk) + minetest.register_alias("stairsplus:micro_" .. blk, "default:" .. blk) + minetest.register_alias("stairsplus:corner_" .. blk, "stairs:corner_" .. blk) +end + +stairs.register_plus_alias("wood") +stairs.register_plus_alias("stone") +stairs.register_plus_alias("cobble") +stairs.register_plus_alias("mossycobble") +stairs.register_plus_alias("brick") +stairs.register_plus_alias("sandstone") +stairs.register_plus_alias("steelblock") +stairs.register_plus_alias("desert_stone") +stairs.register_plus_alias("copperblock") diff --git a/mods/stairs/license.txt b/mods/stairs/license.txt index 8f16bbd..411823a 100644 --- a/mods/stairs/license.txt +++ b/mods/stairs/license.txt @@ -21,6 +21,7 @@ Licenses of media (models) Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) Copyright (C) 2015-2016 Jean-Patrick G. (kilbith) +Copyright (C) 2017 GreenXenith You are free to: Share — copy and redistribute the material in any medium or format. diff --git a/mods/stairs/models/stairs_stair_inner.obj b/mods/stairs/models/stairs_stair_inner.obj new file mode 100644 index 0000000..5e4968e --- /dev/null +++ b/mods/stairs/models/stairs_stair_inner.obj @@ -0,0 +1,161 @@ +# Blender v2.78 (sub 0) OBJ File: '' +# www.blender.org +mtllib stairs_inner_stair.mtl +o stairs_back_right_stairs_back.001 +v 0.500000 -0.500000 0.500000 +v 0.500000 0.500000 0.500000 +v -0.500000 0.500000 0.500000 +v -0.500000 -0.500000 0.500000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vn 0.0000 -0.0000 1.0000 +usemtl None.001 +s 1 +f 1/1/1 2/2/1 3/3/1 4/4/1 +o stairs_front_right_stairs_back.003 +v 0.000000 0.000000 -0.500000 +v 0.000000 0.000000 0.000000 +v 0.000000 0.500000 0.000000 +v 0.000000 0.500000 -0.500000 +v -0.500000 0.000000 -0.500000 +v -0.500000 -0.500000 -0.500000 +v -0.500000 0.000000 0.000000 +v -0.500000 0.500000 0.500000 +v -0.500000 0.500000 0.000000 +v -0.500000 -0.500000 0.500000 +vt 0.0000 0.5000 +vt 0.5000 0.5000 +vt 0.5000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.5000 +vt 0.0000 0.0000 +vt 0.5000 0.5000 +vt 1.0000 1.0000 +vt 0.5000 1.0000 +vt 1.0000 0.0000 +vn -1.0000 0.0000 0.0000 +usemtl None +s 1 +f 5/5/2 6/6/2 7/7/2 8/8/2 +f 9/9/2 10/10/2 11/11/2 +f 11/11/2 12/12/2 13/13/2 +f 10/10/2 14/14/2 11/11/2 +f 14/14/2 12/12/2 11/11/2 +o stairs_bottom +v -0.500000 -0.500000 0.500000 +v -0.500000 -0.500000 -0.500000 +v 0.500000 -0.500000 -0.500000 +v 0.500000 -0.500000 0.500000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vn 0.0000 -1.0000 -0.0000 +usemtl None +s 1 +f 15/15/3 16/16/3 17/17/3 18/18/3 +o stairs_front_left_stairs_front.002 +v -0.500000 0.000000 0.000000 +v -0.500000 0.500000 0.000000 +v 0.000000 0.500000 0.000000 +v 0.000000 0.000000 0.000000 +v -0.500000 -0.500000 -0.500000 +v -0.500000 0.000000 -0.500000 +v 0.500000 0.000000 -0.500000 +v 0.500000 -0.500000 -0.500000 +v 0.000000 0.000000 -0.500000 +v 0.000000 0.500000 -0.500000 +v 0.500000 0.500000 -0.500000 +v 0.500000 0.000000 -0.500000 +vt 1.0000 0.5000 +vt 1.0000 1.0000 +vt 0.5000 1.0000 +vt 0.5000 0.5000 +vt 1.0000 0.0000 +vt 1.0000 0.5000 +vt 0.0000 0.5000 +vt 0.0000 0.0000 +vt 0.5000 0.5000 +vt 0.5000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.5000 +vn 0.0000 0.0000 -1.0000 +usemtl None +s 1 +f 19/19/4 20/20/4 21/21/4 22/22/4 +f 23/23/4 24/24/4 25/25/4 26/26/4 +f 27/27/4 28/28/4 29/29/4 30/30/4 +o stairs_top_stairs_top.001 +v 0.000000 0.000000 -0.500000 +v -0.500000 0.000000 -0.500000 +v -0.500000 0.000000 0.000000 +v 0.000000 0.000000 0.000000 +v 0.500000 0.500000 -0.500000 +v 0.000000 0.500000 -0.500000 +v 0.000000 0.500000 0.000000 +v 0.500000 0.500000 0.000000 +v -0.500000 0.500000 0.500000 +v 0.500000 0.500000 0.500000 +v 0.500000 0.500000 0.000000 +v -0.500000 0.500000 0.000000 +vt 0.5000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.5000 +vt 0.5000 0.5000 +vt 1.0000 1.0000 +vt 0.5000 1.0000 +vt 0.5000 0.5000 +vt 1.0000 0.5000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 0.5000 +vt 0.0000 0.5000 +vn 0.0000 1.0000 0.0000 +usemtl None +s 1 +f 31/31/5 32/32/5 33/33/5 34/34/5 +f 35/35/5 36/36/5 37/37/5 38/38/5 +f 39/39/5 40/40/5 41/41/5 42/42/5 +o stairs_back_left_stairs_back.005 +v 0.500000 0.000000 -0.500000 +v 0.500000 0.500000 -0.500000 +v 0.500000 0.500000 0.000000 +v 0.500000 0.000000 0.000000 +v 0.500000 0.000000 0.000000 +v 0.500000 0.500000 0.000000 +v 0.500000 0.500000 0.500000 +v 0.500000 -0.000000 0.500000 +v 0.500000 -0.500000 -0.500000 +v 0.500000 0.000000 -0.500000 +v 0.500000 0.000000 0.000000 +v 0.500000 -0.500000 -0.000000 +v 0.500000 -0.500000 -0.000000 +v 0.500000 0.000000 0.000000 +v 0.500000 -0.000000 0.500000 +v 0.500000 -0.500000 0.500000 +vt 0.5000 0.5000 +vt 0.5000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.5000 +vt 1.0000 0.0000 +vt 1.0000 0.5000 +vt 0.5000 0.5000 +vt 0.5000 0.0000 +vt 0.5000 0.0000 +vt 0.5000 0.5000 +vt 0.0000 0.5000 +vt 0.0000 0.0000 +vt 1.0000 0.5000 +vt 1.0000 1.0000 +vt 0.5000 1.0000 +vt 0.5000 0.5000 +vn 1.0000 0.0000 0.0000 +usemtl None +s 1 +f 47/43/6 48/44/6 49/45/6 50/46/6 +f 51/47/6 52/48/6 53/49/6 54/50/6 +f 55/51/6 56/52/6 57/53/6 58/54/6 +usemtl None.002 +f 43/55/6 44/56/6 45/57/6 46/58/6 diff --git a/mods/stairs/models/stairs_stair_outer.obj b/mods/stairs/models/stairs_stair_outer.obj new file mode 100644 index 0000000..cc1975b --- /dev/null +++ b/mods/stairs/models/stairs_stair_outer.obj @@ -0,0 +1,136 @@ +# Blender v2.78 (sub 0) OBJ File: '' +# www.blender.org +mtllib stairs_outer_stair.mtl +o stairs_bottom +v -0.500000 -0.500000 0.500000 +v -0.500000 -0.500000 -0.500000 +v 0.500000 -0.500000 -0.500000 +v 0.500000 -0.500000 0.500000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vn 0.0000 -1.0000 -0.0000 +usemtl None +s 1 +f 1/1/1 2/2/1 3/3/1 4/4/1 +o stairs_back_left_stairs_left +v 0.500000 0.000000 0.000000 +v 0.500000 -0.500000 -0.500000 +v 0.500000 0.000000 -0.500000 +v 0.500000 0.500000 0.000000 +v 0.500000 0.500000 0.500000 +v 0.500000 -0.500000 0.500000 +vt 0.5000 0.5000 +vt 1.0000 0.0000 +vt 1.0000 0.5000 +vt 0.5000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vn 1.0000 0.0000 0.0000 +usemtl None +s 1 +f 5/5/2 6/6/2 7/7/2 +f 5/5/2 8/8/2 9/9/2 +f 6/6/2 5/5/2 10/10/2 +f 5/5/2 9/9/2 10/10/2 +o stairs_back_right_stairs_back +v 0.000000 -0.500000 0.500000 +v 0.000000 -0.000000 0.500000 +v -0.500000 -0.000000 0.500000 +v -0.500000 -0.500000 0.500000 +v 0.500000 -0.500000 0.500000 +v 0.500000 -0.000000 0.500000 +v 0.500000 0.500000 0.500000 +v 0.000000 0.500000 0.500000 +vt 0.5000 0.0000 +vt 0.5000 0.5000 +vt 0.0000 0.5000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 0.5000 +vt 1.0000 1.0000 +vt 0.5000 1.0000 +vn 0.0000 -0.0000 1.0000 +usemtl None +s 1 +f 11/11/3 12/12/3 13/13/3 14/14/3 +f 15/15/3 16/16/3 12/12/3 11/11/3 +f 16/16/3 17/17/3 18/18/3 12/12/3 +o stairs_top_stairs_top.001 +v 0.000000 0.500000 0.500000 +v 0.501689 0.500000 0.500000 +v 0.501689 0.500000 0.000000 +v 0.000000 0.500000 0.000000 +v -0.500000 -0.000000 0.500000 +v 0.001689 -0.000000 0.500000 +v 0.001689 0.000000 0.000000 +v -0.500000 0.000000 0.000000 +v 0.500000 0.000000 -0.500000 +v -0.500000 0.000000 -0.500000 +v -0.500000 0.000000 0.000000 +v 0.500000 0.000000 0.000000 +vt 0.5000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 0.5000 +vt 0.5000 0.5000 +vt 0.0000 0.0000 +vt 0.5000 0.0000 +vt 0.5000 0.5000 +vt 0.0000 0.5000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.5000 +vt 1.0000 0.5000 +vn 0.0000 1.0000 0.0000 +usemtl None +s 1 +f 19/19/4 20/20/4 21/21/4 22/22/4 +usemtl None.004 +f 23/23/4 24/24/4 25/25/4 26/26/4 +f 27/27/4 28/28/4 29/29/4 30/30/4 +o stairs_front_left_stairs_front.000 +v -0.500000 -0.500000 -0.500000 +v -0.500000 0.000000 -0.500000 +v 0.500000 0.000000 -0.500000 +v 0.500000 -0.500000 -0.500000 +v 0.500000 0.500000 0.000000 +v 0.500000 0.000000 0.000000 +v 0.000000 0.000000 0.000000 +v 0.000000 0.500000 0.000000 +vt 1.0000 0.0000 +vt 1.0000 0.5000 +vt -0.0000 0.5000 +vt -0.0000 0.0000 +vt 0.5000 0.5000 +vt 0.5000 1.0000 +vt -0.0000 1.0000 +vt -0.0000 0.5000 +vn 0.0000 0.0000 -1.0000 +usemtl None.001 +s 1 +f 31/31/5 32/32/5 33/33/5 34/34/5 +usemtl None.003 +f 37/35/5 38/36/5 35/37/5 36/38/5 +o stairs_front_right_stairs_right.001_stairs_front_left_stairs_front.002 +v -0.500000 -0.500000 0.500000 +v -0.500000 0.000000 0.500000 +v -0.500000 0.000000 -0.500000 +v -0.500000 -0.500000 -0.500000 +v 0.000000 0.000000 0.500000 +v 0.000000 0.500000 0.500000 +v 0.000000 0.500000 -0.000000 +v -0.000000 0.000000 0.000000 +vt 1.0000 0.0000 +vt 1.0000 0.5021 +vt -0.0000 0.5021 +vt -0.0000 0.0000 +vt 1.0000 0.5021 +vt 1.0000 1.0000 +vt 0.5000 1.0000 +vt 0.5000 0.5021 +vn -1.0000 0.0000 0.0000 +usemtl None.002 +s 1 +f 39/39/6 40/40/6 41/41/6 42/42/6 +f 43/43/6 44/44/6 45/45/6 46/46/6 diff --git a/todo/TODO.md b/todo/TODO.md index 4796fb5..ad153ff 100644 --- a/todo/TODO.md +++ b/todo/TODO.md @@ -23,3 +23,6 @@ Textures: * "obsidian_brick_slab" * "obsidian_brick_slab" * "desert stone slab" + +UNKNOWNs + * sushi recipe