Вопрос Пакеты, armorstand

Версия Minecraft
1.12.X

GoldenSunsetMine

Пользователь
Сообщения
121
Решения
2
Не обращайте внимания на то, что сейчас всё находится в классе Main.

Проблема следующая: если игрок Player1 смотрит на сундук, и ему тем самым отображаются голограммы, то при входе на сервер или респауне(из далекого от сундука места) игрока Player2 ему будут видны те же armorstand'ы, что и Player1. Нужно это исправить, чтобы каждый игрок видел только свои armorstand'ы, независимо от других игроков.

Если вам не трудно, допишите код который нужно дописать за меня, я уже несколько дней пытаюсь это исправить и устал.

Java:
package com.bodya.skypvp;

import com.bodya.skypvp.Commands.xCommand;
import com.bodya.skypvp.Jumps.JumpCommand;
import com.bodya.skypvp.Jumps.JumpManager;
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.entity.ItemDespawnEvent;
import org.bukkit.event.player.*;
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 Map<Player, List<ArmorStand>> playerArmorStands = 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);
        getServer().getPluginManager().registerEvents(new JumpManager(this), this);
        this.getCommand("skypvpx").setExecutor(new xCommand(this));
        this.getCommand("skyshop").setExecutor(this);
        this.getCommand("skyjump").setExecutor(new JumpCommand(this));
        SignSetup.setupAllSigns(this);
        getServer().getPluginManager().registerEvents(this, this);
        createShopFile();
        if (!setupEconomy()) {
            getLogger().warning("Плагин Vault не обнаружен! Пожалуйста, установите Vault для корректной работы магазинов.");
        } else {
            getLogger().info("Плагин Vault успешно инициализирован!");
        }
    }

    @Override
    public void onDisable() {
        for (Player player : Bukkit.getOnlinePlayers()) {
            removeAllArmorStands(player);
        }
        playerArmorStands.clear();
        playerLookBlock.clear();

        Bukkit.getScheduler().cancelTasks(this);
    }

    @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)) {
            removeArmorStandsForPlayer(player);
            playerLookBlock.put(player, currentBlock);
            if (currentBlock.getType() == Material.CHEST || currentBlock.getType() == Material.TRAPPED_CHEST) {
                Location loc = currentBlock.getLocation();
                String locString = loc.getWorld().getName() + ","
                        + loc.getBlockX() + "," + loc.getBlockY() + "," + loc.getBlockZ();
                if (shopConfig.contains(locString)) {
                    createArmorStand(player, currentBlock, locString);
                }
            }
        }
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if (sender instanceof Player) {
            Player player = (Player) sender;
            Block block = player.getTargetBlock(null, 5);
            if (block == null || (block.getType() != Material.CHEST && block.getType() != Material.TRAPPED_CHEST)) {
                player.sendMessage(ChatColor.RED + "Ошибка! Вы должны смотреть на сундук.");
                return true;
            }

            if (args.length != 2) {
                player.sendMessage(ChatColor.RED + "Держите предмет с нужным количеством в руке и пропишите команду: " + ChatColor.WHITE + "/skypvpx <sell/buy> <цена>");
                return true;
            }

            String action = args[0];
            int price;
            try {
                price = Integer.parseInt(args[1]);
            } catch (NumberFormatException e) {
                player.sendMessage(ChatColor.RED + "Ошибка! Ваша цена не является допустимой.");
                return true;
            }

            ItemStack item = player.getInventory().getItemInMainHand();

            Location loc = block.getLocation();
            String locString = loc.getWorld().getName() + ","
                    + loc.getBlockX() + "," + loc.getBlockY() + "," + loc.getBlockZ();
            shopConfig.set(locString + ".item", serializeItemStack(item));
            shopConfig.set(locString + ".action", action);
            shopConfig.set(locString + ".price", price);
            try {
                shopConfig.save(shopFile);
            } catch (IOException e) {
                e.printStackTrace();
            }

            String displayName = (item.hasItemMeta() && item.getItemMeta().hasDisplayName()) ? item.getItemMeta().getDisplayName() : item.getType().toString();
            player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6SkyPvP: &eМагазин успешно создан. Предмет: &r" + displayName + " x" + item.getAmount() + "&e, Действие: &f" + action + "&e, Цена: &f" + price + "$"));
        }
        return true;
    }

    private boolean isShopLocation(Location itemLocation) {
        for (String key : shopConfig.getKeys(false)) {
            String[] locData = key.split(",");
            if (locData.length == 4) {
                String worldName = locData[0];
                int x = Integer.parseInt(locData[1]);
                int y = Integer.parseInt(locData[2]);
                int z = Integer.parseInt(locData[3]);

                Location shopLocation = new Location(Bukkit.getWorld(worldName), x, y, z);
                Block shopBlock = shopLocation.getBlock();

                if ((shopBlock.getType() == Material.CHEST || shopBlock.getType() == Material.TRAPPED_CHEST) &&
                        shopBlock.getLocation().equals(itemLocation.getBlock().getLocation())) {
                    return true;
                }
            }
        }
        return false;
    }

    @EventHandler
    public void onPickupItem(PlayerPickupItemEvent event) {
        Item item = event.getItem();
        Location itemLocation = item.getLocation();

        if (isShopLocation(itemLocation)) {
            event.setCancelled(true);
        }
    }

    @EventHandler
    public void onItemDespawn(ItemDespawnEvent event) {
        Item item = event.getEntity();
        Location itemLocation = item.getLocation();

        if (isShopLocation(itemLocation)) {
            event.setCancelled(true);
        }
    }

    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));
        playerArmorStands.computeIfAbsent(player, k -> new ArrayList<>()).add(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));
        playerArmorStands.computeIfAbsent(player, k -> new ArrayList<>()).add(armorStand2);

        broadcastArmorStand(player, block, armorStand);
        broadcastArmorStand(player, block, armorStand2);
    }

    private void removeArmorStandsForPlayer(Player player) {
        List<ArmorStand> armorStands = playerArmorStands.get(player);
        if (armorStands != null) {
            for (ArmorStand armorStand : armorStands) {
                armorStand.remove();
            }
            playerArmorStands.remove(player);
        }
    }

    private void removeAllArmorStands(Player player) {
        List<ArmorStand> armorStands = playerArmorStands.get(player);
        if (armorStands != null) {
            for (ArmorStand armorStand : armorStands) {
                armorStand.remove();
            }
            playerArmorStands.remove(player);
        }
    }

    private void broadcastArmorStand(Player player, 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());

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

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

        for (Player p : Bukkit.getOnlinePlayers()) {
            if (p.equals(player)) {
                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 || block.getType() == Material.TRAPPED_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 || clickedBlock.getType() == Material.TRAPPED_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;
    }
}
 
Назад
Сверху Снизу