Orientation Fixes when Placing Blocks with Tile Entities

Sky Compass Rendering (no rotation yet)
This commit is contained in:
Sebastian Hartte
2020-06-03 01:19:18 +02:00
parent 58afa6539f
commit 36eb8c807e
21 changed files with 432 additions and 407 deletions
@@ -22,13 +22,14 @@ package appeng.client.render.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.annotation.Nullable;
import javax.vecmath.AxisAngle4f;
import net.minecraft.block.BlockState;
import net.minecraft.client.entity.PlayerEntitySP;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.Quaternion;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.ItemCameraTransforms;
@@ -40,20 +41,21 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
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 net.minecraftforge.client.model.data.IDynamicBakedModel;
import appeng.block.misc.BlockSkyCompass;
import appeng.hooks.CompassManager;
import appeng.hooks.CompassResult;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.data.ModelProperty;
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
/**
* 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
public class SkyCompassBakedModel implements IDynamicBakedModel
{
// Rotation is expressed as radians
public static final ModelProperty<Float> ROTATION = new ModelProperty<>();
private final IBakedModel base;
@@ -68,19 +70,15 @@ public class SkyCompassBakedModel implements IBakedModel
}
@Override
public List<BakedQuad> getQuads( @Nullable BlockState state, @Nullable Direction side, long rand )
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand, IModelData extraData )
{
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;
}
Float rotationFromData = extraData.getData(ROTATION);
if (rotationFromData != null) {
rotation = rotationFromData;
}
else if( state == null )
else
{
// This is used to render a compass pointing in a specific direction when being held in hand
rotation = this.fallbackRotation;
@@ -88,8 +86,7 @@ public class SkyCompassBakedModel implements IBakedModel
// Pre-compute the quad count to avoid list resizes
List<BakedQuad> quads = new ArrayList<>();
quads.addAll( this.base.getQuads( state, side, rand ) );
quads.addAll( this.base.getQuads( state, side, rand, extraData ) );
// We'll add the pointer as "sideless"
if( side == null )
@@ -97,17 +94,18 @@ public class SkyCompassBakedModel implements IBakedModel
// 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 ) );
matrix.mul( new Quaternion( 0, rotation, 0, false ) );
MatrixVertexTransformer transformer = new MatrixVertexTransformer( matrix );
for( BakedQuad bakedQuad : this.pointer.getQuads( state, side, rand ) )
for( BakedQuad bakedQuad : this.pointer.getQuads( state, side, rand, extraData ) )
{
UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder( bakedQuad.getFormat() );
BakedQuadBuilder builder = new BakedQuadBuilder();
transformer.setParent( builder );
transformer.setVertexFormat( builder.getVertexFormat() );
bakedQuad.pipe( transformer );
builder.setQuadOrientation( null ); // After rotation, facing a specific side cannot be guaranteed
// 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 );
@@ -129,6 +127,11 @@ public class SkyCompassBakedModel implements IBakedModel
return true;
}
@Override
public boolean func_230044_c_() {
return false;
}
@Override
public boolean isBuiltInRenderer()
{
@@ -155,13 +158,12 @@ public class SkyCompassBakedModel implements IBakedModel
* animate using the
* spinning animation.
*/
return new ItemOverrideList( Collections.emptyList() )
return new ItemOverrideList()
{
@Override
public IBakedModel handleItemState( IBakedModel originalModel, ItemStack stack, World world, LivingEntity entity )
{
if( world != null && entity instanceof PlayerEntitySP )
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;
@@ -186,38 +188,38 @@ public class SkyCompassBakedModel implements IBakedModel
{
// 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();
}
}
}
// FIXME if( pos != null )
// FIXME {
// FIXME CompassResult cr = CompassManager.INSTANCE.getCompassDirection( 0, pos.getX(), pos.getY(), pos.getZ() );
// FIXME
// FIXME // Prefetch meteor positions from the server for adjacent blocks so they are available more quickly when
// FIXME // we're moving
// FIXME if( prefetch )
// FIXME {
// FIXME for( int i = 0; i < 3; i++ )
// FIXME {
// FIXME for( int j = 0; j < 3; j++ )
// FIXME {
// FIXME CompassManager.INSTANCE.getCompassDirection( 0, pos.getX() + i - 1, pos.getY(), pos.getZ() + j - 1 );
// FIXME }
// FIXME }
// FIXME }
// FIXME
// FIXME if( cr.isValidResult() )
// FIXME {
// FIXME if( cr.isSpin() )
// FIXME {
// FIXME long timeMillis = System.currentTimeMillis();
// FIXME // .5 seconds per full rotation
// FIXME timeMillis %= 500;
// FIXME return timeMillis / 500.f * (float) Math.PI * 2;
// FIXME }
// FIXME else
// FIXME {
// FIXME return (float) cr.getRad();
// FIXME }
// FIXME }
// FIXME }
long timeMillis = System.currentTimeMillis();
// 3 seconds per full rotation