Вопрос Как сделать защищённый приват с tnt-deny, но с удалением региона при взрыве (destroy_region_when_explode = true) с использованием ProtectionStones?

Ядро
Paper

gamer228413

Пользователь
Сообщения
5
Разрешается выкладывание кода, файлов конфигураций, логов и т.д. только под BB-код CODE
Плагин
ProtectionStones
Ядро сервера
  1. Paper
Версия сервера
  1. 1.21
Память сервера ОЗУ
4Gb
Ссылка
https://www.spigotmc.org/resources/protectionstones-updated-for-1-20-6.61797/
Я с DeepSeek сделали код, который может обходить tnt deny, блоки в привате ломаются, даже блок привата. Но главная проблема что блок пропадает физически, но не логически. Вот код:
Код:
[/SUB]
[CODE]package com.gamer.privatetnt;

import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.command.*;
import org.bukkit.entity.*;
import org.bukkit.event.*;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.inventory.*;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.*;

public final class AntiPrivateTNT extends JavaPlugin implements Listener {

        private final NamespacedKey tntKey = new NamespacedKey(this, "anti_private_tnt");
        private final Set<Material> PROTECTED_BLOCKS = Set.of(
                Material.BEDROCK,
                Material.BARRIER,
                Material.REINFORCED_DEEPSLATE  // Исправленная строка
        );

    @Override
    public void onEnable() {
        if (!isVersionSupported()) {
            getLogger().severe("Этот плагин требует Minecraft 1.21+!");
            getServer().getPluginManager().disablePlugin(this);
            return;
        }

        getServer().getPluginManager().registerEvents(this, this);
        registerRecipe();
        registerCommands();
        getLogger().info("§aAntiPrivateTNT для 1.21.4 активирован!");
    }

    private boolean isVersionSupported() {
        try {
            Material.valueOf("BREEZE_ROD");
            return true;
        } catch (IllegalArgumentException e) {
            return false;
        }
    }

    private void registerCommands() {
        // Получаем команду из CommandMap вместо getCommand()
        try {
            CommandMap commandMap = getServer().getCommandMap();
            Command command = new Command("antitnt") {
                @Override
                public boolean execute(CommandSender sender, String label, String[] args) {
                    if (sender instanceof Player player) {
                        player.getInventory().addItem(createTNTItem());
                        player.sendMessage("§aВы получили Антиприватное ТНТ!");
                        return true;
                    }
                    sender.sendMessage("§cЭта команда только для игроков!");
                    return false;
                }
            };
            command.setDescription("Получить антиприватное ТНТ");
            command.setUsage("/antitnt");
            commandMap.register("antiprivatetnt", command);
        } catch (Exception e) {
            getLogger().severe("Ошибка при регистрации команды: " + e.getMessage());
        }
    }

    private ItemStack createTNTItem() {
        ItemStack item = new ItemStack(Material.TNT);
        ItemMeta meta = item.getItemMeta();

        meta.setDisplayName("§4Антиприватное ТНТ");
        meta.setLore(List.of(
                "§cВзрывает §6любые§c защиты",
                "§7Даже в новых версиях 1.21!",
                "§8Рецепт: 4 медных блока + 4 ТНТ + ядро ветра"
        ));

        meta.getPersistentDataContainer().set(tntKey, PersistentDataType.BYTE, (byte)1);
        item.setItemMeta(meta);
        return item;
    }

    private void registerRecipe() {
        // Основной рецепт (1.21+)
        ShapedRecipe recipe = new ShapedRecipe(tntKey, createTNTItem());
        recipe.shape("CBC", "BTB", "CBC");

        recipe.setIngredient('C', Material.COPPER_BLOCK);
        recipe.setIngredient('B', Material.BREEZE_ROD);
        recipe.setIngredient('T', Material.TNT);

        // Альтернативный рецепт
        ShapelessRecipe fallback = new ShapelessRecipe(
                new NamespacedKey(this, "antitnt_fallback"),
                createTNTItem()
        );
        fallback.addIngredient(4, Material.COPPER_BLOCK);
        fallback.addIngredient(4, Material.TNT);
        fallback.addIngredient(1, Material.BREEZE_ROD);

        try {
            getServer().addRecipe(recipe);
            getServer().addRecipe(fallback);
            getLogger().info("Рецепты для 1.21.4 зарегистрированы!");
        } catch (Exception e) {
            getLogger().severe("Ошибка рецептов: " + e.getMessage());
        }
    }

