Solved GENERIC_MAX_HEALTH disappear after using bootstrapper

Noy

New member
Jan 8, 2023
15
1
0
1
After I used the bootstrapper to create my custom enchantment Glow, an unexpected error occurred.

It shows that GENERIC_MAX_HEALTH is not one of the member field in org.bukkit.attribute.Attribute. This seems to be an mapping error, I guess.

If I change it to the deprecated method Player.getMaxHealth() (or remove the bootstrapper), the error disappeared.

Paper version: 1.21.3-82

Java:
            cui.edit().layer(1, new Layer(0, 9).edit().marginTop(1).tile(size, true, index -> {
                var player = players[index];
                var health = String.format("%.1f", player.getHealth());
                var maxHealth = String.format("%.1f", player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue());// <--- THIS LINE
                var lore = new ArrayList<Component>();
                if (player.isOp()) {
                    lore.add(Component.text("- ", NamedTextColor.GRAY)
                            .append(Component.text("[OP]", NamedTextColor.RED, TextDecoration.BOLD)));
                }
                if (player.getAllowFlight()) {
                    lore.add(Component.text("- ", NamedTextColor.GRAY)
                            .append(Component.text("Allow Fly", NamedTextColor.RED)));
                }
                lore.addAll(List.of(
                        Component.text("- GameMode: ", NamedTextColor.GRAY)
                                .append(Component.text(player.getGameMode().name(), NamedTextColor.RED)),
                        Component.text("- UUID: ", NamedTextColor.GRAY)
                                .append(Component.text(player.getUniqueId().toString(), NamedTextColor.AQUA)),
                        Component.text("- Name: ", NamedTextColor.GRAY)
                                .append(Component.text(player.getName(), NamedTextColor.AQUA)),
                        Component.text("- World: ", NamedTextColor.GRAY)
                                .append(Component.text(player.getWorld().getName(), NamedTextColor.AQUA)),
                        Component.text("- Location: ", NamedTextColor.GRAY)
                                .append(Component.text(player.getLocation().getBlockX(), NamedTextColor.AQUA))
                                .append(Component.text(","))
                                .append(Component.text(player.getLocation().getBlockY(), NamedTextColor.AQUA))
                                .append(Component.text(","))
                                .append(Component.text(player.getLocation().getBlockZ(), NamedTextColor.AQUA)),
                        Component.text("- Health: ", NamedTextColor.GRAY)
                                .append(Component.text(health, NamedTextColor.AQUA)).append(Component.text("/"))
                                .append(Component.text(maxHealth, NamedTextColor.AQUA)),
                        Component.text("- Food: ", NamedTextColor.GRAY)
                                .append(Component.text(player.getFoodLevel(), NamedTextColor.AQUA)),
                        Component.text("- Level: ", NamedTextColor.GRAY)
                                .append(Component.text(player.getLevel(), NamedTextColor.AQUA)),
                        Component.text("- Exp: ", NamedTextColor.GRAY)
                                .append(Component.text(player.getExp(), NamedTextColor.AQUA))));
                return Button.builder().skull(player).displayName(player.displayName()).lore(lore)
                        .click(cuiClickEvent -> {
                            if (cuiClickEvent.getClickType().isLeftClick()) {
                                getByPlayer(player).createCamera().open(cuiClickEvent.getPlayer(), true);
                            }
                        }).build();
            }).done()).done();

