mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-28 16:06:48 +01:00
Merge branch 'mc1.15/dev' into mc1.16/dev
This commit is contained in:
commit
2b4ef88fc1
7 changed files with 293 additions and 99 deletions
|
@ -455,6 +455,8 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
|
||||||
if (!ticking)
|
if (!ticking)
|
||||||
contraption.stop(world);
|
contraption.stop(world);
|
||||||
}
|
}
|
||||||
|
if (contraption != null)
|
||||||
|
contraption.onEntityRemoved(this);
|
||||||
super.remove(keepData);
|
super.remove(keepData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,30 @@
|
||||||
package com.simibubi.create.content.contraptions.components.structureMovement;
|
package com.simibubi.create.content.contraptions.components.structureMovement;
|
||||||
|
|
||||||
|
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole;
|
||||||
|
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.tuple.MutablePair;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.AllMovementBehaviours;
|
import com.simibubi.create.AllMovementBehaviours;
|
||||||
import com.simibubi.create.content.contraptions.base.IRotate;
|
import com.simibubi.create.content.contraptions.base.IRotate;
|
||||||
|
@ -32,9 +57,22 @@ import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
|
||||||
import com.simibubi.create.foundation.render.backend.instancing.IFlywheelWorld;
|
import com.simibubi.create.foundation.render.backend.instancing.IFlywheelWorld;
|
||||||
import com.simibubi.create.foundation.render.backend.light.EmptyLighter;
|
import com.simibubi.create.foundation.render.backend.light.EmptyLighter;
|
||||||
import com.simibubi.create.foundation.render.backend.light.GridAlignedBB;
|
import com.simibubi.create.foundation.render.backend.light.GridAlignedBB;
|
||||||
import com.simibubi.create.foundation.utility.*;
|
import com.simibubi.create.foundation.utility.BlockFace;
|
||||||
|
import com.simibubi.create.foundation.utility.Coordinate;
|
||||||
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.NBTProcessors;
|
||||||
|
import com.simibubi.create.foundation.utility.UniqueLinkedList;
|
||||||
import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld;
|
import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld;
|
||||||
import net.minecraft.block.*;
|
|
||||||
|
import net.minecraft.block.AbstractButtonBlock;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.block.Blocks;
|
||||||
|
import net.minecraft.block.ChestBlock;
|
||||||
|
import net.minecraft.block.DoorBlock;
|
||||||
|
import net.minecraft.block.IWaterLoggable;
|
||||||
|
import net.minecraft.block.PressurePlateBlock;
|
||||||
import net.minecraft.block.material.PushReaction;
|
import net.minecraft.block.material.PushReaction;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.fluid.FluidState;
|
import net.minecraft.fluid.FluidState;
|
||||||
|
@ -54,6 +92,9 @@ import net.minecraft.util.Direction.Axis;
|
||||||
import net.minecraft.util.Rotation;
|
import net.minecraft.util.Rotation;
|
||||||
import net.minecraft.util.math.AxisAlignedBB;
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.shapes.IBooleanFunction;
|
||||||
|
import net.minecraft.util.math.shapes.VoxelShape;
|
||||||
|
import net.minecraft.util.math.shapes.VoxelShapes;
|
||||||
import net.minecraft.util.math.vector.Vector3d;
|
import net.minecraft.util.math.vector.Vector3d;
|
||||||
import net.minecraft.util.palette.HashMapPalette;
|
import net.minecraft.util.palette.HashMapPalette;
|
||||||
import net.minecraft.village.PointOfInterestType;
|
import net.minecraft.village.PointOfInterestType;
|
||||||
|
@ -72,19 +113,10 @@ import net.minecraftforge.fluids.capability.templates.FluidTank;
|
||||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||||
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
|
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
|
||||||
import net.minecraftforge.registries.GameData;
|
import net.minecraftforge.registries.GameData;
|
||||||
import org.apache.commons.lang3.tuple.MutablePair;
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.BiConsumer;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole;
|
|
||||||
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead;
|
|
||||||
|
|
||||||
public abstract class Contraption {
|
public abstract class Contraption {
|
||||||
|
|
||||||
|
public Optional<List<AxisAlignedBB>> simplifiedEntityColliders;
|
||||||
public AbstractContraptionEntity entity;
|
public AbstractContraptionEntity entity;
|
||||||
public CombinedInvWrapper inventory;
|
public CombinedInvWrapper inventory;
|
||||||
public CombinedTankWrapper fluidInventory;
|
public CombinedTankWrapper fluidInventory;
|
||||||
|
@ -105,6 +137,8 @@ public abstract class Contraption {
|
||||||
private Map<BlockPos, Entity> initialPassengers;
|
private Map<BlockPos, Entity> initialPassengers;
|
||||||
private List<BlockFace> pendingSubContraptions;
|
private List<BlockFace> pendingSubContraptions;
|
||||||
|
|
||||||
|
private CompletableFuture<Void> simplifiedEntityColliderProvider;
|
||||||
|
|
||||||
// Client
|
// Client
|
||||||
public Map<BlockPos, TileEntity> presentTileEntities;
|
public Map<BlockPos, TileEntity> presentTileEntities;
|
||||||
public List<TileEntity> maybeInstancedTileEntities;
|
public List<TileEntity> maybeInstancedTileEntities;
|
||||||
|
@ -127,13 +161,12 @@ public abstract class Contraption {
|
||||||
specialRenderedTileEntities = new ArrayList<>();
|
specialRenderedTileEntities = new ArrayList<>();
|
||||||
pendingSubContraptions = new ArrayList<>();
|
pendingSubContraptions = new ArrayList<>();
|
||||||
stabilizedSubContraptions = new HashMap<>();
|
stabilizedSubContraptions = new HashMap<>();
|
||||||
|
simplifiedEntityColliders = Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContraptionWorld getContraptionWorld() {
|
public ContraptionWorld getContraptionWorld() {
|
||||||
if (world == null) {
|
if (world == null)
|
||||||
world = new ContraptionWorld(entity.world, this);
|
world = new ContraptionWorld(entity.world, this);
|
||||||
}
|
|
||||||
|
|
||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,6 +193,8 @@ public abstract class Contraption {
|
||||||
String type = nbt.getString("Type");
|
String type = nbt.getString("Type");
|
||||||
Contraption contraption = ContraptionType.fromType(type);
|
Contraption contraption = ContraptionType.fromType(type);
|
||||||
contraption.readNBT(world, nbt, spawnData);
|
contraption.readNBT(world, nbt, spawnData);
|
||||||
|
contraption.world = new ContraptionWorld(world, contraption);
|
||||||
|
contraption.gatherBBsOffThread();
|
||||||
return contraption;
|
return contraption;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,6 +258,14 @@ public abstract class Contraption {
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
fluidInventory = new CombinedTankWrapper(
|
fluidInventory = new CombinedTankWrapper(
|
||||||
Arrays.copyOf(fluidHandlers.toArray(), fluidHandlers.size(), IFluidHandler[].class));
|
Arrays.copyOf(fluidHandlers.toArray(), fluidHandlers.size(), IFluidHandler[].class));
|
||||||
|
gatherBBsOffThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onEntityRemoved(AbstractContraptionEntity entity) {
|
||||||
|
if (simplifiedEntityColliderProvider != null) {
|
||||||
|
simplifiedEntityColliderProvider.cancel(false);
|
||||||
|
simplifiedEntityColliderProvider = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onEntityInitialize(World world, AbstractContraptionEntity contraptionEntity) {
|
public void onEntityInitialize(World world, AbstractContraptionEntity contraptionEntity) {
|
||||||
|
@ -1136,6 +1179,28 @@ public abstract class Contraption {
|
||||||
return new EmptyLighter(this);
|
return new EmptyLighter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void gatherBBsOffThread() {
|
||||||
|
getContraptionWorld();
|
||||||
|
simplifiedEntityColliderProvider = CompletableFuture.supplyAsync(() -> {
|
||||||
|
VoxelShape combinedShape = VoxelShapes.empty();
|
||||||
|
for (Entry<BlockPos, BlockInfo> entry : blocks.entrySet()) {
|
||||||
|
BlockInfo info = entry.getValue();
|
||||||
|
BlockPos localPos = entry.getKey();
|
||||||
|
VoxelShape collisionShape = info.state.getCollisionShape(world, localPos);
|
||||||
|
if (collisionShape.isEmpty())
|
||||||
|
continue;
|
||||||
|
combinedShape = VoxelShapes.combine(combinedShape,
|
||||||
|
collisionShape.withOffset(localPos.getX(), localPos.getY(), localPos.getZ()), IBooleanFunction.OR);
|
||||||
|
}
|
||||||
|
return combinedShape.simplify()
|
||||||
|
.toBoundingBoxList();
|
||||||
|
})
|
||||||
|
.thenAccept(r -> {
|
||||||
|
simplifiedEntityColliders = Optional.of(r);
|
||||||
|
simplifiedEntityColliderProvider = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public static float getRadius(Set<BlockPos> blocks, Direction.Axis axis) {
|
public static float getRadius(Set<BlockPos> blocks, Direction.Axis axis) {
|
||||||
switch (axis) {
|
switch (axis) {
|
||||||
case X:
|
case X:
|
||||||
|
|
|
@ -22,6 +22,7 @@ import com.simibubi.create.foundation.collision.ContinuousOBBCollider.Continuous
|
||||||
import com.simibubi.create.foundation.collision.Matrix3d;
|
import com.simibubi.create.foundation.collision.Matrix3d;
|
||||||
import com.simibubi.create.foundation.collision.OrientedBB;
|
import com.simibubi.create.foundation.collision.OrientedBB;
|
||||||
import com.simibubi.create.foundation.networking.AllPackets;
|
import com.simibubi.create.foundation.networking.AllPackets;
|
||||||
|
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
|
@ -36,6 +37,8 @@ import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.Direction.Axis;
|
import net.minecraft.util.Direction.Axis;
|
||||||
import net.minecraft.util.Direction.AxisDirection;
|
import net.minecraft.util.Direction.AxisDirection;
|
||||||
import net.minecraft.util.ReuseableStream;
|
import net.minecraft.util.ReuseableStream;
|
||||||
|
import net.minecraft.util.SoundCategory;
|
||||||
|
import net.minecraft.util.SoundEvents;
|
||||||
import net.minecraft.util.math.AxisAlignedBB;
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
@ -103,42 +106,56 @@ public class ContraptionCollider {
|
||||||
AxisAlignedBB entityBounds = entity.getBoundingBox();
|
AxisAlignedBB entityBounds = entity.getBoundingBox();
|
||||||
Vector3d motion = entity.getMotion();
|
Vector3d motion = entity.getMotion();
|
||||||
float yawOffset = rotation.getYawOffset();
|
float yawOffset = rotation.getYawOffset();
|
||||||
|
|
||||||
Vector3d position = getWorldToLocalTranslation(entity, anchorVec, rotationMatrix, yawOffset);
|
Vector3d position = getWorldToLocalTranslation(entity, anchorVec, rotationMatrix, yawOffset);
|
||||||
|
|
||||||
// Find all potential block shapes to collide with
|
// Prepare entity bounds
|
||||||
AxisAlignedBB localBB = entityBounds.offset(position)
|
AxisAlignedBB localBB = entityBounds.offset(position)
|
||||||
.grow(1.0E-7D);
|
.grow(1.0E-7D);
|
||||||
ReuseableStream<VoxelShape> potentialHits =
|
|
||||||
getPotentiallyCollidedShapes(world, contraption, localBB.expand(motion));
|
|
||||||
if (potentialHits.createStream()
|
|
||||||
.count() == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Prepare entity bounds
|
|
||||||
OrientedBB obb = new OrientedBB(localBB);
|
OrientedBB obb = new OrientedBB(localBB);
|
||||||
obb.setRotation(rotationMatrix);
|
obb.setRotation(rotationMatrix);
|
||||||
motion = motion.subtract(contraptionMotion);
|
motion = motion.subtract(contraptionMotion);
|
||||||
motion = rotationMatrix.transform(motion);
|
motion = rotationMatrix.transform(motion);
|
||||||
|
|
||||||
|
// Use simplified bbs when present
|
||||||
|
final Vector3d motionCopy = motion;
|
||||||
|
List<AxisAlignedBB> collidableBBs = contraption.simplifiedEntityColliders.orElseGet(() -> {
|
||||||
|
|
||||||
|
// Else find 'nearby' individual block shapes to collide with
|
||||||
|
List<AxisAlignedBB> bbs = new ArrayList<>();
|
||||||
|
ReuseableStream<VoxelShape> potentialHits =
|
||||||
|
getPotentiallyCollidedShapes(world, contraption, localBB.expand(motionCopy));
|
||||||
|
potentialHits.createStream()
|
||||||
|
.forEach(shape -> shape.toBoundingBoxList()
|
||||||
|
.forEach(bbs::add));
|
||||||
|
return bbs;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
MutableObject<Vector3d> collisionResponse = new MutableObject<>(Vector3d.ZERO);
|
MutableObject<Vector3d> collisionResponse = new MutableObject<>(Vector3d.ZERO);
|
||||||
|
MutableObject<Vector3d> normal = new MutableObject<>(Vector3d.ZERO);
|
||||||
|
MutableObject<Vector3d> location = new MutableObject<>(Vector3d.ZERO);
|
||||||
MutableBoolean surfaceCollision = new MutableBoolean(false);
|
MutableBoolean surfaceCollision = new MutableBoolean(false);
|
||||||
MutableFloat temporalResponse = new MutableFloat(1);
|
MutableFloat temporalResponse = new MutableFloat(1);
|
||||||
Vector3d obbCenter = obb.getCenter();
|
Vector3d obbCenter = obb.getCenter();
|
||||||
|
|
||||||
// Apply separation maths
|
// Apply separation maths
|
||||||
List<AxisAlignedBB> bbs = new ArrayList<>();
|
|
||||||
potentialHits.createStream()
|
|
||||||
.forEach(shape -> shape.toBoundingBoxList()
|
|
||||||
.forEach(bbs::add));
|
|
||||||
|
|
||||||
boolean doHorizontalPass = !rotation.hasVerticalRotation();
|
boolean doHorizontalPass = !rotation.hasVerticalRotation();
|
||||||
for (boolean horizontalPass : Iterate.trueAndFalse) {
|
for (boolean horizontalPass : Iterate.trueAndFalse) {
|
||||||
boolean verticalPass = !horizontalPass || !doHorizontalPass;
|
boolean verticalPass = !horizontalPass || !doHorizontalPass;
|
||||||
|
|
||||||
for (AxisAlignedBB bb : bbs) {
|
for (AxisAlignedBB bb : collidableBBs) {
|
||||||
Vector3d currentResponse = collisionResponse.getValue();
|
Vector3d currentResponse = collisionResponse.getValue();
|
||||||
obb.setCenter(obbCenter.add(currentResponse));
|
Vector3d currentCenter = obbCenter.add(currentResponse);
|
||||||
|
|
||||||
|
if (Math.abs(currentCenter.x - bb.getCenter().x) - entityBounds.getXSize() - 1 > bb.getXSize() / 2)
|
||||||
|
continue;
|
||||||
|
if (Math.abs((currentCenter.y + motion.y) - bb.getCenter().y) - entityBounds.getYSize()
|
||||||
|
- 1 > bb.getYSize() / 2)
|
||||||
|
continue;
|
||||||
|
if (Math.abs(currentCenter.z - bb.getCenter().z) - entityBounds.getZSize() - 1 > bb.getZSize() / 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
obb.setCenter(currentCenter);
|
||||||
ContinuousSeparationManifold intersect = obb.intersect(bb, motion);
|
ContinuousSeparationManifold intersect = obb.intersect(bb, motion);
|
||||||
|
|
||||||
if (intersect == null)
|
if (intersect == null)
|
||||||
|
@ -147,15 +164,28 @@ public class ContraptionCollider {
|
||||||
surfaceCollision.setValue(intersect.isSurfaceCollision());
|
surfaceCollision.setValue(intersect.isSurfaceCollision());
|
||||||
|
|
||||||
double timeOfImpact = intersect.getTimeOfImpact();
|
double timeOfImpact = intersect.getTimeOfImpact();
|
||||||
if (timeOfImpact > 0 && timeOfImpact < 1) {
|
boolean isTemporal = timeOfImpact > 0 && timeOfImpact < 1;
|
||||||
if (temporalResponse.getValue() > timeOfImpact)
|
Vector3d collidingNormal = intersect.getCollisionNormal();
|
||||||
temporalResponse.setValue(timeOfImpact);
|
Vector3d collisionPosition = intersect.getCollisionPosition();
|
||||||
continue;
|
|
||||||
|
if (!isTemporal) {
|
||||||
|
Vector3d separation = intersect.asSeparationVec(entity.stepHeight);
|
||||||
|
if (separation != null && !separation.equals(Vector3d.ZERO)) {
|
||||||
|
collisionResponse.setValue(currentResponse.add(separation));
|
||||||
|
timeOfImpact = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3d separation = intersect.asSeparationVec(entity.stepHeight);
|
boolean nearest = timeOfImpact >= 0 && temporalResponse.getValue() > timeOfImpact;
|
||||||
if (separation != null && !separation.equals(Vector3d.ZERO))
|
if (collidingNormal != null && nearest)
|
||||||
collisionResponse.setValue(currentResponse.add(separation));
|
normal.setValue(collidingNormal);
|
||||||
|
if (collisionPosition != null && nearest)
|
||||||
|
location.setValue(collisionPosition);
|
||||||
|
|
||||||
|
if (isTemporal) {
|
||||||
|
if (temporalResponse.getValue() > timeOfImpact)
|
||||||
|
temporalResponse.setValue(timeOfImpact);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verticalPass)
|
if (verticalPass)
|
||||||
|
@ -174,6 +204,9 @@ public class ContraptionCollider {
|
||||||
|
|
||||||
// Resolve collision
|
// Resolve collision
|
||||||
Vector3d entityMotion = entity.getMotion();
|
Vector3d entityMotion = entity.getMotion();
|
||||||
|
Vector3d entityMotionNoTemporal = entityMotion;
|
||||||
|
Vector3d collisionNormal = normal.getValue();
|
||||||
|
Vector3d collisionLocation = location.getValue();
|
||||||
Vector3d totalResponse = collisionResponse.getValue();
|
Vector3d totalResponse = collisionResponse.getValue();
|
||||||
boolean hardCollision = !totalResponse.equals(Vector3d.ZERO);
|
boolean hardCollision = !totalResponse.equals(Vector3d.ZERO);
|
||||||
boolean temporalCollision = temporalResponse.getValue() != 1;
|
boolean temporalCollision = temporalResponse.getValue() != 1;
|
||||||
|
@ -186,8 +219,47 @@ public class ContraptionCollider {
|
||||||
.add(contraptionMotion);
|
.add(contraptionMotion);
|
||||||
totalResponse = rotationMatrix.transform(totalResponse);
|
totalResponse = rotationMatrix.transform(totalResponse);
|
||||||
totalResponse = VecHelper.rotate(totalResponse, yawOffset, Axis.Y);
|
totalResponse = VecHelper.rotate(totalResponse, yawOffset, Axis.Y);
|
||||||
|
collisionNormal = rotationMatrix.transform(collisionNormal);
|
||||||
|
collisionNormal = VecHelper.rotate(collisionNormal, yawOffset, Axis.Y);
|
||||||
|
collisionLocation = rotationMatrix.transform(collisionLocation);
|
||||||
|
collisionLocation = VecHelper.rotate(collisionLocation, yawOffset, Axis.Y);
|
||||||
rotationMatrix.transpose();
|
rotationMatrix.transpose();
|
||||||
|
|
||||||
|
double bounce = 0;
|
||||||
|
double slide = 0;
|
||||||
|
|
||||||
|
if (!collisionLocation.equals(Vector3d.ZERO)) {
|
||||||
|
collisionLocation = collisionLocation.add(entity.getPositionVec()
|
||||||
|
.add(entity.getBoundingBox()
|
||||||
|
.getCenter())
|
||||||
|
.scale(.5f));
|
||||||
|
if (temporalCollision)
|
||||||
|
collisionLocation = collisionLocation.add(0, motionResponse.y, 0);
|
||||||
|
BlockPos pos = new BlockPos(contraptionEntity.toLocalVector(collisionLocation, 0));
|
||||||
|
if (contraption.getBlocks()
|
||||||
|
.containsKey(pos)) {
|
||||||
|
BlockState blockState = contraption.getBlocks()
|
||||||
|
.get(pos).state;
|
||||||
|
bounce = BlockHelper.getBounceMultiplier(blockState.getBlock());
|
||||||
|
slide = Math.max(0, blockState.getSlipperiness(contraption.world, pos, entity) - .6f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasNormal = !collisionNormal.equals(Vector3d.ZERO);
|
||||||
|
boolean anyCollision = hardCollision || temporalCollision;
|
||||||
|
|
||||||
|
if (bounce > 0 && hasNormal && anyCollision) {
|
||||||
|
collisionNormal = collisionNormal.normalize();
|
||||||
|
Vector3d newNormal = collisionNormal.crossProduct(collisionNormal.crossProduct(entityMotionNoTemporal))
|
||||||
|
.normalize();
|
||||||
|
if (bounceEntity(entity, newNormal, contraptionEntity, bounce)) {
|
||||||
|
entity.world.playSound(playerType == PlayerType.CLIENT ? (PlayerEntity) entity : null,
|
||||||
|
entity.getX(), entity.getY(), entity.getZ(), SoundEvents.BLOCK_SLIME_BLOCK_FALL,
|
||||||
|
SoundCategory.BLOCKS, .5f, 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (temporalCollision) {
|
if (temporalCollision) {
|
||||||
double idealVerticalMotion = motionResponse.y;
|
double idealVerticalMotion = motionResponse.y;
|
||||||
if (idealVerticalMotion != entityMotion.y) {
|
if (idealVerticalMotion != entityMotion.y) {
|
||||||
|
@ -215,6 +287,18 @@ public class ContraptionCollider {
|
||||||
entityMotion = entityMotion.mul(1, 1, 0);
|
entityMotion = entityMotion.mul(1, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bounce == 0 && slide > 0 && hasNormal && anyCollision && rotation.hasVerticalRotation()) {
|
||||||
|
collisionNormal = collisionNormal.normalize();
|
||||||
|
Vector3d motionIn = entityMotionNoTemporal.mul(0, 1, 0)
|
||||||
|
.add(0, -.01f, 0);
|
||||||
|
Vector3d slideNormal = collisionNormal.crossProduct(motionIn.crossProduct(collisionNormal))
|
||||||
|
.normalize();
|
||||||
|
entity.setMotion(entityMotion.mul(.8, 0, .8)
|
||||||
|
.add(slideNormal.scale((.2f + slide) * motionIn.length())
|
||||||
|
.add(0, -0.1, 0)));
|
||||||
|
entityMotion = entity.getMotion();
|
||||||
|
}
|
||||||
|
|
||||||
if (!hardCollision && surfaceCollision.isFalse())
|
if (!hardCollision && surfaceCollision.isFalse())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -228,10 +312,14 @@ public class ContraptionCollider {
|
||||||
|
|
||||||
if (surfaceCollision.isTrue()) {
|
if (surfaceCollision.isTrue()) {
|
||||||
entity.fallDistance = 0;
|
entity.fallDistance = 0;
|
||||||
entity.setOnGround(true);
|
|
||||||
contraptionEntity.collidingEntities.put(entity, new MutableInt(0));
|
contraptionEntity.collidingEntities.put(entity, new MutableInt(0));
|
||||||
if (entity instanceof ItemEntity)
|
boolean canWalk = bounce != 0 || slide == 0;
|
||||||
entityMotion = entityMotion.mul(.5f, 1, .5f);
|
if (canWalk || !rotation.hasVerticalRotation()) {
|
||||||
|
if (canWalk)
|
||||||
|
entity.onGround = true;
|
||||||
|
if (entity instanceof ItemEntity)
|
||||||
|
entityMotion = entityMotion.mul(.5f, 1, .5f);
|
||||||
|
}
|
||||||
contactPointMotion = contraptionEntity.getContactPointMotion(entityPosition);
|
contactPointMotion = contraptionEntity.getContactPointMotion(entityPosition);
|
||||||
allowedMovement = getAllowedMovement(contactPointMotion, entity);
|
allowedMovement = getAllowedMovement(contactPointMotion, entity);
|
||||||
entity.setPosition(entityPosition.x + allowedMovement.x, entityPosition.y,
|
entity.setPosition(entityPosition.x + allowedMovement.x, entityPosition.y,
|
||||||
|
@ -253,6 +341,42 @@ public class ContraptionCollider {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean bounceEntity(Entity entity, Vector3d normal, AbstractContraptionEntity contraption, double factor) {
|
||||||
|
if (factor == 0)
|
||||||
|
return false;
|
||||||
|
if (entity.bypassesLandingEffects())
|
||||||
|
return false;
|
||||||
|
if (normal.equals(Vector3d.ZERO))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Vector3d contraptionVec = Vector3d.ZERO;
|
||||||
|
Vector3d contactPointMotion = contraption.getContactPointMotion(entity.getPositionVec());
|
||||||
|
Vector3d motion = entity.getMotion()
|
||||||
|
.subtract(contactPointMotion);
|
||||||
|
|
||||||
|
Vector3d v2 = motion.crossProduct(normal)
|
||||||
|
.normalize();
|
||||||
|
if (v2 != Vector3d.ZERO)
|
||||||
|
contraptionVec = normal.scale(contraptionVec.dotProduct(normal))
|
||||||
|
.add(v2.scale(contraptionVec.dotProduct(v2)));
|
||||||
|
else
|
||||||
|
v2 = normal.crossProduct(normal.add(Math.random(), Math.random(), Math.random()))
|
||||||
|
.normalize();
|
||||||
|
|
||||||
|
Vector3d v3 = normal.crossProduct(v2);
|
||||||
|
motion = motion.subtract(contraptionVec);
|
||||||
|
Vector3d lr = new Vector3d(factor * motion.dotProduct(normal), -motion.dotProduct(v2), -motion.dotProduct(v3));
|
||||||
|
|
||||||
|
if (lr.dotProduct(lr) > 1 / 16f) {
|
||||||
|
Vector3d newMot = contactPointMotion.add(normal.x * lr.x + v2.x * lr.y + v3.x * lr.z,
|
||||||
|
normal.y * lr.x + v2.y * lr.y + v3.y * lr.z, normal.z * lr.x + v2.z * lr.y + v3.z * lr.z);
|
||||||
|
entity.setMotion(newMot);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static Vector3d getWorldToLocalTranslation(Entity entity, AbstractContraptionEntity contraptionEntity) {
|
public static Vector3d getWorldToLocalTranslation(Entity entity, AbstractContraptionEntity contraptionEntity) {
|
||||||
return getWorldToLocalTranslation(entity, contraptionEntity.getAnchorVec(), contraptionEntity.getRotationState());
|
return getWorldToLocalTranslation(entity, contraptionEntity.getAnchorVec(), contraptionEntity.getRotationState());
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,24 +36,25 @@ public class ContinuousOBBCollider extends OBBCollider {
|
||||||
checkCount = 0;
|
checkCount = 0;
|
||||||
mf.stepSeparationAxis = uB1;
|
mf.stepSeparationAxis = uB1;
|
||||||
mf.stepSeparation = Double.MAX_VALUE;
|
mf.stepSeparation = Double.MAX_VALUE;
|
||||||
|
mf.normalSeparation = Double.MAX_VALUE;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
// Separate along A's local axes (global XYZ)
|
// Separate along A's local axes (global XYZ)
|
||||||
!(separate(mf, uA0, diff.x, eA.x, a00 * eB.x + a01 * eB.y + a02 * eB.z, motion.x)
|
!(separate(mf, uA0, diff.x, eA.x, a00 * eB.x + a01 * eB.y + a02 * eB.z, motion.x, true)
|
||||||
|| separate(mf, uA1, diff.y, eA.y, a10 * eB.x + a11 * eB.y + a12 * eB.z, motion.y)
|
|| separate(mf, uA1, diff.y, eA.y, a10 * eB.x + a11 * eB.y + a12 * eB.z, motion.y, true)
|
||||||
|| separate(mf, uA2, diff.z, eA.z, a20 * eB.x + a21 * eB.y + a22 * eB.z, motion.z)
|
|| separate(mf, uA2, diff.z, eA.z, a20 * eB.x + a21 * eB.y + a22 * eB.z, motion.z, true)
|
||||||
|
|
||||||
// Separate along B's local axes
|
// Separate along B's local axes
|
||||||
|| separate(mf, uB0, diff2.x, eA.x * a00 + eA.y * a10 + eA.z * a20, eB.x, motion2.x)
|
|| separate(mf, uB0, diff2.x, eA.x * a00 + eA.y * a10 + eA.z * a20, eB.x, motion2.x, false)
|
||||||
|| separate(mf, uB1, diff2.y, eA.x * a01 + eA.y * a11 + eA.z * a21, eB.y, motion2.y)
|
|| separate(mf, uB1, diff2.y, eA.x * a01 + eA.y * a11 + eA.z * a21, eB.y, motion2.y, false)
|
||||||
|| separate(mf, uB2, diff2.z, eA.x * a02 + eA.y * a12 + eA.z * a22, eB.z, motion2.z)))
|
|| separate(mf, uB2, diff2.z, eA.x * a02 + eA.y * a12 + eA.z * a22, eB.z, motion2.z, false)))
|
||||||
return mf;
|
return mf;
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean separate(ContinuousSeparationManifold mf, Vector3d axis, double TL, double rA, double rB,
|
static boolean separate(ContinuousSeparationManifold mf, Vector3d axis, double TL, double rA, double rB,
|
||||||
double projectedMotion) {
|
double projectedMotion, boolean axisOfObjA) {
|
||||||
checkCount++;
|
checkCount++;
|
||||||
double distance = abs(TL);
|
double distance = abs(TL);
|
||||||
double diff = distance - (rA + rB);
|
double diff = distance - (rA + rB);
|
||||||
|
@ -82,7 +83,12 @@ public class ContinuousOBBCollider extends OBBCollider {
|
||||||
Vector3d normalizedAxis = axis.normalize();
|
Vector3d normalizedAxis = axis.normalize();
|
||||||
|
|
||||||
boolean isBestSeperation = distance != 0 && -(diff) <= abs(mf.separation);
|
boolean isBestSeperation = distance != 0 && -(diff) <= abs(mf.separation);
|
||||||
// boolean isBestSeperation = discreteCollision && checkCount == 5; // Debug specific separations
|
// boolean isBestSeperation = discreteCollision && checkCount == 5; // Debug specific separations
|
||||||
|
|
||||||
|
if (axisOfObjA && distance != 0 && -(diff) <= abs(mf.normalSeparation)) {
|
||||||
|
mf.normalAxis = normalizedAxis;
|
||||||
|
mf.normalSeparation = seperation;
|
||||||
|
}
|
||||||
|
|
||||||
double dot = mf.stepSeparationAxis.dotProduct(axis);
|
double dot = mf.stepSeparationAxis.dotProduct(axis);
|
||||||
if (dot != 0 && discreteCollision) {
|
if (dot != 0 && discreteCollision) {
|
||||||
|
@ -98,45 +104,19 @@ public class ContinuousOBBCollider extends OBBCollider {
|
||||||
stepSeparationVec =
|
stepSeparationVec =
|
||||||
sepVec.subtract(axisPlane.scale(sepVec.dotProduct(stepPlane) / axisPlane.dotProduct(stepPlane)));
|
sepVec.subtract(axisPlane.scale(sepVec.dotProduct(stepPlane) / axisPlane.dotProduct(stepPlane)));
|
||||||
stepSeparation = stepSeparationVec.length();
|
stepSeparation = stepSeparationVec.length();
|
||||||
|
if (abs(mf.stepSeparation) > abs(stepSeparation) && stepSeparation != 0)
|
||||||
|
|
||||||
if (abs(mf.stepSeparation) > abs(stepSeparation) && stepSeparation != 0) {
|
|
||||||
// CollisionDebugger.showDebugLine(Vector3d.ZERO, sepVec, 0x111155, "stepsep", -16);
|
|
||||||
mf.stepSeparation = stepSeparation;
|
mf.stepSeparation = stepSeparation;
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (abs(mf.stepSeparation) > stepSeparation) {
|
if (abs(mf.stepSeparation) > stepSeparation)
|
||||||
mf.stepSeparation = stepSeparation;
|
mf.stepSeparation = stepSeparation;
|
||||||
// CollisionDebugger.showDebugLine(Vector3d.ZERO, stepSeparationVec, 0xff9999, "axis", -16);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (abs(mf.separation) < abs(stepSeparation) && stepSeparation != 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isBestSeperation) {
|
if (isBestSeperation) {
|
||||||
|
|
||||||
mf.axis = normalizedAxis;
|
mf.axis = normalizedAxis;
|
||||||
mf.separation = seperation;
|
mf.separation = seperation;
|
||||||
|
mf.collisionPosition = normalizedAxis.scale(signum(TL) * (axisOfObjA ? -rB : -rB) - signum(seperation) * .125f);
|
||||||
// Visualize values
|
|
||||||
// if (CollisionDebugger.AABB != null) {
|
|
||||||
// Vector3d normalizedAxis = axis.normalize();
|
|
||||||
// showDebugLine(Vector3d.ZERO, normalizedAxis.scale(projectedMotion), 0x111155, "motion", 5);
|
|
||||||
// showDebugLine(Vector3d.ZERO, normalizedAxis.scale(TL), 0xbb00bb, "tl", 4);
|
|
||||||
// showDebugLine(Vector3d.ZERO, normalizedAxis.scale(sTL * rA), 0xff4444, "ra", 3);
|
|
||||||
// showDebugLine(normalizedAxis.scale(sTL * rA),
|
|
||||||
// normalizedAxis.scale(sTL * rA - entryTime * projectedMotion), 0x44ff44, "entry", 0);
|
|
||||||
// showDebugLine(normalizedAxis.scale(sTL * rA - entryTime * projectedMotion),
|
|
||||||
// normalizedAxis.scale(sTL * rA - entryTime * projectedMotion + exitTime * projectedMotion), 0x44ffff,
|
|
||||||
// "exit", -1);
|
|
||||||
// showDebugLine(normalizedAxis.scale(sTL * (distance - rB)), normalizedAxis.scale(TL), 0x4444ff, "rb", 2);
|
|
||||||
// showDebugLine(normalizedAxis.scale(sTL * (distance - rB)),
|
|
||||||
// normalizedAxis.scale(sTL * (distance - rB) + value), 0xff9966, "separation", 1);
|
|
||||||
//// System.out.println("TL:" + TL + ", rA: " + rA + ", rB: " + rB);
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -148,10 +128,14 @@ public class ContinuousOBBCollider extends OBBCollider {
|
||||||
double latestCollisionEntryTime = UNDEFINED;
|
double latestCollisionEntryTime = UNDEFINED;
|
||||||
double earliestCollisionExitTime = Double.MAX_VALUE;
|
double earliestCollisionExitTime = Double.MAX_VALUE;
|
||||||
boolean isDiscreteCollision = true;
|
boolean isDiscreteCollision = true;
|
||||||
|
Vector3d collisionPosition;
|
||||||
|
|
||||||
Vector3d stepSeparationAxis;
|
Vector3d stepSeparationAxis;
|
||||||
double stepSeparation;
|
double stepSeparation;
|
||||||
|
|
||||||
|
Vector3d normalAxis;
|
||||||
|
double normalSeparation;
|
||||||
|
|
||||||
public double getTimeOfImpact() {
|
public double getTimeOfImpact() {
|
||||||
if (latestCollisionEntryTime == UNDEFINED)
|
if (latestCollisionEntryTime == UNDEFINED)
|
||||||
return UNDEFINED;
|
return UNDEFINED;
|
||||||
|
@ -164,9 +148,17 @@ public class ContinuousOBBCollider extends OBBCollider {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector3d getCollisionNormal() {
|
||||||
|
return normalAxis == null ? null : createSeparationVec(normalSeparation, normalAxis);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3d getCollisionPosition() {
|
||||||
|
return collisionPosition;
|
||||||
|
}
|
||||||
|
|
||||||
public Vector3d asSeparationVec(double obbStepHeight) {
|
public Vector3d asSeparationVec(double obbStepHeight) {
|
||||||
if (isDiscreteCollision) {
|
if (isDiscreteCollision) {
|
||||||
if (stepSeparation <= obbStepHeight)
|
if (stepSeparation <= obbStepHeight)
|
||||||
return createSeparationVec(stepSeparation, stepSeparationAxis);
|
return createSeparationVec(stepSeparation, stepSeparationAxis);
|
||||||
return super.asSeparationVec();
|
return super.asSeparationVec();
|
||||||
}
|
}
|
||||||
|
@ -175,7 +167,7 @@ public class ContinuousOBBCollider extends OBBCollider {
|
||||||
return null;
|
return null;
|
||||||
return Vector3d.ZERO;
|
return Vector3d.ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector3d asSeparationVec() {
|
public Vector3d asSeparationVec() {
|
||||||
return asSeparationVec(0);
|
return asSeparationVec(0);
|
||||||
|
|
|
@ -16,6 +16,7 @@ import net.minecraft.util.math.vector.Vector3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.gen.feature.template.Template;
|
import net.minecraft.world.gen.feature.template.Template;
|
||||||
import org.apache.logging.log4j.util.TriConsumer;
|
import org.apache.logging.log4j.util.TriConsumer;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
@ -30,10 +31,12 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Mixin(Entity.class)
|
@Mixin(Entity.class)
|
||||||
public abstract class StepSoundMixin {
|
public abstract class StepSoundMixin {
|
||||||
|
private final Entity self = (Entity) (Object) this;
|
||||||
|
|
||||||
@Shadow
|
@Shadow
|
||||||
public World world;
|
public World world;
|
||||||
|
|
||||||
|
@Final
|
||||||
@Shadow
|
@Shadow
|
||||||
protected Random rand;
|
protected Random rand;
|
||||||
|
|
||||||
|
@ -55,21 +58,20 @@ public abstract class StepSoundMixin {
|
||||||
@Shadow
|
@Shadow
|
||||||
protected abstract void playStepSound(BlockPos p_180429_1_, BlockState p_180429_2_);
|
protected abstract void playStepSound(BlockPos p_180429_1_, BlockState p_180429_2_);
|
||||||
|
|
||||||
private Set<AbstractContraptionEntity> getIntersectingContraptions(Entity entity) {
|
private Set<AbstractContraptionEntity> getIntersectingContraptions() {
|
||||||
Set<AbstractContraptionEntity> contraptions = ContraptionHandler.loadedContraptions.get(entity.world)
|
Set<AbstractContraptionEntity> contraptions = ContraptionHandler.loadedContraptions.get(this.world)
|
||||||
.values()
|
.values()
|
||||||
.stream()
|
.stream()
|
||||||
.map(Reference::get)
|
.map(Reference::get)
|
||||||
.filter(cEntity -> cEntity != null && cEntity.collidingEntities.containsKey(entity))
|
.filter(cEntity -> cEntity != null && cEntity.collidingEntities.containsKey(self))
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
contraptions.addAll(entity.world.getEntitiesWithinAABB(AbstractContraptionEntity.class, getBoundingBox().grow(1f)));
|
contraptions.addAll(this.world.getEntitiesWithinAABB(AbstractContraptionEntity.class, getBoundingBox().grow(1f)));
|
||||||
return contraptions;
|
return contraptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void forCollision(Vector3d anchorPos, TriConsumer<Contraption, BlockState, BlockPos> action) {
|
private void forCollision(Vector3d anchorPos, TriConsumer<Contraption, BlockState, BlockPos> action) {
|
||||||
Entity thi = (Entity) (Object) this;
|
getIntersectingContraptions().forEach(cEntity -> {
|
||||||
getIntersectingContraptions(thi).forEach(cEntity -> {
|
|
||||||
Vector3d localPos = ContraptionCollider.getWorldToLocalTranslation(anchorPos, cEntity);
|
Vector3d localPos = ContraptionCollider.getWorldToLocalTranslation(anchorPos, cEntity);
|
||||||
|
|
||||||
localPos = anchorPos.add(localPos);
|
localPos = anchorPos.add(localPos);
|
||||||
|
@ -87,15 +89,14 @@ public abstract class StepSoundMixin {
|
||||||
|
|
||||||
@Inject(at = @At(
|
@Inject(at = @At(
|
||||||
value = "JUMP",
|
value = "JUMP",
|
||||||
opcode = 154, //IFNE
|
opcode = 154, // IFNE line 587 injecting before `!blockstate.isAir(this.world, blockpos)`
|
||||||
ordinal = 4
|
ordinal = 4
|
||||||
),
|
),
|
||||||
method = "move"
|
method = "move"
|
||||||
)
|
)
|
||||||
private void movementMixin(MoverType mover, Vector3d movement, CallbackInfo ci) {
|
private void movementMixin(MoverType mover, Vector3d movement, CallbackInfo ci) {
|
||||||
Entity thi = (Entity) (Object) this;
|
|
||||||
World entityWorld = world;
|
World entityWorld = world;
|
||||||
Vector3d worldPos = thi.getPositionVec().add(0, -0.2, 0);
|
Vector3d worldPos = self.getPositionVec().add(0, -0.2, 0);
|
||||||
AtomicBoolean stepped = new AtomicBoolean(false);
|
AtomicBoolean stepped = new AtomicBoolean(false);
|
||||||
|
|
||||||
forCollision(worldPos, (contraption, blockstate, blockPos) -> {
|
forCollision(worldPos, (contraption, blockstate, blockPos) -> {
|
||||||
|
@ -110,19 +111,18 @@ public abstract class StepSoundMixin {
|
||||||
world = entityWorld;
|
world = entityWorld;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = {"Lnet/minecraft/entity/Entity;spawnSprintingParticles()V"}, at = @At(value = "TAIL"))
|
@Inject(method = {"spawnSprintingParticles"}, at = @At(value = "TAIL"))
|
||||||
private void createRunningParticlesMixin(CallbackInfo ci) {
|
private void createRunningParticlesMixin(CallbackInfo ci) {
|
||||||
Entity thi = (Entity) (Object) this;
|
Vector3d worldPos = self.getPositionVec().add(0, -0.2, 0);
|
||||||
Vector3d worldPos = thi.getPositionVec().add(0, -0.2, 0);
|
|
||||||
BlockPos pos = new BlockPos(worldPos); // pos where particles are spawned
|
BlockPos pos = new BlockPos(worldPos); // pos where particles are spawned
|
||||||
|
|
||||||
forCollision(worldPos, (contraption, blockstate, blockpos) -> {
|
forCollision(worldPos, (contraption, blockstate, blockpos) -> {
|
||||||
if (!blockstate.addRunningEffects(world, blockpos, thi) && blockstate.getRenderType() != BlockRenderType.INVISIBLE) {
|
if (!blockstate.addRunningEffects(world, blockpos, self) && blockstate.getRenderType() != BlockRenderType.INVISIBLE) {
|
||||||
Vector3d Vector3d = thi.getMotion();
|
Vector3d vec3d = self.getMotion();
|
||||||
this.world.addParticle(new BlockParticleData(ParticleTypes.BLOCK, blockstate).setPos(pos),
|
this.world.addParticle(new BlockParticleData(ParticleTypes.BLOCK, blockstate).setPos(pos),
|
||||||
thi.getX() + ((double) rand.nextFloat() - 0.5D) * (double) thi.getWidth(),
|
self.getX() + ((double) rand.nextFloat() - 0.5D) * (double) self.getWidth(),
|
||||||
thi.getY() + 0.1D, thi.getZ() + ((double) rand.nextFloat() - 0.5D) * (double) thi.getWidth(),
|
self.getY() + 0.1D, self.getZ() + ((double) rand.nextFloat() - 0.5D) * (double) self.getWidth(),
|
||||||
Vector3d.x * -4.0D, 1.5D, Vector3d.z * -4.0D);
|
vec3d.x * -4.0D, 1.5D, vec3d.z * -4.0D);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,13 @@ import org.apache.commons.lang3.mutable.MutableInt;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.components.actors.SeatBlock;
|
||||||
|
|
||||||
|
import net.minecraft.block.BedBlock;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
|
import net.minecraft.block.SlimeBlock;
|
||||||
import net.minecraft.client.particle.DiggingParticle;
|
import net.minecraft.client.particle.DiggingParticle;
|
||||||
import net.minecraft.client.particle.ParticleManager;
|
import net.minecraft.client.particle.ParticleManager;
|
||||||
import net.minecraft.client.world.ClientWorld;
|
import net.minecraft.client.world.ClientWorld;
|
||||||
|
@ -260,6 +263,14 @@ public class BlockHelper {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static double getBounceMultiplier(Block block) {
|
||||||
|
if (block instanceof SlimeBlock)
|
||||||
|
return 0.8D;
|
||||||
|
if (block instanceof BedBlock || block instanceof SeatBlock)
|
||||||
|
return 0.66 * 0.8D;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean hasBlockSolidSide(BlockState p_220056_0_, IBlockReader p_220056_1_, BlockPos p_220056_2_, Direction p_220056_3_) {
|
public static boolean hasBlockSolidSide(BlockState p_220056_0_, IBlockReader p_220056_1_, BlockPos p_220056_2_, Direction p_220056_3_) {
|
||||||
return !p_220056_0_.isIn(BlockTags.LEAVES) && Block.doesSideFillSquare(p_220056_0_.getCollisionShape(p_220056_1_, p_220056_2_), p_220056_3_);
|
return !p_220056_0_.isIn(BlockTags.LEAVES) && Block.doesSideFillSquare(p_220056_0_.getCollisionShape(p_220056_1_, p_220056_2_), p_220056_3_);
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
"package": "com.simibubi.create.foundation.mixin",
|
"package": "com.simibubi.create.foundation.mixin",
|
||||||
"compatibilityLevel": "JAVA_8",
|
"compatibilityLevel": "JAVA_8",
|
||||||
"refmap": "create.refmap.json",
|
"refmap": "create.refmap.json",
|
||||||
"mixins": ["StepSoundMixin"],
|
|
||||||
"client": [
|
"client": [
|
||||||
"TileWorldHookMixin",
|
"TileWorldHookMixin",
|
||||||
"CancelTileEntityRenderMixin",
|
"CancelTileEntityRenderMixin",
|
||||||
|
@ -13,7 +12,8 @@
|
||||||
"NetworkLightUpdateMixin",
|
"NetworkLightUpdateMixin",
|
||||||
"RenderHooksMixin",
|
"RenderHooksMixin",
|
||||||
"ShaderCloseMixin",
|
"ShaderCloseMixin",
|
||||||
"TileRemoveMixin"
|
"TileRemoveMixin",
|
||||||
|
"StepSoundMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
|
|
Loading…
Reference in a new issue