Skip to content

Commit

Permalink
- 完成部分流体储罐设计
Browse files Browse the repository at this point in the history
  • Loading branch information
TartaricAcid committed Dec 24, 2023
1 parent 8c6c348 commit 339080b
Show file tree
Hide file tree
Showing 5 changed files with 248 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import com.github.tartaricacid.touhoulittlemaid.TouhouLittleMaid;
import com.github.tartaricacid.touhoulittlemaid.client.gui.entity.maid.AbstractMaidContainerGui;
import com.github.tartaricacid.touhoulittlemaid.entity.backpack.data.TankBackpackData;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.github.tartaricacid.touhoulittlemaid.inventory.container.backpack.TankBackpackContainer;
import com.github.tartaricacid.touhoulittlemaid.util.MaidFluidRender;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.GameRenderer;
Expand All @@ -28,6 +30,15 @@ protected void renderBg(GuiGraphics graphics, float partialTicks, int x, int y)
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderTexture(0, BACKPACK);
graphics.blit(BACKPACK, leftPos + 85, topPos + 36, 0, 0, 165, 128);

RenderSystem.enableBlend();
MaidFluidRender.drawFluid(graphics, leftPos + 197, topPos + 104, 34, 50, maid.getBackpackFluid(), this.menu.getFluidCount(), TankBackpackData.CAPACITY);
RenderSystem.setShaderColor(1, 1, 1, 1);
RenderSystem.disableBlend();
graphics.blit(BACKPACK, leftPos + 197, topPos + 104, 165, 0, 34, 50);


