Merge pull request #671 from Dragon2488/1.9.4

Properly fluid rendering in dynamic cells. Temporary fix of recipes incapability…
This commit is contained in:
Prospector 2016-07-14 22:39:43 -07:00 committed by GitHub
commit 31d1afa044
7 changed files with 416 additions and 68 deletions

View file

@ -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<ResourceLocation> getDependencies() {
return ImmutableList.of();
}
@Override
public Collection<ResourceLocation> getTextures() {
return ImmutableList.of(baseTexture, emptyTexture);
}
@Override
public IBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter) {
ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> transformMap = IPerspectiveAwareModel.MapWrapper.getTransforms(state);
TRSRTransformation transform = state.apply(Optional.<IModelPart>absent()).or(TRSRTransformation.identity());
ImmutableList.Builder<BakedQuad> 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<BakedQuad> quads;
private final ModelDynamicCell parent;
private final TextureAtlasSprite particle;
private final VertexFormat format;
private final ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> transformMap;
public BakedDynamicCell(List<BakedQuad> quads, ModelDynamicCell parent, TextureAtlasSprite particle, VertexFormat format, ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> transformMap) {
this.transformMap = transformMap;
this.quads = quads;
this.parent = parent;
this.particle = particle;
this.format = format;
}
@Override
public List<BakedQuad> 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<String, IBakedModel> modelCache = new HashMap<>();
private final Function<ResourceLocation, TextureAtlasSprite> 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);
}
}
}

View file

@ -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));
}
}

View file

@ -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");

View file

@ -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<ItemStack> 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<ItemStack> 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<ItemStack> 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);
}
}
}

View file

@ -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<String> 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;
}
}

View file

@ -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();
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 B