Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

[1.15.2] Fluid Tanks


Issac29
 Share

Recommended Posts

Alright, I am currently working on the fluid tanks that display how much fluid is the tile. The problem is I don't know how to display the fluid and render.

Here are some Codes

Tile Entity Code:

Spoiler

package com.mreyeballs29.itnc.tileentity;

import com.mreyeballs29.itnc.inventory.TankContainer;

import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.fluid.Fluid;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.templates.FluidTank;
import net.minecraftforge.registries.ForgeRegistries;

public class TankTileEntity extends TileEntity implements INamedContainerProvider {

	private final FluidTank tank = new FluidTank(8000);
	private LazyOptional<FluidTank> optional = LazyOptional.of(() -> tank);
	
	public TankTileEntity() {
		super(INCTileEntityTypes.TANK);
	}
	
	public FluidTank getTank() {
		return tank;
	}
	
	private void deseralize(CompoundNBT nbt, FluidTank fluidtank) {
		Fluid fluid = null;
		int amount = 0;
		if (nbt.contains("fluid")) {
			String string = nbt.getString("fluid");
			fluid = ForgeRegistries.FLUIDS.getValue(new ResourceLocation(string));
		}
		if (nbt.contains("amount")) {
			amount = nbt.getInt("amount");
		}
		if (fluid != null && amount > 0) {
			fluidtank.setFluid(new FluidStack(fluid, amount));
		} else {
			fluidtank.setFluid(FluidStack.EMPTY);
		}
	}
	
	private CompoundNBT seralize(FluidTank fluidtank) {
		CompoundNBT nbt = new CompoundNBT();
		FluidStack fluidstack = fluidtank.getFluid();
		nbt.putString("fluid", fluidstack.getFluid().getRegistryName().toString());
		nbt.putInt("amount", fluidstack.getAmount());
		return nbt;
	}
	
	@Override
	public void read(CompoundNBT compound) {
		CompoundNBT nbtfluid = compound.getCompound("tank");
		optional.ifPresent(h -> {deseralize(nbtfluid, h);});
		super.read(compound);
	}
	
	@Override
	public CompoundNBT write(CompoundNBT compound) {
		optional.ifPresent(h -> {CompoundNBT nbt = seralize(h); compound.put("tank", nbt);});
		return super.write(compound);
	}

	@Override
	public <T> LazyOptional<T> getCapability(Capability<T> cap) {
		return cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY ? optional.cast() : super.getCapability(cap);
	}

	@Override
	public Container createMenu(int p_createMenu_1_, PlayerInventory p_createMenu_2_, PlayerEntity p_createMenu_3_) {
		return new TankContainer(p_createMenu_1_, world, pos, p_createMenu_2_, p_createMenu_3_);
	}

	@Override
	public ITextComponent getDisplayName() {
		return new TranslationTextComponent("container.tank");
	}
}

 

 

Screen Code:

Spoiler

package com.mreyeballs29.itnc.client.gui.screen.inventory;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.mojang.blaze3d.platform.GlStateManager;
import com.mreyeballs29.itnc.inventory.TankContainer;
import com.mreyeballs29.itnc.tileentity.TankTileEntity;

import net.minecraft.block.Block;
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.client.gui.widget.Widget;
import net.minecraft.client.renderer.texture.AtlasTexture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.PlayerContainer;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.fluids.capability.templates.FluidTank;

public class TankScreen extends ContainerScreen<TankContainer> {

	private static final ResourceLocation GUI = new ResourceLocation("itnc", "textures/gui/container/basic_tank.png");

	public TankScreen(TankContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
		super(screenContainer, inv, titleIn);
	}
	
	@Override
    public void render(int mouseX, int mouseY, float partialTicks) {
        this.renderBackground();
        super.render(mouseX, mouseY, partialTicks);
        this.renderHoveredToolTip(mouseX, mouseY);
    }
	
	private void addScreen() {
		Logger log = LogManager.getLogger();
		log.info(this.container);
		log.info(this.container.getTileEntity().getTank().getFluid());
		@SuppressWarnings("resource")
		TextureAtlasSprite sprite = getSprite(this.container.getTileEntity().getTank().getFluid().getFluid().getRegistryName());
		blit(56, 56, 2, 2, 200, sprite);
	}

