Implemented the sky compass.

This commit is contained in:
Sebastian Hartte 2016-08-26 13:07:37 +02:00
parent d1ccb126b6
commit 576923a2f2
13 changed files with 803 additions and 6 deletions

View File

@ -24,12 +24,17 @@ import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.property.ExtendedBlockState;
import net.minecraftforge.common.property.IUnlistedProperty;
import net.minecraftforge.common.property.PropertyFloat;
import appeng.block.AEBaseTileBlock;
import appeng.helpers.ICustomCollision;
@ -38,12 +43,22 @@ import appeng.tile.misc.TileSkyCompass;
public class BlockSkyCompass extends AEBaseTileBlock implements ICustomCollision
{
// Rotation is expressed as radians
public static final PropertyFloat ROTATION = new PropertyFloat( "rotation" );
public BlockSkyCompass()
{
super( Material.IRON );
super( Material.CIRCUITS );
this.setTileEntity( TileSkyCompass.class );
this.setOpaque( this.setFullSize( false ) );
this.lightOpacity = 0;
this.setLightOpacity( 0 );
this.setFullSize( false );
this.setOpaque( false );
}
@Override
protected BlockStateContainer createBlockState()
{
return new ExtendedBlockState( this, getAEStates(), new IUnlistedProperty[] { ROTATION } );
}
@Override
@ -66,7 +81,7 @@ public class BlockSkyCompass extends AEBaseTileBlock implements ICustomCollision
public void neighborChanged( final IBlockState state, final World w, final BlockPos pos, final Block neighborBlock )
{
final TileSkyCompass sc = this.getTileEntity( w, pos );
final EnumFacing up = sc.getForward();
final EnumFacing up = sc.getUp();
if( !this.canPlaceAt( w, pos, up.getOpposite() ) )
{
this.dropTorch( w, pos );
@ -99,7 +114,7 @@ public class BlockSkyCompass extends AEBaseTileBlock implements ICustomCollision
final TileSkyCompass tile = this.getTileEntity( w, pos );
if( tile != null )
{
final EnumFacing forward = tile.getForward();
final EnumFacing forward = tile.getUp();
double minX = 0;
double minY = 0;
@ -160,4 +175,17 @@ public class BlockSkyCompass extends AEBaseTileBlock implements ICustomCollision
{
}
@Override
public EnumBlockRenderType getRenderType( IBlockState state )
{
return EnumBlockRenderType.ENTITYBLOCK_ANIMATED;
}
@Override
public boolean isFullBlock( IBlockState state )
{
return false;
}
}

View File

@ -0,0 +1,27 @@
package appeng.block.misc;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import appeng.bootstrap.BlockRenderingCustomizer;
import appeng.bootstrap.IBlockRendering;
import appeng.bootstrap.IItemRendering;
import appeng.client.render.model.SkyCompassModel;
import appeng.client.render.tesr.SkyCompassTESR;
public class SkyCompassRendering extends BlockRenderingCustomizer
{
private static final ModelResourceLocation ITEM_MODEL = new ModelResourceLocation( "appliedenergistics2:sky_compass", "normal" );
@Override
public void customize( IBlockRendering rendering, IItemRendering itemRendering )
{
rendering.tesr( new SkyCompassTESR() );
// This disables the default smart-rotating model
rendering.modelCustomizer( ( loc, model ) -> model );
itemRendering.model( ITEM_MODEL );
itemRendering.builtInModel( "models/block/builtin/sky_compass", new SkyCompassModel() );
}
}

View File

@ -0,0 +1,166 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.model;
import javax.vecmath.Matrix4f;
import javax.vecmath.Vector4f;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.client.model.pipeline.QuadGatheringTransformer;
/**
* Applies an arbitrary transformation matrix to the vertices of a quad.
*/
final class MatrixVertexTransformer extends QuadGatheringTransformer
{
private final Matrix4f transform;
public MatrixVertexTransformer( Matrix4f transform )
{
this.transform = transform;
}
@Override
protected void processQuad()
{
VertexFormat format = parent.getVertexFormat();
int count = format.getElementCount();
for( int v = 0; v < 4; v++ )
{
for( int e = 0; e < count; e++ )
{
VertexFormatElement element = format.getElement( e );
if( element.getUsage() == VertexFormatElement.EnumUsage.POSITION )
{
parent.put( e, transform( quadData[e][v] ) );
}
else if( element.getUsage() == VertexFormatElement.EnumUsage.NORMAL )
{
parent.put( e, transformNormal( quadData[e][v] ) );
}
else
{
parent.put( e, quadData[e][v] );
}
}
}
}
@Override
public void setQuadTint( int tint )
{
parent.setQuadTint( tint );
}
@Override
public void setQuadOrientation( EnumFacing orientation )
{
parent.setQuadOrientation( orientation );
}
@Override
public void setApplyDiffuseLighting( boolean diffuse )
{
parent.setApplyDiffuseLighting( diffuse );
}
@Override
public void setTexture( TextureAtlasSprite texture )
{
parent.setTexture( texture );
}
private float[] transform( float[] fs )
{
switch( fs.length )
{
case 3:
javax.vecmath.Vector3f vec = new javax.vecmath.Vector3f( fs[0], fs[1], fs[2] );
vec.x -= 0.5f;
vec.y -= 0.5f;
vec.z -= 0.5f;
transform.transform( vec );
vec.x += 0.5f;
vec.y += 0.5f;
vec.z += 0.5f;
return new float[] {
vec.x,
vec.y,
vec.z
};
case 4:
Vector4f vecc = new Vector4f( fs[0], fs[1], fs[2], fs[3] );
vecc.x -= 0.5f;
vecc.y -= 0.5f;
vecc.z -= 0.5f;
transform.transform( vecc );
vecc.x += 0.5f;
vecc.y += 0.5f;
vecc.z += 0.5f;
return new float[] {
vecc.x,
vecc.y,
vecc.z,
vecc.w
};
default:
return fs;
}
}
private float[] transformNormal( float[] fs )
{
Vector4f normal;
switch( fs.length )
{
case 3:
normal = new Vector4f( fs[0], fs[1], fs[2], 0 );
this.transform.transform( normal );
normal.normalize();
return new float[] {
normal.x,
normal.y,
normal.z
};
case 4:
normal = new Vector4f( fs[0], fs[1], fs[2], fs[3] );
this.transform.transform( normal );
normal.normalize();
return new float[] {
normal.x,
normal.y,
normal.z,
normal.w
};
default:
return fs;
}
}
}

View File

@ -0,0 +1,223 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
import javax.vecmath.AxisAngle4f;
import javax.vecmath.Matrix4f;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.model.ItemOverrideList;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad;
import net.minecraftforge.common.property.IExtendedBlockState;
import appeng.block.misc.BlockSkyCompass;
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.
*/
public class SkyCompassBakedModel implements IBakedModel
{
private final IBakedModel base;
private final IBakedModel pointer;
private float fallbackRotation = 0;
public SkyCompassBakedModel( IBakedModel base, IBakedModel pointer )
{
this.base = base;
this.pointer = pointer;
}
@Override
public List<BakedQuad> getQuads( @Nullable IBlockState state, @Nullable EnumFacing side, long rand )
{
float rotation = 0;
// Get rotation from the special block state
if( state instanceof IExtendedBlockState )
{
Float rotationOpt = ( (IExtendedBlockState) state ).getValue( BlockSkyCompass.ROTATION );
if( rotationOpt != null )
{
rotation = rotationOpt;
}
}
else if( state == null )
{
// This is used to render a compass pointing in a specific direction when being held in hand
rotation = fallbackRotation;
}
// Pre-compute the quad count to avoid list resizes
List<BakedQuad> quads = new ArrayList<>();
quads.addAll( base.getQuads( state, side, rand ) );
// 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.setRotation( new AxisAngle4f( 0, 1, 0, rotation ) );
MatrixVertexTransformer transformer = new MatrixVertexTransformer( matrix );
for( BakedQuad bakedQuad : pointer.getQuads( state, side, rand ) )
{
UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder( bakedQuad.getFormat() );
transformer.setParent( builder );
transformer.setVertexFormat( builder.getVertexFormat() );
bakedQuad.pipe( transformer );
builder.setQuadOrientation( null ); // After rotation, facing a specific side cannot be guaranteed anymore
BakedQuad q = builder.build();
quads.add( q );
}
}
return quads;
}
@Override
public boolean isAmbientOcclusion()
{
return base.isAmbientOcclusion();
}
@Override
public boolean isGui3d()
{
return true;
}
@Override
public boolean isBuiltInRenderer()
{
return false;
}
@Override
public TextureAtlasSprite getParticleTexture()
{
return base.getParticleTexture();
}
@Override
public ItemCameraTransforms getItemCameraTransforms()
{
return 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( Collections.emptyList() )
{
@Override
public IBakedModel handleItemState( IBakedModel originalModel, ItemStack stack, World world, EntityLivingBase entity )
{
if( world != null && entity instanceof EntityPlayerSP )
{
EntityPlayer player = (EntityPlayer) entity;
float offRads = (float) ( player.rotationYaw / 180.0f * (float) Math.PI + Math.PI );
fallbackRotation = offRads + getAnimatedRotation( player.getPosition(), true );
}
else
{
fallbackRotation = getAnimatedRotation( null, false );
}
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 )
{
// 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 );
}
}
}
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;
}
}

View File

@ -0,0 +1,87 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.model;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.IModel;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.common.model.IModelState;
import net.minecraftforge.common.model.TRSRTransformation;
/**
* The parent model for the compass baked model. Declares the dependencies for the base and pointer submodels mostly.
*/
public class SkyCompassModel implements IModel
{
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 List<ResourceLocation> DEPENDENCIES = ImmutableList.of( MODEL_BASE, MODEL_POINTER );
@Override
public Collection<ResourceLocation> getDependencies()
{
return DEPENDENCIES;
}
@Override
public Collection<ResourceLocation> getTextures()
{
return Collections.emptyList();
}
@Override
public IBakedModel bake( IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter )
{
IModel baseModel, pointerModel;
try
{
baseModel = ModelLoaderRegistry.getModel( MODEL_BASE );
pointerModel = ModelLoaderRegistry.getModel( MODEL_POINTER );
}
catch( Exception e )
{
throw new RuntimeException( e );
}
IBakedModel bakedBase = baseModel.bake( state, format, bakedTextureGetter );
IBakedModel bakedPointer = pointerModel.bake( state, format, bakedTextureGetter );
return new SkyCompassBakedModel( bakedBase, bakedPointer );
}
@Override
public IModelState getDefaultState()
{
return TRSRTransformation.identity();
}
}

View File

@ -0,0 +1,110 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.tesr;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.VertexBuffer;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraftforge.client.MinecraftForgeClient;
import net.minecraftforge.client.model.animation.FastTESR;
import net.minecraftforge.common.property.IExtendedBlockState;
import net.minecraftforge.common.property.Properties;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import appeng.block.misc.BlockSkyCompass;
import appeng.client.render.model.SkyCompassBakedModel;
import appeng.tile.misc.TileSkyCompass;
@SideOnly( Side.CLIENT )
public class SkyCompassTESR extends FastTESR<TileSkyCompass>
{
private static BlockRendererDispatcher blockRenderer;
@Override
public void renderTileEntityFast( TileSkyCompass te, double x, double y, double z, float partialTicks, int destroyStage, VertexBuffer buffer )
{
if( !te.hasWorldObj() )
{
return;
}
if( blockRenderer == null )
{
blockRenderer = Minecraft.getMinecraft().getBlockRendererDispatcher();
}
BlockPos pos = te.getPos();
IBlockAccess world = MinecraftForgeClient.getRegionRenderCache( te.getWorld(), pos );
IBlockState state = world.getBlockState( pos );
if( state.getPropertyNames().contains( Properties.StaticProperty ) )
{
state = state.withProperty( Properties.StaticProperty, false );
}
if( state instanceof IExtendedBlockState )
{
IExtendedBlockState exState = (IExtendedBlockState) state;
IBakedModel model = blockRenderer.getBlockModelShapes().getModelForState( exState.getClean() );
exState = exState.withProperty( BlockSkyCompass.ROTATION, getRotation( te ) );
buffer.setTranslation( x - pos.getX(), y - pos.getY(), z - pos.getZ() );
blockRenderer.getBlockModelRenderer().renderModel( world, model, exState, pos, buffer, false );
}
}
private static float getRotation( TileSkyCompass skyCompass )
{
float rotation;
if( skyCompass.getUp() == EnumFacing.UP || skyCompass.getUp() == EnumFacing.DOWN )
{
rotation = SkyCompassBakedModel.getAnimatedRotation( skyCompass.getPos(), false );
}
else
{
rotation = SkyCompassBakedModel.getAnimatedRotation( null, false );
}
if( skyCompass.getUp() == EnumFacing.DOWN )
{
rotation = flipidiy( rotation );
}
return rotation;
}
private static float flipidiy( float rad )
{
float x = (float) Math.cos( rad );
float y = (float) Math.sin( rad );
return (float) Math.atan2( -y, x );
}
}

View File

@ -52,6 +52,7 @@ import appeng.block.misc.BlockSecurityStation;
import appeng.block.misc.BlockSkyCompass;
import appeng.block.misc.BlockTinyTNT;
import appeng.block.misc.BlockVibrationChamber;
import appeng.block.misc.SkyCompassRendering;
import appeng.block.networking.BlockCableBus;
import appeng.block.networking.BlockController;
import appeng.block.networking.BlockCreativeEnergyCell;
@ -236,7 +237,10 @@ public final class ApiBlocks implements IBlocks
.rendering( new SkyChestRenderingCustomizer( SkyChestType.BLOCK ) )
.build();
this.skyCompass = registry.block( "sky_compass", BlockSkyCompass::new ).features( AEFeature.MeteoriteCompass ).build();
this.skyCompass = registry.block( "sky_compass", BlockSkyCompass::new )
.features( AEFeature.MeteoriteCompass )
.rendering( new SkyCompassRendering() )
.build();
this.grindstone = registry.block( "grindstone", BlockGrinder::new ).features( AEFeature.GrindStone ).build();
this.crank = registry.block( "crank", BlockCrank::new )
.features( AEFeature.GrindStone )

View File

@ -30,4 +30,11 @@ public class TileSkyCompass extends AEBaseTile
{
return true;
}
@Override
public boolean hasFastRenderer()
{
return true;
}
}

