1. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

Помогите Интерфейс SkullMeta, метод setOwningPlayer/setOwner ведет себя не адекватно

Тема в разделе "Разработка плагинов для новичков", создана пользователем MurlikMurlik, 2 авг 2018.

Статус темы:
Закрыта.
  1. Автор темы
    MurlikMurlik

    MurlikMurlik Активный участник Пользователь

    Баллы:
    96
    Вроде работает, только дропа нет после смерти почему то.
    По сообщениям видно что вроде поток другой совсем.
    Но после смерти, вещи не было, хотя я установил 100% шанс выпадения. Исключений тоже нет..
    Код:
    [15:22:49] [Server thread/INFO]: Я тут конвертирую игрока в офлайн игрока..
    [15:22:49] [Server thread/INFO]: Вроде конвертировал
    [15:22:49] [Server thread/INFO]: Установил мету
    [15:22:49] [Server thread/INFO]: Прикрепляю мету
    [15:22:49] [Server thread/INFO]: Все закончил.
    [15:22:49] [ForkJoinPool.commonPool-worker-2/INFO]: Копирую вещь
    [15:22:49] [ForkJoinPool.commonPool-worker-2/INFO]: Дропаю вещь

    UPD:
    Написал более подробный дебаг.
    Выходит так, что на методе world.dropItemNaturally(loc, item); "спотыкается" и все.
    Ибо дальше я не вижу никаких дебажных сообщений.
    Код:
    [16:02:48] [Server thread/INFO]: Я тут конвертирую игрока в офлайн игрока..
    [16:02:48] [Server thread/INFO]: Вроде конвертировал
    [16:02:48] [Server thread/INFO]: Установил мету
    [16:02:48] [Server thread/INFO]: Прикрепляю мету
    [16:02:48] [ForkJoinPool.commonPool-worker-0/INFO]: Копирую вещь SKULL_ITEM
    [16:02:48] [ForkJoinPool.commonPool-worker-0/INFO]: Вроде скопировал..
    [16:02:48] [ForkJoinPool.commonPool-worker-0/INFO]: Дропаю вещь SKULL_ITEM
    [16:02:48] [Server thread/INFO]: Все закончил здесь.
     
    Последнее редактирование: 3 авг 2018
  2. LuckyZeeRo

    LuckyZeeRo Активный участник Пользователь

    Баллы:
    96
    Имя в Minecraft:
    i0xHeX
    А попробуй запихнуть дроп в баккит таск, оно должно то в главном потоке дропать.
     
  3. Автор темы
    MurlikMurlik

    MurlikMurlik Активный участник Пользователь

    Баллы:
    96
    Вроде так же баккитом сделал асинхронном, как делал выше, но ругается все равно.
    Код:
    [16:10:50] [Craft Scheduler Thread - 25/INFO]: [TrophyHeads] Тест1
    [16:10:50] [Craft Scheduler Thread - 25/WARN]: [TrophyHeads] Plugin TrophyHeads v2.1.2 generated an exception while executing task 8805
    java.lang.IllegalStateException: Asynchronous entity add!
        at org.spigotmc.AsyncCatcher.catchOp(AsyncCatcher.java:14) ~[spigot-1.12.2.jar:git-Spigot-642f6d2-6103339]
        at net.minecraft.server.v1_12_R1.World.addEntity(World.java:1017) ~[spigot-1.12.2.jar:git-Spigot-642f6d2-6103339]
        at net.minecraft.server.v1_12_R1.WorldServer.addEntity(WorldServer.java:1115) ~[spigot-1.12.2.jar:git-Spigot-642f6d2-6103339]
        at org.bukkit.craftbukkit.v1_12_R1.CraftWorld.dropItem(CraftWorld.java:295) ~[spigot-1.12.2.jar:git-Spigot-642f6d2-6103339]
        at org.bukkit.craftbukkit.v1_12_R1.CraftWorld.dropItemNaturally(CraftWorld.java:334) ~[spigot-1.12.2.jar:git-Spigot-642f6d2-6103339]
        at ru.BoomEaro.TrophyHeads.AsyncTest.run(AsyncTest.java:31) ~[?:?]
        at org.bukkit.craftbukkit.v1_12_R1.scheduler.CraftTask.run(CraftTask.java:76) ~[spigot-1.12.2.jar:git-Spigot-642f6d2-6103339]
        at org.bukkit.craftbukkit.v1_12_R1.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:52) [spigot-1.12.2.jar:git-Spigot-642f6d2-6103339]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:1.8.0_121]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:1.8.0_121]
        at java.lang.Thread.run(Unknown Source) [?:1.8.0_121]
     
  4. alexandrage

    alexandrage Старожил Пользователь

    Баллы:
    173
    runTaskLater юзай.
     
  5. LuckyZeeRo

    LuckyZeeRo Активный участник Пользователь

    Баллы:
    96
    Имя в Minecraft:
    i0xHeX
    Дак не асинхронном, говорю же в основном должно быть, просто runTask
     
  6. LuckyZeeRo

    LuckyZeeRo Активный участник Пользователь

    Баллы:
    96
    Имя в Minecraft:
    i0xHeX
    PHP:
    CompletableFuture.runAsync(() -> {
        
    Bukkit.getLogger().info("Копирую вещь");
        
    CraftItemStack.asNMSCopy(item);
    }).
    thenRun(() -> {
        
    Bukkit.getScheduler().runTask(plugin, () -> {
            
    Bukkit.getLogger().info("Дропаю вещь");
            
    world.dropItemNaturally(locitem);
        });
    });
     
  7. Автор темы
    MurlikMurlik

    MurlikMurlik Активный участник Пользователь

    Баллы:
    96
    Почти каждое убийство теперь выглядит так в тайминге:
    Код:
           0.25%      28.21%      0.01 s        14.11 ms     0.0           0.0k        TrophyHeads::onPlayerDeathEvent(PlayerDeathEvent)
           0.12%      13.67%      0.01 s         6.84 ms     0.0           0.0k        Task: TrophyHeads$$Lambda$132/605064028(Single)
    А когда игрок не был на сервере по крайней мере после перезагрузки, оно светится красным и процент в 2 раза больше.
    По сути.. ничего не изменилось выходит..
     
  8. LuckyZeeRo

    LuckyZeeRo Активный участник Пользователь

    Баллы:
    96
    Имя в Minecraft:
    i0xHeX
    Интересно, я вот блин не припомню, какой конкретно из тех методов вызывал подключение к моджангу, но когда делал фикс одному челу, я делал через два метода, возможно это второй, что то не найду сейчас, попробуй еще так:
    PHP:
    CompletableFuture.runAsync(() -> {
        
    Bukkit.getLogger().info("Копирую вещь");
        
    CraftItemStack.asBukkitCopy(CraftItemStack.asNMSCopy(item));
    }).
    thenRun(() -> {
        
    Bukkit.getScheduler().runTask(plugin, () -> {
            
    Bukkit.getLogger().info("Дропаю вещь");
            
    world.dropItemNaturally(locitem);
        });
    });
    Было бы неплохо при себе иметь MassiveLag и видеть конкретные строчки, где залагивает. Может быть у тебя вообще не кеширует скины. Тогда нужно переопределять как то метод дропа предмета, и добавлять туда асинхрон на копирование.
     
  9. Автор темы
    MurlikMurlik

    MurlikMurlik Активный участник Пользователь

    Баллы:
    96
    Там это выглядит так. Мб что то не так мы делаем?
    Код:
        public org.bukkit.entity.Item dropItem(Location loc, ItemStack item) {
            Validate.notNull(item, "Cannot drop a Null item.");
            EntityItem entity = new EntityItem(world, loc.getX(), loc.getY(), loc.getZ(), CraftItemStack.asNMSCopy(item));
            entity.pickupDelay = 10;
            world.addEntity(entity, SpawnReason.CUSTOM);
            // TODO this is inconsistent with how Entity.getBukkitEntity() works.
            // However, this entity is not at the moment backed by a server entity class so it may be left.
            return new CraftItem(world.getServer(), entity);
        }
     
  10. Автор темы
    MurlikMurlik

    MurlikMurlik Активный участник Пользователь

    Баллы:
    96
    Вообщем, ни один вариант не сработал к сожалению.
    В таймингах все равно виднеется плагин, эти подвисания чувствуются даже без них.
    Может быть есть еще варианты?
     
  11. LuckyZeeRo

    LuckyZeeRo Активный участник Пользователь

    Баллы:
    96
    Имя в Minecraft:
    i0xHeX
    Скопируй метод дропа из сурсов и сделай копирование предмета в асинхроне с CompletableFuture
     
  12. Автор темы
    MurlikMurlik

    MurlikMurlik Активный участник Пользователь

    Баллы:
    96
    Не получается привести к типу мир с апи в мир ванильного ядра (вроде)
    Caused by: java.lang.ClassCastException: org.bukkit.craftbukkit.v1_12_R1.CraftWorld cannot be cast to net.minecraft.server.v1_12_R1.World
    А так, я в принципе подумал, что реально твой способ с использованием своих методов на добавление предмета в мир, сможет помочь, и даже смогу замерить какой метод тормозит и подключается.
    А пока, я нигде не нашел как можно конвертировать..

    upd:
    Код:
                new DropMethods(this).dropItemNaturally(loc, item, (net.minecraft.server.v1_12_R1.World) world);
    

    Код:
    public class DropMethods {
        private TrophyHeads plugin;
        
        public DropMethods(TrophyHeads plugin) {
            this.plugin = plugin;
        }
        
        
        public org.bukkit.entity.Item dropItemMy(Location loc, ItemStack item, net.minecraft.server.v1_12_R1.World world) {
            long time1 = System.currentTimeMillis();
            Validate.notNull(item, "Cannot drop a Null item.");
            EntityItem entity = new EntityItem(world, loc.getX(), loc.getY(), loc.getZ(), CraftItemStack.asNMSCopy(item));
            entity.pickupDelay = 10;
            world.addEntity(entity, SpawnReason.CUSTOM);
            long time2 = System.currentTimeMillis();
            long times = time2 - time1;
            plugin.getLogger().info("Потребовалось " + times + "ms");
            return new CraftItem(world.getServer(), entity);
        }
        
        public org.bukkit.entity.Item dropItemNaturally(Location loc, ItemStack item, net.minecraft.server.v1_12_R1.World world) {
            double xs = world.random.nextFloat() * 0.7F - 0.35D;
            double ys = world.random.nextFloat() * 0.7F - 0.35D;
            double zs = world.random.nextFloat() * 0.7F - 0.35D;
            loc = loc.clone();
            // Makes sure the new item is created within the block the location points to.
            // This prevents item spill in 1-block wide farms.
            randomLocationWithinBlock(loc, xs, ys, zs);
            return dropItemMy(loc, item, world);
        }
        
        private static void randomLocationWithinBlock(Location loc, double xs, double ys, double zs) {
            double prevX = loc.getX();
            double prevY = loc.getY();
            double prevZ = loc.getZ();
            loc.add(xs, ys, zs);
            if (loc.getX() < Math.floor(prevX)) {
                loc.setX(Math.floor(prevX));
            }
            if (loc.getX() >= Math.ceil(prevX)) {
                loc.setX(Math.ceil(prevX - 0.01));
            }
            if (loc.getY() < Math.floor(prevY)) {
                loc.setY(Math.floor(prevY));
            }
            if (loc.getY() >= Math.ceil(prevY)) {
                loc.setY(Math.ceil(prevY - 0.01));
            }
            if (loc.getZ() < Math.floor(prevZ)) {
                loc.setZ(Math.floor(prevZ));
            }
            if (loc.getZ() >= Math.ceil(prevZ)) {
                loc.setZ(Math.ceil(prevZ - 0.01));
            }
        }
    }
     
  13. alexandrage

    alexandrage Старожил Пользователь

    Баллы:
    173
    Код:
        public static ItemStack setSkullSkin(ItemStack item, String name) {
            NBTTagCompound tag = new NBTTagCompound();
            try {
                String uuid = getUUID(name);
                try {
                    //Тут некое получение SkinProfile из кеш базы.
                    tag = MojangsonParser.parse(nbt(getSkinProfile(uuid)));
                } catch (MojangsonParseException e) {
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            NBTTagCompound nbt = new NBTTagCompound();
            CraftItemStack.asNMSCopy(item).save(nbt);
            nbt.set("tag", tag);
            return CraftItemStack.asBukkitCopy(new net.minecraft.server.v1_12_R1.ItemStack(nbt));
        }
     
  14. alexandrage

    alexandrage Старожил Пользователь

    Баллы:
    173
  15. Автор темы
    MurlikMurlik

    MurlikMurlik Активный участник Пользователь

    Баллы:
    96
    Спасибо за код!
    Вроде работает правильно, игроков кеширует, правда есть несколько вопросов.
    Почему выполняется сразу 2 запроса?
    Код:
    [12:47:47] [Server thread/WARN]: [AutoSaveWorld] Plugin TrophyHeads attempted to establish connection https://api.mojang.com/profiles/minecraft in main server thread
    [12:47:47] [Server thread/WARN]: [AutoSaveWorld] Plugin TrophyHeads attempted to establish connection socket://api.mojang.com:443 in main server thread
    [12:47:47] [Server thread/WARN]: [AutoSaveWorld] Plugin TrophyHeads attempted to establish connection https://sessionserver.mojang.com/session/minecraft/profile/4a6525ce83b34640844488796f9a669f?unsigned=true in main server thread
    [12:47:47] [Server thread/WARN]: [AutoSaveWorld] Plugin TrophyHeads attempted to establish connection socket://sessionserver.mojang.com:443 in main server thread
    Ладно, я второй запрос в асинхрон пихну, но как быть с первым? Он вызывается именно на методе NBTCreator.setSkullSkin(item, pName);
    Я не совсем понимаю, что там делают ивент на ломание блоков и ивент на крафты? Они же вроде не работают, да даже если бы работали, для чего они? (мне не ясна немного логика кода)
     
  16. Cool_boy

    Cool_boy Активный участник Пользователь

    Баллы:
    96
    Имя в Minecraft:
    prettydude
    Получение UUID.

    Получение скина.
     
  17. alexandrage

    alexandrage Старожил Пользователь

    Баллы:
    173
    Первый запрос не имеет лимита, только второй getSkinProfile.
    И да там есть прочие nms методы не связанные с головами. getPosition получает локацию где открыли верстак и последний получает звук ломания блоков.
     
    Последнее редактирование: 4 авг 2018
  18. Автор темы
    MurlikMurlik

    MurlikMurlik Активный участник Пользователь

    Баллы:
    96
    В таком случае, все отлично работает! Я в другом потоке выполнил метод установки головы, а потом там запустил задачу которая выполнит метод спавна лута.
    В итоге, да, лаги прекратились, проблем по сути теперь нет, но осталась одна.
    Если нет данных о игроке, то есть, игрок не имеет скин/лицензии, то один метод возвращает нулл, из-за чего другой метод вызывает исключение когда пытается реплейснуть строку.. Что делать с такими игроками?
     
  19. alexandrage

    alexandrage Старожил Пользователь

    Баллы:
    173
    При null пропускай и юзай простую голову.
     
  20. alexandrage

    alexandrage Старожил Пользователь

    Баллы:
    173
    А если RATE LIMITED. Значит не прошло достаточно времени на повторный запрос.
     
Статус темы:
Закрыта.

Поделиться этой страницей