diff --git a/src/main/java/appeng/block/AEBaseBlock.java b/src/main/java/appeng/block/AEBaseBlock.java index 120991c6b..8d21cb2f5 100644 --- a/src/main/java/appeng/block/AEBaseBlock.java +++ b/src/main/java/appeng/block/AEBaseBlock.java @@ -21,6 +21,7 @@ package appeng.block; import javax.annotation.Nullable; +import appeng.util.Platform; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; @@ -234,17 +235,18 @@ public abstract class AEBaseBlock extends Block return 0; } - @Override - public BlockState rotate(BlockState state, IWorld w, BlockPos pos, Rotation direction) { + /** + * Rotates around the given Axis (usually the current up axis). + */ + public boolean rotateAroundFaceAxis(IWorld w, BlockPos pos, Direction face) { final IOrientable rotatable = this.getOrientable( w, pos ); if( rotatable != null && rotatable.canBeRotated() ) { if( this.hasCustomRotation() ) { - // FIXME this.customRotateBlock( rotatable, axis ); - // FIXME return true; - throw new IllegalStateException(); + this.customRotateBlock( rotatable, face ); + return true; } else { @@ -253,26 +255,19 @@ public abstract class AEBaseBlock extends Block for( int rs = 0; rs < 4; rs++ ) { - // FIXME forward = Platform.rotateAround( forward, axis ); - // FIXME up = Platform.rotateAround( up, axis ); + forward = Platform.rotateAround( forward, face ); + up = Platform.rotateAround( up, face ); if( this.isValidOrientation( w, pos, forward, up ) ) { rotatable.setOrientation( forward, up ); - // FIXME - throw new IllegalStateException(); + return true; } } } } - return state; - } - - @Override - public Direction[] getValidRotations(BlockState state, IBlockReader world, BlockPos pos) - { - return new Direction[0]; + return false; } public ActionResultType onActivated(final World w, final BlockPos pos, final PlayerEntity player, final Hand hand, final @Nullable ItemStack heldItem, final BlockRayTraceResult hit) diff --git a/src/main/java/appeng/block/AEBaseTileBlock.java b/src/main/java/appeng/block/AEBaseTileBlock.java index 568d875ee..ceb3d83bd 100644 --- a/src/main/java/appeng/block/AEBaseTileBlock.java +++ b/src/main/java/appeng/block/AEBaseTileBlock.java @@ -26,6 +26,7 @@ import java.util.function.Supplier; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import appeng.client.render.FacingToRotation; import com.google.common.collect.Lists; import net.minecraft.block.Block; @@ -33,12 +34,16 @@ import net.minecraft.block.BlockState; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.DyeColor; +import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.state.EnumProperty; +import net.minecraft.state.StateContainer; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ActionResultType; import net.minecraft.util.Direction; import net.minecraft.util.Hand; +import net.minecraft.util.NonNullList; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.world.IBlockReader; @@ -152,18 +157,6 @@ public abstract class AEBaseTileBlock extends AEBaseBlock super.onReplaced( state, w, pos, newState, isMoving ); } - @Override - public Direction[] getValidRotations(BlockState state, IBlockReader world, BlockPos pos) - { - final AEBaseTile obj = this.getTileEntity( world, pos ); - if( obj != null && obj.canBeRotated() ) - { - return Direction.values(); - } - - return super.getValidRotations( state, world, pos ); - } - @Override public boolean recolorBlock( BlockState state, final IWorld world, final BlockPos pos, final Direction side, final DyeColor color ) { diff --git a/src/main/java/appeng/client/render/model/AutoRotatingBakedModel.java b/src/main/java/appeng/client/render/model/AutoRotatingBakedModel.java index 30228e35f..0aa21e9c7 100644 --- a/src/main/java/appeng/client/render/model/AutoRotatingBakedModel.java +++ b/src/main/java/appeng/client/render/model/AutoRotatingBakedModel.java @@ -19,29 +19,35 @@ package appeng.client.render.model; -import java.util.List; -import java.util.Random; - -import appeng.client.render.cablebus.QuadRotator; +import appeng.block.AEBaseTileBlock; +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; import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.model.ItemCameraTransforms; import net.minecraft.client.renderer.model.ItemOverrideList; 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.Direction; +import net.minecraft.util.math.Vec3i; import net.minecraftforge.client.model.data.EmptyModelData; import net.minecraftforge.client.model.data.IModelData; - -import appeng.block.AEBaseTileBlock; -import appeng.client.render.FacingToRotation; +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; public class AutoRotatingBakedModel implements IBakedModel @@ -67,8 +73,37 @@ public class AutoRotatingBakedModel implements IBakedModel private List getRotatedModel( BlockState state, Direction side, Direction forward, Direction up ) { FacingToRotation f2r = FacingToRotation.get( forward, up ); - List original = AutoRotatingBakedModel.this.parent.getQuads( state, f2r.resultingRotate( side ), new Random(0), EmptyModelData.INSTANCE ); - return new QuadRotator().rotateQuads(original, forward, up); + List original = AutoRotatingBakedModel.this.parent.getQuads( state, f2r.resultingRotate( side ), new Random(0) ); + List 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(); + + // 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 @@ -137,4 +172,162 @@ public class AutoRotatingBakedModel implements IBakedModel } + 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; + } + + @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 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] ); + } + } + } + } + + 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; + } + } + + 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; + } + } + } + + @Override + public void setQuadTint( int tint ) + { + this.parent.setQuadTint( tint ); + } + + @Override + public void setQuadOrientation( Direction orientation ) + { + this.parent.setQuadOrientation( orientation ); + } + + @Override + public void setApplyDiffuseLighting( boolean diffuse ) + { + this.parent.setApplyDiffuseLighting( diffuse ); + } + + @Override + public void setTexture( TextureAtlasSprite texture ) + { + this.parent.setTexture( texture ); + } + } } diff --git a/src/main/java/appeng/core/AppEng.java b/src/main/java/appeng/core/AppEng.java index 9e1fd9722..7f2b5133d 100644 --- a/src/main/java/appeng/core/AppEng.java +++ b/src/main/java/appeng/core/AppEng.java @@ -20,6 +20,8 @@ package appeng.core; import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import appeng.bootstrap.components.IClientSetupComponent; import appeng.client.ClientHelper; @@ -29,7 +31,10 @@ import appeng.client.render.model.GlassModelLoader; import appeng.client.render.model.SkyCompassModelLoader; import appeng.core.stats.AdvancementTriggers; import appeng.server.ServerHelper; +import com.google.gson.Gson; import net.minecraft.block.Block; +import net.minecraft.client.renderer.model.BlockModelDefinition; +import net.minecraft.client.renderer.model.ModelBakery; import net.minecraft.entity.EntityType; import net.minecraft.inventory.container.ContainerType; import net.minecraft.item.Item; @@ -46,6 +51,7 @@ import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.ObfuscationReflectionHelper; import net.minecraftforge.fml.config.ModConfig; import appeng.core.crash.ModCrashEnhancement; diff --git a/src/main/java/appeng/core/api/definitions/ApiBlocks.java b/src/main/java/appeng/core/api/definitions/ApiBlocks.java index 564b2e5fa..847865c20 100644 --- a/src/main/java/appeng/core/api/definitions/ApiBlocks.java +++ b/src/main/java/appeng/core/api/definitions/ApiBlocks.java @@ -51,6 +51,7 @@ import appeng.core.features.registries.PartModels; import appeng.debug.*; import appeng.decorative.AEDecorativeBlock; import appeng.decorative.solid.*; +import appeng.entity.EntityTinyTNTPrimed; import appeng.fluids.block.BlockFluidInterface; import appeng.fluids.tile.TileFluidInterface; import appeng.hooks.DispenserBehaviorTinyTNT; @@ -72,6 +73,8 @@ import appeng.tile.storage.TileSkyChest; import net.minecraft.block.*; import net.minecraft.block.material.Material; import net.minecraft.client.renderer.RenderType; +import net.minecraft.entity.EntityClassification; +import net.minecraft.entity.EntityType; import net.minecraft.util.ResourceLocation; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -279,7 +282,7 @@ public final class ApiBlocks implements IBlocks }) .build() ) .build(); - this.inscriber = registry.block( "inscriber", () -> new BlockInscriber(Block.Properties.create(Material.IRON)) ) + this.inscriber = registry.block( "inscriber", () -> new BlockInscriber(Block.Properties.create(Material.IRON).notSolid()) ) .features( AEFeature.INSCRIBER ) .tileEntity( registry.tileEntity("inscriber", TileInscriber.class, TileInscriber::new) .rendering(new InscriberRendering()) @@ -310,13 +313,13 @@ public final class ApiBlocks implements IBlocks new DispenserBehaviorTinyTNT() ) ) .bootstrap( ( block, item ) -> (IEntityRegistrationComponent) r -> { -// FIXME r.register( EntityEntryBuilder.create() -// FIXME .entity( EntityTinyTNTPrimed.class ) -// FIXME .id( new ResourceLocation( "appliedenergistics2", EntityTinyTNTPrimed.class.getName() ), -// FIXME EntityIds.get( EntityTinyTNTPrimed.class ) ) -// FIXME .name( "EntityTinyTNTPrimed" ) -// FIXME .tracker( 16, 4, true ) -// FIXME .build() ); + r.register(EntityType.Builder.create(EntityTinyTNTPrimed::new, EntityClassification.MISC) + .setTrackingRange(16) + .setUpdateInterval(4) + .setShouldReceiveVelocityUpdates(true) + .build(AppEng.MOD_ID + ":tiny_tnt_primed") + .setRegistryName(AppEng.MOD_ID + ":tiny_tnt_primed") + ); } ) .build(); this.securityStation = registry.block( "security_station", BlockSecurityStation::new ) diff --git a/src/main/java/appeng/entity/EntityTinyTNTPrimed.java b/src/main/java/appeng/entity/EntityTinyTNTPrimed.java index ee99551d4..292a0d76a 100644 --- a/src/main/java/appeng/entity/EntityTinyTNTPrimed.java +++ b/src/main/java/appeng/entity/EntityTinyTNTPrimed.java @@ -54,8 +54,7 @@ import appeng.util.Platform; public final class EntityTinyTNTPrimed extends TNTEntity implements IEntityAdditionalSpawnData { - @Reflected - public EntityTinyTNTPrimed( EntityType type, World worldIn ) + public EntityTinyTNTPrimed( EntityType type, World worldIn ) { super( type, worldIn ); this.preventEntitySpawning = true; diff --git a/src/main/java/appeng/items/tools/quartz/ToolQuartzWrench.java b/src/main/java/appeng/items/tools/quartz/ToolQuartzWrench.java index f27e746f6..c4aea7bbe 100644 --- a/src/main/java/appeng/items/tools/quartz/ToolQuartzWrench.java +++ b/src/main/java/appeng/items/tools/quartz/ToolQuartzWrench.java @@ -19,22 +19,19 @@ package appeng.items.tools.quartz; -import appeng.core.CreativeTab; +import appeng.api.implementations.items.IAEWrench; +import appeng.api.util.DimensionalCoord; +import appeng.block.AEBaseBlock; +import appeng.items.AEBaseItem; +import appeng.util.Platform; import net.minecraft.block.Block; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; -import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUseContext; import net.minecraft.util.ActionResultType; -import net.minecraft.util.Rotation; import net.minecraft.util.math.BlockPos; -import appeng.api.implementations.items.IAEWrench; -import appeng.api.util.DimensionalCoord; -import appeng.items.AEBaseItem; -import appeng.util.Platform; - public class ToolQuartzWrench extends AEBaseItem implements IAEWrench { @@ -45,22 +42,24 @@ public class ToolQuartzWrench extends AEBaseItem implements IAEWrench } @Override - public ActionResultType onItemUse( ItemUseContext context ) - { - final Block b = context.getWorld().getBlockState( context.getPos() ).getBlock(); + public ActionResultType onItemUseFirst(ItemStack stack, ItemUseContext context) { if( !context.getPlayer().isCrouching() && Platform.hasPermissions( new DimensionalCoord( context.getWorld(), context.getPos() ), context.getPlayer() ) ) { - if( Platform.isClient() ) - { - // TODO 1.10-R - if we return FAIL on client, action will not be sent to server. Fix that in all Block#onItemUseFirst overrides. - return !context.getWorld().isRemote ? ActionResultType.SUCCESS : ActionResultType.PASS; - } - if( b.rotate( context.getWorld().getBlockState( context.getPos() ), context.getWorld(), context.getPos(), Rotation.CLOCKWISE_90 ) != null ) - { - context.getPlayer().swingArm( context.getHand() ); - return !context.getWorld().isRemote ? ActionResultType.SUCCESS : ActionResultType.FAIL; + Block block = context.getWorld().getBlockState(context.getPos()).getBlock(); + if (block instanceof AEBaseBlock) { + if( Platform.isClient() ) + { + // TODO 1.10-R - if we return FAIL on client, action will not be sent to server. Fix that in all Block#onItemUseFirst overrides. + return !context.getWorld().isRemote ? ActionResultType.SUCCESS : ActionResultType.PASS; + } + + AEBaseBlock aeBlock = (AEBaseBlock) block; + if (aeBlock.rotateAroundFaceAxis(context.getWorld(), context.getPos(), context.getFace())) { + context.getPlayer().swingArm(context.getHand()); + return !context.getWorld().isRemote ? ActionResultType.SUCCESS : ActionResultType.FAIL; + } } } return ActionResultType.PASS; diff --git a/src/main/java/appeng/tile/AEBaseTile.java b/src/main/java/appeng/tile/AEBaseTile.java index c9a297235..6629e1401 100644 --- a/src/main/java/appeng/tile/AEBaseTile.java +++ b/src/main/java/appeng/tile/AEBaseTile.java @@ -24,12 +24,14 @@ import appeng.api.util.IConfigManager; import appeng.api.util.IConfigurableObject; import appeng.api.util.IOrientable; import appeng.block.AEBaseTileBlock; +import appeng.client.render.FacingToRotation; import appeng.core.AELog; import appeng.core.features.IStackSrc; import appeng.helpers.ICustomNameObject; import appeng.util.Platform; import appeng.util.SettingsFrom; import io.netty.buffer.Unpooled; +import net.minecraft.block.BlockState; import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; @@ -63,8 +65,8 @@ public class AEBaseTile extends TileEntity implements IOrientable, ICommonTile, private int renderFragment = 0; @Nullable private String customName; - private Direction forward = null; - private Direction up = null; + private Direction forward = Direction.NORTH; + private Direction up = Direction.UP; private boolean markDirtyQueued = false; public AEBaseTile(TileEntityType tileEntityTypeIn) { @@ -293,6 +295,7 @@ public class AEBaseTile extends TileEntity implements IOrientable, ICommonTile, { AELog.blockUpdate( this.pos, this ); this.world.notifyBlockUpdate( this.pos, this.getBlockState(), this.getBlockState(), 3 ); + this.requestModelDataUpdate(); } } } @@ -311,20 +314,12 @@ public class AEBaseTile extends TileEntity implements IOrientable, ICommonTile, @Override public Direction getForward() { - if( this.forward == null ) - { - return Direction.NORTH; - } return this.forward; } @Override public Direction getUp() { - if( this.up == null ) - { - return Direction.UP; - } return this.up; } diff --git a/src/main/java/appeng/util/Platform.java b/src/main/java/appeng/util/Platform.java index ef5dc54c4..93f22b604 100644 --- a/src/main/java/appeng/util/Platform.java +++ b/src/main/java/appeng/util/Platform.java @@ -50,6 +50,7 @@ import appeng.core.AELog; import appeng.core.Api; import appeng.core.stats.AeStats; import appeng.fluids.util.AEFluidStack; +import appeng.hooks.TickHandler; import appeng.me.GridAccessException; import appeng.me.GridNode; import appeng.me.helpers.AENetworkProxy; @@ -1476,7 +1477,7 @@ public class Platform { if( !world.isRemote ) { -// FIXME TickHandler.INSTANCE.addCallable( world, new BlockUpdate( pos ) ); + TickHandler.INSTANCE.addCallable( world, new BlockUpdate( pos ) ); } }