Code:
java.lang.NoSuchFieldError: Class org.bukkit.attribute.Attribute does not have member field 'org.bukkit.attribute.Attribute GENERIC_MAX_HEALTH'
    at ChestUI-1.0.1-SNAPSHOT.jar/fun.polyvoxel.cui.prebuilt.PlayerMonitor$MonitorAllPlayersHandler.lambda$refresh$9(PlayerMonitor.java:137) ~[ChestUI-1.0.1-SNAPSHOT.jar:?]
    at ChestUI-1.0.1-SNAPSHOT.jar/fun.polyvoxel.cui.layer.Layer$Editor.lambda$tile$4(Layer.java:314) ~[ChestUI-1.0.1-SNAPSHOT.jar:?]
    at ChestUI-1.0.1-SNAPSHOT.jar/fun.polyvoxel.cui.layer.Layer$Editor.slot(Layer.java:232) ~[ChestUI-1.0.1-SNAPSHOT.jar:?]
    at ChestUI-1.0.1-SNAPSHOT.jar/fun.polyvoxel.cui.layer.Layer$Editor.tile(Layer.java:314) ~[ChestUI-1.0.1-SNAPSHOT.jar:?]
    at ChestUI-1.0.1-SNAPSHOT.jar/fun.polyvoxel.cui.prebuilt.PlayerMonitor$MonitorAllPlayersHandler.refresh(PlayerMonitor.java:134) ~[ChestUI-1.0.1-SNAPSHOT.jar:?]
    at ChestUI-1.0.1-SNAPSHOT.jar/fun.polyvoxel.cui.prebuilt.PlayerMonitor$MonitorAllPlayersHandler.onInitialize(PlayerMonitor.java:113) ~[ChestUI-1.0.1-SNAPSHOT.jar:?]
    at ChestUI-1.0.1-SNAPSHOT.jar/fun.polyvoxel.cui.ui.CUIInstance.<init>(CUIInstance.java:38) ~[ChestUI-1.0.1-SNAPSHOT.jar:?]
    at ChestUI-1.0.1-SNAPSHOT.jar/fun.polyvoxel.cui.ui.CUIType.createInstance(CUIType.java:158) ~[ChestUI-1.0.1-SNAPSHOT.jar:?]
    at ChestUI-1.0.1-SNAPSHOT.jar/fun.polyvoxel.cui.prebuilt.PlayerMonitor.getAllPlayers(PlayerMonitor.java:67) ~[ChestUI-1.0.1-SNAPSHOT.jar:?]
    at ChestUI-1.0.1-SNAPSHOT.jar/fun.polyvoxel.cui.prebuilt.PlayerMonitor.lambda$onInitialize$0(PlayerMonitor.java:42) ~[ChestUI-1.0.1-SNAPSHOT.jar:?]
    at ChestUI-1.0.1-SNAPSHOT.jar/fun.polyvoxel.cui.ui.CUIType.trigger(CUIType.java:193) ~[ChestUI-1.0.1-SNAPSHOT.jar:?]
    at ChestUI-1.0.1-SNAPSHOT.jar/fun.polyvoxel.cui.ui.CUIType.display(CUIType.java:189) ~[ChestUI-1.0.1-SNAPSHOT.jar:?]
    at ChestUI-1.0.1-SNAPSHOT.jar/fun.polyvoxel.cui.prebuilt.CUIMonitor$MainHandler.lambda$refresh$0(CUIMonitor.java:177) ~[ChestUI-1.0.1-SNAPSHOT.jar:?]
    at ChestUI-1.0.1-SNAPSHOT.jar/fun.polyvoxel.cui.slot.Button$Builder.lambda$click$0(Button.java:187) ~[ChestUI-1.0.1-SNAPSHOT.jar:?]
    at ChestUI-1.0.1-SNAPSHOT.jar/fun.polyvoxel.cui.slot.Button.click(Button.java:44) ~[ChestUI-1.0.1-SNAPSHOT.jar:?]
    at ChestUI-1.0.1-SNAPSHOT.jar/fun.polyvoxel.cui.layer.Layer.click(Layer.java:146) ~[ChestUI-1.0.1-SNAPSHOT.jar:?]
    at ChestUI-1.0.1-SNAPSHOT.jar/fun.polyvoxel.cui.ui.Camera.click(Camera.java:382) ~[ChestUI-1.0.1-SNAPSHOT.jar:?]
    at ChestUI-1.0.1-SNAPSHOT.jar/fun.polyvoxel.cui.ui.CUIManager.onClick(CUIManager.java:332) ~[ChestUI-1.0.1-SNAPSHOT.jar:?]
    at com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor15.execute(Unknown Source) ~[?:?]
    at org.bukkit.plugin.EventExecutor$2.execute(EventExecutor.java:77) ~[paper-api-1.21.3-R0.1-SNAPSHOT.jar:?]
    at co.aikar.timings.TimedEventExecutor.execute(TimedEventExecutor.java:80) ~[paper-api-1.21.3-R0.1-SNAPSHOT.jar:?]
    at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:70) ~[paper-api-1.21.3-R0.1-SNAPSHOT.jar:?]
    at io.papermc.paper.plugin.manager.PaperEventManager.callEvent(PaperEventManager.java:54) ~[paper-1.21.3.jar:1.21.3-82-5a60ffb]
    at io.papermc.paper.plugin.manager.PaperPluginManagerImpl.callEvent(PaperPluginManagerImpl.java:131) ~[paper-1.21.3.jar:1.21.3-82-5a60ffb]
    at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:628) ~[paper-api-1.21.3-R0.1-SNAPSHOT.jar:?]
    at net.minecraft.server.network.ServerGamePacketListenerImpl.handleContainerClick(ServerGamePacketListenerImpl.java:3250) ~[paper-1.21.3.jar:1.21.3-82-5a60ffb]
    at net.minecraft.network.protocol.game.ServerboundContainerClickPacket.handle(ServerboundContainerClickPacket.java:69) ~[paper-1.21.3.jar:1.21.3-82-5a60ffb]
    at net.minecraft.network.protocol.game.ServerboundContainerClickPacket.handle(ServerboundContainerClickPacket.java:33) ~[paper-1.21.3.jar:1.21.3-82-5a60ffb]
    at net.minecraft.network.protocol.PacketUtils.lambda$ensureRunningOnSameThread$0(PacketUtils.java:55) ~[paper-1.21.3.jar:1.21.3-82-5a60ffb]
    at net.minecraft.server.TickTask.run(TickTask.java:18) ~[paper-1.21.3.jar:1.21.3-82-5a60ffb]
    at net.minecraft.util.thread.BlockableEventLoop.doRunTask(BlockableEventLoop.java:154) ~[paper-1.21.3.jar:1.21.3-82-5a60ffb]
    at net.minecraft.util.thread.ReentrantBlockableEventLoop.doRunTask(ReentrantBlockableEventLoop.java:24) ~[paper-1.21.3.jar:1.21.3-82-5a60ffb]
    at net.minecraft.server.MinecraftServer.doRunTask(MinecraftServer.java:1578) ~[paper-1.21.3.jar:1.21.3-82-5a60ffb]
    at net.minecraft.server.MinecraftServer.doRunTask(MinecraftServer.java:207) ~[paper-1.21.3.jar:1.21.3-82-5a60ffb]
    at net.minecraft.util.thread.BlockableEventLoop.pollTask(BlockableEventLoop.java:128) ~[paper-1.21.3.jar:1.21.3-82-5a60ffb]
    at net.minecraft.server.MinecraftServer.pollTaskInternal(MinecraftServer.java:1555) ~[paper-1.21.3.jar:1.21.3-82-5a60ffb]
    at net.minecraft.server.MinecraftServer.pollTask(MinecraftServer.java:1548) ~[paper-1.21.3.jar:1.21.3-82-5a60ffb]
    at net.minecraft.util.thread.BlockableEventLoop.managedBlock(BlockableEventLoop.java:138) ~[paper-1.21.3.jar:1.21.3-82-5a60ffb]
    at net.minecraft.server.MinecraftServer.managedBlock(MinecraftServer.java:1499) ~[paper-1.21.3.jar:1.21.3-82-5a60ffb]
    at net.minecraft.server.MinecraftServer.waitUntilNextTick(MinecraftServer.java:1509) ~[paper-1.21.3.jar:1.21.3-82-5a60ffb]
    at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:1345) ~[paper-1.21.3.jar:1.21.3-82-5a60ffb]
    at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:340) ~[paper-1.21.3.jar:1.21.3-82-5a60ffb]
    at java.base/java.lang.Thread.run(Thread.java:1583) ~[?:?]
 

