Вопрос Помощь с пакетами и ArmorStand

Версия Minecraft
1.12.X

GoldenSunsetMine

Пользователь
Сообщения
97
Помогите, я уже задолбался это решать. Мне нужно сделать такую систему:
Когда игрок смотрит на сундук, то ему отображается голограмма через armorstand, а когда он отворачивается от сундука, голограмма перестает отображаться.
Сейчас такая проблема, что если на сундук смотрят 2 игрока, то если 1 из них отвернется и посмотрит заново, то у другого игрока поставится ещё 1 armorstand и то есть голограмма будет заполняться так каждый раз.

И да, потом я разделю все методы на классы, не обращайте внимания что всё в Main.

Java:
package com.bodya.skypvp;

import com.bodya.skypvp.Commands.xCommand;
import com.bodya.skypvp.Listener.*;
import com.bodya.skypvp.Managers.ItemManager;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.PacketContainer;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.*;
import org.bukkit.block.*;
import org.bukkit.command.*;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.*;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.inventory.*;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.io.BukkitObjectInputStream;
import org.bukkit.util.io.BukkitObjectOutputStream;
import java.io.*;
import java.util.*;

public class Main extends JavaPlugin implements Listener, CommandExecutor {
    private HashMap<Player, Block> playerLookBlock = new HashMap<>();
    private HashMap<Block, List<ArmorStand>> activeArmorStands = new HashMap<>();

    private static Economy economy = null;
    private File shopFile;
    private FileConfiguration shopConfig;

    private static Main instance;
    public static Main plugin;

    @Override
    public void onEnable() {
        plugin = this;
        instance = this;
        this.saveDefaultConfig();
        ItemManager.init();
        getServer().getPluginManager().registerEvents(new PlayerDeath(), this);
        getServer().getPluginManager().registerEvents(new SignSetup(this), this);
        getServer().getPluginManager().registerEvents(new LaunchTNT(this), this);
        getServer().getPluginManager().registerEvents(new JumpModule(this), this);
        getServer().getPluginManager().registerEvents(new GoldenCarrot(this), this);
        this.getCommand("skypvpx").setExecutor(new xCommand(this));
        SignSetup.setupAllSigns(this);
        getServer().getPluginManager().registerEvents(this, this);
        createShopFile();
        if (!setupEconomy()) {
            getLogger().warning("Плагин Vault не обнаружен! Пожалуйста, установите Vault для корректной работы магазинов.");
        } else {
            getLogger().info("Плагин Vault успешно инициализирован!");
        }
    }

    @Override
    public void onDisable() {
        playerLookBlock.clear();
    }

    @EventHandler
    public void onPlayerMove(PlayerMoveEvent event) {
        Player player = event.getPlayer();
        Block currentBlock = player.getTargetBlock(null, 5);

        Block previousBlock = playerLookBlock.get(player);
        if (previousBlock == null || !currentBlock.equals(previousBlock)) {
            if (previousBlock != null) {
                removeArmorStand(player, previousBlock);
                playerLookBlock.remove(player);
            }
            if (currentBlock.getType() == Material.CHEST) {
                Location loc = currentBlock.getLocation();
                String locString = loc.getWorld().getName() + ","
                        + loc.getBlockX() + "," + loc.getBlockY() + "," + loc.getBlockZ();
                if (shopConfig.contains(locString)) {
                    createArmorStand(player, currentBlock, locString);
                    playerLookBlock.put(player, currentBlock);
                }
            }
        }
    }

    private void createArmorStand(Player player, Block block, String locString) {
        String action = shopConfig.getString(locString + ".action");
        int price = shopConfig.getInt(locString + ".price");
        ItemStack item = deserializeItemStack(shopConfig.getString(locString + ".item"));
        String itemName = (item.getItemMeta() != null && item.getItemMeta().hasDisplayName()) ? item.getItemMeta().getDisplayName() : ChatColor.YELLOW + item.getI18NDisplayName();

        Location spawnLocation = block.getLocation().clone().add(0.5, -0.50, 0.5);
        ArmorStand armorStand = (ArmorStand) block.getWorld().spawnEntity(spawnLocation, EntityType.ARMOR_STAND);

        armorStand.setCustomNameVisible(true);
        armorStand.setGravity(false);
        armorStand.setVisible(false);
        armorStand.setCustomName(ChatColor.translateAlternateColorCodes('&', itemName + " &fx" + item.getAmount()));

        armorStand.setMetadata("shopArmorStand", new FixedMetadataValue(this, true));

        broadcastArmorStand(block, armorStand);

        ArmorStand armorStand2 = (ArmorStand) block.getWorld().spawnEntity(spawnLocation.clone().add(0, -0.25, 0), EntityType.ARMOR_STAND);
        armorStand2.setCustomNameVisible(true);
        armorStand2.setGravity(false);
        armorStand2.setVisible(false);
        armorStand2.setCustomName(ChatColor.translateAlternateColorCodes('&', (action.equalsIgnoreCase("sell") ? "&aПродать: $" + price : "&6Цена: $" + price)));

        armorStand2.setMetadata("shopArmorStand", new FixedMetadataValue(this, true));

        broadcastArmorStand(block, armorStand2);
    }

