1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-08-30 00:57:55 +00:00

fix: turtle upgrades item render

This commit is contained in:
Nikita Savyolov
2021-10-08 18:31:07 +03:00
parent d787c6e6c1
commit f3b731460e
10 changed files with 181 additions and 140 deletions

View File

@@ -5,15 +5,14 @@
*/
package dan200.computercraft.client.render;
import dan200.computercraft.fabric.mixin.BakedQuadAccess;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.client.render.VertexFormatElement;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.util.math.Vector4f;
import net.minecraft.util.math.Matrix4f;
import net.minecraft.util.math.Vector4f;
import java.util.List;
@@ -58,28 +57,41 @@ public final class ModelTransformer
private static BakedQuad doTransformQuad( VertexFormat format, BakedQuad quad, Matrix4f transform )
{
int[] vertexData = quad.getVertexData().clone();
BakedQuad copy = new BakedQuad( vertexData, -1, quad.getFace(), ((BakedQuadAccess) quad).getSprite(), true );
BakedQuad copy = new BakedQuad( vertexData, -1, quad.getFace(), quad.getSprite(), true );
int offsetBytes = 0;
for( int v = 0; v < 4; ++v )
{
for( VertexFormatElement element : format.getElements() ) // For each vertex element
{
int start = offsetBytes / Integer.BYTES;
if( element.getType() == VertexFormatElement.Type.POSITION && element.getDataType() == VertexFormatElement.DataType.FLOAT ) // When we find a position element
if( element.isPosition() &&
element.getDataType() == VertexFormatElement.DataType.FLOAT &&
element.getLength() == 3 ) // When we find a position element
{
Vector4f pos = new Vector4f( Float.intBitsToFloat( vertexData[start] ),
Float.intBitsToFloat( vertexData[start + 1] ),
Float.intBitsToFloat( vertexData[start + 2] ),
1 );
for ( int j = 0; j < 4; ++j ) // For each corner of the quad
{
int start = offsetBytes + j * format.getVertexSize();
if ( (start % 4) == 0 )
{
start = start / 4;
// Transform the position
pos.transform( transform );
// Extract the position
Vector4f pos = new Vector4f(
Float.intBitsToFloat( vertexData[start] ),
Float.intBitsToFloat( vertexData[start + 1] ),
Float.intBitsToFloat( vertexData[start + 2] ),
1
);
// Insert the position
vertexData[start] = Float.floatToRawIntBits( pos.getX() );
vertexData[start + 1] = Float.floatToRawIntBits( pos.getY() );
vertexData[start + 2] = Float.floatToRawIntBits( pos.getZ() );
// Transform the position
pos.transform( transform );
// Insert the position
vertexData[start] = Float.floatToRawIntBits( pos.getX() );
vertexData[start + 1] = Float.floatToRawIntBits( pos.getY() );
vertexData[start + 2] = Float.floatToRawIntBits( pos.getZ() );
}
}
}
offsetBytes += element.getLength();
}

View File

@@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.render;
import dan200.computercraft.api.client.TransformedModel;
@@ -148,7 +147,7 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
transform.pop();
}
public void renderUpgrade( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, TileTurtle turtle,
private void renderUpgrade( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, TileTurtle turtle,
TurtleSide side, float f )
{
ITurtleUpgrade upgrade = turtle.getUpgrade( side );
@@ -171,7 +170,7 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
transform.pop();
}
public void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight,
private void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight,
ModelIdentifier modelLocation, int[] tints )
{
BakedModelManager modelManager = MinecraftClient.getInstance()
@@ -181,7 +180,7 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
renderModel( transform, renderer, lightmapCoord, overlayLight, modelManager.getModel( modelLocation ), tints );
}
public void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, BakedModel model,
private void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, BakedModel model,
int[] tints )
{
random.setSeed( 0 );

View File

@@ -30,7 +30,7 @@ public class TurtleMultiModel implements BakedModel
private final TransformedModel leftUpgradeModel;
private final TransformedModel rightUpgradeModel;
private List<BakedQuad> generalQuads = null;
private Map<Direction, List<BakedQuad>> faceQuads = new EnumMap<>( Direction.class );
private final Map<Direction, List<BakedQuad>> faceQuads = new EnumMap<>( Direction.class );
public TurtleMultiModel( BakedModel baseModel, BakedModel overlayModel, AffineTransformation generalTransform, TransformedModel leftUpgradeModel,
TransformedModel rightUpgradeModel )
@@ -117,6 +117,7 @@ public class TurtleMultiModel implements BakedModel
return baseModel.isBuiltin();
}
@Nonnull
@Override
@Deprecated
public Sprite getParticleSprite()
@@ -124,14 +125,6 @@ public class TurtleMultiModel implements BakedModel
return baseModel.getParticleSprite();
}
// @Nonnull
// @Override
// @Deprecated
// public Sprite getSprite()
// {
// return baseModel.getSprite();
// }
@Nonnull
@Override
@Deprecated

View File