Machine Maker

Paper Developer
Staff member
Dec 17, 2021
151
6
24
18
California
GENERIC_MAX_HEALTH was renamed in some recent update. Make sure your api dependency is up to date. There is no backwards compatibility promised yet for paper plugins as they are still experimental. So they don't go through the bytecode rewrites required to update plugin bytecode to the new names for renames.
 
  • Like
Reactions: Noy

Noy

New member
Jan 8, 2023
15
1
0
1
GENERIC_MAX_HEALTH was renamed in some recent update. Make sure your api dependency is up to date. There is no backwards compatibility promised yet for paper plugins as they are still experimental. So they don't go through the bytecode rewrites required to update plugin bytecode to the new names for renames.
You are right! It was renamed to MAX_HEALTH after changing the API version to 1.21.4. But I'm still confused:

1. When I use 1.21.3 server jar, with a 1.21.1 API, this bug didn't occur until I added a bootstrapper. They should be irrelevant

// 2. If the experimental phase ends in the future, should we add a @Deprecated GENERIC_MAX_HEALTH for compatibility?
 

Machine Maker

Paper Developer
Staff member
Dec 17, 2021
151
6
24
18
California
bug didn't occur until I added a bootstrapper

No, it is relevant. If you use paper-plugin.yml, your plugin's bytecode is not rewritten to handle the renaming because all of paper plugins are experimental. If you used a plugin.yml, then it was handled correctly.

No, no such compatibility will be added. Only for changes made after paper plugins leave experimental status, not changes from before.
 
  • Like
Reactions: Noy