Вопросы по GUI

Версия Minecraft
1.16.5
API
Forge
Решение
Всё оказалось куда проще, чем я думал...
Java:
public void addHealthHandler(Supplier<NetworkEvent.ServerCustomPayloadLoginEvent.Context> ctx) {
        ctx.get().enqueueWork(() -> {
            PlayerEntity player = ctx.get().getSender();
            IBaseExperienceCapability expCap = IGenericCapability.getUnwrappedCapability(player,
                    PlayerExperienceCapabilityProvider.LEVEL_CAP);
            expCap.setMaxHealth(addHealth, maxHealth, player);
        });
        ctx.get().setPacketHandled(true);
    }
1,075
72
372
МожнА.
initGui() вызывается не только при открытии экрана, но также при изменении размера окна. Достаточно высчитывать размер элементов относительно размеров окна.
 
76
3
5
Как добавить title к тексту или кнопке в gui?
Так же не могу найти функции схожии с onFocus или onMouseOver, есть ли такие вообще?

P.s нашёл isHovered, isMouseOver, isFocused, но не пойму как присобачить свой border к кнопке.
 
Последнее редактирование:
76
3
5
Что я делаю не так?
вот мой Gui
UpgradeStatsGui:
public class UpgradeStatsGui extends Screen {
    protected UpgradeStatsGui(ITextComponent p_i51108_1_) {
        super(p_i51108_1_);
    }

    World world = Minecraft.getInstance().level;
    static PlayerEntity player = Minecraft.getInstance().player;
    FontRenderer fr = Minecraft.getInstance().font;
    public static IBaseExperienceCapability expCap = IGenericCapability.getUnwrappedCapability(player,
            PlayerExperienceCapabilityProvider.LEVEL_CAP);
    float currentPoints = expCap.getPoints();
    float strength = expCap.getStrength();
    float points = expCap.getPoints();
    float betterPoints = expCap.getBetterPoints();
    TranslationTextComponent current_strength = new TranslationTextComponent("Str: " + (int) strength);
    TranslationTextComponent current_points= new TranslationTextComponent(String.valueOf((int) points));
    TranslationTextComponent current_betterPoints = new TranslationTextComponent(String.valueOf((int) betterPoints));

    Button addStrength;

    ResourceLocation STATS_HUB_UPGRADE = new ResourceLocation(StalinRpg.MOD_ID, "textures/gui/menu/screens/menu_stats_upgrade.png");
    ResourceLocation BUTTON_ADD_STATS = new ResourceLocation(StalinRpg.MOD_ID, "textures/gui/menu/buttons/buttons_stats_add.png");


    public static void addToStr(PlayerEntity player) {
        float max_Hp = player.getMaxHealth();
        Objects.requireNonNull(((LivingEntity) player).getAttribute(MAX_HEALTH)).setBaseValue(max_Hp + 5);
        expCap.addStrength(1, player);
        expCap.removePoints(1, player);
    }

    @Override
    protected void init() {
        buttons.clear();
        buttons.add(addStrength = new ImageButton(this.width / 2 - 70, 89, 9, 9, 0, 0, 0, BUTTON_ADD_STATS, (button) -> {
            if (world.isClientSide) {
                if (currentPoints <= 0) {
                    return;
                } else {
                    addToStr(player);
                }
            } else
                return;
        }));
        this.addButton(addStrength);

        super.init();
    }

    @Override
    public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        this.renderBackground(matrixStack);
        RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
        this.minecraft.getTextureManager().bind(STATS_HUB_UPGRADE);
        int textureWidth = 256;
        int textureHeight = 156;
        blit(matrixStack, this.width / 2 - 130, 10, 0, 0, textureWidth, textureHeight);
        this.addStrength.render(matrixStack, mouseX, mouseY, partialTicks);
//        drawCenteredString(matrixStack, this.font, current_strength, this.width / 2 - 95, 90, 0xd50000);
        fr.draw(matrixStack, current_strength, this.width / 2 - 115, 90, 0xd50000);
        fr.draw(matrixStack, current_points, this.width / 2 - 79.5F, 33   , 0xd50000);
        fr.draw(matrixStack, current_betterPoints, this.width / 2 + 79.5F, 33, 0xd50000);
        super.render(matrixStack, mouseX, mouseY, partialTicks);
    }
}
Пытаюсь увеличить макс хп, оно прибовляется, но не регенится и не остаётся после смерти, где моя ошибка?
 