	@SuppressWarnings("deprecation")
	public TextureAtlasSprite getSprite(ResourceLocation resourceLocation) {
		return this.minecraft.getAtlasSpriteGetter(AtlasTexture.LOCATION_BLOCKS_TEXTURE).apply(resourceLocation);
	}
	
	@Override
    protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY)
    {
        this.font.drawString(this.title.getFormattedText(), 8.0F, 7.0F, 4210752);
        this.font.drawString(this.playerInventory.getDisplayName().getFormattedText(), 8.0F, (float) (this.ySize - 96 + 5), 4210752);
        addScreen();
    }

	@SuppressWarnings({ "deprecation", "resource" })
	@Override
    protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
        GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
        this.minecraft.getTextureManager().bindTexture(GUI);
        int relX = (this.width - this.xSize) / 2;
        int relY = (this.height - this.ySize+3) / 2;
        this.blit(relX, relY, 0, 0, this.xSize, this.ySize+3);
    }

}

 

 

Container Code:

Spoiler

package com.mreyeballs29.itnc.inventory;

import com.mreyeballs29.itnc.tileentity.TankTileEntity;

import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.SlotItemHandler;
import net.minecraftforge.items.wrapper.InvWrapper;

public class TankContainer extends Container {
	
	private TileEntity tileEntity;
	private PlayerEntity playerEntity;
	private InvWrapper playerInventory;
	
	public TankContainer(int id, World world, BlockPos pos, PlayerInventory inv, PlayerEntity playerEntity2) {
		super(INContainerTypes.TANK, id);
		
		tileEntity = world.getTileEntity(pos);
		playerEntity = playerEntity2;
		playerInventory = new InvWrapper(inv);
		layoutPlayerInventorySlots(8, 87);
	}
	
	public TankTileEntity getTileEntity() {
		return (TankTileEntity) tileEntity;
	}
	
	private int addSlotRange(IItemHandler handler, int index, int x, int y, int amount, int dx) {
        for (int i = 0 ; i < amount ; i++) {
            addSlot(new SlotItemHandler(handler, index, x, y));
            x += dx;
            index++;
        }
        return index;
    }

    private int addSlotBox(IItemHandler handler, int index, int x, int y, int horAmount, int dx, int verAmount, int dy) {
        for (int j = 0 ; j < verAmount ; j++) {
            index = addSlotRange(handler, index, x, y, horAmount, dx);
            y += dy;
        }
        return index;
    }

    private void layoutPlayerInventorySlots(int leftCol, int topRow) {
        addSlotBox(playerInventory, 9, leftCol, topRow, 9, 18, 3, 18);

        topRow += 58;
        addSlotRange(playerInventory, 0, leftCol, topRow, 9, 18);
    }

	@Override
	public boolean canInteractWith(PlayerEntity playerIn) {
		return !(playerEntity.getDistanceSq((double)tileEntity.getPos().getX() + 0.5D, (double)this.tileEntity.getPos().getY() + 0.5D, (double)this.tileEntity.getPos().getZ() + 0.5D) > 64.0D);
	}

}

 

 

Link to comment
Share on other sites

1 hour ago, Issac29 said:

Yeah, but that texture needs to bind into the GUI which is the problem. I tried to use  Minecraft#getAltasSprtiteGettter but I get a mess of textures.

All block textures exist on one texture sheet. You can bind it using PlayerContainer.LOCATION_BLOCKS_TEXTURE. The TextureAtlasSprite then tells you the u v coordinates in that atlas texture.

Link to comment
Share on other sites

31 minutes ago, diesieben07 said:

All block textures exist on one texture sheet. You can bind it using PlayerContainer.LOCATION_BLOCKS_TEXTURE. The TextureAtlasSprite then tells you the u v coordinates in that atlas texture.

I tried using the method blit(int a, int b, int c, int d, int e, TextureAltasSprite f)but that did not work.

Link to comment
Share on other sites

I used water as an example. The parameters were 16, 16, one, 16, 16, and water. Did I forget something?

