-
[1.18.1] Render Fluid in GUI [Solved]
Ah, I should have bound InventoryMenu.BLOCK_ATLAS. Sorry.
-
[1.18.1] Render Fluid in GUI [Solved]
It still renders the same. private void renderFluid(@NotNull PoseStack matrixStack, FluidStack fluid, int maxFluid) { drawString(matrixStack, this.font, "fluid: " + fluid.getAmount() + " / " + maxFluid + " (" + fluid.getDisplayName().getString() + ")", 10, 25, 0xFFFFFF); if (!fluid.isEmpty() && this.minecraft != null) { int scaledHeight = Tools.scaled(fluid.getAmount(), maxFluid, 48); if (scaledHeight > 0) { FluidAttributes fluidAttributes = fluid.getFluid().getAttributes(); ResourceLocation fluidLoc = fluidAttributes.getStillTexture(fluid); TextureAtlasSprite sprite = minecraft.getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(fluidLoc); int color = fluidAttributes.getColor(); int yCount = scaledHeight / 16; int yRemainder = scaledHeight % 16; RenderSystem.setShaderTexture(0, new ResourceLocation(fluidLoc.getNamespace(), "textures/" + fluidLoc.getPath() + ".png")); RenderSystem.setShaderColor(((color >> 16) & 0xFF) / 255f, ((color >> 8) & 0xFF) / 255f, (color & 0xFF) / 255f, ((color >> 24) & 0xFF) / 255f); for (int i = 1; i <= yCount; i++) { blit(matrixStack, this.leftPos + 98, this.topPos + 66 - 16 * i, 0, 16, 16, sprite); } blit(matrixStack, this.leftPos + 98, this.topPos + 66 - 16 * yCount - yRemainder, 0, 16, yRemainder, sprite); // reset color RenderSystem.setShaderColor(1f, 1f, 1f, 1f); } } } (TextureAtlasSprite sprite = minecraft.getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(fluidLoc); The sprite height is just 16.)
-
[1.18.1] Render Fluid in GUI [Solved]
How can I get fluid texture's height? Ah, I got. TextureAtlasSprite fluidSprite = minecraft.getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(fluidLoc); int textureHeight = fluidSprite.getHeight();
-
[1.18.1] Render Fluid in GUI [Solved]
Ah! Okay. Thank you!
-
[1.18.1] Render Fluid in GUI [Solved]
Rendering was successful, but it's a bit different from what I intended. And what I intend is this. in RenderFluid() FluidAttributes fluidAttributes = fluid.getFluid().getAttributes(); ResourceLocation fluidLoc = fluidAttributes.getStillTexture(fluid); RenderSystem.setShaderTexture(0, new ResourceLocation(fluidLoc.getNamespace(), "textures/" + fluidLoc.getPath() + ".png")); int color = fluidAttributes.getColor(); RenderSystem.setShaderColor(((color >> 16) & 0xFF) / 255f, ((color >> 8) & 0xFF) / 255f, (color & 0xFF) / 255f, ((color >> 24) & 0xFF) / 255f); int scaledHeight = Tools.scaled(fluid.getAmount(), maxFluid, 48); blit(matrixStack, this.leftPos + 98, this.topPos + 66 - scaledHeight, 0, 17, 16, scaledHeight); Tools.scaled public static int scaled(float value, float maxValue, int height) { if (value <= 0 || maxValue <= 0) { return 0; } return (int) (value / maxValue * height); }
-
[1.18.1] Render Fluid in GUI [Solved]
I've been trying to render a fluid to the gui. And referenced here. But the result is this: public class LavaGeneratorScreen extends AbstractContainerScreen<LavaGeneratorMenu> { private final ResourceLocation GUI = new ResourceLocation(GeneratorMod.MODID, "textures/gui/lava_generator_gui.png"); public LavaGeneratorScreen(LavaGeneratorMenu menu, Inventory playerInv, Component title) { super(menu, playerInv, title); } @Override public void render(@NotNull PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) { this.renderBackground(matrixStack); super.render(matrixStack, mouseX, mouseY, partialTicks); FluidStack fluid = menu.getFluid().copy(); int maxFluid = menu.getMaxFluidAmount(); renderFluid(matrixStack, fluid, maxFluid); this.renderTooltip(matrixStack, mouseX, mouseY); } private void renderFluid(@NotNull PoseStack matrixStack, FluidStack fluid, int maxFluid) { drawString(matrixStack, this.font, "fluid: " + fluid.getAmount() + " / " + maxFluid + " (" + fluid.getDisplayName().getString() + ")", 10, 20, 0xFFFFFF); if (!fluid.isEmpty() && this.minecraft != null) { FluidAttributes fluidAttributes = fluid.getFluid().getAttributes(); ResourceLocation fluidLoc = fluidAttributes.getFlowingTexture(fluid); TextureAtlasSprite fluidSprite = minecraft.getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(fluidLoc); minecraft.getTextureManager().bindForSetup(new ResourceLocation(fluidLoc.getNamespace(), "textures/" + fluidLoc.getPath() + ".png")); int color = fluidAttributes.getColor(); GlStateManager._clearColor(((color >> 16) & 0xFF) / 255f, ((color >> 8) & 0xFF) / 255f, (color & 0xFF) / 255f, ((color >> 24) & 0xFF) / 255f); int scaledHeight = Tools.scaled(fluid.getAmount(), maxFluid, 48); blit(matrixStack, this.leftPos + 98, this.topPos + 66 - scaledHeight, 0, 16, scaledHeight, fluidSprite); } } @Override protected void renderBg(@NotNull PoseStack matrixStack, float partialTick, int mouseX, int mouseY) { RenderSystem.setShaderTexture(0, GUI); this.blit(matrixStack, this.leftPos, this.topPos, 0, 0, this.imageWidth, this.imageHeight); } } What's wrong?
-
[1.18.1] Syncing Fluid Capability in BlockEntity [Solved]
In Container class, I change "this.fluid = newFluid;" -> "this.fluid = newFluid.copy();" And It works correctly. And I wonder if I should use fluid.copy() in Packet as well.
-
[1.18.1] Syncing Fluid Capability in BlockEntity [Solved]
It seems to have been solved by rewriting the code from scratch. thank you! Is it correct to do this? If this method is correct, I will post the code for other people to refer to as well. (For other parts, refer to mcjty's block entity and container tutorial.) there's a bug again. Real-time update doesn't work. Should the block entity also send packets? (Container Class) public class LavaGeneratorMenu extends AbstractContainerMenu { private final BlockEntity blockEntity; private final ContainerLevelAccess access; private final IItemHandler playerInventory; private FluidStack fluid; private final Player player; public LavaGeneratorMenu(int windowId, Inventory playerInv, BlockPos pos) { super(ModMenuTypes.LAVA_GENERATOR_CONTAINER.get(), windowId); this.playerInventory = new InvWrapper(playerInv); this.access = ContainerLevelAccess.create(playerInv.player.level, pos); this.player = playerInv.player; this.fluid = FluidStack.EMPTY; ... } public FluidStack getFluid() { return blockEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY).map(f -> f.getFluidInTank(0)).orElse(FluidStack.EMPTY); } @Override public boolean stillValid(@NotNull Player player) { return stillValid(access, player, ModBlocks.LAVA_GENERATOR.get()); } @Override public void broadcastChanges() { super.broadcastChanges(); if (player instanceof ServerPlayer sp) { FluidStack newFluid = getFluid(); if (fluid.getAmount() != newFluid.getAmount() || !fluid.isFluidEqual(newFluid)) { PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> sp), new FluidUpdatePacket(blockEntity.getBlockPos(), newFluid)); this.fluid = newFluid; } } } @Override public void sendAllDataToRemote() { super.sendAllDataToRemote(); if (player instanceof ServerPlayer sp) { PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> sp), new FluidUpdatePacket(blockEntity.getBlockPos(), getFluid())); } } } (FluidUpdatePacket) public class FluidUpdatePacket { public final BlockPos bePos; public final FluidStack fluid; public FluidUpdatePacket(BlockPos pos, FluidStack fluid) { this.bePos = pos; this.fluid = fluid; } public void encode(FriendlyByteBuf buffer) { buffer.writeBlockPos(bePos); buffer.writeFluidStack(fluid); } public static FluidUpdatePacket decode(FriendlyByteBuf buffer) { return new FluidUpdatePacket(buffer.readBlockPos(), buffer.readFluidStack()); } public static void handle(FluidUpdatePacket msg, Supplier<NetworkEvent.Context> ctx) { AtomicBoolean success = new AtomicBoolean(false); ctx.get().enqueueWork(() -> { DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> success.set(ClientAccess.updateFluid(msg.bePos, msg.fluid))); }); ctx.get().setPacketHandled(success.get()); } } (ClientAccess (needed in Packet)) public class ClientAccess { public static boolean updateFluid(BlockPos pos, FluidStack fluid) { AtomicBoolean success = new AtomicBoolean(false); if (Minecraft.getInstance().level != null) { final BlockEntity blockEntity = Minecraft.getInstance().level.getBlockEntity(pos); if (blockEntity != null) { blockEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY).ifPresent(h -> { if (h instanceof FluidTank tank) { tank.setFluid(fluid); success.set(true); } }); } } return success.get(); } } Edit) I removed the "if (fluid.getAmount() != newFluid.getAmount() || !fluid.isFluidEqual(newFluid)) {" which is part of the container class and synchronized it unconditionally, and it worked fine.
-
[1.18.1] Syncing Fluid Capability in BlockEntity [Solved]
Synchronization from server to client was successful. However, when I reconnected to the world, it was out of sync. (It says the fluid is empty.) What's wrong? (If the fluid changes again, it will resynchronize.) In MyBlockEntity.class @Override public void setChanged() { super.setChanged(); onFluidChanged(); } private void onFluidChanged() { if (level != null) { PacketHandler.INSTANCE.send(PacketDistributor.TRACKING_CHUNK.with(() -> level.getChunkAt(worldPosition)), new FluidUpdatePacket(worldPosition, fluidTank.getFluid())); } } @Override public void load(CompoundTag tag) { ... if (tag.contains("Fluid")) { fluidTank.readFromNBT(tag.getCompound("Fluid")); } super.load(tag); onFluidChanged(); }
-
[1.18.1] Syncing Fluid Capability in BlockEntity [Solved]
Sorry to keep asking basic questions. More specifically, after creating a packet from the server to the client, should I send this packet in sendAllDataToRemoted() of the Menu class?
-
[1.18.1] Syncing Fluid Capability in BlockEntity [Solved]
Ok, Thank you.
-
[1.18.1] Syncing Fluid Capability in BlockEntity [Solved]
In the mcjty tutorial I saw, inventory was synchronized using slots and energy using data slots. But what about fluid?
-
[1.18.1] Syncing Fluid Capability in BlockEntity [Solved]
I choose 2nd. And like this? MyBlockEntity private final FluidTank fluidTank = createFluidTank(); private final LazyOptional<IFluidHandler> fluidHandler = LazyOptional.of(() -> fluidTank); ... public void loadClient(CompoundTag tag) { if (tag.contains("Fluid")) { fluidTank.readFromNBT(tag.getCompound("Fluid")); } } public void saveClient(CompoundTag tag) { CompoundTag fluid = new CompoundTag(); fluidTank.writeToNBT(fluid); tag.put("Fluid", fluid); } @NotNull @Override public CompoundTag getUpdateTag() { CompoundTag tag = super.getUpdateTag(); saveClient(tag); return tag; } @Override public void handleUpdateTag(CompoundTag tag) { if (tag != null) { loadClient(tag); } } ... private FluidTank createFluidTank() { return new FluidTank(FLUID_CAPACITY, (fluid -> fluid.getFluid().is(FluidTags.LAVA))) { @Override protected void onContentsChanged() { setChanged(); } }; } @Override public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) { if (cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { return fluidHandler.cast(); } else { return super.getCapability(cap, side); } } And MyContainerMenu public FluidStack getFluid() { return blockEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY).map(f -> f.getFluidInTank(0).copy()).orElse(null); } And In Screen: FluidStack fluid = menu.getFluid() The values are out of sync.
-
[1.18.1] Syncing Fluid Capability in BlockEntity [Solved]
I have created a fluid capability on the block entity. Now I want to display this liquid in the GUI. (Type and amount of liquid) But I have no idea how to synchronize this capability in container or screen.
-
[1.16.5] Add Potion
public static final RegistryObject<Potion> EXPLOSIVE_POTION = POTIONS.register("explosive", () -> new Potion(new EffectInstance(EXPLOSIVE_EFFECT.get(), 1200, 0))); public static final RegistryObject<Potion> LONG_EXPLOSIVE_POTION = POTIONS.register("long_explosive", () -> new Potion(new EffectInstance(EXPLOSIVE_EFFECT.get(), 2400, 0))); public static final RegistryObject<Potion> STRONG_EXPLOSIVEPOTION = POTIONS.register("strong_explosive", () -> new Potion(new EffectInstance(EXPLOSIVE_EFFECT.get(), 600, 2))); It worked! Thank you!
IPS spam blocked by CleanTalk.