From 8c793b8d28946cc65d56ad9f3ca4ca36be8a5f91 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Tue, 10 Mar 2020 16:34:04 +0100 Subject: [PATCH] Portable Belts - Belts can now be moved and rotated by a contraption, holding on to its items if possible. - Fixed belts not transporting entities when moving at less than 32 rpm - Fixed belt initialization to allow migration old belts and re-initialization of moved belts - Added a little in-world tooltip for kinetic blocks rotating below their required speed level - Fixed kinetic tileentities keeping their previous speed when animated in a contraption - Fixed motors not trying to overpower a network when directly attached on placement - Belts now spawn a reasonable amount of particles when broken - Coloured belts now spawn coloured particles when broken - Fixed belts segments dropping too many connectors when not broken by a player - Fixed falldamage being applied after an entity has left the belt it fell upon - Fixed belt voxelshapes not being cached properly, leading to some bad performance hit when broken or looked at - Fixed blazing tools not always smelting mob drops --- .../foundation/item/AbstractToolItem.java | 4 +- .../create/foundation/utility/Iterate.java | 21 ++ .../contraptions/BlockMovementTraits.java | 2 + .../components/contraptions/Contraption.java | 48 ++- .../contraptions/StructureTransform.java | 47 ++- .../deployer/DeployerFakePlayer.java | 3 +- .../components/motor/MotorTileEntity.java | 2 +- .../contraptions/relays/belt/BeltBlock.java | 294 +++++++++++++----- .../relays/belt/BeltConnectorItem.java | 10 - .../relays/belt/BeltInventory.java | 27 +- .../relays/belt/BeltMovementHandler.java | 4 +- .../contraptions/relays/belt/BeltShapes.java | 24 +- .../relays/belt/BeltTileEntity.java | 34 +- .../relays/belt/BeltTileEntityRenderer.java | 177 +++++------ .../gauge/GaugeInformationRenderer.java | 33 +- .../curiosities/tools/BlazingToolItem.java | 7 +- .../tools/ShadowSteelToolItem.java | 4 +- .../modules/curiosities/tools/ToolEvents.java | 31 +- .../resources/assets/create/lang/en_us.json | 4 +- 19 files changed, 535 insertions(+), 241 deletions(-) create mode 100644 src/main/java/com/simibubi/create/foundation/utility/Iterate.java diff --git a/src/main/java/com/simibubi/create/foundation/item/AbstractToolItem.java b/src/main/java/com/simibubi/create/foundation/item/AbstractToolItem.java index 51f3ffd55..eb0c01d9f 100644 --- a/src/main/java/com/simibubi/create/foundation/item/AbstractToolItem.java +++ b/src/main/java/com/simibubi/create/foundation/item/AbstractToolItem.java @@ -6,8 +6,8 @@ import static com.simibubi.create.foundation.item.AllToolTypes.PICKAXE; import static com.simibubi.create.foundation.item.AllToolTypes.SHOVEL; import static com.simibubi.create.foundation.item.AllToolTypes.SWORD; +import java.util.Collection; import java.util.Collections; -import java.util.List; import java.util.function.Supplier; import com.simibubi.create.foundation.packet.SimplePacketBase; @@ -126,7 +126,7 @@ public abstract class AbstractToolItem extends ToolItem { return false; } - public void modifyDrops(final List drops, IWorld world, BlockPos pos, ItemStack tool, BlockState state) { + public void modifyDrops(final Collection drops, IWorld world, BlockPos pos, ItemStack tool, BlockState state) { } public void spawnParticles(IWorld world, BlockPos pos, ItemStack tool, BlockState state) { diff --git a/src/main/java/com/simibubi/create/foundation/utility/Iterate.java b/src/main/java/com/simibubi/create/foundation/utility/Iterate.java new file mode 100644 index 000000000..f8d1ee966 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/Iterate.java @@ -0,0 +1,21 @@ +package com.simibubi.create.foundation.utility; + +import net.minecraft.util.Direction; +import net.minecraft.util.Direction.Axis; + +public class Iterate { + + public static final boolean[] trueAndFalse = { true, false }; + public static final int[] positiveAndNegative = { 1, -1 }; + public static final Direction[] directions = Direction.values(); + public static final Direction[] horizontalDirections = getHorizontals(); + public static final Axis[] axes = Axis.values(); + + private static Direction[] getHorizontals() { + Direction[] directions = new Direction[4]; + for (int i = 0; i < 4; i++) + directions[i] = Direction.byHorizontalIndex(i); + return directions; + } + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/BlockMovementTraits.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/BlockMovementTraits.java index 1e481da9a..411eda950 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/BlockMovementTraits.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/BlockMovementTraits.java @@ -22,6 +22,8 @@ public class BlockMovementTraits { return false; if (blockState.getBlock() == Blocks.OBSIDIAN) return false; + if (AllBlocks.BELT.typeOf(blockState)) + return true; return blockState.getPushReaction() != PushReaction.BLOCK; } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/Contraption.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/Contraption.java index 604556139..22cd8c9d9 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/Contraption.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/Contraption.java @@ -26,6 +26,8 @@ import com.simibubi.create.modules.contraptions.components.contraptions.chassis. import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ChassisTileEntity; import com.simibubi.create.modules.contraptions.components.saw.SawBlock; import com.simibubi.create.modules.contraptions.redstone.ContactBlock; +import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; +import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.modules.logistics.block.inventories.FlexcrateBlock; import net.minecraft.block.Block; @@ -48,6 +50,7 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.world.IWorld; import net.minecraft.world.World; import net.minecraft.world.gen.feature.template.Template.BlockInfo; +import net.minecraftforge.common.util.Constants.BlockFlags; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.wrapper.CombinedInvWrapper; @@ -150,6 +153,14 @@ public abstract class Contraption { return false; if (AllBlocks.FLEXCRATE.typeOf(state)) FlexcrateBlock.splitCrate(world, pos); + if (AllBlocks.BELT.typeOf(state)) { + BlockPos nextPos = BeltBlock.nextSegmentPosition(state, pos, true); + BlockPos prevPos = BeltBlock.nextSegmentPosition(state, pos, false); + if (nextPos != null && !visited.contains(nextPos)) + frontier.add(nextPos); + if (prevPos != null && !visited.contains(prevPos)) + frontier.add(prevPos); + } if (state.getBlock() instanceof SlimeBlock) for (Direction offset : Direction.values()) { @@ -248,6 +259,7 @@ public abstract class Contraption { NBTUtil.readBlockState(comp.getCompound("Block")), comp.contains("Data") ? comp.getCompound("Data") : null); blocks.put(info.pos, info); + if (world.isRemote) { Block block = info.state.getBlock(); BlockRenderLayer renderLayer = block.getRenderLayer(); @@ -255,23 +267,27 @@ public abstract class Contraption { renderOrder.add(info.pos); else renderOrder.add(0, info.pos); - if (info.nbt == null || block instanceof IPortableBlock) + CompoundNBT tag = info.nbt; + if (tag == null || block instanceof IPortableBlock) return; - info.nbt.putInt("x", info.pos.getX()); - info.nbt.putInt("y", info.pos.getY()); - info.nbt.putInt("z", info.pos.getZ()); - TileEntity te = TileEntity.create(info.nbt); + tag.putInt("x", info.pos.getX()); + tag.putInt("y", info.pos.getY()); + tag.putInt("z", info.pos.getZ()); + + TileEntity te = TileEntity.create(tag); te.setWorld(new WrappedWorld(world) { @Override public BlockState getBlockState(BlockPos pos) { - if (isOutsideBuildHeight(pos) || !pos.equals(te.getPos())) + if (!pos.equals(te.getPos())) return Blocks.AIR.getDefaultState(); return info.state; } }); + if (te instanceof KineticTileEntity) + ((KineticTileEntity) te).setSpeed(0); te.getBlockState(); customRenderTEs.add(te); } @@ -392,13 +408,21 @@ public abstract class Contraption { state = state.with(SawBlock.RUNNING, false); world.destroyBlock(targetPos, world.getBlockState(targetPos).getCollisionShape(world, targetPos).isEmpty()); - world.setBlockState(targetPos, state, 3); + world.setBlockState(targetPos, state, 3 | BlockFlags.IS_MOVING); TileEntity tileEntity = world.getTileEntity(targetPos); - if (tileEntity != null && block.nbt != null) { - block.nbt.putInt("x", targetPos.getX()); - block.nbt.putInt("y", targetPos.getY()); - block.nbt.putInt("z", targetPos.getZ()); - tileEntity.read(block.nbt); + CompoundNBT tag = block.nbt; + if (tileEntity != null && tag != null) { + tag.putInt("x", targetPos.getX()); + tag.putInt("y", targetPos.getY()); + tag.putInt("z", targetPos.getZ()); + + if (tileEntity instanceof BeltTileEntity) { + tag.remove("Length"); + tag.remove("Index"); + tag.putBoolean("DontClearAttachments", true); + } + + tileEntity.read(tag); if (tileEntity instanceof KineticTileEntity) { KineticTileEntity kineticTileEntity = (KineticTileEntity) tileEntity; diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/StructureTransform.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/StructureTransform.java index 84e2a1021..49a8281fd 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/StructureTransform.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/StructureTransform.java @@ -1,7 +1,10 @@ package com.simibubi.create.modules.contraptions.components.contraptions; +import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.modules.contraptions.components.contraptions.chassis.AbstractChassisBlock; +import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; +import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope; import net.minecraft.block.BlockState; import net.minecraft.block.SlabBlock; @@ -93,9 +96,49 @@ public class StructureTransform { return state; } + if (AllBlocks.BELT.typeOf(state)) { + if (state.get(BeltBlock.HORIZONTAL_FACING).getAxis() != rotationAxis) { + for (int i = 0; i < rotation.ordinal(); i++) { + Slope slope = state.get(BeltBlock.SLOPE); + Direction direction = state.get(BeltBlock.HORIZONTAL_FACING); + + // Rotate diagonal + if (slope != Slope.HORIZONTAL && slope != Slope.VERTICAL) { + if (direction.getAxisDirection() == AxisDirection.POSITIVE ^ slope == Slope.DOWNWARD + ^ direction.getAxis() == Axis.Z) { + state = + state.with(BeltBlock.SLOPE, slope == Slope.UPWARD ? Slope.DOWNWARD : Slope.UPWARD); + } else { + state = state.with(BeltBlock.HORIZONTAL_FACING, direction.getOpposite()); + } + + // Rotate horizontal/vertical + } else { + if (slope == Slope.HORIZONTAL ^ direction.getAxis() == Axis.Z) { + state = state.with(BeltBlock.HORIZONTAL_FACING, direction.getOpposite()); + } + state = state.with(BeltBlock.SLOPE, + slope == Slope.HORIZONTAL ? Slope.VERTICAL : Slope.HORIZONTAL); + } + } + } else { + if (rotation == Rotation.CLOCKWISE_180) { + Slope slope = state.get(BeltBlock.SLOPE); + Direction direction = state.get(BeltBlock.HORIZONTAL_FACING); + if (slope == Slope.UPWARD || slope == Slope.DOWNWARD) { + state = state.with(BeltBlock.SLOPE, slope == Slope.UPWARD ? Slope.DOWNWARD + : slope == Slope.DOWNWARD ? Slope.UPWARD : slope); + } else if (slope == Slope.VERTICAL) { + state = state.with(BeltBlock.HORIZONTAL_FACING, direction.getOpposite()); + } + } + } + return state; + } + if (state.has(BlockStateProperties.FACING)) { - state = state.with(BlockStateProperties.FACING, - transformFacing(state.get(BlockStateProperties.FACING))); + state = + state.with(BlockStateProperties.FACING, transformFacing(state.get(BlockStateProperties.FACING))); } else if (state.has(BlockStateProperties.AXIS)) { state = state.with(BlockStateProperties.AXIS, transformAxis(state.get(BlockStateProperties.AXIS))); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/deployer/DeployerFakePlayer.java b/src/main/java/com/simibubi/create/modules/contraptions/components/deployer/DeployerFakePlayer.java index 545687ac6..fa8e15b89 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/deployer/DeployerFakePlayer.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/deployer/DeployerFakePlayer.java @@ -38,6 +38,7 @@ import net.minecraftforge.event.entity.EntityEvent; import net.minecraftforge.event.entity.living.LivingDropsEvent; import net.minecraftforge.event.entity.living.LivingExperienceDropEvent; import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent; +import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @@ -86,7 +87,7 @@ public class DeployerFakePlayer extends FakePlayer { event.setNewHeight(0); } - @SubscribeEvent + @SubscribeEvent(priority = EventPriority.LOWEST) public static void deployerCollectsDropsFromKilledEntities(LivingDropsEvent event) { if (!(event.getSource() instanceof EntityDamageSource)) return; diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/motor/MotorTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/motor/MotorTileEntity.java index 9fadca26d..c342777c1 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/motor/MotorTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/motor/MotorTileEntity.java @@ -41,7 +41,7 @@ public class MotorTileEntity extends GeneratingKineticTileEntity { @Override public void initialize() { super.initialize(); - if (!hasSource()) + if (!hasSource() || getGeneratedSpeed() > getTheoreticalSpeed()) updateGeneratedRotation(); } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltBlock.java index c044405ee..b07e5aef8 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltBlock.java @@ -1,22 +1,30 @@ package com.simibubi.create.modules.contraptions.relays.belt; +import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; +import org.apache.commons.lang3.mutable.MutableInt; + import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; +import com.simibubi.create.foundation.block.IHaveColorHandler; import com.simibubi.create.foundation.block.IHaveNoBlockItem; import com.simibubi.create.foundation.block.IWithTileEntity; -import com.simibubi.create.foundation.utility.AllShapes; +import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock; import com.simibubi.create.modules.contraptions.relays.belt.BeltMovementHandler.TransportedEntityInfo; import net.minecraft.block.Block; +import net.minecraft.block.BlockRenderType; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.material.Material; +import net.minecraft.client.particle.DiggingParticle; +import net.minecraft.client.particle.ParticleManager; +import net.minecraft.client.renderer.color.IBlockColor; import net.minecraft.entity.Entity; import net.minecraft.entity.MobEntity; import net.minecraft.entity.item.ItemEntity; @@ -40,19 +48,21 @@ import net.minecraft.util.Hand; import net.minecraft.util.IStringSerializable; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.shapes.IBooleanFunction; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; -import net.minecraft.util.math.shapes.VoxelShapes; import net.minecraft.world.IBlockReader; +import net.minecraft.world.IEnviromentBlockReader; import net.minecraft.world.IWorldReader; import net.minecraft.world.World; +import net.minecraft.world.storage.loot.LootParameters; import net.minecraftforge.common.Tags; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; -public class BeltBlock extends HorizontalKineticBlock implements IHaveNoBlockItem, IWithTileEntity { +public class BeltBlock extends HorizontalKineticBlock + implements IHaveNoBlockItem, IWithTileEntity, IHaveColorHandler { public static final IProperty SLOPE = EnumProperty.create("slope", Slope.class); public static final IProperty PART = EnumProperty.create("part", Part.class); @@ -90,13 +100,14 @@ public class BeltBlock extends HorizontalKineticBlock implements IHaveNoBlockIte @SuppressWarnings("deprecation") @Override public List getDrops(BlockState state, net.minecraft.world.storage.loot.LootContext.Builder builder) { - List drops = super.getDrops(state, builder); + List drops = new ArrayList<>(); + if (state.get(PART) == Part.START || builder.get(LootParameters.THIS_ENTITY) != null) + drops.addAll(super.getDrops(state, builder)); if (state.get(CASING)) - drops.addAll(AllBlocks.BRASS_CASING.getDefault() - .getDrops(builder)); + drops.addAll(AllBlocks.BRASS_CASING.getDefault().getDrops(builder)); return drops; } - + @Override public void spawnAdditionalDrops(BlockState state, World worldIn, BlockPos pos, ItemStack stack) { withTileEntityDo(worldIn, pos, te -> { @@ -170,8 +181,10 @@ public class BeltBlock extends HorizontalKineticBlock implements IHaveNoBlockIte TransportedEntityInfo info = controller.passengers.get(entityIn); if (info.ticksSinceLastCollision != 0 || pos.equals(entityIn.getPosition())) info.refresh(pos, state); - } else + } else { controller.passengers.put(entityIn, new TransportedEntityInfo(pos, state)); + entityIn.onGround = true; + } } @Override @@ -295,12 +308,52 @@ public class BeltBlock extends HorizontalKineticBlock implements IHaveNoBlockIte @Override public PathNodeType getAiPathNodeType(BlockState state, IBlockReader world, BlockPos pos, MobEntity entity) { - return PathNodeType.DANGER_OTHER; + return PathNodeType.RAIL; + } + + @Override + public boolean addDestroyEffects(BlockState state, World world, BlockPos pos, ParticleManager manager) { + // From Particle Manager, but reduced density for belts with lots of boxes + VoxelShape voxelshape = state.getShape(world, pos); + MutableInt amtBoxes = new MutableInt(0); + voxelshape.forEachBox((x1, y1, z1, x2, y2, z2) -> amtBoxes.increment()); + double chance = 1d / amtBoxes.getValue(); + + voxelshape.forEachBox((x1, y1, z1, x2, y2, z2) -> { + double d1 = Math.min(1.0D, x2 - x1); + double d2 = Math.min(1.0D, y2 - y1); + double d3 = Math.min(1.0D, z2 - z1); + int i = Math.max(2, MathHelper.ceil(d1 / 0.25D)); + int j = Math.max(2, MathHelper.ceil(d2 / 0.25D)); + int k = Math.max(2, MathHelper.ceil(d3 / 0.25D)); + + for (int l = 0; l < i; ++l) { + for (int i1 = 0; i1 < j; ++i1) { + for (int j1 = 0; j1 < k; ++j1) { + if (world.rand.nextDouble() > chance) + continue; + + double d4 = ((double) l + 0.5D) / (double) i; + double d5 = ((double) i1 + 0.5D) / (double) j; + double d6 = ((double) j1 + 0.5D) / (double) k; + double d7 = d4 * d1 + x1; + double d8 = d5 * d2 + y1; + double d9 = d6 * d3 + z1; + manager.addEffect( + (new DiggingParticle(world, (double) pos.getX() + d7, (double) pos.getY() + d8, + (double) pos.getZ() + d9, d4 - 0.5D, d5 - 0.5D, d6 - 0.5D, state)) + .setBlockPos(pos)); + } + } + } + + }); + return true; } @Override public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return VoxelShapes.or(BeltShapes.getShape(state), BeltShapes.getCasingShape(state)); + return BeltShapes.getShape(state); } @Override @@ -314,7 +367,7 @@ public class BeltBlock extends HorizontalKineticBlock implements IHaveNoBlockIte if (controller == null) return shape; if (controller.passengers == null || !controller.passengers.containsKey(context.getEntity())) { - return VoxelShapes.combine(AllShapes.BELT_COLLISION_MASK, shape, IBooleanFunction.AND); + return BeltShapes.getCollisionShape(state); } return shape; @@ -326,41 +379,112 @@ public class BeltBlock extends HorizontalKineticBlock implements IHaveNoBlockIte } @Override - public boolean canRenderInLayer(BlockState state, BlockRenderLayer layer) { - return state.get(CASING) && layer == getRenderLayer(); + public BlockRenderType getRenderType(BlockState state) { + return state.get(CASING) && state.get(SLOPE) != Slope.VERTICAL ? BlockRenderType.MODEL + : BlockRenderType.ENTITYBLOCK_ANIMATED; } @Override - public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { - if (worldIn.isRemote) + public boolean canRenderInLayer(BlockState state, BlockRenderLayer layer) { + return state.get(CASING) && state.get(SLOPE) != Slope.VERTICAL && layer == getRenderLayer(); + } + + public static void initBelt(World world, BlockPos pos) { + if (world.isRemote) + return; + + BlockState state = world.getBlockState(pos); + if (!AllBlocks.BELT.typeOf(state)) + return; + // Find controller + int limit = 1000; + BlockPos currentPos = pos; + while (limit-- > 0) { + BlockState currentState = world.getBlockState(currentPos); + if (!AllBlocks.BELT.typeOf(currentState)) { + world.destroyBlock(pos, true); + return; + } + BlockPos nextSegmentPosition = nextSegmentPosition(currentState, currentPos, false); + if (nextSegmentPosition == null) + break; + if (!world.isAreaLoaded(nextSegmentPosition, 0)) + return; + currentPos = nextSegmentPosition; + } + + // Init belts + int index = 0; + List beltChain = getBeltChain(world, pos); + if (beltChain.size() < 2) { + world.destroyBlock(pos, true); + return; + } + + for (BlockPos beltPos : beltChain) { + TileEntity tileEntity = world.getTileEntity(beltPos); + if (tileEntity instanceof BeltTileEntity) { + BeltTileEntity te = (BeltTileEntity) tileEntity; + te.setController(pos); + te.beltLength = beltChain.size(); + te.index = index; + te.attachKinetics(); + te.markDirty(); + te.sendData(); + + BlockState currentState = world.getBlockState(beltPos); + boolean isVertical = currentState.get(BeltBlock.SLOPE) == Slope.VERTICAL; + + if (currentState.get(CASING) && isVertical) { + Block.spawnAsEntity(world, beltPos, new ItemStack(AllBlocks.BRASS_CASING.get())); + world.setBlockState(beltPos, currentState.with(CASING, false), 2); + } + + if (te.isController() && isVertical) { + BeltInventory inventory = te.getInventory(); + for (TransportedItemStack s : inventory.items) + inventory.eject(s); + inventory.items.clear(); + } + } else { + world.destroyBlock(pos, true); + return; + } + index++; + } + + } + + @Override + public void onReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean isMoving) { + if (world.isRemote) return; if (state.getBlock() == newState.getBlock()) return; - updateNeighbouringTunnel(worldIn, pos, state); + + updateNeighbouringTunnel(world, pos, state); + + if (isMoving) + return; + TileEntity belt = world.getTileEntity(pos); + if (belt instanceof BeltTileEntity) + belt.remove(); // Destroy chain - boolean endWasDestroyed = state.get(PART) == Part.END; - TileEntity tileEntity = worldIn.getTileEntity(pos); - if (tileEntity == null) - return; - if (!(tileEntity instanceof BeltTileEntity)) - return; - BeltTileEntity beltEntity = (BeltTileEntity) tileEntity; - BlockPos controller = beltEntity.getController(); - beltEntity.remove(); + for (boolean forward : Iterate.trueAndFalse) { + BlockPos currentPos = nextSegmentPosition(state, pos, forward); + if (currentPos == null) + continue; + BlockState currentState = world.getBlockState(currentPos); + if (!AllBlocks.BELT.typeOf(currentState)) + continue; + if (currentState.get(CASING)) + Block.spawnAsEntity(world, currentPos, new ItemStack(AllBlocks.BRASS_CASING.get())); - int limit = 1000; - BlockPos toDestroy = controller; - BlockState destroyedBlock = null; - - do { - - if (!toDestroy.equals(pos)) { - destroyedBlock = worldIn.getBlockState(toDestroy); - if (!AllBlocks.BELT.typeOf(destroyedBlock)) - break; - - BeltTileEntity te = (BeltTileEntity) worldIn.getTileEntity(toDestroy); + boolean hasPulley = false; + TileEntity tileEntity = world.getTileEntity(currentPos); + if (tileEntity instanceof BeltTileEntity) { + BeltTileEntity te = (BeltTileEntity) tileEntity; if (te.isController()) { BeltInventory inv = te.getInventory(); for (TransportedItemStack stack : inv.items) @@ -368,36 +492,14 @@ public class BeltBlock extends HorizontalKineticBlock implements IHaveNoBlockIte } te.remove(); - - if (destroyedBlock.get(CASING)) - Block.spawnAsEntity(worldIn, toDestroy, new ItemStack(AllBlocks.BRASS_CASING.get())); - if (te.hasPulley()) - worldIn.setBlockState(toDestroy, AllBlocks.SHAFT.get().getDefaultState() - .with(BlockStateProperties.AXIS, getRotationAxis(destroyedBlock)), 3); - else - worldIn.destroyBlock(toDestroy, false); - - if (destroyedBlock.get(PART) == Part.END) - break; - } else { - if (endWasDestroyed) - break; + hasPulley = te.hasPulley(); } - Slope slope = state.get(SLOPE); - Direction direction = state.get(HORIZONTAL_FACING); - - if (slope == Slope.VERTICAL) { - toDestroy = toDestroy.up(direction.getAxisDirection() == AxisDirection.POSITIVE ? 1 : -1); - continue; - } - - toDestroy = toDestroy.offset(direction); - if (slope != Slope.HORIZONTAL) - toDestroy = toDestroy.up(slope == Slope.UPWARD ? 1 : -1); - - } while (limit-- > 0); - + BlockState shaftState = + AllBlocks.SHAFT.get().getDefaultState().with(BlockStateProperties.AXIS, getRotationAxis(currentState)); + world.setBlockState(currentPos, hasPulley ? shaftState : Blocks.AIR.getDefaultState(), 3); + world.playEvent(2001, currentPos, Block.getStateId(currentState)); + } } private void updateNeighbouringTunnel(World world, BlockPos pos, BlockState beltState) { @@ -435,30 +537,36 @@ public class BeltBlock extends HorizontalKineticBlock implements IHaveNoBlockIte if (!AllBlocks.BELT.typeOf(blockState)) return positions; - Slope slope = blockState.get(SLOPE); - Direction direction = blockState.get(HORIZONTAL_FACING); - int limit = 1000; BlockPos current = controllerPos; - do { + while (limit-- > 0 && current != null) { positions.add(current); - - if (!AllBlocks.BELT.typeOf(world.getBlockState(current))) + BlockState state = world.getBlockState(current); + if (!AllBlocks.BELT.typeOf(state)) break; - if (world.getBlockState(current).get(PART) == Part.END) - break; - if (slope == Slope.VERTICAL) { - current = current.up(direction.getAxisDirection() == AxisDirection.POSITIVE ? 1 : -1); - continue; - } - current = current.offset(direction); - if (slope != Slope.HORIZONTAL) - current = current.up(slope == Slope.UPWARD ? 1 : -1); - } while (limit-- > 0); + current = nextSegmentPosition(state, current, true); + } return positions; } + public static BlockPos nextSegmentPosition(BlockState state, BlockPos pos, boolean forward) { + Direction direction = state.get(HORIZONTAL_FACING); + Slope slope = state.get(SLOPE); + Part part = state.get(PART); + + int offset = forward ? 1 : -1; + + if (part == Part.END && forward || part == Part.START && !forward) + return null; + if (slope == Slope.VERTICAL) + return pos.up(direction.getAxisDirection() == AxisDirection.POSITIVE ? offset : -offset); + pos = pos.offset(direction, offset); + if (slope != Slope.HORIZONTAL) + return pos.up(slope == Slope.UPWARD ? offset : -offset); + return pos; + } + @Override protected boolean hasStaticPart() { return false; @@ -489,4 +597,26 @@ public class BeltBlock extends HorizontalKineticBlock implements IHaveNoBlockIte return true; } + @Override + public IBlockColor getColorHandler() { + return color; + } + + private static BeltColor color = new BeltColor(); + + private static class BeltColor implements IBlockColor { + + @Override + public int getColor(BlockState state, IEnviromentBlockReader reader, BlockPos pos, int layer) { + TileEntity tileEntity = reader.getTileEntity(pos); + if (tileEntity instanceof BeltTileEntity) { + BeltTileEntity te = (BeltTileEntity) tileEntity; + if (te.color != -1) + return te.color; + } + return 0; + } + + } + } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltConnectorItem.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltConnectorItem.java index b972397ce..500d3e069 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltConnectorItem.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltConnectorItem.java @@ -102,7 +102,6 @@ public class BeltConnectorItem extends BlockItem implements IAddedByOther { List beltsToCreate = getBeltChainBetween(start, end, slope, facing); BlockState beltBlock = AllBlocks.BELT.get().getDefaultState(); - int index = 0; for (BlockPos pos : beltsToCreate) { BeltBlock.Part part = pos.equals(start) ? Part.START : pos.equals(end) ? Part.END : Part.MIDDLE; boolean pulley = AllBlocks.SHAFT.typeOf(world.getBlockState(pos)); @@ -110,15 +109,6 @@ public class BeltConnectorItem extends BlockItem implements IAddedByOther { part = Part.PULLEY; world.setBlockState(pos, beltBlock.with(BeltBlock.SLOPE, slope).with(BeltBlock.PART, part) .with(BeltBlock.HORIZONTAL_FACING, facing), 3); - - BeltTileEntity te = (BeltTileEntity) world.getTileEntity(pos); - if (te != null) { - te.setController(start); - te.beltLength = beltsToCreate.size(); - te.index = index; - } - - index++; } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltInventory.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltInventory.java index eae999c24..c76d952b3 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltInventory.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltInventory.java @@ -91,8 +91,8 @@ public class BeltInventory { float diff = stackInFront.beltPosition - currentPos; if (Math.abs(diff) <= spacing) continue; - movement = beltMovementPositive ? Math.min(movement, diff - spacing) - : Math.max(movement, diff + spacing); + movement = + beltMovementPositive ? Math.min(movement, diff - spacing) : Math.max(movement, diff + spacing); } // Determine current segment @@ -104,8 +104,8 @@ public class BeltInventory { // Don't move beyond the edge float diffToEnd = beltMovementPositive ? belt.beltLength - currentPos : -currentPos; - float limitedMovement = beltMovementPositive ? Math.min(movement, diffToEnd) - : Math.max(movement, diffToEnd); + float limitedMovement = + beltMovementPositive ? Math.min(movement, diffToEnd) : Math.max(movement, diffToEnd); float nextOffset = current.beltPosition + limitedMovement; if (!onClient) { @@ -204,12 +204,12 @@ public class BeltInventory { if (AllBlocks.BASIN.typeOf(state) || AllBlocks.SAW.typeOf(state)) { TileEntity te = world.getTileEntity(nextPosition); if (te != null) { - LazyOptional optional = te - .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, Direction.UP); + LazyOptional optional = + te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, Direction.UP); if (optional.isPresent()) { IItemHandler itemHandler = optional.orElse(null); - ItemStack remainder = ItemHandlerHelper.insertItemStacked(itemHandler, current.stack.copy(), - false); + ItemStack remainder = + ItemHandlerHelper.insertItemStacked(itemHandler, current.stack.copy(), false); if (remainder.equals(current.stack, false)) continue; @@ -272,7 +272,7 @@ public class BeltInventory { return false; Direction flapFacing = movementDirection.getOpposite(); - + BeltTunnelTileEntity tunnel = (BeltTunnelTileEntity) te; if (!tunnel.flaps.containsKey(flapFacing)) return false; @@ -385,6 +385,7 @@ public class BeltInventory { outPos.add(outMotion.normalize()); ItemEntity entity = new ItemEntity(belt.getWorld(), outPos.x, outPos.y + 6 / 16f, outPos.z, ejected); entity.setMotion(outMotion); + entity.setDefaultPickupDelay(); entity.velocityChanged = true; belt.getWorld().addEntity(entity); } @@ -398,8 +399,12 @@ public class BeltInventory { verticalMovement = verticalMovement * (Math.min(offset, belt.beltLength - .5f) - .5f); Vec3d vec = VecHelper.getCenterOf(belt.getPos()); - vec = vec.add(new Vec3d(belt.getBeltFacing().getDirectionVec()).scale(offset - .5f)).add(0, verticalMovement, - 0); + Vec3d horizontalMovement = new Vec3d(belt.getBeltFacing().getDirectionVec()).scale(offset - .5f); + + if (slope == Slope.VERTICAL) + horizontalMovement = Vec3d.ZERO; + + vec = vec.add(horizontalMovement).add(0, verticalMovement, 0); return vec; } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltMovementHandler.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltMovementHandler.java index f6c33e786..2aac23aad 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltMovementHandler.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltMovementHandler.java @@ -78,7 +78,7 @@ public class BeltMovementHandler { // Too slow boolean notHorizontal = beltTe.getBlockState().get(BeltBlock.SLOPE) != Slope.HORIZONTAL; - if (Math.abs(beltTe.getSpeed()) < (notHorizontal ? 32 : 1)) + if (Math.abs(beltTe.getSpeed()) < 1) return; // Not on top @@ -158,6 +158,8 @@ public class BeltMovementHandler { } } + entityIn.fallDistance = 0; + if (movingUp) { float minVelocity = .13f; float yMovement = (float) -(Math.max(Math.abs(movement.y), minVelocity)); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltShapes.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltShapes.java index a0a72bbc4..eb5d0291e 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltShapes.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltShapes.java @@ -2,6 +2,9 @@ package com.simibubi.create.modules.contraptions.relays.belt; import static net.minecraft.block.Block.makeCuboidShape; +import java.util.HashMap; +import java.util.Map; + import com.simibubi.create.foundation.utility.AllShapes; import com.simibubi.create.foundation.utility.VoxelShaper; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part; @@ -98,6 +101,8 @@ public class BeltShapes { private static final VoxelShaper PARTIAL_CASING = VoxelShaper.forHorizontal(makeCuboidShape(0, 0, 5, 16, 11, 16), Direction.SOUTH); + static Map cache = new HashMap<>(); + static Map collisionCache = new HashMap<>(); private static VoxelShape compose(VoxelShape southPart, VoxelShape northPart){ return VoxelShapes.or( @@ -134,6 +139,22 @@ public class BeltShapes { } public static VoxelShape getShape(BlockState state) { + if (cache.containsKey(state)) + return cache.get(state); + VoxelShape createdShape = VoxelShapes.or(getBeltShape(state), getCasingShape(state)); + cache.put(state, createdShape); + return createdShape; + } + + public static VoxelShape getCollisionShape(BlockState state) { + if (collisionCache.containsKey(state)) + return collisionCache.get(state); + VoxelShape createdShape = VoxelShapes.combine(AllShapes.BELT_COLLISION_MASK, getShape(state), IBooleanFunction.AND); + collisionCache.put(state, createdShape); + return createdShape; + } + + private static VoxelShape getBeltShape(BlockState state) { Direction facing = state.get(BeltBlock.HORIZONTAL_FACING); Axis axis = facing.getAxis(); Part part = state.get(BeltBlock.PART); @@ -166,10 +187,9 @@ public class BeltShapes { //bad state return VoxelShapes.empty(); - } - public static VoxelShape getCasingShape(BlockState state) { + private static VoxelShape getCasingShape(BlockState state) { if (!state.get(BeltBlock.CASING)) return VoxelShapes.empty(); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java index 56575fbfa..69b6a5f7a 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java @@ -61,23 +61,21 @@ public class BeltTileEntity extends KineticTileEntity { attachmentTracker = new Tracker(this); itemHandler = LazyOptional.empty(); color = -1; - beltLength = -1; - index = -1; } @Override public void initialize() { super.initialize(); - // 0.1 belt - if (beltLength == 0) { - world.destroyBlock(pos, true); - } } - + @Override public void tick() { super.tick(); + // Init belt + if (beltLength == 0) + BeltBlock.initBelt(world, pos); + // Initialize Belt Attachments if (world != null && trackerUpdateTag != null) { attachmentTracker.readAndSearch(trackerUpdateTag, this); @@ -100,9 +98,8 @@ public class BeltTileEntity extends KineticTileEntity { List toRemove = new ArrayList<>(); passengers.forEach((entity, info) -> { boolean canBeTransported = BeltMovementHandler.canBeTransported(entity); - boolean leftTheBelt = info.ticksSinceLastCollision > ((getBlockState().get(BeltBlock.SLOPE) != HORIZONTAL) - ? 3 - : 1); + boolean leftTheBelt = + info.ticksSinceLastCollision > ((getBlockState().get(BeltBlock.SLOPE) != HORIZONTAL) ? 3 : 1); if (!canBeTransported || leftTheBelt) { toRemove.add(entity); return; @@ -165,6 +162,7 @@ public class BeltTileEntity extends KineticTileEntity { public CompoundNBT write(CompoundNBT compound) { attachmentTracker.write(compound); compound.put("Controller", NBTUtil.writeBlockPos(controller)); + compound.putBoolean("IsController", isController()); compound.putInt("Color", color); compound.putInt("Length", beltLength); compound.putInt("Index", index); @@ -177,8 +175,13 @@ public class BeltTileEntity extends KineticTileEntity { @Override public void read(CompoundNBT compound) { super.read(compound); - trackerUpdateTag = compound; - controller = NBTUtil.readBlockPos(compound.getCompound("Controller")); + if (compound.getBoolean("IsController")) + controller = pos; + else + controller = NBTUtil.readBlockPos(compound.getCompound("Controller")); + + if (!compound.contains("DontClearAttachments")) + trackerUpdateTag = compound; color = compound.getInt("Color"); beltLength = compound.getInt("Length"); index = compound.getInt("Index"); @@ -249,8 +252,8 @@ public class BeltTileEntity extends KineticTileEntity { if (part == MIDDLE) return false; - boolean movingPositively = (getSpeed() > 0 == (direction.getAxisDirection().getOffset() == 1)) - ^ direction.getAxis() == Axis.X; + boolean movingPositively = + (getSpeed() > 0 == (direction.getAxisDirection().getOffset() == 1)) ^ direction.getAxis() == Axis.X; return part == Part.START ^ movingPositively; } @@ -305,8 +308,9 @@ public class BeltTileEntity extends KineticTileEntity { return controllerTE.getInventory(); return null; } - if (inventory == null) + if (inventory == null) { inventory = new BeltInventory(this); + } return inventory; } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntityRenderer.java index e44b53fc0..e9e2d545b 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntityRenderer.java @@ -28,6 +28,7 @@ import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.Direction.Axis; +import net.minecraft.util.Direction.AxisDirection; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3i; @@ -47,15 +48,15 @@ public class BeltTileEntityRenderer extends SafeTileEntityRenderer 0 - ^ te.getBeltMovementSpeed() < 0 ? -45 : 45 - : 0; - - GlStateManager.translated(offsetVec.x, offsetVec.y, offsetVec.z); - - boolean alongX = te.getBeltFacing().rotateY().getAxis() == Axis.X; - if (!alongX) - sideOffset *= -1; - GlStateManager.translated(alongX ? sideOffset : 0, 0, alongX ? 0 : sideOffset); - - ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer(); - boolean blockItem = itemRenderer.getModelWithOverrides(transported.stack).isGui3d(); - if (Minecraft.getInstance().gameSettings.fancyGraphics) { - Vec3d shadowPos = new Vec3d(te.getPos()).add(beltStartOffset.scale(1).add(offsetVec) - .add(alongX ? sideOffset : 0, .39, alongX ? 0 : sideOffset)); - IndependentShadowRenderer.renderShadow(shadowPos.x, shadowPos.y, shadowPos.z, .75f, - blockItem ? .2f : .2f); - } - - RenderHelper.enableStandardItemLighting(); - - int count = (int) (MathHelper.log2((int) (transported.stack.getCount()))) / 2; - GlStateManager.rotated(slopeAngle, slopeAlongX ? 0 : 1, 0, slopeAlongX ? 1 : 0); - if (onSlope) - GlStateManager.translated(0, 1 / 8f, 0); - Random r = new Random(transported.angle); - - for (int i = 0; i <= count; i++) { - GlStateManager.pushMatrix(); - - GlStateManager.rotated(transported.angle, 0, 1, 0); - if (!blockItem) { - GlStateManager.translated(0, -.09375, 0); - GlStateManager.rotated(90, 1, 0, 0); - } - - if (blockItem) { - GlStateManager.translated(r.nextFloat() * .0625f * i, 0, r.nextFloat() * .0625f * i); - } - - GlStateManager.scaled(.5, .5, .5); - itemRenderer.renderItem(transported.stack, TransformType.FIXED); - GlStateManager.popMatrix(); - - if (!blockItem) - GlStateManager.rotated(10, 0, 1, 0); - GlStateManager.translated(0, blockItem ? 1 / 64d : 1 / 16d, 0); - - } - - RenderHelper.disableStandardItemLighting(); - GlStateManager.popMatrix(); + if (te.getSpeed() == 0) { + offset = transported.beltPosition; + sideOffset = transported.sideOffset; } - GlStateManager.disableBlend(); + if (offset < .5) + verticalMovement = 0; + verticalMovement = verticalMovement * (Math.min(offset, te.beltLength - .5f) - .5f); + Vec3d offsetVec = new Vec3d(directionVec).scale(offset).add(0, verticalMovement, 0); + boolean onSlope = slope != Slope.HORIZONTAL && MathHelper.clamp(offset, .5f, te.beltLength - .5f) == offset; + boolean tiltForward = + (slope == Slope.DOWNWARD ^ te.getBeltFacing().getAxisDirection() == AxisDirection.POSITIVE) == (te + .getBeltFacing().getAxis() == Axis.Z); + float slopeAngle = onSlope ? tiltForward ? -45 : 45 : 0; + + GlStateManager.translated(offsetVec.x, offsetVec.y, offsetVec.z); + + boolean alongX = te.getBeltFacing().rotateY().getAxis() == Axis.X; + if (!alongX) + sideOffset *= -1; + GlStateManager.translated(alongX ? sideOffset : 0, 0, alongX ? 0 : sideOffset); + + ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer(); + boolean blockItem = itemRenderer.getModelWithOverrides(transported.stack).isGui3d(); + if (Minecraft.getInstance().gameSettings.fancyGraphics) { + Vec3d shadowPos = new Vec3d(te.getPos()).add(beltStartOffset.scale(1).add(offsetVec) + .add(alongX ? sideOffset : 0, .39, alongX ? 0 : sideOffset)); + IndependentShadowRenderer.renderShadow(shadowPos.x, shadowPos.y, shadowPos.z, .75f, + blockItem ? .2f : .2f); + } + + RenderHelper.enableStandardItemLighting(); + + int count = (int) (MathHelper.log2((int) (transported.stack.getCount()))) / 2; + GlStateManager.rotated(slopeAngle, slopeAlongX ? 0 : 1, 0, slopeAlongX ? 1 : 0); + if (onSlope) + GlStateManager.translated(0, 1 / 8f, 0); + Random r = new Random(transported.angle); + + for (int i = 0; i <= count; i++) { + GlStateManager.pushMatrix(); + + GlStateManager.rotated(transported.angle, 0, 1, 0); + if (!blockItem) { + GlStateManager.translated(0, -.09375, 0); + GlStateManager.rotated(90, 1, 0, 0); + } + + if (blockItem) { + GlStateManager.translated(r.nextFloat() * .0625f * i, 0, r.nextFloat() * .0625f * i); + } + + GlStateManager.scaled(.5, .5, .5); + itemRenderer.renderItem(transported.stack, TransformType.FIXED); + GlStateManager.popMatrix(); + + if (!blockItem) + GlStateManager.rotated(10, 0, 1, 0); + GlStateManager.translated(0, blockItem ? 1 / 64d : 1 / 16d, 0); + + } + + RenderHelper.disableStandardItemLighting(); GlStateManager.popMatrix(); } + + GlStateManager.disableBlend(); + GlStateManager.popMatrix(); } protected BlockState getBeltState(KineticTileEntity te) { diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/GaugeInformationRenderer.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/GaugeInformationRenderer.java index 6304d6757..daa470f0d 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/GaugeInformationRenderer.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/GaugeInformationRenderer.java @@ -13,6 +13,7 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.foundation.gui.ScreenElementRenderer; import com.simibubi.create.foundation.item.ItemDescription; +import com.simibubi.create.foundation.item.TooltipHelper; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.modules.contraptions.base.GeneratingKineticTileEntity; import com.simibubi.create.modules.contraptions.base.IRotate.SpeedLevel; @@ -22,6 +23,7 @@ import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.resources.I18n; import net.minecraft.client.world.ClientWorld; import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.item.ItemStack; @@ -56,21 +58,28 @@ public class GaugeInformationRenderer { BlockPos pos = result.getPos(); BlockState state = world.getBlockState(pos); ItemStack goggles = mc.player.getItemStackFromSlot(EquipmentSlotType.HEAD); + TileEntity te = world.getTileEntity(pos); + boolean notFastEnough = (te instanceof KineticTileEntity) + && !((KineticTileEntity) te).isSpeedRequirementFulfilled() && ((KineticTileEntity) te).getSpeed() != 0; - if (!AllItems.GOGGLES.typeOf(goggles)) + if (!AllItems.GOGGLES.typeOf(goggles) && !notFastEnough) return; if (mc.player.isSneaking()) return; List tooltip = new ArrayList<>(); - TileEntity te = world.getTileEntity(pos); - if (state.getBlock() instanceof GaugeBlock) + if (notFastEnough) { + addSpeedRequirementMessage(state, tooltip, (KineticTileEntity) te); + goggles = AllItems.GOGGLES.asStack(); + } else if (state.getBlock() instanceof GaugeBlock) addGaugeTooltip(state, tooltip, te); - if (te instanceof GeneratingKineticTileEntity) - addGeneratorTooltip(state, tooltip, (GeneratingKineticTileEntity) te); - if (te instanceof KineticTileEntity) - addStressTooltip(state, tooltip, (KineticTileEntity) te); + else { + if (te instanceof GeneratingKineticTileEntity) + addGeneratorTooltip(state, tooltip, (GeneratingKineticTileEntity) te); + if (te instanceof KineticTileEntity) + addStressTooltip(state, tooltip, (KineticTileEntity) te); + } if (tooltip.isEmpty()) return; @@ -91,14 +100,22 @@ public class GaugeInformationRenderer { tooltipScreen.init(mc, mc.mainWindow.getScaledWidth(), mc.mainWindow.getScaledHeight()); tooltipScreen.renderTooltip(tooltip, tooltipScreen.width / 2, tooltipScreen.height / 2); + ItemStack item = goggles; ScreenElementRenderer.render3DItem(() -> { GlStateManager.translated(tooltipScreen.width / 2 + 10, tooltipScreen.height / 2 - 16, 0); - return goggles; + return item; }); GlStateManager.popMatrix(); } + private static void addSpeedRequirementMessage(BlockState state, List tooltip, KineticTileEntity te) { + String spacing = " "; + tooltip.addAll(TooltipHelper.cutString(spacing + + Lang.translate("gui.contraptions.not_fast_enough", I18n.format(state.getBlock().getTranslationKey())), + GRAY, TextFormatting.WHITE)); + } + private static void addStressTooltip(BlockState state, List tooltip, KineticTileEntity te) { String spacing = " "; float stressApplied = te.getStressApplied(); diff --git a/src/main/java/com/simibubi/create/modules/curiosities/tools/BlazingToolItem.java b/src/main/java/com/simibubi/create/modules/curiosities/tools/BlazingToolItem.java index 0895ab89c..27aa1107a 100644 --- a/src/main/java/com/simibubi/create/modules/curiosities/tools/BlazingToolItem.java +++ b/src/main/java/com/simibubi/create/modules/curiosities/tools/BlazingToolItem.java @@ -1,6 +1,7 @@ package com.simibubi.create.modules.curiosities.tools; import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Optional; @@ -63,13 +64,15 @@ public class BlazingToolItem extends AbstractToolItem { } @Override - public void modifyDrops(List drops, IWorld world, BlockPos pos, ItemStack tool, BlockState state) { + public void modifyDrops(Collection drops, IWorld world, BlockPos pos, ItemStack tool, BlockState state) { super.modifyDrops(drops, world, pos, tool, state); World worldIn = world.getWorld(); helperFurnace.setWorld(worldIn); - + RecipeManager recipeManager = worldIn.getRecipeManager(); int enchantmentLevel = EnchantmentHelper.getEnchantmentLevel(Enchantments.FORTUNE, tool); + if (state == null) + enchantmentLevel = 0; List smeltedStacks = new ArrayList<>(); Iterator dropper = drops.iterator(); while (dropper.hasNext()) { diff --git a/src/main/java/com/simibubi/create/modules/curiosities/tools/ShadowSteelToolItem.java b/src/main/java/com/simibubi/create/modules/curiosities/tools/ShadowSteelToolItem.java index 66926d92b..4ece6a42b 100644 --- a/src/main/java/com/simibubi/create/modules/curiosities/tools/ShadowSteelToolItem.java +++ b/src/main/java/com/simibubi/create/modules/curiosities/tools/ShadowSteelToolItem.java @@ -1,6 +1,6 @@ package com.simibubi.create.modules.curiosities.tools; -import java.util.List; +import java.util.Collection; import com.simibubi.create.foundation.item.AbstractToolItem; import com.simibubi.create.foundation.item.AllToolTypes; @@ -25,7 +25,7 @@ public class ShadowSteelToolItem extends AbstractToolItem { } @Override - public void modifyDrops(List drops, IWorld world, BlockPos pos, ItemStack tool, BlockState state) { + public void modifyDrops(Collection drops, IWorld world, BlockPos pos, ItemStack tool, BlockState state) { drops.clear(); } diff --git a/src/main/java/com/simibubi/create/modules/curiosities/tools/ToolEvents.java b/src/main/java/com/simibubi/create/modules/curiosities/tools/ToolEvents.java index c492d9065..178960f71 100644 --- a/src/main/java/com/simibubi/create/modules/curiosities/tools/ToolEvents.java +++ b/src/main/java/com/simibubi/create/modules/curiosities/tools/ToolEvents.java @@ -1,6 +1,7 @@ package com.simibubi.create.modules.curiosities.tools; import java.util.List; +import java.util.stream.Collectors; import com.simibubi.create.AllPackets; import com.simibubi.create.foundation.item.AbstractToolItem; @@ -12,8 +13,10 @@ import net.minecraft.block.Blocks; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.Entity; +import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.EntityDamageSource; @@ -111,15 +114,39 @@ public class ToolEvents { } @SubscribeEvent - public static void shadowSteelToolsDoNotDropEntityLoot(LivingDropsEvent event) { + public static void toolsMayModifyEntityLoot(LivingDropsEvent event) { if (!(event.getSource() instanceof EntityDamageSource)) return; + EntityDamageSource source = (EntityDamageSource) event.getSource(); + Entity target = event.getEntity(); Entity trueSource = source.getTrueSource(); + World world = target.getEntityWorld(); + if (trueSource != null && trueSource instanceof PlayerEntity) { PlayerEntity player = (PlayerEntity) trueSource; - if (player.getHeldItemMainhand().getItem() instanceof ShadowSteelToolItem) + ItemStack heldItemMainhand = player.getHeldItemMainhand(); + Item item = heldItemMainhand.getItem(); + + if (item instanceof ShadowSteelToolItem) event.setCanceled(true); + + if (item instanceof BlazingToolItem) { + BlazingToolItem blazingToolItem = (BlazingToolItem) item; + List drops = event.getDrops().stream().map(entity -> { + ItemStack stack = entity.getItem(); + entity.remove(); + return stack; + }).collect(Collectors.toList()); + blazingToolItem.modifyDrops(drops, world, player.getPosition(), heldItemMainhand, null); + event.getDrops().clear(); + drops.stream().map(stack -> { + ItemEntity entity = new ItemEntity(world, target.posX, target.posY, target.posZ, stack); + world.addEntity(entity); + return entity; + }).forEach(event.getDrops()::add); + } + } } diff --git a/src/main/resources/assets/create/lang/en_us.json b/src/main/resources/assets/create/lang/en_us.json index c536dc8e9..f6d638ee5 100644 --- a/src/main/resources/assets/create/lang/en_us.json +++ b/src/main/resources/assets/create/lang/en_us.json @@ -408,6 +408,8 @@ "create.gui.stress_gauge.capacity": "Remaining Capacity", "create.gui.stress_gauge.overstressed": "Overstressed", "create.gui.stress_gauge.no_rotation": "No Rotation", + + "create.gui.contraptions.not_fast_enough": "It appears that this %1$s is _not_ rotating with _enough_ _speed._", "create.gui.flexcrate.title": "Adjustable Crate", "create.gui.flexcrate.storageSpace": "Storage Space", @@ -1115,7 +1117,7 @@ "item.create.slot_cover.tooltip.summary": "Used to mark a _Mechanical_ _Crafter_ as an empty slot in a recipe. Crafters do not necessarily have to form a full square grid, this cover find its use when there are recipes where _ingredients_ _are_ _diagonal_ to each other.", "tool.create.shadow_steel.tooltip": "SHADOW STEEL TOOLS", - "tool.create.shadow_steel.tooltip.summary": "This tool breaks blocks _extremely_ _quick,_ but _shatters_ all of their _drops_ with them. Killed mobs can drop _more_ _experience_ based on the _Looting_ modifier of this tool.", + "tool.create.shadow_steel.tooltip.summary": "A fast and powerful tool that _destroys_ _drops_ from any block or entity. Killed mobs can drop _more_ _experience_ based on the _Looting_ modifier of this tool.", "tool.create.blazing.tooltip": "BLAZING TOOLS", "tool.create.blazing.tooltip.summary": "This tool will _melt_ _broken_ _blocks_ and _ignite_ _attacked_ _mobs._ It will not lose Durability while being used in the _Nether._",