1,379
113
241
1. Все переменные должны быть инициализированы в конструкторе, иначе ты у тебя всё время будет одно и то же значение.
2. Капу игрока ты получаешь через клиентского, такое тоже нежелательно. Пиши в пакет, который открывает гуи, ещё и данные с игрока
3. Как и сказал человек выше, при нажатии на кнопоньку отправляй пакет с клиента на сервер о том, что она нажата. Дальше делай всё на сервере, иначе возможен пакетхак.
 
76
3
5
Создал тестовый предмет, на нём всё работает
Networking:
public class Networking {
    public static SimpleChannel INSTANCE;
    public static final String VERSION = "1.0";
    private static int ID = 0;

    public static int nextID() {
        return ID++;
    }

    public static void registerMessage() {
        INSTANCE = NetworkRegistry.newSimpleChannel(
                new ResourceLocation(StalinRpg.MOD_ID, "first_networking"),
                () -> VERSION,
                (version) -> version.equals(VERSION),
                (version) -> version.equals(VERSION)
        );
        INSTANCE.messageBuilder(SendPack.class, nextID())
                .encoder(SendPack::toBytes)
                .decoder(SendPack::new)
                .consumer(SendPack::handler)
                .add();
    }
}
SendPack:
public class SendPack {
    private final String message;
    public static final Logger LOGGER = LogManager.getLogger(MOD_ID);

    public SendPack(PacketBuffer buffer) {
        message = buffer.readUtf(Short.MAX_VALUE);
    }

    public SendPack(String message) {
        this.message = message;
    }

    public void toBytes(PacketBuffer buf) {
        buf.writeUtf(this.message);
    }

    public void handler(Supplier<NetworkEvent.Context> ctx) {
        ctx.get().enqueueWork(() -> {
            LOGGER.info(this.message);
        });
        ctx.get().setPacketHandled(true);
    }
}
CommonEventHandler:
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD)
public class CommonEventHandler {
    @SubscribeEvent
    public static void onCommonSetup(FMLCommonSetupEvent event) {
        event.enqueueWork(Networking::registerMessage);
    }
}
TestMessage:
public class TestMessage extends Item {

    public TestMessage() {
        super(new Properties().tab(ModGroup.itemGroup));
    }

    @Override
    public ActionResult<ItemStack> use(World worldIn, PlayerEntity playerIn, Hand handIn) {
        if (playerIn.level.isClientSide) {
            Networking.INSTANCE.sendToServer(new SendPack("From the Client"));
        }
        if (!playerIn.level.isClientSide) {
            float max_hp = playerIn.getMaxHealth();
            Objects.requireNonNull(((LivingEntity) playerIn).getAttribute(MAX_HEALTH)).setBaseValue(max_hp + 5);
            Networking.INSTANCE.send(
                    PacketDistributor.PLAYER.with(
                            () -> (ServerPlayerEntity) playerIn
                    ),
                    new SendPack("From Server"));
        }
        return super.use(worldIn, playerIn, handIn);
    }
}
ItemRegistry:
public class ItemRegistry {
    public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, StalinRpg.MOD_ID);
    public static final RegistryObject<Item> obsidianIngot = ITEMS.register("first_gui", MainHubGuiItem::new);
    public static final RegistryObject<Item> obsidianIngot2 = ITEMS.register("test_network", TestMessage::new);
}

Перенёс это в кнопку и отрабатывает только клиент, чего я не панимаю?
Java:
public static void addToStr(World worldIn ,PlayerEntity playerIn) {
        float max_hp = playerIn.getMaxHealth();
        if (worldIn.isClientSide) {
            Networking.INSTANCE.sendToServer(new SendPack("From the Client"));
            expCap.addStrength(1, playerIn);
            expCap.removePoints(1, playerIn);
            Minecraft.getInstance().setScreen(new UpgradeStatsGui(new TranslationTextComponent(StalinRpg.MOD_ID + ".stats_hub_upgrade")));
        }
        if (!worldIn.isClientSide) {
            Objects.requireNonNull(((LivingEntity) playerIn).getAttribute(MAX_HEALTH)).setBaseValue(max_hp + 5);
            Networking.INSTANCE.send(
                    PacketDistributor.PLAYER.with(
                            () -> (ServerPlayerEntity) playerIn
                    ),
                    new SendPack("From Server"));
        }
    }

    @Override
    protected void init() {
        buttons.clear();
        buttons.add(addStrength = new ImageButton(this.width / 2 - 70, 89, 9, 9, 0, 0, 0, BUTTON_ADD_STATS, (button) -> {
            if (currentPoints == 0) {
                return;
            } else
                addToStr(world ,player);
        }));
        this.addButton(addStrength);

        super.init();
    }
 
