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 ecee91208..000000000 Binary files a/src/main/resources/assets/techreborn/textures/items/cell_fluid.png and /dev/null differ