diff --git a/gradle.properties b/gradle.properties index 79739da3d..14cb1efe7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ org.gradle.daemon=false # mod version info mod_version=0.3 minecraft_version=1.15.2 -forge_version=31.2.21 +forge_version=31.2.31 # dependency versions registrate_version=0.0.4.18 diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java index 235858024..e91c2221d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java @@ -8,7 +8,7 @@ import java.util.Iterator; import java.util.List; import java.util.concurrent.ExecutionException; -import org.apache.commons.lang3.mutable.MutableBoolean; +import org.apache.commons.lang3.mutable.MutableObject; import com.google.common.base.Predicates; import com.google.common.cache.Cache; @@ -29,6 +29,7 @@ import net.minecraft.entity.EntityType; import net.minecraft.entity.MoverType; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.AxisDirection; @@ -41,6 +42,7 @@ import net.minecraft.world.World; import net.minecraft.world.gen.feature.template.Template.BlockInfo; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.util.Constants.NBT; import net.minecraftforge.event.TickEvent.ClientTickEvent; import net.minecraftforge.event.TickEvent.Phase; import net.minecraftforge.event.TickEvent.WorldTickEvent; @@ -118,7 +120,11 @@ public class ContraptionCollider { if (bounds == null) return; - for (Entity entity : world.getEntitiesWithinAABB((EntityType) null, bounds.grow(1), + double conRotX = contraptionRotation.z; + double conRotY = contraptionRotation.y; + double conRotZ = contraptionRotation.x; + + for (Entity entity : world.getEntitiesWithinAABB((EntityType) null, bounds.grow(2), contraptionEntity::canCollideWith)) { if (entity instanceof PlayerEntity && !world.isRemote) return; @@ -127,11 +133,13 @@ public class ContraptionCollider { Vec3d entityPosition = entity.getPositionVec(); Vec3d centerY = new Vec3d(0, entity.getBoundingBox() .getYSize() / 2, 0); - Vec3d position = entityPosition.subtract(contraptionPosition) - .subtract(contraptionEntity.stationary ? centerOfBlock : Vec3d.ZERO.add(0, 0.5, 0)) - .add(centerY); - position = - VecHelper.rotate(position, -contraptionRotation.z, -contraptionRotation.y, -contraptionRotation.x); + + Vec3d position = + entityPosition.subtract(contraptionEntity.stationary ? centerOfBlock : Vec3d.ZERO.add(0, 0.5, 0)) + .add(centerY); + + position = position.subtract(contraptionPosition); + position = VecHelper.rotate(position, -conRotX, -conRotY, -conRotZ); position = position.add(centerOfBlock) .subtract(centerY) .subtract(entityPosition); @@ -139,6 +147,16 @@ public class ContraptionCollider { .offset(position) .grow(1.0E-7D); + String nbtMotionKey = "ContraptionCollisionFeedback"; + CompoundNBT entityData = entity.getPersistentData(); + Vec3d previousIntersection = Vec3d.ZERO; + if (entityData.contains(nbtMotionKey)) { + previousIntersection = VecHelper.readNBT(entityData.getList(nbtMotionKey, NBT.TAG_DOUBLE)); + entity.setMotion(entity.getMotion() + .subtract(previousIntersection.mul(1, 0, 1))); + entityData.remove(nbtMotionKey); + } + ReuseableStream potentialHits = getPotentiallyCollidedShapes(world, contraption, localBB); if (potentialHits.createStream() .count() == 0) @@ -147,51 +165,72 @@ public class ContraptionCollider { OrientedBB obb = new OrientedBB(localBB); if (!contraptionRotation.equals(Vec3d.ZERO)) { Matrix3d rotation = new Matrix3d().asIdentity(); - rotation.multiply(new Matrix3d().asXRotation(AngleHelper.rad(contraptionRotation.z))); - rotation.multiply(new Matrix3d().asYRotation(AngleHelper.rad(contraptionRotation.y))); - rotation.multiply(new Matrix3d().asZRotation(AngleHelper.rad(contraptionRotation.x))); + rotation.multiply(new Matrix3d().asXRotation(AngleHelper.rad(-conRotX))); + rotation.multiply(new Matrix3d().asYRotation(AngleHelper.rad(conRotY))); + rotation.multiply(new Matrix3d().asZRotation(AngleHelper.rad(-conRotZ))); obb.setRotation(rotation); } - MutableBoolean onCollide = new MutableBoolean(true); + MutableObject collisionResponse = new MutableObject<>(Vec3d.ZERO); + Vec3d obbCenter = obb.getCenter(); + potentialHits.createStream() .forEach(shape -> { - AxisAlignedBB bb = shape.getBoundingBox(); - Vec3d intersect = obb.intersect(bb); - if (intersect == null) - return; - intersect = VecHelper.rotate(intersect, contraptionRotation.z, contraptionRotation.y, - contraptionRotation.x); - - obb.setCenter(obb.getCenter() - .add(intersect)); - entity.move(MoverType.PISTON, intersect); - - Vec3d entityMotion = entity.getMotion(); - if (entityMotion.getX() > 0 == intersect.getX() < 0) - entityMotion = entityMotion.mul(0, 1, 1); - if (entityMotion.getY() > 0 == intersect.getY() < 0) - entityMotion = entityMotion.mul(1, 0, 1); - if (entityMotion.getZ() > 0 == intersect.getZ() < 0) - entityMotion = entityMotion.mul(1, 1, 0); - entity.setMotion(entityMotion); - - if (onCollide.isTrue()) { - onCollide.setFalse(); - contraptionEntity.collidingEntities.add(entity); - entity.velocityChanged = true; - } - - if (intersect.y > 0) { - entity.handleFallDamage(entity.fallDistance, 1); - entity.fallDistance = 0; - entity.onGround = true; - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> checkForClientPlayerCollision(entity)); - } - - if (entity instanceof ServerPlayerEntity) - ((ServerPlayerEntity) entity).connection.floatingTickCount = 0; + Vec3d currentResponse = collisionResponse.getValue(); + shape.toBoundingBoxList() + .parallelStream() + .forEach(bb -> { + obb.setCenter(obbCenter.add(currentResponse)); + Vec3d intersect = obb.intersect(bb); + if (intersect != null) + collisionResponse.setValue(currentResponse.add(intersect)); + }); }); + + Vec3d entityMotion = entity.getMotion(); + Vec3d totalResponse = collisionResponse.getValue(); + + if (totalResponse == Vec3d.ZERO) + continue; + + totalResponse = VecHelper.rotate(totalResponse, conRotX, Axis.X); + totalResponse = VecHelper.rotate(totalResponse, conRotY, Axis.Y); + totalResponse = VecHelper.rotate(totalResponse, conRotZ, Axis.Z); + + double motionX = entityMotion.getX(); + double motionY = entityMotion.getY(); + double motionZ = entityMotion.getZ(); + double intersectX = totalResponse.getX(); + double intersectY = totalResponse.getY(); + double intersectZ = totalResponse.getZ(); + + double horizonalEpsilon = 1 / 128f; + + if (motionX != 0 && Math.abs(intersectX) > horizonalEpsilon && motionX > 0 == intersectX < 0) + entityMotion = entityMotion.mul(0, 1, 1); + if (motionY != 0 && intersectY != 0 && motionY > 0 == intersectY < 0) + entityMotion = entityMotion.mul(1, 0, 1); + if (motionZ != 0 && Math.abs(intersectZ) > horizonalEpsilon && motionZ > 0 == intersectZ < 0) + entityMotion = entityMotion.mul(1, 1, 0); + + entityMotion = entityMotion.add(totalResponse.mul(1, 0, 1)); + contraptionEntity.collidingEntities.add(entity); + entity.velocityChanged = true; + + if (totalResponse.y > 0) { + entity.handleFallDamage(entity.fallDistance, 1); + entity.fallDistance = 0; + entity.onGround = true; + DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> checkForClientPlayerCollision(entity)); + } + + if (entity instanceof ServerPlayerEntity) + ((ServerPlayerEntity) entity).connection.floatingTickCount = 0; + + entity.setMotion(entityMotion); + Vec3d epos = entityPosition; + entity.setPosition(epos.x, epos.y + totalResponse.y, epos.z); + entityData.put(nbtMotionKey, VecHelper.writeNBT(totalResponse)); } } @@ -266,7 +305,14 @@ public class ContraptionCollider { public static ReuseableStream getPotentiallyCollidedShapes(World world, Contraption contraption, AxisAlignedBB localBB) { + + double height = localBB.getYSize(); + double width = localBB.getXSize(); + double horizontalFactor = (height > width && width != 0) ? height / width : 1; + double verticalFactor = (width > height && height != 0) ? width / height : 1; AxisAlignedBB blockScanBB = localBB.grow(.5f); + blockScanBB = blockScanBB.grow(horizontalFactor, verticalFactor, horizontalFactor); + BlockPos min = new BlockPos(blockScanBB.minX, blockScanBB.minY, blockScanBB.minZ); BlockPos max = new BlockPos(blockScanBB.maxX, blockScanBB.maxY, blockScanBB.maxZ); diff --git a/src/main/java/com/simibubi/create/foundation/collision/CollisionDebugger.java b/src/main/java/com/simibubi/create/foundation/collision/CollisionDebugger.java index 9901e28f4..32270f0f1 100644 --- a/src/main/java/com/simibubi/create/foundation/collision/CollisionDebugger.java +++ b/src/main/java/com/simibubi/create/foundation/collision/CollisionDebugger.java @@ -4,34 +4,31 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllSpecialTextures; import com.simibubi.create.CreateClient; import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.outliner.AABBOutline; -import net.minecraft.client.Minecraft; import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.BlockRayTraceResult; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.RayTraceResult.Type; import net.minecraft.util.math.Vec3d; public class CollisionDebugger { - static AxisAlignedBB staticBB = new AxisAlignedBB(BlockPos.ZERO.up(10)); - static OrientedBB movingBB = new OrientedBB(new AxisAlignedBB(BlockPos.ZERO)); + public static AxisAlignedBB AABB = null; + public static OrientedBB OBB = null; static Vec3d seperation; static double angle = 0; static AABBOutline outline; public static void onScroll(double delta) { - angle += delta; - movingBB.setRotation(new Matrix3d().asZRotation(AngleHelper.rad(angle))); +// angle += delta; +// movingBB = new OrientedBB(new AxisAlignedBB(BlockPos.ZERO).expand(0, 1, 0)); +// movingBB.setRotation(new Matrix3d().asZRotation(AngleHelper.rad(angle))); } public static void render(MatrixStack ms, SuperRenderTypeBuffer buffer) { + if (OBB == null) + return; ms.push(); - outline = new AABBOutline(movingBB.getAsAxisAlignedBB()); + outline = new AABBOutline(OBB.getAsAxisAlignedBB()); outline.getParams() .withFaceTexture(seperation == null ? AllSpecialTextures.CHECKERED : null) .colored(0xffffff); @@ -40,12 +37,12 @@ public class CollisionDebugger { .lineWidth(1 / 64f) .colored(0xff6544); MatrixStacker.of(ms) - .translate(movingBB.center); + .translate(OBB.center); ms.peek() .getModel() - .multiply(movingBB.rotation.getAsMatrix4f()); + .multiply(OBB.rotation.getAsMatrix4f()); MatrixStacker.of(ms) - .translateBack(movingBB.center); + .translateBack(OBB.center); outline.render(ms, buffer); ms.pop(); @@ -56,26 +53,24 @@ public class CollisionDebugger { .lineWidth(1 / 32f); MatrixStacker.of(ms) .translate(seperation) - .translate(movingBB.center); + .translate(OBB.center); ms.peek() .getModel() - .multiply(movingBB.rotation.getAsMatrix4f()); + .multiply(OBB.rotation.getAsMatrix4f()); MatrixStacker.of(ms) - .translateBack(movingBB.center); + .translateBack(OBB.center); outline.render(ms, buffer); } ms.pop(); } public static void tick() { - staticBB = new AxisAlignedBB(BlockPos.ZERO.up(60)); - RayTraceResult mouse = Minecraft.getInstance().objectMouseOver; - if (mouse != null && mouse.getType() == Type.BLOCK) { - BlockRayTraceResult hit = (BlockRayTraceResult) mouse; - movingBB.setCenter(hit.getHitVec()); - seperation = movingBB.intersect(staticBB); - } - CreateClient.outliner.showAABB(staticBB, staticBB) + if (OBB == null) + return; + if (AABB == null) + return; + seperation = OBB.intersect(AABB); + CreateClient.outliner.showAABB(AABB, AABB) .withFaceTexture(seperation == null ? AllSpecialTextures.CHECKERED : null); } diff --git a/src/main/java/com/simibubi/create/foundation/collision/OrientedBB.java b/src/main/java/com/simibubi/create/foundation/collision/OrientedBB.java index 1fa62944d..0c7a2e770 100644 --- a/src/main/java/com/simibubi/create/foundation/collision/OrientedBB.java +++ b/src/main/java/com/simibubi/create/foundation/collision/OrientedBB.java @@ -29,6 +29,10 @@ public class OrientedBB { this.extents = extents; this.setRotation(rotation); } + + public OrientedBB copy() { + return new OrientedBB(center, extents, rotation); + } public Vec3d intersect(AxisAlignedBB bb) { Vec3d extentsA = extentsFromBB(bb); @@ -152,7 +156,7 @@ public class OrientedBB { } static void showDebugLine(Vec3d relativeStart, Vec3d relativeEnd, int color, String id, int offset) { - Vec3d center = CollisionDebugger.staticBB.getCenter() + Vec3d center = CollisionDebugger.AABB.getCenter() .add(0, 1 + offset / 16f, 0); CreateClient.outliner.showLine(id + checkCount, center.add(relativeStart), center.add(relativeEnd)) .colored(color) @@ -174,6 +178,10 @@ public class OrientedBB { public void setCenter(Vec3d center) { this.center = center; } + + public void move(Vec3d offset) { + setCenter(getCenter().add(offset)); + } public AxisAlignedBB getAsAxisAlignedBB() { return new AxisAlignedBB(0, 0, 0, 0, 0, 0).offset(center) diff --git a/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java b/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java index 1ad8edf3e..3852632ff 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java @@ -26,6 +26,8 @@ public class VecHelper { public static Vec3d rotate(Vec3d vec, double deg, Axis axis) { if (deg == 0) return vec; + if (vec == Vec3d.ZERO) + return vec; float angle = (float) (deg / 180f * Math.PI); double sin = MathHelper.sin(angle);