76
3
5
не может сработать на клиентской?
Да я уже понял, что гуи только на клиентской части, но тогда как отлавливать нажатие кнопки на сервере?

Допустим я отправляю на сервер своё максимальное хп и хп, которое нужно прибавить, как мне теперь это всё сделать на серверной части?
Java:
Networking.INSTANCE.sendToServer(new SendPack("From the Client", maxHp, 1));
 
Да я уже понял, что гуи только на клиентской части, но тогда как отлавливать нажатие кнопки на сервере?
Создаёшь пакет --> пакет посылаешь на сервер --> передаёшь в него 3 типа данных((entityID допустим, или же UUID для проверки, что нажал именно ты, а не левый человек), макс кол-во хп, хп которое прибавить) --> ну и уже в классе пакета, выполняешь нужные тебе функции.
 
76
3
5
Создаёшь пакет
Создал
Java:
public class SendPack {
    private final float maxHealth;
    private final float addHealth;
    UUID UUID;
    public static final Logger LOGGER = LogManager.getLogger(MOD_ID);

    public SendPack(PacketBuffer buffer) {
        maxHealth = buffer.readFloat();
        addHealth = buffer.readFloat();
        UUID = buffer.readUUID();
    }

    public SendPack(float maxHealth, float addHealth, UUID UUID) {
        this.maxHealth = maxHealth;
        this.addHealth = addHealth;
        this.UUID = UUID;
    }

    public void toBytes(PacketBuffer buf) {
        buf.writeFloat(this.maxHealth);
        buf.writeFloat(this.addHealth);
        buf.writeUUID(this.UUID);
    }

    public void handler(Supplier<NetworkEvent.Context> ctx) {
        ctx.get().enqueueWork(() -> {
            LOGGER.info(this.maxHealth);
            LOGGER.info(this.addHealth);
            LOGGER.info(this.UUID);
        });
        ctx.get().setPacketHandled(true);
    }

