Определение количества блоков над игроком

Версия Minecraft
1.12.2
Добавил новый атрибут для игрока. Для постоянного его изменения (по аналогии с стандартным игровым голодом) мне понадобилось добавить переменную (float) radModifier, которая по умолчанию равна 1.0F, и которая должна уменьшаться на 30% с каждым найденным над игроком блоком (проще говоря, мне надо узнать количество плотных блоков над игроком) Для этого я воспользовался циклом "for". Но при наличии этого цикла в коде игра просто виснет, когда я пытаюсь войти в любой мир, а консоль говорит, что я пытаюсь выполнить слишком много операций за короткий промежуток времени. Есть ли какая-нибудь альтернатива моему способу (которая не будет заставлять игру виснуть)? Код ивента, логи и скрин ниже (Краш игры не происходит, клиент приходится закрывать насильно)screenshot.png).
Java:
@SubscribeEvent
    public static void onPlayerUpdate(LivingEvent.LivingUpdateEvent event) {

        float radModifier = 1.0F;

        if (event.getEntityLiving() instanceof EntityPlayer) {

            EntityPlayer player = (EntityPlayer) event.getEntityLiving();
            BlockPos pos = new BlockPos(player);
            boolean isSafe = false;

            if (player.ticksExisted % 60 == 0 && player.dimension == 0 && !player.capabilities.isCreativeMode) {

                for (int i = 1; i < 9; i++) {
                    BlockPos posF = pos.up(i);
                    if (player.world.getBlockState(posF) != Blocks.AIR) {

                        radModifier = radModifier - (radModifier / 100 * 30);
                        isSafe = true;
                        i = 1;

                    }
                    if (i == 8) {
                        if (!isSafe) {
                            radModifier = 1.0F;
                        }
                        break;
                    }

                }

                if (getRad(player) != 0 && getRad(player) != 199) {
                    increaseRad(player, radModifier - 0.3F);
                    saveRadToNBT(player);
                }
            }
        }

    }
[12:19:34] [Server thread/INFO] [minecraft/MinecraftServer]: Player734 joined the game
[12:19:39] [pool-2-thread-1/WARN] [mojang/YggdrasilMinecraftSessionService]: Couldn't look up profile properties for com.mojang.authlib.GameProfile@6eb42e56[id=3f66a67c-db6c-36b7-b762-d7a40c17883b,name=Player734,properties={},legacy=false]
com.mojang.authlib.exceptions.AuthenticationException: The client has sent too many requests within a certain amount of time
at com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService.makeRequest(YggdrasilAuthenticationService.java:79) ~[YggdrasilAuthenticationService.class:?]
at com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService.fillGameProfile(YggdrasilMinecraftSessionService.java:180) [YggdrasilMinecraftSessionService.class:?]
at com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService$1.load(YggdrasilMinecraftSessionService.java:60) [YggdrasilMinecraftSessionService$1.class:?]
at com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService$1.load(YggdrasilMinecraftSessionService.java:57) [YggdrasilMinecraftSessionService$1.class:?]
at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3716) [guava-21.0.jar:?]
at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2424) [guava-21.0.jar:?]
at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2298) [guava-21.0.jar:?]
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2211) [guava-21.0.jar:?]
at com.google.common.cache.LocalCache.get(LocalCache.java:4154) [guava-21.0.jar:?]
at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:4158) [guava-21.0.jar:?]
at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:5147) [guava-21.0.jar:?]
at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:5153) [guava-21.0.jar:?]
at com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService.fillProfileProperties(YggdrasilMinecraftSessionService.java:170) [YggdrasilMinecraftSessionService.class:?]
at net.minecraft.client.Minecraft.getProfileProperties(Minecraft.java:3181) [Minecraft.class:?]
at net.minecraft.client.resources.SkinManager$3.run(SkinManager.java:138) [SkinManager$3.class:?]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_181]
at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266) [?:1.8.0_181]
at java.util.concurrent.FutureTask.run(FutureTask.java) [?:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_181]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_181]
 
Решение
Java:
@Mod.EventBusSubscriber(modid = MainClass.MODID)
public class RadiationHandler {

    private static Thread kek = null;
    
    public static float getRadMax(EntityPlayer player) {

        return (float) player.getEntityAttribute(PropRegistry.RAD_MAX).getAttributeValue();

    }

    public static float getRad(EntityPlayer player) {

        return player.getDataManager().get(PropRegistry.RAD);

    }

    public static void increaseRad(EntityPlayer player, float value) {

        player.getDataManager().set(PropRegistry.RAD, MathHelper.clamp(getRad(player) - value, 0.0F, getRadMax(player)));
    }

