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

View File

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

View File

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

View File

@@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com * Send enquiries to dratcliffe@gmail.com
*/ */
package dan200.computercraft.client.render; package dan200.computercraft.client.render;
import com.google.common.base.Objects; import com.google.common.base.Objects;
@@ -55,8 +54,60 @@ public class TurtleSmartItemModel implements BakedModel
.getModel() ); .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 familyModel;
private final BakedModel colourModel; private final BakedModel colourModel;
private final HashMap<TurtleModelCombination, BakedModel> cachedModels = new HashMap<>(); private final HashMap<TurtleModelCombination, BakedModel> cachedModels = new HashMap<>();
private final ModelOverrideList overrides; private final ModelOverrideList overrides;
@@ -79,9 +130,7 @@ public class TurtleSmartItemModel implements BakedModel
Identifier overlay = turtle.getOverlay( stack ); Identifier overlay = turtle.getOverlay( stack );
boolean christmas = HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS; boolean christmas = HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS;
String label = turtle.getLabel( stack ); 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 = label != null && (label.equals("Dinnerbone") || label.equals("Grumm"));
boolean flip = false;
TurtleModelCombination combo = new TurtleModelCombination( colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip ); TurtleModelCombination combo = new TurtleModelCombination( colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip );
BakedModel model = cachedModels.get( combo ); BakedModel model = cachedModels.get( combo );
@@ -149,13 +198,12 @@ public class TurtleSmartItemModel implements BakedModel
return familyModel.getParticleSprite(); return familyModel.getParticleSprite();
} }
// @Nonnull @Nonnull
// @Override @Override
// @Deprecated public ModelOverrideList getOverrides()
// public Sprite getSprite() {
// { return overrides;
// return familyModel.getSprite(); }
// }
@Nonnull @Nonnull
@Override @Override
@@ -165,63 +213,4 @@ public class TurtleSmartItemModel implements BakedModel
return familyModel.getTransformation(); 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. * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com * Send enquiries to dratcliffe@gmail.com
*/ */
package dan200.computercraft.shared; 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.entity.player.PlayerEntity;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
@@ -17,23 +13,14 @@ import net.minecraft.world.World;
public final class TurtlePermissions 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 ) public static boolean isBlockEnterable( World world, BlockPos pos, PlayerEntity player )
{ {
MinecraftServer server = world.getServer(); MinecraftServer server = world.getServer();
return server == null || world.isClient || world instanceof ServerWorld && !server.isSpawnProtected( (ServerWorld) world, pos, player ); return server == null || world.isClient || world instanceof ServerWorld && !server.isSpawnProtected( (ServerWorld) world, pos, player );
} }
@Subscribe public static boolean isBlockEditable( World world, BlockPos pos, PlayerEntity player )
public void onTurtleAction( TurtleActionEvent event )
{ {
if( ComputerCraft.turtleDisabledActions.contains( event.getAction() ) ) return isBlockEnterable( world, pos, player );
{
event.setCanceled( true, "Action has been disabled" );
}
} }
} }

View File

@@ -12,6 +12,8 @@ import dan200.computercraft.api.turtle.*;
import dan200.computercraft.api.turtle.event.TurtleAttackEvent; import dan200.computercraft.api.turtle.event.TurtleAttackEvent;
import dan200.computercraft.api.turtle.event.TurtleBlockEvent; import dan200.computercraft.api.turtle.event.TurtleBlockEvent;
import dan200.computercraft.api.turtle.event.TurtleEvent; 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.TurtlePermissions;
import dan200.computercraft.shared.turtle.core.TurtleBrain; import dan200.computercraft.shared.turtle.core.TurtleBrain;
import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand; 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.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntity;
import net.minecraft.util.math.AffineTransformation; import net.minecraft.client.render.model.json.Transformation;
import net.minecraft.util.math.Vec3f; import net.minecraft.util.math.*;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.damage.DamageSource;
@@ -38,9 +40,6 @@ import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.Identifier; 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 net.minecraft.world.World;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
@@ -106,8 +105,7 @@ public class TurtleTool extends AbstractTurtleUpgrade
@Environment( EnvType.CLIENT ) @Environment( EnvType.CLIENT )
public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side )
{ {
float xOffset = side == TurtleSide.LEFT ? -0.40625f : 0.40625f; return TransformedModel.of( getCraftingItem(), side == TurtleSide.LEFT ? Transforms.leftTransform : Transforms.rightTransform );
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 ) ) );
} }
private TurtleCommandResult attack( ITurtleAccess turtle, Direction direction, TurtleSide side ) private TurtleCommandResult attack( ITurtleAccess turtle, Direction direction, TurtleSide side )
@@ -296,4 +294,22 @@ public class TurtleTool extends AbstractTurtleUpgrade
Block block = state.getBlock(); Block block = state.getBlock();
return !state.isAir() && block != Blocks.BEDROCK && state.calcBlockBreakingDelta( player, world, pos ) > 0; 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", "WorldSavePathAccess",
"MixinServerPlayerInteractionManager", "MixinServerPlayerInteractionManager",
"MusicDiscItemAccessor", "MusicDiscItemAccessor",
"GameRendererMixin" "GameRendererMixin",
"MixinMatrix4f"
], ],
"client": [ "client": [
"AffineTransformationAccess", "AffineTransformationAccess",
"BakedQuadAccess",
"ChatHudAccess", "ChatHudAccess",
"HeldItemRendererAccess", "HeldItemRendererAccess",
"MixinHeldItemRenderer", "MixinHeldItemRenderer",