private void addScreen() {
    @SuppressWarnings("resource")
    TextureAtlasSprite sprite = getSprite(new ResourceLocation("minecraft", "water"));
    // This is the one I used
    blit(16, 16, 1, 16, 16, sprite);
}

public TextureAtlasSprite getSprite(ResourceLocation resourceLocation) {
   return this.minecraft.getAtlasSpriteGetter(PlayerContainer.LOCATION_BLOCKS_TEXTURE).apply(resourceLocation);
}
	
@Override
protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
    this.font.drawString(this.title.getFormattedText(), 8.0F, 7.0F, 4210752);
    this.font.drawString(this.playerInventory.getDisplayName().getFormattedText(), 8.0F, (float) (this.ySize - 96 + 5), 4210752);
    addScreen();
}

 

Link to comment
Share on other sites

2 minutes ago, diesieben07 said:

What on earth are you doing... Nothing about what you are doing there makes any sense.

I know it makes nonsense but I am trying to get the fluid texture into the tank screen. I used water as an example.

Link to comment
Share on other sites

30 minutes ago, Issac29 said:

I know it makes nonsense but I am trying to get the fluid texture into the tank screen. I used water as an example.

Anyway Here is the better code. 

 

	@SuppressWarnings("resource")
	private void addScreen(int x, int y) {
		TextureAtlasSprite sprite = getSprite(new ResourceLocation("minecraft:water"));
		sprite.getAtlasTexture().bindTexture();
		blit(100, 50, 0, 32, 32, sprite);
	}

	public TextureAtlasSprite getSprite(ResourceLocation resourceLocation) {
		return this.minecraft.getAtlasSpriteGetter(PlayerContainer.LOCATION_BLOCKS_TEXTURE).apply(resourceLocation);
	}
	
	@Override
    protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY)
    {
        this.font.drawString(this.title.getFormattedText(), 8.0F, 7.0F, 4210752);
        this.font.drawString(this.playerInventory.getDisplayName().getFormattedText(), 8.0F, (float) (this.ySize - 96 + 5), 4210752);
        addScreen(mouseX, mouseY);
    }

 

Edit: For odd reason there still a invalid or missing texture.

Edited by Issac29
Link to comment
Share on other sites

20 minutes ago, diesieben07 said:

Why on earth is the method called "addScreen". That makes zero sense.

 

Do not use getAtlasSpriteGetter. You need to get the model from the block and then get the textures from the model. There can be multiple or there could even potentially be none at all.

OK I renamed the method "addScreen" to "drawFluidTexture". Which makes more sense.

@SuppressWarnings("resource")
	private void drawFluidTexture(int x, int y) {
		TextureAtlasSprite texture = this.minecraft.getModelManager().getModel(new ResourceLocation("minecraft:water")).getParticleTexture(EmptyModelData.INSTANCE);
		texture.getAtlasTexture().bindTexture();
		blit(84, 12, 0, 32, 32, texture);
	}

	
	@Override
    protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY)
    {
        this.font.drawString(this.title.getFormattedText(), 8.0F, 7.0F, 4210752);
        this.font.drawString(this.playerInventory.getDisplayName().getFormattedText(), 8.0F, (float) (this.ySize - 96 + 5), 4210752);
        drawFluidTexture(mouseX, mouseY);
    }

 

But still has a missing texture. Maybe I needed to soft code it into something better.

Link to comment
Share on other sites

7 minutes ago, diesieben07 said:

Have you verified that its actually returning a proper model and texture?

The texture for weird reason returns "minecraft:missingno". This does not make any sense. As for the model it seems to have a number SimpleBakedModel@411933.

Link to comment
Share on other sites

9 hours ago, Issac29 said:

The texture for weird reason returns "minecraft:missingno". This does not make any sense. As for the model it seems to have a number SimpleBakedModel@411933.

That sounds like you got the missing model, because you did not provide a valid model location.

Link to comment
Share on other sites

I figured out that to get the sprite texture, you needed the Fluid#getAttributes#getStillTexture to obtain that texture. No need for getting the model or the blockstate for just a simple four step code.

