pick 97420a31d The big reformat of 2020

This commit is contained in:
yueh
2020-06-16 21:41:28 +02:00
parent 5304b3febe
commit 5225ea426b
2252 changed files with 95466 additions and 118582 deletions
@@ -1,10 +1,10 @@
package appeng.client.render.model;
import javax.annotation.Nullable;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.data.ModelProperty;
import javax.annotation.Nullable;
public abstract class AEInternalModelData implements IModelData {
@Override
@@ -1,16 +1,19 @@
package appeng.client.render.model;
import java.util.Objects;
import javax.annotation.Nullable;
import com.google.common.base.Preconditions;
import net.minecraft.util.Direction;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.data.ModelProperty;
import javax.annotation.Nullable;
import java.util.Objects;
/**
* This implementation of IModelData allows us to know precisely which data is part of the
* model data. This is relevant for {@link AutoRotatingBakedModel} and {@link AutoRotatingCacheKey}.
* This implementation of IModelData allows us to know precisely which data is
* part of the model data. This is relevant for {@link AutoRotatingBakedModel}
* and {@link AutoRotatingCacheKey}.
*/
public class AEModelData implements IModelData {
@@ -36,11 +39,12 @@ public class AEModelData implements IModelData {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
AEModelData that = (AEModelData) o;
return up == that.up &&
forward == that.forward;
return up == that.up && forward == that.forward;
}
@Override
@@ -18,13 +18,19 @@
package appeng.client.render.model;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import appeng.client.render.FacingToRotation;
import com.google.common.base.Objects;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.Vector4f;
import net.minecraft.client.renderer.model.BakedQuad;
@@ -44,298 +50,249 @@ import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
import net.minecraftforge.client.model.pipeline.QuadGatheringTransformer;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import appeng.client.render.FacingToRotation;
public class AutoRotatingBakedModel implements IBakedModel {
public class AutoRotatingBakedModel implements IBakedModel
{
private final IBakedModel parent;
private final LoadingCache<AutoRotatingCacheKey, List<BakedQuad>> quadCache;
private final IBakedModel parent;
private final LoadingCache<AutoRotatingCacheKey, List<BakedQuad>> quadCache;
public AutoRotatingBakedModel(IBakedModel parent) {
this.parent = parent;
// 6 (DUNSWE) * 6 (DUNSWE) * 7 (DUNSWE + null) = 252
this.quadCache = CacheBuilder.newBuilder().maximumSize(252)
.build(new CacheLoader<AutoRotatingCacheKey, List<BakedQuad>>() {
@Override
public List<BakedQuad> load(AutoRotatingCacheKey key) {
return AutoRotatingBakedModel.this.getRotatedModel(key.getBlockState(), key.getSide(),
new Random(0), key.getModelData());
}
});
}
public AutoRotatingBakedModel(IBakedModel parent )
{
this.parent = parent;
// 6 (DUNSWE) * 6 (DUNSWE) * 7 (DUNSWE + null) = 252
this.quadCache = CacheBuilder.newBuilder().maximumSize( 252 ).build( new CacheLoader<AutoRotatingCacheKey, List<BakedQuad>>()
{
@Override
public List<BakedQuad> load( AutoRotatingCacheKey key )
{
return AutoRotatingBakedModel.this.getRotatedModel( key.getBlockState(), key.getSide(), new Random(0), key.getModelData() );
}
} );
}
private List<BakedQuad> getRotatedModel(BlockState state, Direction side, Random rand, AEModelData modelData) {
FacingToRotation f2r = FacingToRotation.get(modelData.getForward(), modelData.getUp());
private List<BakedQuad> getRotatedModel(BlockState state, Direction side, Random rand, AEModelData modelData)
{
FacingToRotation f2r = FacingToRotation.get( modelData.getForward(), modelData.getUp() );
if (f2r.isRedundant()) {
return AutoRotatingBakedModel.this.parent.getQuads(state, side, rand, modelData);
}
if (f2r.isRedundant()) {
return AutoRotatingBakedModel.this.parent.getQuads( state, side, rand, modelData );
}
List<BakedQuad> original = AutoRotatingBakedModel.this.parent.getQuads(state, f2r.resultingRotate(side), rand,
modelData);
List<BakedQuad> rotated = new ArrayList<>(original.size());
for (BakedQuad quad : original) {
BakedQuadBuilder builder = new BakedQuadBuilder();
VertexRotator rot = new VertexRotator(f2r, quad.getFace());
rot.setParent(builder);
quad.pipe(rot);
if (quad.getFace() != null) {
builder.setQuadOrientation(f2r.rotate(quad.getFace()));
} else {
builder.setQuadOrientation(null);
List<BakedQuad> original = AutoRotatingBakedModel.this.parent.getQuads( state, f2r.resultingRotate( side ), rand, modelData );
List<BakedQuad> rotated = new ArrayList<>( original.size() );
for( BakedQuad quad : original )
{
BakedQuadBuilder builder = new BakedQuadBuilder();
VertexRotator rot = new VertexRotator( f2r, quad.getFace() );
rot.setParent( builder );
quad.pipe( rot );
if( quad.getFace() != null )
{
builder.setQuadOrientation( f2r.rotate( quad.getFace() ) );
}
else
{
builder.setQuadOrientation( null );
}
BakedQuad unpackedQuad = builder.build();
}
BakedQuad unpackedQuad = builder.build();
// Make a copy of it to resolve the vertex data and throw away the unpacked
// stuff
// This also fixes a bug in Forge's UnpackedBakedQuad, which unpacks a
// byte-based normal like 0,0,-1
// to 0,0,-0.99607843. We replace these normals with the proper 0,0,-1 when
// rotation, which
// causes a bug in the AO lighter, if an unpacked quad pipes this value back to
// it.
// Packing it back to the vanilla vertex format will fix this inconsistency
// because it converts
// the normal back to a byte-based format, which then re-applies Forge's own bug
// when piping it
// to the AO lighter, thus fixing our problem.
BakedQuad packedQuad = new BakedQuad(unpackedQuad.getVertexData(), quad.getTintIndex(),
unpackedQuad.getFace(), quad.func_187508_a(), quad.shouldApplyDiffuseLighting());
rotated.add(packedQuad);
}
return rotated;
}
// Make a copy of it to resolve the vertex data and throw away the unpacked stuff
// This also fixes a bug in Forge's UnpackedBakedQuad, which unpacks a byte-based normal like 0,0,-1
// to 0,0,-0.99607843. We replace these normals with the proper 0,0,-1 when rotation, which
// causes a bug in the AO lighter, if an unpacked quad pipes this value back to it.
// Packing it back to the vanilla vertex format will fix this inconsistency because it converts
// the normal back to a byte-based format, which then re-applies Forge's own bug when piping it
// to the AO lighter, thus fixing our problem.
BakedQuad packedQuad = new BakedQuad( unpackedQuad.getVertexData(), quad.getTintIndex(), unpackedQuad.getFace(), quad.func_187508_a(), quad
.shouldApplyDiffuseLighting() );
rotated.add( packedQuad );
}
return rotated;
}
@Override
public boolean isAmbientOcclusion() {
return this.parent.isAmbientOcclusion();
}
@Override
public boolean isAmbientOcclusion()
{
return this.parent.isAmbientOcclusion();
}
@Override
public boolean isGui3d() {
return this.parent.isGui3d();
}
@Override
public boolean isGui3d()
{
return this.parent.isGui3d();
}
@Override
public boolean func_230044_c_() {
return parent.func_230044_c_();
}
@Override
public boolean func_230044_c_() {
return parent.func_230044_c_();
}
@Override
public boolean isBuiltInRenderer() {
return this.parent.isBuiltInRenderer();
}
@Override
public boolean isBuiltInRenderer()
{
return this.parent.isBuiltInRenderer();
}
@Override
public TextureAtlasSprite getParticleTexture() {
return this.parent.getParticleTexture();
}
@Override
public TextureAtlasSprite getParticleTexture()
{
return this.parent.getParticleTexture();
}
@Override
@Deprecated
public ItemCameraTransforms getItemCameraTransforms() {
return parent.getItemCameraTransforms();
}
@Override
@Deprecated
public ItemCameraTransforms getItemCameraTransforms() {
return parent.getItemCameraTransforms();
}
@Override
public ItemOverrideList getOverrides() {
return parent.getOverrides();
}
@Override
public ItemOverrideList getOverrides() {
return parent.getOverrides();
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
return getQuads(state, side, rand, EmptyModelData.INSTANCE);
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
return getQuads(state, side, rand, EmptyModelData.INSTANCE);
}
@Nonnull
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand,
@Nonnull IModelData extraData) {
@Nonnull
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand, @Nonnull IModelData extraData) {
if (!(extraData instanceof AEModelData)) {
return this.parent.getQuads(state, side, rand, extraData);
}
if (!(extraData instanceof AEModelData)) {
return this.parent.getQuads( state, side, rand, extraData );
}
AEModelData aeModelData = (AEModelData) extraData;
quadCache.invalidateAll(); // FIXME
if (aeModelData.isCacheable()) {
return quadCache.getUnchecked(new AutoRotatingCacheKey(state, aeModelData, side));
} else {
return this.getRotatedModel(state, side, rand, aeModelData);
}
}
AEModelData aeModelData = (AEModelData) extraData;
quadCache.invalidateAll(); // FIXME
if (aeModelData.isCacheable()) {
return quadCache.getUnchecked(new AutoRotatingCacheKey(state, aeModelData, side));
} else {
return this.getRotatedModel(state, side, rand, aeModelData);
}
}
@Nonnull
@Override
public IModelData getModelData(@Nonnull ILightReader world, @Nonnull BlockPos pos, @Nonnull BlockState state,
@Nonnull IModelData tileData) {
return this.parent.getModelData(world, pos, state, tileData);
}
@Nonnull
@Override
public IModelData getModelData(@Nonnull ILightReader world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nonnull IModelData tileData) {
return this.parent.getModelData(world, pos, state, tileData);
}
public static class VertexRotator extends QuadGatheringTransformer {
private final FacingToRotation f2r;
private final Direction face;
public static class VertexRotator extends QuadGatheringTransformer
{
private final FacingToRotation f2r;
private final Direction face;
public VertexRotator(FacingToRotation f2r, Direction face) {
this.f2r = f2r;
this.face = face;
}
public VertexRotator( FacingToRotation f2r, Direction face )
{
this.f2r = f2r;
this.face = face;
}
@Override
public void setParent(IVertexConsumer parent) {
super.setParent(parent);
if (Objects.equal(this.getVertexFormat(), parent.getVertexFormat())) {
return;
}
this.setVertexFormat(parent.getVertexFormat());
}
@Override
public void setParent( IVertexConsumer parent )
{
super.setParent( parent );
if( Objects.equal( this.getVertexFormat(), parent.getVertexFormat() ) )
{
return;
}
this.setVertexFormat( parent.getVertexFormat() );
}
@Override
protected void processQuad() {
VertexFormat format = this.parent.getVertexFormat();
ImmutableList<VertexFormatElement> elements = format.getElements();
@Override
protected void processQuad()
{
VertexFormat format = this.parent.getVertexFormat();
ImmutableList<VertexFormatElement> elements = format.getElements();
for (int v = 0; v < 4; v++) {
for (int e = 0; e < elements.size(); e++) {
VertexFormatElement element = elements.get(e);
if (element.getUsage() == VertexFormatElement.Usage.POSITION) {
this.parent.put(e, this.transform(this.quadData[e][v]));
} else if (element.getUsage() == VertexFormatElement.Usage.NORMAL) {
this.parent.put(e, this.transformNormal(this.quadData[e][v]));
} else {
this.parent.put(e, this.quadData[e][v]);
}
}
}
}
for( int v = 0; v < 4; v++ )
{
for( int e = 0; e < elements.size(); e++ )
{
VertexFormatElement element = elements.get( e );
if( element.getUsage() == VertexFormatElement.Usage.POSITION )
{
this.parent.put( e, this.transform( this.quadData[e][v] ) );
}
else if( element.getUsage() == VertexFormatElement.Usage.NORMAL )
{
this.parent.put( e, this.transformNormal( this.quadData[e][v] ) );
}
else
{
this.parent.put( e, this.quadData[e][v] );
}
}
}
}
private float[] transform(float[] fs) {
switch (fs.length) {
case 3:
Vector4f vec = new Vector4f(fs[0], fs[1], fs[2], 1);
vec.setX(vec.getX() - 0.5f);
vec.setY(vec.getY() - 0.5f);
vec.setZ(vec.getZ() - 0.5f);
vec.transform(this.f2r.getMat());
vec.setX(vec.getX() + 0.5f);
vec.setY(vec.getY() + 0.5f);
vec.setZ(vec.getZ() + 0.5f);
return new float[] { vec.getX(), vec.getY(), vec.getZ() };
case 4:
Vector4f vecc = new Vector4f(fs[0], fs[1], fs[2], fs[3]);
vecc.setX(vecc.getX() - 0.5f);
vecc.setY(vecc.getY() - 0.5f);
vecc.setZ(vecc.getZ() - 0.5f);
vecc.transform(this.f2r.getMat());
vecc.setX(vecc.getX() + 0.5f);
vecc.setY(vecc.getY() + 0.5f);
vecc.setZ(vecc.getZ() + 0.5f);
return new float[] { vecc.getX(), vecc.getY(), vecc.getZ(), vecc.getW() };
private float[] transform( float[] fs )
{
switch( fs.length )
{
case 3:
Vector4f vec = new Vector4f( fs[0], fs[1], fs[2], 1 );
vec.setX(vec.getX() - 0.5f);
vec.setY(vec.getY() - 0.5f);
vec.setZ(vec.getZ() - 0.5f);
vec.transform(this.f2r.getMat());
vec.setX(vec.getX() + 0.5f);
vec.setY(vec.getY() + 0.5f);
vec.setZ(vec.getZ() + 0.5f);
return new float[] { vec.getX(), vec.getY(), vec.getZ() };
case 4:
Vector4f vecc = new Vector4f( fs[0], fs[1], fs[2], fs[3] );
vecc.setX(vecc.getX() - 0.5f);
vecc.setY(vecc.getY() - 0.5f);
vecc.setZ(vecc.getZ() - 0.5f);
vecc.transform(this.f2r.getMat());
vecc.setX(vecc.getX() + 0.5f);
vecc.setY(vecc.getY() + 0.5f);
vecc.setZ(vecc.getZ() + 0.5f);
return new float[] { vecc.getX(), vecc.getY(), vecc.getZ(), vecc.getW() };
default:
return fs;
}
}
default:
return fs;
}
}
private float[] transformNormal(float[] fs) {
if (this.face == null) {
switch (fs.length) {
case 3:
Vector4f vec = new Vector4f(fs[0], fs[1], fs[2], 0);
vec.transform(this.f2r.getMat());
return new float[] { vec.getX(), vec.getY(), vec.getZ() };
case 4:
Vector4f vec4 = new Vector4f(fs[0], fs[1], fs[2], fs[3]);
vec4.transform(this.f2r.getMat());
return new float[] { vec4.getX(), vec4.getY(), vec4.getZ(), 0 };
private float[] transformNormal( float[] fs )
{
if( this.face == null )
{
switch( fs.length )
{
case 3:
Vector4f vec = new Vector4f( fs[0], fs[1], fs[2], 0 );
vec.transform( this.f2r.getMat() );
return new float[] {
vec.getX(),
vec.getY(),
vec.getZ()
};
case 4:
Vector4f vec4 = new Vector4f( fs[0], fs[1], fs[2], fs[3] );
vec4.transform( this.f2r.getMat() );
return new float[] {
vec4.getX(),
vec4.getY(),
vec4.getZ(),
0
};
default:
return fs;
}
} else {
switch (fs.length) {
case 3:
Vec3i vec = this.f2r.rotate(this.face).getDirectionVec();
return new float[] { vec.getX(), vec.getY(), vec.getZ() };
case 4:
Vector4f veccc = new Vector4f(fs[0], fs[1], fs[2], fs[3]);
Vec3i vecc = this.f2r.rotate(this.face).getDirectionVec();
return new float[] { vecc.getX(), vecc.getY(), vecc.getZ(), veccc.getW() };
default:
return fs;
}
}
else
{
switch( fs.length )
{
case 3:
Vec3i vec = this.f2r.rotate( this.face ).getDirectionVec();
return new float[] {
vec.getX(),
vec.getY(),
vec.getZ()
};
case 4:
Vector4f veccc = new Vector4f( fs[0], fs[1], fs[2], fs[3] );
Vec3i vecc = this.f2r.rotate( this.face ).getDirectionVec();
return new float[] {
vecc.getX(),
vecc.getY(),
vecc.getZ(),
veccc.getW()
};
default:
return fs;
}
}
}
default:
return fs;
}
}
}
@Override
public void setQuadTint(int tint) {
this.parent.setQuadTint(tint);
}
@Override
public void setQuadTint( int tint )
{
this.parent.setQuadTint( tint );
}
@Override
public void setQuadOrientation(Direction orientation) {
this.parent.setQuadOrientation(f2r.rotate(orientation));
}
@Override
public void setQuadOrientation( Direction orientation )
{
this.parent.setQuadOrientation( f2r.rotate(orientation) );
}
@Override
public void setApplyDiffuseLighting(boolean diffuse) {
this.parent.setApplyDiffuseLighting(diffuse);
}
@Override
public void setApplyDiffuseLighting( boolean diffuse )
{
this.parent.setApplyDiffuseLighting( diffuse );
}
@Override
public void setTexture( TextureAtlasSprite texture )
{
this.parent.setTexture( texture );
}
}
@Override
public void setTexture(TextureAtlasSprite texture) {
this.parent.setTexture(texture);
}
}
}
@@ -18,63 +18,54 @@
package appeng.client.render.model;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction;
/**
* Used as the cache key for caching automatically rotated baked models.
*/
final class AutoRotatingCacheKey
{
private final BlockState blockState;
private final AEModelData modelData;
private final Direction side;
final class AutoRotatingCacheKey {
private final BlockState blockState;
private final AEModelData modelData;
private final Direction side;
AutoRotatingCacheKey( BlockState blockState, AEModelData modelData, Direction side )
{
this.blockState = blockState;
this.modelData = modelData;
this.side = side;
}
AutoRotatingCacheKey(BlockState blockState, AEModelData modelData, Direction side) {
this.blockState = blockState;
this.modelData = modelData;
this.side = side;
}
public BlockState getBlockState()
{
return this.blockState;
}
public BlockState getBlockState() {
return this.blockState;
}
public AEModelData getModelData() {
return modelData;
}
public AEModelData getModelData() {
return modelData;
}
public Direction getSide()
{
return this.side;
}
public Direction getSide() {
return this.side;
}
@Override
public boolean equals( Object o )
{
if( this == o )
{
return true;
}
if( o == null || this.getClass() != o.getClass() )
{
return false;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || this.getClass() != o.getClass()) {
return false;
}
AutoRotatingCacheKey cacheKey = (AutoRotatingCacheKey) o;
return this.blockState.equals( cacheKey.blockState ) && this.modelData.equals(cacheKey.modelData) && this.side == cacheKey.side;
}
AutoRotatingCacheKey cacheKey = (AutoRotatingCacheKey) o;
return this.blockState.equals(cacheKey.blockState) && this.modelData.equals(cacheKey.modelData)
&& this.side == cacheKey.side;
}
@Override
public int hashCode()
{
int result = this.blockState.hashCode();
result = 31 * result + this.modelData.hashCode();
result = 31 * result + ( this.side != null ? this.side.hashCode() : 0 );
return result;
}
@Override
public int hashCode() {
int result = this.blockState.hashCode();
result = 31 * result + this.modelData.hashCode();
result = 31 * result + (this.side != null ? this.side.hashCode() : 0);
return result;
}
}
@@ -1,10 +1,10 @@
package appeng.client.render.model;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import javax.annotation.Nullable;
import com.google.common.cache.Cache;
@@ -30,191 +30,160 @@ import appeng.api.util.AEColor;
import appeng.client.render.cablebus.CubeBuilder;
import appeng.core.AELog;
class BiometricCardBakedModel implements IBakedModel {
class BiometricCardBakedModel implements IBakedModel
{
private final IBakedModel baseModel;
private final IBakedModel baseModel;
private final TextureAtlasSprite texture;
private final TextureAtlasSprite texture;
private final int hash;
private final int hash;
private final Cache<Integer, BiometricCardBakedModel> modelCache;
private final Cache<Integer, BiometricCardBakedModel> modelCache;
private final ImmutableList<BakedQuad> generalQuads;
private final ImmutableList<BakedQuad> generalQuads;
BiometricCardBakedModel(IBakedModel baseModel, TextureAtlasSprite texture) {
this(baseModel, texture, 0, createCache());
}
BiometricCardBakedModel( IBakedModel baseModel, TextureAtlasSprite texture )
{
this( baseModel, texture, 0, createCache() );
}
private BiometricCardBakedModel(IBakedModel baseModel, TextureAtlasSprite texture, int hash,
Cache<Integer, BiometricCardBakedModel> modelCache) {
this.baseModel = baseModel;
this.texture = texture;
this.hash = hash;
this.generalQuads = ImmutableList.copyOf(this.buildGeneralQuads());
this.modelCache = modelCache;
}
private BiometricCardBakedModel( IBakedModel baseModel, TextureAtlasSprite texture, int hash, Cache<Integer, BiometricCardBakedModel> modelCache )
{
this.baseModel = baseModel;
this.texture = texture;
this.hash = hash;
this.generalQuads = ImmutableList.copyOf( this.buildGeneralQuads() );
this.modelCache = modelCache;
}
private static Cache<Integer, BiometricCardBakedModel> createCache() {
return CacheBuilder.newBuilder().maximumSize(100).build();
}
private static Cache<Integer, BiometricCardBakedModel> createCache()
{
return CacheBuilder.newBuilder().maximumSize( 100 ).build();
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
@Override
public List<BakedQuad> getQuads( @Nullable BlockState state, @Nullable Direction side, Random rand )
{
List<BakedQuad> quads = this.baseModel.getQuads(state, side, rand, EmptyModelData.INSTANCE);
List<BakedQuad> quads = this.baseModel.getQuads( state, side, rand, EmptyModelData.INSTANCE );
if (side != null) {
return quads;
}
if( side != null )
{
return quads;
}
List<BakedQuad> result = new ArrayList<>(quads.size() + this.generalQuads.size());
result.addAll(quads);
result.addAll(this.generalQuads);
return result;
}
List<BakedQuad> result = new ArrayList<>( quads.size() + this.generalQuads.size() );
result.addAll( quads );
result.addAll( this.generalQuads );
return result;
}
private List<BakedQuad> buildGeneralQuads() {
CubeBuilder builder = new CubeBuilder();
private List<BakedQuad> buildGeneralQuads()
{
CubeBuilder builder = new CubeBuilder();
builder.setTexture(this.texture);
builder.setTexture( this.texture );
AEColor col = AEColor.values()[Math.abs(3 + this.hash) % AEColor.values().length];
if (this.hash == 0) {
col = AEColor.BLACK;
}
AEColor col = AEColor.values()[Math.abs( 3 + this.hash ) % AEColor.values().length];
if( this.hash == 0 )
{
col = AEColor.BLACK;
}
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 6; y++) {
final boolean isLit;
for( int x = 0; x < 8; x++ )
{
for( int y = 0; y < 6; y++ )
{
final boolean isLit;
// This makes the border always use the darker color
if (x == 0 || y == 0 || x == 7 || y == 5) {
isLit = false;
} else {
isLit = (this.hash & (1 << x)) != 0 || (this.hash & (1 << y)) != 0;
}
// This makes the border always use the darker color
if( x == 0 || y == 0 || x == 7 || y == 5 )
{
isLit = false;
}
else
{
isLit = ( this.hash & ( 1 << x ) ) != 0 || ( this.hash & ( 1 << y ) ) != 0;
}
if (isLit) {
builder.setColorRGB(col.mediumVariant);
} else {
final float scale = 0.3f / 255.0f;
builder.setColorRGB(((col.blackVariant >> 16) & 0xff) * scale,
((col.blackVariant >> 8) & 0xff) * scale, (col.blackVariant & 0xff) * scale);
}
if( isLit )
{
builder.setColorRGB( col.mediumVariant );
}
else
{
final float scale = 0.3f / 255.0f;
builder.setColorRGB( ( ( col.blackVariant >> 16 ) & 0xff ) * scale, ( ( col.blackVariant >> 8 ) & 0xff ) * scale, ( col.blackVariant & 0xff ) * scale );
}
builder.addCube(4 + x, 6 + y, 7.5f, 4 + x + 1, 6 + y + 1, 8.5f);
}
}
return builder.getOutput();
}
builder.addCube( 4 + x, 6 + y, 7.5f, 4 + x + 1, 6 + y + 1, 8.5f );
}
}
return builder.getOutput();
}
@Override
public boolean isAmbientOcclusion() {
return this.baseModel.isAmbientOcclusion();
}
@Override
public boolean isAmbientOcclusion()
{
return this.baseModel.isAmbientOcclusion();
}
@Override
public boolean isGui3d() {
return this.baseModel.isGui3d();
}
@Override
public boolean isGui3d()
{
return this.baseModel.isGui3d();
}
@Override
public boolean func_230044_c_() {
return false;// TODO
}
@Override
public boolean func_230044_c_()
{
return false;//TODO
}
@Override
public boolean isBuiltInRenderer() {
return this.baseModel.isBuiltInRenderer();
}
@Override
public boolean isBuiltInRenderer()
{
return this.baseModel.isBuiltInRenderer();
}
@Override
public TextureAtlasSprite getParticleTexture() {
return this.baseModel.getParticleTexture();
}
@Override
public TextureAtlasSprite getParticleTexture()
{
return this.baseModel.getParticleTexture();
}
@Override
public ItemCameraTransforms getItemCameraTransforms() {
return this.baseModel.getItemCameraTransforms();
}
@Override
public ItemCameraTransforms getItemCameraTransforms()
{
return this.baseModel.getItemCameraTransforms();
}
@Override
public ItemOverrideList getOverrides() {
return new ItemOverrideList() {
@Override
public IBakedModel getModelWithOverrides(IBakedModel originalModel, ItemStack stack, World world,
LivingEntity entity) {
String username = "";
if (stack.getItem() instanceof IBiometricCard) {
final GameProfile gp = ((IBiometricCard) stack.getItem()).getProfile(stack);
if (gp != null) {
if (gp.getId() != null) {
username = gp.getId().toString();
} else {
username = gp.getName();
}
}
}
final int hash = !username.isEmpty() ? username.hashCode() : 0;
@Override
public ItemOverrideList getOverrides()
{
return new ItemOverrideList()
{
@Override
public IBakedModel getModelWithOverrides( IBakedModel originalModel, ItemStack stack, World world, LivingEntity entity )
{
String username = "";
if( stack.getItem() instanceof IBiometricCard )
{
final GameProfile gp = ( (IBiometricCard) stack.getItem() ).getProfile( stack );
if( gp != null )
{
if( gp.getId() != null )
{
username = gp.getId().toString();
}
else
{
username = gp.getName();
}
}
}
final int hash = !username.isEmpty() ? username.hashCode() : 0;
// Get hash
if (hash == 0) {
return BiometricCardBakedModel.this;
}
// Get hash
if( hash == 0 )
{
return BiometricCardBakedModel.this;
}
try {
return BiometricCardBakedModel.this.modelCache.get(hash,
() -> new BiometricCardBakedModel(BiometricCardBakedModel.this.baseModel,
BiometricCardBakedModel.this.texture, hash,
BiometricCardBakedModel.this.modelCache));
} catch (ExecutionException e) {
AELog.error(e);
return BiometricCardBakedModel.this;
}
}
};
}
try
{
return BiometricCardBakedModel.this.modelCache.get( hash, () -> new BiometricCardBakedModel( BiometricCardBakedModel.this.baseModel, BiometricCardBakedModel.this.texture, hash, BiometricCardBakedModel.this.modelCache ) );
}
catch( ExecutionException e )
{
AELog.error( e );
return BiometricCardBakedModel.this;
}
}
};
}
@Override
public boolean doesHandlePerspectives() {
return true;
}
@Override
public boolean doesHandlePerspectives()
{
return true;
}
@Override
public IBakedModel handlePerspective( ItemCameraTransforms.TransformType cameraTransformType, MatrixStack mat )
{
baseModel.handlePerspective( cameraTransformType, mat );
return this;
}
@Override
public IBakedModel handlePerspective(ItemCameraTransforms.TransformType cameraTransformType, MatrixStack mat) {
baseModel.handlePerspective(cameraTransformType, mat);
return this;
}
}
@@ -1,10 +1,10 @@
package appeng.client.render.model;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.function.Function;
import javax.annotation.Nullable;
import com.mojang.datafixers.util.Pair;
@@ -13,37 +13,37 @@ import net.minecraft.client.renderer.model.*;
import net.minecraft.client.renderer.texture.AtlasTexture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.ResourceLocation;
import appeng.core.AppEng;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.geometry.IModelGeometry;
import appeng.core.AppEng;
/**
* Model wrapper for the biometric card item model, which combines a base card layer with a "visual hash" of the player
* name
* Model wrapper for the biometric card item model, which combines a base card
* layer with a "visual hash" of the player name
*/
public class BiometricCardModel implements IModelGeometry<BiometricCardModel>
{
public class BiometricCardModel implements IModelGeometry<BiometricCardModel> {
public static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "item/biometric_card_base" );
private static final Material TEXTURE = new Material( AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( AppEng.MOD_ID, "item/biometric_card_hash" ) );
public static final ResourceLocation MODEL_BASE = new ResourceLocation(AppEng.MOD_ID, "item/biometric_card_base");
private static final Material TEXTURE = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
new ResourceLocation(AppEng.MOD_ID, "item/biometric_card_hash"));
@Override
public Collection<Material> getTextures( IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors )
{
return Collections.singleton( TEXTURE );
}
@Override
public Collection<Material> getTextures(IModelConfiguration owner,
Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
return Collections.singleton(TEXTURE);
}
@Nullable
@Override
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform transformIn, ItemOverrideList overrides, ResourceLocation locationIn )
{
TextureAtlasSprite texture = spriteGetter.apply( TEXTURE );
@Nullable
@Override
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery,
Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform transformIn,
ItemOverrideList overrides, ResourceLocation locationIn) {
TextureAtlasSprite texture = spriteGetter.apply(TEXTURE);
IBakedModel baseModel = bakery.getBakedModel( MODEL_BASE, transformIn, spriteGetter );
IBakedModel baseModel = bakery.getBakedModel(MODEL_BASE, transformIn, spriteGetter);
return new BiometricCardBakedModel( baseModel, texture );
}
return new BiometricCardBakedModel(baseModel, texture);
}
}
@@ -1,10 +1,10 @@
package appeng.client.render.model;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Random;
import javax.annotation.Nullable;
import com.mojang.blaze3d.matrix.MatrixStack;
@@ -20,120 +20,100 @@ import net.minecraft.util.Direction;
import net.minecraftforge.client.model.PerspectiveMapWrapper;
import net.minecraftforge.client.model.data.EmptyModelData;
class ColorApplicatorBakedModel implements IBakedModel {
class ColorApplicatorBakedModel implements IBakedModel
{
private final IBakedModel baseModel;
private final IBakedModel baseModel;
private final IModelTransform transforms;
private final IModelTransform transforms;
private final EnumMap<Direction, List<BakedQuad>> quadsBySide;
private final EnumMap<Direction, List<BakedQuad>> quadsBySide;
private final List<BakedQuad> generalQuads;
private final List<BakedQuad> generalQuads;
ColorApplicatorBakedModel(IBakedModel baseModel, IModelTransform transforms, TextureAtlasSprite texDark,
TextureAtlasSprite texMedium, TextureAtlasSprite texBright) {
this.baseModel = baseModel;
this.transforms = transforms;
ColorApplicatorBakedModel( IBakedModel baseModel, IModelTransform transforms, TextureAtlasSprite texDark, TextureAtlasSprite texMedium, TextureAtlasSprite texBright )
{
this.baseModel = baseModel;
this.transforms = transforms;
// Put the tint indices in... Since this is an item model, we are ignoring rand
this.generalQuads = this.fixQuadTint(null, texDark, texMedium, texBright);
this.quadsBySide = new EnumMap<>(Direction.class);
for (Direction facing : Direction.values()) {
this.quadsBySide.put(facing, this.fixQuadTint(facing, texDark, texMedium, texBright));
}
}
// Put the tint indices in... Since this is an item model, we are ignoring rand
this.generalQuads = this.fixQuadTint( null, texDark, texMedium, texBright );
this.quadsBySide = new EnumMap<>( Direction.class );
for( Direction facing : Direction.values() )
{
this.quadsBySide.put( facing, this.fixQuadTint( facing, texDark, texMedium, texBright ) );
}
}
private List<BakedQuad> fixQuadTint(Direction facing, TextureAtlasSprite texDark, TextureAtlasSprite texMedium,
TextureAtlasSprite texBright) {
List<BakedQuad> quads = this.baseModel.getQuads(null, facing, new Random(0), EmptyModelData.INSTANCE);
List<BakedQuad> result = new ArrayList<>(quads.size());
for (BakedQuad quad : quads) {
int tint;
private List<BakedQuad> fixQuadTint( Direction facing, TextureAtlasSprite texDark, TextureAtlasSprite texMedium, TextureAtlasSprite texBright )
{
List<BakedQuad> quads = this.baseModel.getQuads( null, facing, new Random( 0 ), EmptyModelData.INSTANCE );
List<BakedQuad> result = new ArrayList<>( quads.size() );
for( BakedQuad quad : quads )
{
int tint;
if (quad.func_187508_a() == texDark) {
tint = 1;
} else if (quad.func_187508_a() == texMedium) {
tint = 2;
} else if (quad.func_187508_a() == texBright) {
tint = 3;
} else {
result.add(quad);
continue;
}
if( quad.func_187508_a() == texDark )
{
tint = 1;
}
else if( quad.func_187508_a() == texMedium )
{
tint = 2;
}
else if( quad.func_187508_a() == texBright )
{
tint = 3;
}
else
{
result.add( quad );
continue;
}
BakedQuad newQuad = new BakedQuad(quad.getVertexData(), tint, quad.getFace(), quad.func_187508_a(),
quad.shouldApplyDiffuseLighting());
result.add(newQuad);
}
BakedQuad newQuad = new BakedQuad( quad.getVertexData(), tint, quad.getFace(), quad.func_187508_a(), quad.shouldApplyDiffuseLighting() );
result.add( newQuad );
}
return result;
}
return result;
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
if (side == null) {
return this.generalQuads;
}
return this.quadsBySide.get(side);
}
@Override
public List<BakedQuad> getQuads( @Nullable BlockState state, @Nullable Direction side, Random rand )
{
if( side == null )
{
return this.generalQuads;
}
return this.quadsBySide.get( side );
}
@Override
public boolean isAmbientOcclusion() {
return this.baseModel.isAmbientOcclusion();
}
@Override
public boolean isAmbientOcclusion()
{
return this.baseModel.isAmbientOcclusion();
}
@Override
public boolean isGui3d() {
return this.baseModel.isGui3d();
}
@Override
public boolean isGui3d()
{
return this.baseModel.isGui3d();
}
@Override
public boolean func_230044_c_() {
return false;// TODO
}
@Override
public boolean func_230044_c_()
{
return false;//TODO
}
@Override
public boolean isBuiltInRenderer() {
return this.baseModel.isBuiltInRenderer();
}
@Override
public boolean isBuiltInRenderer()
{
return this.baseModel.isBuiltInRenderer();
}
@Override
public TextureAtlasSprite getParticleTexture() {
return this.baseModel.getParticleTexture();
}
@Override
public TextureAtlasSprite getParticleTexture()
{
return this.baseModel.getParticleTexture();
}
@Override
public ItemCameraTransforms getItemCameraTransforms() {
return this.baseModel.getItemCameraTransforms();
}
@Override
public ItemCameraTransforms getItemCameraTransforms()
{
return this.baseModel.getItemCameraTransforms();
}
@Override
public ItemOverrideList getOverrides() {
return this.baseModel.getOverrides();
}
@Override
public ItemOverrideList getOverrides()
{
return this.baseModel.getOverrides();
}
@Override
public IBakedModel handlePerspective( ItemCameraTransforms.TransformType cameraTransformType, MatrixStack mat )
{
return PerspectiveMapWrapper.handlePerspective( this, transforms, cameraTransformType, mat );
}
@Override
public IBakedModel handlePerspective(ItemCameraTransforms.TransformType cameraTransformType, MatrixStack mat) {
return PerspectiveMapWrapper.handlePerspective(this, transforms, cameraTransformType, mat);
}
}
@@ -1,11 +1,11 @@
package appeng.client.render.model;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.function.Function;
import javax.annotation.Nullable;
import com.mojang.datafixers.util.Pair;
@@ -16,37 +16,42 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import appeng.core.AppEng;
import net.minecraftforge.client.model.geometry.IModelGeometry;
import appeng.core.AppEng;
/**
* A color applicator uses the base model, and extends it with additional layers that are colored according to the
* selected color of the applicator.
* A color applicator uses the base model, and extends it with additional layers
* that are colored according to the selected color of the applicator.
*/
public class ColorApplicatorModel implements IModelGeometry<ColorApplicatorModel>
{
public class ColorApplicatorModel implements IModelGeometry<ColorApplicatorModel> {
private static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "item/color_applicator_colored" );
private static final ResourceLocation MODEL_BASE = new ResourceLocation(AppEng.MOD_ID,
"item/color_applicator_colored");
private static final Material TEXTURE_DARK = new Material( AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( AppEng.MOD_ID, "item/color_applicator_tip_dark" ) );
private static final Material TEXTURE_MEDIUM = new Material( AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( AppEng.MOD_ID, "item/color_applicator_tip_medium" ) );
private static final Material TEXTURE_BRIGHT = new Material( AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( AppEng.MOD_ID, "item/color_applicator_tip_bright" ) );
private static final Material TEXTURE_DARK = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
new ResourceLocation(AppEng.MOD_ID, "item/color_applicator_tip_dark"));
private static final Material TEXTURE_MEDIUM = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
new ResourceLocation(AppEng.MOD_ID, "item/color_applicator_tip_medium"));
private static final Material TEXTURE_BRIGHT = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
new ResourceLocation(AppEng.MOD_ID, "item/color_applicator_tip_bright"));
@Override
public Collection<Material> getTextures(IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
return Arrays.asList( TEXTURE_DARK, TEXTURE_MEDIUM, TEXTURE_DARK );
}
@Override
public Collection<Material> getTextures(IModelConfiguration owner,
Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
return Arrays.asList(TEXTURE_DARK, TEXTURE_MEDIUM, TEXTURE_DARK);
}
@Override
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation) {
IBakedModel baseModel = bakery.getBakedModel( MODEL_BASE, modelTransform, spriteGetter );
@Override
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery,
Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform,
ItemOverrideList overrides, ResourceLocation modelLocation) {
IBakedModel baseModel = bakery.getBakedModel(MODEL_BASE, modelTransform, spriteGetter);
TextureAtlasSprite texDark = spriteGetter.apply( TEXTURE_DARK );
TextureAtlasSprite texMedium = spriteGetter.apply( TEXTURE_MEDIUM );
TextureAtlasSprite texBright = spriteGetter.apply( TEXTURE_BRIGHT );
TextureAtlasSprite texDark = spriteGetter.apply(TEXTURE_DARK);
TextureAtlasSprite texMedium = spriteGetter.apply(TEXTURE_MEDIUM);
TextureAtlasSprite texBright = spriteGetter.apply(TEXTURE_BRIGHT);
return new ColorApplicatorBakedModel( baseModel, modelTransform, texDark, texMedium, texBright );
}
return new ColorApplicatorBakedModel(baseModel, modelTransform, texDark, texMedium, texBright);
}
}
@@ -18,12 +18,14 @@
package appeng.client.render.model;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import appeng.api.definitions.IItems;
import appeng.block.storage.DriveSlotCellType;
import appeng.block.storage.DriveSlotsState;
import appeng.client.render.DelegateBakedModel;
import appeng.core.Api;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.model.BakedQuad;
@@ -34,98 +36,92 @@ import net.minecraft.util.Direction;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import appeng.api.definitions.IItems;
import appeng.block.storage.DriveSlotCellType;
import appeng.block.storage.DriveSlotsState;
import appeng.client.render.DelegateBakedModel;
import appeng.core.Api;
public class DriveBakedModel extends DelegateBakedModel {
private final Map<DriveSlotCellType, IBakedModel> bakedCells;
public class DriveBakedModel extends DelegateBakedModel
{
private final Map<DriveSlotCellType, IBakedModel> bakedCells;
public DriveBakedModel(IBakedModel bakedBase, Map<DriveSlotCellType, IBakedModel> bakedCells) {
super(bakedBase);
this.bakedCells = bakedCells;
}
public DriveBakedModel( IBakedModel bakedBase, Map<DriveSlotCellType, IBakedModel> bakedCells )
{
super(bakedBase);
this.bakedCells = bakedCells;
}
@Nonnull
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand,
@Nonnull IModelData extraData) {
@Nonnull
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand, @Nonnull IModelData extraData) {
List<BakedQuad> result = new ArrayList<>(super.getQuads(state, side, rand, extraData));
List<BakedQuad> result = new ArrayList<>(super.getQuads(state, side, rand, extraData));
if (!(extraData instanceof DriveModelData)) {
return result;
}
DriveModelData driveModelData = (DriveModelData) extraData;
if (!(extraData instanceof DriveModelData)) {
return result;
}
DriveModelData driveModelData = (DriveModelData) extraData;
DriveSlotsState slotsState = driveModelData.getSlotsState();
DriveSlotsState slotsState = driveModelData.getSlotsState();
if (side == null && slotsState != null) {
for (int row = 0; row < 5; row++) {
for (int col = 0; col < 2; col++) {
Matrix4f transform = new Matrix4f();
if( side == null && slotsState != null )
{
for( int row = 0; row < 5; row++ )
{
for( int col = 0; col < 2; col++ )
{
Matrix4f transform = new Matrix4f();
// Position this drive model copy at the correct slot. The transform is based on
// the
// cell-model being in slot 0,0 at the top left of the drive.
float xOffset = -col * 7 / 16.0f;
float yOffset = -row * 3 / 16.0f;
transform.setTranslation(xOffset, yOffset, 0);
// Position this drive model copy at the correct slot. The transform is based on the
// cell-model being in slot 0,0 at the top left of the drive.
float xOffset = -col * 7 / 16.0f;
float yOffset = -row * 3 / 16.0f;
transform.setTranslation( xOffset, yOffset, 0 );
int slot = row * 2 + col;
int slot = row * 2 + col;
// Add the drive chassis
Item cell = slotsState.getCell(slot);
IBakedModel cellChassisModel = getCellChassisModel(cell);
addModel(state, rand, extraData, result, cellChassisModel, transform);
}
}
}
// Add the drive chassis
Item cell = slotsState.getCell(slot);
IBakedModel cellChassisModel = getCellChassisModel(cell);
addModel(state, rand, extraData, result, cellChassisModel, transform);
}
}
}
return result;
}
return result;
}
@Override
public boolean isAmbientOcclusion() {
// We have faces inside the chassis that are facing east, but should not receive
// ambient occlusion from the east-side, but sadly this cannot be fine-tuned on
// a
// face-by-face basis.
return false;
}
@Override
public boolean isAmbientOcclusion() {
// We have faces inside the chassis that are facing east, but should not receive
// ambient occlusion from the east-side, but sadly this cannot be fine-tuned on a
// face-by-face basis.
return false;
}
// Determine which drive chassis to show based on the used cell
private IBakedModel getCellChassisModel(Item cell) {
IItems items = Api.INSTANCE.definitions().items();
if (cell == null) {
return bakedCells.get(DriveSlotCellType.EMPTY);
} else if (items.fluidCell1k().item() == cell || items.fluidCell4k().item() == cell
|| items.fluidCell16k().item() == cell || items.fluidCell64k().item() == cell) {
return bakedCells.get(DriveSlotCellType.FLUID);
} else {
// Fall back to an item model
return bakedCells.get(DriveSlotCellType.ITEM);
}
}
// Determine which drive chassis to show based on the used cell
private IBakedModel getCellChassisModel(Item cell) {
IItems items = Api.INSTANCE.definitions().items();
if (cell == null) {
return bakedCells.get(DriveSlotCellType.EMPTY);
} else if (items.fluidCell1k().item() == cell
|| items.fluidCell4k().item() == cell
|| items.fluidCell16k().item() == cell
|| items.fluidCell64k().item() == cell) {
return bakedCells.get(DriveSlotCellType.FLUID);
} else {
// Fall back to an item model
return bakedCells.get(DriveSlotCellType.ITEM);
}
}
private static void addModel(@Nullable BlockState state, @Nonnull Random rand, @Nonnull IModelData extraData, List<BakedQuad> result, IBakedModel bakedCell, Matrix4f transform) {
MatrixVertexTransformer transformer = new MatrixVertexTransformer( transform );
for( BakedQuad bakedQuad : bakedCell.getQuads( state, null, rand, extraData ) )
{
BakedQuadBuilder builder = new BakedQuadBuilder();
transformer.setParent( builder );
transformer.setVertexFormat( builder.getVertexFormat() );
bakedQuad.pipe( transformer );
result.add( builder.build() );
}
}
private static void addModel(@Nullable BlockState state, @Nonnull Random rand, @Nonnull IModelData extraData,
List<BakedQuad> result, IBakedModel bakedCell, Matrix4f transform) {
MatrixVertexTransformer transformer = new MatrixVertexTransformer(transform);
for (BakedQuad bakedQuad : bakedCell.getQuads(state, null, rand, extraData)) {
BakedQuadBuilder builder = new BakedQuadBuilder();
transformer.setParent(builder);
transformer.setVertexFormat(builder.getVertexFormat());
bakedQuad.pipe(transformer);
result.add(builder.build());
}
}
}
@@ -18,56 +18,56 @@
package appeng.client.render.model;
import java.util.*;
import java.util.function.Function;
import appeng.block.storage.DriveSlotCellType;
import appeng.block.storage.DriveSlotState;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.model.*;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.geometry.IModelGeometry;
import java.util.*;
import java.util.function.Function;
import appeng.block.storage.DriveSlotCellType;
import appeng.block.storage.DriveSlotState;
public class DriveModel implements IModelGeometry<DriveModel>
{
public class DriveModel implements IModelGeometry<DriveModel> {
private static final ResourceLocation MODEL_BASE = new ResourceLocation( "appliedenergistics2:block/drive/drive_base" );
private static final ResourceLocation MODEL_BASE = new ResourceLocation(
"appliedenergistics2:block/drive/drive_base");
private static final Map<DriveSlotCellType, ResourceLocation> MODELS_CELLS = ImmutableMap.of(
DriveSlotCellType.EMPTY, new ResourceLocation( "appliedenergistics2:block/drive/drive_cell_empty" ),
DriveSlotCellType.ITEM, new ResourceLocation( "appliedenergistics2:block/drive/drive_cell_items" ),
DriveSlotCellType.FLUID, new ResourceLocation( "appliedenergistics2:block/drive/drive_cell_fluids" )
);
private static final Map<DriveSlotCellType, ResourceLocation> MODELS_CELLS = ImmutableMap.of(
DriveSlotCellType.EMPTY, new ResourceLocation("appliedenergistics2:block/drive/drive_cell_empty"),
DriveSlotCellType.ITEM, new ResourceLocation("appliedenergistics2:block/drive/drive_cell_items"),
DriveSlotCellType.FLUID, new ResourceLocation("appliedenergistics2:block/drive/drive_cell_fluids"));
public static final Set<ResourceLocation> DEPENDENCIES = ImmutableSet.<ResourceLocation>builder()
.addAll(MODELS_CELLS.values())
.add(MODEL_BASE)
.build();
public static final Set<ResourceLocation> DEPENDENCIES = ImmutableSet.<ResourceLocation>builder()
.addAll(MODELS_CELLS.values()).add(MODEL_BASE).build();
@Override
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation) {
EnumMap<DriveSlotCellType, IBakedModel> cellModels = new EnumMap<>( DriveSlotCellType.class );
@Override
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery,
Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform,
ItemOverrideList overrides, ResourceLocation modelLocation) {
EnumMap<DriveSlotCellType, IBakedModel> cellModels = new EnumMap<>(DriveSlotCellType.class);
// Load the base model and the model for each cell state.
for( DriveSlotCellType cellType : MODELS_CELLS.keySet() )
{
IBakedModel cellModel = bakery.getBakedModel( MODELS_CELLS.get( cellType ), modelTransform, spriteGetter );
cellModels.put( cellType, cellModel );
}
// Load the base model and the model for each cell state.
for (DriveSlotCellType cellType : MODELS_CELLS.keySet()) {
IBakedModel cellModel = bakery.getBakedModel(MODELS_CELLS.get(cellType), modelTransform, spriteGetter);
cellModels.put(cellType, cellModel);
}
IBakedModel baseModel = bakery.getBakedModel( MODEL_BASE, modelTransform, spriteGetter );
return new DriveBakedModel( baseModel, cellModels );
}
IBakedModel baseModel = bakery.getBakedModel(MODEL_BASE, modelTransform, spriteGetter);
return new DriveBakedModel(baseModel, cellModels);
}
@Override
public Collection<Material> getTextures(IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
return Collections.emptyList();
}
@Override
public Collection<Material> getTextures(IModelConfiguration owner,
Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
return Collections.emptyList();
}
}
@@ -1,13 +1,16 @@
package appeng.client.render.model;
import appeng.block.storage.DriveSlotsState;
import java.util.Objects;
import javax.annotation.Nullable;
import com.google.common.base.Preconditions;
import net.minecraft.util.Direction;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.data.ModelProperty;
import javax.annotation.Nullable;
import java.util.Objects;
import appeng.block.storage.DriveSlotsState;
public class DriveModelData extends AEModelData {
@@ -29,9 +32,12 @@ public class DriveModelData extends AEModelData {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
if (!super.equals(o))
return false;
DriveModelData that = (DriveModelData) o;
return slotsState.equals(that.slotsState);
}
@@ -18,7 +18,6 @@
package appeng.client.render.model;
import java.util.*;
import java.util.function.Function;
import java.util.stream.IntStream;
@@ -41,9 +40,6 @@ import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import appeng.decorative.solid.BlockQuartzGlass;
import appeng.decorative.solid.GlassState;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.ILightReader;
import net.minecraftforge.client.model.data.IDynamicBakedModel;
@@ -52,304 +48,277 @@ import net.minecraftforge.client.model.data.ModelDataMap;
import net.minecraftforge.client.model.data.ModelProperty;
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
import appeng.decorative.solid.BlockQuartzGlass;
import appeng.decorative.solid.GlassState;
class GlassBakedModel implements IDynamicBakedModel
{
class GlassBakedModel implements IDynamicBakedModel {
// This unlisted property is used to determine the actual block that should be rendered
public static final ModelProperty<GlassState> GLASS_STATE = new ModelProperty<>();
// This unlisted property is used to determine the actual block that should be
// rendered
public static final ModelProperty<GlassState> GLASS_STATE = new ModelProperty<>();
private static final byte[][][] OFFSETS = generateOffsets();
private static final byte[][][] OFFSETS = generateOffsets();
// Alternating textures based on position
static final Material TEXTURE_A = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( "appliedenergistics2:block/glass/quartz_glass_a" ));
static final Material TEXTURE_B = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( "appliedenergistics2:block/glass/quartz_glass_b" ));
static final Material TEXTURE_C = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( "appliedenergistics2:block/glass/quartz_glass_c" ));
static final Material TEXTURE_D = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( "appliedenergistics2:block/glass/quartz_glass_d" ));
// Alternating textures based on position
static final Material TEXTURE_A = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
new ResourceLocation("appliedenergistics2:block/glass/quartz_glass_a"));
static final Material TEXTURE_B = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
new ResourceLocation("appliedenergistics2:block/glass/quartz_glass_b"));
static final Material TEXTURE_C = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
new ResourceLocation("appliedenergistics2:block/glass/quartz_glass_c"));
static final Material TEXTURE_D = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
new ResourceLocation("appliedenergistics2:block/glass/quartz_glass_d"));
// Frame texture
static final Material[] TEXTURES_FRAME = generateTexturesFrame();
// Frame texture
static final Material[] TEXTURES_FRAME = generateTexturesFrame();
// Generates the required textures for the frame
private static Material[] generateTexturesFrame()
{
return IntStream.range( 1, 16 )
.mapToObj( Integer::toBinaryString )
.map( s -> Strings.padStart( s, 4, '0' ) )
.map( s -> new ResourceLocation( "appliedenergistics2:block/glass/quartz_glass_frame" + s ) )
.map( rl -> new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE, rl) )
.toArray( Material[]::new );
}
// Generates the required textures for the frame
private static Material[] generateTexturesFrame() {
return IntStream.range(1, 16).mapToObj(Integer::toBinaryString).map(s -> Strings.padStart(s, 4, '0'))
.map(s -> new ResourceLocation("appliedenergistics2:block/glass/quartz_glass_frame" + s))
.map(rl -> new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE, rl)).toArray(Material[]::new);
}
private final TextureAtlasSprite[] glassTextures;
private final TextureAtlasSprite[] glassTextures;
private final TextureAtlasSprite[] frameTextures;
private final TextureAtlasSprite[] frameTextures;
public GlassBakedModel( Function<Material, TextureAtlasSprite> bakedTextureGetter )
{
this.glassTextures = new TextureAtlasSprite[] {
bakedTextureGetter.apply( TEXTURE_A ),
bakedTextureGetter.apply( TEXTURE_B ),
bakedTextureGetter.apply( TEXTURE_C ),
bakedTextureGetter.apply( TEXTURE_D )
};
public GlassBakedModel(Function<Material, TextureAtlasSprite> bakedTextureGetter) {
this.glassTextures = new TextureAtlasSprite[] { bakedTextureGetter.apply(TEXTURE_A),
bakedTextureGetter.apply(TEXTURE_B), bakedTextureGetter.apply(TEXTURE_C),
bakedTextureGetter.apply(TEXTURE_D) };
// The first frame texture would be empty, so we simply leave it set to null here
this.frameTextures = new TextureAtlasSprite[16];
for( int i = 0; i < TEXTURES_FRAME.length; i++ )
{
this.frameTextures[1 + i] = bakedTextureGetter.apply( TEXTURES_FRAME[i] );
}
}
// The first frame texture would be empty, so we simply leave it set to null
// here
this.frameTextures = new TextureAtlasSprite[16];
for (int i = 0; i < TEXTURES_FRAME.length; i++) {
this.frameTextures[1 + i] = bakedTextureGetter.apply(TEXTURES_FRAME[i]);
}
}
@Override
public List<BakedQuad> getQuads( @Nullable BlockState state, @Nullable Direction side, Random rand, IModelData extraData )
{
if( side == null )
{
return Collections.emptyList();
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand,
IModelData extraData) {
if (side == null) {
return Collections.emptyList();
}
final GlassState glassState = extraData.getData( GLASS_STATE );
final GlassState glassState = extraData.getData(GLASS_STATE);
if( glassState == null )
{
return Collections.emptyList();
}
if (glassState == null) {
return Collections.emptyList();
}
// TODO: This could just use the Random instance we're given...
final int cx = Math.abs( glassState.getX() % 10 );
final int cy = Math.abs( glassState.getY() % 10 );
final int cz = Math.abs( glassState.getZ() % 10 );
// TODO: This could just use the Random instance we're given...
final int cx = Math.abs(glassState.getX() % 10);
final int cy = Math.abs(glassState.getY() % 10);
final int cz = Math.abs(glassState.getZ() % 10);
int u = OFFSETS[cx][cy][cz] % 4;
int v = OFFSETS[9 - cx][9 - cy][9 - cz] % 4;
int u = OFFSETS[cx][cy][cz] % 4;
int v = OFFSETS[9 - cx][9 - cy][9 - cz] % 4;
int texIdx = Math.abs( ( OFFSETS[cx][cy][cz] + ( glassState.getX() + glassState.getY() + glassState.getZ() ) ) % 4 );
int texIdx = Math.abs((OFFSETS[cx][cy][cz] + (glassState.getX() + glassState.getY() + glassState.getZ())) % 4);
if( texIdx < 2 )
{
u /= 2;
v /= 2;
}
if (texIdx < 2) {
u /= 2;
v /= 2;
}
final TextureAtlasSprite glassTexture = this.glassTextures[texIdx];
final TextureAtlasSprite glassTexture = this.glassTextures[texIdx];
// Render the glass side
final List<BakedQuad> quads = new ArrayList<>( 5 ); // At most 5
// Render the glass side
final List<BakedQuad> quads = new ArrayList<>(5); // At most 5
final List<Vec3d> corners = RenderHelper.getFaceCorners( side );
quads.add( this.createQuad( side, corners, glassTexture, u, v ) );
final List<Vec3d> corners = RenderHelper.getFaceCorners(side);
quads.add(this.createQuad(side, corners, glassTexture, u, v));
/*
* This needs some explanation:
* The bit-field contains 4-bits, one for each direction that a frame may be drawn.
* Converted to a number, the bit-field is then used as an index into the list of
* frame textures, which have been created in such a way that their filenames
* indicate, in which directions they contain borders.
* i.e. bitmask = 0101 means a border should be drawn up and down (in terms of u,v space).
* Converted to a number, this bitmask is 5. So the texture at index 5 is used.
* That texture had "0101" in its filename to indicate this.
*/
final int edgeBitmask = makeBitmask( glassState, side );
final TextureAtlasSprite sideSprite = this.frameTextures[edgeBitmask];
/*
* This needs some explanation: The bit-field contains 4-bits, one for each
* direction that a frame may be drawn. Converted to a number, the bit-field is
* then used as an index into the list of frame textures, which have been
* created in such a way that their filenames indicate, in which directions they
* contain borders. i.e. bitmask = 0101 means a border should be drawn up and
* down (in terms of u,v space). Converted to a number, this bitmask is 5. So
* the texture at index 5 is used. That texture had "0101" in its filename to
* indicate this.
*/
final int edgeBitmask = makeBitmask(glassState, side);
final TextureAtlasSprite sideSprite = this.frameTextures[edgeBitmask];
if( sideSprite != null )
{
quads.add( this.createQuad( side, corners, sideSprite, 0, 0 ) );
}
if (sideSprite != null) {
quads.add(this.createQuad(side, corners, sideSprite, 0, 0));
}
return quads;
}
return quads;
}
@Override
public boolean func_230044_c_()
{
// TODO: Forge: Auto-generated method stub
return false;
}
@Override
public boolean func_230044_c_() {
// TODO: Forge: Auto-generated method stub
return false;
}
/**
* Creates the bitmask that indicates, in which directions (in terms of u,v space) a border should be drawn.
*/
private static int makeBitmask( GlassState state, Direction side )
{
switch( side )
{
case DOWN:
return makeBitmask( state, Direction.SOUTH, Direction.EAST, Direction.NORTH, Direction.WEST );
case UP:
return makeBitmask( state, Direction.SOUTH, Direction.WEST, Direction.NORTH, Direction.EAST );
case NORTH:
return makeBitmask( state, Direction.UP, Direction.WEST, Direction.DOWN, Direction.EAST );
case SOUTH:
return makeBitmask( state, Direction.UP, Direction.EAST, Direction.DOWN, Direction.WEST );
case WEST:
return makeBitmask( state, Direction.UP, Direction.SOUTH, Direction.DOWN, Direction.NORTH );
case EAST:
return makeBitmask( state, Direction.UP, Direction.NORTH, Direction.DOWN, Direction.SOUTH );
default:
throw new IllegalArgumentException( "Unsupported side!" );
}
}
/**
* Creates the bitmask that indicates, in which directions (in terms of u,v
* space) a border should be drawn.
*/
private static int makeBitmask(GlassState state, Direction side) {
switch (side) {
case DOWN:
return makeBitmask(state, Direction.SOUTH, Direction.EAST, Direction.NORTH, Direction.WEST);
case UP:
return makeBitmask(state, Direction.SOUTH, Direction.WEST, Direction.NORTH, Direction.EAST);
case NORTH:
return makeBitmask(state, Direction.UP, Direction.WEST, Direction.DOWN, Direction.EAST);
case SOUTH:
return makeBitmask(state, Direction.UP, Direction.EAST, Direction.DOWN, Direction.WEST);
case WEST:
return makeBitmask(state, Direction.UP, Direction.SOUTH, Direction.DOWN, Direction.NORTH);
case EAST:
return makeBitmask(state, Direction.UP, Direction.NORTH, Direction.DOWN, Direction.SOUTH);
default:
throw new IllegalArgumentException("Unsupported side!");
}
}
private static int makeBitmask( GlassState state, Direction up, Direction right, Direction down, Direction left )
{
private static int makeBitmask(GlassState state, Direction up, Direction right, Direction down, Direction left) {
int bitmask = 0;
int bitmask = 0;
if( !state.isFlushWith( up ) )
{
bitmask |= 1;
}
if( !state.isFlushWith( right ) )
{
bitmask |= 2;
}
if( !state.isFlushWith( down ) )
{
bitmask |= 4;
}
if( !state.isFlushWith( left ) )
{
bitmask |= 8;
}
return bitmask;
}
if (!state.isFlushWith(up)) {
bitmask |= 1;
}
if (!state.isFlushWith(right)) {
bitmask |= 2;
}
if (!state.isFlushWith(down)) {
bitmask |= 4;
}
if (!state.isFlushWith(left)) {
bitmask |= 8;
}
return bitmask;
}
private BakedQuad createQuad( Direction side, List<Vec3d> corners, TextureAtlasSprite sprite, float uOffset, float vOffset )
{
return this.createQuad( side, corners.get( 0 ), corners.get( 1 ), corners.get( 2 ), corners.get( 3 ), sprite, uOffset, vOffset );
}
private BakedQuad createQuad(Direction side, List<Vec3d> corners, TextureAtlasSprite sprite, float uOffset,
float vOffset) {
return this.createQuad(side, corners.get(0), corners.get(1), corners.get(2), corners.get(3), sprite, uOffset,
vOffset);
}
private BakedQuad createQuad( Direction side, Vec3d c1, Vec3d c2, Vec3d c3, Vec3d c4, TextureAtlasSprite sprite, float uOffset, float vOffset )
{
Vec3d normal = new Vec3d( side.getDirectionVec() );
private BakedQuad createQuad(Direction side, Vec3d c1, Vec3d c2, Vec3d c3, Vec3d c4, TextureAtlasSprite sprite,
float uOffset, float vOffset) {
Vec3d normal = new Vec3d(side.getDirectionVec());
// Apply the u,v shift.
// This mirrors the logic from OffsetIcon from 1.7
float u1 = MathHelper.clamp( 0 - uOffset, 0, 16 );
float u2 = MathHelper.clamp( 16 - uOffset, 0, 16 );
float v1 = MathHelper.clamp( 0 - vOffset, 0, 16 );
float v2 = MathHelper.clamp( 16 - vOffset, 0, 16 );
// Apply the u,v shift.
// This mirrors the logic from OffsetIcon from 1.7
float u1 = MathHelper.clamp(0 - uOffset, 0, 16);
float u2 = MathHelper.clamp(16 - uOffset, 0, 16);
float v1 = MathHelper.clamp(0 - vOffset, 0, 16);
float v2 = MathHelper.clamp(16 - vOffset, 0, 16);
BakedQuadBuilder builder = new BakedQuadBuilder(sprite);
builder.setQuadOrientation(side);
this.putVertex( builder, normal, c1.x, c1.y, c1.z, sprite, u1, v1 );
this.putVertex( builder, normal, c2.x, c2.y, c2.z, sprite, u1, v2 );
this.putVertex( builder, normal, c3.x, c3.y, c3.z, sprite, u2, v2 );
this.putVertex( builder, normal, c4.x, c4.y, c4.z, sprite, u2, v1 );
return builder.build();
}
BakedQuadBuilder builder = new BakedQuadBuilder(sprite);
builder.setQuadOrientation(side);
this.putVertex(builder, normal, c1.x, c1.y, c1.z, sprite, u1, v1);
this.putVertex(builder, normal, c2.x, c2.y, c2.z, sprite, u1, v2);
this.putVertex(builder, normal, c3.x, c3.y, c3.z, sprite, u2, v2);
this.putVertex(builder, normal, c4.x, c4.y, c4.z, sprite, u2, v1);
return builder.build();
}
/*
* This method is as complicated as it is, because the order in which we push data into the vertexbuffer actually
* has to be precisely the order
* in which the vertex elements had been declared in the vertex format.
*/
private void putVertex( BakedQuadBuilder builder, Vec3d normal, double x, double y, double z, TextureAtlasSprite sprite, float u, float v )
{
VertexFormat vertexFormat = builder.getVertexFormat();
for( int e = 0; e < vertexFormat.getElements().size(); e++ )
{
VertexFormatElement el = vertexFormat.getElements().get(e);
switch( el.getUsage() )
{
case POSITION:
builder.put( e, (float) x, (float) y, (float) z, 1.0f );
break;
case COLOR:
builder.put( e, 1.0f, 1.0f, 1.0f, 1.0f );
break;
case NORMAL:
builder.put( e, (float) normal.x, (float) normal.y, (float) normal.z, 0f );
break;
case UV:
if( el.getIndex() == 0 )
{
u = sprite.getInterpolatedU( u );
v = sprite.getInterpolatedV( v );
builder.put( e, u, v, 0f, 1f );
break;
}
// Important: Fall through for getIndex() != 0
default:
builder.put( e );
break;
}
}
}
/*
* This method is as complicated as it is, because the order in which we push
* data into the vertexbuffer actually has to be precisely the order in which
* the vertex elements had been declared in the vertex format.
*/
private void putVertex(BakedQuadBuilder builder, Vec3d normal, double x, double y, double z,
TextureAtlasSprite sprite, float u, float v) {
VertexFormat vertexFormat = builder.getVertexFormat();
for (int e = 0; e < vertexFormat.getElements().size(); e++) {
VertexFormatElement el = vertexFormat.getElements().get(e);
switch (el.getUsage()) {
case POSITION:
builder.put(e, (float) x, (float) y, (float) z, 1.0f);
break;
case COLOR:
builder.put(e, 1.0f, 1.0f, 1.0f, 1.0f);
break;
case NORMAL:
builder.put(e, (float) normal.x, (float) normal.y, (float) normal.z, 0f);
break;
case UV:
if (el.getIndex() == 0) {
u = sprite.getInterpolatedU(u);
v = sprite.getInterpolatedV(v);
builder.put(e, u, v, 0f, 1f);
break;
}
// Important: Fall through for getIndex() != 0
default:
builder.put(e);
break;
}
}
}
@Override
public ItemOverrideList getOverrides()
{
return ItemOverrideList.EMPTY;
}
@Override
public ItemOverrideList getOverrides() {
return ItemOverrideList.EMPTY;
}
@Override
public boolean isAmbientOcclusion()
{
return false;
}
@Override
public boolean isAmbientOcclusion() {
return false;
}
@Override
public boolean isGui3d()
{
return false;
}
@Override
public boolean isGui3d() {
return false;
}
@Override
public boolean isBuiltInRenderer()
{
return false;
}
@Override
public boolean isBuiltInRenderer() {
return false;
}
@Override
public TextureAtlasSprite getParticleTexture()
{
return this.frameTextures[this.frameTextures.length - 1];
}
@Override
public TextureAtlasSprite getParticleTexture() {
return this.frameTextures[this.frameTextures.length - 1];
}
private static byte[][][] generateOffsets()
{
final Random r = new Random( 924 );
final byte[][][] offset = new byte[10][10][10];
private static byte[][][] generateOffsets() {
final Random r = new Random(924);
final byte[][][] offset = new byte[10][10][10];
for( int x = 0; x < 10; x++ )
{
for( int y = 0; y < 10; y++ )
{
r.nextBytes( offset[x][y] );
}
}
for (int x = 0; x < 10; x++) {
for (int y = 0; y < 10; y++) {
r.nextBytes(offset[x][y]);
}
}
return offset;
}
return offset;
}
@Nonnull
@Override
public IModelData getModelData(@Nonnull ILightReader world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nonnull IModelData tileData) {
@Nonnull
@Override
public IModelData getModelData(@Nonnull ILightReader world, @Nonnull BlockPos pos, @Nonnull BlockState state,
@Nonnull IModelData tileData) {
EnumSet<Direction> flushWith = EnumSet.noneOf( Direction.class );
// Test every direction for another glass block
for( Direction facing : Direction.values() )
{
if( isGlassBlock( world, pos, facing ) )
{
flushWith.add( facing );
}
}
EnumSet<Direction> flushWith = EnumSet.noneOf(Direction.class);
// Test every direction for another glass block
for (Direction facing : Direction.values()) {
if (isGlassBlock(world, pos, facing)) {
flushWith.add(facing);
}
}
GlassState glassState = new GlassState( pos.getX(), pos.getY(), pos.getZ(), flushWith );
return new ModelDataMap.Builder()
.withInitial(GLASS_STATE, glassState)
.build();
GlassState glassState = new GlassState(pos.getX(), pos.getY(), pos.getZ(), flushWith);
return new ModelDataMap.Builder().withInitial(GLASS_STATE, glassState).build();
}
}
private static boolean isGlassBlock(IBlockReader world, BlockPos pos, Direction facing )
{
return world.getBlockState( pos.offset( facing ) ).getBlock() instanceof BlockQuartzGlass;
}
private static boolean isGlassBlock(IBlockReader world, BlockPos pos, Direction facing) {
return world.getBlockState(pos.offset(facing)).getBlock() instanceof BlockQuartzGlass;
}
}
@@ -18,41 +18,42 @@
package appeng.client.render.model;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.function.Function;
import com.google.common.collect.ImmutableSet;
import javax.annotation.Nullable;
import com.google.common.collect.ImmutableSet;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.model.*;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.geometry.IModelGeometry;
import javax.annotation.Nullable;
/**
* Model class for the connected texture glass model.
*/
public class GlassModel implements IModelGeometry<GlassModel>
{
public class GlassModel implements IModelGeometry<GlassModel> {
@Override
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation) {
return new GlassBakedModel( spriteGetter );
}
@Override
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery,
Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform,
ItemOverrideList overrides, ResourceLocation modelLocation) {
return new GlassBakedModel(spriteGetter);
}
@Override
public Collection<Material> getTextures(IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
return ImmutableSet.<Material>builder()
.add(GlassBakedModel.TEXTURE_A, GlassBakedModel.TEXTURE_B, GlassBakedModel.TEXTURE_C, GlassBakedModel.TEXTURE_D)
.add(GlassBakedModel.TEXTURES_FRAME)
.build();
}
@Override
public Collection<Material> getTextures(IModelConfiguration owner,
Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
return ImmutableSet
.<Material>builder().add(GlassBakedModel.TEXTURE_A, GlassBakedModel.TEXTURE_B,
GlassBakedModel.TEXTURE_C, GlassBakedModel.TEXTURE_D)
.add(GlassBakedModel.TEXTURES_FRAME).build();
}
}
@@ -18,6 +18,7 @@
package appeng.client.render.model;
import java.util.List;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.Vector4f;
@@ -27,147 +28,107 @@ import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.util.Direction;
import net.minecraftforge.client.model.pipeline.QuadGatheringTransformer;
import java.util.List;
/**
* Applies an arbitrary transformation matrix to the vertices of a quad.
*/
final class MatrixVertexTransformer extends QuadGatheringTransformer
{
final class MatrixVertexTransformer extends QuadGatheringTransformer {
private final Matrix4f transform;
private final Matrix4f transform;
public MatrixVertexTransformer( Matrix4f transform )
{
this.transform = transform;
}
public MatrixVertexTransformer(Matrix4f transform) {
this.transform = transform;
}
@Override
protected void processQuad()
{
VertexFormat format = this.parent.getVertexFormat();
List<VertexFormatElement> elements = format.getElements();
int count = elements.size();
@Override
protected void processQuad() {
VertexFormat format = this.parent.getVertexFormat();
List<VertexFormatElement> elements = format.getElements();
int count = elements.size();
for( int v = 0; v < 4; v++ )
{
for( int e = 0; e < count; e++ )
{
VertexFormatElement element = elements.get( e );
if( element.getUsage() == VertexFormatElement.Usage.POSITION )
{
this.parent.put( e, this.transform( this.quadData[e][v], element.getElementCount() ) );
}
else if( element.getUsage() == VertexFormatElement.Usage.NORMAL )
{
this.parent.put( e, this.transformNormal( this.quadData[e][v] ) );
}
else
{
this.parent.put( e, this.quadData[e][v] );
}
}
}
}
for (int v = 0; v < 4; v++) {
for (int e = 0; e < count; e++) {
VertexFormatElement element = elements.get(e);
if (element.getUsage() == VertexFormatElement.Usage.POSITION) {
this.parent.put(e, this.transform(this.quadData[e][v], element.getElementCount()));
} else if (element.getUsage() == VertexFormatElement.Usage.NORMAL) {
this.parent.put(e, this.transformNormal(this.quadData[e][v]));
} else {
this.parent.put(e, this.quadData[e][v]);
}
}
}
}
@Override
public void setQuadTint( int tint )
{
this.parent.setQuadTint( tint );
}
@Override
public void setQuadTint(int tint) {
this.parent.setQuadTint(tint);
}
@Override
public void setQuadOrientation( Direction orientation )
{
this.parent.setQuadOrientation( orientation );
}
@Override
public void setQuadOrientation(Direction orientation) {
this.parent.setQuadOrientation(orientation);
}
@Override
public void setApplyDiffuseLighting( boolean diffuse )
{
this.parent.setApplyDiffuseLighting( diffuse );
}
@Override
public void setApplyDiffuseLighting(boolean diffuse) {
this.parent.setApplyDiffuseLighting(diffuse);
}
@Override
public void setTexture( TextureAtlasSprite texture )
{
this.parent.setTexture( texture );
}
@Override
public void setTexture(TextureAtlasSprite texture) {
this.parent.setTexture(texture);
}
private float[] transform( float[] fs, int elemCount )
{
switch( fs.length )
{
case 3:
Vector4f vec = new Vector4f( fs[0], fs[1], fs[2], 1 );
vec.setX(vec.getX() - 0.5f);
vec.setY(vec.getY() - 0.5f);
vec.setZ(vec.getZ() - 0.5f);
vec.transform(this.transform); // FIXME: Check this, we're using a Vec4, input is Vec3
vec.setX(vec.getX() + 0.5f);
vec.setY(vec.getY() + 0.5f);
vec.setZ(vec.getZ() + 0.5f);
return new float[] {
vec.getX(),
vec.getY(),
vec.getZ()
};
case 4:
Vector4f vecc = new Vector4f( fs[0], fs[1], fs[2], fs[3] );
// Otherwise all translation is lost
if( elemCount == 3 )
{
vecc.setW(1);
}
vecc.setX(vecc.getX() - 0.5f);
vecc.setY(vecc.getY() - 0.5f);
vecc.setZ(vecc.getZ() - 0.5f);
vecc.transform(this.transform);
vecc.setX(vecc.getX() + 0.5f);
vecc.setY(vecc.getY() + 0.5f);
vecc.setZ(vecc.getZ() + 0.5f);
return new float[] {
vecc.getX(),
vecc.getY(),
vecc.getZ(),
vecc.getW()
};
private float[] transform(float[] fs, int elemCount) {
switch (fs.length) {
case 3:
Vector4f vec = new Vector4f(fs[0], fs[1], fs[2], 1);
vec.setX(vec.getX() - 0.5f);
vec.setY(vec.getY() - 0.5f);
vec.setZ(vec.getZ() - 0.5f);
vec.transform(this.transform); // FIXME: Check this, we're using a Vec4, input is Vec3
vec.setX(vec.getX() + 0.5f);
vec.setY(vec.getY() + 0.5f);
vec.setZ(vec.getZ() + 0.5f);
return new float[] { vec.getX(), vec.getY(), vec.getZ() };
case 4:
Vector4f vecc = new Vector4f(fs[0], fs[1], fs[2], fs[3]);
// Otherwise all translation is lost
if (elemCount == 3) {
vecc.setW(1);
}
vecc.setX(vecc.getX() - 0.5f);
vecc.setY(vecc.getY() - 0.5f);
vecc.setZ(vecc.getZ() - 0.5f);
vecc.transform(this.transform);
vecc.setX(vecc.getX() + 0.5f);
vecc.setY(vecc.getY() + 0.5f);
vecc.setZ(vecc.getZ() + 0.5f);
return new float[] { vecc.getX(), vecc.getY(), vecc.getZ(), vecc.getW() };
default:
return fs;
}
}
default:
return fs;
}
}
private float[] transformNormal( float[] fs )
{
Vector4f normal;
private float[] transformNormal(float[] fs) {
Vector4f normal;
switch( fs.length )
{
case 3:
normal = new Vector4f( fs[0], fs[1], fs[2], 0 );
normal.transform(this.transform);
normal.normalize();
return new float[] {
normal.getX(),
normal.getY(),
normal.getZ()
};
switch (fs.length) {
case 3:
normal = new Vector4f(fs[0], fs[1], fs[2], 0);
normal.transform(this.transform);
normal.normalize();
return new float[] { normal.getX(), normal.getY(), normal.getZ() };
case 4:
normal = new Vector4f( fs[0], fs[1], fs[2], fs[3] );
normal.transform(this.transform);
normal.normalize();
return new float[] {
normal.getX(),
normal.getY(),
normal.getZ(),
normal.getW()
};
case 4:
normal = new Vector4f(fs[0], fs[1], fs[2], fs[3]);
normal.transform(this.transform);
normal.normalize();
return new float[] { normal.getX(), normal.getY(), normal.getZ(), normal.getW() };
default:
return fs;
}
}
default:
return fs;
}
}
}
@@ -1,12 +1,12 @@
package appeng.client.render.model;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import javax.annotation.Nullable;
import com.google.common.cache.Cache;
@@ -34,187 +34,159 @@ import appeng.api.util.AEColor;
import appeng.client.render.cablebus.CubeBuilder;
import appeng.core.AELog;
class MemoryCardBakedModel implements IBakedModel {
private static final AEColor[] DEFAULT_COLOR_CODE = new AEColor[] { AEColor.TRANSPARENT, AEColor.TRANSPARENT,
AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT,
AEColor.TRANSPARENT, };
class MemoryCardBakedModel implements IBakedModel
{
private static final AEColor[] DEFAULT_COLOR_CODE = new AEColor[] {
AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT,
AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT,
};
private final IBakedModel baseModel;
private final IBakedModel baseModel;
private final TextureAtlasSprite texture;
private final TextureAtlasSprite texture;
private final AEColor[] colorCode;
private final AEColor[] colorCode;
private final Cache<CacheKey, MemoryCardBakedModel> modelCache;
private final Cache<CacheKey, MemoryCardBakedModel> modelCache;
private final ImmutableList<BakedQuad> generalQuads;
private final ImmutableList<BakedQuad> generalQuads;
MemoryCardBakedModel(IBakedModel baseModel, TextureAtlasSprite texture) {
this(baseModel, texture, DEFAULT_COLOR_CODE, createCache());
}
MemoryCardBakedModel( IBakedModel baseModel, TextureAtlasSprite texture )
{
this( baseModel, texture, DEFAULT_COLOR_CODE, createCache() );
}
private MemoryCardBakedModel(IBakedModel baseModel, TextureAtlasSprite texture, AEColor[] hash,
Cache<CacheKey, MemoryCardBakedModel> modelCache) {
this.baseModel = baseModel;
this.texture = texture;
this.colorCode = hash;
this.generalQuads = ImmutableList.copyOf(this.buildGeneralQuads());
this.modelCache = modelCache;
}
private MemoryCardBakedModel( IBakedModel baseModel, TextureAtlasSprite texture, AEColor[] hash, Cache<CacheKey, MemoryCardBakedModel> modelCache )
{
this.baseModel = baseModel;
this.texture = texture;
this.colorCode = hash;
this.generalQuads = ImmutableList.copyOf( this.buildGeneralQuads() );
this.modelCache = modelCache;
}
private static Cache<CacheKey, MemoryCardBakedModel> createCache() {
return CacheBuilder.newBuilder().maximumSize(100).build();
}
private static Cache<CacheKey, MemoryCardBakedModel> createCache()
{
return CacheBuilder.newBuilder().maximumSize( 100 ).build();
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
@Override
public List<BakedQuad> getQuads( @Nullable BlockState state, @Nullable Direction side, Random rand )
{
List<BakedQuad> quads = this.baseModel.getQuads(state, side, rand, EmptyModelData.INSTANCE);
List<BakedQuad> quads = this.baseModel.getQuads( state, side, rand, EmptyModelData.INSTANCE );
if (side != null) {
return quads;
}
if( side != null )
{
return quads;
}
List<BakedQuad> result = new ArrayList<>(quads.size() + this.generalQuads.size());
result.addAll(quads);
result.addAll(this.generalQuads);
return result;
}
List<BakedQuad> result = new ArrayList<>( quads.size() + this.generalQuads.size() );
result.addAll( quads );
result.addAll( this.generalQuads );
return result;
}
private List<BakedQuad> buildGeneralQuads() {
CubeBuilder builder = new CubeBuilder();
private List<BakedQuad> buildGeneralQuads()
{
CubeBuilder builder = new CubeBuilder();
builder.setTexture(this.texture);
builder.setTexture( this.texture );
for (int x = 0; x < 4; x++) {
for (int y = 0; y < 2; y++) {
final AEColor color = this.colorCode[x + y * 4];
for( int x = 0; x < 4; x++ )
{
for( int y = 0; y < 2; y++ )
{
final AEColor color = this.colorCode[x + y * 4];
builder.setColorRGB(color.mediumVariant);
builder.addCube(7 + x, 8 + (1 - y), 7.5f, 7 + x + 1, 8 + (1 - y) + 1, 8.5f);
}
}
builder.setColorRGB( color.mediumVariant );
builder.addCube( 7 + x, 8 + ( 1 - y ), 7.5f, 7 + x + 1, 8 + ( 1 - y ) + 1, 8.5f );
}
}
return builder.getOutput();
}
return builder.getOutput();
}
@Override
public boolean isAmbientOcclusion() {
return this.baseModel.isAmbientOcclusion();
}
@Override
public boolean isAmbientOcclusion()
{
return this.baseModel.isAmbientOcclusion();
}
@Override
public boolean isGui3d() {
return this.baseModel.isGui3d();
}
@Override
public boolean isGui3d()
{
return this.baseModel.isGui3d();
}
@Override
public boolean func_230044_c_() {
return false;// TODO
}
@Override
public boolean func_230044_c_()
{
return false;//TODO
}
@Override
public boolean isBuiltInRenderer() {
return this.baseModel.isBuiltInRenderer();
}
@Override
public boolean isBuiltInRenderer()
{
return this.baseModel.isBuiltInRenderer();
}
@Override
public TextureAtlasSprite getParticleTexture() {
return this.baseModel.getParticleTexture();
}
@Override
public TextureAtlasSprite getParticleTexture()
{
return this.baseModel.getParticleTexture();
}
@Override
public ItemCameraTransforms getItemCameraTransforms() {
return this.baseModel.getItemCameraTransforms();
}
@Override
public ItemCameraTransforms getItemCameraTransforms()
{
return this.baseModel.getItemCameraTransforms();
}
@Override
public ItemOverrideList getOverrides() {
return new ItemOverrideList() {
@Override
public IBakedModel getModelWithOverrides(IBakedModel originalModel, ItemStack stack, World world,
LivingEntity entity) {
try {
if (stack.getItem() instanceof IMemoryCard) {
final IMemoryCard memoryCard = (IMemoryCard) stack.getItem();
final AEColor[] colors = memoryCard.getColorCode(stack);
@Override
public ItemOverrideList getOverrides()
{
return new ItemOverrideList()
{
@Override
public IBakedModel getModelWithOverrides( IBakedModel originalModel, ItemStack stack, World world, LivingEntity entity )
{
try
{
if( stack.getItem() instanceof IMemoryCard )
{
final IMemoryCard memoryCard = (IMemoryCard) stack.getItem();
final AEColor[] colors = memoryCard.getColorCode( stack );
return MemoryCardBakedModel.this.modelCache.get(new CacheKey(colors),
() -> new MemoryCardBakedModel(MemoryCardBakedModel.this.baseModel,
MemoryCardBakedModel.this.texture, colors,
MemoryCardBakedModel.this.modelCache));
}
} catch (ExecutionException e) {
AELog.error(e);
}
return MemoryCardBakedModel.this.modelCache.get( new CacheKey( colors ),
() -> new MemoryCardBakedModel( MemoryCardBakedModel.this.baseModel, MemoryCardBakedModel.this.texture, colors, MemoryCardBakedModel.this.modelCache ) );
}
}
catch( ExecutionException e )
{
AELog.error( e );
}
return MemoryCardBakedModel.this;
}
};
}
return MemoryCardBakedModel.this;
}
};
}
@Override
public IBakedModel handlePerspective(ItemCameraTransforms.TransformType cameraTransformType, MatrixStack mat) {
baseModel.handlePerspective(cameraTransformType, mat);
return this;
}
@Override
public IBakedModel handlePerspective( ItemCameraTransforms.TransformType cameraTransformType, MatrixStack mat )
{
baseModel.handlePerspective( cameraTransformType, mat );
return this;
}
private static class CacheKey {
private final AEColor[] key;
private static class CacheKey
{
private final AEColor[] key;
CacheKey(AEColor[] key) {
this.key = key;
}
CacheKey( AEColor[] key )
{
this.key = key;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(this.key);
return result;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode( this.key );
return result;
}
@Override
public boolean equals( Object obj )
{
if( this == obj )
{
return true;
}
if( obj == null )
{
return false;
}
if( this.getClass() != obj.getClass() )
{
return false;
}
CacheKey other = (CacheKey) obj;
return Arrays.equals( this.key, other.key );
}
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (this.getClass() != obj.getClass()) {
return false;
}
CacheKey other = (CacheKey) obj;
return Arrays.equals(this.key, other.key);
}
}
}
@@ -1,10 +1,10 @@
package appeng.client.render.model;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.function.Function;
import javax.annotation.Nullable;
import com.mojang.datafixers.util.Pair;
@@ -13,36 +13,37 @@ import net.minecraft.client.renderer.model.*;
import net.minecraft.client.renderer.texture.AtlasTexture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.ResourceLocation;
import appeng.core.AppEng;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.geometry.IModelGeometry;
import appeng.core.AppEng;
/**
* Model wrapper for the memory card item model, which combines a base card layer with a "visual hash" of the part/tile.
* Model wrapper for the memory card item model, which combines a base card
* layer with a "visual hash" of the part/tile.
*/
public class MemoryCardModel implements IModelGeometry<MemoryCardModel>
{
public class MemoryCardModel implements IModelGeometry<MemoryCardModel> {
public static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "item/memory_card_base" );
private static final Material TEXTURE = new Material( AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( AppEng.MOD_ID, "item/memory_card_hash" ) );
public static final ResourceLocation MODEL_BASE = new ResourceLocation(AppEng.MOD_ID, "item/memory_card_base");
private static final Material TEXTURE = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
new ResourceLocation(AppEng.MOD_ID, "item/memory_card_hash"));
@Override
public Collection<Material> getTextures( IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors )
{
return Collections.singleton( TEXTURE );
}
@Override
public Collection<Material> getTextures(IModelConfiguration owner,
Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
return Collections.singleton(TEXTURE);
}
@Nullable
@Override
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation)
{
TextureAtlasSprite texture = spriteGetter.apply( TEXTURE );
@Nullable
@Override
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery,
Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform,
ItemOverrideList overrides, ResourceLocation modelLocation) {
TextureAtlasSprite texture = spriteGetter.apply(TEXTURE);
IBakedModel baseModel = bakery.getBakedModel( MODEL_BASE, modelTransform, spriteGetter );
IBakedModel baseModel = bakery.getBakedModel(MODEL_BASE, modelTransform, spriteGetter);
return new MemoryCardBakedModel( baseModel, texture );
}
return new MemoryCardBakedModel(baseModel, texture);
}
}
@@ -18,7 +18,6 @@
package appeng.client.render.model;
import java.util.EnumMap;
import java.util.List;
@@ -28,69 +27,62 @@ import com.google.common.collect.Lists;
import net.minecraft.util.Direction;
import net.minecraft.util.math.Vec3d;
// TODO: Investigate use of CubeBuilder instead
final class RenderHelper
{
final class RenderHelper {
private static EnumMap<Direction, List<Vec3d>> cornersForFacing = generateCornersForFacings();
private static EnumMap<Direction, List<Vec3d>> cornersForFacing = generateCornersForFacings();
private RenderHelper()
{
private RenderHelper() {
}
}
static List<Vec3d> getFaceCorners( Direction side )
{
return cornersForFacing.get( side );
}
static List<Vec3d> getFaceCorners(Direction side) {
return cornersForFacing.get(side);
}
private static EnumMap<Direction, List<Vec3d>> generateCornersForFacings()
{
EnumMap<Direction, List<Vec3d>> result = new EnumMap<>( Direction.class );
private static EnumMap<Direction, List<Vec3d>> generateCornersForFacings() {
EnumMap<Direction, List<Vec3d>> result = new EnumMap<>(Direction.class);
for( Direction facing : Direction.values() )
{
List<Vec3d> corners;
for (Direction facing : Direction.values()) {
List<Vec3d> corners;
float offset = ( facing.getAxisDirection() == Direction.AxisDirection.NEGATIVE ) ? 0 : 1;
float offset = (facing.getAxisDirection() == Direction.AxisDirection.NEGATIVE) ? 0 : 1;
switch( facing.getAxis() )
{
default:
case X:
corners = Lists.newArrayList( new Vec3d( offset, 1, 1 ), new Vec3d( offset, 0, 1 ), new Vec3d( offset, 0, 0 ), new Vec3d( offset, 1, 0 ) );
break;
case Y:
corners = Lists.newArrayList( new Vec3d( 1, offset, 1 ), new Vec3d( 1, offset, 0 ), new Vec3d( 0, offset, 0 ), new Vec3d( 0, offset, 1 ) );
break;
case Z:
corners = Lists.newArrayList( new Vec3d( 0, 1, offset ), new Vec3d( 0, 0, offset ), new Vec3d( 1, 0, offset ), new Vec3d( 1, 1, offset ) );
break;
}
switch (facing.getAxis()) {
default:
case X:
corners = Lists.newArrayList(new Vec3d(offset, 1, 1), new Vec3d(offset, 0, 1),
new Vec3d(offset, 0, 0), new Vec3d(offset, 1, 0));
break;
case Y:
corners = Lists.newArrayList(new Vec3d(1, offset, 1), new Vec3d(1, offset, 0),
new Vec3d(0, offset, 0), new Vec3d(0, offset, 1));
break;
case Z:
corners = Lists.newArrayList(new Vec3d(0, 1, offset), new Vec3d(0, 0, offset),
new Vec3d(1, 0, offset), new Vec3d(1, 1, offset));
break;
}
if( facing.getAxisDirection() == Direction.AxisDirection.NEGATIVE )
{
corners = Lists.reverse( corners );
}
if (facing.getAxisDirection() == Direction.AxisDirection.NEGATIVE) {
corners = Lists.reverse(corners);
}
result.put( facing, ImmutableList.copyOf( corners ) );
}
result.put(facing, ImmutableList.copyOf(corners));
}
return result;
}
return result;
}
private static Vec3d adjust( Vec3d vec, Direction.Axis axis, double delta )
{
switch( axis )
{
default:
case X:
return new Vec3d( vec.x + delta, vec.y, vec.z );
case Y:
return new Vec3d( vec.x, vec.y + delta, vec.z );
case Z:
return new Vec3d( vec.x, vec.y, vec.z + delta );
}
}
private static Vec3d adjust(Vec3d vec, Direction.Axis axis, double delta) {
switch (axis) {
default:
case X:
return new Vec3d(vec.x + delta, vec.y, vec.z);
case Y:
return new Vec3d(vec.x, vec.y + delta, vec.z);
case Z:
return new Vec3d(vec.x, vec.y, vec.z + delta);
}
}
}
@@ -18,7 +18,6 @@
package appeng.client.render.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -26,8 +25,6 @@ import java.util.Random;
import javax.annotation.Nullable;
import appeng.hooks.CompassManager;
import appeng.hooks.CompassResult;
import net.minecraft.block.BlockState;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.renderer.Matrix4f;
@@ -44,188 +41,172 @@ import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.client.model.data.IDynamicBakedModel;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.data.ModelProperty;
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
import appeng.hooks.CompassManager;
import appeng.hooks.CompassResult;
/**
* This baked model combines the quads of a compass base and the quads of a compass pointer, which will be rotated
* around the Y-axis to get the compass to point in the right direction.
* This baked model combines the quads of a compass base and the quads of a
* compass pointer, which will be rotated around the Y-axis to get the compass
* to point in the right direction.
*/
public class SkyCompassBakedModel implements IDynamicBakedModel
{
// Rotation is expressed as radians
public static final ModelProperty<Float> ROTATION = new ModelProperty<>();
public class SkyCompassBakedModel implements IDynamicBakedModel {
// Rotation is expressed as radians
public static final ModelProperty<Float> ROTATION = new ModelProperty<>();
private final IBakedModel base;
private final IBakedModel base;
private final IBakedModel pointer;
private final IBakedModel pointer;
private float fallbackRotation = 0;
private float fallbackRotation = 0;
public SkyCompassBakedModel( IBakedModel base, IBakedModel pointer )
{
this.base = base;
this.pointer = pointer;
}
public SkyCompassBakedModel(IBakedModel base, IBakedModel pointer) {
this.base = base;
this.pointer = pointer;
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand, IModelData extraData )
{
float rotation = 0;
// Get rotation from the special block state
Float rotationFromData = extraData.getData(ROTATION);
if (rotationFromData != null) {
rotation = rotationFromData;
}
else
{
// This is used to render a compass pointing in a specific direction when being held in hand
rotation = this.fallbackRotation;
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand,
IModelData extraData) {
float rotation = 0;
// Get rotation from the special block state
Float rotationFromData = extraData.getData(ROTATION);
if (rotationFromData != null) {
rotation = rotationFromData;
} else {
// This is used to render a compass pointing in a specific direction when being
// held in hand
rotation = this.fallbackRotation;
}
// Pre-compute the quad count to avoid list resizes
List<BakedQuad> quads = new ArrayList<>();
quads.addAll( this.base.getQuads( state, side, rand, extraData ) );
// Pre-compute the quad count to avoid list resizes
List<BakedQuad> quads = new ArrayList<>();
quads.addAll(this.base.getQuads(state, side, rand, extraData));
// We'll add the pointer as "sideless"
if( side == null )
{
// Set up the rotation around the Y-axis for the pointer
Matrix4f matrix = new Matrix4f();
matrix.setIdentity();
matrix.mul( new Quaternion( 0, rotation, 0, false ) );
// We'll add the pointer as "sideless"
if (side == null) {
// Set up the rotation around the Y-axis for the pointer
Matrix4f matrix = new Matrix4f();
matrix.setIdentity();
matrix.mul(new Quaternion(0, rotation, 0, false));
MatrixVertexTransformer transformer = new MatrixVertexTransformer( matrix );
for( BakedQuad bakedQuad : this.pointer.getQuads( state, side, rand, extraData ) )
{
BakedQuadBuilder builder = new BakedQuadBuilder();
MatrixVertexTransformer transformer = new MatrixVertexTransformer(matrix);
for (BakedQuad bakedQuad : this.pointer.getQuads(state, side, rand, extraData)) {
BakedQuadBuilder builder = new BakedQuadBuilder();
transformer.setParent( builder );
transformer.setVertexFormat( builder.getVertexFormat() );
bakedQuad.pipe( transformer );
// FIXME: This entire code is no longer truly valid...
// FIXME builder.setQuadOrientation( null ); // After rotation, facing a specific side cannot be guaranteed
// anymore
BakedQuad q = builder.build();
quads.add( q );
}
}
transformer.setParent(builder);
transformer.setVertexFormat(builder.getVertexFormat());
bakedQuad.pipe(transformer);
// FIXME: This entire code is no longer truly valid...
// FIXME builder.setQuadOrientation( null ); // After rotation, facing a
// specific side cannot be guaranteed
// anymore
BakedQuad q = builder.build();
quads.add(q);
}
}
return quads;
}
return quads;
}
@Override
public boolean isAmbientOcclusion()
{
return this.base.isAmbientOcclusion();
}
@Override
public boolean isAmbientOcclusion() {
return this.base.isAmbientOcclusion();
}
@Override
public boolean isGui3d()
{
return true;
}
@Override
public boolean isGui3d() {
return true;
}
@Override
public boolean func_230044_c_() {
return false;
}
@Override
public boolean func_230044_c_() {
return false;
}
@Override
public boolean isBuiltInRenderer()
{
return false;
}
@Override
public boolean isBuiltInRenderer() {
return false;
}
@Override
public TextureAtlasSprite getParticleTexture()
{
return this.base.getParticleTexture();
}
@Override
public TextureAtlasSprite getParticleTexture() {
return this.base.getParticleTexture();
}
@Override
public ItemCameraTransforms getItemCameraTransforms()
{
return this.base.getItemCameraTransforms();
}
@Override
public ItemCameraTransforms getItemCameraTransforms() {
return this.base.getItemCameraTransforms();
}
@Override
public ItemOverrideList getOverrides()
{
/*
* This handles setting the rotation of the compass when being held in hand. If it's not held in hand, it'll
* animate using the
* spinning animation.
*/
return new ItemOverrideList()
{
@Override
public IBakedModel getModelWithOverrides(IBakedModel originalModel, ItemStack stack, @Nullable World world, @Nullable LivingEntity entity) {
// FIXME: This check prevents compasses being held by OTHERS from getting the rotation, BUT do we actually still need this???
if (world != null && entity instanceof ClientPlayerEntity)
{
PlayerEntity player = (PlayerEntity) entity;
@Override
public ItemOverrideList getOverrides() {
/*
* This handles setting the rotation of the compass when being held in hand. If
* it's not held in hand, it'll animate using the spinning animation.
*/
return new ItemOverrideList() {
@Override
public IBakedModel getModelWithOverrides(IBakedModel originalModel, ItemStack stack, @Nullable World world,
@Nullable LivingEntity entity) {
// FIXME: This check prevents compasses being held by OTHERS from getting the
// rotation, BUT do we actually still need this???
if (world != null && entity instanceof ClientPlayerEntity) {
PlayerEntity player = (PlayerEntity) entity;
float offRads = (float) ( player.rotationYaw / 180.0f * (float) Math.PI + Math.PI );
float offRads = (float) (player.rotationYaw / 180.0f * (float) Math.PI + Math.PI);
SkyCompassBakedModel.this.fallbackRotation = offRads + getAnimatedRotation( player.getPosition(), true );
}
else
{
SkyCompassBakedModel.this.fallbackRotation = getAnimatedRotation( null, false );
}
SkyCompassBakedModel.this.fallbackRotation = offRads
+ getAnimatedRotation(player.getPosition(), true);
} else {
SkyCompassBakedModel.this.fallbackRotation = getAnimatedRotation(null, false);
}
return originalModel;
}
};
}
return originalModel;
}
};
}
/**
* Gets the effective, animated rotation for the compass given the current position of the compass.
*/
public static float getAnimatedRotation( @Nullable BlockPos pos, boolean prefetch )
{
/**
* Gets the effective, animated rotation for the compass given the current
* position of the compass.
*/
public static float getAnimatedRotation(@Nullable BlockPos pos, boolean prefetch) {
// Only query for a meteor position if we know our own position
if( pos != null )
{
CompassResult cr = CompassManager.INSTANCE.getCompassDirection( 0, pos.getX(), pos.getY(), pos.getZ() );
// Only query for a meteor position if we know our own position
if (pos != null) {
CompassResult cr = CompassManager.INSTANCE.getCompassDirection(0, pos.getX(), pos.getY(), pos.getZ());
// Prefetch meteor positions from the server for adjacent blocks so they are available more quickly when
// we're moving
if( prefetch )
{
for( int i = 0; i < 3; i++ )
{
for( int j = 0; j < 3; j++ )
{
CompassManager.INSTANCE.getCompassDirection( 0, pos.getX() + i - 1, pos.getY(), pos.getZ() + j - 1 );
}
}
}
// Prefetch meteor positions from the server for adjacent blocks so they are
// available more quickly when
// we're moving
if (prefetch) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
CompassManager.INSTANCE.getCompassDirection(0, pos.getX() + i - 1, pos.getY(),
pos.getZ() + j - 1);
}
}
}
if( cr.isValidResult() )
{
if( cr.isSpin() )
{
long timeMillis = System.currentTimeMillis();
// .5 seconds per full rotation
timeMillis %= 500;
return timeMillis / 500.f * (float) Math.PI * 2;
}
else
{
return (float) cr.getRad();
}
}
}
if (cr.isValidResult()) {
if (cr.isSpin()) {
long timeMillis = System.currentTimeMillis();
// .5 seconds per full rotation
timeMillis %= 500;
return timeMillis / 500.f * (float) Math.PI * 2;
} else {
return (float) cr.getRad();
}
}
}
long timeMillis = System.currentTimeMillis();
// 3 seconds per full rotation
timeMillis %= 3000;
return timeMillis / 3000.f * (float) Math.PI * 2;
}
long timeMillis = System.currentTimeMillis();
// 3 seconds per full rotation
timeMillis %= 3000;
return timeMillis / 3000.f * (float) Math.PI * 2;
}
}
@@ -18,44 +18,48 @@
package appeng.client.render.model;
import com.google.common.collect.ImmutableList;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.model.*;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.geometry.IModelGeometry;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import com.google.common.collect.ImmutableList;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.model.*;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.geometry.IModelGeometry;
/**
* The parent model for the compass baked model. Declares the dependencies for the base and pointer submodels mostly.
* The parent model for the compass baked model. Declares the dependencies for
* the base and pointer submodels mostly.
*/
public class SkyCompassModel implements IModelGeometry<SkyCompassModel>
{
public class SkyCompassModel implements IModelGeometry<SkyCompassModel> {
private static final ResourceLocation MODEL_BASE = new ResourceLocation( "appliedenergistics2:block/sky_compass_base" );
private static final ResourceLocation MODEL_BASE = new ResourceLocation(
"appliedenergistics2:block/sky_compass_base");
private static final ResourceLocation MODEL_POINTER = new ResourceLocation( "appliedenergistics2:block/sky_compass_pointer" );
private static final ResourceLocation MODEL_POINTER = new ResourceLocation(
"appliedenergistics2:block/sky_compass_pointer");
public static final List<ResourceLocation> DEPENDENCIES = ImmutableList.of( MODEL_BASE, MODEL_POINTER );
public static final List<ResourceLocation> DEPENDENCIES = ImmutableList.of(MODEL_BASE, MODEL_POINTER);
@Override
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation) {
IBakedModel baseModel = bakery.getBakedModel(MODEL_BASE, modelTransform, spriteGetter);
IBakedModel pointerModel = bakery.getBakedModel(MODEL_POINTER, modelTransform, spriteGetter);
return new SkyCompassBakedModel(baseModel, pointerModel);
}
@Override
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery,
Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform,
ItemOverrideList overrides, ResourceLocation modelLocation) {
IBakedModel baseModel = bakery.getBakedModel(MODEL_BASE, modelTransform, spriteGetter);
IBakedModel pointerModel = bakery.getBakedModel(MODEL_POINTER, modelTransform, spriteGetter);
return new SkyCompassBakedModel(baseModel, pointerModel);
}
@Override
public Collection<Material> getTextures(IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
return Collections.emptyList();
}
@Override
public Collection<Material> getTextures(IModelConfiguration owner,
Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
return Collections.emptyList();
}
}
@@ -18,9 +18,21 @@
package appeng.client.render.model;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import javax.annotation.Nullable;
import com.google.gson.*;
import com.mojang.blaze3d.matrix.MatrixStack;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.TransformationMatrix;
@@ -40,160 +52,146 @@ import net.minecraftforge.client.model.geometry.IModelGeometry;
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
import net.minecraftforge.client.model.pipeline.VertexLighterFlat;
import net.minecraftforge.common.model.TransformationHelper;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nullable;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
public class UVLModelLoader implements IModelLoader<UVLModelLoader.UVLModelWrapper> {
public static final UVLModelLoader INSTANCE = new UVLModelLoader();
public class UVLModelLoader implements IModelLoader<UVLModelLoader.UVLModelWrapper>
{
@Override
public void onResourceManagerReload(IResourceManager resourceManager) {
}
public static final UVLModelLoader INSTANCE = new UVLModelLoader();
@Override
public UVLModelWrapper read(JsonDeserializationContext deserializationContext, JsonObject modelContents) {
modelContents.remove("loader");
BlockModel blockModel = UVLSERIALIZER.fromJson(modelContents, BlockModel.class);
return new UVLModelWrapper(blockModel);
}
@Override
public void onResourceManagerReload(IResourceManager resourceManager) {
}
final Gson UVLSERIALIZER = (new GsonBuilder())
.registerTypeAdapter(BlockModel.class, new ModelLoaderRegistry.ExpandedBlockModelDeserializer())
.registerTypeAdapter(BlockPart.class, new BlockPart.Deserializer())
.registerTypeAdapter(BlockPartFace.class, new BlockPartFaceOverrideSerializer())
.registerTypeAdapter(BlockFaceUV.class, new BlockFaceUV.Deserializer())
.registerTypeAdapter(ItemTransformVec3f.class, new ItemTransformVec3f.Deserializer())
.registerTypeAdapter(ItemCameraTransforms.class, new ItemCameraTransforms.Deserializer())
.registerTypeAdapter(ItemOverride.class, new ItemOverride.Deserializer())
.registerTypeAdapter(TransformationMatrix.class, new TransformationHelper.Deserializer()).create();
@Override
public UVLModelWrapper read(JsonDeserializationContext deserializationContext, JsonObject modelContents) {
modelContents.remove("loader");
BlockModel blockModel = UVLSERIALIZER.fromJson(modelContents, BlockModel.class);
return new UVLModelWrapper(blockModel);
}
private static class BlockPartFaceOverrideSerializer extends BlockPartFace.Deserializer {
@Override
public BlockPartFace deserialize(JsonElement p_deserialize_1_, Type p_deserialize_2_,
JsonDeserializationContext p_deserialize_3_) throws JsonParseException {
BlockPartFace blockFace = super.deserialize(p_deserialize_1_, p_deserialize_2_, p_deserialize_3_);
Pair<Float, Float> uvl = this.parseUVL(p_deserialize_1_.getAsJsonObject());
if (uvl != null) {
return new BlockPartFaceWithUVL(blockFace.cullFace, blockFace.tintIndex, blockFace.texture,
blockFace.blockFaceUV, uvl.getLeft(), uvl.getRight());
}
return blockFace;
}
final Gson UVLSERIALIZER = (new GsonBuilder())
.registerTypeAdapter(BlockModel.class, new ModelLoaderRegistry.ExpandedBlockModelDeserializer())
.registerTypeAdapter(BlockPart.class, new BlockPart.Deserializer())
.registerTypeAdapter(BlockPartFace.class, new BlockPartFaceOverrideSerializer())
.registerTypeAdapter(BlockFaceUV.class, new BlockFaceUV.Deserializer())
.registerTypeAdapter(ItemTransformVec3f.class, new ItemTransformVec3f.Deserializer())
.registerTypeAdapter(ItemCameraTransforms.class, new ItemCameraTransforms.Deserializer())
.registerTypeAdapter(ItemOverride.class, new ItemOverride.Deserializer())
.registerTypeAdapter(TransformationMatrix.class, new TransformationHelper.Deserializer())
.create();
protected Pair<Float, Float> parseUVL(JsonObject object) {
if (!object.has("uvlightmap")) {
return null;
}
object = object.get("uvlightmap").getAsJsonObject();
return new ImmutablePair<>(JSONUtils.getFloat(object, "sky", 0), JSONUtils.getFloat(object, "block", 0));
}
}
private static class BlockPartFaceOverrideSerializer extends BlockPartFace.Deserializer
{
@Override
public BlockPartFace deserialize( JsonElement p_deserialize_1_, Type p_deserialize_2_, JsonDeserializationContext p_deserialize_3_ ) throws JsonParseException
{
BlockPartFace blockFace = super.deserialize(p_deserialize_1_, p_deserialize_2_, p_deserialize_3_);
Pair<Float, Float> uvl = this.parseUVL(p_deserialize_1_.getAsJsonObject());
if (uvl != null) {
return new BlockPartFaceWithUVL(blockFace.cullFace, blockFace.tintIndex, blockFace.texture, blockFace.blockFaceUV, uvl.getLeft(), uvl.getRight());
}
return blockFace;
}
private static class BlockPartFaceWithUVL extends BlockPartFace {
protected Pair<Float, Float> parseUVL( JsonObject object )
{
if( !object.has( "uvlightmap" ) )
{
return null;
}
object = object.get( "uvlightmap" ).getAsJsonObject();
return new ImmutablePair<>( JSONUtils.getFloat( object, "sky", 0 ), JSONUtils.getFloat( object, "block", 0 ) );
}
}
private final float sky;
private final float block;
private static class BlockPartFaceWithUVL extends BlockPartFace {
public BlockPartFaceWithUVL(@Nullable Direction cullFaceIn, int tintIndexIn, String textureIn,
BlockFaceUV blockFaceUVIn, float sky, float block) {
super(cullFaceIn, tintIndexIn, textureIn, blockFaceUVIn);
this.sky = sky;
this.block = block;
}
private final float sky;
private final float block;
public float getSky() {
return sky;
}
public BlockPartFaceWithUVL(@Nullable Direction cullFaceIn, int tintIndexIn, String textureIn, BlockFaceUV blockFaceUVIn, float sky, float block) {
super(cullFaceIn, tintIndexIn, textureIn, blockFaceUVIn);
this.sky = sky;
this.block = block;
}
public float getBlock() {
return block;
}
}
public float getSky() {
return sky;
}
public static class UVLModelWrapper implements IModelGeometry<UVLModelWrapper> {
private final BlockModel parent;
public float getBlock() {
return block;
}
}
public UVLModelWrapper(BlockModel parent) {
this.parent = parent;
}
public static class UVLModelWrapper implements IModelGeometry<UVLModelWrapper>
{
private final BlockModel parent;
@Override
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery,
Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform,
ItemOverrideList overrides, ResourceLocation modelLocation) {
TextureAtlasSprite particle = spriteGetter.apply(owner.resolveTexture("particle"));
public UVLModelWrapper( BlockModel parent )
{
this.parent = parent;
}
IModelBuilder<?> builder = IModelBuilder.of(owner, overrides, particle);
for (BlockPart blockpart : parent.getElements()) {
for (Direction direction : blockpart.mapFaces.keySet()) {
BlockPartFace blockpartface = blockpart.mapFaces.get(direction);
TextureAtlasSprite textureatlassprite1 = spriteGetter
.apply(owner.resolveTexture(blockpartface.texture));
BakedQuad quad = BlockModel.makeBakedQuad(blockpart, blockpartface, textureatlassprite1, direction,
modelTransform, modelLocation);
@Override
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation) {
TextureAtlasSprite particle = spriteGetter.apply(owner.resolveTexture("particle"));
if (blockpartface instanceof BlockPartFaceWithUVL) {
BlockPartFaceWithUVL uvlFace = (BlockPartFaceWithUVL) blockpartface;
quad = applyPreBakedLighting(quad, textureatlassprite1, uvlFace.sky, uvlFace.block);
}
IModelBuilder<?> builder = IModelBuilder.of(owner, overrides, particle);
for(BlockPart blockpart : parent.getElements()) {
for(Direction direction : blockpart.mapFaces.keySet()) {
BlockPartFace blockpartface = blockpart.mapFaces.get(direction);
TextureAtlasSprite textureatlassprite1 = spriteGetter.apply(owner.resolveTexture(blockpartface.texture));
BakedQuad quad = BlockModel.makeBakedQuad(blockpart, blockpartface, textureatlassprite1, direction, modelTransform, modelLocation);
if (blockpartface.cullFace == null) {
builder.addGeneralQuad(quad);
} else {
builder.addFaceQuad(modelTransform.getRotation().rotateTransform(blockpartface.cullFace), quad);
}
}
}
return builder.build();
}
if (blockpartface instanceof BlockPartFaceWithUVL) {
BlockPartFaceWithUVL uvlFace = (BlockPartFaceWithUVL) blockpartface;
quad = applyPreBakedLighting(quad, textureatlassprite1, uvlFace.sky, uvlFace.block);
}
private BakedQuad applyPreBakedLighting(BakedQuad quad, TextureAtlasSprite sprite, float sky, float block) {
// FIXME: just piping through the quads and manipulating uv index 2 directly
// seems way easier than this
BakedQuadBuilder builder = new BakedQuadBuilder(sprite);
VertexLighterFlat trans = new VertexLighterFlat(Minecraft.getInstance().getBlockColors()) {
if (blockpartface.cullFace == null) {
builder.addGeneralQuad(quad);
} else {
builder.addFaceQuad(
modelTransform.getRotation().rotateTransform(blockpartface.cullFace),
quad);
}
}
}
return builder.build();
}
@Override
protected void updateLightmap(float[] normal, float[] lightmap, float x, float y, float z) {
lightmap[0] = block;
lightmap[1] = sky;
}
private BakedQuad applyPreBakedLighting(BakedQuad quad, TextureAtlasSprite sprite, float sky, float block) {
// FIXME: just piping through the quads and manipulating uv index 2 directly seems way easier than this
BakedQuadBuilder builder = new BakedQuadBuilder(sprite);
VertexLighterFlat trans = new VertexLighterFlat( Minecraft.getInstance().getBlockColors() )
{
@Override
public void setQuadTint(int tint) {
// Tint requires a block state which we don't have at this point
}
};
MatrixStack identity = new MatrixStack();
trans.setTransform(identity.getLast());
trans.setParent(builder);
quad.pipe(trans);
builder.setQuadTint(quad.getTintIndex());
builder.setQuadOrientation(quad.getFace());
builder.setApplyDiffuseLighting(false);
return builder.build();
}
@Override
protected void updateLightmap( float[] normal, float[] lightmap, float x, float y, float z )
{
lightmap[0] = block;
lightmap[1] = sky;
}
@Override
public Collection<Material> getTextures(IModelConfiguration owner,
Function<ResourceLocation, IUnbakedModel> modelGetter,
Set<com.mojang.datafixers.util.Pair<String, String>> missingTextureErrors) {
return parent.getTextures(modelGetter, missingTextureErrors);
}
@Override
public void setQuadTint( int tint )
{
// Tint requires a block state which we don't have at this point
}
};
MatrixStack identity = new MatrixStack();
trans.setTransform(identity.getLast());
trans.setParent( builder );
quad.pipe( trans );
builder.setQuadTint( quad.getTintIndex() );
builder.setQuadOrientation( quad.getFace() );
builder.setApplyDiffuseLighting( false );
return builder.build();
}
@Override
public Collection<Material> getTextures(IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<com.mojang.datafixers.util.Pair<String, String>> missingTextureErrors) {
return parent.getTextures(modelGetter, missingTextureErrors);
}
}
}
}