From 2b148f3d68bb87890fa24b7c529de29ccec8b23d Mon Sep 17 00:00:00 2001 From: Dragon2488 Date: Fri, 15 Jul 2016 12:15:09 +0700 Subject: [PATCH] Properly fluid rendering in dynamic cells. Temporary fix of recipes incapability with renamed (or tagged) cells. Merge dynamic and empty cells into one item. Right click on fluid block fills cell with fluid. --- .../client/render/ModelDynamicCell.java | 211 ++++++++++++++++++ .../techreborn/client/render/ModelHelper.java | 46 ++++ src/main/java/techreborn/init/ModItems.java | 9 +- .../java/techreborn/items/DynamicCell.java | 187 +++++++++++----- src/main/java/techreborn/items/EmptyCell.java | 18 +- .../java/techreborn/proxies/ClientProxy.java | 13 +- .../techreborn/textures/items/cell_fluid.png | Bin 243 -> 0 bytes 7 files changed, 416 insertions(+), 68 deletions(-) create mode 100644 src/main/java/techreborn/client/render/ModelDynamicCell.java create mode 100644 src/main/java/techreborn/client/render/ModelHelper.java delete mode 100644 src/main/resources/assets/techreborn/textures/items/cell_fluid.png diff --git a/src/main/java/techreborn/client/render/ModelDynamicCell.java b/src/main/java/techreborn/client/render/ModelDynamicCell.java new file mode 100644 index 000000000..40b104877 --- /dev/null +++ b/src/main/java/techreborn/client/render/ModelDynamicCell.java @@ -0,0 +1,211 @@ +package techreborn.client.render; + +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.model.*; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.vertex.VertexFormat; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; +import net.minecraftforge.client.model.*; +import net.minecraftforge.common.model.IModelPart; +import net.minecraftforge.common.model.IModelState; +import net.minecraftforge.common.model.TRSRTransformation; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import techreborn.init.ModItems; +import techreborn.items.DynamicCell; + +import javax.annotation.Nullable; +import java.awt.*; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; + +@SideOnly(Side.CLIENT) +public class ModelDynamicCell implements IModel { + + public static final ModelDynamicCell MODEL = new ModelDynamicCell( + new ResourceLocation("techreborn:items/cell_cover"), + new ResourceLocation("techreborn:items/cell_empty") + ); + + public static final ModelResourceLocation MODEL_LOCATION = new ModelResourceLocation(new ResourceLocation("techreborn", "dynamic_cell"), "default"); + + private static final float NORTH_Z_FLUID = 7.6f / 16f; + private static final float SOUTH_Z_FLUID = 8.4f / 16f; + + + public static void init() { + ModelLoader.setCustomMeshDefinition(ModItems.dynamicCell, stack -> MODEL_LOCATION); + ModelBakery.registerItemVariants(ModItems.dynamicCell, MODEL_LOCATION); + ModelLoaderRegistry.registerLoader(new DynamicCellLoader()); + } + + + private final ResourceLocation baseTexture; + private final ResourceLocation emptyTexture; + private final Fluid fluid; + + public ModelDynamicCell(ResourceLocation baseTexture, ResourceLocation emptyTexture) { + this(baseTexture, emptyTexture, null); + } + + public ModelDynamicCell(ResourceLocation baseTexture, ResourceLocation emptyTexture, Fluid fluid) { + this.baseTexture = baseTexture; + this.emptyTexture = emptyTexture; + this.fluid = fluid; + } + + @Override + public Collection getDependencies() { + return ImmutableList.of(); + } + + @Override + public Collection getTextures() { + return ImmutableList.of(baseTexture, emptyTexture); + } + + @Override + public IBakedModel bake(IModelState state, VertexFormat format, Function bakedTextureGetter) { + + ImmutableMap transformMap = IPerspectiveAwareModel.MapWrapper.getTransforms(state); + TRSRTransformation transform = state.apply(Optional.absent()).or(TRSRTransformation.identity()); + + ImmutableList.Builder builder = ImmutableList.builder(); + builder.addAll(new ItemLayerModel(ImmutableList.of(baseTexture)).bake(transform, format, bakedTextureGetter).getQuads(null, null, 0L)); + + ResourceLocation sprite = fluid != null ? fluid.getStill() : emptyTexture; + int color = fluid != null ? fluid.getColor() : Color.WHITE.getRGB(); + TextureAtlasSprite fluidSprite = bakedTextureGetter.apply(sprite); + if (fluidSprite != null) { + builder.add(ItemTextureQuadConverter.genQuad(format, transform, 5, 2, 11, 14, NORTH_Z_FLUID, fluidSprite, EnumFacing.NORTH, color)); + builder.add(ItemTextureQuadConverter.genQuad(format, transform, 5, 2, 11, 14, SOUTH_Z_FLUID, fluidSprite, EnumFacing.SOUTH, color)); + } + + return new BakedDynamicCell(builder.build(), this, bakedTextureGetter.apply(baseTexture), format, transformMap); + } + + @Override + public IModelState getDefaultState() { + return TRSRTransformation.identity(); + } + + + public static class DynamicCellLoader implements ICustomModelLoader { + + @Override + public boolean accepts(ResourceLocation modelLocation) { + return modelLocation.getResourceDomain().equals("techreborn") && modelLocation.getResourcePath().contains("dynamic_cell"); + } + + @Override + public IModel loadModel(ResourceLocation modelLocation) throws Exception { + return MODEL; + } + + @Override + public void onResourceManagerReload(IResourceManager resourceManager) {} + + } + + public static class BakedDynamicCell implements IBakedModel{ + + private final List quads; + private final ModelDynamicCell parent; + private final TextureAtlasSprite particle; + private final VertexFormat format; + private final ImmutableMap transformMap; + + public BakedDynamicCell(List quads, ModelDynamicCell parent, TextureAtlasSprite particle, VertexFormat format, ImmutableMap transformMap) { + this.transformMap = transformMap; + this.quads = quads; + this.parent = parent; + this.particle = particle; + this.format = format; + } + + @Override + public List getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand) { + return quads; + } + + @Override + public boolean isAmbientOcclusion() { + return true; + } + + @Override + public boolean isGui3d() { + return false; + } + + @Override + public boolean isBuiltInRenderer() { + return false; + } + + @Override + public TextureAtlasSprite getParticleTexture() { + return particle; + } + + @Override + public ItemCameraTransforms getItemCameraTransforms() { + return ModelHelper.DEFAULT_ITEM_TRANSFORMS; + } + + @Override + public ItemOverrideList getOverrides() { + return OVERRIDES; + } + + + } + + + public static final OverrideHandler OVERRIDES = new OverrideHandler(); + + public static class OverrideHandler extends ItemOverrideList { + + private final HashMap modelCache = new HashMap<>(); + + private final Function textureGetter = location -> + Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(location.toString()); + + private OverrideHandler() { + super(ImmutableList.of()); + } + + @Override + public IBakedModel handleItemState(IBakedModel originalModel, ItemStack stack, World world, EntityLivingBase entity) { + FluidStack fluidStack = DynamicCell.getFluidHandler(stack).getFluid(); + if(fluidStack == null) { + //return default bucket + return originalModel; + } + String name = fluidStack.getFluid().getName(); + if(!modelCache.containsKey(name)) { + BakedDynamicCell bakedCell = (BakedDynamicCell) originalModel; + ModelDynamicCell model = new ModelDynamicCell(bakedCell.parent.baseTexture, bakedCell.parent.emptyTexture, fluidStack.getFluid()); + modelCache.put(name, model.bake(new SimpleModelState(bakedCell.transformMap), bakedCell.format, textureGetter)); + } + return modelCache.get(name); + } + + } + + + +} diff --git a/src/main/java/techreborn/client/render/ModelHelper.java b/src/main/java/techreborn/client/render/ModelHelper.java new file mode 100644 index 000000000..f4044c7fe --- /dev/null +++ b/src/main/java/techreborn/client/render/ModelHelper.java @@ -0,0 +1,46 @@ +package techreborn.client.render; + +import com.google.common.base.Charsets; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.model.ItemCameraTransforms; +import net.minecraft.client.renderer.block.model.ModelBlock; +import net.minecraft.client.resources.IResource; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import techreborn.Core; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; + +/* + * Credits to JsonDestroyer + */ +@SideOnly(Side.CLIENT) +public class ModelHelper { + + public static final ItemCameraTransforms DEFAULT_ITEM_TRANSFORMS = loadTransformFromJson(new ResourceLocation("minecraft:models/item/generated")); + public static final ItemCameraTransforms HANDHELD_ITEM_TRANSFORMS = loadTransformFromJson(new ResourceLocation("minecraft:models/item/handheld")); + + + public static ItemCameraTransforms loadTransformFromJson(ResourceLocation location) { + try { + + return ModelBlock.deserialize(getReaderForResource(location)).getAllTransforms(); + } catch (IOException exception) { + Core.logHelper.warn("Can't load resource " + location); + exception.printStackTrace(); + return null; + } + } + + public static Reader getReaderForResource(ResourceLocation location) throws IOException { + ResourceLocation file = new ResourceLocation(location.getResourceDomain(), location.getResourcePath() + ".json"); + IResource iresource = Minecraft.getMinecraft().getResourceManager().getResource(file); + return new BufferedReader(new InputStreamReader(iresource.getInputStream(), Charsets.UTF_8)); + } + + +} diff --git a/src/main/java/techreborn/init/ModItems.java b/src/main/java/techreborn/init/ModItems.java index c6d797227..6dbc6e8aa 100644 --- a/src/main/java/techreborn/init/ModItems.java +++ b/src/main/java/techreborn/init/ModItems.java @@ -3,6 +3,7 @@ package techreborn.init; import net.minecraft.init.Items; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fluids.FluidContainerRegistry; import net.minecraftforge.fluids.FluidRegistry; @@ -294,12 +295,14 @@ public class ModItems debug = new ItemDebugTool(); registerItem(debug, "debug"); - emptyCell = new EmptyCell(); - registerItem(emptyCell, "emptyCell"); - dynamicCell = new DynamicCell(); registerItem(dynamicCell, "dynamicCell"); + emptyCell = dynamicCell; + Item cell = new EmptyCell(); + registerItem(cell, "emptyCell"); + GameRegistry.addShapelessRecipe(new ItemStack(dynamicCell), cell); + MinecraftForge.EVENT_BUS.register(BucketHandler.INSTANCE); Core.logHelper.info("TechReborns Items Loaded"); diff --git a/src/main/java/techreborn/items/DynamicCell.java b/src/main/java/techreborn/items/DynamicCell.java index ad5edc966..a21a1d5ec 100644 --- a/src/main/java/techreborn/items/DynamicCell.java +++ b/src/main/java/techreborn/items/DynamicCell.java @@ -1,95 +1,182 @@ package techreborn.items; +import net.minecraft.block.Block; +import net.minecraft.block.BlockStaticLiquid; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ActionResult; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.text.TextComponentString; import net.minecraft.world.World; -import net.minecraftforge.event.entity.player.FillBucketEvent; +import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.UniversalBucket; +import net.minecraftforge.fluids.IFluidBlock; +import net.minecraftforge.fluids.capability.templates.FluidHandlerItemStack; import org.apache.commons.lang3.Validate; import techreborn.client.TechRebornCreativeTab; import techreborn.init.ModItems; +import techreborn.init.ModRecipes; + +import java.util.List; /** * Created by modmuss50 on 17/05/2016. */ -public class DynamicCell extends UniversalBucket{ +public class DynamicCell extends Item { + + public static final int CAPACITY = Fluid.BUCKET_VOLUME; public DynamicCell() { - super(1000, new ItemStack(ModItems.emptyCell), false); + super(); setCreativeTab(TechRebornCreativeTab.instance); - setUnlocalizedName("techreborn.cellFilled"); + setUnlocalizedName("techreborn.cell"); setMaxStackSize(16); } @Override - public ActionResult onItemRightClick(ItemStack itemstack, World world, EntityPlayer player, EnumHand hand) { - return ActionResult.newResult(EnumActionResult.FAIL, itemstack); - } - - @Override - public void onFillBucket(FillBucketEvent event) { - return; - } - - @Override - public String getItemStackDisplayName(ItemStack stack) - { - FluidStack fluidStack = getFluid(stack); - if (fluidStack == null) - { - if(getEmpty() != null) - { - return getEmpty().getDisplayName(); + public void onUpdate(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + //Clearing tag because ItemUtils.isItemEqual doesn't handle tags ForgeCaps and display + //And breaks ability to use in recipes + //TODO: Property ItemUtils.isItemEquals tags equality handling? + if(stack.hasTagCompound()) { + NBTTagCompound tag = stack.getTagCompound(); + if(tag.getSize() != 1 || tag.hasKey("Fluid")) { + NBTTagCompound clearTag = new NBTTagCompound(); + clearTag.setTag("Fluid", tag.getCompoundTag("Fluid")); + stack.setTagCompound(clearTag); } - return super.getItemStackDisplayName(stack); } + } + @Override + public ActionResult onItemRightClick(ItemStack stack, World worldIn, EntityPlayer playerIn, EnumHand hand) { + if(!worldIn.isRemote) { + RayTraceResult result = rayTrace(worldIn, playerIn, true); + + if (result.typeOfHit == RayTraceResult.Type.BLOCK) { + BlockPos pos = result.getBlockPos(); + IBlockState state = worldIn.getBlockState(pos); + Block block = state.getBlock(); + + if (block instanceof IFluidBlock) { + IFluidBlock fluidBlock = (IFluidBlock) block; + + if (fluidBlock.canDrain(worldIn, pos)) { + FluidStack fluid = fluidBlock.drain(worldIn, pos, false); + + if (fluid != null && fluid.amount == DynamicCell.CAPACITY) { + if(tryAddCellToInventory(playerIn, stack, fluid.getFluid())) { + fluidBlock.drain(worldIn, pos, true); + return ActionResult.newResult(EnumActionResult.SUCCESS, stack); + } + } + + } + + } else if (block instanceof BlockStaticLiquid) { + Fluid fluid = block.getMaterial(state) == Material.LAVA ? FluidRegistry.LAVA : FluidRegistry.WATER; + + if(tryAddCellToInventory(playerIn, stack, fluid)) { + if(fluid != FluidRegistry.WATER) + worldIn.setBlockToAir(pos); + return ActionResult.newResult(EnumActionResult.SUCCESS, stack); + } + + } + } + } + return ActionResult.newResult(EnumActionResult.FAIL, stack); + } + + public boolean tryAddCellToInventory(EntityPlayer player, ItemStack stack, Fluid fluid) { + if (player.inventory.addItemStackToInventory(DynamicCell.getCellWithFluid(fluid))) { + --stack.stackSize; + return true; + } + return false; + } + + @Override + public void getSubItems(Item itemIn, CreativeTabs tab, List subItems) { + subItems.add(getEmptyCell(1)); + for(Fluid fluid : FluidRegistry.getRegisteredFluids().values()) { + subItems.add(getCellWithFluid(fluid)); + } + } + + @Override + public String getItemStackDisplayName(ItemStack stack) { + FluidStack fluidStack = getFluidHandler(stack).getFluid(); + if (fluidStack == null) + return super.getItemStackDisplayName(stack); return fluidStack.getLocalizedName() + " Cell"; } @Override - public int fill(ItemStack container, FluidStack resource, boolean doFill) - { - // has to be exactly 1, must be handled from the caller - if (container.stackSize != 1) - { - return 0; - } + public ICapabilityProvider initCapabilities(ItemStack stack, NBTTagCompound nbt) { + return getFluidHandler(stack); + } - // can only fill exact capacity - if (resource == null || resource.amount != getCapacity()) - { - return 0; - } - // fill the container - if (doFill) - { - NBTTagCompound tag = container.getTagCompound(); - if (tag == null) - { - tag = new NBTTagCompound(); - } - resource.writeToNBT(tag); - container.setTagCompound(tag); - } - return getCapacity(); + public static FluidHandler getFluidHandler(ItemStack stack) { + return new FluidHandler(stack, CAPACITY); } public static ItemStack getCellWithFluid(Fluid fluid, int stackSize){ Validate.notNull(fluid); - ItemStack stack = new ItemStack(ModItems.dynamicCell, stackSize); - ModItems.dynamicCell.fill(stack, new FluidStack(fluid, ModItems.dynamicCell.getCapacity()), true); + ItemStack stack = new ItemStack(ModItems.dynamicCell); + getFluidHandler(stack).fill(new FluidStack(fluid, CAPACITY), true); + stack.stackSize = stackSize; return stack; } + public static ItemStack getEmptyCell(int amount) { + return new ItemStack(ModItems.dynamicCell, amount); + } + public static ItemStack getCellWithFluid(Fluid fluid){ return getCellWithFluid(fluid, 1); } + public static class FluidHandler extends FluidHandlerItemStack { + + public FluidHandler(ItemStack container, int capacity) { + super(container, capacity); + + //backwards compatibility + if(container.hasTagCompound() && container.getTagCompound().hasKey("FluidName")) { + FluidStack stack = FluidStack.loadFluidStackFromNBT(container.getTagCompound()); + if(stack != null) { + container.setTagCompound(new NBTTagCompound()); + fill(stack, true); + } + } + + + } + + @Override + public int fill(FluidStack resource, boolean doFill) { + if(resource.amount != capacity) return 0; + return super.fill(resource, doFill); + } + + @Override + public FluidStack drain(int maxDrain, boolean doDrain) { + if(maxDrain != capacity) return null; + return super.drain(maxDrain, doDrain); + } + + } + } diff --git a/src/main/java/techreborn/items/EmptyCell.java b/src/main/java/techreborn/items/EmptyCell.java index 68691cb26..c8b50c8f8 100644 --- a/src/main/java/techreborn/items/EmptyCell.java +++ b/src/main/java/techreborn/items/EmptyCell.java @@ -1,19 +1,28 @@ package techreborn.items; -import techreborn.client.TechRebornCreativeTab; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; import techreborn.lib.ModInfo; +import java.util.List; + /** * Created by modmuss50 on 17/05/2016. */ +@Deprecated public class EmptyCell extends ItemTextureBase { - public EmptyCell() - { + public EmptyCell() { super(); setUnlocalizedName("techreborn.cell"); - setCreativeTab(TechRebornCreativeTab.instance); } + + @Override + public void addInformation(ItemStack stack, EntityPlayer playerIn, List tooltip, boolean advanced) { + tooltip.add("§cDeprecated"); + tooltip.add("§7Place to workbench to get new item"); + } + @Override public String getTextureName(int damage) { return ModInfo.MOD_ID + ":items/cell_base"; @@ -23,4 +32,5 @@ public class EmptyCell extends ItemTextureBase { public int getMaxMeta() { return 1; } + } diff --git a/src/main/java/techreborn/proxies/ClientProxy.java b/src/main/java/techreborn/proxies/ClientProxy.java index eca79dab1..b5305b9f8 100644 --- a/src/main/java/techreborn/proxies/ClientProxy.java +++ b/src/main/java/techreborn/proxies/ClientProxy.java @@ -30,6 +30,7 @@ import techreborn.client.RegisterItemJsons; import techreborn.client.StackToolTipEvent; import techreborn.client.hud.ChargeHud; import techreborn.client.keybindings.KeyBindings; +import techreborn.client.render.ModelDynamicCell; import techreborn.client.render.entitys.RenderNukePrimed; import techreborn.entitys.EntityNukePrimed; import techreborn.init.ModBlocks; @@ -44,8 +45,6 @@ public class ClientProxy extends CommonProxy public static MultiblockRenderEvent multiblockRenderEvent; - public static final ModelResourceLocation MODEL_DYNAMIC_CELL = new ModelResourceLocation(new ResourceLocation("techreborn", "dyncell"), "inventory"); - @Override public void preInit(FMLPreInitializationEvent event) { @@ -70,15 +69,7 @@ public class ClientProxy extends CommonProxy } } - ModelLoader.setCustomMeshDefinition(ModItems.dynamicCell, new ItemMeshDefinition() - { - @Override - public ModelResourceLocation getModelLocation(ItemStack stack) - { - return MODEL_DYNAMIC_CELL; - } - }); - ModelBakery.registerItemVariants(ModItems.dynamicCell, MODEL_DYNAMIC_CELL); + ModelDynamicCell.init(); RegisterItemJsons.registerModels(); } diff --git a/src/main/resources/assets/techreborn/textures/items/cell_fluid.png b/src/main/resources/assets/techreborn/textures/items/cell_fluid.png deleted file mode 100644 index ecee91208dd80a94430c45e07ead66418c4ad32a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 243 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`3dtTpz6=aistgPb%?u1b{{!il z3=E|P3=FRl7#OT(FffScPl`Y422{&g;1OBOz`!j8!i<;h*8KqrN|d-plmzFem6RtI zr7{#GX6BXX<)xM=nCKbkS>_nm`2p30db&7