Не обновляется количество maxHealth при переходе между мирами.

Версия Minecraft
1.7.10
210
1
19
В конфиг записываю количество добавленных или отбавленных сердец. При входе на сервер (эвент PlayerLoggedInEvent), при респавне игрока после смерти (эвент PlayerRespawnEvent), при переходе из края в верхний мир (эвент Clone) всё работает. При любом другом переходе между мирами (эвент PlayerChangedDimensionEvent) сообщение о том, что переход случился, есть, а эффекта нет - у игрока дефолтные 10 сердец (maxHealth). Но если отключиться от мира и сразу снова зайти - всё становится нормально. То есть игра считает, что максимум сердец столько, сколько нужно, но я их не вижу. Ниже мой код. Закомментированы все способы, которые я попробовал. Подчеркну ещё раз: во всех других перечисленных случаях всё работает нормально.
Java:
    @SubscribeEvent
    public void onChangeDim(PlayerChangedDimensionEvent e){
        if(!e.player.worldObj.isRemote){
            if(RespawnConfig.isDebug())System.out.println("Fired 'PlayerChangedDimensionEvent' for player " + e.player.getDisplayName());
            float defaulthp = 20.0f;
            float add = RespawnConfig.getHitPoints(e.player.getDisplayName());
            float current = e.player.getMaxHealth();
            System.out.println("def+add=" + (defaulthp+add));
            /[I]if(current != defaulthp + add){[/I]/e.player.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(defaulthp + add);//}
            updateHealth((EntityPlayerMP) e.player);
        }
        //updateHealth((EntityPlayerMP) e.player);
        //e.player.setHealth(e.player.getHealth());
        //e.player.heal(1f);
    }

    public static void updateHealth(EntityPlayerMP player) {
player.playerNetServerHandler.sendPacket(new S06PacketUpdateHealth(player.getHealth(), player.getFoodStats().getFoodLevel(),                      player.getFoodStats().getSaturationLevel()));
    }
 

tox1cozZ

aka Agravaine
8,455
598
2,892
Жесть, даже моя тема 2015 года всплыла :D
 
210
1
19
Поковырялся... Сделал вот такой метод и вызываю его отовсюду:
Java:
    public static void updateHealthModifier(EntityPlayer player) {
        float defaulthp = 20.0f;
        float add = RespawnConfig.getHitPoints(player.getDisplayName());
        IAttributeInstance healthAttribute = player.getEntityAttribute(SharedMonsterAttributes.maxHealth);
        float target = defaulthp + add;
        float currentmax = (float) healthAttribute.getAttributeValue();    
        float currenthealth = player.getHealth();
        float modify = target - currentmax;
        AttributeModifier moras = new AttributeModifier(UUID.randomUUID(), "Health Boost", modify, 0).setSaved(true);
        healthAttribute.applyModifier(moras);
        if(player.getMaxHealth() < currenthealth) player.setHealth(player.getMaxHealth());
        updateHealth((EntityPlayerMP) player);
        if(RespawnConfig.isDebug())System.out.println("Player=" + player.getDisplayName() + ", currentmax=" + currentmax + "hp, currenthp=" +
                                                                        currenthealth + "hp, add=" + add + "hp, modify=" + modify + "hp.");
    }
    
    public static void updateHealth(EntityPlayerMP player) {
        player.playerNetServerHandler.sendPacket(new S06PacketUpdateHealth(player.getHealth(), player.getFoodStats().getFoodLevel(), player.getFoodStats().getSaturationLevel()));
    }

В итоге теперь всё работает, кроме одного момента: когда у меня maxHealth больше 10 сердец - например, 15 - при телепортации в любой мир (PlayerChangedDimensionEvent) maxHealth делается требуемый, но здоровья показывает, что 10 сердец. При этом в логе пишет, что здоровья 15. И если быстренько перезайти в игру - всё встаёт на место. Если же maxHealth требуется меньше 10, то всё нормально вроде. Что я снова делаю не так?
 
210
1
19
Возможно, костыльнул, как индус, но работает:
Java:
    @SubscribeEvent
    public void onChangeDim(PlayerChangedDimensionEvent e){
        if(!e.player.worldObj.isRemote){
            if(RespawnConfig.isDebug())System.out.println("Fired 'PlayerChangedDimensionEvent' for player " + e.player.getDisplayName());
            Func.updateHealthModifier(e.player);
            float oldhp = e.player.getHealth();
            e.player.setHealth(oldhp - 0.001f);
            e.player.heal(0.001f);
        }
    }
 
210
1
19
@tox1cozZ
Вдогонку вопрос. У меня есть блоки, по ним бежишь - получаешь эффект зелья скорости. Но это, конечно, не тру. Используя полученные выше знания, я решил попробовать написать код, который увеличивает скорость иначе.
Java:
    /**
     * no effect     run: 0.13000000312924387,    step: 0.1000000149011612,
     * speed-1         run: 0.15600000414252285,    step: 0.12000000208616257,
     * speed-2         run: 0.1820000051558018,    step: 0.14000000268220902
     * 
     * @param player
     */
    public static void updateMoveSpeed(EntityPlayer player) {
        boolean boosted = player.getEntityData().getBoolean("SpeedBoosted");
        IAttributeInstance movespeedAttribute = player.getEntityAttribute(SharedMonsterAttributes.movementSpeed);
        double currentspeed = movespeedAttribute.getAttributeValue();
        boolean sprint = player.isSprinting();
        Block floor = player.worldObj.getBlock((int)player.posX, (int)player.posY - 1, (int)player.posZ);
        double targetspeed = sprint ? 0.13000000312924387 : 0.1000000149011612;
        if(floor instanceof Block_Pathway) {targetspeed = sprint ?  0.16 : 0.13;}    
        if(floor instanceof Block_Asphalt) {targetspeed = sprint ?  0.19 : 0.15;}
        double modify = targetspeed - currentspeed;
        AttributeModifier modifier = new AttributeModifier(UUID.randomUUID(), "Speed Boost", modify, 0).setSaved(true);
        movespeedAttribute.applyModifier(modifier);
    }
И вот скорость увеличивается, когда я на этом блоке. И уменьшается, когда я не на нём. Только проблема в том, что уменьшаю я скорость до той, которая должна быть дефолтная (там, где инициализируется переменная targetspeed). А ведь там могут быть какие-то эффекты - скорости или замедления или ещё чего-нибудь. Голода, например. Как мне получить правильную скорость, когда "я не на моём блоке"? Или может, как-то вообще иначе надо было всё реализовать? Подскажи, пожалуйста.
 

tox1cozZ

aka Agravaine
8,455
598
2,892
Честно, на верхние два вопроса ответить не могу, очень давно такое не писал. Насколько я помню, мне тогда хватало модификатора и его копирование в Clone ивенте.

У меня есть блоки, по ним бежишь - получаешь эффект зелья скорости.
Тут модификатор вообще не нужен.
В onCollidedWithBlock делай так: entity.motionX/Z *= 1.5D; // Ускорить на 50%
Пример есть в песке душ.
Только надо будет сделать блок чуть ниже по коллизии, буквально на пол пикселя. Заметно это никак не будет. Это нужно чтобы вызывался onCollidedWithBlock, а то игра не детектит полный блок, вроде.
 
210
1
19
Пример есть в песке душ.
Всё не так просто, совсем не просто.
Убил несколько часов и вот какие результаты:
1) Метод действительно рабочий, но если прибавлять, как пишешь ты, то скорость быстро растёт, не останавливаясь на каком-то пределе, пропорционально пройденному расстоянию. Поэтому я замудрил алгоритм, ограничивающий скорость - то есть как бы ладно, эту проблему решил.
2) Из-за того, что блок стал пониже по коллизии (я пробовал разные значения, у песка душ -0.125, я делал даже -0.005), с блока стало невозможно перебежать на ступеньки, не подпрыгивая. То есть при попытке взбежать на лестницу игрок останавливается, как будто в стену уперся.

В итоге всё насмарку, вернул пока, как было. .. :(
 
Сверху