Изменение здоровья игрока

Версия Minecraft
1.12.2
12
0
Недавно возникла проблема с изменением здоровья игрока. Банально - максимально выводит и использует только 1024. Не больше.
Меняю в апдейте игрока его макс. хп по формуле:
Код:
  public void update(EntityPlayer player)
   {
     if (player.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).getBaseValue() < (20 + ((this.level - 1) * 4.096F) * (2.048F * (this.level-1))) {
       player.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(20 + ((this.level - 1) * 4.096F) * (2.048F * (this.level-1)));
     }
}

Вывожу на экран при рендере хп:
Код:
if (e.getType() == RenderGameOverlayEvent.ElementType.HEALTH) {
      FontRenderer font = this.mc.fontRenderer;
       ScaledResolution res = new ScaledResolution(this.mc);
       int width = res.getScaledWidth();
       int height = res.getScaledHeight();
       double percent = this.mc.player.getHealth() / this.mc.player.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).getBaseValue();
       String str = String.format("%.0f/%.0f", new Object[] {  this.mc.player.getHealth() + this.mc.player.getAbsorptionAmount(), (float) this.mc.player.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).getBaseValue() });
      if (font.getStringWidth(str) > 79) {
         str = String.format("%.0f", new Object[] { (float) (this.mc.player.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).getBaseValue() + this.mc.player.getAbsorptionAmount()) });
      }
       rect(width / 2 - 91, height - 40, 81, 9, 2130706432);
       rect(width / 2 - 90, height - 39, 79, 7, 1056964608);
       rect(width / 2 - 90, height - 39, (int)(percent * 79.0D), 7, -1073807360);
      string(str, width / 2 - 90, height - 39, 16777215);
       GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
       this.mc.getTextureManager().bindTexture(ICONS);
       e.setCanceled(true);
     } else {}
Получаю в игре:
2019-02-22_21.21.24.png
Есть ли способ задать большее, чем 1024 здоровье игроку? Возможно SharedMonsterAttributes не совсем для этого подходят?
 
Решение
Хм, неужели в 1.12 ввели кап.
Да, так и есть. Странно, зачем они это сделали)
Нужно заюзать рефлексию:
Java:
public static boolean modifyFieldToFinal(Field field){
        try{
            if(field != null){
                Field modfield = Field.class.getDeclaredField("modifiers");
                modfield.setAccessible(true);
                modfield.setInt(field, field.getModifiers() & ~Modifier.FINAL);
                return true;
            }
        }catch(ReflectiveOperationException e){
            System.err.println("Failed to modify field with name " + field.getName() + " to final in class " + field.getDeclaringClass().getSimpleName());
        }

        return false;
    }

    public static <I, V> boolean...
1,038
57
229
обычно смерть игра помогает обновить максимальное здоровье, если не поможет. Значит видимо что то не так делаешь.
так что, "kill him!.." :D:cool:
 
5,021
47
784
Чего лол? Максимальное здоровье это 20 единиц. Чтобы сделать больше хукаешься в класс игрока и там ставишь как тебе нравится, потом просто получаешь. Что ты тут нагородил?
Какие ты там еще нафиг атрибуты юзаешь?
 

tox1cozZ

aka Agravaine
8,456
598
2,893
Во-первых, зачем это делать в апдейте, если можно делать в EntityJoinWorldEvent, чтобы один раз.
Во-вторых, после того как установил максимальное хп, нужно же отхилить игрока, логично?
В третьих, значение может быть мксимально Double.MAX_VALUE, а это овердохриллион.
 

tox1cozZ

aka Agravaine
8,456
598
2,893
Чего лол? Максимальное здоровье это 20 единиц.
getEntityPlayer().getMaxHealth() (или как то так)
Какие ты там еще нафиг атрибуты юзаешь?
Хоспаде, открой метод getMaxHealth и посмотри что он возвращает значение атрибута. Лишь бы ляпнуть.
 
5,021
47
784
12
0
Во-первых, зачем это делать в апдейте, если можно делать в EntityJoinWorldEvent, чтобы один раз.
Во-вторых, после того как установил максимальное хп, нужно же отхилить игрока, логично?
В третьих, значение может быть мксимально Double.MAX_VALUE, а это овердохриллион.

Мне нужно делать это при апдейте из-за системы левелинга, а именно: при изменении уровня меняется и здоровье игрока.
Хоть хилю, хоть не хилю: результат один: 1024.
Я знаю, что Double.MAX_VALUE это овердохрена. Именно по-этому я и задал вопрос.
 

tox1cozZ

aka Agravaine
8,456
598
2,893
А как хилишь-то? Я не увидел у тебя в коде этого: player.setHealth(player.getMaxHealth());
Здоровье игрока - 20 единиц. насрать что там в атрибутах. Ты чего?
Чо ты несешь-то? Здоровье не задано константой, а хранится в атрибуте. Можешь менять его как хочешь.
 

tox1cozZ

aka Agravaine
8,456
598
2,893
Хм, неужели в 1.12 ввели кап.
Да, так и есть. Странно, зачем они это сделали)
Нужно заюзать рефлексию:
Java:
public static boolean modifyFieldToFinal(Field field){
        try{
            if(field != null){
                Field modfield = Field.class.getDeclaredField("modifiers");
                modfield.setAccessible(true);
                modfield.setInt(field, field.getModifiers() & ~Modifier.FINAL);
                return true;
            }
        }catch(ReflectiveOperationException e){
            System.err.println("Failed to modify field with name " + field.getName() + " to final in class " + field.getDeclaringClass().getSimpleName());
        }

        return false;
    }

    public static <I, V> boolean setPrivateValue(Class<?> clazz, I instance, V value, String... names){
        try{
            Field field = ReflectionHelper.findField(clazz, names);
            if(Modifier.isFinal(field.getModifiers())){
                modifyFieldToFinal(field);
            }
            field.set(instance, value);
            return true;
        }catch(ReflectiveOperationException e){
            System.err.println("Failed to set private value in field with name " + "[" + Joiner.on("or ").join(names) + "]" + " in class " + clazz.getSimpleName());
        }
       
        return false;
    }
Где-то вызови один раз:
setPrivateValue(RangedAttribute.class, EntityLivingBase.MAX_HEALTH, Double.MAX_VALUE, "maximumValue", "тут укажи обфусцированное имя переменной maximumValue, найди его в маппингах");
 
Сверху