@@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.render;
import com.google.common.base.Objects;
@@ -55,8 +54,60 @@ public class TurtleSmartItemModel implements BakedModel
.getModel() );
}
private static class TurtleModelCombination
{
final boolean colour;
final ITurtleUpgrade leftUpgrade;
final ITurtleUpgrade rightUpgrade;
final Identifier overlay;
final boolean christmas;
final boolean flip;
TurtleModelCombination( boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, Identifier overlay, boolean christmas,
boolean flip )
{
this.colour = colour;
this.leftUpgrade = leftUpgrade;
this.rightUpgrade = rightUpgrade;
this.overlay = overlay;
this.christmas = christmas;
this.flip = flip;
}
@Override
public boolean equals( Object other )
{
if( other == this )
{
return true;
}
if( !(other instanceof TurtleModelCombination otherCombo) )
{
return false;
}
return otherCombo.colour == colour && otherCombo.leftUpgrade == leftUpgrade && otherCombo.rightUpgrade == rightUpgrade && Objects.equal(
otherCombo.overlay, overlay ) && otherCombo.christmas == christmas && otherCombo.flip == flip;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 0;
result = prime * result + (colour ? 1 : 0);
result = prime * result + (leftUpgrade != null ? leftUpgrade.hashCode() : 0);
result = prime * result + (rightUpgrade != null ? rightUpgrade.hashCode() : 0);
result = prime * result + (overlay != null ? overlay.hashCode() : 0);
result = prime * result + (christmas ? 1 : 0);
result = prime * result + (flip ? 1 : 0);
return result;
}
}
private final BakedModel familyModel;
private final BakedModel colourModel;
private final HashMap<TurtleModelCombination, BakedModel> cachedModels = new HashMap<>();
private final ModelOverrideList overrides;
@@ -79,9 +130,7 @@ public class TurtleSmartItemModel implements BakedModel
Identifier overlay = turtle.getOverlay( stack );
boolean christmas = HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS;
String label = turtle.getLabel( stack );
// TODO make upside down turtle items render properly (currently inivisible)
//boolean flip = label != null && (label.equals("Dinnerbone") || label.equals("Grumm"));
boolean flip = false;
boolean flip = label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" ));
TurtleModelCombination combo = new TurtleModelCombination( colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip );
BakedModel model = cachedModels.get( combo );
@@ -149,13 +198,12 @@ public class TurtleSmartItemModel implements BakedModel
return familyModel.getParticleSprite();
}
// @Nonnull
// @Override
// @Deprecated
// public Sprite getSprite()
// {
// return familyModel.getSprite();
// }
@Nonnull
@Override
public ModelOverrideList getOverrides()
{
return overrides;
}
@Nonnull
@Override
@@ -165,63 +213,4 @@ public class TurtleSmartItemModel implements BakedModel
return familyModel.getTransformation();
}
@Nonnull
@Override
public ModelOverrideList getOverrides()
{
return overrides;
}
private static class TurtleModelCombination
{
final boolean colour;
final ITurtleUpgrade leftUpgrade;
final ITurtleUpgrade rightUpgrade;
final Identifier overlay;
final boolean christmas;
final boolean flip;
TurtleModelCombination( boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, Identifier overlay, boolean christmas,
boolean flip )
{
this.colour = colour;
this.leftUpgrade = leftUpgrade;
this.rightUpgrade = rightUpgrade;
this.overlay = overlay;
this.christmas = christmas;
this.flip = flip;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 0;
result = prime * result + (colour ? 1 : 0);
result = prime * result + (leftUpgrade != null ? leftUpgrade.hashCode() : 0);
result = prime * result + (rightUpgrade != null ? rightUpgrade.hashCode() : 0);
result = prime * result + (overlay != null ? overlay.hashCode() : 0);
result = prime * result + (christmas ? 1 : 0);
result = prime * result + (flip ? 1 : 0);
return result;
}
@Override
public boolean equals( Object other )
{
if( other == this )
{
return true;
}
if( !(other instanceof TurtleModelCombination) )
{
return false;
}
TurtleModelCombination otherCombo = (TurtleModelCombination) other;
return otherCombo.colour == colour && otherCombo.leftUpgrade == leftUpgrade && otherCombo.rightUpgrade == rightUpgrade && Objects.equal(
otherCombo.overlay, overlay ) && otherCombo.christmas == christmas && otherCombo.flip == flip;
}
}
}

View File

@@ -1,18 +0,0 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.fabric.mixin;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.texture.Sprite;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin( BakedQuad.class )
public interface BakedQuadAccess
{
@Accessor
Sprite getSprite();
}

View File

