mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-12 08:17:35 +00:00
Improve the Forge Bucket (#4435)
This commit is contained in:
1 parent
48320b315f
commit
b5e88dd07b
13 files changed
+372
-199
No files matched your search
@@ -103,6 +103,7 @@ import net.minecraftforge.client.event.RenderWorldLastEvent;
|
||||
import net.minecraftforge.client.event.ScreenshotEvent;
|
||||
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||
import net.minecraftforge.client.event.sound.PlaySoundEvent;
|
||||
import net.minecraftforge.client.model.ModelDynBucket;
|
||||
import net.minecraftforge.client.model.ModelLoader;
|
||||
import net.minecraftforge.client.model.animation.Animation;
|
||||
import net.minecraftforge.common.ForgeModContainer;
|
||||
@@ -174,6 +175,7 @@ public class ForgeHooksClient
|
||||
{
|
||||
MinecraftForge.EVENT_BUS.post(new TextureStitchEvent.Pre(map));
|
||||
ModelLoader.White.INSTANCE.register(map);
|
||||
ModelDynBucket.LoaderDynBucket.INSTANCE.register(map);
|
||||
}
|
||||
|
||||
public static void onTextureStitchedPost(TextureMap map)
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.minecraftforge.client.model;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.vecmath.Matrix4f;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.block.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType;
|
||||
import net.minecraft.client.renderer.block.model.ItemOverrideList;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraftforge.common.model.TRSRTransformation;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
public class BakedItemModel implements IBakedModel
|
||||
{
|
||||
protected final ImmutableList<BakedQuad> quads;
|
||||
protected final TextureAtlasSprite particle;
|
||||
protected final ImmutableMap<TransformType, TRSRTransformation> transforms;
|
||||
protected final ItemOverrideList overrides;
|
||||
protected final IBakedModel guiModel;
|
||||
|
||||
public BakedItemModel(ImmutableList<BakedQuad> quads, TextureAtlasSprite particle, ImmutableMap<TransformType, TRSRTransformation> transforms, ItemOverrideList overrides)
|
||||
{
|
||||
this.quads = quads;
|
||||
this.particle = particle;
|
||||
this.transforms = transforms;
|
||||
this.overrides = overrides;
|
||||
this.guiModel = new BakedGuiItemModel<>(this);
|
||||
}
|
||||
|
||||
@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 ItemOverrideList getOverrides() { return overrides; }
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand)
|
||||
{
|
||||
if (side == null)
|
||||
{
|
||||
return quads;
|
||||
}
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<? extends IBakedModel, Matrix4f> handlePerspective(TransformType type)
|
||||
{
|
||||
if (type == TransformType.GUI)
|
||||
{
|
||||
return this.guiModel.handlePerspective(type);
|
||||
}
|
||||
return PerspectiveMapWrapper.handlePerspective(this, transforms, type);
|
||||
}
|
||||
|
||||
public static class BakedGuiItemModel<T extends BakedItemModel> extends BakedModelWrapper<T>
|
||||
{
|
||||
private final ImmutableList<BakedQuad> quads;
|
||||
|
||||
public BakedGuiItemModel(T originalModel)
|
||||
{
|
||||
super(originalModel);
|
||||
ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
|
||||
for (BakedQuad quad : originalModel.quads)
|
||||
{
|
||||
if (quad.getFace() == EnumFacing.SOUTH)
|
||||
{
|
||||
builder.add(quad);
|
||||
}
|
||||
}
|
||||
this.quads = builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand)
|
||||
{
|
||||
if(side == null)
|
||||
{
|
||||
return quads;
|
||||
}
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<? extends IBakedModel, Matrix4f> handlePerspective(TransformType type)
|
||||
{
|
||||
if (type == TransformType.GUI)
|
||||
{
|
||||
return PerspectiveMapWrapper.handlePerspective(this, originalModel.transforms, type);
|
||||
}
|
||||
return this.originalModel.handlePerspective(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.minecraftforge.client.model;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.vecmath.Matrix4f;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.block.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
|
||||
import net.minecraft.client.renderer.block.model.ItemOverrideList;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
public abstract class BakedModelWrapper<T extends IBakedModel> implements IBakedModel
|
||||
{
|
||||
protected final T originalModel;
|
||||
|
||||
public BakedModelWrapper(T originalModel)
|
||||
{
|
||||
this.originalModel = originalModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand)
|
||||
{
|
||||
return originalModel.getQuads(state, side, rand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAmbientOcclusion()
|
||||
{
|
||||
return originalModel.isAmbientOcclusion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGui3d()
|
||||
{
|
||||
return originalModel.isGui3d();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltInRenderer()
|
||||
{
|
||||
return originalModel.isBuiltInRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture()
|
||||
{
|
||||
return originalModel.getParticleTexture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemCameraTransforms getItemCameraTransforms()
|
||||
{
|
||||
return originalModel.getItemCameraTransforms();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemOverrideList getOverrides()
|
||||
{
|
||||
return originalModel.getOverrides();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<? extends IBakedModel, Matrix4f> handlePerspective(ItemCameraTransforms.TransformType cameraTransformType)
|
||||
{
|
||||
return originalModel.handlePerspective(cameraTransformType);
|
||||
}
|
||||
}
|
||||
@@ -19,14 +19,10 @@
|
||||
|
||||
package net.minecraftforge.client.model;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.vecmath.Matrix4f;
|
||||
import javax.vecmath.Vector4f;
|
||||
|
||||
import net.minecraftforge.common.ForgeVersion;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.block.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType;
|
||||
@@ -45,7 +41,6 @@ import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
@@ -122,69 +117,7 @@ public final class ItemLayerModel implements IModel
|
||||
}
|
||||
TextureAtlasSprite particle = bakedTextureGetter.apply(textures.isEmpty() ? new ResourceLocation("missingno") : textures.get(0));
|
||||
ImmutableMap<TransformType, TRSRTransformation> map = PerspectiveMapWrapper.getTransforms(state);
|
||||
return new BakedItemModel(builder.build(), particle, map, overrides, null);
|
||||
}
|
||||
|
||||
private static final class BakedItemModel implements IBakedModel
|
||||
{
|
||||
private final ImmutableList<BakedQuad> quads;
|
||||
private final TextureAtlasSprite particle;
|
||||
private final ImmutableMap<TransformType, TRSRTransformation> transforms;
|
||||
private final IBakedModel otherModel;
|
||||
private final boolean isCulled;
|
||||
private final ItemOverrideList overrides;
|
||||
|
||||
public BakedItemModel(ImmutableList<BakedQuad> quads, TextureAtlasSprite particle, ImmutableMap<TransformType, TRSRTransformation> transforms, ItemOverrideList overrides, @Nullable IBakedModel otherModel)
|
||||
{
|
||||
this.quads = quads;
|
||||
this.particle = particle;
|
||||
this.transforms = transforms;
|
||||
this.overrides = overrides;
|
||||
if(otherModel != null)
|
||||
{
|
||||
this.otherModel = otherModel;
|
||||
this.isCulled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
|
||||
for(BakedQuad quad : quads)
|
||||
{
|
||||
if(quad.getFace() == EnumFacing.SOUTH)
|
||||
{
|
||||
builder.add(quad);
|
||||
}
|
||||
}
|
||||
this.otherModel = new BakedItemModel(builder.build(), particle, transforms, overrides, this);
|
||||
isCulled = false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAmbientOcclusion() { return true; }
|
||||
public boolean isGui3d() { return false; }
|
||||
public boolean isBuiltInRenderer() { return false; }
|
||||
public TextureAtlasSprite getParticleTexture() { return particle; }
|
||||
public ItemOverrideList getOverrides() { return overrides; }
|
||||
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand)
|
||||
{
|
||||
if(side == null) return quads;
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<? extends IBakedModel, Matrix4f> handlePerspective(TransformType type)
|
||||
{
|
||||
Pair<? extends IBakedModel, Matrix4f> pair = PerspectiveMapWrapper.handlePerspective(this, transforms, type);
|
||||
if(type == TransformType.GUI && !isCulled && pair.getRight() == null)
|
||||
{
|
||||
return Pair.of(otherModel, null);
|
||||
}
|
||||
else if(type != TransformType.GUI && isCulled)
|
||||
{
|
||||
return Pair.of(otherModel, pair.getRight());
|
||||
}
|
||||
return pair;
|
||||
}
|
||||
return new BakedItemModel(builder.build(), particle, map, overrides);
|
||||
}
|
||||
|
||||
public static ImmutableList<BakedQuad> getQuadsForSprite(int tint, TextureAtlasSprite sprite, VertexFormat format, Optional<TRSRTransformation> transform)
|
||||
|
||||
@@ -239,13 +239,12 @@ public final class ItemTextureQuadConverter
|
||||
float x1, float y1, float x2, float y2, float z,
|
||||
float u1, float v1, float u2, float v2)
|
||||
{
|
||||
side = side.getOpposite();
|
||||
UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder(format);
|
||||
builder.setQuadTint(-1);
|
||||
builder.setQuadOrientation(side);
|
||||
builder.setTexture(sprite);
|
||||
|
||||
if (side == EnumFacing.NORTH)
|
||||
if (side == EnumFacing.SOUTH)
|
||||
{
|
||||
putVertex(builder, format, transform, side, x1, y1, z, u1, v2, color);
|
||||
putVertex(builder, format, transform, side, x2, y1, z, u2, v2, color);
|
||||
|
||||
@@ -19,25 +19,24 @@
|
||||
|
||||
package net.minecraftforge.client.model;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.vecmath.Matrix4f;
|
||||
import javax.vecmath.Quat4f;
|
||||
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.block.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
|
||||
import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType;
|
||||
import net.minecraft.client.renderer.block.model.ItemOverride;
|
||||
import net.minecraft.client.renderer.block.model.ItemOverrideList;
|
||||
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.texture.TextureMap;
|
||||
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||
import net.minecraft.client.resources.IResource;
|
||||
import net.minecraft.client.resources.IResourceManager;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -45,7 +44,6 @@ import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.ForgeVersion;
|
||||
import net.minecraftforge.common.model.IModelPart;
|
||||
import net.minecraftforge.common.model.IModelState;
|
||||
import net.minecraftforge.common.model.TRSRTransformation;
|
||||
import net.minecraftforge.fluids.Fluid;
|
||||
@@ -53,10 +51,12 @@ import net.minecraftforge.fluids.FluidRegistry;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.FluidUtil;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.Optional;
|
||||
|
||||
import static net.minecraftforge.client.model.ModelDynBucket.LoaderDynBucket.getResource;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -67,8 +67,8 @@ public final class ModelDynBucket implements IModel
|
||||
public static final ModelResourceLocation LOCATION = new ModelResourceLocation(new ResourceLocation(ForgeVersion.MOD_ID, "dynbucket"), "inventory");
|
||||
|
||||
// minimal Z offset to prevent depth-fighting
|
||||
private static final float NORTH_Z_BASE = 7.496f / 16f;
|
||||
private static final float SOUTH_Z_BASE = 8.504f / 16f;
|
||||
private static final float NORTH_Z_COVER = 7.496f / 16f;
|
||||
private static final float SOUTH_Z_COVER = 8.504f / 16f;
|
||||
private static final float NORTH_Z_FLUID = 7.498f / 16f;
|
||||
private static final float SOUTH_Z_FLUID = 8.502f / 16f;
|
||||
|
||||
@@ -127,6 +127,7 @@ public final class ModelDynBucket implements IModel
|
||||
|
||||
TRSRTransformation transform = state.apply(Optional.empty()).orElse(TRSRTransformation.identity());
|
||||
TextureAtlasSprite fluidSprite = null;
|
||||
TextureAtlasSprite particleSprite = null;
|
||||
ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
|
||||
|
||||
if(fluid != null) {
|
||||
@@ -138,6 +139,7 @@ public final class ModelDynBucket implements IModel
|
||||
// build base (insidest)
|
||||
IBakedModel model = (new ItemLayerModel(ImmutableList.of(baseLocation))).bake(state, format, bakedTextureGetter);
|
||||
builder.addAll(model.getQuads(null, null, 0));
|
||||
particleSprite = model.getParticleTexture();
|
||||
}
|
||||
if (liquidLocation != null && fluidSprite != null)
|
||||
{
|
||||
@@ -145,17 +147,21 @@ public final class ModelDynBucket implements IModel
|
||||
// build liquid layer (inside)
|
||||
builder.addAll(ItemTextureQuadConverter.convertTexture(format, transform, liquid, fluidSprite, NORTH_Z_FLUID, EnumFacing.NORTH, fluid.getColor()));
|
||||
builder.addAll(ItemTextureQuadConverter.convertTexture(format, transform, liquid, fluidSprite, SOUTH_Z_FLUID, EnumFacing.SOUTH, fluid.getColor()));
|
||||
particleSprite = fluidSprite;
|
||||
}
|
||||
if (coverLocation != null)
|
||||
{
|
||||
// cover (the actual item around the other two)
|
||||
TextureAtlasSprite base = bakedTextureGetter.apply(coverLocation);
|
||||
builder.add(ItemTextureQuadConverter.genQuad(format, transform, 0, 0, 16, 16, NORTH_Z_BASE, base, EnumFacing.NORTH, 0xffffffff));
|
||||
builder.add(ItemTextureQuadConverter.genQuad(format, transform, 0, 0, 16, 16, SOUTH_Z_BASE, base, EnumFacing.SOUTH, 0xffffffff));
|
||||
TextureAtlasSprite cover = bakedTextureGetter.apply(coverLocation);
|
||||
builder.add(ItemTextureQuadConverter.genQuad(format, transform, 0, 0, 16, 16, NORTH_Z_COVER, cover, EnumFacing.NORTH, 0xffffffff));
|
||||
builder.add(ItemTextureQuadConverter.genQuad(format, transform, 0, 0, 16, 16, SOUTH_Z_COVER, cover, EnumFacing.SOUTH, 0xffffffff));
|
||||
if (particleSprite == null)
|
||||
{
|
||||
particleSprite = cover;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return new BakedDynBucket(this, builder.build(), fluidSprite, format, Maps.immutableEnumMap(transformMap), Maps.newHashMap());
|
||||
return new BakedDynBucket(this, builder.build(), particleSprite, format, Maps.immutableEnumMap(transformMap), Maps.newHashMap());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -235,6 +241,135 @@ public final class ModelDynBucket implements IModel
|
||||
{
|
||||
// no need to clear cache since we create a new model instance
|
||||
}
|
||||
|
||||
public void register(TextureMap map)
|
||||
{
|
||||
// only create these textures if they are not added by a resource pack
|
||||
|
||||
if (getResource(new ResourceLocation(ForgeVersion.MOD_ID, "textures/items/bucket_cover.png")) == null)
|
||||
{
|
||||
ResourceLocation bucketCover = new ResourceLocation(ForgeVersion.MOD_ID, "items/bucket_cover");
|
||||
BucketCoverSprite bucketCoverSprite = new BucketCoverSprite(bucketCover);
|
||||
map.setTextureEntry(bucketCoverSprite);
|
||||
}
|
||||
|
||||
if (getResource(new ResourceLocation(ForgeVersion.MOD_ID, "textures/items/bucket_base.png")) == null)
|
||||
{
|
||||
ResourceLocation bucketBase = new ResourceLocation(ForgeVersion.MOD_ID, "items/bucket_base");
|
||||
BucketBaseSprite bucketBaseSprite = new BucketBaseSprite(bucketBase);
|
||||
map.setTextureEntry(bucketBaseSprite);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static IResource getResource(ResourceLocation resourceLocation)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Minecraft.getMinecraft().getResourceManager().getResource(resourceLocation);
|
||||
}
|
||||
catch (IOException ignored)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class BucketBaseSprite extends TextureAtlasSprite
|
||||
{
|
||||
private final ResourceLocation bucket = new ResourceLocation("items/bucket_empty");
|
||||
private final ImmutableList<ResourceLocation> dependencies = ImmutableList.of(bucket);
|
||||
|
||||
private BucketBaseSprite(ResourceLocation resourceLocation)
|
||||
{
|
||||
super(resourceLocation.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCustomLoader(@Nonnull IResourceManager manager, @Nonnull ResourceLocation location)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ResourceLocation> getDependencies()
|
||||
{
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean load(@Nonnull IResourceManager manager, @Nonnull ResourceLocation location, @Nonnull Function<ResourceLocation, TextureAtlasSprite> textureGetter)
|
||||
{
|
||||
final TextureAtlasSprite sprite = textureGetter.apply(bucket);
|
||||
width = sprite.getIconWidth();
|
||||
height = sprite.getIconHeight();
|
||||
final int[][] pixels = sprite.getFrameTextureData(0);
|
||||
this.clearFramesTextureData();
|
||||
this.framesTextureData.add(pixels);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a bucket cover sprite from the vanilla resource.
|
||||
*/
|
||||
private static final class BucketCoverSprite extends TextureAtlasSprite
|
||||
{
|
||||
private final ResourceLocation bucket = new ResourceLocation("items/bucket_empty");
|
||||
private final ResourceLocation bucketCoverMask = new ResourceLocation(ForgeVersion.MOD_ID, "items/vanilla_bucket_cover_mask");
|
||||
private final ImmutableList<ResourceLocation> dependencies = ImmutableList.of(bucket, bucketCoverMask);
|
||||
|
||||
private BucketCoverSprite(ResourceLocation resourceLocation)
|
||||
{
|
||||
super(resourceLocation.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCustomLoader(@Nonnull IResourceManager manager, @Nonnull ResourceLocation location)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ResourceLocation> getDependencies()
|
||||
{
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean load(@Nonnull IResourceManager manager, @Nonnull ResourceLocation location, @Nonnull Function<ResourceLocation, TextureAtlasSprite> textureGetter)
|
||||
{
|
||||
final TextureAtlasSprite sprite = textureGetter.apply(bucket);
|
||||
final TextureAtlasSprite alphaMask = textureGetter.apply(bucketCoverMask);
|
||||
width = sprite.getIconWidth();
|
||||
height = sprite.getIconHeight();
|
||||
final int[][] pixels = new int[Minecraft.getMinecraft().gameSettings.mipmapLevels + 1][];
|
||||
pixels[0] = new int[width * height];
|
||||
|
||||
IResource empty = getResource(new ResourceLocation("textures/items/bucket_empty.png"));
|
||||
IResource mask = getResource(new ResourceLocation(ForgeVersion.MOD_ID, "textures/items/vanilla_bucket_cover_mask.png"));
|
||||
|
||||
// use the alpha mask if it fits, otherwise leave the cover texture blank
|
||||
if (empty != null && mask != null && Objects.equals(empty.getResourcePackName(), mask.getResourcePackName()) &&
|
||||
alphaMask.getIconWidth() == width && alphaMask.getIconHeight() == height)
|
||||
{
|
||||
final int[][] oldPixels = sprite.getFrameTextureData(0);
|
||||
final int[][] alphaPixels = alphaMask.getFrameTextureData(0);
|
||||
|
||||
for (int p = 0; p < width * height; p++)
|
||||
{
|
||||
final int alphaMultiplier = alphaPixels[0][p] >>> 24;
|
||||
final int oldPixel = oldPixels[0][p];
|
||||
final int oldPixelAlpha = oldPixel >>> 24;
|
||||
final int newAlpha = oldPixelAlpha * alphaMultiplier / 0xFF;
|
||||
pixels[0][p] = (oldPixel & 0xFFFFFF) + (newAlpha << 24);
|
||||
}
|
||||
}
|
||||
|
||||
this.clearFramesTextureData();
|
||||
this.framesTextureData.add(pixels);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class BakedDynBucketOverrideHandler extends ItemOverrideList
|
||||
@@ -278,51 +413,24 @@ public final class ModelDynBucket implements IModel
|
||||
}
|
||||
|
||||
// the dynamic bucket is based on the empty bucket
|
||||
private static final class BakedDynBucket implements IBakedModel
|
||||
private static final class BakedDynBucket extends BakedItemModel
|
||||
{
|
||||
|
||||
private final ModelDynBucket parent;
|
||||
// FIXME: guava cache?
|
||||
private final Map<String, IBakedModel> cache; // contains all the baked models since they'll never change
|
||||
private final ImmutableMap<TransformType, TRSRTransformation> transforms;
|
||||
private final ImmutableList<BakedQuad> quads;
|
||||
private final TextureAtlasSprite particle;
|
||||
private final VertexFormat format;
|
||||
|
||||
public BakedDynBucket(ModelDynBucket parent,
|
||||
ImmutableList<BakedQuad> quads, TextureAtlasSprite particle, VertexFormat format, ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> transforms,
|
||||
ImmutableList<BakedQuad> quads,
|
||||
TextureAtlasSprite particle,
|
||||
VertexFormat format,
|
||||
ImmutableMap<TransformType, TRSRTransformation> transforms,
|
||||
Map<String, IBakedModel> cache)
|
||||
{
|
||||
this.quads = quads;
|
||||
this.particle = particle;
|
||||
super(quads, particle, transforms, BakedDynBucketOverrideHandler.INSTANCE);
|
||||
this.format = format;
|
||||
this.parent = parent;
|
||||
this.transforms = transforms;
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemOverrideList getOverrides()
|
||||
{
|
||||
return BakedDynBucketOverrideHandler.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<? extends IBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType)
|
||||
{
|
||||
return PerspectiveMapWrapper.handlePerspective(this, transforms, cameraTransformType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand)
|
||||
{
|
||||
if(side == null) return quads;
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
public boolean isAmbientOcclusion() { return true; }
|
||||
public boolean isGui3d() { return false; }
|
||||
public boolean isBuiltInRenderer() { return false; }
|
||||
public TextureAtlasSprite getParticleTexture() { return particle; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -318,79 +318,6 @@ public final class ModelLoader extends ModelBakery
|
||||
}
|
||||
}
|
||||
ProgressManager.pop(itemBar);
|
||||
|
||||
// replace vanilla bucket models if desired. done afterwards for performance reasons
|
||||
if(ForgeModContainer.replaceVanillaBucketModel)
|
||||
{
|
||||
// ensure the bucket model is loaded
|
||||
if(!stateModels.containsKey(ModelDynBucket.LOCATION))
|
||||
{
|
||||
// load forges blockstate json for it
|
||||
try
|
||||
{
|
||||
registerVariant(getModelBlockDefinition(ModelDynBucket.LOCATION), ModelDynBucket.LOCATION);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
FMLLog.log.error("Could not load the forge bucket model from the blockstate", exception);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// empty bucket
|
||||
for(String s : getVariantNames(Items.BUCKET))
|
||||
{
|
||||
ModelResourceLocation memory = getInventoryVariant(s);
|
||||
IModel model = ModelLoaderRegistry.getModelOrMissing(new ResourceLocation(ForgeVersion.MOD_ID, "item/bucket"));
|
||||
// only on successful load, otherwise continue using the old model
|
||||
if(model != getMissingModel())
|
||||
{
|
||||
stateModels.put(memory, model);
|
||||
}
|
||||
}
|
||||
|
||||
setBucketModel(Items.WATER_BUCKET);
|
||||
setBucketModel(Items.LAVA_BUCKET);
|
||||
// milk bucket only replaced if some mod adds milk
|
||||
if(FluidRegistry.isFluidRegistered("milk"))
|
||||
{
|
||||
// can the milk be put into a bucket?
|
||||
Fluid milk = FluidRegistry.getFluid("milk");
|
||||
FluidStack milkStack = new FluidStack(milk, Fluid.BUCKET_VOLUME);
|
||||
IFluidHandler bucketHandler = FluidUtil.getFluidHandler(new ItemStack(Items.BUCKET));
|
||||
if (bucketHandler != null && bucketHandler.fill(milkStack, false) == Fluid.BUCKET_VOLUME)
|
||||
{
|
||||
setBucketModel(Items.MILK_BUCKET);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// milk bucket if no milk fluid is present
|
||||
for(String s : getVariantNames(Items.MILK_BUCKET))
|
||||
{
|
||||
ModelResourceLocation memory = getInventoryVariant(s);
|
||||
IModel model = ModelLoaderRegistry.getModelOrMissing(new ResourceLocation(ForgeVersion.MOD_ID, "item/bucket_milk"));
|
||||
// only on successful load, otherwise continue using the old model
|
||||
if(model != getMissingModel())
|
||||
{
|
||||
stateModels.put(memory, model);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setBucketModel(Item item)
|
||||
{
|
||||
for(String s : getVariantNames(item))
|
||||
{
|
||||
ModelResourceLocation memory = getInventoryVariant(s);
|
||||
IModel model = stateModels.get(ModelDynBucket.LOCATION);
|
||||
if(model != null)
|
||||
{
|
||||
stateModels.put(memory, model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -112,6 +112,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
||||
public static boolean shouldSortRecipies = true;
|
||||
public static boolean disableVersionCheck = false;
|
||||
public static boolean forgeLightPipelineEnabled = true;
|
||||
@Deprecated // TODO remove in 1.13
|
||||
public static boolean replaceVanillaBucketModel = true;
|
||||
public static boolean zoomInMissingModelTextInGui = false;
|
||||
public static boolean disableStairSlabCulling = false; // Also known as the "DontCullStairsBecauseIUseACrappyTexturePackThatBreaksBasicBlockShapesSoICantTrustBasicBlockCulling" flag
|
||||
@@ -213,6 +214,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
||||
if (config.getCategory(CATEGORY_GENERAL).containsKey("spawnHasFuzz")) config.getCategory(CATEGORY_GENERAL).remove("spawnHasFuzz");
|
||||
if (config.getCategory(CATEGORY_GENERAL).containsKey("disableStitchedFileSaving")) config.getCategory(CATEGORY_GENERAL).remove("disableStitchedFileSaving");
|
||||
if (config.getCategory(CATEGORY_CLIENT).containsKey("java8Reminder")) config.getCategory(CATEGORY_CLIENT).remove("java8Reminder");
|
||||
if (config.getCategory(CATEGORY_CLIENT).containsKey("replaceVanillaBucketModel")) config.getCategory(CATEGORY_CLIENT).remove("replaceVanillaBucketModel");
|
||||
|
||||
// remap properties wrongly listed as general properties to client properties
|
||||
remapGeneralPropertyToClient("biomeSkyBlendRange");
|
||||
@@ -315,12 +317,6 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
||||
// Client-Side only properties
|
||||
propOrder = new ArrayList<String>();
|
||||
|
||||
prop = config.get(Configuration.CATEGORY_CLIENT, "replaceVanillaBucketModel", false,
|
||||
"Replace the vanilla bucket models with Forges own dynamic bucket model. Unifies bucket visuals if a mod uses the Forge bucket model.");
|
||||
prop.setLanguageKey("forge.configgui.replaceBuckets").setRequiresMcRestart(true);
|
||||
replaceVanillaBucketModel = prop.getBoolean(false);
|
||||
propOrder.add(prop.getName());
|
||||
|
||||
prop = config.get(Configuration.CATEGORY_CLIENT, "zoomInMissingModelTextInGui", false,
|
||||
"Toggle off to make missing model text in the gui fit inside the slot.");
|
||||
zoomInMissingModelTextInGui = prop.getBoolean(false);
|
||||
|
||||
Reference in new issue
Block a user