    public void addHealth(PacketBuffer buf) {
        PlayerEntity player = Minecraft.getInstance().player;
        IBaseExperienceCapability expCap = IGenericCapability.getUnwrappedCapability(player,
                PlayerExperienceCapabilityProvider.LEVEL_CAP);
        expCap.setMaxHealth(addHealth, maxHealth, player);
    }
}
пакет посылаешь на сервер
Посылаю
Java:
Networking.INSTANCE.sendToServer(new SendPack(player.getMaxHealth(), 1, player.getUUID()));
ну и уже в классе пакета, выполняешь нужные тебе функции.
После нажатия прибавляет хп только на клиенте и выводит ошибку, что не так?(
Java:
[08:36:48] [Server thread/FATAL] [minecraft/ThreadTaskExecutor]: Error executing task on Server
java.lang.IndexOutOfBoundsException: readerIndex(1) + length(4) exceeds writerIndex(1): UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeHeapByteBuf(ridx: 1, widx: 1, cap: 256)
    at io.netty.buffer.AbstractByteBuf.checkReadableBytes0(AbstractByteBuf.java:1405) ~[netty-all-4.1.25.Final.jar:4.1.25.Final] {}
    at io.netty.buffer.AbstractByteBuf.readInt(AbstractByteBuf.java:786) ~[netty-all-4.1.25.Final.jar:4.1.25.Final] {}
    at io.netty.buffer.AbstractByteBuf.readFloat(AbstractByteBuf.java:833) ~[netty-all-4.1.25.Final.jar:4.1.25.Final] {}
    at net.minecraft.network.PacketBuffer.readFloat(PacketBuffer.java:817) ~[forge-1.16.5-36.2.34_mapped_official_1.16.5-recomp.jar:?] {re:classloading}
    at net.stalin.stalinrpg.network.networking.SendPack.<init>(SendPack.java:26) ~[main/:?] {re:classloading}
    at net.minecraftforge.fml.network.simple.IndexedMessageCodec.lambda$tryDecode$0(IndexedMessageCodec.java:120) ~[forge-1.16.5-36.2.34_mapped_official_1.16.5-recomp.jar:?] {re:classloading}
    at java.util.Optional.map(Optional.java:215) ~[?:1.8.0_352] {}
    at net.minecraftforge.fml.network.simple.IndexedMessageCodec.tryDecode(IndexedMessageCodec.java:120) ~[forge-1.16.5-36.2.34_mapped_official_1.16.5-recomp.jar:?] {re:classloading}
    at net.minecraftforge.fml.network.simple.IndexedMessageCodec.consume(IndexedMessageCodec.java:162) ~[forge-1.16.5-36.2.34_mapped_official_1.16.5-recomp.jar:?] {re:classloading}
    at net.minecraftforge.fml.network.simple.SimpleChannel.networkEventListener(SimpleChannel.java:80) ~[forge-1.16.5-36.2.34_mapped_official_1.16.5-recomp.jar:?] {re:classloading}
    at net.minecraftforge.eventbus.EventBus.doCastFilter(EventBus.java:247) ~[eventbus-4.0.0.jar:?] {}
    at net.minecraftforge.eventbus.EventBus.lambda$addListener$11(EventBus.java:239) ~[eventbus-4.0.0.jar:?] {}
    at net.minecraftforge.eventbus.EventBus.post(EventBus.java:302) ~[eventbus-4.0.0.jar:?] {}
    at net.minecraftforge.eventbus.EventBus.post(EventBus.java:283) ~[eventbus-4.0.0.jar:?] {}
    at net.minecraftforge.fml.network.NetworkInstance.dispatch(NetworkInstance.java:86) ~[forge:?] {re:classloading}
    at net.minecraftforge.fml.network.NetworkHooks.lambda$onCustomPayload$1(NetworkHooks.java:91) ~[forge:?] {re:classloading}
    at java.util.Optional.map(Optional.java:215) ~[?:1.8.0_352] {}
    at net.minecraftforge.fml.network.NetworkHooks.onCustomPayload(NetworkHooks.java:91) ~[forge:?] {re:classloading}
    at net.minecraft.network.play.ServerPlayNetHandler.handleCustomPayload(ServerPlayNetHandler.java:1413) ~[forge:?] {re:classloading}
    at net.minecraft.network.play.client.CCustomPayloadPacket.handle(CCustomPayloadPacket.java:42) ~[forge:?] {re:classloading}
    at net.minecraft.network.play.client.CCustomPayloadPacket.handle(CCustomPayloadPacket.java:12) ~[forge:?] {re:classloading}
    at net.minecraft.network.PacketThreadUtil.lambda$ensureRunningOnSameThread$0(PacketThreadUtil.java:19) ~[forge:?] {re:classloading}
    at net.minecraft.util.concurrent.TickDelayedTask.run(TickDelayedTask.java:17) ~[forge:?] {re:classloading}
    at net.minecraft.util.concurrent.ThreadTaskExecutor.doRunTask(ThreadTaskExecutor.java:136) ~[forge:?] {re:classloading,pl:accesstransformer:B}
    at net.minecraft.util.concurrent.RecursiveEventLoop.doRunTask(RecursiveEventLoop.java:22) ~[forge:?] {re:classloading}
    at net.minecraft.server.MinecraftServer.doRunTask(MinecraftServer.java:734) ~[forge:?] {re:classloading,pl:accesstransformer:B}
    at net.minecraft.server.MinecraftServer.doRunTask(MinecraftServer.java:159) ~[forge:?] {re:classloading,pl:accesstransformer:B}
    at net.minecraft.util.concurrent.ThreadTaskExecutor.pollTask(ThreadTaskExecutor.java:109) ~[forge:?] {re:classloading,pl:accesstransformer:B}
    at net.minecraft.server.MinecraftServer.pollTaskInternal(MinecraftServer.java:717) ~[forge:?] {re:classloading,pl:accesstransformer:B}
    at net.minecraft.server.MinecraftServer.pollTask(MinecraftServer.java:711) ~[forge:?] {re:classloading,pl:accesstransformer:B}
    at net.minecraft.util.concurrent.ThreadTaskExecutor.managedBlock(ThreadTaskExecutor.java:119) ~[forge:?] {re:classloading,pl:accesstransformer:B}
    at net.minecraft.server.MinecraftServer.waitUntilNextTick(MinecraftServer.java:697) ~[forge:?] {re:classloading,pl:accesstransformer:B}
    at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:646) ~[forge:?] {re:classloading,pl:accesstransformer:B}
    at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:232) ~[forge:?] {re:classloading,pl:accesstransformer:B}
    at java.lang.Thread.run(Thread.java:750) [?:1.8.0_352] {}
 
76
3
5
Всё оказалось куда проще, чем я думал...
Java:
public void addHealthHandler(Supplier<NetworkEvent.ServerCustomPayloadLoginEvent.Context> ctx) {
        ctx.get().enqueueWork(() -> {
            PlayerEntity player = ctx.get().getSender();
            IBaseExperienceCapability expCap = IGenericCapability.getUnwrappedCapability(player,
                    PlayerExperienceCapabilityProvider.LEVEL_CAP);
            expCap.setMaxHealth(addHealth, maxHealth, player);
        });
        ctx.get().setPacketHandled(true);
    }
 
Сверху