AtlasTexture texture = minecraft.getModelManager().getAtlasTexture(PlayerContainer.LOCATION_BLOCKS_TEXTURE);
TextureAtlasSprite sprite = texture.getSprite(Fluids.WATER.getAttributes().getStillTexture());
texture.bindTexture();
blit(70, 20, 0, 32, 32, sprite);

 

Link to comment
Share on other sites

Alright most of the tank is synced but the only problem is the when I type this command /setblock x y z namespace:tankName{tankData: {FluidName: #fluidName, Amount: #amount}}, the server loads the data but the client does not load until reloading the world or chunk. That same applies to /data modify block x y z tankData set value {FluidName: #fluidName, Amount: #Amount}. I used every method to sync the client but some odd reason they don't sync when changing the tank value with commands.

Before Reloading Chunks:

2020-05-15_10_41_36.thumb.png.250b037d1649ee9d0b5c140384fce5cd.png

 

After Reloading Chunks:

2020-05-15_10_51_33.thumb.png.f852d9c66f565f8c0413600622be7f43.png

Link to comment
Share on other sites

Just now, diesieben07 said:

Show your code.

 

44 minutes ago, Issac29 said:

Alright most of the tank is synced but the only problem is the when I type this command /setblock x y z namespace:tankName{tankData: {FluidName: #fluidName, Amount: #amount}}, the server loads the data but the client does not load until reloading the world or chunk. That same applies to /data modify block x y z tankData set value {FluidName: #fluidName, Amount: #Amount}. I used every method to sync the client but some odd reason they don't sync when changing the tank value with commands.

Before Reloading Chunks:

2020-05-15_10_41_36.thumb.png.250b037d1649ee9d0b5c140384fce5cd.png

 

After Reloading Chunks:

2020-05-15_10_51_33.thumb.png.f852d9c66f565f8c0413600622be7f43.png

What the Images don't give enough information. Fine here is the code.

public class TankTileEntity extends TileEntity implements INamedContainerProvider, ITickableTileEntity {

	ManualTank tank = new ManualTank(8000, this);
	private LazyOptional<FluidTank> optional = LazyOptional.of(() -> this.tank);

	public TankTileEntity() {
		super(INCTileEntityTypes.TANK);
	}

	@Override
	public void read(CompoundNBT compound) {
		super.read(compound);
		CompoundNBT nbtfluid = compound.getCompound("tank"); //$NON-NLS-1$
		this.tank.readFromNBT(nbtfluid);
	}

	@Override
	public CompoundNBT write(CompoundNBT compound) {
		compound.put("tank", this.tank.writeToNBT(new CompoundNBT())); //$NON-NLS-1$
		return super.write(compound);
	}
	
	@Override
	public CompoundNBT getUpdateTag() {
		CompoundNBT nbt = super.getUpdateTag();
		return this.write(nbt);
	}

	@Override
	public boolean receiveClientEvent(int id, int type) {
		return true;

	}
	
	@Override
	public void handleUpdateTag(CompoundNBT tag) {
		read(tag);
	}

	@Override
	public <T> LazyOptional<T> getCapability(Capability<T> cap) {
		return cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY ? this.optional.cast() : super.getCapability(cap);
	}

	@Override
	public Container createMenu(int p_createMenu_1_, PlayerInventory p_createMenu_2_, PlayerEntity p_createMenu_3_) {
		return new TankContainer(p_createMenu_1_, this.world, this.pos, p_createMenu_2_);
	}

	@Override
	public ITextComponent getDisplayName() {
		return new TranslationTextComponent("container.tank"); //$NON-NLS-1$
	}

	public FluidTank getTank() {
		return this.tank;
	}

	@Override
	public void tick() {
		return;
	}
}

 

Link to comment
Share on other sites

5 minutes ago, diesieben07 said:

unnecessarily puts load on the network.

I guess that can cause server lag.

7 minutes ago, diesieben07 said:

You should instead only sync when the Container is open, vanilla has some examples of this.

How am I able to do that. Also I could not find anything that relates to that.

Link to comment
Share on other sites

3 minutes ago, Issac29 said:

How am I able to do that. Also I could not find anything that relates to that.

Override detectAndSendChanges in your container class. In there check if the data has changed since last time it was called. If it did, send it to the player watching the container using a custom packet.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share



×
×
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.