    @EventHandler
    public void onBlockPlace(BlockPlaceEvent event) {
        if (!isAntiTNT(event.getItemInHand())) return;

        event.getBlock().setType(Material.AIR);
        TNTPrimed tnt = event.getBlock().getWorld().spawn(
                event.getBlock().getLocation().add(0.5, 0, 0.5),
                TNTPrimed.class
        );
        tnt.getPersistentDataContainer().set(tntKey, PersistentDataType.BYTE, (byte)1);
        tnt.setFuseTicks(30);
    }

    @EventHandler(priority = EventPriority.HIGHEST)
    public void onEntityExplode(EntityExplodeEvent event) {
        if (!isAntiTNT(event.getEntity())) return;
        event.setCancelled(true);

        Location loc = event.getLocation();
        World world = loc.getWorld();

        new BukkitRunnable() {
            @Override
            public void run() {
                destroyArea(world, loc, 12);

                new BukkitRunnable() {
                    @Override
                    public void run() {
                        executeCommands(
                                "rg forceregiondelete -w " + world.getName() + " " + loc.getBlockX() + " " + loc.getBlockZ(),
                                "ps admin purge " + loc.getBlockX() + " " + loc.getBlockY() + " " + loc.getBlockZ()
                        );
                        world.spawnParticle(Particle.TRIAL_SPAWNER_DETECTION, loc, 100);
                    }
                }.runTaskLater(AntiPrivateTNT.this, 5);
            }
        }.runTaskLater(this, 2);
    }

    private void destroyArea(World world, Location center, int radius) {
        for (int x = -radius; x <= radius; x++) {
            for (int y = -radius; y <= radius; y++) {
                for (int z = -radius; z <= radius; z++) {
                    Block block = world.getBlockAt(center.clone().add(x, y, z));
                    if (shouldDestroy(block)) {
                        block.breakNaturally();
                        block.setType(Material.AIR, false);
                    }
                }
            }
        }
    }

    private boolean shouldDestroy(Block block) {
        return !block.getType().isAir() &&
                !PROTECTED_BLOCKS.contains(block.getType()) &&
                !block.getType().name().contains("COMMAND");
    }

    private void executeCommands(String... commands) {
        for (String cmd : commands) {
            try {
                getServer().dispatchCommand(getServer().getConsoleSender(), cmd);
            } catch (Exception e) {
                getLogger().warning("Не удалось выполнить команду: " + cmd);
            }
        }
    }

    private boolean isAntiTNT(ItemStack item) {
        return item != null &&
                item.hasItemMeta() &&
                item.getItemMeta().getPersistentDataContainer().has(tntKey, PersistentDataType.BYTE);
    }

    private boolean isAntiTNT(Entity entity) {
        return entity instanceof TNTPrimed &&
                entity.getPersistentDataContainer().has(tntKey, PersistentDataType.BYTE);
    }
}
[/CODE]
И вот настройки защищенного блока:
type = "DIAMOND_BLOCK"
alias = "Алмазный блок"
description = ""
restrict_obtaining = false
# Enable or disable the use of this protection stone in specific worlds
# "blacklist" mode prevents this protect block from being used in the worlds in "worlds"
# "whitelist" mode allows this protect block to only be used in the worlds in "worlds"
# Can be overriden with protectionstones.admin permission (including OP)!
world_list_type = "blacklist"
worlds = ["exampleworld1", "exampleworld2"]
# Whether or not to actually restrict the protection stone from being placed when the world is restricted (in blacklist/whitelist)
# The block will place normally, without PS behaviour.
prevent_block_place_in_restricted_world = true
# Whether or not to allow the block to be placed in the wild.
# If set to false, the protection block can only be placed in existing regions.
allow_placing_in_wild = true
# Whether or not to allow the block to bypass the WorldGuard passthrough flag.
# This allows the protection block to be placed even if WorldGuard prevents block placing in the wild.
placing_bypasses_wg_passthrough = true