graphics.drawString(font, this.menu.getFluidCount() + " mB", leftPos + 145, topPos + 130, 0x000000, false);
graphics.drawString(font, MaidFluidRender.getFluidName(maid.getBackpackFluid(), this.menu.getFluidCount()), leftPos + 145, topPos + 140, 0x000000, false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@

import com.github.tartaricacid.touhoulittlemaid.api.backpack.IBackpackData;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.github.tartaricacid.touhoulittlemaid.util.MaidFluidUtil;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.inventory.ContainerData;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.fluids.FluidActionResult;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidType;
import net.minecraftforge.fluids.FluidUtil;
import net.minecraftforge.fluids.capability.templates.FluidTank;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
import net.minecraftforge.registries.ForgeRegistries;

public class TankBackpackData extends SimpleContainer implements IBackpackData {
public static final int CAPACITY = 10 * FluidType.BUCKET_VOLUME;
Expand All @@ -22,24 +22,22 @@ public class TankBackpackData extends SimpleContainer implements IBackpackData {
private final ContainerData dataAccess = new ContainerData() {
public int get(int index) {
if (index == 0) {
return TankBackpackData.this.tank.getFluidAmount();
return TankBackpackData.this.tankFluidCount;
}
return 0;
}

public void set(int index, int value) {
if (index == 0) {
FluidStack fluid = TankBackpackData.this.tank.getFluid();
if (!fluid.isEmpty()) {
fluid.setAmount(value);
}
TankBackpackData.this.tankFluidCount = value;
}
}

public int getCount() {
return 2;
return 1;
}
};
private int tankFluidCount = 0;

public TankBackpackData(EntityMaid maid) {
super(1);
Expand All @@ -48,20 +46,24 @@ public TankBackpackData(EntityMaid maid) {

@Override
public void setItem(int index, ItemStack stack) {
super.setItem(index, stack);
CombinedInvWrapper availableInv = this.maid.getAvailableInv(false);
FluidActionResult fluidActionResult = FluidUtil.tryFillContainerAndStow(stack, tank, availableInv, Integer.MAX_VALUE, null, true);
if (!fluidActionResult.isSuccess()) {
fluidActionResult = FluidUtil.tryEmptyContainerAndStow(stack, tank, availableInv, Integer.MAX_VALUE, null, true);
}
if (fluidActionResult.isSuccess()) {
ItemStack result = fluidActionResult.getResult();
ItemStack remainder = ItemHandlerHelper.insertItemStacked(availableInv, result, false);
if (!remainder.isEmpty()) {
this.maid.spawnAtLocation(remainder);
if (!this.maid.level.isClientSide) {
CombinedInvWrapper availableInv = this.maid.getAvailableInv(false);
FluidActionResult fluidActionResult = MaidFluidUtil.tankToBucket(stack, tank, availableInv);
if (!fluidActionResult.isSuccess()) {
MaidFluidUtil.bucketToTank(stack, tank, availableInv);
}
this.tankFluidCount = tank.getFluidAmount();
ResourceLocation key = ForgeRegistries.FLUIDS.getKey(tank.getFluid().getFluid());
if (key != null) {
maid.setBackpackFluid(key.toString());
}
this.getItem(0).shrink(result.getCount());
}
super.setItem(index, stack);
}

@Override
public int getMaxStackSize() {
return 1;
}

@Override
Expand All @@ -73,6 +75,11 @@ public ContainerData getDataAccess() {
public void load(CompoundTag tag, EntityMaid maid) {
tank.readFromNBT(tag.getCompound("Tanks"));
this.fromTag(tag.getList("Items", Tag.TAG_COMPOUND));
this.tankFluidCount = tank.getFluidAmount();
ResourceLocation key = ForgeRegistries.FLUIDS.getKey(tank.getFluid().getFluid());
if (key != null) {
maid.setBackpackFluid(key.toString());
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ public class EntityMaid extends TamableAnimal implements CrossbowAttackMob {
private static final EntityDataAccessor<MaidChatBubbles> CHAT_BUBBLE = SynchedEntityData.defineId(EntityMaid.class, MaidChatBubbles.DATA);
private static final EntityDataAccessor<String> BACKPACK_TYPE = SynchedEntityData.defineId(EntityMaid.class, EntityDataSerializers.STRING);
private static final EntityDataAccessor<ItemStack> BACKPACK_ITEM_SHOW = SynchedEntityData.defineId(EntityMaid.class, EntityDataSerializers.ITEM_STACK);
private static final EntityDataAccessor<String> BACKPACK_FLUID = SynchedEntityData.defineId(EntityMaid.class, EntityDataSerializers.STRING);
private static final String TASK_TAG = "MaidTask";
private static final String PICKUP_TAG = "MaidIsPickup";
private static final String HOME_TAG = "MaidIsHome";
Expand Down Expand Up @@ -230,6 +231,7 @@ protected void defineSynchedData() {
this.entityData.define(CHAT_BUBBLE, MaidChatBubbles.DEFAULT);
this.entityData.define(BACKPACK_TYPE, EmptyBackpack.ID.toString());
this.entityData.define(BACKPACK_ITEM_SHOW, ItemStack.EMPTY);
this.entityData.define(BACKPACK_FLUID, "");
}

@Override
Expand Down Expand Up @@ -1326,6 +1328,14 @@ public void setSwingingArms(boolean swingingArms) {
this.entityData.set(DATA_ARM_RISE, swingingArms);
}

public String getBackpackFluid() {
return this.entityData.get(BACKPACK_FLUID);
}

public void setBackpackFluid(String fluidName) {
this.entityData.set(BACKPACK_FLUID, fluidName);
}

public MaidSchedule getSchedule() {
return this.entityData.get(SCHEDULE_MODE);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package com.github.tartaricacid.touhoulittlemaid.util;

import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.Tesselator;
import com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.inventory.InventoryMenu;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.Fluids;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.registries.ForgeRegistries;
import org.joml.Matrix4f;

import java.util.Optional;


/**
* From JEI: https://github.com/mezz/JustEnoughItems/blob/1.20/Forge/src/main/java/mezz/jei/forge/platform/FluidHelper.java
*/
@OnlyIn(Dist.CLIENT)
public final class MaidFluidRender {
private static final int TEXTURE_SIZE = 16;

public static Component getFluidName(String fluidId, int amount) {
Fluid fluid = ForgeRegistries.FLUIDS.getValue(new ResourceLocation(fluidId));
if (amount <= 0 || fluid == null || fluid.isSame(Fluids.EMPTY)) {
return Component.empty();
}
return fluid.getFluidType().getDescription();
}

public static void drawFluid(GuiGraphics graphics, int x, int y, int width, int height, String fluidId, int amount, int capacity) {
Fluid fluid = ForgeRegistries.FLUIDS.getValue(new ResourceLocation(fluidId));
if (amount <= 0 || fluid == null || fluid.isSame(Fluids.EMPTY)) {
return;
}
FluidStack fluidStack = new FluidStack(fluid, amount);
getStillFluidSprite(fluidStack).ifPresent(fluidStillSprite -> {
int fluidColor = getColorTint(fluidStack);
int scaledAmount = (amount * height) / capacity;
if (scaledAmount < 1) {
// 至少渲染一行像素,让人知道里面有东西
scaledAmount = 1;
}
if (scaledAmount > height) {
scaledAmount = height;
}
graphics.pose().pushPose();
graphics.pose().translate(x, y, 0);
drawTiledSprite(graphics, width, height, fluidColor, scaledAmount, fluidStillSprite);
graphics.pose().popPose();
});
}

private static Optional<TextureAtlasSprite> getStillFluidSprite(FluidStack fluidStack) {
Fluid fluid = fluidStack.getFluid();
IClientFluidTypeExtensions renderProperties = IClientFluidTypeExtensions.of(fluid);
ResourceLocation fluidStill = renderProperties.getStillTexture(fluidStack);
TextureAtlasSprite sprite = Minecraft.getInstance().getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(fluidStill);
return Optional.of(sprite).filter(s -> s.atlasLocation() != MissingTextureAtlasSprite.getLocation());
}

private static int getColorTint(FluidStack fluidStack) {
Fluid fluid = fluidStack.getFluid();
IClientFluidTypeExtensions renderProperties = IClientFluidTypeExtensions.of(fluid);
return renderProperties.getTintColor(fluidStack);
}

private static void drawTiledSprite(GuiGraphics guiGraphics, final int tiledWidth, final int tiledHeight, int color, long scaledAmount, TextureAtlasSprite sprite) {
RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS);
Matrix4f matrix = guiGraphics.pose().last().pose();
setGLColorFromInt(color);

final int xTileCount = tiledWidth / TEXTURE_SIZE;
final int xRemainder = tiledWidth - (xTileCount * TEXTURE_SIZE);
final long yTileCount = scaledAmount / TEXTURE_SIZE;
final long yRemainder = scaledAmount - (yTileCount * TEXTURE_SIZE);

for (int xTile = 0; xTile <= xTileCount; xTile++) {
for (int yTile = 0; yTile <= yTileCount; yTile++) {
int width = (xTile == xTileCount) ? xRemainder : TEXTURE_SIZE;
long height = (yTile == yTileCount) ? yRemainder : TEXTURE_SIZE;
int x = (xTile * TEXTURE_SIZE);
int y = tiledHeight - ((yTile + 1) * TEXTURE_SIZE);
if (width > 0 && height > 0) {
long maskTop = TEXTURE_SIZE - height;
int maskRight = TEXTURE_SIZE - width;
drawTextureWithMasking(matrix, x, y, sprite, maskTop, maskRight, 100);
}
}
}
}

private static void setGLColorFromInt(int color) {
float red = (color >> 16 & 0xFF) / 255.0F;
float green = (color >> 8 & 0xFF) / 255.0F;
float blue = (color & 0xFF) / 255.0F;
float alpha = ((color >> 24) & 0xFF) / 255F;

RenderSystem.setShaderColor(red, green, blue, alpha);
}

private static void drawTextureWithMasking(Matrix4f matrix, float xCoord, float yCoord, TextureAtlasSprite textureSprite, long maskTop, long maskRight, float zLevel) {
float uMin = textureSprite.getU0();
float uMax = textureSprite.getU1();
float vMin = textureSprite.getV0();
float vMax = textureSprite.getV1();
uMax = uMax - (maskRight / 16F * (uMax - uMin));
vMax = vMax - (maskTop / 16F * (vMax - vMin));

RenderSystem.setShader(GameRenderer::getPositionTexShader);

Tesselator tesselator = Tesselator.getInstance();
BufferBuilder bufferBuilder = tesselator.getBuilder();
bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX);
bufferBuilder.vertex(matrix, xCoord, yCoord + 16, zLevel).uv(uMin, vMax).endVertex();
bufferBuilder.vertex(matrix, xCoord + 16 - maskRight, yCoord + 16, zLevel).uv(uMax, vMax).endVertex();
bufferBuilder.vertex(matrix, xCoord + 16 - maskRight, yCoord + maskTop, zLevel).uv(uMax, vMin).endVertex();
bufferBuilder.vertex(matrix, xCoord, yCoord + maskTop, zLevel).uv(uMin, vMin).endVertex();
tesselator.end();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.github.tartaricacid.touhoulittlemaid.util;

import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.Tesselator;
import com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.inventory.InventoryMenu;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.Fluids;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions;
import net.minecraftforge.fluids.FluidActionResult;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidUtil;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.registries.ForgeRegistries;
import org.joml.Matrix4f;

import java.util.Optional;

public class MaidFluidUtil {
public static FluidActionResult tankToBucket(ItemStack bucket, IFluidHandler tank, IItemHandler maidBackpack) {
if (bucket.isEmpty()) {
return FluidActionResult.FAILURE;
}
FluidActionResult filledSimulated = FluidUtil.tryFillContainer(bucket, tank, Integer.MAX_VALUE, null, false);
if (filledSimulated.isSuccess()) {
ItemStack remainder = ItemHandlerHelper.insertItemStacked(maidBackpack, filledSimulated.getResult(), true);
if (remainder.isEmpty()) {
FluidActionResult filledReal = FluidUtil.tryFillContainer(bucket, tank, Integer.MAX_VALUE, null, true);
ItemHandlerHelper.insertItemStacked(maidBackpack, filledReal.getResult(), false);
bucket.shrink(1);
return new FluidActionResult(bucket);
}
}
return FluidActionResult.FAILURE;
}

public static FluidActionResult bucketToTank(ItemStack bucket, IFluidHandler tank, IItemHandler maidBackpack) {
if (bucket.isEmpty()) {
return FluidActionResult.FAILURE;
}
FluidActionResult emptiedSimulated = FluidUtil.tryEmptyContainer(bucket, tank, Integer.MAX_VALUE, null, false);
if (emptiedSimulated.isSuccess()) {
ItemStack remainder = ItemHandlerHelper.insertItemStacked(maidBackpack, emptiedSimulated.getResult(), true);
if (remainder.isEmpty()) {
FluidActionResult emptiedReal = FluidUtil.tryEmptyContainer(bucket, tank, Integer.MAX_VALUE, null, true);
ItemHandlerHelper.insertItemStacked(maidBackpack, emptiedReal.getResult(), false);
bucket.shrink(1);
return new FluidActionResult(bucket);
}
}
return FluidActionResult.FAILURE;
}
}

0 comments on commit 339080b

Please sign in to comment.