    private void broadcastArmorStand(Block targetBlock, ArmorStand armorStand) {
        ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager();

        PacketContainer spawnPacket = protocolManager.createPacket(PacketType.Play.Server.SPAWN_ENTITY);
        spawnPacket.getIntegers()
                .write(0, armorStand.getEntityId())
                .write(1, (int) EntityType.ARMOR_STAND.getTypeId());
        spawnPacket.getDoubles()
                .write(0, armorStand.getLocation().getX())
                .write(1, armorStand.getLocation().getY())
                .write(2, armorStand.getLocation().getZ());
        spawnPacket.getUUIDs()
                .write(0, armorStand.getUniqueId());

        PacketContainer destroyPacket = protocolManager.createPacket(PacketType.Play.Server.ENTITY_DESTROY);
        destroyPacket.getIntegerArrays().write(0, new int[] { armorStand.getEntityId() });

        for (Player p : Bukkit.getOnlinePlayers()) {
            if (p.getWorld().equals(armorStand.getWorld()) && p.getLocation().distance(armorStand.getLocation()) < 50) {
                Block playerTargetBlock = p.getTargetBlock(null, 5);
                if (playerTargetBlock.equals(targetBlock)) {
                    try {
                        protocolManager.sendServerPacket(p, spawnPacket);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    try {
                        protocolManager.sendServerPacket(p, destroyPacket);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    private void removeArmorStand(Player player, Block block) {
        List<Entity> entities = new ArrayList<>(block.getWorld().getNearbyEntities(block.getLocation().add(0.5, 0.5, 0.5), 0.5, 1.0, 0.5));
        ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager();

        for (Entity entity : entities) {
            if (entity instanceof ArmorStand && entity.hasMetadata("shopArmorStand")) {
                ArmorStand armorStand = (ArmorStand) entity;

                Block playerTargetBlock = player.getTargetBlock(null, 5);
                if (!playerTargetBlock.equals(block)) {
                    PacketContainer destroyPacket = protocolManager.createPacket(PacketType.Play.Server.ENTITY_DESTROY);
                    destroyPacket.getIntegerArrays().write(0, new int[] { armorStand.getEntityId() });

                    try {
                        protocolManager.sendServerPacket(player, destroyPacket);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }


    private void createShopFile() {
        shopFile = new File(getDataFolder() + "/data", "shops.yml");
        if (!shopFile.exists()) {
            shopFile.getParentFile().mkdirs();
            try {
                shopFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        shopConfig = YamlConfiguration.loadConfiguration(shopFile);
    }


    private String serializeItemStack(ItemStack itemStack) {
        if (itemStack == null || itemStack.getType() == Material.AIR) {
            return "";
        }

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        DataOutputStream dataOutput = new DataOutputStream(outputStream);

        try {
            BukkitObjectOutputStream bukkitOutput = new BukkitObjectOutputStream(dataOutput);
            bukkitOutput.writeObject(itemStack);
            bukkitOutput.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return Base64.getEncoder().encodeToString(outputStream.toByteArray());
    }

    private ItemStack deserializeItemStack(String data) {
        if (data == null || data.isEmpty()) {
            return new ItemStack(Material.AIR);
        }

        ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64.getDecoder().decode(data));
        DataInputStream dataInput = new DataInputStream(inputStream);

        try {
            BukkitObjectInputStream bukkitInput = new BukkitObjectInputStream(dataInput);
            ItemStack itemStack = (ItemStack) bukkitInput.readObject();
            bukkitInput.close();
            return itemStack;
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }

        return new ItemStack(Material.AIR);
    }

    @EventHandler
    public void onBlockBreak(BlockBreakEvent event) {
        Block block = event.getBlock();
        if (block.getType() == Material.CHEST) {
            Chest chest = (Chest) block.getState();
            Location loc = chest.getLocation();
            String locString = Objects.requireNonNull(loc.getWorld()).getName() + ","
                    + loc.getBlockX() + "," + loc.getBlockY() + "," + loc.getBlockZ();
            if (shopConfig.contains(locString)) {
                shopConfig.set(locString, null);
                try {
                    shopConfig.save(shopFile);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @EventHandler
    public void onPlayerInteract(PlayerInteractEvent event) {
        Player player = event.getPlayer();
        if (event.getAction() == Action.RIGHT_CLICK_BLOCK) {
            Block clickedBlock = event.getClickedBlock();
            if (clickedBlock != null && clickedBlock.getType() == Material.CHEST) {
                Chest chest = (Chest) clickedBlock.getState();
                Location loc = chest.getLocation();
                String locString = loc.getWorld().getName() + ","
                        + loc.getBlockX() + "," + loc.getBlockY() + "," + loc.getBlockZ();
                if (shopConfig.contains(locString)) {
                    event.setCancelled(true);
                    String action = shopConfig.getString(locString + ".action");
                    int price = shopConfig.getInt(locString + ".price");
                    ItemStack itemShop = deserializeItemStack(shopConfig.getString(locString + ".item"));

                    if (action.equalsIgnoreCase("buy")) {
                        if (player.getInventory().firstEmpty() != -1) {
                            if (economy.getBalance(player) >= price) {
                                economy.withdrawPlayer(player, price);
                                player.getInventory().addItem(itemShop);
                                String displayName = (itemShop.hasItemMeta() && itemShop.getItemMeta().hasDisplayName()) ? itemShop.getItemMeta().getDisplayName() : itemShop.getType().toString();
                                player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Вы купили &r" + displayName + " x" + itemShop.getAmount() + " &6за " + price + "$"));
                            } else {
                                player.sendMessage(ChatColor.RED + "У Вас недостаточно денег.");
                            }
                        } else {
                            player.sendMessage(ChatColor.RED + "Ваш инвентарь полон.");
                        }
                    } else if (action.equalsIgnoreCase("sell")) {
                        ItemStack itemStack = null;
                        for (ItemStack stack : player.getInventory().getContents()) {
                            if (stack != null && stack.isSimilar(itemShop)) {
                                itemStack = stack;
                                break;
                            }
                        }

                        if (itemStack != null && itemStack.getAmount() >= itemShop.getAmount()) {
                            ItemMeta itemMeta = itemShop.getItemMeta();
                            String displayName = (itemMeta == null || itemMeta.getDisplayName() == null) ? itemShop.getI18NDisplayName() : itemMeta.getDisplayName();
                            economy.depositPlayer(player, price);
                            itemStack.setAmount(itemStack.getAmount() - itemShop.getAmount());
                            player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6Вы продали &r" + displayName + " x" + itemShop.getAmount() + " &6за " + price + "$"));
                        } else {
                            player.sendMessage(ChatColor.RED + "Вашего товара недостаточно.");
                        }
                    }
                }
            }
        }
    }

    private boolean setupEconomy()
    {
        RegisteredServiceProvider<Economy> economyProvider = getServer().getServicesManager().getRegistration(net.milkbowl.vault.economy.Economy.class);
        if (economyProvider != null) {
            economy = economyProvider.getProvider();
        }

        return (economy != null);
    }

    public static Main getInstance() {
        return instance;
    }

    public static Economy getEconomy() {
        return economy;
    }
}
 
Должна быть такая логика: У тебя должен быть массив Игрок - Арморстенд, когда игрок начинает смотреть на эндер сундук - создаешь арморстенд и добавляешь в массив игрока и созданный арморстенд, при отвороте от эндер сундука ты удаляешь арморстенд и удаляешь игрока с арморстендом из массива
При создании арморстенда ты отправляешь его только тому игроку, который начал смотреть на эндер сундук

Задавай вопросы уже по тому, что я написал, в чём у тебя возникают проблемы
 
Должна быть такая логика: У тебя должен быть массив Игрок - Арморстенд, когда игрок начинает смотреть на эндер сундук - создаешь арморстенд и добавляешь в массив игрока и созданный арморстенд, при отвороте от эндер сундука ты удаляешь арморстенд и удаляешь игрока с арморстендом из массива
При создании арморстенда ты отправляешь его только тому игроку, который начал смотреть на эндер сундук

Задавай вопросы уже по тому, что я написал, в чём у тебя возникают проблемы

Я хочу попросить вас написать код за меня. Могу оплатить потраченное время.
 
Назад
Сверху Снизу