[region]
x_radius = 15
y_radius = 15
z_radius = 15
flags = ["pvp allow", "tnt deny", "creeper-explosion deny "]
# Minimum distance between claims (that aren't owned by the same owner), measured from the protection block to the edge of another region
# You will probably have to change this between blocks, since the region sizes will be different
# Set to -1 for no minimum, but will still check for overlapping regions
distance_between_claims = -1
# Enables "chunk snapping mode", where the region boundaries will be determined by the chunk the block is in, and the
# chunk_radius (how many chunks away from the center chunk).
# Allows players to not have to worry about the exact placement of their block, and removes the issue of messy overlapping
# regions (as they all conform to chunk boundaries).
# Set to -1 to disable, and any number larger than or equal to 1 to enable.
# Note: If enabled, x_radius and z_radius will be ignored!
chunk_radius = -1
# How many blocks to offset the default location of /ps home from the protection block
home_x_offset = 0.0
home_y_offset = 1.0
home_z_offset = 0.0
# List all the flags that can be set by region owners.
# If you want to whitelist the groups that can be set as well, use -g (ex. "-g all,members pvp" restricts it to no group flag, and members group)
# "-g all pvp" - Prevents players setting the group to nonmembers, and being invulnerable to attacks.
allowed_flags = ["-g all pvp", "greeting", "greeting-title", "greeting-action", "farewell", "farewell-title", "farewell-action", "mob-spawning", "creeper-explosion", "wither-damage", "ghast-fireball"]
# Which flags to hide from /ps info
hidden_flags_from_info = ["ps-name", "ps-merged-regions", "ps-merged-regions-types", "ps-block-material", "ps-price", "ps-landlord", "ps-tenant", "ps-rent-period", "ps-rent-last-paid", "ps-for-sale", "ps-rent-settings", "ps-tax-payments-due", "ps-tax-last-payment-added", "ps-tax-autopayer"]
# Default priority type for this block type protection stone
priority = 0
# Whether or not to allow creation of regions that overlap other regions you don't own
# This is dangerous, so think about this carefully if you set it to true.
allow_overlap_unowned_regions = false
# Whether or not to allow players to create other regions that overlap this region.
# "owner" - only allow owners to overlap this (default)
# "member" - allow members and owners to overlap this region type. (useful for city plots)
# "all" - allow all players to overlap this region type.
# "none" - no players, not even the owners of the region can overlap it
# allow_overlap_unowned_regions does not need to be true for this to work.
allow_other_regions_to_overlap = "owner"
# Whether or not to allow this regions created with this block to merge with other regions
# allow_merging_regions must be set to true in config.toml
allow_merging = true
# Allowed types of regions to merge into (referred to by alias)
# Be sure to add the alias of this current region type to allow merging with it ex. ["64"]
# Add "all" if you want to allow this region to merge into any region
allowed_merging_into_types = ["all"]

[behaviour]
prevent_explode = true
destroy_region_when_explode = true
# Hide protection stone right away when placed?
auto_hide = false
# Whether or not to automatically merge into other regions when placed if there is only one overlapping and allow_merging is true
auto_merge = false
# Disable returning the block when removed/unclaimed?
no_drop = false
# Prevents piston pushing of the block. Recommended to keep as true.
prevent_piston_push = true
# Silk Touch: if true, ore-blocks that are also configured by ProtectionStones will disallow Silk Touch drops
# This was the old behaviour to prevent natural obtaining of the protection stone.
# Recommended to keep false if "Restrict Obtaining" (the new way) is true
prevent_silk_touch = false
# Set cost for when a protection block is placed (separate from /ps get cost)
cost_to_place = 0.0
# Allow protect block item to be smelt in furnaces
allow_smelt_item = false
# Allows the protection block to be used in crafting recipes
# You may want it set to false to prevent players decomposing its elements
allow_use_in_crafting = false