View File

@ -0,0 +1,5 @@
{
"variants": {
"normal": { "model": "appliedenergistics2:builtin/sky_compass" }
}
}

View File

@ -0,0 +1,119 @@
{
"parent": "block/block",
"textures": {
"particle": "appliedenergistics2:blocks/sky_compass",
"0": "appliedenergistics2:blocks/sky_compass"
},
"display": {
"gui": {
"rotation": [ 30, 225, 0 ],
"translation": [ 0, 8, 0],
"scale":[ 1.5, 1.5, 1.5 ]
},
"ground": {
"rotation": [ 0, 0, 0 ],
"translation": [ 0, 3, 0],
"scale":[ 0.5, 0.5, 0.5 ]
},
"fixed": {
"rotation": [ 270, 0, 0 ],
"translation": [ 0, 0, -10.1 ],
"scale":[ 1.5, 1.5, 1.5 ]
},
"thirdperson_righthand": {
"rotation": [ 75, 45, 0 ],
"translation": [ 0, 2.5, 2],
"scale": [ 0.375, 0.375, 0.375 ]
},
"firstperson_righthand": {
"rotation": [ 10, 0, 0 ],
"translation": [ 0, 8, -12 ],
"scale": [ 2, 2, 2 ]
},
"firstperson_lefthand": {
"rotation": [ 10, 0, 0 ],
"translation": [ 0, 8, -12 ],
"scale": [ 2, 2, 2 ]
}
},
"elements": [
{
"name": "Base",
"from": [ 6.0, 0.0, 6.0 ],
"to": [ 10.0, 1.0, 10.0 ],
"faces": {
"north": { "texture": "#0", "uv": [ 0.0, 4.0, 4.0, 5.0 ] },
"east": { "texture": "#0", "uv": [ 4.0, 4.0, 8.0, 5.0 ] },
"south": { "texture": "#0", "uv": [ 8.0, 4.0, 12.0, 5.0 ] },
"west": { "texture": "#0", "uv": [ 12.0, 4.0, 16.0, 5.0 ] },
"up": { "texture": "#0", "uv": [ 6.0, 0.0, 10.0, 4.0 ] },
"down": { "texture": "#0", "uv": [ 6.0, 0.0, 10.0, 4.0 ] }
}
},
{
"name": "Border",
"from": [ 6.0, 1.0, 5.0 ],
"to": [ 10.0, 2.0, 6.0 ],
"faces": {
"north": { "texture": "#0", "uv": [ 1.0, 0.0, 5.0, 1.0 ] },
"east": { "texture": "#0", "uv": [ 0.0, 1.0, 1.0, 2.0 ] },
"south": { "texture": "#0", "uv": [ 5.0, 0.0, 9.0, 1.0 ] },
"west": { "texture": "#0", "uv": [ 4.0, 0.0, 5.0, 1.0 ] },
"up": { "texture": "#0", "uv": [ 8.0, 0.0, 12.0, 1.0 ] },
"down": { "texture": "#0", "uv": [ 8.0, 0.0, 12.0, 1.0 ] }
}
},
{
"name": "Border",
"from": [ 6.0, 1.0, 10.0 ],
"to": [ 10.0, 2.0, 11.0 ],
"faces": {
"north": { "texture": "#0", "uv": [ 1.0, 0.0, 5.0, 1.0 ] },
"east": { "texture": "#0", "uv": [ 0.0, 1.0, 1.0, 2.0 ] },
"south": { "texture": "#0", "uv": [ 5.0, 0.0, 9.0, 1.0 ] },
"west": { "texture": "#0", "uv": [ 4.0, 0.0, 5.0, 1.0 ] },
"up": { "texture": "#0", "uv": [ 8.0, 0.0, 12.0, 1.0 ] },
"down": { "texture": "#0", "uv": [ 8.0, 0.0, 12.0, 1.0 ] }
}
},
{
"name": "Border",
"from": [ 10.0, 1.0, 6.0 ],
"to": [ 11.0, 2.0, 10.0 ],
"faces": {
"north": { "texture": "#0", "uv": [ 2.0, 0.0, 3.0, 1.0 ] },
"east": { "texture": "#0", "uv": [ 0.0, 1.0, 4.0, 2.0 ] },
"south": { "texture": "#0", "uv": [ 5.0, 0.0, 6.0, 1.0 ] },
"west": { "texture": "#0", "uv": [ 4.0, 0.0, 8.0, 1.0 ] },
"up": { "texture": "#0", "uv": [ 11.0, 0.0, 12.0, 4.0 ] },
"down": { "texture": "#0", "uv": [ 10.0, 0.0, 11.0, 4.0 ] }
}
},
{
"name": "Border",
"from": [ 5.0, 1.0, 6.0 ],
"to": [ 6.0, 2.0, 10.0 ],
"faces": {
"north": { "texture": "#0", "uv": [ 2.0, 0.0, 3.0, 1.0 ] },
"east": { "texture": "#0", "uv": [ 0.0, 1.0, 4.0, 2.0 ] },
"south": { "texture": "#0", "uv": [ 5.0, 0.0, 6.0, 1.0 ] },
"west": { "texture": "#0", "uv": [ 4.0, 0.0, 8.0, 1.0 ] },
"up": { "texture": "#0", "uv": [ 9.0, 0.0, 10.0, 4.0 ] },
"down": { "texture": "#0", "uv": [ 10.0, 0.0, 11.0, 4.0 ] }
}
},
{
"name": "Nibble",
"from": [ 7.5, 1.0, 7.5 ],
"to": [ 8.5, 2.0, 8.5 ],
"faces": {
"north": { "texture": "#0", "uv": [ 4.0, 2.0, 6.0, 4.0 ] },
"east": { "texture": "#0", "uv": [ 6.0, 2.0, 8.0, 4.0 ] },
"south": { "texture": "#0", "uv": [ 7.0, 2.0, 9.0, 4.0 ] },
"west": { "texture": "#0", "uv": [ 8.0, 2.0, 10.0, 4.0 ] },
"up": { "texture": "#0", "uv": [ 10.0, 2.0, 12.0, 4.0 ] },
"down": { "texture": "#0", "uv": [ 7.0, 2.0, 9.0, 4.0 ] }
}
}
]
}

View File

@ -0,0 +1,21 @@
{
"parent": "block/block",
"textures": {
"0": "appliedenergistics2:blocks/sky_compass"
},
"elements": [
{
"name": "Pointer",
"from": [ 7.7, 1.0, 6 ],
"to": [ 8.2, 1.5, 8 ],
"faces": {
"north": { "texture": "#0", "uv": [ 0.0, 5.0, 16.0, 8 ] },
"east": { "texture": "#0", "uv": [ 0.0, 5.0, 16, 8 ] },
"south": { "texture": "#0", "uv": [ 0.0, 5.0, 16.0, 8 ] },
"west": { "texture": "#0", "uv": [ 0.0, 5.0, 16, 8 ] },
"up": { "texture": "#0", "uv": [ 0.0, 5.0, 16.0, 8 ] },
"down": { "texture": "#0", "uv": [ 0.0, 5.0, 16.0, 8 ] }
}
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 B