mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-16 23:11:40 +01:00
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
This commit is contained in:
parent
59e9a76e49
commit
8c793b8d28
19 changed files with 535 additions and 241 deletions
|
@ -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<ItemStack> drops, IWorld world, BlockPos pos, ItemStack tool, BlockState state) {
|
||||
public void modifyDrops(final Collection<ItemStack> drops, IWorld world, BlockPos pos, ItemStack tool, BlockState state) {
|
||||
}
|
||||
|
||||
public void spawnParticles(IWorld world, BlockPos pos, ItemStack tool, BlockState state) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -41,7 +41,7 @@ public class MotorTileEntity extends GeneratingKineticTileEntity {
|
|||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
if (!hasSource())
|
||||
if (!hasSource() || getGeneratedSpeed() > getTheoreticalSpeed())
|
||||
updateGeneratedRotation();
|
||||
}
|
||||
|
||||
|
|
|
@ -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<BeltTileEntity> {
|
||||
public class BeltBlock extends HorizontalKineticBlock
|
||||
implements IHaveNoBlockItem, IWithTileEntity<BeltTileEntity>, IHaveColorHandler {
|
||||
|
||||
public static final IProperty<Slope> SLOPE = EnumProperty.create("slope", Slope.class);
|
||||
public static final IProperty<Part> PART = EnumProperty.create("part", Part.class);
|
||||
|
@ -90,10 +100,11 @@ public class BeltBlock extends HorizontalKineticBlock implements IHaveNoBlockIte
|
|||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public List<ItemStack> getDrops(BlockState state, net.minecraft.world.storage.loot.LootContext.Builder builder) {
|
||||
List<ItemStack> drops = super.getDrops(state, builder);
|
||||
List<ItemStack> 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;
|
||||
}
|
||||
|
||||
|
@ -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<BlockPos> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -102,7 +102,6 @@ public class BeltConnectorItem extends BlockItem implements IAddedByOther {
|
|||
List<BlockPos> 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++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<IItemHandler> optional = te
|
||||
.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, Direction.UP);
|
||||
LazyOptional<IItemHandler> 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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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<BlockState, VoxelShape> cache = new HashMap<>();
|
||||
static Map<BlockState, VoxelShape> 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();
|
||||
|
||||
|
|
|
@ -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<Entity> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<BeltTileEntit
|
|||
}
|
||||
|
||||
@Override
|
||||
public void renderFast(BeltTileEntity te, double x, double y, double z, float partialTicks,
|
||||
int destroyStage, BufferBuilder buffer) {
|
||||
public void renderFast(BeltTileEntity te, double x, double y, double z, float partialTicks, int destroyStage,
|
||||
BufferBuilder buffer) {
|
||||
BlockState blockState = te.getBlockState();
|
||||
if (!AllBlocks.BELT.typeOf(blockState))
|
||||
return;
|
||||
|
||||
BlockState renderedState = getBeltState(te);
|
||||
SuperByteBuffer beltBuffer = CreateClient.bufferCache.renderBlockIn(KineticTileEntityRenderer.KINETIC_TILE,
|
||||
renderedState);
|
||||
SuperByteBuffer beltBuffer =
|
||||
CreateClient.bufferCache.renderBlockIn(KineticTileEntityRenderer.KINETIC_TILE, renderedState);
|
||||
|
||||
beltBuffer.color(te.color == -1 ? 0x808080 : te.color);
|
||||
|
||||
|
@ -64,8 +65,8 @@ public class BeltTileEntityRenderer extends SafeTileEntityRenderer<BeltTileEntit
|
|||
if (animatedTexture == null)
|
||||
animatedTexture = SpriteShifter.get("block/belt", "block/belt_animated");
|
||||
if (speed != 0) {
|
||||
float time = AnimationTickHolder.getRenderTick()
|
||||
* blockState.get(HORIZONTAL_FACING).getAxisDirection().getOffset();
|
||||
float time =
|
||||
AnimationTickHolder.getRenderTick() * blockState.get(HORIZONTAL_FACING).getAxisDirection().getOffset();
|
||||
if (renderedState.get(BeltBlock.HORIZONTAL_FACING).getAxis() == Axis.X)
|
||||
speed = -speed;
|
||||
int textureIndex = (int) ((speed * time / 36) % 16);
|
||||
|
@ -92,93 +93,95 @@ public class BeltTileEntityRenderer extends SafeTileEntityRenderer<BeltTileEntit
|
|||
}
|
||||
|
||||
protected void renderItems(BeltTileEntity te, double x, double y, double z, float partialTicks) {
|
||||
if (te.isController()) {
|
||||
if (!te.isController())
|
||||
return;
|
||||
if (te.beltLength == 0)
|
||||
return;
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
Vec3i directionVec = te.getBeltFacing().getDirectionVec();
|
||||
Vec3d beltStartOffset = new Vec3d(directionVec).scale(-.5).add(.5, 13 / 16f + .125f, .5);
|
||||
GlStateManager.translated(x + beltStartOffset.x, y + beltStartOffset.y, z + beltStartOffset.z);
|
||||
Slope slope = te.getBlockState().get(BeltBlock.SLOPE);
|
||||
int verticality = slope == Slope.DOWNWARD ? -1 : slope == Slope.UPWARD ? 1 : 0;
|
||||
boolean slopeAlongX = te.getBeltFacing().getAxis() == Axis.X;
|
||||
|
||||
for (TransportedItemStack transported : te.getInventory().items) {
|
||||
GlStateManager.pushMatrix();
|
||||
TessellatorHelper.fightZFighting(transported.angle);
|
||||
float offset = MathHelper.lerp(partialTicks, transported.prevBeltPosition, transported.beltPosition);
|
||||
float sideOffset = MathHelper.lerp(partialTicks, transported.prevSideOffset, transported.sideOffset);
|
||||
float verticalMovement = verticality;
|
||||
|
||||
Vec3i directionVec = te.getBeltFacing().getDirectionVec();
|
||||
Vec3d beltStartOffset = new Vec3d(directionVec).scale(-.5).add(.5, 13 / 16f + .125f, .5);
|
||||
GlStateManager.translated(x + beltStartOffset.x, y + beltStartOffset.y, z + beltStartOffset.z);
|
||||
Slope slope = te.getBlockState().get(BeltBlock.SLOPE);
|
||||
int verticality = slope == Slope.DOWNWARD ? -1 : slope == Slope.UPWARD ? 1 : 0;
|
||||
boolean slopeAlongX = te.getBeltFacing().getAxis() == Axis.X;
|
||||
|
||||
for (TransportedItemStack transported : te.getInventory().items) {
|
||||
GlStateManager.pushMatrix();
|
||||
TessellatorHelper.fightZFighting(transported.angle);
|
||||
float offset = MathHelper.lerp(partialTicks, transported.prevBeltPosition, transported.beltPosition);
|
||||
float sideOffset = MathHelper.lerp(partialTicks, transported.prevSideOffset, transported.sideOffset);
|
||||
float verticalMovement = verticality;
|
||||
|
||||
if (te.getSpeed() == 0) {
|
||||
offset = transported.beltPosition;
|
||||
sideOffset = transported.sideOffset;
|
||||
}
|
||||
|
||||
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;
|
||||
float slopeAngle = onSlope
|
||||
? slope == Slope.DOWNWARD ^ te.getDirectionAwareBeltMovementSpeed() > 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) {
|
||||
|
|
|
@ -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<String> 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<String> 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<String> tooltip, KineticTileEntity te) {
|
||||
String spacing = " ";
|
||||
float stressApplied = te.getStressApplied();
|
||||
|
|
|
@ -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<ItemStack> drops, IWorld world, BlockPos pos, ItemStack tool, BlockState state) {
|
||||
public void modifyDrops(Collection<ItemStack> 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<ItemStack> smeltedStacks = new ArrayList<>();
|
||||
Iterator<ItemStack> dropper = drops.iterator();
|
||||
while (dropper.hasNext()) {
|
||||
|
|
|
@ -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<ItemStack> drops, IWorld world, BlockPos pos, ItemStack tool, BlockState state) {
|
||||
public void modifyDrops(Collection<ItemStack> drops, IWorld world, BlockPos pos, ItemStack tool, BlockState state) {
|
||||
drops.clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -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<ItemStack> 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -409,6 +409,8 @@
|
|||
"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._",
|
||||
|
|
Loading…
Reference in a new issue