[block_data]
display_name = "Защищенный приват"
lore = [""]
# Whether the item should have an "glow/enchant" effect look when in a player's inventory.
enchanted_effect = false
# Add price when using /ps get
# Must have compatible economy plugin (requires Vault, ie. Essentials)
# Must be a decimal (ex. not 10, but 10.0)
price = 100000.0
# Whether or not to allow crafting this item using a custom recipe
# Useful to allow crafting the item when restrict_obtaining is set to true
allow_craft_with_custom_recipe = false
# Specify the custom crafting recipe below
# You must fill the item spots with names from here:
# You can also use other protection stone items as ingredients in the recipe, in the format PROTECTION_STONES:alias
# Make sure that you set allow_use_in_crafting for that block to true, or else you can't use it in crafting
# If you want air, you can just leave the spot as ""
custom_recipe = [["", "STONE", ""], ["STONE", "EMERALD", "STONE"], ["", "STONE", ""]]
# Amount of the protection item to give when crafted
recipe_amount = 1
# The custom model data of the block item, useful for resource packs. Set to -1 to disable.
custom_model_data = -1

[economy]
# Taxes must be enabled in config.toml first (tax_enabled)
# The amount to tax the region per tax cycle.
# Must be a decimal (ex. not 10, but 10.0)
tax_amount = 0.0
# The amount of seconds between tax cycles. Set to -1 to disable taxes.
tax_period = -1
# Amount of time to pay taxes in seconds after tax cycle before there is punishment.
tax_payment_time = 86400
# Automatically set the player that created the region as the taxpayer.
start_with_tax_autopay = true
# What role tenants should be added as (for rents). It can either be "owner" or "member".
tenant_rent_role = "member"
# Should the landlords of rented out regions still be an owner while it is rented out?
landlord_still_owner = false

[player]
# Whether or not to allow breaking the protection block with a shift-right click
# Useful if the protection block is unbreakable (bedrock, command block), etc.
allow_shift_right_break = false
# Whether or not to prevent teleporting into a protected region if the player doesn't own it (except with ender pearl and chorus fruit)
# Does not prevent entry, use the flag "entry deny" for preventing entry.
# Bypass with protectionstones.tp.bypassprevent
prevent_teleport_in = false
# Can't move for x seconds before teleporting with /ps home or /ps tp. Can be disabled with 0.
# Option to teleport only if player stands still.
# Can override with permission protectionstones.tp.bypasswait
no_moving_when_tp_waiting = true
tp_waiting_seconds = 0
# Whether or not to prevent obtaining this block through /ps get.
# Ignored with protectionstones.admin
prevent_ps_get = false
# Whether or not to prevent this region type from showing up in /ps home, and allowing teleport.
# Note: admins can still use /ps tp to this region type
prevent_ps_home = false
# Extra permission required to place this specific protection block (you still need protectionstones.create)
# Also applies to /ps get (you still need protectionstones.get)
# '' for no extra permission
permission = ""

[event]
# Events section
# ~~~~~~~~~~~~~~
# For each line on events, it is the format 'type: action'
# The following are accepted types:
# player_command - Execute command by player that caused event (won't execute if not applicable)
# console_command - Execute command by console
# message - Send message to player or console if applicable (colour support with &)
# global_message - Send message to all players and console (colour support with &)
# console_message - Send message to console (colour support with &)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Whether or not to enable event tracking (API events will still be enabled)
enable = false
# Execute commands when a region is created (ex. player place protection block)
# Variables: %player%, %world%, %region%, %block_x%, %block_y%, %block_z%
on_region_create = ["global_message: &l%player% created the region %region%!"]
# Execute commands when a region is destroyed (ex. when player destroy protection block)
# Variables: %player%, %world%, %region%, %block_x%, %block_y%, %block_z%
on_region_destroy = ["console_command: say %player% has destroyed region %region%!"]
 
Последнее редактирование:
Тогда напиши мне правильный код, который будет выполнять туже функцию, только исправно
зачем мне писать для тебе этот код? я сказал лишь всю проблему которая и кроется в твоём вопросе решение это заплатить нормальному кодеру который сможет это сделать а не DeepSeek который может и напишит тебе код но он будет по любому с багами или не оптимален
 
Назад
Сверху Снизу