    public static void setRad(EntityPlayer player, float value) {

        player.getDataManager().set(PropRegistry.RAD...
68
1
7
Хм.. :unsure:
Ещё одна ошибка. В логике. У вас
Java:
if (getRad(player) != 0 && getRad(player) != 199) {
    increaseRad(player, radModifier - 0.3F);
    saveRadToNBT(player);
}
выполнится только после for'a, а for закончится только после выполнения этого if'a
Java:
if (i == 8) {
    if (!isSafe) {
        radModifier = 1.0F;
    }
    break;
}

И тут сразу 3 бессмыслицы:

1. После for'a radModifier всегда будет равен 1.0F, значит в последнем if'e, который после цикла, первый кусок кода в этом сообщении,
Java:
increaseRad(player, radModifier - 0.3F)
можно заменять на
Java:
increaseRad(player, 0.7F)
Хотя это вероятно ошибка

2. Смысла от
Java:
if (player.world.getBlockState(posF) != Blocks.AIR) {
    radModifier = radModifier - (radModifier / 100 * 30);
    isSafe = true;
    i = 1;
}
Тоже нету, потому что эти данные никуда не передаются. Там, я полагаю, должен быть метод который будет передавать эти данные куда-то, где эти данные будут отображаться в вашей шкале.

3. Смысла от условия i < 9 тоже нету, т.к. выход из цикла происходит только через break. Лишняя проверка, её можно опустить
 
После for'a radModifier всегда будет равен 1.0F
Тут вот в чем дело: radModifier с каждым найденным блоком "неВоздуха" уменьшается на 30 % ( radModifier = radModifier - (radModifier / 100 * 30); ). А вот в "increaseRad(player, radModifier - 0.3F)" смысл в том, чтобы если над игроком есть ~5 плотных блоков (не помню сколько точно я рассчитывал), то "-0.3" делает параметр отрицательным и соответственно переменная начинает увеличиваться за его счет. Вроде как тут проблемы нет. (Ну или я что то не понял =) )
 
68
1
7
Ну или я что то не понял
Прочитайте внимательно что я написал в том "изложении", я понимаю ± что и зачем там, я говорю что это не будет работать, там всё статично выходит, у вас в логике ошибка. Я вроде подробно всё расписал, хотя не исключено что не ошибся. Но думаю, что я понял всё правильно. И всё же, как вы оцениваете свои знания Java?
 
И всё же, как вы оцениваете свои знания Java?
Мои знания Java можно, наверное, назвать почти отсутствующими ), ну так бы я сказал. Но этот скрипт вроде как работает, хоть я и не понимаю, из-за чего выдается ошибка.
 
68
1
7
В логике всё же есть ошибка.
Java:
if (i == 8) {
    if (!isSafe) {
        radModifier = 1.0F;
    }
    break;
}
Можно убирать. Т.к. программа зайдёт в это иф, если не выполнится следующий код:
Java:
if (player.world.getBlockState(posF) != Blocks.AIR) {
    radModifier = radModifier - (radModifier / 100 * 30);
    isSafe = true;
    i = 1;
}
А кроме этого кода radModifier ничего не меняет, соответственно он останется 1.0F

И тогда условие выхода в самом for'е можно поменять, из i<=9 в i<=8
 
В логике всё же есть ошибка.
Действительно, вы правы. Я понял, где была моя ошибка только когда детально просмотрел работу кода на практике. То, что i устанавливалось на 1 не давало скрипту проверять блоки выше. Я решил проблему добавлением новой переменной, от которой зависит теперь высота проверки (раньше зависела от i) и по мере работы цикла она увеличивается на 1 как и i. Это решило проблему с логикой и в логах теперь я получаю практически идеальный результат. Вот новый код:
Java:
for (int i = 1; i < 9; i++) {

                        BlockPos posF = pos.up(h);
                        if (player.world.getBlockState(posF).getBlock() != Blocks.AIR) {

                            radModifier = radModifier - (radModifier / 100 * 30);
                            isSafe = true;
                            i = 1;

                        }
                        h++;
                        if (i == 8) {
                            if (!isSafe) {
                                radModifier = 1.0F;
                            }
                            break;
                        }
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                    }
И да, "Thread.sleep" позже на что то заменю. Но у меня до сих пор вылазит та самая ошибка. Может есть еще какие-либо идеи, как это исправить?
 
68
1
7
А, так это норма. Она у всех вылетает. Я чекал на форуме, сказали что она вылетает если майн не может к маджонг подключится, исправить можно если запустить майн с аккаунтом лицензионным типа. Игнорируйте её
 
Сверху