@@ -0,0 +1,52 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.fabric.mixin;
import dan200.computercraft.fabric.mixininterface.IMatrix4f;
import net.minecraft.util.math.Matrix4f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin( Matrix4f.class )
public class MixinMatrix4f implements IMatrix4f
{
@Shadow protected float a00;
@Shadow protected float a01;
@Shadow protected float a02;
@Shadow protected float a03;
@Shadow protected float a10;
@Shadow protected float a11;
@Shadow protected float a12;
@Shadow protected float a13;
@Shadow protected float a20;
@Shadow protected float a21;
@Shadow protected float a22;
@Shadow protected float a23;
@Shadow protected float a30;
@Shadow protected float a31;
@Shadow protected float a32;
@Shadow protected float a33;
public void setFloatArray( float[] values )
{
a00 = values[0];
a01 = values[1];
a02 = values[2];
a03 = values[3];
a10 = values[4];
a11 = values[5];
a12 = values[6];
a13 = values[7];
a20 = values[8];
a21 = values[9];
a22 = values[10];
a23 = values[11];
a30 = values[12];
a31 = values[13];
a32 = values[14];
a33 = values[15];
}
}

View File

@@ -0,0 +1,11 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.fabric.mixininterface;
public interface IMatrix4f
{
void setFloatArray( float[] values );
}

View File

@@ -3,12 +3,8 @@
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared;
import com.google.common.eventbus.Subscribe;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.turtle.event.TurtleActionEvent;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.world.ServerWorld;
@@ -17,23 +13,14 @@ import net.minecraft.world.World;
public final class TurtlePermissions
{
public static boolean isBlockEditable( World world, BlockPos pos, PlayerEntity player )
{
return isBlockEnterable( world, pos, player );
}
public static boolean isBlockEnterable( World world, BlockPos pos, PlayerEntity player )
{
MinecraftServer server = world.getServer();
return server == null || world.isClient || world instanceof ServerWorld && !server.isSpawnProtected( (ServerWorld) world, pos, player );
}
@Subscribe
public void onTurtleAction( TurtleActionEvent event )
public static boolean isBlockEditable( World world, BlockPos pos, PlayerEntity player )
{
if( ComputerCraft.turtleDisabledActions.contains( event.getAction() ) )
{
event.setCanceled( true, "Action has been disabled" );
}
return isBlockEnterable( world, pos, player );
}
}

View File

@@ -12,6 +12,8 @@ import dan200.computercraft.api.turtle.*;
import dan200.computercraft.api.turtle.event.TurtleAttackEvent;
import dan200.computercraft.api.turtle.event.TurtleBlockEvent;
import dan200.computercraft.api.turtle.event.TurtleEvent;
import dan200.computercraft.fabric.mixin.MixinMatrix4f;
import dan200.computercraft.fabric.mixininterface.IMatrix4f;
import dan200.computercraft.shared.TurtlePermissions;
import dan200.computercraft.shared.turtle.core.TurtleBrain;
import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand;
@@ -26,8 +28,8 @@ import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.util.math.AffineTransformation;
import net.minecraft.util.math.Vec3f;
import net.minecraft.client.render.model.json.Transformation;
import net.minecraft.util.math.*;
import net.minecraft.entity.Entity;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.damage.DamageSource;
@@ -38,9 +40,6 @@ import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import org.apache.commons.lang3.tuple.Pair;
@@ -106,8 +105,7 @@ public class TurtleTool extends AbstractTurtleUpgrade
@Environment( EnvType.CLIENT )
public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side )
{
float xOffset = side == TurtleSide.LEFT ? -0.40625f : 0.40625f;
return TransformedModel.of( getCraftingItem(), new AffineTransformation( new Vec3f( xOffset + 1, 0, 1 ), Vec3f.POSITIVE_Y.getDegreesQuaternion( 270 ), new Vec3f( 1, 1, 1 ), Vec3f.POSITIVE_Z.getDegreesQuaternion( 90 ) ) );
return TransformedModel.of( getCraftingItem(), side == TurtleSide.LEFT ? Transforms.leftTransform : Transforms.rightTransform );
}
private TurtleCommandResult attack( ITurtleAccess turtle, Direction direction, TurtleSide side )
@@ -296,4 +294,22 @@ public class TurtleTool extends AbstractTurtleUpgrade
Block block = state.getBlock();
return !state.isAir() && block != Blocks.BEDROCK && state.calcBlockBreakingDelta( player, world, pos ) > 0;
}
private static class Transforms
{
static final AffineTransformation leftTransform = getMatrixFor( -0.40625f );
static final AffineTransformation rightTransform = getMatrixFor( 0.40625f );
private static AffineTransformation getMatrixFor( float offset )
{
Matrix4f matrix = new Matrix4f();
((IMatrix4f) (Object) matrix).setFloatArray( new float[] {
0.0f, 0.0f, -1.0f, 1.0f + offset,
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f,
} );
return new AffineTransformation( matrix );
}
}
}

View File

@@ -14,11 +14,11 @@
"WorldSavePathAccess",
"MixinServerPlayerInteractionManager",
"MusicDiscItemAccessor",
"GameRendererMixin"
"GameRendererMixin",
"MixinMatrix4f"
],
"client": [
"AffineTransformationAccess",
"BakedQuadAccess",
"ChatHudAccess",
"HeldItemRendererAccess",
"MixinHeldItemRenderer",