From 84668505d42c7a325743bf68cee1eeda05338015 Mon Sep 17 00:00:00 2001 From: Milan2018 Date: Sun, 16 May 2021 18:37:45 +0200 Subject: [PATCH] update --- blox/init.lua | 1351 ++++++++--------- crops/.gitignore | 3 + crops/pumpkin.lua | 5 +- protector/README.md | 20 + protector/admin.lua | 109 +- protector/depends.txt | 3 +- protector/doors_chest.lua | 180 ++- protector/hud.lua | 24 +- protector/init.lua | 201 ++- protector/locale/de.po | 16 +- protector/locale/es.po | 177 +++ protector/locale/fr.po | 17 +- protector/locale/it.po | 180 +++ protector/locale/protector.de.tr | 55 + protector/locale/protector.es.tr | 55 + protector/locale/protector.fr.tr | 55 + protector/locale/protector.it.tr | 55 + protector/locale/protector.ru.tr | 55 + protector/locale/protector.tr.tr | 55 + protector/locale/ru.po | 16 +- protector/locale/template.pot | 12 - protector/locale/tr.po | 17 +- protector/mod.conf | 4 +- protector/settingtypes.txt | 32 + protector/tool.lua | 299 ++-- teleport_potion/README.md | 3 +- teleport_potion/depends.txt | 5 +- teleport_potion/init.lua | 153 +- teleport_potion/intllib.lua | 46 +- .../locale/{template.pot => es.po} | 18 +- teleport_potion/locale/teleport_potion.de.tr | 11 + teleport_potion/locale/teleport_potion.es.tr | 11 + teleport_potion/locale/teleport_potion.fr.tr | 11 + teleport_potion/locale/template.txt | 9 + teleport_potion/mod.conf | 5 +- teleport_potion/textures/pad.png | Bin 334 -> 0 bytes teleport_potion/textures/padd.png | Bin 201 -> 0 bytes .../textures/teleport_potion_pad.png | Bin 0 -> 266 bytes ...ticle.png => teleport_potion_particle.png} | Bin ...{portal.png => teleport_potion_portal.png} | Bin ...{potion.png => teleport_potion_potion.png} | Bin throwing/.luacheckrc | 26 + throwing/README.md | 46 +- throwing/depends.txt | 3 - throwing/description.txt | 1 - throwing/init.lua | 224 ++- throwing/locale/template.txt | 7 + throwing/locale/throwing.fr.tr | 7 + throwing/mod.conf | 2 + throwing_arrows/README.md | 1 + throwing_arrows/depends.txt | 5 - throwing_arrows/init.lua | 185 ++- throwing_arrows/locale/template.txt | 25 + throwing_arrows/locale/throwing_arrows.fr.tr | 25 + throwing_arrows/mod.conf | 3 + .../textures/throwing_arrow_diamond.png | Bin 0 -> 3542 bytes .../textures/throwing_arrow_diamond_2.png | Bin 0 -> 3595 bytes .../textures/throwing_arrow_diamond_back.png | Bin 0 -> 3739 bytes .../textures/throwing_arrow_diamond_front.png | Bin 0 -> 2175 bytes .../textures/throwing_arrow_teleport.png | Bin 139 -> 3462 bytes .../textures/throwing_arrow_teleport_2.png | Bin 141 -> 3727 bytes .../textures/throwing_arrow_teleport_back.png | Bin 141 -> 3503 bytes .../throwing_arrow_teleport_front.png | Bin 119 -> 1774 bytes trash_can/README.txt | 5 +- trash_can/depends.txt | 1 - trash_can/description.txt | 1 - trash_can/init.lua | 135 +- trash_can/mod.conf | 2 + trash_can/settingtypes.txt | 2 + wine/README.md | 15 +- wine/depends.txt | 9 +- wine/init.lua | 557 ++++--- wine/license.txt | 25 + wine/locale/de.txt | 14 - wine/locale/template.txt | 41 +- wine/locale/wine.de.tr | 34 + wine/locale/wine.es.tr | 35 + wine/locale/wine.fr.tr | 33 + wine/mod.conf | 4 + wine/textures/wine_agave_syrup.png | Bin 0 -> 190 bytes wine/textures/wine_beer_bottle.png | Bin 0 -> 426 bytes wine/textures/wine_bourbon_bottle.png | Bin 0 -> 214 bytes wine/textures/wine_bourbon_glass.png | Bin 0 -> 197 bytes wine/textures/wine_brandy_bottle.png | Bin 0 -> 318 bytes wine/textures/wine_brandy_glass.png | Bin 0 -> 169 bytes wine/textures/wine_champagne_bottle.png | Bin 0 -> 330 bytes wine/textures/wine_champagne_glass.png | Bin 0 -> 199 bytes wine/textures/wine_champagne_raw_glass.png | Bin 0 -> 212 bytes wine/textures/wine_cider_bottle.png | Bin 0 -> 438 bytes wine/textures/wine_coffee_liquor_bottle.png | Bin 0 -> 2482 bytes wine/textures/wine_coffee_liquor_glass.png | Bin 0 -> 218 bytes wine/textures/wine_mead_bottle.png | Bin 0 -> 323 bytes wine/textures/wine_mint_bottle.png | Bin 0 -> 191 bytes wine/textures/wine_mint_glass.png | Bin 0 -> 198 bytes wine/textures/wine_rum_bottle.png | Bin 0 -> 379 bytes wine/textures/wine_rum_glass.png | Bin 0 -> 389 bytes wine/textures/wine_sake_bottle.png | Bin 0 -> 205 bytes .../{wine_sake.png => wine_sake_glass.png} | Bin ...ine_tequila.png => wine_tequila_glass.png} | Bin wine/textures/wine_vodka_bottle.png | Bin 0 -> 237 bytes wine/textures/wine_vodka_glass.png | Bin 0 -> 166 bytes wine/textures/wine_wheat_beer_bottle.png | Bin 0 -> 458 bytes .../{wine_bottle.png => wine_wine_bottle.png} | Bin .../{wine_glass.png => wine_wine_glass.png} | Bin 104 files changed, 3105 insertions(+), 1636 deletions(-) create mode 100644 crops/.gitignore create mode 100644 protector/locale/es.po create mode 100644 protector/locale/it.po create mode 100644 protector/locale/protector.de.tr create mode 100644 protector/locale/protector.es.tr create mode 100644 protector/locale/protector.fr.tr create mode 100644 protector/locale/protector.it.tr create mode 100644 protector/locale/protector.ru.tr create mode 100644 protector/locale/protector.tr.tr create mode 100644 protector/settingtypes.txt rename teleport_potion/locale/{template.pot => es.po} (66%) create mode 100644 teleport_potion/locale/teleport_potion.de.tr create mode 100644 teleport_potion/locale/teleport_potion.es.tr create mode 100644 teleport_potion/locale/teleport_potion.fr.tr create mode 100644 teleport_potion/locale/template.txt delete mode 100644 teleport_potion/textures/pad.png delete mode 100644 teleport_potion/textures/padd.png create mode 100644 teleport_potion/textures/teleport_potion_pad.png rename teleport_potion/textures/{particle.png => teleport_potion_particle.png} (100%) rename teleport_potion/textures/{portal.png => teleport_potion_portal.png} (100%) rename teleport_potion/textures/{potion.png => teleport_potion_potion.png} (100%) create mode 100644 throwing/.luacheckrc delete mode 100644 throwing/depends.txt delete mode 100644 throwing/description.txt create mode 100644 throwing/locale/template.txt create mode 100644 throwing/locale/throwing.fr.tr delete mode 100644 throwing_arrows/depends.txt create mode 100644 throwing_arrows/locale/template.txt create mode 100644 throwing_arrows/locale/throwing_arrows.fr.tr create mode 100644 throwing_arrows/textures/throwing_arrow_diamond.png create mode 100644 throwing_arrows/textures/throwing_arrow_diamond_2.png create mode 100644 throwing_arrows/textures/throwing_arrow_diamond_back.png create mode 100644 throwing_arrows/textures/throwing_arrow_diamond_front.png delete mode 100644 trash_can/depends.txt delete mode 100644 trash_can/description.txt create mode 100644 trash_can/settingtypes.txt delete mode 100644 wine/locale/de.txt create mode 100644 wine/locale/wine.de.tr create mode 100644 wine/locale/wine.es.tr create mode 100644 wine/locale/wine.fr.tr create mode 100644 wine/mod.conf create mode 100644 wine/textures/wine_agave_syrup.png create mode 100644 wine/textures/wine_beer_bottle.png create mode 100644 wine/textures/wine_bourbon_bottle.png create mode 100644 wine/textures/wine_bourbon_glass.png create mode 100644 wine/textures/wine_brandy_bottle.png create mode 100644 wine/textures/wine_brandy_glass.png create mode 100644 wine/textures/wine_champagne_bottle.png create mode 100644 wine/textures/wine_champagne_glass.png create mode 100644 wine/textures/wine_champagne_raw_glass.png create mode 100644 wine/textures/wine_cider_bottle.png create mode 100644 wine/textures/wine_coffee_liquor_bottle.png create mode 100644 wine/textures/wine_coffee_liquor_glass.png create mode 100644 wine/textures/wine_mead_bottle.png create mode 100644 wine/textures/wine_mint_bottle.png create mode 100644 wine/textures/wine_mint_glass.png create mode 100644 wine/textures/wine_rum_bottle.png create mode 100644 wine/textures/wine_rum_glass.png create mode 100644 wine/textures/wine_sake_bottle.png rename wine/textures/{wine_sake.png => wine_sake_glass.png} (100%) rename wine/textures/{wine_tequila.png => wine_tequila_glass.png} (100%) create mode 100644 wine/textures/wine_vodka_bottle.png create mode 100644 wine/textures/wine_vodka_glass.png create mode 100644 wine/textures/wine_wheat_beer_bottle.png rename wine/textures/{wine_bottle.png => wine_wine_bottle.png} (100%) rename wine/textures/{wine_glass.png => wine_wine_glass.png} (100%) diff --git a/blox/init.lua b/blox/init.lua index 95d087a..5b6b67a 100644 --- a/blox/init.lua +++ b/blox/init.lua @@ -1,727 +1,624 @@ ---[[ -*********** -Blox -by Sanchez - -modified mapgen -by blert2112 -*********** ---]] - -blox = {} - -local version = "0.8" - -local BloxColours = { - "pink", - "yellow", - "white", - "orange", - "purple", - "blue", - "cyan", - "red", - "green", - "black", -} - -local NodeClass = { - "diamond", - "quarter", - "cross", - "checker", - "corner", - "loop", -} - -local NodeMaterial = { - "stone", - "wood", - "cobble", -} - -local moreblocks = minetest.get_modpath("moreblocks") - --- Nodes - -minetest.register_node("blox:glowstone", { - description = "Glowstone", - tiles = {"blox_glowstone.png"}, - --inventory_image = "blox_glowstone.png", - light_propagates = true, - paramtype = "light", - sunlight_propagates = true, - light_source = 14, - is_ground_content = true, - groups = {cracky=2}, - sounds = default.node_sound_stone_defaults(), -}) - -minetest.register_node("blox:glowore", { - description = "Glow Ore", - tiles = {"default_stone.png^blox_glowore.png"}, - --inventory_image = {"default_stone.png^blox_glowore.png"}, - light_propagates = true, - paramtype = "light", - sunlight_propagates = false, - light_source = 8, - drop = { - max_items = 1, - items = { - { - items = {"blox:glowstone"}, - rarity = 15, - }, - { - items = {"blox:glowdust"}, - } - } - }, - is_ground_content = true, - groups = {cracky=2}, - sounds = default.node_sound_stone_defaults(), -}) - -minetest.register_node("blox:glowdust", { - description = "Glow Dust", - drawtype = "plantlike", - tiles = {"blox_glowdust.png"}, - inventory_image = "blox_glowdust.png", - light_propagates = true, - paramtype = "light", - sunlight_propagates = true, - light_source = 9, - walkable = false, - groups = {cracky=3, snappy=3}, - }) - --- param2-colored nodes: standard patterns - -blox.old_89_color_nodes = {} - -for _, nodeclass in ipairs(NodeClass) do - - minetest.register_node("blox:stone_"..nodeclass, { - description = "Blox stone "..nodeclass, - tiles = { - { name = "default_stone.png", color = 0xffffffff }, - }, - overlay_tiles = { - "blox_stone_"..nodeclass..".png" - }, - palette = "unifieddyes_palette_extended.png", - paramtype = "light", - paramtype2 = "color", - is_ground_content = true, - groups = {cracky=3, ud_param2_colorable = 1}, - sounds = default.node_sound_stone_defaults(), - on_construct = unifieddyes.on_construct, - }) - - minetest.register_node("blox:cobble_"..nodeclass, { - description = "Blox cobble "..nodeclass, - tiles = { - { name = "default_cobble.png", color = 0xffffffff }, - }, - overlay_tiles = { - "blox_cobble_"..nodeclass..".png" - }, - palette = "unifieddyes_palette_extended.png", - paramtype = "light", - paramtype2 = "color", - is_ground_content = true, - groups = {cracky=3, ud_param2_colorable = 1}, - sounds = default.node_sound_stone_defaults(), - on_construct = unifieddyes.on_construct, - }) - - minetest.register_node("blox:wood_"..nodeclass, { - description = "Blox wood "..nodeclass, - tiles = { - { name = "default_wood.png", color = 0xffffffff }, - }, - overlay_tiles = { - "blox_wood_"..nodeclass..".png" - }, - palette = "unifieddyes_palette_extended.png", - paramtype = "light", - paramtype2 = "color", - is_ground_content = true, - groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,flammable=3, ud_param2_colorable = 1}, - sounds = default.node_sound_wood_defaults(), - on_construct = unifieddyes.on_construct, - }) - - table.insert(blox.old_89_color_nodes, "blox:stone_"..nodeclass) - table.insert(blox.old_89_color_nodes, "blox:cobble_"..nodeclass) - table.insert(blox.old_89_color_nodes, "blox:wood_"..nodeclass) -end - --- param2-colored nodes: tinted wood, cobble, stone, stone square - -minetest.register_node("blox:wood_tinted", { - description = "Blox tinted wood", - tiles = { "blox_wood_tinted.png" }, - palette = "unifieddyes_palette_extended.png", - paramtype = "light", - paramtype2 = "color", - is_ground_content = true, - groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,flammable=3, ud_param2_colorable = 1}, - sounds = default.node_sound_wood_defaults(), - on_construct = unifieddyes.on_construct, -}) - -minetest.register_node("blox:stone_square", { - description = "Blox stone square", - tiles = { "blox_stone_square.png" }, - palette = "unifieddyes_palette_extended.png", - paramtype = "light", - paramtype2 = "color", - is_ground_content = true, - groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,flammable=3, ud_param2_colorable = 1}, - sounds = default.node_sound_wood_defaults(), - on_construct = unifieddyes.on_construct, -}) - -minetest.register_node("blox:cobble_tinted", { - description = "Blox tinted cobble", - tiles = { "blox_cobble_tinted.png" }, - palette = "unifieddyes_palette_extended.png", - paramtype = "light", - paramtype2 = "color", - is_ground_content = true, - groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,flammable=3, not_in_creative_inventory = 1, ud_param2_colorable = 1}, - sounds = default.node_sound_wood_defaults(), - on_construct = unifieddyes.on_construct, -}) - -minetest.register_node("blox:stone_tinted", { - description = "Blox tinted stone", - tiles = { "blox_stone_tinted.png" }, - palette = "unifieddyes_palette_extended.png", - paramtype = "light", - paramtype2 = "color", - is_ground_content = true, - groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,flammable=3, not_in_creative_inventory = 1, ud_param2_colorable = 1}, - sounds = default.node_sound_wood_defaults(), - on_construct = unifieddyes.on_construct, - drop = { - items = { - {items = {"blox:cobble_tinted"}, inherit_color = true }, - } - } -}) - -table.insert(blox.old_89_color_nodes, "blox:wood_tinted") -table.insert(blox.old_89_color_nodes, "blox:stone_square") -table.insert(blox.old_89_color_nodes, "blox:cobble_tinted") -table.insert(blox.old_89_color_nodes, "blox:stone_tinted") - --- Override default stone and default cobble - -minetest.override_item("default:stone_block", { - palette = "unifieddyes_palette_extended.png", - ud_replacement_node = "blox:stone_square", - groups = {cracky = 3, stone = 1, ud_param2_colorable = 1}, -}) - -minetest.override_item("default:stone", { - palette = "unifieddyes_palette_extended.png", - ud_replacement_node = "blox:stone_tinted", - groups = {cracky = 3, stone = 1, ud_param2_colorable = 1}, -}) - -minetest.override_item("default:cobble", { - palette = "unifieddyes_palette_extended.png", - ud_replacement_node = "blox:cobble_tinted", - groups = {cracky = 3, stone = 2, ud_param2_colorable = 1}, -}) - --- override the Moreblocks nodes we use - -if moreblocks then - minetest.override_item("moreblocks:circle_stone_bricks", { - palette = "unifieddyes_palette_extended.png", - ud_replacement_node = "blox:stone_loop", - groups = {cracky = 3, ud_param2_colorable = 1}, - }) - - unifieddyes.register_color_craft({ - output = "blox:stone_loop", - type = "shapeless", - palette = "extended", - neutral_node = "moreblocks:circle_stone_bricks", - recipe = { - "NEUTRAL_NODE", - "MAIN_DYE" - } - }) - - minetest.override_item("moreblocks:iron_checker", { - palette = "unifieddyes_palette_extended.png", - ud_replacement_node = "blox:stone_checker", - groups = {cracky = 3, ud_param2_colorable = 1}, - }) - - unifieddyes.register_color_craft({ - output = "blox:stone_checker", - type = "shapeless", - palette = "extended", - neutral_node = "moreblocks:iron_checker", - recipe = { - "NEUTRAL_NODE", - "MAIN_DYE" - } - }) - - minetest.override_item("moreblocks:wood_tile", { - palette = "unifieddyes_palette_extended.png", - ud_replacement_node = "blox:wood_quarter", - groups = {wood = 1, snappy = 1, choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, ud_param2_colorable = 1}, - }) - - unifieddyes.register_color_craft({ - output = "blox:wood_quarter", - type = "shapeless", - palette = "extended", - neutral_node = "moreblocks:wood_tile", - recipe = { - "NEUTRAL_NODE", - "MAIN_DYE" - } - }) - - minetest.override_item("moreblocks:wood_tile_flipped", { - palette = "unifieddyes_palette_extended.png", - ud_replacement_node = "blox:wood_quarter", - groups = {wood = 1, snappy = 1, choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, ud_param2_colorable = 1}, - }) - - unifieddyes.register_color_craft({ - output = "blox:wood_quarter", - type = "shapeless", - palette = "extended", - neutral_node = "moreblocks:wood_tile_flipped", - recipe = { - "NEUTRAL_NODE", - "MAIN_DYE" - } - }) -end - -local dye_color = "dye:white" - -if minetest.get_modpath("coloredwood") then - minetest.register_craft({ - output = unifieddyes.make_colored_itemstack("blox:wood_tinted 4", "extended", dye_color), - recipe = { - { dye_color, "default:wood", dye_color }, - { "default:wood", "", "default:wood" }, - { dye_color, "default:wood", dye_color }, - } - }) - - unifieddyes.register_color_craft({ - output = "blox:wood_tinted", - type = "shapeless", - palette = "extended", - neutral_node = "blox:wood_tinted", - recipe = { - "NEUTRAL_NODE", - "MAIN_DYE" - } - }) - -else - minetest.override_item("default:wood", { - ud_replacement_node = "blox:wood_tinted", - groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, wood = 1, ud_param2_colorable = 1}, - }) - - minetest.override_item("blox:wood_tinted", { - drop = "default:wood", - groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,flammable=3, not_in_creative_inventory = 1, ud_param2_colorable = 1}, - }) - - unifieddyes.register_color_craft({ - output = "blox:wood_tinted", - type = "shapeless", - palette = "extended", - neutral_node = "default:wood", - recipe = { - "NEUTRAL_NODE", - "MAIN_DYE" - } - }) - -end - --- Other crafts - -for _, nodeclass in ipairs(NodeClass) do - for _, material in ipairs(NodeMaterial) do - - local item = "blox:"..material.."_"..nodeclass - unifieddyes.register_color_craft({ - output = item, - type = "shapeless", - palette = "extended", - neutral_node = item, - recipe = { - "NEUTRAL_NODE", - "MAIN_DYE" - } - }) - end -end - -unifieddyes.register_color_craft({ - output = "blox:stone_square", - type = "shapeless", - palette = "extended", - neutral_node = "default:stone_block", - recipe = { - "NEUTRAL_NODE", - "MAIN_DYE" - } -}) - -unifieddyes.register_color_craft({ - output = "blox:stone_square", - type = "shapeless", - palette = "extended", - neutral_node = "blox:stone_square", - recipe = { - "NEUTRAL_NODE", - "MAIN_DYE" - } -}) - -unifieddyes.register_color_craft({ - output = "blox:cobble_tinted", - type = "shapeless", - palette = "extended", - neutral_node = "default:cobble", - recipe = { - "NEUTRAL_NODE", - "MAIN_DYE" - } -}) - -unifieddyes.register_color_craft({ - output = "blox:cobble_tinted", - type = "shapeless", - palette = "extended", - neutral_node = "blox:cobble_tinted", - recipe = { - "NEUTRAL_NODE", - "MAIN_DYE" - } -}) - -unifieddyes.register_color_craft({ - output = "blox:stone_tinted", - type = "shapeless", - palette = "extended", - neutral_node = "default:stone", - recipe = { - "NEUTRAL_NODE", - "MAIN_DYE" - } -}) - -unifieddyes.register_color_craft({ - output = "blox:stone_tinted", - type = "shapeless", - palette = "extended", - neutral_node = "blox:stone_tinted", - recipe = { - "NEUTRAL_NODE", - "MAIN_DYE" - } -}) - - -minetest.register_craft({ - output = 'blox:glowstone 2', - recipe = { - {"", 'blox:glowdust', ""}, - {'blox:glowdust', 'default:stone', 'blox:glowdust'}, - {"", 'blox:glowdust', ""}, - } -}) - -for _, material in ipairs(NodeMaterial) do - - local def_mat = "default:"..material - - unifieddyes.register_color_craft({ - output = "blox:"..material.."_diamond 4", - palette = "extended", - neutral_node = def_mat, - recipe = { - { "NEUTRAL_NODE", "MAIN_DYE", "NEUTRAL_NODE" }, - { "MAIN_DYE", "", "MAIN_DYE" }, - { "NEUTRAL_NODE", "MAIN_DYE", "NEUTRAL_NODE" } - } - }) - - if not (moreblocks and material == "wood") then - unifieddyes.register_color_craft({ - output = "blox:"..material.."_quarter 4", - palette = "extended", - neutral_node = def_mat, - recipe = { - { "MAIN_DYE", "NEUTRAL_NODE" }, - { "NEUTRAL_NODE", "MAIN_DYE" }, - } - }) - end - - unifieddyes.register_color_craft({ - output = "blox:"..material.."_cross 4", - palette = "extended", - neutral_node = def_mat, - recipe = { - { "NEUTRAL_NODE", "", "NEUTRAL_NODE" }, - { "", "MAIN_DYE", "" }, - { "NEUTRAL_NODE", "", "NEUTRAL_NODE" } - } - }) - - unifieddyes.register_color_craft({ - output = "blox:"..material.."_corner 4", - palette = "extended", - neutral_node = def_mat, - recipe = { - { "MAIN_DYE", "", "MAIN_DYE" }, - { "", "NEUTRAL_NODE", "" }, - { "MAIN_DYE", "", "MAIN_DYE" } - } - }) - - if not (moreblocks and material == "stone") then - - unifieddyes.register_color_craft({ - output = "blox:"..material.."_checker 6", - palette = "extended", - neutral_node = def_mat, - recipe = { - { "NEUTRAL_NODE", "MAIN_DYE", "NEUTRAL_NODE" }, - { "MAIN_DYE", "NEUTRAL_NODE", "MAIN_DYE" }, - { "NEUTRAL_NODE", "MAIN_DYE", "NEUTRAL_NODE" } - } - }) - - unifieddyes.register_color_craft({ - output = "blox:"..material.."_checker 8", - palette = "extended", - neutral_node = def_mat, - recipe = { - { "MAIN_DYE", "NEUTRAL_NODE", "MAIN_DYE" }, - { "NEUTRAL_NODE", "MAIN_DYE", "NEUTRAL_NODE" }, - { "MAIN_DYE", "NEUTRAL_NODE", "MAIN_DYE" } - } - }) - - unifieddyes.register_color_craft({ - output = "blox:"..material.."_loop 6", - palette = "extended", - neutral_node = def_mat, - recipe = { - { "NEUTRAL_NODE", "NEUTRAL_NODE", "NEUTRAL_NODE" }, - { "NEUTRAL_NODE", "MAIN_DYE", "NEUTRAL_NODE" }, - { "NEUTRAL_NODE", "NEUTRAL_NODE", "NEUTRAL_NODE" }, - } - }) - - end -end - ---Fuel - -for _, nodeclass in ipairs(NodeClass) do - minetest.register_craft({ - type = "fuel", - recipe = "blox:wood_"..nodeclass, - burntime = 7, - }) -end - -minetest.register_craft({ - type = "fuel", - recipe = "blox:wood_tinted", - burntime = 7, -}) - --- Tools - -minetest.register_tool("blox:bloodbane", { - description = "Blood Bane", - inventory_image = "blox_bloodbane.png", - tool_capabilities = { - full_punch_interval = 0.2, - max_drop_level=1, - groupcaps={ - fleshy={times={[1]=0.001, [2]=0.001, [3]=0.001}, uses=0, maxlevel=3}, - snappy={times={[1]=0.01, [2]=0.01, [3]=0.01}, uses=0, maxlevel=3}, - crumbly={times={[1]=0.01, [2]=0.01, [3]=0.01}, uses=0, maxlevel=3}, - cracky={times={[1]=0.01, [2]=0.01, [3]=0.01}, uses=0, maxlevel=3}, - choppy={times={[1]=0.01, [2]=0.01, [3]=0.01}, uses=0, maxlevel=3} - }, - damage_groups = {fleshy=200}, - } -}) - --- Ores - -local sea_level = 1 - -minetest.register_on_mapgen_init(function(mapgen_params) - sea_level = mapgen_params.water_level -end) - -minetest.register_ore({ - ore_type = "scatter", - ore = "blox:glowore", - wherein = "default:stone", - clust_scarcity = 36 * 36 * 36, - clust_num_ores = 3, - clust_size = 2, - y_min = sea_level, - y_max = 31000, -}) - -minetest.register_ore({ - ore_type = "scatter", - ore = "blox:glowore", - wherein = "default:stone", - clust_scarcity = 14 * 14 * 14, - clust_num_ores = 5, - clust_size = 3, - y_min = sea_level - 30, - y_max = sea_level + 20, -}) - -minetest.register_ore({ - ore_type = "scatter", - ore = "blox:glowore", - wherein = "default:stone", - clust_scarcity = 36 * 36 * 36, - clust_num_ores = 3, - clust_size = 2, - y_min = -31000, - y_max = sea_level - 1, -}) - --- Convert old static nodes to param2 color - -blox.old_static_list = {} - -for _, nodeclass in ipairs(NodeClass) do - if nodeclass ~= "colored" then - for _, color in ipairs(BloxColours) do - table.insert(blox.old_static_list, "blox:"..color..nodeclass) - table.insert(blox.old_static_list, "blox:"..color..nodeclass.."_cobble") - table.insert(blox.old_static_list, "blox:"..color..nodeclass.."_wood") - end - end -end - -for _, color in ipairs(BloxColours) do - table.insert(blox.old_static_list, "blox:"..color.."square") - table.insert(blox.old_static_list, "blox:"..color.."stone") - table.insert(blox.old_static_list, "blox:"..color.."wood") - table.insert(blox.old_static_list, "blox:"..color.."cobble") -end - -minetest.register_lbm({ - name = "blox:convert", - label = "Convert blox blocks to use param2 color", - run_at_every_load = false, - nodenames = blox.old_static_list, - action = function(pos, node) - local basename = string.sub(node.name, 6) - local color = basename - local material = "stone" - local pattern = "tinted" - - if string.find(basename, "_cobble") then - basename = string.sub(basename, 1, -8) - material = "cobble" - elseif string.find(basename, "cobble") then - basename = string.sub(basename, 1, -7) - material = "cobble" - elseif string.find(basename, "_wood") then - basename = string.sub(basename, 1, -6) - material = "wood" - elseif string.find(basename, "wood") then - basename = string.sub(basename, 1, -5) - material = "wood" - elseif string.find(basename, "square") then - basename = string.sub(basename, 1, -7) - pattern = "square" - elseif string.find(basename, "stone") then - basename = string.sub(basename, 1, -6) - end - - -- at this point, the material type has been deleted from `basename`. - - if string.find(basename, "quarter") then - basename = string.sub(basename, 1, -8) - pattern = "quarter" - elseif string.find(basename, "cross") then - basename = string.sub(basename, 1, -6) - pattern = "cross" - elseif string.find(basename, "corner") then - basename = string.sub(basename, 1, -7) - pattern = "corner" - elseif string.find(basename, "diamond") then - basename = string.sub(basename, 1, -8) - pattern = "diamond" - elseif string.find(basename, "loop") then - basename = string.sub(basename, 1, -5) - pattern = "loop" - elseif string.find(basename, "checker") then - basename = string.sub(basename, 1, -8) - pattern = "checker" - end - - -- all that's left in `basename` now is the color. - - color = basename - if color == "purple" then - color = "violet" - elseif color == "blue" then - color = "skyblue" - elseif color == "pink" then - color = "magenta" - elseif color == "black" and - ( pattern == "square" or - pattern == "tinted" ) then - color = "dark_grey" - end - - local paletteidx, _ = unifieddyes.getpaletteidx("unifieddyes:"..color, "extended") - minetest.set_node(pos, { name = "blox:"..material.."_"..pattern, param2 = paletteidx }) - local meta = minetest.get_meta(pos) - meta:set_string("dye", "unifieddyes:"..color) - meta:set_string("palette", "ext") - end -}) - -minetest.register_lbm({ - name = "blox:recolor_stuff", - label = "Convert 89-color blocks to use UD extended palette", - run_at_every_load = false, - nodenames = blox.old_89_color_nodes, - action = function(pos, node) - local meta = minetest.get_meta(pos) - if meta:get_string("palette") ~= "ext" then - minetest.swap_node(pos, { name = node.name, param2 = unifieddyes.convert_classic_palette[node.param2] }) - meta:set_string("palette", "ext") - end - end -}) - -print("Blox Mod [" ..version.. "] Loaded!") +--[[ +*********** +Blox +by Sanchez + +modified mapgen +by blert2112 +*********** +--]] + +blox = {} + +local version = "0.8" + +local BloxColours = { + "pink", + "yellow", + "white", + "orange", + "purple", + "blue", + "cyan", + "red", + "green", + "black", +} + +local NodeClass = { + "diamond", + "quarter", + "cross", + "checker", + "corner", + "loop", +} + +local NodeMaterial = { + "stone", + "wood", + "cobble", +} + +local moreblocks = minetest.get_modpath("moreblocks") + +-- Nodes + +minetest.register_node("blox:glowstone", { + description = "Glowstone", + tiles = {"blox_glowstone.png"}, + --inventory_image = "blox_glowstone.png", + light_propagates = true, + paramtype = "light", + sunlight_propagates = true, + light_source = 14, + is_ground_content = true, + groups = {cracky=2}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("blox:glowore", { + description = "Glow Ore", + tiles = {"default_stone.png^blox_glowore.png"}, + --inventory_image = {"default_stone.png^blox_glowore.png"}, + light_propagates = true, + paramtype = "light", + sunlight_propagates = false, + light_source = 8, + drop = { + max_items = 1, + items = { + { + items = {"blox:glowstone"}, + rarity = 15, + }, + { + items = {"blox:glowdust"}, + } + } + }, + is_ground_content = true, + groups = {cracky=2}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("blox:glowdust", { + description = "Glow Dust", + drawtype = "plantlike", + tiles = {"blox_glowdust.png"}, + inventory_image = "blox_glowdust.png", + light_propagates = true, + paramtype = "light", + sunlight_propagates = true, + light_source = 9, + walkable = false, + groups = {cracky=3, snappy=3}, + }) + +-- param2-colored nodes: standard patterns + +blox.old_89_color_nodes = {} + +for _, nodeclass in ipairs(NodeClass) do + + minetest.register_node("blox:stone_"..nodeclass, { + description = "Blox stone "..nodeclass, + tiles = { + { name = "default_stone.png", color = 0xffffffff }, + }, + overlay_tiles = { + "blox_stone_"..nodeclass..".png" + }, + palette = "unifieddyes_palette_extended.png", + paramtype = "light", + paramtype2 = "color", + is_ground_content = true, + groups = {cracky=3, stone=1, ud_param2_colorable = 1}, + sounds = default.node_sound_stone_defaults(), + on_construct = unifieddyes.on_construct, + on_dig = unifieddyes.on_dig + }) + + minetest.register_node("blox:cobble_"..nodeclass, { + description = "Blox cobble "..nodeclass, + tiles = { + { name = "default_cobble.png", color = 0xffffffff }, + }, + overlay_tiles = { + "blox_cobble_"..nodeclass..".png" + }, + palette = "unifieddyes_palette_extended.png", + paramtype = "light", + paramtype2 = "color", + is_ground_content = true, + groups = {cracky=3, stone=2, ud_param2_colorable = 1}, + sounds = default.node_sound_stone_defaults(), + on_construct = unifieddyes.on_construct, + on_dig = unifieddyes.on_dig + }) + + minetest.register_node("blox:wood_"..nodeclass, { + description = "Blox wood "..nodeclass, + tiles = { + { name = "default_wood.png", color = 0xffffffff }, + }, + overlay_tiles = { + "blox_wood_"..nodeclass..".png" + }, + palette = "unifieddyes_palette_extended.png", + paramtype = "light", + paramtype2 = "color", + is_ground_content = true, + groups = {snappy=2, choppy=2, wood=1, oddly_breakable_by_hand=2,flammable=3, ud_param2_colorable = 1}, + sounds = default.node_sound_wood_defaults(), + on_construct = unifieddyes.on_construct, + on_dig = unifieddyes.on_dig + }) + + table.insert(blox.old_89_color_nodes, "blox:stone_"..nodeclass) + table.insert(blox.old_89_color_nodes, "blox:cobble_"..nodeclass) + table.insert(blox.old_89_color_nodes, "blox:wood_"..nodeclass) +end + +-- param2-colored nodes: tinted wood, cobble, stone, stone square + +minetest.register_node("blox:wood_tinted", { + description = "Blox tinted wood", + tiles = { "blox_wood_tinted.png" }, + palette = "unifieddyes_palette_extended.png", + paramtype = "light", + paramtype2 = "color", + is_ground_content = true, + groups = {snappy=2, choppy=2, wood=1, oddly_breakable_by_hand=2,flammable=3, ud_param2_colorable = 1}, + sounds = default.node_sound_wood_defaults(), + on_construct = unifieddyes.on_construct, + on_dig = unifieddyes.on_dig +}) + +minetest.register_node("blox:stone_square", { + description = "Blox stone square", + tiles = { "blox_stone_square.png" }, + palette = "unifieddyes_palette_extended.png", + paramtype = "light", + paramtype2 = "color", + is_ground_content = true, + groups = {snappy=2, choppy=2, stone=1, oddly_breakable_by_hand=2,flammable=3, ud_param2_colorable = 1}, + sounds = default.node_sound_wood_defaults(), + on_construct = unifieddyes.on_construct, + on_dig = unifieddyes.on_dig +}) + +minetest.register_node("blox:cobble_tinted", { + description = "Blox tinted cobble", + tiles = { "blox_cobble_tinted.png" }, + palette = "unifieddyes_palette_extended.png", + paramtype = "light", + paramtype2 = "color", + is_ground_content = true, + groups = {snappy=2, choppy=2, stone=2, oddly_breakable_by_hand=2,flammable=3, not_in_creative_inventory = 1, ud_param2_colorable = 1}, + sounds = default.node_sound_wood_defaults(), + on_construct = unifieddyes.on_construct, + on_dig = unifieddyes.on_dig +}) + +minetest.register_node("blox:stone_tinted", { + description = "Blox tinted stone", + tiles = { "blox_stone_tinted.png" }, + palette = "unifieddyes_palette_extended.png", + paramtype = "light", + paramtype2 = "color", + is_ground_content = true, + groups = {snappy=2, choppy=2, stone=1, oddly_breakable_by_hand=2,flammable=3, not_in_creative_inventory = 1, ud_param2_colorable = 1}, + sounds = default.node_sound_wood_defaults(), + on_construct = unifieddyes.on_construct, + on_dig = unifieddyes.on_dig, + drop = { + items = { + {items = {"blox:cobble_tinted"}, inherit_color = true }, + } + } +}) + +table.insert(blox.old_89_color_nodes, "blox:wood_tinted") +table.insert(blox.old_89_color_nodes, "blox:stone_square") +table.insert(blox.old_89_color_nodes, "blox:cobble_tinted") +table.insert(blox.old_89_color_nodes, "blox:stone_tinted") + +-- Override default stone and default cobble + +minetest.override_item("default:stone_block", { + palette = "unifieddyes_palette_extended.png", + airbrush_replacement_node = "blox:stone_square", + groups = {cracky = 3, stone = 1, ud_param2_colorable = 1}, +}) + +minetest.override_item("default:stone", { + palette = "unifieddyes_palette_extended.png", + airbrush_replacement_node = "blox:stone_tinted", + groups = {cracky = 3, stone = 1, ud_param2_colorable = 1}, +}) + +minetest.override_item("default:cobble", { + palette = "unifieddyes_palette_extended.png", + airbrush_replacement_node = "blox:cobble_tinted", + groups = {cracky = 3, stone = 2, ud_param2_colorable = 1}, +}) + +-- override the Moreblocks nodes we use + +if moreblocks then + minetest.override_item("moreblocks:circle_stone_bricks", { + palette = "unifieddyes_palette_extended.png", + airbrush_replacement_node = "blox:stone_loop", + groups = {cracky = 3, ud_param2_colorable = 1}, + }) + + unifieddyes.register_color_craft({ + output = "blox:stone_loop", + type = "shapeless", + palette = "extended", + neutral_node = "moreblocks:circle_stone_bricks", + recipe = { + "NEUTRAL_NODE", + "MAIN_DYE" + } + }) + + minetest.override_item("moreblocks:iron_checker", { + palette = "unifieddyes_palette_extended.png", + airbrush_replacement_node = "blox:stone_checker", + groups = {cracky = 3, ud_param2_colorable = 1}, + }) + + unifieddyes.register_color_craft({ + output = "blox:stone_checker", + type = "shapeless", + palette = "extended", + neutral_node = "moreblocks:iron_checker", + recipe = { + "NEUTRAL_NODE", + "MAIN_DYE" + } + }) + + minetest.override_item("moreblocks:wood_tile", { + palette = "unifieddyes_palette_extended.png", + airbrush_replacement_node = "blox:wood_quarter", + groups = {wood = 1, snappy = 1, choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, ud_param2_colorable = 1}, + }) + + unifieddyes.register_color_craft({ + output = "blox:wood_quarter", + type = "shapeless", + palette = "extended", + neutral_node = "moreblocks:wood_tile", + recipe = { + "NEUTRAL_NODE", + "MAIN_DYE" + } + }) + + minetest.override_item("moreblocks:wood_tile_flipped", { + palette = "unifieddyes_palette_extended.png", + airbrush_replacement_node = "blox:wood_quarter", + groups = {wood = 1, snappy = 1, choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, ud_param2_colorable = 1}, + }) + + unifieddyes.register_color_craft({ + output = "blox:wood_quarter", + type = "shapeless", + palette = "extended", + neutral_node = "moreblocks:wood_tile_flipped", + recipe = { + "NEUTRAL_NODE", + "MAIN_DYE" + } + }) +end + +local dye_color = "dye:white" + +if minetest.get_modpath("coloredwood") then + minetest.register_craft({ + output = unifieddyes.make_colored_itemstack("blox:wood_tinted 4", "extended", dye_color), + recipe = { + { dye_color, "default:wood", dye_color }, + { "default:wood", "", "default:wood" }, + { dye_color, "default:wood", dye_color }, + } + }) + + unifieddyes.register_color_craft({ + output = "blox:wood_tinted", + type = "shapeless", + palette = "extended", + neutral_node = "blox:wood_tinted", + recipe = { + "NEUTRAL_NODE", + "MAIN_DYE" + } + }) + +else + minetest.override_item("default:wood", { + airbrush_replacement_node = "blox:wood_tinted", + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, wood = 1, ud_param2_colorable = 1}, + }) + + minetest.override_item("blox:wood_tinted", { + drop = "default:wood", + groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,flammable=3, not_in_creative_inventory = 1, ud_param2_colorable = 1}, + }) + + unifieddyes.register_color_craft({ + output = "blox:wood_tinted", + type = "shapeless", + palette = "extended", + neutral_node = "default:wood", + recipe = { + "NEUTRAL_NODE", + "MAIN_DYE" + } + }) + +end + +-- Other crafts + +for _, nodeclass in ipairs(NodeClass) do + for _, material in ipairs(NodeMaterial) do + + local item = "blox:"..material.."_"..nodeclass + unifieddyes.register_color_craft({ + output = item, + type = "shapeless", + palette = "extended", + neutral_node = item, + recipe = { + "NEUTRAL_NODE", + "MAIN_DYE" + } + }) + end +end + +unifieddyes.register_color_craft({ + output = "blox:stone_square", + type = "shapeless", + palette = "extended", + neutral_node = "default:stone_block", + recipe = { + "NEUTRAL_NODE", + "MAIN_DYE" + } +}) + +unifieddyes.register_color_craft({ + output = "blox:stone_square", + type = "shapeless", + palette = "extended", + neutral_node = "blox:stone_square", + recipe = { + "NEUTRAL_NODE", + "MAIN_DYE" + } +}) + +unifieddyes.register_color_craft({ + output = "blox:cobble_tinted", + type = "shapeless", + palette = "extended", + neutral_node = "default:cobble", + recipe = { + "NEUTRAL_NODE", + "MAIN_DYE" + } +}) + +unifieddyes.register_color_craft({ + output = "blox:cobble_tinted", + type = "shapeless", + palette = "extended", + neutral_node = "blox:cobble_tinted", + recipe = { + "NEUTRAL_NODE", + "MAIN_DYE" + } +}) + +unifieddyes.register_color_craft({ + output = "blox:stone_tinted", + type = "shapeless", + palette = "extended", + neutral_node = "default:stone", + recipe = { + "NEUTRAL_NODE", + "MAIN_DYE" + } +}) + +unifieddyes.register_color_craft({ + output = "blox:stone_tinted", + type = "shapeless", + palette = "extended", + neutral_node = "blox:stone_tinted", + recipe = { + "NEUTRAL_NODE", + "MAIN_DYE" + } +}) + + +minetest.register_craft({ + output = 'blox:glowstone 2', + recipe = { + {"", 'blox:glowdust', ""}, + {'blox:glowdust', 'default:stone', 'blox:glowdust'}, + {"", 'blox:glowdust', ""}, + } +}) + +for _, material in ipairs(NodeMaterial) do + + local def_mat = "default:"..material + + unifieddyes.register_color_craft({ + output = "blox:"..material.."_diamond 4", + palette = "extended", + neutral_node = def_mat, + recipe = { + { "NEUTRAL_NODE", "MAIN_DYE", "NEUTRAL_NODE" }, + { "MAIN_DYE", "", "MAIN_DYE" }, + { "NEUTRAL_NODE", "MAIN_DYE", "NEUTRAL_NODE" } + } + }) + + if not (moreblocks and material == "wood") then + unifieddyes.register_color_craft({ + output = "blox:"..material.."_quarter 4", + palette = "extended", + neutral_node = def_mat, + recipe = { + { "MAIN_DYE", "NEUTRAL_NODE" }, + { "NEUTRAL_NODE", "MAIN_DYE" }, + } + }) + end + + unifieddyes.register_color_craft({ + output = "blox:"..material.."_cross 4", + palette = "extended", + neutral_node = def_mat, + recipe = { + { "NEUTRAL_NODE", "", "NEUTRAL_NODE" }, + { "", "MAIN_DYE", "" }, + { "NEUTRAL_NODE", "", "NEUTRAL_NODE" } + } + }) + + unifieddyes.register_color_craft({ + output = "blox:"..material.."_corner 4", + palette = "extended", + neutral_node = def_mat, + recipe = { + { "MAIN_DYE", "", "MAIN_DYE" }, + { "", "NEUTRAL_NODE", "" }, + { "MAIN_DYE", "", "MAIN_DYE" } + } + }) + + if not (moreblocks and material == "stone") then + + unifieddyes.register_color_craft({ + output = "blox:"..material.."_checker 6", + palette = "extended", + neutral_node = def_mat, + recipe = { + { "NEUTRAL_NODE", "MAIN_DYE", "NEUTRAL_NODE" }, + { "MAIN_DYE", "NEUTRAL_NODE", "MAIN_DYE" }, + { "NEUTRAL_NODE", "MAIN_DYE", "NEUTRAL_NODE" } + } + }) + + unifieddyes.register_color_craft({ + output = "blox:"..material.."_checker 8", + palette = "extended", + neutral_node = def_mat, + recipe = { + { "MAIN_DYE", "NEUTRAL_NODE", "MAIN_DYE" }, + { "NEUTRAL_NODE", "MAIN_DYE", "NEUTRAL_NODE" }, + { "MAIN_DYE", "NEUTRAL_NODE", "MAIN_DYE" } + } + }) + + unifieddyes.register_color_craft({ + output = "blox:"..material.."_loop 6", + palette = "extended", + neutral_node = def_mat, + recipe = { + { "NEUTRAL_NODE", "NEUTRAL_NODE", "NEUTRAL_NODE" }, + { "NEUTRAL_NODE", "MAIN_DYE", "NEUTRAL_NODE" }, + { "NEUTRAL_NODE", "NEUTRAL_NODE", "NEUTRAL_NODE" }, + } + }) + + end +end + +--Fuel + +for _, nodeclass in ipairs(NodeClass) do + minetest.register_craft({ + type = "fuel", + recipe = "blox:wood_"..nodeclass, + burntime = 7, + }) +end + +minetest.register_craft({ + type = "fuel", + recipe = "blox:wood_tinted", + burntime = 7, +}) + +-- Tools + +minetest.register_tool("blox:bloodbane", { + description = "Blood Bane", + inventory_image = "blox_bloodbane.png", + tool_capabilities = { + full_punch_interval = 0.2, + max_drop_level=1, + groupcaps={ + fleshy={times={[1]=0.001, [2]=0.001, [3]=0.001}, uses=0, maxlevel=3}, + snappy={times={[1]=0.01, [2]=0.01, [3]=0.01}, uses=0, maxlevel=3}, + crumbly={times={[1]=0.01, [2]=0.01, [3]=0.01}, uses=0, maxlevel=3}, + cracky={times={[1]=0.01, [2]=0.01, [3]=0.01}, uses=0, maxlevel=3}, + choppy={times={[1]=0.01, [2]=0.01, [3]=0.01}, uses=0, maxlevel=3} + }, + damage_groups = {fleshy=200}, + } +}) + +-- Ores + +local sea_level = 1 + +minetest.register_on_mapgen_init(function(mapgen_params) + sea_level = mapgen_params.water_level +end) + +minetest.register_ore({ + ore_type = "scatter", + ore = "blox:glowore", + wherein = "default:stone", + clust_scarcity = 36 * 36 * 36, + clust_num_ores = 3, + clust_size = 2, + y_min = sea_level, + y_max = 31000, +}) + +minetest.register_ore({ + ore_type = "scatter", + ore = "blox:glowore", + wherein = "default:stone", + clust_scarcity = 14 * 14 * 14, + clust_num_ores = 5, + clust_size = 3, + y_min = sea_level - 30, + y_max = sea_level + 20, +}) + +minetest.register_ore({ + ore_type = "scatter", + ore = "blox:glowore", + wherein = "default:stone", + clust_scarcity = 36 * 36 * 36, + clust_num_ores = 3, + clust_size = 2, + y_min = -31000, + y_max = sea_level - 1, +}) + +print("Blox Mod [" ..version.. "] Loaded!") diff --git a/crops/.gitignore b/crops/.gitignore new file mode 100644 index 0000000..8b38e58 --- /dev/null +++ b/crops/.gitignore @@ -0,0 +1,3 @@ +## Generic ignorable patterns and files +*~ +debug.txt diff --git a/crops/pumpkin.lua b/crops/pumpkin.lua index 3f9f2f5..a64757d 100644 --- a/crops/pumpkin.lua +++ b/crops/pumpkin.lua @@ -184,9 +184,8 @@ minetest.register_abm({ return end - if minetest.registered_nodes[n.name] and - (minetest.registered_nodes[n.name].drawtype == "plantlike" or - minetest.registered_nodes[n.name].groups.flora == 1) or + if minetest.registered_nodes[n.name].drawtype == "plantlike" or + minetest.registered_nodes[n.name].groups.flora == 1 or n.name == "air" then minetest.set_node(t, {name = "crops:pumpkin", param2 = faces[r].m}) diff --git a/protector/README.md b/protector/README.md index 132d54d..fae4769 100644 --- a/protector/README.md +++ b/protector/README.md @@ -55,6 +55,12 @@ Change log: - 2.5 - Added HUD text to show when player is inside a protected area (updates every 5 seconds) - 2.6 - Add protection against CSM tampering, updated Intllib support (thanks codexp), tweaked block textures - 2.7 - Remove protection field entity when protector has been dug +- 2.8 - Added 'protector_show_interval' setting to minetest.conf [default is 5], make protection field glow in dark. +- 2.9 - Added MineClone2 recipes for protection block but no official support as yet +- 3.0 - Added PlayerFactions support, 'protector_hud_interval' setting and listing in advanced settings for mod values. +- 3.1 - Ability to hide protection blocks using /protector_hide and /protector_show , italian local added (thanks Hamlet) +- 3.2 - Defaults to Minetest translation if found, otherwise intllib fallback if loaded, locale files updated for both. Added 'protector_msg' setting for player text. +- 3.3 - Added support for playerfactions new api (thanks louisroyer), added limiter to protection radius of 22. Lucky Blocks: 10 @@ -91,6 +97,11 @@ reset name list show protected areas of your nearby protectors (max of 5) + /protector_show_area + + +A players own protection blocks can be hidden and shown using the following: + /protector_hide /protector_show @@ -114,6 +125,15 @@ protector_hurt = 2 protector_flip = true - When true players who dig inside a protected area will flipped around to stop them using lag to grief into someone else's build +protector_show_interval +- Number of seconds the protection field is visible, defaults to 5 seconds. + +protector_recipe = true +- When true allows players to craft protection blocks + +protector_msg = true +- When true shows protection messages in players chat when trying to interact in someone else's area + Protector Tool diff --git a/protector/admin.lua b/protector/admin.lua index dad48a8..ad1afce 100644 --- a/protector/admin.lua +++ b/protector/admin.lua @@ -29,7 +29,6 @@ minetest.register_chatcommand("protector_remove", { end removal_names = param - end, }) @@ -57,20 +56,19 @@ minetest.register_chatcommand("protector_replace", { local names = replace_names:split(" ") minetest.chat_send_player(name, - S("Replacing Protector name '@1' with '@2'", + S("Replacing Protector name @1 with @2", names[1] or "", names[2] or "")) return end replace_names = param - end, }) minetest.register_abm({ - nodenames = {"protector:protect", "protector:protect2"}, + nodenames = {"protector:protect", "protector:protect2", "protector:protect_hidden"}, interval = 8, chance = 1, catch_up = false, @@ -106,7 +104,6 @@ minetest.register_abm({ meta:set_string("owner", names[2]) meta:set_string("infotext", S("Protection (owned by @1)", names[2])) end - end end }) @@ -115,7 +112,7 @@ minetest.register_abm({ local r = tonumber(minetest.settings:get("protector_radius")) or 5 -- show protection areas of nearby protectors owned by you (thanks agaran) -minetest.register_chatcommand("protector_show", { +minetest.register_chatcommand("protector_show_area", { params = "", description = S("Show protected areas of your nearby protectors"), privs = {}, @@ -128,7 +125,7 @@ minetest.register_chatcommand("protector_show", { local pos = minetest.find_nodes_in_area( {x = pos.x - r, y = pos.y - r, z = pos.z - r}, {x = pos.x + r, y = pos.y + r, z = pos.z + r}, - {"protector:protect", "protector:protect2"}) + {"protector:protect", "protector:protect2", "protector:protect_hidden"}) local meta, owner @@ -138,9 +135,105 @@ minetest.register_chatcommand("protector_show", { meta = minetest.get_meta(pos[n]) owner = meta:get_string("owner") or "" - if owner == name then + if owner == name + or minetest.check_player_privs(name, {protection_bypass = true}) then minetest.add_entity(pos[n], "protector:display") end end end }) + + +-- ability to hide protection blocks (borrowed from doors mod :) +minetest.register_node("protector:protect_hidden", { + description = "Hidden Protector", + drawtype = "airlike", + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + -- has to be walkable for falling nodes to stop falling + walkable = true, + pointable = false, + diggable = false, + buildable_to = false, + floodable = false, + drop = "", + groups = {not_in_creative_inventory = 1, unbreakable = 1}, + on_blast = function() end, + -- 1px block inside door hinge near node top + collision_box = { + type = "fixed", + fixed = {-15/32, 13/32, -15/32, -13/32, 1/2, -13/32}, + }, +}) + + +minetest.register_chatcommand("protector_show", { + params = "", + description = S("Show your nearby protection blocks"), + privs = {interact = true}, + + func = function(name, param) + + local player = minetest.get_player_by_name(name) + + if not player then + return false, "Player not found" + end + + local pos = player:get_pos() + + local a = minetest.find_nodes_in_area( + {x = pos.x - r, y = pos.y - r, z = pos.z - r}, + {x = pos.x + r, y = pos.y + r, z = pos.z + r}, + {"protector:protect_hidden"}) + + local meta, owner + + for _, row in pairs(a) do + + meta = minetest.get_meta(row) + owner = meta:get_string("owner") or "" + + if owner == name + or minetest.check_player_privs(name, {protection_bypass = true}) then + minetest.swap_node(row, {name = "protector:protect"}) + end + end + end +}) + +minetest.register_chatcommand("protector_hide", { + params = "", + description = S("Hide your nearby protection blocks"), + privs = {interact = true}, + + func = function(name, param) + + local player = minetest.get_player_by_name(name) + + if not player then + return false, "Player not found" + end + + local pos = player:get_pos() + + local a = minetest.find_nodes_in_area( + {x = pos.x - r, y = pos.y - r, z = pos.z - r}, + {x = pos.x + r, y = pos.y + r, z = pos.z + r}, + {"protector:protect", "protector:protect2"}) + + local meta, owner + + for _, row in pairs(a) do + + meta = minetest.get_meta(row) + owner = meta:get_string("owner") or "" + + if owner == name + or minetest.check_player_privs(name, {protection_bypass = true}) then + minetest.swap_node(row, {name = "protector:protect_hidden"}) + end + end + end +}) diff --git a/protector/depends.txt b/protector/depends.txt index 4713add..5b09c28 100644 --- a/protector/depends.txt +++ b/protector/depends.txt @@ -1,4 +1,5 @@ -default +default? intllib? lucky_block? mesecons_mvps? +playerfactions? diff --git a/protector/doors_chest.lua b/protector/doors_chest.lua index 6d4408b..f5a2dea 100644 --- a/protector/doors_chest.lua +++ b/protector/doors_chest.lua @@ -6,6 +6,9 @@ local S = protector.intllib local F = minetest.formspec_escape +-- MineClone2 support +local mcl = not minetest.registered_items["default:steel_ingot"] + -- Registers a door function register_door(name, def) def.groups.not_in_creative_inventory = 1 @@ -74,7 +77,7 @@ function register_door(name, def) minetest.get_meta(pt2):set_int("right", 1) end - if not minetest.setting_getbool("creative_mode") then + if not minetest.settings:get_bool("creative_mode") then itemstack:take_item() end return itemstack @@ -147,6 +150,7 @@ function register_door(name, def) tiles = {tb[2], tb[2], tb[2], tb[2], tb[1], tb[1].."^[transformfx"}, paramtype = "light", paramtype2 = "facedir", + use_texture_alpha = "clip", is_ground_content = false, drop = name, drawtype = "nodebox", @@ -184,6 +188,7 @@ function register_door(name, def) tiles = {tt[2], tt[2], tt[2], tt[2], tt[1], tt[1].."^[transformfx"}, paramtype = "light", paramtype2 = "facedir", + use_texture_alpha = "clip", is_ground_content = false, drop = "", drawtype = "nodebox", @@ -221,6 +226,7 @@ function register_door(name, def) tiles = {tb[2], tb[2], tb[2], tb[2], tb[1].."^[transformfx", tb[1]}, paramtype = "light", paramtype2 = "facedir", + use_texture_alpha = "clip", is_ground_content = false, drop = name, drawtype = "nodebox", @@ -258,6 +264,7 @@ function register_door(name, def) tiles = {tt[2], tt[2], tt[2], tt[2], tt[1].."^[transformfx", tt[1]}, paramtype = "light", paramtype2 = "facedir", + use_texture_alpha = "clip", is_ground_content = false, drop = "", drawtype = "nodebox", @@ -310,6 +317,14 @@ register_door(name, { sunlight = false, }) +if mcl then +minetest.register_craft({ + output = name, + recipe = { + {"mcl_doors:wooden_door", "mcl_core:gold_ingot"} + } +}) +else minetest.register_craft({ output = name, recipe = { @@ -325,6 +340,7 @@ minetest.register_craft({ {"doors:door_wood", "default:copper_ingot"} } }) +end -- Protected Steel Door @@ -343,6 +359,14 @@ register_door(name, { sunlight = false, }) +if mcl then +minetest.register_craft({ + output = name, + recipe = { + {"mcl_doors:iron_door", "mcl_core:gold_ingot"} + } +}) +else minetest.register_craft({ output = name, recipe = { @@ -358,6 +382,7 @@ minetest.register_craft({ {"doors:door_steel", "default:copper_ingot"} } }) +end ----trapdoor---- @@ -383,6 +408,7 @@ function register_trapdoor(name, def) def.drawtype = "nodebox" def.paramtype = "light" def.paramtype2 = "facedir" + def.use_texture_alpha = "clip" def.is_ground_content = false local def_opened = table.copy(def) @@ -408,8 +434,8 @@ function register_trapdoor(name, def) fixed = {-0.5, -0.5, 6/16, 0.5, 0.5, 0.5} } def_opened.tiles = { def.tile_side, def.tile_side, - def.tile_side .. '^[transform3', - def.tile_side .. '^[transform1', + def.tile_side .. "^[transform3", + def.tile_side .. "^[transform1", def.tile_front, def.tile_front } def_opened.drop = name_closed @@ -434,12 +460,19 @@ register_trapdoor("protector:trapdoor", { sounds = default.node_sound_wood_defaults(), }) +if mcl then minetest.register_craft({ - output = 'protector:trapdoor 2', + output = "protector:trapdoor", recipe = { - {'group:wood', 'default:copper_ingot', 'group:wood'}, - {'group:wood', 'group:wood', 'group:wood'}, - {'', '', ''}, + {"mcl_doors:trapdoor", "mcl_core:gold_ingot"} + } +}) +else +minetest.register_craft({ + output = "protector:trapdoor 2", + recipe = { + {"group:wood", "default:copper_ingot", "group:wood"}, + {"group:wood", "group:wood", "group:wood"}, } }) @@ -449,6 +482,7 @@ minetest.register_craft({ {"doors:trapdoor", "default:copper_ingot"} } }) +end -- Protected Steel Trapdoor @@ -465,11 +499,19 @@ register_trapdoor("protector:trapdoor_steel", { sounds = default.node_sound_wood_defaults(), }) +if mcl then minetest.register_craft({ - output = 'protector:trapdoor_steel', + output = "protector:trapdoor_steel", recipe = { - {'default:copper_ingot', 'default:steel_ingot'}, - {'default:steel_ingot', 'default:steel_ingot'}, + {"mcl_doors:iron_trapdoor", "mcl_core:gold_ingot"} + } +}) +else +minetest.register_craft({ + output = "protector:trapdoor_steel", + recipe = { + {"default:copper_ingot", "default:steel_ingot"}, + {"default:steel_ingot", "default:steel_ingot"}, } }) @@ -479,6 +521,7 @@ minetest.register_craft({ {"doors:trapdoor_steel", "default:copper_ingot"} } }) +end -- Protected Chest @@ -501,7 +544,7 @@ minetest.register_node("protector:chest", { local inv = meta:get_inventory() meta:set_string("infotext", S("Protected Chest")) - meta:set_string("name", "") + meta:set_string("name", S("Protected Chest")) inv:set_size("main", 8 * 4) end, @@ -520,20 +563,24 @@ minetest.register_node("protector:chest", { on_metadata_inventory_put = function(pos, listname, index, stack, player) - minetest.log("action", S("@1 moves stuff to protected chest at @2", - player:get_player_name(), minetest.pos_to_string(pos))) + minetest.log("action", player:get_player_name() .. + " moves stuff to protected chest at " .. + minetest.pos_to_string(pos)) end, on_metadata_inventory_take = function(pos, listname, index, stack, player) - minetest.log("action", S("@1 takes stuff from protected chest at @2", - player:get_player_name(), minetest.pos_to_string(pos))) + minetest.log("action", player:get_player_name() .. + " takes stuff from protected chest at " .. + minetest.pos_to_string(pos)) end, - on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) + on_metadata_inventory_move = function( + pos, from_list, from_index, to_list, to_index, count, player) - minetest.log("action", S("@1 moves stuff inside protected chest at @2", - player:get_player_name(), minetest.pos_to_string(pos))) + minetest.log("action", player:get_player_name() .. + " moves stuff inside protected chest at " .. + minetest.pos_to_string(pos)) end, allow_metadata_inventory_put = function(pos, listname, index, stack, player) @@ -554,7 +601,8 @@ minetest.register_node("protector:chest", { return stack:get_count() end, - allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) + allow_metadata_inventory_move = function( + pos, from_list, from_index, to_list, to_index, count, player) if minetest.is_protected(pos, player:get_player_name()) then return 0 @@ -577,9 +625,9 @@ minetest.register_node("protector:chest", { local spos = pos.x .. "," .. pos.y .. "," ..pos.z local formspec = "size[8,9]" - .. default.gui_bg - .. default.gui_bg_img - .. default.gui_slots +-- .. default.gui_bg +-- .. default.gui_bg_img +-- .. default.gui_slots .. "list[nodemeta:".. spos .. ";main;0,0.3;8,4;]" .. "button[0,4.5;2,0.25;toup;" .. F(S("To Chest")) .. "]" .. "field[2.3,4.8;4,0.25;chestname;;" @@ -599,15 +647,39 @@ minetest.register_node("protector:chest", { on_blast = function() end, }) +-- Container transfer helper +local to_from = function(src, dst) + + local stack, item, leftover + local size = dst:get_size("main") + + for i = 1, size do + + stack = src:get_stack("main", i) + item = stack:get_name() + + if item ~= "" and dst:room_for_item("main", item) then + + leftover = dst:add_item("main", stack) + + if leftover and not leftover:is_empty() then + src:set_stack("main", i, leftover) + else + src:set_stack("main", i, nil) + end + end + end +end + -- Protected Chest formspec buttons minetest.register_on_player_receive_fields(function(player, formname, fields) - if string.sub(formname, 0, string.len("protector:chest_")) ~= "protector:chest_" then + if string.sub(formname, 0, 16) ~= "protector:chest_" then return end - local pos_s = string.sub(formname,string.len("protector:chest_") + 1) + local pos_s = string.sub(formname, 17) local pos = minetest.string_to_pos(pos_s) if minetest.is_protected(pos, player:get_player_name()) then @@ -617,43 +689,16 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) local meta = minetest.get_meta(pos) ; if not meta then return end local chest_inv = meta:get_inventory() ; if not chest_inv then return end local player_inv = player:get_inventory() - local leftover + -- copy contents of player inventory to chest if fields.toup then - -- copy contents of players inventory to chest - for i, v in ipairs(player_inv:get_list("main") or {}) do - - if chest_inv:room_for_item("main", v) then - - leftover = chest_inv:add_item("main", v) - - player_inv:remove_item("main", v) - - if leftover - and not leftover:is_empty() then - player_inv:add_item("main", v) - end - end - end + to_from(player_inv, chest_inv) + -- copy contents of chest to player inventory elseif fields.todn then - -- copy contents of chest to players inventory - for i, v in ipairs(chest_inv:get_list("main") or {}) do - - if player_inv:room_for_item("main", v) then - - leftover = player_inv:add_item("main", v) - - chest_inv:remove_item("main", v) - - if leftover - and not leftover:is_empty() then - chest_inv:add_item("main", v) - end - end - end + to_from(chest_inv, player_inv) elseif fields.chestname then @@ -661,9 +706,9 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if fields.chestname ~= "" then meta:set_string("name", fields.chestname) - meta:set_string("infotext", - S("Protected Chest (@1)", fields.chestname)) + meta:set_string("infotext", fields.chestname) else + meta:set_string("name", S("Protected Chest")) meta:set_string("infotext", S("Protected Chest")) end @@ -672,18 +717,27 @@ end) -- Protected Chest recipes +if mcl then minetest.register_craft({ - output = 'protector:chest', + output = "protector:chest", recipe = { - {'group:wood', 'group:wood', 'group:wood'}, - {'group:wood', 'default:copper_ingot', 'group:wood'}, - {'group:wood', 'group:wood', 'group:wood'}, + {"mcl_chests:chest", "mcl_core:gold_ingot"}, + } +}) +else +minetest.register_craft({ + output = "protector:chest", + recipe = { + {"group:wood", "group:wood", "group:wood"}, + {"group:wood", "default:copper_ingot", "group:wood"}, + {"group:wood", "group:wood", "group:wood"}, } }) minetest.register_craft({ - output = 'protector:chest', + output = "protector:chest", recipe = { - {'default:chest', 'default:copper_ingot', ''}, + {"default:chest", "default:copper_ingot"}, } }) +end diff --git a/protector/hud.lua b/protector/hud.lua index c74a4dc..4a5d711 100644 --- a/protector/hud.lua +++ b/protector/hud.lua @@ -1,14 +1,20 @@ local S = protector.intllib -local radius = (tonumber(minetest.setting_get("protector_radius")) or 5) +local radius = (tonumber(minetest.settings:get("protector_radius")) or 5) + +-- radius limiter (minetest cannot handle node volume of more than 4096000) +if radius > 22 then radius = 22 end + local hud = {} local hud_timer = 0 +local hud_interval = (tonumber(minetest.settings:get("protector_hud_interval")) or 5) +if hud_interval > 0 then minetest.register_globalstep(function(dtime) -- every 5 seconds hud_timer = hud_timer + dtime - if hud_timer < 5 then + if hud_timer < hud_interval then return end hud_timer = 0 @@ -22,7 +28,7 @@ minetest.register_globalstep(function(dtime) local protectors = minetest.find_nodes_in_area( {x = pos.x - radius , y = pos.y - radius , z = pos.z - radius}, {x = pos.x + radius , y = pos.y + radius , z = pos.z + radius}, - {"protector:protect","protector:protect2"}) + {"protector:protect","protector:protect2", "protector:protect_hidden"}) if #protectors > 0 then local npos = protectors[1] @@ -40,17 +46,15 @@ minetest.register_globalstep(function(dtime) hud_elem_type = "text", name = "Protector Area", number = 0xFFFF22, - position = {x=0, y=0.95}, - offset = {x=8, y=-8}, + position = {x = 0, y = 0.95}, + offset = {x = 8, y = -8}, text = hud_text, - scale = {x=200, y=60}, - alignment = {x=1, y=-1}, + scale = {x = 200, y = 60}, + alignment = {x = 1, y = -1}, }) return - else - player:hud_change(hud[name].id, "text", hud_text) end end @@ -59,3 +63,5 @@ end) minetest.register_on_leaveplayer(function(player) hud[player:get_player_name()] = nil end) + +end diff --git a/protector/init.lua b/protector/init.lua index c9dd9d2..f12b424 100644 --- a/protector/init.lua +++ b/protector/init.lua @@ -1,14 +1,27 @@ +-- default support (for use with MineClone2 and other [games] +default = default or { + node_sound_stone_defaults = function(table) end, + node_sound_wood_defaults = function(table) end, + gui_bg = "", + gui_bg_img = "", + gui_slots = "", +} + -- Load support for intllib. local MP = minetest.get_modpath(minetest.get_current_modname()) -local S = dofile(MP .. "/intllib.lua") local F = minetest.formspec_escape +local S = minetest.get_translator and minetest.get_translator("protector") or + dofile(MP .. "/intllib.lua") +-- Load support for factions +local factions_available = minetest.global_exists("factions") -protector = {} -protector.mod = "redo" -protector.modpath = MP -protector.intllib = S +protector = { + mod = "redo", + modpath = MP, + intllib = S +} local protector_max_share_count = 12 -- get minetest.conf settings @@ -17,6 +30,13 @@ local protector_flip = minetest.settings:get_bool("protector_flip") or false local protector_hurt = tonumber(minetest.settings:get("protector_hurt")) or 0 local protector_spawn = tonumber(minetest.settings:get("protector_spawn") or minetest.settings:get("protector_pvp_spawn")) or 0 +local protector_show = tonumber(minetest.settings:get("protector_show_interval")) or 5 +local protector_recipe = minetest.settings:get_bool("protector_recipe") ~= false +local protector_msg = minetest.settings:get_bool("protector_msg") ~= false + +-- radius limiter (minetest cannot handle node volume of more than 4096000) +if protector_radius > 22 then protector_radius = 22 end + -- get static spawn position local statspawn = minetest.string_to_pos(minetest.settings:get("static_spawnpoint")) @@ -45,7 +65,35 @@ end -- check for member name -local is_member = function (meta, name) +local is_member = function(meta, name) + + if factions_available + and meta:get_int("faction_members") == 1 then + + if factions.version == nil then + + -- backward compatibility + if factions.get_player_faction(name) ~= nil + and factions.get_player_faction(meta:get_string("owner")) == + factions.get_player_faction(name) then + return true + end + else + -- is member if player and owner share at least one faction + local owner_factions = factions.get_player_factions(name) + local owner = meta:get_string("owner") + + if owner_factions ~= nil and owner_factions ~= false then + + for _, f in ipairs(owner_factions) do + + if factions.player_is_in_faction(f, owner) then + return true + end + end + end + end + end for _, n in pairs(get_member_list(meta)) do @@ -117,6 +165,36 @@ local protector_formspec = function(meta) local members = get_member_list(meta) local npp = protector_max_share_count -- max users added to protector list local i = 0 + local checkbox_faction = false + + -- Display the checkbox only if the owner is member of at least 1 faction + if factions_available then + + if factions.version == nil then + + -- backward compatibility + if factions.get_player_faction(meta:get_string("owner")) then + checkbox_faction = true + end + else + local player_factions = factions.get_player_factions(meta:get_string("owner")) + + if player_factions ~= nil and #player_factions >= 1 then + checkbox_faction = true + end + end + end + if checkbox_faction then + + formspec = formspec .. "checkbox[0,5;faction_members;" + .. F(S("Allow faction access")) + .. ";" .. (meta:get_int("faction_members") == 1 and + "true" or "false") .. "]" + + if npp > 8 then + npp = 8 + end + end for n = 1, #members do @@ -174,6 +252,18 @@ local inside_spawn = function(pos, radius) end +-- show protection message if enabled +local show_msg = function(player, msg) + + -- if messages disabled or no player name provided + if protector_msg == false or not player or player == "" then + return + end + + minetest.chat_send_player(player, msg) +end + + -- Infolevel: -- 0 for no info -- 1 for "This area is owned by !" if you can't dig @@ -198,7 +288,7 @@ protector.can_dig = function(r, pos, digger, onlyowner, infolevel) -- is spawn area protected ? if inside_spawn(pos, protector_spawn) then - minetest.chat_send_player(digger, + show_msg(digger, S("Spawn @1 has been protected up to a @2 block radius.", minetest.pos_to_string(statspawn), protector_spawn)) @@ -209,7 +299,7 @@ protector.can_dig = function(r, pos, digger, onlyowner, infolevel) local pos = minetest.find_nodes_in_area( {x = pos.x - r, y = pos.y - r, z = pos.z - r}, {x = pos.x + r, y = pos.y + r, z = pos.z + r}, - {"protector:protect", "protector:protect2"}) + {"protector:protect", "protector:protect2", "protector:protect_hidden"}) local meta, owner, members @@ -225,7 +315,7 @@ protector.can_dig = function(r, pos, digger, onlyowner, infolevel) -- and you aren't on the member list if onlyowner or not is_member(meta, digger) then - minetest.chat_send_player(digger, + show_msg(digger, S("This area is owned by @1", owner) .. "!") return false @@ -282,7 +372,11 @@ function minetest.is_protected(pos, digger) -- hurt player if protection violated if protector_hurt > 0 and player:get_hp() > 0 then - player:set_hp(player:get_hp() - protector_hurt) + + -- This delay fixes item duplication bug (thanks luk3yx) + minetest.after(0.1, function() + player:set_hp(player:get_hp() - protector_hurt) + end) end -- flip player when protection violated @@ -356,6 +450,20 @@ local check_overlap = function(itemstack, placer, pointed_thing) end +-- remove protector display entities +local del_display = function(pos) + + local objects = minetest.get_objects_inside_radius(pos, 0.5) + + for _, v in ipairs(objects) do + + if v and v:get_luaentity() + and v:get_luaentity().name == "protector:display" then + v:remove() + end + end +end + -- temporary pos store local player_pos = {} @@ -388,8 +496,9 @@ minetest.register_node("protector:protect", { local meta = minetest.get_meta(pos) meta:set_string("owner", placer:get_player_name() or "") - meta:set_string("infotext", S("Protection (owned by @1)", meta:get_string("owner"))) meta:set_string("members", "") + meta:set_string("infotext", + S("Protection (owned by @1)", meta:get_string("owner"))) end, on_use = function(itemstack, user, pointed_thing) @@ -398,7 +507,8 @@ minetest.register_node("protector:protect", { return end - protector.can_dig(protector_radius, pointed_thing.under, user:get_player_name(), false, 2) + protector.can_dig(protector_radius, pointed_thing.under, + user:get_player_name(), false, 2) end, on_rightclick = function(pos, node, clicker, itemstack) @@ -431,23 +541,34 @@ minetest.register_node("protector:protect", { on_blast = function() end, - after_destruct = function(pos, oldnode) - local objects = minetest.get_objects_inside_radius(pos, 0.5) - for _, v in ipairs(objects) do - v:remove() - end - end, + after_destruct = del_display }) -minetest.register_craft({ - output = "protector:protect", - recipe = { - {"default:stone", "default:stone", "default:stone"}, - {"default:stone", "default:gold_ingot", "default:stone"}, - {"default:stone", "default:stone", "default:stone"}, - } -}) +-- default recipe and alternative for MineClone2 +if protector_recipe then + if minetest.registered_items["default:stone"] then + + minetest.register_craft({ + output = "protector:protect", + recipe = { + {"default:stone", "default:stone", "default:stone"}, + {"default:stone", "default:gold_ingot", "default:stone"}, + {"default:stone", "default:stone", "default:stone"}, + } + }) + else + + minetest.register_craft({ + output = "protector:protect", + recipe = { + {"mcl_core:stone", "mcl_core:stone", "mcl_core:stone"}, + {"mcl_core:stone", "mcl_core:gold_ingot", "mcl_core:stone"}, + {"mcl_core:stone", "mcl_core:stone", "mcl_core:stone"}, + } + }) + end +end -- protection logo minetest.register_node("protector:protect2", { @@ -457,6 +578,7 @@ minetest.register_node("protector:protect2", { inventory_image = "protector_logo.png", sounds = default.node_sound_stone_defaults(), groups = {dig_immediate = 2, unbreakable = 1}, + use_texture_alpha = "clip", paramtype = "light", paramtype2 = "wallmounted", legacy_wallmounted = true, @@ -479,8 +601,9 @@ minetest.register_node("protector:protect2", { local meta = minetest.get_meta(pos) meta:set_string("owner", placer:get_player_name() or "") - meta:set_string("infotext", S("Protection (owned by @1)", meta:get_string("owner"))) meta:set_string("members", "") + meta:set_string("infotext", + S("Protection (owned by @1)", meta:get_string("owner"))) end, on_use = function(itemstack, user, pointed_thing) @@ -489,7 +612,8 @@ minetest.register_node("protector:protect2", { return end - protector.can_dig(protector_radius, pointed_thing.under, user:get_player_name(), false, 2) + protector.can_dig(protector_radius, pointed_thing.under, + user:get_player_name(), false, 2) end, on_rightclick = function(pos, node, clicker, itemstack) @@ -522,12 +646,7 @@ minetest.register_node("protector:protect2", { on_blast = function() end, - after_destruct = function(pos, oldnode) - local objects = minetest.get_objects_inside_radius(pos, 0.5) - for _, v in ipairs(objects) do - v:remove() - end - end, + after_destruct = del_display }) -- recipes to switch between protectors @@ -587,6 +706,11 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) return end + -- add faction members + if factions_available then + meta:set_int("faction_members", fields.faction_members == "true" and 1 or 0) + end + -- add member [+] if add_member_input then @@ -616,16 +740,17 @@ minetest.register_entity("protector:display", { collisionbox = {0, 0, 0, 0, 0, 0}, visual = "wielditem", -- wielditem seems to be scaled to 1.5 times original node size - visual_size = {x = 1.0 / 1.5, y = 1.0 / 1.5}, + visual_size = {x = 0.67, y = 0.67}, textures = {"protector:display_node"}, timer = 0, + glow = 10, on_step = function(self, dtime) self.timer = self.timer + dtime - -- remove after 5 seconds - if self.timer > 5 then + -- remove after set number of seconds + if self.timer > protector_show then self.object:remove() end end, @@ -638,7 +763,7 @@ minetest.register_entity("protector:display", { local x = protector_radius minetest.register_node("protector:display_node", { tiles = {"protector_display.png"}, - use_texture_alpha = true, + use_texture_alpha = "clip", -- true, walkable = false, drawtype = "nodebox", node_box = { diff --git a/protector/locale/de.po b/protector/locale/de.po index 5f8a695..478a9ca 100644 --- a/protector/locale/de.po +++ b/protector/locale/de.po @@ -19,10 +19,8 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" #: admin.lua -#, fuzzy msgid "Remove Protectors around players (separate names with spaces)" -msgstr "" -"Entferne Störschützer von bestimmten Namen in der Nähe von Spielern (trenne " +msgstr "Entferne Störschützer von bestimmten Namen in der Nähe von Spielern (trenne " "Namen durch Leerzeichen)" #: admin.lua @@ -73,18 +71,6 @@ msgstr "Geschützte Stahlfalltür" msgid "Protected Chest" msgstr "Geschützte Truhe" -#: doors_chest.lua -msgid "@1 moves stuff to protected chest at @2" -msgstr "@1 verlagert Dinge in geschützte Truhe bei @2" - -#: doors_chest.lua -msgid "@1 takes stuff from protected chest at @2" -msgstr "@1 nimmt Dinge aus geschützter Truhe bei @2" - -#: doors_chest.lua -msgid "@1 moves stuff inside protected chest at @2" -msgstr "@1 verschiebt Dinge innerhalb der geschützten Truhe bei @2" - #: doors_chest.lua msgid "To Chest" msgstr "Zur Truhe" diff --git a/protector/locale/es.po b/protector/locale/es.po new file mode 100644 index 0000000..3cf2089 --- /dev/null +++ b/protector/locale/es.po @@ -0,0 +1,177 @@ +# Spanish translation for PROTECTOR MOD. +# Copyright (C) 2018 universales +# This file is distributed under the same license as the PROTECTOR MOD package. +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PROTECTOR MOD\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-07-10 17:33+0200\n" +"PO-Revision-Date: 2020-02-27\n" +"Last-Translator: Universales\n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: admin.lua +msgid "Remove Protectors around players (separate names with spaces)" +msgstr "Eliminar protectores alrededor de los jugadores (nombres separados con espacios)" + +#: admin.lua +msgid "" +msgstr "" + +#: admin.lua +msgid "Replace Protector Owner with name provided" +msgstr "Reemplace el propietario del protector con el nombre proporcionado" + +#: admin.lua +msgid " " +msgstr " " + +#: admin.lua +msgid "Replacing Protector name '@1' with '@2'" +msgstr "Reemplazando el nombre del protector '@1' a '@2'" + +#: admin.lua +msgid "Show protected areas of your nearby protectors" +msgstr "Mostrar áreas protegidas de sus protectores cercanos" + +#: admin.lua +msgid "Protector Names to remove: @1" +msgstr "Nombres de protectores para eliminar: @1" + +#: admin.lua +msgid "Name List Reset" +msgstr "Restablecer lista de nombres" + +#: doors_chest.lua +msgid "Protected Wooden Door" +msgstr "Puerta de madera protegida" + +#: doors_chest.lua +msgid "Protected Steel Door" +msgstr "Puerta de hierro protegida" + +#: doors_chest.lua +msgid "Protected Trapdoor" +msgstr "Trampilla Protegida" + +#: doors_chest.lua +msgid "Protected Steel Trapdoor" +msgstr "Trampilla de hierro protegida" + +#: doors_chest.lua +msgid "Protected Chest" +msgstr "Cofre protegido" + +#: doors_chest.lua +msgid "To Chest" +msgstr "Al cofre" + +#: doors_chest.lua +msgid "To Inventory" +msgstr "Al inventario" + +#: doors_chest.lua +msgid "Protected Chest (@1)" +msgstr "Cofre protegido (@1)" + +#: init.lua +msgid "-- Protector interface --" +msgstr "-- Interfaz del protector --" + +#: init.lua +msgid "PUNCH node to show protected area" +msgstr "nodo de perforación para mostrar el área protegida" + +#: init.lua +msgid "USE for area check" +msgstr "Usar para chequeo del área" + +#: init.lua +msgid "Members:" +msgstr "Miembros:" + +#: init.lua +msgid "Close" +msgstr "Cerrar" + +#: init.lua +msgid "Protection located at: @1" +msgstr "Protección ubicada en: @1" + +#: init.lua +msgid "Members: @1." +msgstr "Miembros: @1." + +#: init.lua +msgid "This area is not protected." +msgstr "Esta área no está protegida." + +#: init.lua +msgid "You can build here." +msgstr "Puedes construir aquí." + +#: init.lua tool.lua +msgid "Overlaps into above players protected area" +msgstr "Se superpone en el área protegida de los jugadores anteriores" + +#: init.lua +msgid "Protection Block" +msgstr "Bloque de protección" + +#: admin.lua init.lua tool.lua +msgid "Protection (owned by @1)" +msgstr "Protegido (Propiedad de @1)" + +#: init.lua +msgid "Protection Logo" +msgstr "Logotipo de la protección" + +#: init.lua +msgid "[MOD] Protector Redo loaded" +msgstr "[MOD] Protector recargado" + +#: init.lua +msgid "Spawn @1 has been protected up to a @2 block radius." +msgstr "Spawn @1 ha sido protegido hasta un radio de bloque @2." + +#: init.lua +msgid "This area is owned by @1" +msgstr "Esta área es propiedad de @1" + +#: pvp.lua +msgid "[Protector] on_punchplayer called with nil objects" +msgstr "[Protector] on_punchplayer llamado con objetos nulos." + +#: pvp.lua +msgid "[Protector] pvp_protect not active, update your version of Minetest" +msgstr "[Protector] pvp_protect no está activo, actualiza tu versión de Minetest" + +#: pvp.lua +msgid "[Protector] pvp_protect is disabled" +msgstr "[Protector] pvp_protect está deshabilitado" + +#: hud.lua +msgid "Owner: @1" +msgstr "Propietario: @1" + +#: tool.lua +msgid "Protector Placer Tool (stand near protector, face direction and use)" +msgstr "" +"Herramienta de colocación del protector (pararse cerca del protector, dirección de la cara y uso) " + +#: tool.lua +msgid "Protector already in place!" +msgstr "¡El protector ya está en este lugar!" + +#: tool.lua +msgid "No protectors available to place!" +msgstr "¡No hay protectores disponibles para colocar!" + +#: tool.lua +msgid "Protector placed at @1" +msgstr "Protector colocado en @1" diff --git a/protector/locale/fr.po b/protector/locale/fr.po index c2fce21..2452ee4 100644 --- a/protector/locale/fr.po +++ b/protector/locale/fr.po @@ -19,10 +19,8 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" #: admin.lua -#, fuzzy msgid "Remove Protectors around players (separate names with spaces)" -msgstr "" -"Retirer les protecteurs près des joueurs avec les noms fournis (noms séparés " +msgstr "Retirer les protecteurs près des joueurs avec les noms fournis (noms séparés " "avec des espaces)" #: admin.lua @@ -73,19 +71,6 @@ msgstr "Trap en acier protégé" msgid "Protected Chest" msgstr "Coffre protégé" -#: doors_chest.lua -msgid "@1 moves stuff to protected chest at @2" -msgstr "@1 déplace des objets vers le coffre protégée à @2" - -#: doors_chest.lua -msgid "@1 takes stuff from protected chest at @2" -msgstr "@1 prend des objets du coffre protégée à @2" - -#: doors_chest.lua -#, fuzzy -msgid "@1 moves stuff inside protected chest at @2" -msgstr "@1 déplace des objets à l'intérieur de du coffre protégé à @2" - #: doors_chest.lua msgid "To Chest" msgstr "Vers le coffre" diff --git a/protector/locale/it.po b/protector/locale/it.po new file mode 100644 index 0000000..97145f4 --- /dev/null +++ b/protector/locale/it.po @@ -0,0 +1,180 @@ +# Italian translation for PROTECTOR MOD. +# Copyright (C) 2020 Hamlet +# This file is distributed under the same license as the PROTECTOR MOD package. +# Xanthin , 2016. +# CodeXP , 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: PROTECTOR MOD\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-07-10 17:33+0200\n" +"PO-Revision-Date: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.2.1\n" +"Last-Translator: Hamlet \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Language: it\n" + +#: admin.lua +msgid "Remove Protectors around players (separate names with spaces)" +msgstr "Elimina i protettori attorno ai giocatori (separa i nomi con gli spazi)" + +#: admin.lua +msgid "" +msgstr "" + +#: admin.lua +msgid "Replace Protector Owner with name provided" +msgstr "Sostituisci il proprietario del protettore col nome fornito" + +#: admin.lua +msgid " " +msgstr " " + +#: admin.lua +msgid "Replacing Protector name '@1' with '@2'" +msgstr "Sostituzione del nome del protettore '@1' con '@2'" + +#: admin.lua +msgid "Show protected areas of your nearby protectors" +msgstr "Mostra le aree protette dei protettori vicino a te" + +#: admin.lua +msgid "Protector Names to remove: @1" +msgstr "Nomi dei protettori da eliminare: @1" + +#: admin.lua +msgid "Name List Reset" +msgstr "Azzera l'elenco dei nomi" + +#: doors_chest.lua +msgid "Protected Wooden Door" +msgstr "Porta di legno protetta" + +#: doors_chest.lua +msgid "Protected Steel Door" +msgstr "Porta d'acciaio protetta" + +#: doors_chest.lua +msgid "Protected Trapdoor" +msgstr "Botola protetta" + +#: doors_chest.lua +msgid "Protected Steel Trapdoor" +msgstr "Botola d'acciaio protetta" + +#: doors_chest.lua +msgid "Protected Chest" +msgstr "Baule protetto" + +#: doors_chest.lua +msgid "To Chest" +msgstr "Al baule" + +#: doors_chest.lua +msgid "To Inventory" +msgstr "All'inventario" + +#: doors_chest.lua +msgid "Protected Chest (@1)" +msgstr "Baule protetto (@1)" + +#: init.lua +msgid "-- Protector interface --" +msgstr "-- Interfaccia protettore --" + +#: init.lua +msgid "PUNCH node to show protected area" +msgstr "COLPISCI il nodo per mostrare l'area protetta" + +#: init.lua +msgid "USE for area check" +msgstr "USA per controllare l'area" + +#: init.lua +msgid "Members:" +msgstr "Membri:" + +#: init.lua +msgid "Close" +msgstr "Chiudi" + +#: init.lua +msgid "Protection located at: @1" +msgstr "Protezione collocata a: @1" + +#: init.lua +msgid "Members: @1." +msgstr "Membri: @1." + +#: init.lua +msgid "This area is not protected." +msgstr "Quest'area non è protetta." + +#: init.lua +msgid "You can build here." +msgstr "Qui puoi costruire." + +#: init.lua tool.lua +msgid "Overlaps into above players protected area" +msgstr "Si sovrappone ad un'area sovrastante protetta dai giocatori" + +#: init.lua +msgid "Protection Block" +msgstr "Blocco di protezione" + +#: admin.lua init.lua tool.lua +msgid "Protection (owned by @1)" +msgstr "Protezione (di proprietà di @1)" + +#: init.lua +msgid "Protection Logo" +msgstr "Logo di protezione" + +#: init.lua +msgid "[MOD] Protector Redo loaded" +msgstr "[MOD] Protector Redo caricato" + +#: init.lua +msgid "Spawn @1 has been protected up to a @2 block radius." +msgstr "Lo spawn @1 è stato protetto fino a un raggio di @2 blocchi." + +#: init.lua +msgid "This area is owned by @1" +msgstr "Quest'area è di proprietà di @1" + +#: pvp.lua +msgid "[Protector] on_punchplayer called with nil objects" +msgstr "[Protector] on_punchplayer chiamato con oggetti nil" + +#: pvp.lua +msgid "[Protector] pvp_protect not active, update your version of Minetest" +msgstr "[Protector] pvp_protect non attiva, aggiorna la tua versione di Minetest" + +#: pvp.lua +msgid "[Protector] pvp_protect is disabled" +msgstr "[Protector] pvp_protect è disattivato" + +#: hud.lua +msgid "Owner: @1" +msgstr "Proprietario: @1" + +#: tool.lua +msgid "Protector Placer Tool (stand near protector, face direction and use)" +msgstr "Strumento di posizionamento protettore (stai vicino al protettore, guarda la direzione e usa)" + +#: tool.lua +msgid "Protector already in place!" +msgstr "Protettore già presente!" + +#: tool.lua +msgid "No protectors available to place!" +msgstr "Nessun protettore disponibile da posizionare!" + +#: tool.lua +msgid "Protector placed at @1" +msgstr "Protettore posizionato a @1" \ No newline at end of file diff --git a/protector/locale/protector.de.tr b/protector/locale/protector.de.tr new file mode 100644 index 0000000..9656715 --- /dev/null +++ b/protector/locale/protector.de.tr @@ -0,0 +1,55 @@ +# textdomain: protector +# author: Xanthin and CodeXP +# last update: 2020/Jul/12 + +### admin.lua ### +Remove Protectors around players (separate names with spaces)=Entferne Störschützer von bestimmten Namen in der Nähe von Spielern (trenne Namen durch Leerzeichen) += +Replace Protector Owner with name provided=Ersetze Besitzer der Störschützer mit neuem Besitzer + = +Replacing Protector name '@1' with '@2'=Ersetze Besitzer der Störschützer von '@1' mit '@2' +Show protected areas of your nearby protectors=Zeige geschützte Bereiche der Störschützer in der Nähe +Protector Names to remove: @1=Störschutznamen zum Entfernen: @1 +Name List Reset=Namensliste zurückgesetzt + +### doors_chest.lua ### +Protected Wooden Door=Geschützte Holztür +Protected Steel Door=Geschützte Stahltür +Protected Trapdoor=Geschützte Falltür +Protected Steel Trapdoor=Geschützte Stahlfalltür +Protected Chest=Geschützte Truhe +To Chest=Zur Truhe +To Inventory=Zum Inventar +Protected Chest (@1)=Geschützte Truhe (@1) + +### init.lua ### +-- Protector interface --=-- Störschutz-Interface -- +PUNCH node to show protected area=SCHLAGE Node, um geschützten Bereich anzuzeigen oder +USE for area check=BENUTZE für Bereichsprüfung +Members:=Mitglieder: +Close=Schließen +Protection located at: @1=Störschutz befindet sich bei: @1 +Members: @1.=Mitglieder: @1. +This area is not protected.=Dieser Bereich ist nicht geschützt. +You can build here.=Du kannst hier bauen. +Overlaps into above players protected area=Überlappung im geschützen Bereich eines Spielers +Protection Block=Störschutzblock +Protection (owned by @1)=Störschutz (gehört @1) +Protection Logo=Störschutzlogo +[MOD] Protector Redo loaded=[MOD] Protector Redo geladen +Spawn @1 has been protected up to a @2 block radius.=Spawn @1 ist geschützt mit einem Radius von @2 Blöcke. +This area is owned by @1=Dieser Bereich gehört @1 + +### pvp.lua ### +[Protector] on_punchplayer called with nil objects=on_punchplayer wurde durch \"nil objects\" aufgerufen +[Protector] pvp_protect not active, update your version of Minetest=pvp_protect ist nicht aktiv, aktualisiere deine Minetestversion +[Protector] pvp_protect is disabled=pvp_protect ist ausgeschaltet + +### hud.lua ### +Owner: @1=Besitzer: @1 + +### tool.lua ### +Protector Placer Tool (stand near protector, face direction and use)=Störschutz Platzier-Werkzeug (stehe neben Störschutz, schaue in die gewünschte Richtung und anwenden) +Protector already in place!=Störschutz is bereits platziert! +No protectors available to place!=Keine Störschützer mehr im Inventar! +"Protector placed at @1"=Störschutz befindet sich bei: @1 diff --git a/protector/locale/protector.es.tr b/protector/locale/protector.es.tr new file mode 100644 index 0000000..117a4c3 --- /dev/null +++ b/protector/locale/protector.es.tr @@ -0,0 +1,55 @@ +# textdomain: protector +# author: universales +# last update: 2020-02-27 + +### admin.lua ### +Remove Protectors around players (separate names with spaces)=Eliminar protectores alrededor de los jugadores (nombres separados con espacios) += +Replace Protector Owner with name provided=Reemplace el propietario del protector con el nombre proporcionado + = +Replacing Protector name '@1' with '@2'=Reemplazando el nombre del protector '@1' a '@2' +Show protected areas of your nearby protectors=Mostrar áreas protegidas de sus protectores cercanos +Protector Names to remove: @1=Nombres de protectores para eliminar: @1 +Name List Reset=Restablecer lista de nombres + +### doors_chest.lua ### +Protected Wooden Door=Puerta de madera protegida +Protected Steel Door=Puerta de hierro protegida +Protected Trapdoor=Trampilla Protegida +Protected Steel Trapdoor=Trampilla de hierro protegida +Protected Chest=Cofre protegido +To Chest=Al cofre +To Inventory=Al inventario +Protected Chest (@1)=Cofre protegido (@1) + +### init.lua ### +-- Protector interface --=-- Interfaz del protector -- +PUNCH node to show protected area=nodo de perforación para mostrar el área protegida +USE for area check=Usar para chequeo del área +Members:=Miembros: +Close=Cerrar +Protection located at: @1=Protección ubicada en: @1 +Members: @1.=Miembros: @1. +This area is not protected.=Esta área no está protegida. +You can build here.=Puedes construir aquí. +Overlaps into above players protected area=Se superpone en el área protegida de los jugadores anteriores +Protection Block=Bloque de protección +Protection (owned by @1)=Protegido (Propiedad de @1) +Protection Logo=Logotipo de la protección +[MOD] Protector Redo loaded=[MOD] Protector recargado +Spawn @1 has been protected up to a @2 block radius.=Spawn @1 ha sido protegido hasta un radio de bloque @2. +This area is owned by @1=Esta área es propiedad de @1 + +### pvp.lua ### +[Protector] on_punchplayer called with nil objects=[Protector] on_punchplayer llamado con objetos nulos. +[Protector] pvp_protect not active, update your version of Minetest=[Protector] pvp_protect no está activo, actualiza tu versión de Minetest +[Protector] pvp_protect is disabled=[Protector] pvp_protect está deshabilitado + +### hud.lua ### +Owner: @1=Propietario: @1 + +### tool.lua ### +Protector Placer Tool (stand near protector, face direction and use)=Herramienta de colocación del protector (pararse cerca del protector, dirección de la cara y uso) +Protector already in place!=¡El protector ya está en este lugar! +No protectors available to place!=¡No hay protectores disponibles para colocar! +Protector placed at @1=Protector colocado en @1 diff --git a/protector/locale/protector.fr.tr b/protector/locale/protector.fr.tr new file mode 100644 index 0000000..70141bc --- /dev/null +++ b/protector/locale/protector.fr.tr @@ -0,0 +1,55 @@ +# textdomain: protector +# author: CodeXP and TenPlus1 +# last update: 2020/Jul/12 + +### admin.lua ### +Remove Protectors around players (separate names with spaces)=Retirer les protecteurs près des joueurs avec les noms fournis (noms séparés avec des espaces) += +Replace Protector Owner with name provided=Remplacer le propriétaire du protecteur par le nom fourni + = +Replacing Protector name '@1' with '@2'= +Show protected areas of your nearby protectors=Affichez les zones protégées de vos protecteurs à proximité +Protector Names to remove: @1=Noms de protecteurs à supprimer: @1 +Name List Reset=Liste de noms réinitialiser + +### doors_chest.lua ### +Protected Wooden Door=Porte en bois protégée +Protected Steel Door=Porte en acier protégée +Protected Trapdoor=Trappe protégé +Protected Steel Trapdoor=Trap en acier protégé +Protected Chest=Coffre protégé +To Chest=Vers le coffre +To Inventory=Vers l'inventaire +Protected Chest (@1)=Coffre protégé (@1) + +### init.lua ### +-- Protector interface --=-- Interface Protector -- +PUNCH node to show protected area=TAPÉ le bloc pour afficher la zone protégée +USE for area check=UTILISER pour vérifier la zone +Members:=Membres: +Close=Fermer +Protection located at: @1=Protection située à: @1 +Members: @1.=Membres: @1. +This area is not protected.=msgstr "Cette zone n'est pas protégée. +You can build here.=Vous pouvez construire ici. +Overlaps into above players protected area=Vous chevauché une zone protégé. +Protection Block=Bloc de protection +Protection (owned by @1)=Protection (détenue par @1) +Protection Logo=Logo de protection +[MOD] Protector Redo loaded=[MOD] Protector Redo chargé +Spawn @1 has been protected up to a @2 block radius.= +This area is owned by @1=Cette zone appartient à @1! + +### pvp.lua ### +[Protector] on_punchplayer called with nil objects=[Protector] on_punchplayer appelé avec des objets nil +[Protector] pvp_protect not active, update your version of Minetest=[Protector] pvp_protect est désactivé, mettez à jour votre version de Minetest +[Protector] pvp_protect is disabled=[Protector] pvp_protect est désactivé + +### hud.lua ### +Owner: @1=Propriétaire: @1 + +### tool.lua ### +Protector Placer Tool (stand near protector, face direction and use)=Outil de placement du protecteur (se tenir près du protecteur, direction du visage et utilisation) +Protector already in place!=Protecteur déjà en place! +No protectors available to place!=Aucun protecteur disponible à placer! +Protector placed at @1=Protection située à: @1 diff --git a/protector/locale/protector.it.tr b/protector/locale/protector.it.tr new file mode 100644 index 0000000..e2f81c1 --- /dev/null +++ b/protector/locale/protector.it.tr @@ -0,0 +1,55 @@ +# textdomain: protector +# author: Xanthin and CodeXP +# last update: 2018/Jul/10 + +### admin.lua ### +Remove Protectors around players (separate names with spaces)=Elimina i protettori attorno ai giocatori (separa i nomi con gli spazi) += +Replace Protector Owner with name provided=Sostituisci il proprietario del protettore col nome fornito + = +Replacing Protector name '@1' with '@2'=Sostituzione del nome del protettore '@1' con '@2' +Show protected areas of your nearby protectors=Mostra le aree protette dei protettori vicino a te +Protector Names to remove: @1=Nomi dei protettori da eliminare: @1 +Name List Reset=Azzera l'elenco dei nomi + +### doors_chest.lua ### +Protected Wooden Door=Porta di legno protetta +Protected Steel Door=Porta d'acciaio protetta +Protected Trapdoor=Botola protetta +Protected Steel Trapdoor=Botola d'acciaio protetta +Protected Chest=Baule protetto +To Chest=Al baule +To Inventory=All'inventario +Protected Chest (@1)=Baule protetto (@1) + +### init.lua ### +-- Protector interface --=-- Interfaccia protettore -- +PUNCH node to show protected area=COLPISCI il nodo per mostrare l'area protetta +USE for area check=USA per controllare l'area +Members:=Membri: +Close=Chiudi +Protection located at: @1=Protezione collocata a: @1 +Members: @1.=Membri: @1. +This area is not protected.=Quest'area non è protetta. +You can build here.=Qui puoi costruire. +Overlaps into above players protected area=Si sovrappone ad un'area sovrastante protetta dai giocatori +Protection Block=Blocco di protezione +Protection (owned by @1)=Protezione (di proprietà di @1) +Protection Logo=Logo di protezione +[MOD] Protector Redo loaded=[MOD] Protector Redo caricato +Spawn @1 has been protected up to a @2 block radius.=Lo spawn @1 è stato protetto fino a un raggio di @2 blocchi. +This area is owned by @1=Quest'area è di proprietà di @1 + +### pvp.lua ### +[Protector] on_punchplayer called with nil objects=[Protector] on_punchplayer chiamato con oggetti nil +[Protector] pvp_protect not active, update your version of Minetest=[Protector] pvp_protect non attiva, aggiorna la tua versione di Minetest +[Protector] pvp_protect is disabled=[Protector] pvp_protect è disattivato + +### hud.lua ### +Owner: @1=Proprietario: @1 + +### tool.lua ### +Protector Placer Tool (stand near protector, face direction and use)=Strumento di posizionamento protettore (stai vicino al protettore, guarda la direzione e usa) +Protector already in place!=Protettore già presente! +No protectors available to place!=Nessun protettore disponibile da posizionare! +Protector placed at @1=Protettore posizionato a @1 diff --git a/protector/locale/protector.ru.tr b/protector/locale/protector.ru.tr new file mode 100644 index 0000000..fc6068e --- /dev/null +++ b/protector/locale/protector.ru.tr @@ -0,0 +1,55 @@ +# textdomain: protector +# author: CodeXP +# last update: 2018/Jul/10 + +### admin.lua ### +Remove Protectors around players (separate names with spaces)=Удалить защиту рядом с игроками (перечислить имена, разделяя пробелами) +=<список имён> +Replace Protector Owner with name provided=Заменить владельца защиты новым владельцем + =<имя владельца> <имя нового владельца> +Replacing Protector name '@1' with '@2'=Заменяется владелец защиты с '@1' на '@2' +Show protected areas of your nearby protectors=Показать ближайшие защищённые территории +Protector Names to remove: @1=Имена, подлежащие удалению: @1 +Name List Reset=Очистить список имён + +### doors_chest.lua ### +Protected Wooden Door=Защищённая яблоневая дверь +Protected Steel Door=Защищённая стальная дверь +Protected Trapdoor=Защищённый яблоневый люк +Protected Steel Trapdoor=Защищённый стальной люк +Protected Chest=Защищённый сундук +To Chest=В сундук +To Inventory=В инвентрарь +Protected Chest (@1)=Защищённый сундук (@1) + +### init.lua ### +-- Protector interface --=-- Настройка защиты -- +PUNCH node to show protected area=СТУКНУТЬ узел для подсветки защищённой территории +USE for area check=ЛКМ для проверки защищённой территории +Members:=Участники: +Close=Закрыть +Protection located at: @1=Защита находится на координатах @1 +Members: @1.=Участники: @1. +This area is not protected.=Территория свободна. +You can build here.=Здесь можно ставить блоки. +Overlaps into above players protected area=Защитный блок не может быть установлен: пересечение с областями, защищёнными другими игроками +Protection Block=Защитный блок +Protection (owned by @1)=Защита игрока @1 +Protection Logo=Защитный знак +[MOD] Protector Redo loaded=[МОД] Protector Redo загружен +Spawn @1 has been protected up to a @2 block radius.=Спаун @1 защищён в радиусе @2 блока. +This area is owned by @1=Эта территория пренадлежит @1 + +### pvp.lua ### +[Protector] on_punchplayer called with nil objects=[Защита] on_punchplayer вызвана с нулевыми объектами +[Protector] pvp_protect not active, update your version of Minetest=[Защита] pvp_protect неактивен, обновите версию Minetest +[Protector] pvp_protect is disabled=[Защита] pvp_protect отключён + +### hud.lua ### +Owner: @1=Владелец: @1 + +### tool.lua ### +Protector Placer Tool (stand near protector, face direction and use)=Инструмент установки защиты (встаньте рядом с защитой, повернитесь в нужном направлении и используйте) +Protector already in place!=Защита уже установлена! +No protectors available to place!=У вас нет защитных блоков в инвентаре! +Protector placed at @1=Защита находится на координатах @1 diff --git a/protector/locale/protector.tr.tr b/protector/locale/protector.tr.tr new file mode 100644 index 0000000..51e8fb3 --- /dev/null +++ b/protector/locale/protector.tr.tr @@ -0,0 +1,55 @@ +# textdomain: protector +# author: CodeXP and TenPlus1 +# last update: 2020/Jul/12 + +### admin.lua ### +Remove Protectors around players (separate names with spaces)=Ismi verilen oyuncuların yanındaki korumaları kaldır. (İsimleri boşlukla ayır) += +Replace Protector Owner with name provided=Koruyucu Sahibini belirtilen adla değiştirin + = +Replacing Protector name '@1' with '@2'='@ 1' Koruyucu adını '@ 2' ile değiştirin +Show protected areas of your nearby protectors=Yakındaki koruyucuların korunan alanlarını göster +Protector Names to remove: @1=Silinecek korumaların isimleri: @1 +Name List Reset=İsim listesini sıfırla + +### doors_chest.lua ### +Protected Wooden Door=Korumalı ahşap kapı +Protected Steel Door=Korumalı çelik kapı +Protected Trapdoor=Korumalı tuzak kapısı +Protected Steel Trapdoor=Korumalı çelik tuzak kapısı +Protected Chest=Korumalı sandık +To Chest=Sandığa +To Inventory=Envantere +Protected Chest (@1)=Korumalı sandık (@1) + +### init.lua ### +-- Protector interface --=-- Koruyucu arayüz -- +PUNCH node to show protected area=Korunan alanı göstermek için yumruk +USE for area check=Bölge kontrolü için kullan +Members:=Üyeler +Close=Kapat +Protection located at: @1=Korumanın bulunduğu yer @1 +Members: @1.=Üyeler @1. +This area is not protected.=Bu alan korumalı değildir. +You can build here.=Buraya inşaa edebilirsiniz. +Overlaps into above players protected area=Yukarıdaki oyuncuların koruma alanı ile çakışıyor +Protection Block=Koruma kutusu +Protection (owned by @1)=Koruma (@1 sahibidir) +Protection Logo=Koruma arması +[MOD] Protector Redo loaded=[MOD] Protector Redo yüklendi +Spawn @1 has been protected up to a @2 block radius.=Spawn @1, @2 blok yarıçapa kadar korunur. +This area is owned by @1=Burasının sahibi @1! + +### pvp.lua ### +[Protector] on_punchplayer called with nil objects=[Protector] on_punchplayer boş objelerle çağrıldı +[Protector] pvp_protect not active, update your version of Minetest=[Protector] pvp_protect aktif değil, Minetest sürümünüzü güncelleyin. +[Protector] pvp_protect is disabled=[Protector] pvp_protect kapatıldı. + +### hud.lua ### +Owner: @1=Sahip: @1 + +### tool.lua ### +Protector Placer Tool (stand near protector, face direction and use)=Koruyucu Yerleştirme Aleti (koruyucunun yanında durun, yüz yönü ve kullanım) +Protector already in place!=Koruyucu zaten yerinde! +No protectors available to place!=Yerleştirilecek koruyucu yok! +Protector placed at @1=Korumanın bulunduğu yer @1 diff --git a/protector/locale/ru.po b/protector/locale/ru.po index 149082f..19673bf 100644 --- a/protector/locale/ru.po +++ b/protector/locale/ru.po @@ -19,10 +19,8 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" #: admin.lua -#, fuzzy msgid "Remove Protectors around players (separate names with spaces)" -msgstr "" -"Удалить защиту рядом с игроками (перечислить имена, разделяя пробелами)" +msgstr "Удалить защиту рядом с игроками (перечислить имена, разделяя пробелами)" #: admin.lua msgid "" @@ -72,18 +70,6 @@ msgstr "Защищенный стальной люк" msgid "Protected Chest" msgstr "Защищенный сундук" -#: doors_chest.lua -msgid "@1 moves stuff to protected chest at @2" -msgstr "@1 перемещает вещи в защищенный сундук на координатах @2" - -#: doors_chest.lua -msgid "@1 takes stuff from protected chest at @2" -msgstr "@1 берет вещи из защищенного сундука на координатах @2" - -#: doors_chest.lua -msgid "@1 moves stuff inside protected chest at @2" -msgstr "@1 перемещает вещи внутри защищенного сундука на координатах @2" - #: doors_chest.lua msgid "To Chest" msgstr "В сундук" diff --git a/protector/locale/template.pot b/protector/locale/template.pot index f8e095b..c893051 100644 --- a/protector/locale/template.pot +++ b/protector/locale/template.pot @@ -70,18 +70,6 @@ msgstr "" msgid "Protected Chest" msgstr "" -#: doors_chest.lua -msgid "@1 moves stuff to protected chest at @2" -msgstr "" - -#: doors_chest.lua -msgid "@1 takes stuff from protected chest at @2" -msgstr "" - -#: doors_chest.lua -msgid "@1 moves stuff inside protected chest at @2" -msgstr "" - #: doors_chest.lua msgid "To Chest" msgstr "" diff --git a/protector/locale/tr.po b/protector/locale/tr.po index d77f9c0..3434114 100644 --- a/protector/locale/tr.po +++ b/protector/locale/tr.po @@ -19,10 +19,8 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" #: admin.lua -#, fuzzy msgid "Remove Protectors around players (separate names with spaces)" -msgstr "" -"Ismi verilen oyuncuların yanındaki korumaları kaldır. (İsimleri boşlukla " +msgstr "Ismi verilen oyuncuların yanındaki korumaları kaldır. (İsimleri boşlukla " "ayır)" #: admin.lua @@ -73,19 +71,6 @@ msgstr "Korumalı çelik tuzak kapısı" msgid "Protected Chest" msgstr "Korumalı sandık" -#: doors_chest.lua -msgid "@1 moves stuff to protected chest at @2" -msgstr "@1 korumalı sandığa birşeyler koydu @2" - -#: doors_chest.lua -msgid "@1 takes stuff from protected chest at @2" -msgstr "@1 korumalı sandıktan birşeyler aldı @2" - -#: doors_chest.lua -#, fuzzy -msgid "@1 moves stuff inside protected chest at @2" -msgstr "@1 korumalı sandığa içinde bir şeyler taşındı @2" - #: doors_chest.lua msgid "To Chest" msgstr "Sandığa" diff --git a/protector/mod.conf b/protector/mod.conf index 8eb0aa8..774f1a1 100644 --- a/protector/mod.conf +++ b/protector/mod.conf @@ -1 +1,3 @@ -name = protector \ No newline at end of file +name = protector +description = Lets players craft special blocks to protect their builds or disable PVP in areas. +optional_depends = default, intllib, lucky_block, mesecons_mvps, playerfactions diff --git a/protector/settingtypes.txt b/protector/settingtypes.txt new file mode 100644 index 0000000..7fe8446 --- /dev/null +++ b/protector/settingtypes.txt @@ -0,0 +1,32 @@ +# Size of protected area around protection node limiting player interaction +protector_radius (Protector Radius [max 22]) int 5 + +# Flips player around when accessing protected area to stop lag griefing +protector_flip (Protector Flip) bool false + +# Hurts player by amount entered when accessing protected area, 0 to disable +protector_hurt (Protector Hurt) int 0 + +# Sets a protected area around spawn by node radius given +protector_spawn (Protector Spawn) int 0 + +# Enables PVP inside of protected areas +protector_pvp (Protector PVP) bool false + +# When true will allow PVP inside protected spawn area +protector_pvp_spawn (Protector PVP Spawn) int 0 + +# When true will allow PVP inside all protected areas at night time only +protector_night_pvp (Protector Night PVP) bool false + +# Interval in seconds that protection field is shown +protector_show_interval (Protector Show Interval) int 5 + +# Interval in seconds that HUD ownership text is updated, 0 to disable +protector_hud_interval (Protector HUD Interval) int 5 + +# Enables craft recipe for protection block +protector_recipe (Enable Protector recipe) bool true + +# Enables protection messages in player chat +protector_msg (Enable Protector Messages) bool true diff --git a/protector/tool.lua b/protector/tool.lua index 0a4fe12..14570a6 100644 --- a/protector/tool.lua +++ b/protector/tool.lua @@ -1,135 +1,164 @@ - --- protector placement tool (thanks to Shara for code and idea) - --- get protection radius -local r = tonumber(minetest.settings:get("protector_radius")) or 5 - -minetest.register_craftitem("protector:tool", { - description = "Protector Placer Tool (stand near protector, face direction and use)", - inventory_image = "protector_display.png^protector_logo.png", - stack_max = 1, - - on_use = function(itemstack, user, pointed_thing) - - local name = user:get_player_name() - - -- check for protector near player (2 block radius) - local pos = user:get_pos() - local pp = minetest.find_nodes_in_area( - vector.subtract(pos, 2), vector.add(pos, 2), - {"protector:protect", "protector:protect2"}) - - if #pp == 0 then return end -- none found - - pos = pp[1] -- take position of first protector found - - -- get members on protector - local meta = minetest.get_meta(pos) - local members = meta:get_string("members") or "" - - -- get direction player is facing - local dir = minetest.dir_to_facedir( user:get_look_dir() ) - local vec = {x = 0, y = 0, z = 0} - local gap = (r * 2) + 1 - local pit = user:get_look_pitch() - - -- set placement coords - if pit > 1.2 then - vec.y = gap -- up - elseif pit < -1.2 then - vec.y = -gap -- down - elseif dir == 0 then - vec.z = gap -- north - elseif dir == 1 then - vec.x = gap -- east - elseif dir == 2 then - vec.z = -gap -- south - elseif dir == 3 then - vec.x = -gap -- west - end - - -- new position - pos.x = pos.x + vec.x - pos.y = pos.y + vec.y - pos.z = pos.z + vec.z - - -- does placing a protector overlap existing area - if not protector.can_dig(r * 2, pos, user:get_player_name(), true, 3) then - - minetest.chat_send_player(name, - "Overlaps into above players protected area") - - return - end - - -- does a protector already exist ? - if #minetest.find_nodes_in_area( - vector.subtract(pos, 1), vector.add(pos, 1), - {"protector:protect", "protector:protect2"}) > 0 then - - minetest.chat_send_player(name, "Protector already in place!") - return - end - - -- do we have protectors to use ? - local nod - local inv = user:get_inventory() - - if not inv:contains_item("main", "protector:protect") - and not inv:contains_item("main", "protector:protect2") then - minetest.chat_send_player(name, "No protectors available to place!") - return - end - - -- take protector (block first then logo) - if inv:contains_item("main", "protector:protect") then - - inv:remove_item("main", "protector:protect") - nod = "protector:protect" - - elseif inv:contains_item("main", "protector:protect2") then - - inv:remove_item("main", "protector:protect2") - nod = "protector:protect2" - end - - -- do not replace containers with inventory space - local inv = minetest.get_inventory({type = "node", pos = pos}) - - if inv then - minetest.chat_send_player(name, - "Cannot place protector, container at " .. minetest.pos_to_string(pos)) - return - end - - -- place protector - minetest.set_node(pos, {name = nod, param2 = 1}) - - -- set protector metadata - local meta = minetest.get_meta(pos) - - meta:set_string("owner", name) - meta:set_string("infotext", "Protection (owned by " .. name .. ")") - - -- copy members across if holding sneak when using tool - if user:get_player_control().sneak then - meta:set_string("members", members) - else - meta:set_string("members", "") - end - - minetest.chat_send_player(name, - "Protector placed at " .. minetest.pos_to_string(pos)) - - end, -}) - --- tool recipe -minetest.register_craft({ - output = "protector:tool", - recipe = { - {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, - {"default:steel_ingot", "protector:protect", "default:steel_ingot"}, - {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, - } -}) + +-- protector placement tool (thanks to Shara for code and idea) + +local S = protector.intllib + +-- get protection radius +local r = tonumber(minetest.settings:get("protector_radius")) or 5 + +-- radius limiter (minetest cannot handle node volume of more than 4096000) +if r > 22 then r = 22 end + +minetest.register_craftitem("protector:tool", { + description = S("Protector Placer Tool (stand near protector, face direction and use)"), + inventory_image = "protector_display.png^protector_logo.png", + stack_max = 1, + + on_use = function(itemstack, user, pointed_thing) + + local name = user:get_player_name() + + -- check for protector near player (2 block radius) + local pos = user:get_pos() + local pp = minetest.find_nodes_in_area( + vector.subtract(pos, 2), vector.add(pos, 2), + {"protector:protect", "protector:protect2", "protector:protect_hidden"}) + + if #pp == 0 then return end -- none found + + pos = pp[1] -- take position of first protector found + + -- get members on protector + local meta = minetest.get_meta(pos) + local members = meta:get_string("members") or "" + + -- get direction player is facing + local dir = minetest.dir_to_facedir( user:get_look_dir() ) + local vec = {x = 0, y = 0, z = 0} + local gap = (r * 2) + 1 + local pit = user:get_look_vertical() + + -- set placement coords + if pit > 1.2 then + vec.y = -gap -- up + elseif pit < -1.2 then + vec.y = gap -- down + elseif dir == 0 then + vec.z = gap -- north + elseif dir == 1 then + vec.x = gap -- east + elseif dir == 2 then + vec.z = -gap -- south + elseif dir == 3 then + vec.x = -gap -- west + end + + -- new position + pos.x = pos.x + vec.x + pos.y = pos.y + vec.y + pos.z = pos.z + vec.z + + -- does placing a protector overlap existing area + if not protector.can_dig(r * 2, pos, user:get_player_name(), true, 3) then + + minetest.chat_send_player(name, + S("Overlaps into above players protected area")) + + return + end + + -- does a protector already exist ? + if #minetest.find_nodes_in_area( + vector.subtract(pos, 1), vector.add(pos, 1), + {"protector:protect", "protector:protect2", + "protector:protect_hidden"}) > 0 then + + minetest.chat_send_player(name, S("Protector already in place!")) + + return + end + + -- do we have protectors to use ? + local nod + local inv = user:get_inventory() + + if not inv:contains_item("main", "protector:protect") + and not inv:contains_item("main", "protector:protect2") then + + minetest.chat_send_player(name, + S("No protectors available to place!")) + + return + end + + -- take protector (block first then logo) + if inv:contains_item("main", "protector:protect") then + + inv:remove_item("main", "protector:protect") + + nod = "protector:protect" + + elseif inv:contains_item("main", "protector:protect2") then + + inv:remove_item("main", "protector:protect2") + + nod = "protector:protect2" + end + + -- do not replace containers with inventory space + local inv = minetest.get_inventory({type = "node", pos = pos}) + + if inv then + minetest.chat_send_player(name, + S("Cannot place protector, container at") .. + " " .. minetest.pos_to_string(pos)) + return + end + + -- protection check for other mods like Areas + if minetest.is_protected(pos, name) then + minetest.chat_send_player(name, + S("Cannot place protector, already protected at") .. + " " .. minetest.pos_to_string(pos)) + return + end + + -- place protector + minetest.set_node(pos, {name = nod, param2 = 1}) + + -- set protector metadata + local meta = minetest.get_meta(pos) + + meta:set_string("owner", name) + meta:set_string("infotext", "Protection (owned by " .. name .. ")") + + -- copy members across if holding sneak when using tool + if user:get_player_control().sneak then + meta:set_string("members", members) + else + meta:set_string("members", "") + end + + minetest.chat_send_player(name, + S("Protector placed at") .. + " " .. minetest.pos_to_string(pos)) + + end, +}) + +-- tool recipe +local df = "default:steel_ingot" + +if not minetest.registered_items[df] then + df = "mcl_core:iron_ingot" +end + + +minetest.register_craft({ + output = "protector:tool", + recipe = { + {df, df, df}, + {df, "protector:protect", df}, + {df, df, df}, + } +}) diff --git a/teleport_potion/README.md b/teleport_potion/README.md index acf46cf..96f647f 100644 --- a/teleport_potion/README.md +++ b/teleport_potion/README.md @@ -7,7 +7,8 @@ https://forum.minetest.net/viewtopic.php?f=9&t=9234 Change log: -- 1.1 - Using 0.4.16+ code changes, can only teleport players now +- 1.2 - New teleport pad texture, code tweaks to work with minetest 5.x +- 1.1 - Using 0.4.16+ code changes, can only teleport players now, added MineClone2 crafts and spanish translation - 1.0 - Added changes by maybe_dragon to bookmark teleport destination before using pads and potions - 0.9 - Update to newer functions, requires Minetest 0.4.16 to work. - 0.8 - Teleport pads now have arrows showing direction player will face after use diff --git a/teleport_potion/depends.txt b/teleport_potion/depends.txt index 8a8d2a2..f06ddbb 100644 --- a/teleport_potion/depends.txt +++ b/teleport_potion/depends.txt @@ -1,3 +1,4 @@ -default +default? intllib? -lucky_block? \ No newline at end of file +lucky_block? +mcl_core? diff --git a/teleport_potion/init.lua b/teleport_potion/init.lua index ce4ef93..b990f3c 100644 --- a/teleport_potion/init.lua +++ b/teleport_potion/init.lua @@ -1,24 +1,30 @@ ---= Teleport Potion mod by TenPlus1 +--= Teleport Potion mod by TenPlus1 (SFX are license free) + +-- Craft teleport potion or pad, use to bookmark location, place to open +-- portal or place pad, portals show a blue flame that you can walk into +-- before it closes (10 seconds), potions can also be thrown for local teleport. --- Create teleport potion or pad, place then right-click to enter coords --- and step onto pad or walk into the blue portal light, portal closes after --- 10 seconds, pad remains, potions are throwable... SFX are license Free... -- Load support for intllib. local MP = minetest.get_modpath(minetest.get_current_modname()) -local S, NS = dofile(MP.."/intllib.lua") +local S = minetest.get_translator and minetest.get_translator("teleport_potion") or + dofile(MP .. "/intllib.lua") +-- check for MineClone2 +local mcl = minetest.get_modpath("mcl_core") -- max teleport distance local dist = tonumber(minetest.settings:get("map_generation_limit") or 31000) -- creative check local creative_mode_cache = minetest.settings:get_bool("creative_mode") + local function is_creative(name) return creative_mode_cache or minetest.check_player_privs(name, {creative = true}) end +-- make sure coordinates are valid local check_coordinates = function(str) if not str or str == "" then @@ -51,9 +57,9 @@ local check_coordinates = function(str) return {x = x, y = y, z = z} end - -- particle effects local function tp_effect(pos) + minetest.add_particlespawner({ amount = 20, time = 0.25, @@ -67,7 +73,7 @@ local function tp_effect(pos) maxexptime = 1, minsize = 0.5, maxsize = 1.5, - texture = "particle.png", + texture = "teleport_potion_particle.png", glow = 15, }) end @@ -75,22 +81,21 @@ end local teleport_destinations = {} local function set_teleport_destination(playername, dest) + teleport_destinations[playername] = dest + tp_effect(dest) + minetest.sound_play("portal_open", { - pos = dest, - gain = 1.0, - max_hear_distance = 10 - }) + pos = dest, gain = 1.0, max_hear_distance = 10}, true) end --------------------------------------------------------------------------------- --- Teleport portal --------------------------------------------------------------------------------- minetest.register_node("teleport_potion:portal", { drawtype = "plantlike", tiles = { - {name="portal.png", + { + name = "teleport_potion_portal.png", animation = { type = "vertical_frames", aspect_w = 16, @@ -107,6 +112,7 @@ minetest.register_node("teleport_potion:portal", { waving = 1, sunlight_propagates = true, damage_per_second = 1, -- walking into portal hurts player + groups = {not_in_creative_inventory = 1}, -- start timer when portal appears on_construct = function(pos) @@ -117,18 +123,14 @@ minetest.register_node("teleport_potion:portal", { on_timer = function(pos) minetest.sound_play("portal_close", { - pos = pos, - gain = 1.0, - max_hear_distance = 10 - }) + pos = pos, gain = 1.0, max_hear_distance = 10}, true) minetest.remove_node(pos) end, on_blast = function() end, - drop = {}, + drop = {} }) - -- Throwable potion local function throw_potion(itemstack, player) @@ -159,21 +161,23 @@ local function throw_potion(itemstack, player) obj:get_luaentity().player = player end - +-- potion entity local potion_entity = { physical = true, visual = "sprite", visual_size = {x = 1.0, y = 1.0}, - textures = {"potion.png"}, - collisionbox = {0,0,0,0,0,0}, + textures = {"teleport_potion_potion.png"}, + collisionbox = {-0.1,-0.1,-0.1,0.1,0.1,0.1}, lastpos = {}, - player = "", + player = "" } potion_entity.on_step = function(self, dtime) if not self.player then + self.object:remove() + return end @@ -199,7 +203,7 @@ potion_entity.on_step = function(self, dtime) pos = self.lastpos, gain = 1.0, max_hear_distance = 5 - }) + }, true) tp_effect(self.lastpos) end @@ -216,61 +220,76 @@ end minetest.register_entity("teleport_potion:potion_entity", potion_entity) - --------------------------------------------------------------------------------- --- Teleport potion --------------------------------------------------------------------------------- minetest.register_node("teleport_potion:potion", { - tiles = {"pad.png"}, + tiles = {"teleport_potion_potion.png"}, drawtype = "signlike", paramtype = "light", paramtype2 = "wallmounted", walkable = false, sunlight_propagates = true, description = S("Teleport Potion (use to set destination; place to open portal)"), - inventory_image = "potion.png", - wield_image = "potion.png", + inventory_image = "teleport_potion_potion.png", + wield_image = "teleport_potion_potion.png", groups = {dig_immediate = 3, vessel = 1}, selection_box = {type = "wallmounted"}, on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type == "node" then set_teleport_destination(user:get_player_name(), pointed_thing.above) else throw_potion(itemstack, user) + if not is_creative(user:get_player_name()) then + itemstack:take_item() + return itemstack end end end, after_place_node = function(pos, placer, itemstack, pointed_thing) + local name = placer:get_player_name() local dest = teleport_destinations[name] + if dest then + minetest.set_node(pos, {name = "teleport_potion:portal"}) + local meta = minetest.get_meta(pos) + -- Set portal destination meta:set_int("x", dest.x) meta:set_int("y", dest.y) meta:set_int("z", dest.z) + -- Portal open effect and sound tp_effect(pos) + minetest.sound_play("portal_open", { - pos = pos, - gain = 1.0, - max_hear_distance = 10 - }) + pos = pos, gain = 1.0, max_hear_distance = 10}, true) else minetest.chat_send_player(name, S("Potion failed!")) minetest.remove_node(pos) minetest.add_item(pos, "teleport_potion:potion") end - end, + end }) -- teleport potion recipe +if mcl then +minetest.register_craft({ + output = "teleport_potion:potion", + recipe = { + {"", "mcl_core:diamond", ""}, + {"mcl_core:diamond", "mcl_potions:glass_bottle", "mcl_core:diamond"}, + {"", "mcl_core:diamond", ""}, + }, +}) +else minetest.register_craft({ output = "teleport_potion:potion", recipe = { @@ -279,14 +298,13 @@ minetest.register_craft({ {"", "default:diamond", ""}, }, }) +end --------------------------------------------------------------------------------- --- Teleport pad --------------------------------------------------------------------------------- local teleport_formspec_context = {} minetest.register_node("teleport_potion:pad", { - tiles = {"padd.png", "padd.png^[transformFY"}, + tiles = {"teleport_potion_pad.png", "teleport_potion_pad.png^[transformFY"}, drawtype = "nodebox", paramtype = "light", paramtype2 = "facedir", @@ -294,8 +312,8 @@ minetest.register_node("teleport_potion:pad", { walkable = true, sunlight_propagates = true, description = S("Teleport Pad (use to set destination; place to open portal)"), - inventory_image = "padd.png", - wield_image = "padd.png", + inventory_image = "teleport_potion_pad.png", + wield_image = "teleport_potion_pad.png", light_source = 5, groups = {snappy = 3}, node_box = { @@ -309,6 +327,7 @@ minetest.register_node("teleport_potion:pad", { -- Save pointed nodes coordinates as destination for further portals on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type == "node" then set_teleport_destination(user:get_player_name(), pointed_thing.above) end @@ -316,12 +335,15 @@ minetest.register_node("teleport_potion:pad", { -- Initialize teleport to saved location or the current position after_place_node = function(pos, placer, itemstack, pointed_thing) + local meta = minetest.get_meta(pos) local name = placer:get_player_name() local dest = teleport_destinations[name] + if not dest then dest = pos end + -- Set coords meta:set_int("x", dest.x) meta:set_int("y", dest.y) @@ -331,18 +353,18 @@ minetest.register_node("teleport_potion:pad", { dest.x, dest.y, dest.z)) minetest.sound_play("portal_open", { - pos = pos, - gain = 1.0, - max_hear_distance = 10 - }) + pos = pos, gain = 1.0, max_hear_distance = 10}, true) end, -- Show formspec depending on the players privileges. on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + local name = clicker:get_player_name() if minetest.is_protected(pos, name) then + minetest.record_protection_violation(pos, name) + return end @@ -354,8 +376,10 @@ minetest.register_node("teleport_potion:pad", { } local coords = coords.x .. "," .. coords.y .. "," .. coords.z local desc = meta:get_string("desc") + formspec = "field[desc;" .. S("Description") .. ";" .. minetest.formspec_escape(desc) .. "]" + -- Only allow privileged players to change coordinates if minetest.check_player_privs(name, "teleport") then formspec = formspec .. @@ -367,23 +391,32 @@ minetest.register_node("teleport_potion:pad", { coords = coords, desc = desc, } + minetest.show_formspec(name, "teleport_potion:set_destination", formspec) - end, + end }) -- Check and set coordinates minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "teleport_potion:set_destination" then return false end + local name = player:get_player_name() local context = teleport_formspec_context[name] + if not context then return false end + teleport_formspec_context[name] = nil + local meta = minetest.get_meta(context.pos) + -- Coordinates were changed if fields.coords and fields.coords ~= context.coords then + local coords = check_coordinates(fields.coords) + if coords then meta:set_int("x", coords.x) meta:set_int("y", coords.y) @@ -392,19 +425,32 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) minetest.chat_send_player(name, S("Teleport Pad coordinates failed!")) end end + -- Update infotext if fields.desc and fields.desc ~= "" then meta:set_string("desc", fields.desc) meta:set_string("infotext", S("Teleport to @1", fields.desc)) else local coords = minetest.string_to_pos("(" .. context.coords .. ")") + meta:set_string("infotext", S("Pad Active (@1,@2,@3)", coords.x, coords.y, coords.z)) end + return true end) -- teleport pad recipe +if mcl then +minetest.register_craft({ + output = "teleport_potion:pad", + recipe = { + {"teleport_potion:potion", "mcl_core:glass", "teleport_potion:potion"}, + {"mcl_core:glass", "mesecons:redstone", "mcl_core:glass"}, + {"teleport_potion:potion", "mcl_core:glass", "teleport_potion:potion"}, + }, +}) +else minetest.register_craft({ output = "teleport_potion:pad", recipe = { @@ -413,7 +459,7 @@ minetest.register_craft({ {"teleport_potion:potion", "default:glass", "teleport_potion:potion"} } }) - +end -- check portal & pad, teleport any entities on top minetest.register_abm({ @@ -452,7 +498,7 @@ minetest.register_abm({ pos = pos, gain = 1.0, max_hear_distance = 5 - }) + }, true) -- move player objs[n]:set_pos(target_coords) @@ -465,7 +511,7 @@ minetest.register_abm({ pos = target_coords, gain = 1.0, max_hear_distance = 5 - }) + }, true) -- rotate player to look in pad placement direction local rot = node.param2 @@ -481,22 +527,21 @@ minetest.register_abm({ yaw = 1.57 -- east end - objs[n]:set_look_yaw(yaw) + objs[n]:set_look_horizontal(yaw) end end end }) --- add lucky blocks - --- Teleport Potion mod +-- lucky blocks if minetest.get_modpath("lucky_block") then + lucky_block:add_blocks({ {"dro", {"teleport_potion:potion"}, 2}, {"tel"}, {"dro", {"teleport_potion:pad"}, 1}, - {"lig"}, + {"lig"} }) end diff --git a/teleport_potion/intllib.lua b/teleport_potion/intllib.lua index 6669d72..adb0f88 100644 --- a/teleport_potion/intllib.lua +++ b/teleport_potion/intllib.lua @@ -1,45 +1,3 @@ +-- Support for the old multi-load method +dofile(minetest.get_modpath("intllib").."/init.lua") --- Fallback functions for when `intllib` is not installed. --- Code released under Unlicense . - --- Get the latest version of this file at: --- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua - -local function format(str, ...) - local args = { ... } - local function repl(escape, open, num, close) - if escape == "" then - local replacement = tostring(args[tonumber(num)]) - if open == "" then - replacement = replacement..close - end - return replacement - else - return "@"..open..num..close - end - end - return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl)) -end - -local gettext, ngettext -if minetest.get_modpath("intllib") then - if intllib.make_gettext_pair then - -- New method using gettext. - gettext, ngettext = intllib.make_gettext_pair() - else - -- Old method using text files. - gettext = intllib.Getter() - end -end - --- Fill in missing functions. - -gettext = gettext or function(msgid, ...) - return format(msgid, ...) -end - -ngettext = ngettext or function(msgid, msgid_plural, n, ...) - return format(n==1 and msgid or msgid_plural, ...) -end - -return gettext, ngettext diff --git a/teleport_potion/locale/template.pot b/teleport_potion/locale/es.po similarity index 66% rename from teleport_potion/locale/template.pot rename to teleport_potion/locale/es.po index 3826160..ec65fcf 100644 --- a/teleport_potion/locale/template.pot +++ b/teleport_potion/locale/es.po @@ -19,36 +19,36 @@ msgstr "" #: init.lua msgid "Teleport Potion (place and right-click to enchant location)" -msgstr "" +msgstr "Poción de teletransporte (colocar y hacer clic derecho para encantar la ubicación)" #: init.lua msgid "Enter teleport coords (e.g. 200,20,-200)" -msgstr "" +msgstr "Inserta las coordenadas del teletransporte (Por ejemplo, 200,20, -200)" #: init.lua msgid "Right-click to enchant teleport location" -msgstr "" +msgstr "Haga clic derecho para encantar la ubicación de teletransporte" #: init.lua msgid "Potion failed!" -msgstr "" +msgstr "¡Poción fallida!" #: init.lua msgid "Teleport Pad (place and right-click to enchant location)" -msgstr "" +msgstr "Teleport Pad (Colocalo y haz clic derecho para encantar la ubicación)" #: init.lua msgid "Enter teleport coords (e.g. 200,20,-200,Home)" -msgstr "" +msgstr "Inserte las coordenadas del teletransporte (por ejemplo, 200,20, -200, Inicio)" #: init.lua msgid "Teleport to @1" -msgstr "" +msgstr "Teletransportarse a @1" #: init.lua msgid "Pad Active (@1,@2,@3)" -msgstr "" +msgstr "Pad activo" #: init.lua msgid "Teleport Pad coordinates failed!" -msgstr "" +msgstr "¡Coordenadas del Teleport Pad erroneas!" \ No newline at end of file diff --git a/teleport_potion/locale/teleport_potion.de.tr b/teleport_potion/locale/teleport_potion.de.tr new file mode 100644 index 0000000..1e64006 --- /dev/null +++ b/teleport_potion/locale/teleport_potion.de.tr @@ -0,0 +1,11 @@ +# textdomain: teleport_potion + +Teleport Potion (place and right-click to enchant location)=Teleportationstrank (platzieren und rechtsklicken,\n um Standort zu verzaubern) +Enter teleport coords (e.g. 200,20,-200)=Koordinaten eingeben (z.B. 200,20,-200) +Right-click to enchant teleport location=Rechtsklick um Teleportationsort zu verzaubern +Potion failed!=Trank misslungen! +Teleport Pad (place and right-click to enchant location)=Teleportationsfeld (platzieren und rechtsklicken,\n um Standort zu verzaubern) +Enter teleport coords (e.g. 200,20,-200,Home)=Koordinaten eingeben (z.B. 200,20,-200,Haus) +Teleport to @1=Teleportiere nach @1 +Pad Active (@1,@2,@3)=Feld aktiv (@1,@2,@3) +Teleport Pad coordinates failed!=Teleportationsfeldkoordinaten fehlgeschlagen! diff --git a/teleport_potion/locale/teleport_potion.es.tr b/teleport_potion/locale/teleport_potion.es.tr new file mode 100644 index 0000000..d2070eb --- /dev/null +++ b/teleport_potion/locale/teleport_potion.es.tr @@ -0,0 +1,11 @@ +# textdomain: teleport_potion + +Teleport Potion (place and right-click to enchant location)=Poción de teletransporte (colocar y hacer clic derecho para encantar la ubicación) +Enter teleport coords (e.g. 200,20,-200)=Inserta las coordenadas del teletransporte (Por ejemplo, 200,20, -200) +Right-click to enchant teleport location=Haga clic derecho para encantar la ubicación de teletransporte +Potion failed!=¡Poción fallida! +Teleport Pad (place and right-click to enchant location)=Teleport Pad (Colocalo y haz clic derecho para encantar la ubicación) +Enter teleport coords (e.g. 200,20,-200,Home)=Inserte las coordenadas del teletransporte (por ejemplo, 200,20, -200, Inicio) +Teleport to @1=Teletransportarse a @1 +Pad Active (@1,@2,@3)=Pad activo +Teleport Pad coordinates failed!=¡Coordenadas del Teleport Pad erroneas! diff --git a/teleport_potion/locale/teleport_potion.fr.tr b/teleport_potion/locale/teleport_potion.fr.tr new file mode 100644 index 0000000..46ee711 --- /dev/null +++ b/teleport_potion/locale/teleport_potion.fr.tr @@ -0,0 +1,11 @@ +# textdomain: teleport_potion + +Teleport Potion (place and right-click to enchant location)=Potion de téléportation (poser puis clic-droit pour enchanter l'emplacement) +Enter teleport coords (e.g. 200,20,-200)=Saisissez les coordonnées de téléportation (ex : 200,20,-200) +Right-click to enchant teleport location=Clic-droit pour enchanter l'emplacement de téléportation +Potion failed!=La potion n'a pas fonctionné ! +Teleport Pad (place and right-click to enchant location)=Pad de téléportation (poser puis clic-droit pour enchanter l'emplacement) +Enter teleport coords (e.g. 200,20,-200,Home)=Saisissez les coordonnées de téléportation (ex : 200,20,-200,Maison) +Teleport to @1=Téléportation vers @1 +Pad Active (@1,@2,@3)=Pad activé (@1,@,2,@3) +Teleport Pad coordinates failed!=Les coordonnées du pad sont inchangées ! diff --git a/teleport_potion/locale/template.txt b/teleport_potion/locale/template.txt new file mode 100644 index 0000000..8ac2b92 --- /dev/null +++ b/teleport_potion/locale/template.txt @@ -0,0 +1,9 @@ +# textdomain: teleport_potion + +Teleport Potion (place and right-click to enchant location)= +Enter teleport coords (e.g. 200,20,-200)= +Right-click to enchant teleport location= +Teleport Pad (place and right-click to enchant location)= +Enter teleport coords (e.g. 200,20,-200,Home)= +Pad Active (@1,@2,@3)= +Teleport Pad coordinates failed!= diff --git a/teleport_potion/mod.conf b/teleport_potion/mod.conf index 5afd872..27a4ea7 100644 --- a/teleport_potion/mod.conf +++ b/teleport_potion/mod.conf @@ -1 +1,4 @@ -name = teleport_potion \ No newline at end of file +name = teleport_potion +depends = +optional_depends = default, intllib, lucky_block, mcl_core +description = Adds craftable teleport potions (throwable) and teleport pads. diff --git a/teleport_potion/textures/pad.png b/teleport_potion/textures/pad.png deleted file mode 100644 index a9525ef78dba6134064d501e39eeeed80bde8479..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 334 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPGa4)6(az2X-zY3-Ut+qcc!wPW4! zqq{DgKmFkTtyixefBg7xa&87t8DmM1UoeBivm0q3PLj8~3quF1tOt<8S>O>_%)r1c z48n{Iv*t(u1=&kHeO=k_vB(LCsva~vumLFKSmGK{;+&tGo0?a`;2h-Y7~&sfrI4PY zn^lmSu25#EXP}@_TAZ1euHfnAuHY5m>aI{`W~8a3P*|FnlUY)!V5?wm%5{8A;~k)3 z@t!V@Asp9}6C9Y1wJ{|`9lh$x>0-Qd+0<5z29`_KR;T7P@Lcce>-#3c#+J67PeCIz zA%V|1-Joe{5U+&9orW&!pa!06J$-#<6UxN4f7vAB+99gwmvCBQ>KvX4a~K#NvC34J TTkm-Rw2Hyg)z4*}Q$iB}M2T-y diff --git a/teleport_potion/textures/padd.png b/teleport_potion/textures/padd.png deleted file mode 100644 index 0f7c9378bdbe2e2f849d822e38c08dcb8b14a001..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPGa2=EDUJ^kSRqV3ye?%J{L_|aV# z&I7r(UcGw!@uT*Ai4QKdVHJLo(~G zx7HOUe)>1{=fq2G_TdvNU|!JCrx+BRXc83fa?YV=`iaS=AtKKV0$$7i@S5$~l{4+l x#4mb9*FTy~GcI1}YJcwG?pD2sLxB&Z^&NbqDrdYDx&^eC!PC{xWt~$(695*#P`dyC diff --git a/teleport_potion/textures/teleport_potion_pad.png b/teleport_potion/textures/teleport_potion_pad.png new file mode 100644 index 0000000000000000000000000000000000000000..8ec690674b1aee7daa81dff7d485e428340af63b GIT binary patch literal 266 zcmV+l0rmcgP)Xw zaVTaW1+XwMFa&3t6RCRb)RQa_*8ZipAq>Z8RR#uzNmtM0X`5h`Vu9=SO*cd~Y|_;; zRpt(G@y#>OL&TYo6}3G-fZ)h6w4FSF=_)2<>#8Ij+MXX^V`IbA15tp`FzMNJ=sD?)j4YqD*3ZNR`UWDjDQ;n>E31<+>VHZYs60$uAx8ZjZRz2uWg2&FUU%!6+ z`UPh|!VOsg6T#$ACFy{kmLLEUm+= player:get_inventory():get_size("main") then + local arrow_index + if throw_itself then + arrow_index = bow_index + else + if bow_index >= player:get_inventory():get_size("main") then return false end - index = index + 1 + arrow_index = bow_index + 1 end - local arrow_stack = inventory:get_stack("main", index) + local arrow_stack = inventory:get_stack("main", arrow_index) local arrow = arrow_stack:get_name() - local playerpos = player:getpos() + local playerpos = player:get_pos() local pos = {x=playerpos.x,y=playerpos.y+1.5,z=playerpos.z} - local obj = (minetest.registered_items[itemstack:get_name()].spawn_arrow_entity or throwing.spawn_arrow_entity)(pos, arrow, player) + local obj = (def.spawn_arrow_entity or throwing.spawn_arrow_entity)(pos, arrow, player) local luaentity = obj:get_luaentity() + + -- Set custom data in the entity luaentity.player = player:get_player_name() if not luaentity.item then luaentity.item = arrow end + luaentity.data = {} + luaentity.timer = 0 + luaentity.toolranks = toolranks_data -- May be nil if toolranks is disabled if luaentity.on_throw then - if luaentity:on_throw(pos, player, arrow_stack, index, luaentity.data) == false then + if luaentity:on_throw(pos, player, arrow_stack, arrow_index, luaentity.data) == false then obj:remove() return false end end local dir = player:get_look_dir() - local velocity_factor = tonumber(minetest.settings:get("throwing.velocity_factor")) or 19 - local horizontal_acceleration_factor = tonumber(minetest.settings:get("throwing.horizontal_acceleration_factor")) or -3 local vertical_acceleration = tonumber(minetest.settings:get("throwing.vertical_acceleration")) or -10 + local velocity_factor = tonumber(minetest.settings:get("throwing.velocity_factor")) or 19 + local velocity_mode = minetest.settings:get("throwing.velocity_mode") or "strength" - obj:setvelocity({x=dir.x*velocity_factor, y=dir.y*velocity_factor, z=dir.z*velocity_factor}) - obj:setacceleration({x=dir.x*horizontal_acceleration_factor, y=vertical_acceleration, z=dir.z*horizontal_acceleration_factor}) - obj:setyaw(player:get_look_horizontal()-math.pi/2) + local velocity + if velocity_mode == "simple" then + velocity = velocity_factor + elseif velocity_mode == "momentum" then + velocity = def.strength * velocity_factor / luaentity.mass + else + velocity = def.strength * velocity_factor + end + + obj:set_velocity({ + x = dir.x * velocity, + y = dir.y * velocity, + z = dir.z * velocity + }) + obj:set_acceleration({x = 0, y = vertical_acceleration, z = 0}) + obj:set_yaw(player:get_look_horizontal()-math.pi/2) + + apply_realistic_acceleration(obj, luaentity.mass) if luaentity.on_throw_sound ~= "" then minetest.sound_play(luaentity.on_throw_sound or "throwing_sound", {pos=playerpos, gain = 0.5}) end if not minetest.settings:get_bool("creative_mode") then - if new_stack then - inventory:set_stack("main", index, new_stack) - else - local stack = inventory:get_stack("main", index) - stack:take_item() - inventory:set_stack("main", index, stack) - end + inventory:set_stack("main", arrow_index, new_stack) end return true end -local function arrow_step(self, dtime) +function throwing.arrow_step(self, dtime) + if not self.timer or not self.player then + self.object:remove() + return + end + self.timer = self.timer + dtime - local pos = self.object:getpos() + local pos = self.object:get_pos() local node = minetest.get_node(pos) local logging = function(message, level) minetest.log(level or "action", "[throwing] Arrow "..(self.item or self.name).." throwed by player "..self.player.." "..tostring(self.timer).."s ago "..message) end - local hit = function(pos, node, obj) + local hit = function(pos1, node1, obj) if obj then if obj:is_player() then if obj:get_player_name() == self.player then -- Avoid hitting the hitter @@ -109,7 +149,7 @@ local function arrow_step(self, dtime) player:get_inventory():add_item("main", self.item) end if self.on_hit_fails then - self:on_hit_fails(pos, player, self.data) + self:on_hit_fails(pos1, player, self.data) end end @@ -119,14 +159,14 @@ local function arrow_step(self, dtime) return end - if node and minetest.is_protected(pos, self.player) and not self.allow_protected then -- Forbid hitting nodes in protected areas - minetest.record_protection_violation(pos, self.player) + if node1 and minetest.is_protected(pos1, self.player) and not self.allow_protected then -- Forbid hitting nodes in protected areas + minetest.record_protection_violation(pos1, self.player) logging("hitted a node into a protected area") return end if self.on_hit then - local ret, reason = self:on_hit(pos, self.last_pos, node, obj, player, self.data) + local ret, reason = self:on_hit(pos1, self.last_pos, node1, obj, player, self.data) if ret == false then if reason then logging(": on_hit function failed for reason: "..reason) @@ -140,17 +180,33 @@ local function arrow_step(self, dtime) end if self.on_hit_sound then - minetest.sound_play(self.on_hit_sound, {pos = pos, gain = 0.8}) + minetest.sound_play(self.on_hit_sound, {pos = pos1, gain = 0.8}) end - if node then - logging("collided with node "..node.name.." at ("..pos.x..","..pos.y..","..pos.z..")") + + local identifier + if node1 then + identifier = "node " .. node1.name elseif obj then if obj:get_luaentity() then - logging("collided with luaentity "..obj:get_luaentity().name.." at ("..pos.x..","..pos.y..","..pos.z..")") + identifier = "luaentity " .. obj:get_luaentity().name elseif obj:is_player() then - logging("collided with player "..obj:get_player_name().." at ("..pos.x..","..pos.y..","..pos.z..")") + identifier = "player " .. obj:get_player_name() else - logging("collided with object at ("..pos.x..","..pos.y..","..pos.z..")") + identifier = "unknown object" + end + end + if identifier then + logging("collided with " .. identifier .. " at " .. minetest.pos_to_string(pos1) .. ")") + end + + -- Toolranks support: update bow uses + if self.toolranks then + local inventory = player:get_inventory() + -- Check that the player did not move the bow + local current_stack = inventory:get_stack("main", self.toolranks.index) + if current_stack:get_name() == self.toolranks.name then + local new_itemstack = toolranks.new_afteruse(current_stack, player, nil, {wear = self.toolranks.wear}) + inventory:set_stack("main", self.toolranks.index, new_itemstack) end end end @@ -200,14 +256,14 @@ local function arrow_step(self, dtime) wielded_light.update_light_by_item(self.item, self.object:get_pos()) end + apply_realistic_acceleration(self.object, self.mass) -- Physics: air friction + self.last_pos = pos -- Used by the build arrow end +-- Backwards compatibility function throwing.make_arrow_def(def) - def.timer = 0 - def.player = "" - def.on_step = arrow_step - def.data = {} + def.on_step = throwing.arrow_step return def end @@ -234,17 +290,18 @@ function throwing.register_arrow(name, def) if not def.groups.dig_immediate then def.groups.dig_immediate = 3 end + def.inventory_image = def.tiles[1] def.on_place = function(itemstack, placer, pointed_thing) if minetest.settings:get_bool("throwing.allow_arrow_placing") and pointed_thing.above then local playername = placer:get_player_name() if not minetest.is_protected(pointed_thing.above, playername) then - minetest.log("action", "Player "..playername.." placed arrow "..name.." at ("..pointed_thing.above.x..","..pointed_thing.above.y..","..pointed_thing.above.z..")") + minetest.log("action", "Player "..playername.." placed arrow "..name.." at "..minetest.pos_to_string(pointed_thing.above)) minetest.set_node(pointed_thing.above, {name = name}) itemstack:take_item() return itemstack else - minetest.log("warning", "Player "..playername.." tried to place arrow "..name.." into a protected area at ("..pointed_thing.above.x..","..pointed_thing.above.y..","..pointed_thing.above.z..")") + minetest.log("warning", "Player "..playername.." tried to place arrow "..name.." into a protected area at "..minetest.pos_to_string(pointed_thing.above)) minetest.record_protection_violation(pointed_thing.above, playername) return itemstack end @@ -276,7 +333,7 @@ function throwing.register_arrow(name, def) } minetest.register_node(registration_name, def) - minetest.register_entity(registration_name.."_entity", throwing.make_arrow_def{ + minetest.register_entity(registration_name.."_entity", { physical = false, visual = "wielditem", visual_size = {x = 0.125, y = 0.125}, @@ -289,39 +346,40 @@ function throwing.register_arrow(name, def) allow_protected = def.allow_protected, target = def.target, on_hit_fails = def.on_hit_fails, + on_step = throwing.arrow_step, item = name, + mass = def.mass or 1, }) - - if def.itemcraft then - minetest.register_craft({ - output = name.." "..tostring(def.craft_quantity or 1), - recipe = { - {def.itemcraft, "default:stick", "default:stick"} - } - }) - minetest.register_craft({ - output = name.." "..tostring(def.craft_quantity or 1), - recipe = { - { "default:stick", "default:stick", def.itemcraft} - } - }) - end end ---------- Bows ----------- +if use_toolranks and minetest.get_modpath("toolranks_extras") and toolranks_extras.register_tool_type then + toolranks_extras.register_tool_type("bow", S("bow"), S("Arrows thrown")) +end + function throwing.register_bow(name, def) + local enable_toolranks = use_toolranks and not def.no_toolranks + + def.name = name + if not def.allow_shot then def.allow_shot = function(player, itemstack, index) if index >= player:get_inventory():get_size("main") and not def.throw_itself then return false end - return throwing.is_arrow(itemstack) + return throwing.is_arrow(itemstack) or def.throw_itself end end + if not def.inventory_image then def.inventory_image = def.texture end + + if not def.strength then + def.strength = 20 + end + def.on_use = function(itemstack, user, pointed_thing) -- Cooldown local meta = itemstack:get_meta() @@ -348,25 +406,42 @@ function throwing.register_bow(name, def) minetest.after(def.delay or 0, function() -- Re-check that the arrow can be thrown. Overwrite the new_stack local old_new_stack = new_stack - res, new_stack = def.allow_shot(user, user:get_inventory():get_stack("main", arrow_index), arrow_index, true) - if not new_stack then - new_stack = old_new_stack - end + + local arrow_stack = user:get_inventory():get_stack("main", arrow_index) + + res, new_stack = def.allow_shot(user, arrow_stack, arrow_index, true) if not res then return end + if not new_stack then + new_stack = old_new_stack + end + if not new_stack then + arrow_stack:take_item() + new_stack = arrow_stack + end + -- Shoot arrow - if shoot_arrow(itemstack, user, bow_index, def.throw_itself, new_stack) then + local uses = 65535 / (def.uses or 50) + local toolranks_data + if enable_toolranks then + toolranks_data = { + name = itemstack:get_name(), + index = bow_index, + wear = uses + } + end + if shoot_arrow(def, toolranks_data, user, bow_index, def.throw_itself, new_stack) then if not minetest.settings:get_bool("creative_mode") then - itemstack:add_wear(65535 / (def.uses or 50)) + itemstack:add_wear(uses) end end if def.throw_itself then -- This is a bug. If we return ItemStack(nil), the player punches the entity, - -- and if the entity if a __builtin:item, it gets back to his inventory. + -- and if the entity is a __builtin:item, it gets back to his inventory. minetest.after(0.1, function() user:get_inventory():remove_item("main", itemstack) end) @@ -377,22 +452,11 @@ function throwing.register_bow(name, def) end) return itemstack end - minetest.register_tool(name, def) - if def.itemcraft then - -- Check for an override name - -- because an ``output = ":name"'' can't exist in a recipe - local output_name = name - if name:sub(1,1) == ":" then - output_name = name:sub(2) - end - minetest.register_craft({ - output = output_name, - recipe = { - {"farming:cotton", def.itemcraft, ""}, - {"farming:cotton", "", def.itemcraft}, - {"farming:cotton", def.itemcraft, ""}, - } - }) + if enable_toolranks then + def.original_description = def.original_description or def.description + def.description = toolranks.create_description(def.description) end + + minetest.register_tool(name, def) end diff --git a/throwing/locale/template.txt b/throwing/locale/template.txt new file mode 100644 index 0000000..d46b065 --- /dev/null +++ b/throwing/locale/template.txt @@ -0,0 +1,7 @@ +# textdomain: throwing + + +### init.lua ### + +Arrows thrown= +bow= diff --git a/throwing/locale/throwing.fr.tr b/throwing/locale/throwing.fr.tr new file mode 100644 index 0000000..c42ecdb --- /dev/null +++ b/throwing/locale/throwing.fr.tr @@ -0,0 +1,7 @@ +# textdomain: throwing + + +### init.lua ### + +Arrows thrown=Flèches lancées +bow=arc diff --git a/throwing/mod.conf b/throwing/mod.conf index e82e4bc..8cbd9e3 100644 --- a/throwing/mod.conf +++ b/throwing/mod.conf @@ -1 +1,3 @@ name = throwing +optional_depends = wielded_light, toolranks, toolranks_extras +description = Throwing library: provides an API for registering throwing and throwable things diff --git a/throwing_arrows/README.md b/throwing_arrows/README.md index b3dcdb5..8b42bd2 100644 --- a/throwing_arrows/README.md +++ b/throwing_arrows/README.md @@ -8,6 +8,7 @@ The settings are the following: ``` throwing.enable_arrow = true throwing.enable_golden_arrow = true +throwing.enable_diamond_arrow = true throwing.enable_fire_arrow = true throwing.enable_teleport_arrow = true throwing.enable_dig_arrow = true diff --git a/throwing_arrows/depends.txt b/throwing_arrows/depends.txt deleted file mode 100644 index 51f6307..0000000 --- a/throwing_arrows/depends.txt +++ /dev/null @@ -1,5 +0,0 @@ -throwing -default -farming -mesecons? -mesecons_button? diff --git a/throwing_arrows/init.lua b/throwing_arrows/init.lua index 52ac0ee..45fea5b 100644 --- a/throwing_arrows/init.lua +++ b/throwing_arrows/init.lua @@ -1,45 +1,72 @@ +-- Translation support +local S = minetest.get_translator("throwing_arrows") + +local function register_bow_craft(name, itemcraft) + minetest.register_craft({ + output = "throwing:" .. name, + recipe = { + {"farming:string", itemcraft, ""}, + {"farming:string", "", itemcraft}, + {"farming:string", itemcraft, ""}, + } + }) +end + throwing.register_bow(":throwing:bow_wood", { - itemcraft = "default:wood", - description = "Wooden Bow", + description = S("Wooden Bow"), texture = "throwing_bow_wood.png", - uses = 50 + uses = 50, + strength = .5 }) +register_bow_craft("bow_wood", "default:wood") + throwing.register_bow(":throwing:bow_stone", { - itemcraft = "default:cobble", - description = "Stone Bow", + description = S("Stone Bow"), texture = "throwing_bow_stone.png", - uses = 100 + uses = 100, + strength = .65 }) +register_bow_craft("bow_stone", "default:cobble") + throwing.register_bow(":throwing:bow_steel", { - itemcraft = "default:steel_ingot", - description = "Steel Bow", + description = S("Steel Bow"), texture = "throwing_bow_steel.png", - uses = 150 + uses = 150, + strength = .8 }) +register_bow_craft("bow_steel", "default:steel_ingot") + throwing.register_bow(":throwing:bow_bronze", { - itemcraft = "default:bronze_ingot", - description = "Bronze Bow", + description = S("Bronze Bow"), texture = "throwing_bow_bronze.png", - uses = 200 + uses = 200, + strength = .95 }) +register_bow_craft("bow_bronze", "default:bronze_ingot") + throwing.register_bow(":throwing:bow_gold", { - itemcraft = "default:gold_ingot", - description = "Gold Bow", + description = S("Gold Bow"), texture = "throwing_bow_gold.png", - uses = 250 + uses = 250, + strength = 1.1 }) +register_bow_craft("bow_gold", "default:gold_ingot") + throwing.register_bow(":throwing:bow_mese", { - itemcraft = "default:mese_crystal", - description = "Mese Bow", + description = S("Mese Bow"), texture = "throwing_bow_mese.png", - uses = 300 + uses = 300, + strength = 1.25 }) +register_bow_craft("bow_mese", "default:mese_crystal") + throwing.register_bow(":throwing:bow_diamond", { - itemcraft = "default:diamond", - description = "Diamond Bow", + description = S("Diamond Bow"), texture = "throwing_bow_diamond.png", - uses = 320 + uses = 320, + strength = 1.4 }) +register_bow_craft("bow_diamond", "default:diamond") local function get_setting(name) local value = minetest.settings:get_bool("throwing.enable_"..name) @@ -50,19 +77,53 @@ local function get_setting(name) end end +local function register_arrow_craft(name, itemcraft, craft_quantity) + minetest.register_craft({ + output = "throwing:"..name.." "..tostring(craft_quantity or 1), + recipe = { + {itemcraft, "default:stick", "default:stick"} + } + }) + minetest.register_craft({ + output = "throwing:"..name.." "..tostring(craft_quantity or 1), + recipe = { + { "default:stick", "default:stick", itemcraft} + } + }) +end + +local last_punch_times = {} + +local function arrow_punch(object, hitter, caps) + local time_from_last_punch = caps.full_punch_interval or 1 + local hitter_name = hitter:get_player_name() + local player_name = object:get_player_name() + if last_punch_times[hitter_name] then + if last_punch_times[hitter_name][player_name] then + time_from_last_punch = os.difftime(os.time(), last_punch_times[hitter_name][player_name]) + end + else + last_punch_times[hitter_name] = {} + end + if time_from_last_punch >= (caps.full_punch_interval or 1) then + last_punch_times[hitter_name][player_name] = os.time() + end + object:punch(hitter, time_from_last_punch, caps, nil) +end + if get_setting("arrow") then throwing.register_arrow("throwing:arrow", { - itemcraft = "default:steel_ingot", - craft_quantity = 16, - description = "Arrow", + description = S("Arrow"), tiles = {"throwing_arrow.png", "throwing_arrow.png", "throwing_arrow_back.png", "throwing_arrow_front.png", "throwing_arrow_2.png", "throwing_arrow.png"}, target = throwing.target_both, allow_protected = true, + mass = 1, on_hit_sound = "throwing_arrow", on_hit = function(self, pos, _, node, object, hitter) if object then - object:punch(hitter, 1, { - full_punch_interval = 1, + arrow_punch(object, hitter, { + full_punch_interval = 0.7, + max_drop_level = 1, damage_groups = {fleshy = 3} }) elseif node then @@ -72,44 +133,67 @@ if get_setting("arrow") then end end }) + register_arrow_craft("arrow", "default:steel_ingot", 16) end if get_setting("golden_arrow") then throwing.register_arrow("throwing:arrow_gold", { - itemcraft = "default:gold_ingot", - craft_quantity = 16, - description = "Golden Arrow", + description = S("Golden Arrow"), tiles = {"throwing_arrow_gold.png", "throwing_arrow_gold.png", "throwing_arrow_gold_back.png", "throwing_arrow_gold_front.png", "throwing_arrow_gold_2.png", "throwing_arrow_gold.png"}, target = throwing.target_object, allow_protected = true, on_hit_sound = "throwing_arrow", + mass = 2, on_hit = function(self, pos, _, _, object, hitter) - object:punch(hitter, 1, { - full_punch_interval = 1, + arrow_punch(object, hitter, { + full_punch_interval = 0.6, + max_drop_level = 1, damage_groups = {fleshy = 5} }) end }) + register_arrow_craft("arrow_gold", "default:gold_ingot", 16) +end + +if get_setting("diamond_arrow") then + throwing.register_arrow("throwing:arrow_diamond", { + description = S("Diamond Arrow"), + tiles = {"throwing_arrow_diamond.png", "throwing_arrow_diamond.png", "throwing_arrow_diamond_back.png", "throwing_arrow_diamond_front.png", "throwing_arrow_diamond_2.png", "throwing_arrow_diamond.png"}, + target = throwing.target_object, + allow_protected = true, + on_hit_sound = "throwing_arrow", + mass = .7, + on_hit = function(self, pos, _, _, object, hitter) + arrow_punch(object, hitter, { + full_punch_interval = 0.5, + max_drop_level = 1, + damage_groups = {fleshy = 7} + }) + end + }) + register_arrow_craft("arrow_diamond", "default:diamond", 4) end if get_setting("dig_arrow") then throwing.register_arrow("throwing:arrow_dig", { - itemcraft = "default:pick_wood", - description = "Dig Arrow", + description = S("Dig Arrow"), tiles = {"throwing_arrow_dig.png", "throwing_arrow_dig.png", "throwing_arrow_dig_back.png", "throwing_arrow_dig_front.png", "throwing_arrow_dig_2.png", "throwing_arrow_dig.png"}, target = throwing.target_node, + mass = 1, on_hit_sound = "throwing_dig_arrow", on_hit = function(self, pos, _, node, _, hitter) return minetest.dig_node(pos) end }) + register_arrow_craft("arrow_dig", "default:pick_wood") end if get_setting("dig_arrow_admin") then throwing.register_arrow("throwing:arrow_dig_admin", { - description = "Admin Dig Arrow", + description = S("Admin Dig Arrow"), tiles = {"throwing_arrow_dig.png", "throwing_arrow_dig.png", "throwing_arrow_dig_back.png", "throwing_arrow_dig_front.png", "throwing_arrow_dig_2.png", "throwing_arrow_dig.png"}, target = throwing.target_node, + mass = 1, on_hit = function(self, pos, _, node, _, _) minetest.remove_node(pos) end, @@ -119,35 +203,36 @@ end if get_setting("teleport_arrow") then throwing.register_arrow("throwing:arrow_teleport", { - itemcraft = "default:diamond", - description = "Teleport Arrow", + description = S("Teleport Arrow"), tiles = {"throwing_arrow_teleport.png", "throwing_arrow_teleport.png", "throwing_arrow_teleport_back.png", "throwing_arrow_teleport_front.png", "throwing_arrow_teleport_2.png", "throwing_arrow_teleport.png"}, allow_protected = true, + mass = 1, on_hit_sound = "throwing_teleport_arrow", on_hit = function(self, _, last_pos, _, _, hitter) if minetest.get_node(last_pos).name ~= "air" then - minetest.log("warning", "[throwing] BUG: node at last_pos was not air") + minetest.log("warning", "[throwing] BUG: node at "..minetest.pos_to_string(last_pos).." was not air") return end - if minetest.setting_getbool("throwing.allow_teleport_in_protected") == false then + if minetest.settings:get_bool("throwing.allow_teleport_in_protected") == false then return false end - hitter:moveto(last_pos) + hitter:move_to(last_pos) end }) + register_arrow_craft("arrow_teleport", "default:mese_crystal") end if get_setting("fire_arrow") then throwing.register_arrow("throwing:arrow_fire", { - itemcraft = "default:torch", - description = "Torch Arrow", + description = S("Torch Arrow"), tiles = {"throwing_arrow_fire.png", "throwing_arrow_fire.png", "throwing_arrow_fire_back.png", "throwing_arrow_fire_front.png", "throwing_arrow_fire_2.png", "throwing_arrow_fire.png"}, + mass = 1, on_hit_sound = "default_place_node", on_hit = function(self, pos, last_pos, _, _, hitter) if minetest.get_node(last_pos).name ~= "air" then - minetest.log("warning", "[throwing] BUG: node at last_pos was not air") + minetest.log("warning", "[throwing] BUG: node at "..minetest.pos_to_string(last_pos).." was not air") return end @@ -165,17 +250,18 @@ if get_setting("fire_arrow") then {type="node", under=r_pos, above=r_last_pos}) end }) + register_arrow_craft("arrow_fire", "default:torch") end if get_setting("build_arrow") then throwing.register_arrow("throwing:arrow_build", { - itemcraft = "default:obsidian_glass", - description = "Build Arrow", + description = S("Build Arrow"), tiles = {"throwing_arrow_build.png", "throwing_arrow_build.png", "throwing_arrow_build_back.png", "throwing_arrow_build_front.png", "throwing_arrow_build_2.png", "throwing_arrow_build.png"}, + mass = 1, on_hit_sound = "throwing_build_arrow", on_hit = function(self, pos, last_pos, _, _, hitter) if minetest.get_node(last_pos).name ~= "air" then - minetest.log("warning", "[throwing] BUG: node at last_pos was not air") + minetest.log("warning", "[throwing] BUG: node at "..minetest.pos_to_string(last_pos).." was not air") return end @@ -193,16 +279,16 @@ if get_setting("build_arrow") then {type="node", under=r_pos, above=r_last_pos}) end }) + register_arrow_craft("arrow_build", "default:obsidian_glass") end if get_setting("drop_arrow") then throwing.register_arrow("throwing:arrow_drop", { - itemcraft = "default:copper_ingot", - craft_quantity = 16, - description = "Drop Arrow", + description = S("Drop Arrow"), tiles = {"throwing_arrow_drop.png", "throwing_arrow_drop.png", "throwing_arrow_drop_back.png", "throwing_arrow_drop_front.png", "throwing_arrow_drop_2.png", "throwing_arrow_drop.png"}, on_hit_sound = "throwing_build_arrow", allow_protected = true, + mass = 1, on_throw = function(self, _, thrower, _, index, data) local inventory = thrower:get_inventory() if index >= inventory:get_size("main") or inventory:get_stack("main", index+1):get_name() == "" then @@ -216,9 +302,10 @@ if get_setting("drop_arrow") then minetest.item_drop(ItemStack(data.itemstack), hitter, last_pos) end, on_hit_fails = function(self, _, thrower, data) - if not minetest.setting_getbool("creative_mode") then + if not minetest.settings:get_bool("creative_mode") then thrower:get_inventory():set_stack("main", data.index, data.itemstack) end end }) + register_arrow_craft("arrow_drop", "default:copper_ingot", 16) end diff --git a/throwing_arrows/locale/template.txt b/throwing_arrows/locale/template.txt new file mode 100644 index 0000000..b1bf690 --- /dev/null +++ b/throwing_arrows/locale/template.txt @@ -0,0 +1,25 @@ +# textdomain: throwing_arrows + +# Translation template (replace this line with credits) +# Licence: MPL-2.0 + +## Bows +Wooden Bow= +Stone Bow= +Steel Bow= +Bronze Bow= +Gold Bow= +Mese Bow= +Diamond Bow= + + +## Arrows +Arrow= +Golden Arrow= +Diamond Arrow= +Dig Arrow= +Admin Dig Arrow= +Teleport Arrow= +Torch Arrow= +Build Arrow= +Drop Arrow= diff --git a/throwing_arrows/locale/throwing_arrows.fr.tr b/throwing_arrows/locale/throwing_arrows.fr.tr new file mode 100644 index 0000000..ed9557a --- /dev/null +++ b/throwing_arrows/locale/throwing_arrows.fr.tr @@ -0,0 +1,25 @@ +# textdomain: throwing_arrows + +# Translation template (replace this line with credits) +# Licence: MPL-2.0 + +## Bows +Wooden Bow=Arc en bois +Stone Bow=Arc en pierre +Steel Bow=Arc en fer +Bronze Bow=Arc en bronze +Gold Bow=Arc en or +Mese Bow=Arc en mese +Diamond Bow=Arc en diamant + + +## Arrows +Arrow=Flèche +Golden Arrow=Flèche en or +Diamond Arrow=Flèche en diamant +Dig Arrow=Flèche creuseuse +Admin Dig Arrow=Flèche creuseuse d’administrateur +Teleport Arrow=Flèche de téléportation +Torch Arrow=Flèche-torche +Build Arrow=Flèche de construction +Drop Arrow=Flèche de livraison diff --git a/throwing_arrows/mod.conf b/throwing_arrows/mod.conf index 7112236..47a821f 100644 --- a/throwing_arrows/mod.conf +++ b/throwing_arrows/mod.conf @@ -1 +1,4 @@ name = throwing_arrows +depends = throwing, default, farming +optional_depends = mesecons, mesecons_button +description = Bows and Arrows for the throwing mod diff --git a/throwing_arrows/textures/throwing_arrow_diamond.png b/throwing_arrows/textures/throwing_arrow_diamond.png new file mode 100644 index 0000000000000000000000000000000000000000..479b5f68a3158fec5d6f961ba8eeb8d8e4192632 GIT binary patch literal 3542 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 literal 0 HcmV?d00001 diff --git a/throwing_arrows/textures/throwing_arrow_diamond_2.png b/throwing_arrows/textures/throwing_arrow_diamond_2.png new file mode 100644 index 0000000000000000000000000000000000000000..73c3fb7e65f92d51fec8ffc8ea99e0152ee15754 GIT binary patch literal 3595 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 R#)bd@002ovPDHLkV1j6&-1z_i literal 0 HcmV?d00001 diff --git a/throwing_arrows/textures/throwing_arrow_diamond_back.png b/throwing_arrows/textures/throwing_arrow_diamond_back.png new file mode 100644 index 0000000000000000000000000000000000000000..a8a58e97356e37886a11edf849f5b6c76cb8ecfd GIT binary patch literal 3739 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 FV1j$C0SN#A literal 0 HcmV?d00001 diff --git a/throwing_arrows/textures/throwing_arrow_diamond_front.png b/throwing_arrows/textures/throwing_arrow_diamond_front.png new file mode 100644 index 0000000000000000000000000000000000000000..4a3a3b3a234472acc58331d60fb4837facd45a74 GIT binary patch literal 2175 zcmV-_2!QvAP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+U-|ew%#ZXd}kH21dtFC%Ml>XnH}`z)K9xu;x>dy<_J{;%y zqxmfREdKSmDx9$d>oFw?E}ZZCy%WOCg8Jx4)FwXjA44&Qm%db*$%f0|eOhSmd9%r0 zzJgtJLKbEm}`G7@fWGj+SdK3Ejhx z7XTsLKovU#0$8<5ZQz?BgggmL6_F+?CSAO7t4&&K+Kx`SvQ`yss%qNRjjftkGc~hr z-l;QWOj2)MyY=4Pv8h+bT8{aSfkA^u9WvU`VWSV92%lM}%rUAOGEb=&USU#LB(en#ypaz93`JgCtH)S0L6s9{+3ZHaQ^ zL=I*^jA{YmdJsTB)4?oTsg(|L2eaIX6SEMklmiaf4#a?9jY6`^3%hsZ{uH+a@BS=q z^gZO#f$mozmkx9vkoy+5@1VB)l3Tt2IxK`wp^yyvt?6V=Bc|=C`Si{6&$Q`hU--Sy zKYAgbYpmgQ6jWC1mce>sh>L+Fsnh8 zr_W@}R$_o;c{U-0dw@lu0&8@o)mY=0Enp2p6*`y-oj|oT zT`)5k1}<^r^y^=s1f5EeAVyvE{4JQU=Ize~;^vEfC_MgFn?4SV)ntd)W6@a9EU&eD zwFR+VR+hS8ZzyE-Ar#dj)H})W~VhbsxO@lX9f`< z%HBGHL@sOUgK;>|G=2`{KW$U~z0m*XLg%}oBOnFoIv{$GNoZ^gl-ojjf);E`zint$)=lbu5*K; zfa*;3p?U&?9%4cGs2yUhi|e`yL7w@RXE&YmJF;LD*xn0 z)ZOsfy0UodSLQLgcV%zUSHZ69*%g@0$m=Ra}JyodO>z_Y@U( zVKD@s33mZ2_&NgD{1+8SzZd!+TnJx6J?Hcvnc(c+?ksEw0004mX+uL$Nkc;*aB^>E zX>4Tx0C=2zkv&MmKpe$iQ^g{c4t5Z!kfAzR@C$L&DionYsTEpvFuC*#nlvOSE{=k0 z!NHHks)LKOt`4q(Aou~|;_9U6A|?JWDYS_3;J6>}?mh0_0Yam~RI_UgP&La)C*oo@ zw<`9$B7h-;Fph}COnokuO2Tt|-NVP%yBN>%KKJM7Q}QMQd?N8I(+!JwgLrz=(mC%F zhgnHdh|h^f4Z0xlBiCh@-#8Z?7Ib?> z)t?mr000+BL_t&t*JEJ74-}X{Bx?vh5~2nl003t40s?2F6}SKZ002ovPDHLkV1jbY B{2c%Q literal 0 HcmV?d00001 diff --git a/throwing_arrows/textures/throwing_arrow_teleport.png b/throwing_arrows/textures/throwing_arrow_teleport.png index e0b6f080ac9b74c338e92f430419fc613f453cee..069f7f94da15f0e21f6d4d0528f0413df3e09b37 100644 GIT binary patch delta 3460 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 delta 111 zcmZpZ?q-~zoWURz;1lA?z`(%x=YNPYbGkOm#EBC(Z{GZ{OT-o=S`y?J%;50sMjDW# z?&;zf!V#UEpdih{u#utTAlH#5CohKwEGZmZ(#;H;Bqmv@>{Vf6aQ0@t*&!%0AE<@F M)78&qol`;+09v>p@c;k- diff --git a/throwing_arrows/textures/throwing_arrow_teleport_2.png b/throwing_arrows/textures/throwing_arrow_teleport_2.png index 1a3c6fe9831bb8fb77de6dd873e19711f01a9183..2ec4e7b4d988802f831a23b14a8d5ca4c97de9b1 100644 GIT binary patch literal 3727 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%0D06NFic-VyU9kRYs(0B_Oo(V$pTOO z@-LbbLD#yo8Epg=jg7$oH;5nbL8T6$5eo;0I6`7fDH2hsoj%F3oQYJJ0-paF)q zsa}xlg}gmHsTClZY+4%%*e#EwP6I1xJBY6|^aeEZV75)lBOu1gMsiJu!WOj=`gpkD zJc+95%QF;i)FawR-OyaB##MZ7IG7wMkMJWi;%}3YW{ya(`?4d5)g+HDJ4()D9P9`U zSa){Hj#hEY##{NKY$9&%het9|LQXa)*$gDELvoR2-TPV}qP$;1K@L%_+WjA$K%u`F zV=^c-8ghG4MuY-=wLg@xTe8F{WyEHT{ee7rmAj#;;I7L;ilw3?NNI>&Kv5jpH6+(J z2?0W`U>^xluY`!ZIX||ZjKaEt9zW#;&sGURipc;J;KsAKhP2UBL_D#p8<-VcP3w^m zY~~Po?IOC2JWT#gLgkl)Sn8Q@B}8C5nc`pyM3PLp!+^8RQh!E@O1eP*a9wHP@)UQ1Bn)z1cAzAbY1ssqb z^>jBb?XbWjQ4lDmon0S|@=_>QL^!xTl6dwuj8*M;DDh)lp79o=fA7E1LVf!n*0hXm;V68y622X~Dg-Bfu_AcCGX zmUT}cI=*T}ParV5J|__F9N$zNBy^z{=008RLXNj+aj-MRfxN~xYdIjvdaW+oG3~gbs z9{rKTs}X^QQ=gNYmG8-odroeKJhEBaIZFY^&YLLbu&Ppty|ga=Ik{24>5*6S_$}kN zbK=FG1VGf28_(0LAHOkKW+Fv3rQdpbQ+v+8c6js8IpqJ{L{RN&{tG(u1(WLp%)tNv z0fcEoLr_UWLm+T+Z)Rz1WdHzpoPCi!NW(xJ#a~;cMJft*5K+ibJ6RAFanvdlp+cw? zT6HkF^b49aBq=VAf@{ISkHxBki?gl{u7V)=0pjB7r060g{x2!Ci1FaKAMfrx?%o0Z zMun+n*EpbRmXS^-glukA2)-hO5%eQ~n8ZwdP83t{9AEeF@%1jwv%Js!IeL}6$pD`~ zJj-;$BHkdL-n4Yi`@|7ek`&@|;xU6RNc_lk+2uFRMTh-7Gh$@Y^TZKiq1eH42eXo) z5>F9F6;-2rf7WG%^A=~dQe&-q@)w5l+R8H5X$~WaMJz#t02wuuQGtaxtr{sN(zKuO z@DDkDkz6vl%3$PJKou$^#}EDozq>UHlM`-II01CO*!IUL5Znctb=&?vw(aH#5O@Zz zw6?$60A@Z(ueY`65zw~{TwJ#`c@MbU0S2FR$&ef=K+|6+0Pkn?O*vrT7U)@Xdu#3E z^a03FSE(D|;1GxvDSO@H-J#Cj{yo#`?*~${a+=AGB}M=M01r@1R7C&)05@g;v$L~; z^Z>X2WLWj@v;Y7A0d!JMQvg8b*k%9#00Cl4M??UK1szBL000SaNLh0L04^f{04^f| zc%?sf00007bV*G`2jd7G5C#N;7RTTK0019JL_t&t*JEHH12BOR7&sd{Kv{-@26$L- dbx3+i0|4#G0?WKeO=185002ovPDHLkV1krbqmcjr delta 124 zcmV-?0E7Rp8;t>w7Y|98q|hW{*B)l(;msbR=}YJ>?@VrTGxL6iX* eiB7_Jq7(qC(=)M4As;j%Y=V2boPK>Q!A@sq8g!Rwg z9{$2X981WewOA<;N49L#a8u)XoMnpnxSkJJiRX9raQlH^e`1t;K9+UWZ?Mb#1)8?`3N~&iE3U+73zm9V1lP>zHGkojx(^a~yL-xCe2a|l={Oy|b*nt(>9Qwzvh%GO zdKXcmTg&tqf6;1DiVn8ePZwR%eQfc;nWF?$&GDQsN$2GNDMH(VU=o8sEQuwR6qQI* zLLMvlG(=9Ese?e0AT$vrW#$4nm3G^BN7GT4gibT$1t5eAE6`v90anhE3+7wJ5NbhK zvWOH>f2m^93YT1@l%i$pR8!WhqD57!nzqU{SE;3Ht<`EXGKP#vuwrV}%vwXEEjRdT zsNZ1d)Vb#_y>#uhTW|gYXp<&SNI;ln>a5ddTWMh^t-NHFrK>Jm%`w)T zJ-c{u_3GyBM(v{dp4v0H %08Xcf^J-t(de_8d-McQ&An;D2vP9UzE00uN|X0fK6 zX_MQ`q7esXAw($~&P ze}$<{fhac~lM>#MMtxv1#3XxIhQ6UE^#FVQ>o0I>$0d7Cr@CgShQ{ z^qyz_LIT6*6?Pa%@q(sV_c@7uK|77Pf9hVlSytcu%o6a`!L}fIxZQiymlCVwBthUB zhkI|iV-eW7p{#Az=qq&(;!am*R;_ED_t=tsu?(+2$f31vb5YstLfhS|>B?iJp)gIw z$gr~u;&G`_3Ojt+`|jt`a)+F|rol+eGTKfP`>?cnfv(m9pg!uE(BO@@*FT>qf8p2g zK-KI9WV1BB)I4bdYYIfy+G3crQu147{)q5}{%){ltd2`R=WOiy&er4j1F zGgzBZ#rixn;NQV9ms?Xwea~ggdB#?Lj?u6cs#7Y&qe3F~J5FFKwiShQUr7AQ*k#Nd z$XpMpc&o}U6(Kzl(lfV|QGz<Y^_3ghRQQzy@x1;};BkYnNgNw7S4z7YA_yOYL>ZIr*CH^ldw21NGxF7HCJ?`EC{ziqVX4g2N zYL<~sCWLHmRS3Q!gc0;3fSANgeNGfp@El+F@bUF7&a=GF{W*G-yvYEcKs?KI!y?`w zp5C-{&ilj>R+1FrbK)_Be=bP;$aUG}H_kbWYY7*5n`d(!Ey()lA#h$5l0nO zqkMnXWrgz=XSGset$XqphV$CWGS_JiBZ);UL4*JqHIz|-g*dGmDJIgipYZSxIew8` zGP%lNoO54hX`2A_1vkQ^yM(_bh6?`QN)Ibh%x=vi}nYwhFo0mx8S zsT<(n5Qr5id)?#Rq0Zj^J=5y%2U4xXc5cL-uHI00000 LNkvXXu0mjfow-yA delta 101 zcmV-r0Gj{q4R??jUkC;O0028}NBRH&06s}XK~y-)V_={hFfuWW0;0g?&71#|AkN5$ zGsyq^$I$Sf1*>}M#Ll2G 0 then @@ -326,35 +329,84 @@ minetest.register_node("wine:blue_agave", { end }) +-- blue agave into cyan dye minetest.register_craft( { - type = "shapeless", +-- type = "shapeless", output = "dye:cyan 4", - recipe = {"wine:blue_agave"} + recipe = {{"wine:blue_agave"}} }) +-- blue agave as fuel +minetest.register_craft({ + type = "fuel", + recipe = "wine:blue_agave", + burntime = 10, +}) + +-- cook blue agave into a sugar syrup +minetest.register_craftitem("wine:agave_syrup", { + description = "Agave Syrup", + inventory_image = "wine_agave_syrup.png", + groups = {food_sugar = 1, vessel = 1, flammable = 3} +}) + +minetest.register_craft({ + type = "cooking", + cooktime = 7, + output = "wine:agave_syrup 2", + recipe = "wine:blue_agave" +}) + +-- blue agave into paper +minetest.register_craft( { + output = "default:paper 3", + recipe = { + {"wine:blue_agave", "wine:blue_agave", "wine:blue_agave"}, + } +}) + + +-- register blue agave on mapgen minetest.register_decoration({ deco_type = "simple", - place_on = {"default:desert_sand"}, + place_on = {sand}, sidelen = 16, fill_ratio = 0.001, biomes = {"desert"}, decoration = {"wine:blue_agave"}, y_min = 15, y_max = 50, - spawn_by = "default:desert_sand", - num_spawn_by = 6, + spawn_by = sand, + num_spawn_by = 6 }) + +-- add to bonemeal as decoration if available if minetest.get_modpath("bonemeal") then + bonemeal:add_deco({ - {"default:desert_sand", {}, {"default:dry_shrub", "wine:blue_agave", "", ""} } + {sand, {}, {"default:dry_shrub", "wine:blue_agave", "", ""} } }) end --- Wine barrel +-- Mint Julep recipe +if minetest.get_modpath("farming") +and farming.mod and (farming.mod == "redo" or farming.mod == "undo") then + + minetest.register_craft({ +-- type = "shapeless", + output = "wine:glass_mint", + recipe = { + {"farming:mint_leaf", "farming:mint_leaf", "farming:mint_leaf"}, + {"wine:glass_bourbon", "farming:sugar", ""} + } + }) +end + + +-- Wine barrel formspec winebarrel_formspec = "size[8,9]" - .. default.gui_bg..default.gui_bg_img..default.gui_slots .. "list[current_name;src;2,1;1,1;]" .. "list[current_name;dst;5,1;1,1;]" .. "list[current_player;main;0,5;8,4;]" @@ -364,6 +416,8 @@ winebarrel_formspec = "size[8,9]" .. "listring[current_player;main]" .. "image[3.5,1;1,1;gui_furnace_arrow_bg.png^[transformR270]" + +-- Wine barrel node minetest.register_node("wine:wine_barrel", { description = S("Fermenting Barrel"), tiles = {"wine_barrel.png" }, @@ -406,7 +460,8 @@ minetest.register_node("wine:wine_barrel", { return true end, - allow_metadata_inventory_take = function(pos, listname, index, stack, player) + allow_metadata_inventory_take = function( + pos, listname, index, stack, player) if minetest.is_protected(pos, player:get_player_name()) then return 0 @@ -415,7 +470,8 @@ minetest.register_node("wine:wine_barrel", { return stack:get_count() end, - allow_metadata_inventory_put = function(pos, listname, index, stack, player) + allow_metadata_inventory_put = function( + pos, listname, index, stack, player) if minetest.is_protected(pos, player:get_player_name()) then return 0 @@ -431,7 +487,8 @@ minetest.register_node("wine:wine_barrel", { end end, - allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) + allow_metadata_inventory_move = function( + pos, from_list, from_index, to_list, to_index, count, player) if minetest.is_protected(pos, player:get_player_name()) then return 0 @@ -481,8 +538,9 @@ minetest.register_node("wine:wine_barrel", { -- the default stack, from which objects will be taken input_inventory = "dst", - connect_sides = {left = 1, right = 1, back = 1, front = 1, bottom = 1, top = 1} - } end end)(), + connect_sides = { + left = 1, right = 1, back = 1, + front = 1, bottom = 1, top = 1} } end end)(), on_timer = function(pos) @@ -542,14 +600,22 @@ minetest.register_node("wine:wine_barrel", { end return true - end, + end }) + +-- wine barrel craft recipe (with mineclone2 check) +local ingot = "default:steel_ingot" + +if mcl then + ingot = "mcl_core:iron_ingot" +end + minetest.register_craft({ output = "wine:wine_barrel", recipe = { {"group:wood", "group:wood", "group:wood"}, - {"default:steel_ingot", "", "default:steel_ingot"}, + {ingot, "", ingot}, {"group:wood", "group:wood", "group:wood"}, }, }) @@ -585,19 +651,42 @@ minetest.register_lbm({ if minetest.get_modpath("lucky_block") then lucky_block:add_blocks({ + {"fal", {"default:water_source"}, 1, true, 4}, {"dro", {"wine:glass_wine"}, 5}, {"dro", {"wine:glass_beer"}, 5}, {"dro", {"wine:glass_wheat_beer"}, 5}, {"dro", {"wine:glass_mead"}, 5}, {"dro", {"wine:glass_cider"}, 5}, + {"dro", {"wine:glass_rum"}, 5}, + {"dro", {"wine:glass_sake"}, 5}, {"dro", {"wine:glass_tequila"}, 5}, + {"dro", {"wine:glass_bourbon"}, 5}, + {"dro", {"wine:glass_vodka"}, 5}, + {"dro", {"wine:glass_mint"}, 5}, + {"dro", {"wine:glass_coffee_liquor"}, 5}, + {"dro", {"wine:glass_brandy"}, 5}, + {"dro", {"wine:glass_champagne"}, 5}, {"dro", {"wine:wine_barrel"}, 1}, {"tel", 5, 1}, {"nod", "default:chest", 0, { {name = "wine:bottle_wine", max = 1}, {name = "wine:bottle_tequila", max = 1}, + {name = "wine:bottle_rum", max = 1}, + {name = "wine:bottle_cider", max = 1}, + {name = "wine:bottle_bourbon", max = 1}, + {name = "wine:bottle_vodka", max = 1}, + {name = "wine:wine_barrel", max = 1}, + {name = "wine:bottle_sake", max = 1}, + {name = "wine:bottle_mint", max = 1}, + {name = "wine:bottle_mead", max = 1}, + {name = "wine:bottle_beer", max = 1}, + {name = "wine:bottle_wheat_beer", max = 1}, + {name = "wine:bottle_coffee_liquor", max = 1}, + {name = "wine:bottle_brandy", max = 1}, + {name = "wine:bottle_champagne", max = 1}, {name = "wine:blue_agave", max = 4}}}, }) end + print (S("[MOD] Wine loaded")) diff --git a/wine/license.txt b/wine/license.txt index fec6f6a..365aad5 100644 --- a/wine/license.txt +++ b/wine/license.txt @@ -19,3 +19,28 @@ 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. + +Textures by TenPlus1 unless listed below (CC-By-3.0) + +Mikhail Miroscnichenko @ dreamstime.com (royalty free license) + wine_bourbon_bottle.png + +RiverKpocc @ deviantart.com + wine_beer_glass.png + wine_wheat_beer_glass.png + +Textures by Darkstalker (cc-by-3.0 license) + wine_mint_bottle.png + wine_mint_glass.png + +Textures by Darkstalker and edited by Felfa (cc-by-3.0 license) + wine_beer_bottle.png + wine_wheat_beer_bottle.png + wine_cider.bottle.png + wine_mead_bottle.png + +Textures by Felfa (CC0) + wine_champagne*.png + wine_coffee*.png + wine_brandy*.png + wine_sake_bottle.png diff --git a/wine/locale/de.txt b/wine/locale/de.txt deleted file mode 100644 index 74e9f27..0000000 --- a/wine/locale/de.txt +++ /dev/null @@ -1,14 +0,0 @@ -# German Translation for wine mod -# Deutsche Übersetzung der wine Mod -# last update: 2016/May/26 -# Author: Xanthin - -Glass of Wine = Glas Wein -Bottle of Wine = Flasche Wein -Beer = Bier -Honey-Mead = Honigwein -Apple Cider = Apfelwein -Fermenting Barrel = Gärfass -Fermenting Barrel (FULL) = Gärfass (VOLL) -Fermenting Barrel (@1% Done) = Gärfass (@1% erledigt) -[MOD] Wine loaded = [MOD] Wine geladen \ No newline at end of file diff --git a/wine/locale/template.txt b/wine/locale/template.txt index bf4f6c3..4058887 100644 --- a/wine/locale/template.txt +++ b/wine/locale/template.txt @@ -1,12 +1,33 @@ # Template for translations of wine mod -# last update: 2016/May/26 +# textdomain: wine +# author: ? +# last update: 2020/October/27 -Glass of Wine = -Bottle of Wine = -Beer = -Honey-Mead = -Apple Cider = -Fermenting Barrel = -Fermenting Barrel (FULL) = -Fermenting Barrel (@1% Done) = -[MOD] Wine loaded = \ No newline at end of file +Glass of Wine= +Bottle of Wine= +Glass of Beer= +Bottle of Beer= +Glass of Rum= +Bottle of Rum= +Glass of Tequila= +Bottle of Tequila= +Glass of Wheat Beer= +Bottle of Wheat Beer= +Glass of Sake= +Bottle of Sake= +Glass of Bourbon= +Bottle of Bourbon= +Glass of Vodka= +Bottle of Vodka= +Glass of Cider= +Bottle of Cider= +Glass of Honey-Mead= +Bottle of Honey-Mead= +Glass of Mint Julep= +Bottle of Mint Julep= +Blue Agave= +Agave Syrup= +Fermenting Barrel= +Fermenting Barrel (FULL)= +Fermenting Barrel (@1% Done)= +[MOD] Wine loaded= diff --git a/wine/locale/wine.de.tr b/wine/locale/wine.de.tr new file mode 100644 index 0000000..d09bd07 --- /dev/null +++ b/wine/locale/wine.de.tr @@ -0,0 +1,34 @@ +# Deutsche Übersetzung der wine Mod +# textdomain: wine +# author: Xanthin +# author: TheDarkTiger +# last update: 2020/October/27 + +Glass of Wine=Glas Wein +Bottle of Wine=Flasche Wein +Glass of Beer=Bier +Bottle of Beer=Flasche Bier +Glass of Rum=Rum +Bottle of Rum=Flasche Rum +Glass of Tequila=Tequila +Bottle of Tequila=Flasche Tequilla +Glass of Wheat Beer=Weizenbier +Bottle of Wheat Beer=Flasche Weizenbier +Glass of Sake=Sake +Bottle of Sake=Flasche Sake +Glass of Bourbon=Glas Bourbon +Bottle of Bourbon=Flasche Bourbon +Glass of Vodka=Glas Wodka +Bottle of Vodka=Flasche Wodka +Glass of Cider=Apfelwein +Bottle of Cider=Flasche Apfelwein +Glass of Honey-Mead=Honigwein +Bottle of Honey-Mead=Flasche Honigwein +Glass of Mint Julep=Minze Julep +Bottle of Mint Julep=Flasch Minze Julep +Blue Agave=Agave +Agave Syrup=Agavendicksaft +Fermenting Barrel=Gärfass +Fermenting Barrel (FULL)=Gärfass (VOLL) +Fermenting Barrel (@1% Done)=Gärfass (@1% erledigt) +[MOD] Wine loaded=[MOD] Wine geladen diff --git a/wine/locale/wine.es.tr b/wine/locale/wine.es.tr new file mode 100644 index 0000000..18eb14a --- /dev/null +++ b/wine/locale/wine.es.tr @@ -0,0 +1,35 @@ +# Traducción al español del mod Wine por TenPlus1 +# textdomain: wine +# author: Unknown +# author: TenPlus1 +# author: TheDarkTiger +# last update: 2020/October/27 + +Glass of Wine=Copa de vino +Bottle of Wine=Botella de vino +Glass of Beer=Cerveza +Bottle of Beer=Botella de Cerveza +Glass of Rum=Ron +Bottle of Rum=Botella de Ron +Glass of Tequila=Tequíla +Bottle of Tequila=Botella de Tequíla +Glass of Wheat Beer=Cerveza de Trigo +Bottle of Wheat Beer=Botella de Cerveza de Trigo +Glass of Sake=Sake +Bottle of Sake=Botella de Sake +Glass of Bourbon=Copa de Borbón +Bottle of Bourbon=Botella de Borbón +Glass of Vodka=Copa de Vodka +Bottle of Vodka=Botella de Vodka +Glass of Cider=Sidra de Manzana +Bottle of Cider=Botella de Sidra de Manzana +Glass of Honey-Mead=Bebida de Miel +Bottle of Honey-Mead=Botella de Bebida de Miel +Glass of Mint Julep=Julepe de menta +Bottle of Mint Julep=Botella de Julepe de menta +Blue Agave=Agave Tequilana +Agave Syrup=jarabe de agave +Fermenting Barrel=Barril de fermentación +Fermenting Barrel (FULL)=Barril de fermentación (Lleno) +Fermenting Barrel (@1% Done)=Barril de fermentación (@1% completado) +[MOD] Wine loaded=[MOD] Wine cargado diff --git a/wine/locale/wine.fr.tr b/wine/locale/wine.fr.tr new file mode 100644 index 0000000..a396c7b --- /dev/null +++ b/wine/locale/wine.fr.tr @@ -0,0 +1,33 @@ +# Traduction Française du mod Wine par TenPlus1 +# textdomain: wine +# author: TheDarkTiger +# last update: 2020/October/27 + +Glass of Wine=Verre de Vin +Bottle of Wine=Bouteille de Vin +Glass of Beer=Bière +Bottle of Beer=Bouteille de Bière +Glass of Rum=Rhum +Bottle of Rum=Bouteille de Rhum +Glass of Tequila=Tequila +Bottle of Tequila=Bouteille de Tequila +Glass of Wheat Beer=Bière de Blé +Bottle of Wheat Beer=Bouteille de Bière de Blé +Glass of Sake=Saké +Bottle of Sake=Bouteille de Saké +Glass of Bourbon=Bourbon +Bottle of Bourbon=Bouteille de Bourbon +Glass of Vodka=Vodka +Bottle of Vodka=Bouteille de Vodka +Glass of Cider=Cidre +Bottle of Cider=Bouteille de Cidre +Glass of Honey-Mead=Hydromel +Bottle of Honey-Mead=Bouteille d'Hydromel +Glass of Mint Julep=Mint Julep +Bottle of Mint Julep=Bouteille de Mint Julep +Blue Agave=Agave Bleue +Agave Syrup=Sirop d'Agave +Fermenting Barrel=Baril de fermentation +Fermenting Barrel (FULL)=Baril de fermentation (PLEIN) +Fermenting Barrel (@1% Done)=Baril de fermentation (En cours @1%) +[MOD] Wine loaded=[MOD] Wine chargé diff --git a/wine/mod.conf b/wine/mod.conf new file mode 100644 index 0000000..86bfa50 --- /dev/null +++ b/wine/mod.conf @@ -0,0 +1,4 @@ +name = wine +depends = +optional_depends = default, intllib, lucky_block, pipeworks, bonemeal, mcl_core, mcl_sounds, mcl_loot, doc, unified_inventory, thirsty, farming +description = Adds many alcoholic beverages and barrel to ferment them in. diff --git a/wine/textures/wine_agave_syrup.png b/wine/textures/wine_agave_syrup.png new file mode 100644 index 0000000000000000000000000000000000000000..8b644120f525664844e031db857926a8ff641eed GIT binary patch literal 190 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPHF4e$wZHL1VTksIsUSC%lLVP<1) z*Vg5$x1QL#^~{z%XAd5{viHd4V`pxhzkL7F^@q1^J=Jm-=>}?KED7=pW^j0RBMr#0 z_jGX#;kcfhpuo3*!y#jxZMm64M0Co6AXXa#HuaWg9AK&A#TZwyF`A^!jXoe>fL|N7UtA8-Hw00DGTPE!Ct z=GbNc00AyZL_t(Y$JNzAYJ@Np24L|dk`T%aWRud1Sl-5C%qAc`MRy6fDTpM{bIjgN zaiDkUi{iNPS30xk^cPq8NXRoUX4%6_0EA}nF$Ony1P0$(TZaY$*V(tTtsMd%hY7qN5zzX{ z+LIO-e2YHi2zQ}159@=6b?8og|5d{}RL)yYfPg+-s)M_LQVZe|aU};&;K->e@V9Wj zE!Tk*RE5D^S`y&c8x}G0xI}%yg2N{hHjYV0QliG$?alrBA)gxuUQ&}V#jk#>KWH(f UoGyz{)&Kwi07*qoM6N<$f|u*E0RR91 literal 0 HcmV?d00001 diff --git a/wine/textures/wine_bourbon_bottle.png b/wine/textures/wine_bourbon_bottle.png new file mode 100644 index 0000000000000000000000000000000000000000..56aa5c470bcc19ad2a0b88b87b1f8e74d74f5eac GIT binary patch literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*t3?v(r4=o2$(g8jpu8Ir{ObiUETwE%u$_p(R z{#D7$TQK+E0fuiszutcHs|cu!u_VYZn8D%MjWi%9)6>N4Chh{_1&KtNl8m{t1T$tow!q0_LxTu zck<)3kfXA=XKHD72^s|)irpdAdJu6{1-oD!Mlv~y z`a}LdYbZ}Qs>(EecDArS-~9EJ(jWJ08uHB>3oP2ptUJoAyDM$~Jg)oou=d5R60=O+ zm$yq5+*lRdSry$`U*0MSd?cF+G*r4I$S;`TKTdEYv&a;vtkKiOF~p+x=*7ES4GKK0 z4^GYR3DOd||KE3ZQsRc*35$w%^Or4){a#dc;&?*C1_y@-1x0)2i41pxG-o=?6!mEa z^?tPFd@;#vLW|tllxMDwr>i8aEq;Bh!M2?-oc)Wc2!nhRyTcxl27%-S4sn4DcNeb7 o(E9m8KcYbVh2$bGv;4D++;7=>v%bhi0Ug8O>FVdQ&MBb@03|Pq8vp_`=6t@ z`P%J_3*TM?McGP%{DK+&gFsc~gMUB~2TvEr5Q(XC`wnt37;rdwzy4oe*%M)WBU35x zeZs80PgEI=vRNNIVC}iF%~8oc=h+_jN9qc9O{X6J8gLQX+WLsQ+&)gnKZzd27}`&6l&TN5=(TljcQ)i*IeeRWO_D_FbZEak!(NN>oRO^S^g!e0*N>K!b NgQu&X%Q~loCIDoig_{5X literal 0 HcmV?d00001 diff --git a/wine/textures/wine_champagne_glass.png b/wine/textures/wine_champagne_glass.png new file mode 100644 index 0000000000000000000000000000000000000000..812822e292c50cb6d5790795655e6e36b5fa8369 GIT binary patch literal 199 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~xd5LKS0MfG z-@pGe6c2p;_diE*^R?Um@0R`F&+z}*?El|x3)Jv;0#$I81o;Is{D*n+_Uq4#2xVsB3 zXY|=|R*f&glwtnli;RBycVf$A7M{2~!$drQRp!U9_y6ZD@ceHczq{9%i<7C##Mt10 zzk@-8F%Mr&YlhlsQG>HPew<)PXKTE9Mtl942M2te+>}Ha7}ig)DQM0M0J)jL)78&q Iol`;+0Bq4qBLDyZ literal 0 HcmV?d00001 diff --git a/wine/textures/wine_cider_bottle.png b/wine/textures/wine_cider_bottle.png new file mode 100644 index 0000000000000000000000000000000000000000..b79a361f788a29afa3035616ec7a3e3db1d9d22d GIT binary patch literal 438 zcmV;n0ZIOeP)&%>Ypz%Kvs#QgvMa6A>2KmcBPL$_ZYi7yBy00001 zbW%=J06^y0W&i*IG)Y83R5;7U)Uj&AFc1ddKpXl%eSr>nfGjGskkMK~NH!0Bjurx1 z(?N)g_29XNq&H_M)(aHeHwaW`N7$#k6bgay)xOKRRkj$WgK5RbCfcWg1DB@iIHuD#?u_B+Jq943c gy-e9(M4i&h4;rPhQ#Z%fm;e9(07*qoM6N<$f-U#EH~;_u literal 0 HcmV?d00001 diff --git a/wine/textures/wine_coffee_liquor_bottle.png b/wine/textures/wine_coffee_liquor_bottle.png new file mode 100644 index 0000000000000000000000000000000000000000..d492172437321a59a289bb407d10354650b56533 GIT binary patch literal 2482 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 FO#qmwPw)T$ literal 0 HcmV?d00001 diff --git a/wine/textures/wine_mead_bottle.png b/wine/textures/wine_mead_bottle.png new file mode 100644 index 0000000000000000000000000000000000000000..d4f153aedd320ee9162d506b43bf91b9f1f71953 GIT binary patch literal 323 zcmeAS@N?(olHy`uVBq!ia0vp^rXbA13?zk5>~jWEDgizru0R?D7#Sp`CFB(3G&I%S zTrKir`J3|uwojGXxux;hy*a+~18YEPN`m}?862M7NCR@tdb&792Q*3#>|8|;0-idXOE#^7oEd1D*tZ`$*B_WgC$lOfx+?lIOw*RYn@AY*V z=To7}Cd#+f7OhcmSJF{%UvkFhfLCq8EcdOw!Lug%YN~DQ4eqI9+ZNz5ZBP477s00) zUH2A8ev&?LF2eR~*RwC&P48DeTN+umZnfPE^N9S+|L|l3?zm1T2})p{s5m4S0D`pT=KjI1_r)UVvSdd zNCEkbB|(0{3=Yq3qyaf`o-U3d8t0P}8WEal|aXmR9L4<{|kd2MaQ6Wu3pGAmC zVWNovcgN{d4myDX+O`5mxOjQ>^;FVdQ&MBb@06khXlmGw# literal 0 HcmV?d00001 diff --git a/wine/textures/wine_rum_bottle.png b/wine/textures/wine_rum_bottle.png new file mode 100644 index 0000000000000000000000000000000000000000..a26ee940c2387ac64802a447fe5d1d259cf31b0d GIT binary patch literal 379 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy9sxcfu0WdM|NsBB45w$gPP36{ zVqj>JVGs}yIDPu`bC3)W$uKNqVA!^e;rw}q=g%Ym|1SOiyX*h|Hdl*Tk-n>PV|O)` zo}Sfp)M`c=&?t$LAirRcf!M&yJ1%BGHK#mX978Nl&z;=K*Q~(Pc2IV15Le!dd;fi} zXKnJx*_~qV?(-|~jUxy9+P8bz{7+|R>Rp)jth(Y_M9gl6Cyd6-+qx^otVOw3{;pKg z3fw>ct@VV^N4Go~jp_31)2319?R_8WHePsB{EG**nx?C!e@qU z-HAUw3R@UiNhSf0zvp0z-C>`stNx8l%GW%%mi8WjWFTeQP-?7e2 zyu)WSd)n?vw}bMd_(C|QrB09G4BT`4_)5FId-#JM@MQOWydVq;MNd~hmvv4FO#t|x Bs2%_S literal 0 HcmV?d00001 diff --git a/wine/textures/wine_rum_glass.png b/wine/textures/wine_rum_glass.png new file mode 100644 index 0000000000000000000000000000000000000000..b2a746ba249c575fa7d6d27c728cab97729dbcfd GIT binary patch literal 389 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyfdM`tu0WdMKM?)@FC+8c#N>Zq z;Q!p*|6N`GH|736zv%pNhUbrgl0YQ$|9kHL-)#)fpGW@xUHbob*Z=?X{{P7KAvE4$sy67ft%-j3(&tCej#ms1=LoM8 zD_3=#CwYyl`*+U$t(SgTtm*uD&vSwL8YKoE##x#g7hEPR=vwfrHr`cWK|Noc#NXv| z+85=U3#6~@s>-iB*q{&**bpgE;9|hg|3OuW*`Ft};q-wD|NX8Oe2ENo?L0dC8>R`E zX>ZtnfVChz!N1z4;vvJC>NDAC_17$y{pjjszfgMD#P{rC^NoeP+Y^qLodAWWr>mdK II;Vst0JU(sSO5S3 literal 0 HcmV?d00001 diff --git a/wine/textures/wine_sake_bottle.png b/wine/textures/wine_sake_bottle.png new file mode 100644 index 0000000000000000000000000000000000000000..a069dc7f2a78520aabeed3f87b0f61a69c0f6ab8 GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv#Q>iWS0D`mckkZ)|NsB0RjbO& z%UxVt-o1O*(b2Jc_ippjG;yE`#*!evUi$j6CWy#W=O56q=yLX5znxUwuVIg>wr$2O|@x-ki4J;F;c9bmSGT6nysxm3 literal 0 HcmV?d00001 diff --git a/wine/textures/wine_sake.png b/wine/textures/wine_sake_glass.png similarity index 100% rename from wine/textures/wine_sake.png rename to wine/textures/wine_sake_glass.png diff --git a/wine/textures/wine_tequila.png b/wine/textures/wine_tequila_glass.png similarity index 100% rename from wine/textures/wine_tequila.png rename to wine/textures/wine_tequila_glass.png diff --git a/wine/textures/wine_vodka_bottle.png b/wine/textures/wine_vodka_bottle.png new file mode 100644 index 0000000000000000000000000000000000000000..1602517cc43b060f0f733b334a0c8207b29c13a1 GIT binary patch literal 237 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv=>VS)S4RehvT4_6%$mM&%f?+t zE*?L1_T=f~SFc^Z`S{}&KDR8OGRBf1zhDN3XE)M-oCZ%9#}JM4$q5Y%rpas}35|LQ zZF&J0{Wdj3N@>ksyU3Q&RblVq#UeA$M_s&lQK&)Z0wW8b2a}FaZ&R-ZQ&X?d3#JS$ zgEI`A5(=CK{z_f`2yqJL{5#U3oIO~6@nBP_BSk8kid}H#>Bjn iS5>ZO%9JUJIt0aF1-tM3xlVtpUXO@geCwbd{LhO literal 0 HcmV?d00001 diff --git a/wine/textures/wine_vodka_glass.png b/wine/textures/wine_vodka_glass.png new file mode 100644 index 0000000000000000000000000000000000000000..df7a999f90a71f68f9309deb51f2cecd5aa24b05 GIT binary patch literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPHV5AX?b1=72YTzv58{>{f9-@bqS zce(Z*pb%q8kY6x^!?PP{K#r@Yi(?4K_2dKvt{popRyIg-@$l#*v@tU?3(r`Xlas@g zreS2z;c!L5VX27ZjMf7@Y8%`X5)#`C6O??IdIZ>-Cvi_;VEFlx`Ram?3Q9l&89ZJ6 KT-G@yGywo`@HGMe literal 0 HcmV?d00001 diff --git a/wine/textures/wine_wheat_beer_bottle.png b/wine/textures/wine_wheat_beer_bottle.png new file mode 100644 index 0000000000000000000000000000000000000000..de8a7db3b585bb6b16653b58c8bda50633b2447e GIT binary patch literal 458 zcmV;*0X6=KP)_5T3i&Hw;V-~dFw|L!x>#22m^8G8#00002~|M8`n z66$miX8-^I0d!JMQvg8b*k%9#0Y6DZK~z}7?U&)IgD?z*C2}cMns#~rhrLPK+o>Cu zCHXmzf;u=~PRmH!Wx4gQU?}Q$6T*N6epImBfao0h330&M{i`1^^u2)T_Y!VE9B}Zv z2q(XTaPgZ7FMcZ_3V7qU5hh^U(&hjRe<^uS+n!6Y5;~ydoN3>QAH@i$pnkqo@*@8F zIe-aLza*8uvflu}3Q{;V@wX&VfPXXquxS03S`&(Vp$pLb0FGU!WDJf3h!4Kxb`F8P z54l|c9fKrbVIP4NkhLlvUTpw8{}a&;(85DKiU~kt8gd>JK-L7LAyha%Z3(C&hKL*q zXcQ*JIVMp