9
0
mirror of https://github.com/Samsuik/Sakura.git synced 2025-12-23 00:39:20 +00:00
Files
SakuraMC/sakura-server/minecraft-patches/features/0015-Configure-cannon-physics.patch
2025-01-17 11:47:37 +00:00

1198 lines
62 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Samsuik <kfian294ma4@gmail.com>
Date: Tue, 21 Nov 2023 17:03:08 +0000
Subject: [PATCH] Configure cannon physics
diff --git a/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java b/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java
index 651a45b795818bd7b1364b95c52570fd99dd35e4..47c8ed946cb2ad81a4469daf60dabc40c5e8beda 100644
--- a/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java
+++ b/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java
@@ -1774,6 +1774,13 @@ public final class CollisionUtil {
}
public static Vec3 performAABBCollisions(final Vec3 moveVector, AABB axisalignedbb, final List<AABB> potentialCollisions) {
+ // Sakura start - configure cannon physics
+ return performAABBCollisions(moveVector, axisalignedbb, potentialCollisions, null);
+ }
+ public static Vec3 performAABBCollisions(final Vec3 moveVector, AABB axisalignedbb,
+ final List<AABB> potentialCollisions,
+ final me.samsuik.sakura.physics.PhysicsVersion physics) {
+ // Sakura end - configure cannon physics
double x = moveVector.x;
double y = moveVector.y;
double z = moveVector.z;
@@ -1785,7 +1792,10 @@ public final class CollisionUtil {
}
}
- final boolean xSmaller = Math.abs(x) < Math.abs(z);
+ // Sakura start - configure cannon physics
+ final boolean xSmaller = physics == null || physics.afterOrEqual(1_14_0) ? Math.abs(x) < Math.abs(z)
+ : physics.isLegacy() && Math.abs(x) > Math.abs(z);
+ // Sakura end - configure cannon physics
if (xSmaller && z != 0.0) {
z = performAABBCollisionsZ(axisalignedbb, z, potentialCollisions);
@@ -1811,9 +1821,18 @@ public final class CollisionUtil {
public static Vec3 performCollisions(final Vec3 moveVector, AABB axisalignedbb,
final List<VoxelShape> voxels,
final List<AABB> aabbs) {
+ // Sakura start - configure cannon physics
+ return performCollisions(moveVector, axisalignedbb, voxels, aabbs, null);
+ }
+
+ public static Vec3 performCollisions(final Vec3 moveVector, AABB axisalignedbb,
+ final List<VoxelShape> voxels,
+ final List<AABB> aabbs,
+ final me.samsuik.sakura.physics.PhysicsVersion physics) {
+ // Sakura end - configure cannon physics
if (voxels.isEmpty()) {
// fast track only AABBs
- return performAABBCollisions(moveVector, axisalignedbb, aabbs);
+ return performAABBCollisions(moveVector, axisalignedbb, aabbs, physics); // Sakura - configure cannon physics
}
double x = moveVector.x;
@@ -1828,7 +1847,10 @@ public final class CollisionUtil {
}
}
- final boolean xSmaller = Math.abs(x) < Math.abs(z);
+ // Sakura start - configure cannon physics
+ final boolean xSmaller = physics == null || physics.afterOrEqual(1_14_0) ? Math.abs(x) < Math.abs(z)
+ : physics.isLegacy() && Math.abs(x) > Math.abs(z);
+ // Sakura end - configure cannon physics
if (xSmaller && z != 0.0) {
z = performAABBCollisionsZ(axisalignedbb, z, aabbs);
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 8c3e0ca06f89e4d8c08d30272475cdeaca20b3ef..a6a47d9d0d8e475d936ce867cdbb8d597e71ff4e 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -580,6 +580,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
}
// Sakura end - merge cannon entities
+ // Sakura start - configure cannon physics
+ protected me.samsuik.sakura.physics.PhysicsVersion physics = me.samsuik.sakura.physics.PhysicsVersion.LATEST;
+
+ public final me.samsuik.sakura.physics.PhysicsVersion physics() {
+ return this.physics;
+ }
+ // Sakura end - configure cannon physics
public Entity(EntityType<?> entityType, Level level) {
this.type = entityType;
@@ -1092,7 +1099,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
protected void checkSupportingBlock(boolean onGround, @Nullable Vec3 movement) {
- if (onGround) {
+ if (onGround && this.physics.afterOrEqual(1_20_0)) { // Sakura - configure cannon physics
AABB boundingBox = this.getBoundingBox();
AABB aabb = new AABB(boundingBox.minX, boundingBox.minY - 1.0E-6, boundingBox.minZ, boundingBox.maxX, boundingBox.minY, boundingBox.maxZ);
Optional<BlockPos> optional = this.level.findSupportingBlock(this, aabb);
@@ -1147,7 +1154,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
if (this.noPhysics) {
this.setPos(this.getX() + movement.x, this.getY() + movement.y, this.getZ() + movement.z);
} else {
- if (movementType == MoverType.PISTON) {
+ if (movementType == MoverType.PISTON && this.physics.afterOrEqual(1_11_0)) { // Sakura - configure cannon physics
movement = this.limitPistonMovement(movement);
if (movement.equals(Vec3.ZERO)) {
return;
@@ -1165,8 +1172,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
Vec3 vec3d1 = this.sakura_collide(movement);
double d0 = vec3d1.lengthSqr();
- if (d0 > 1.0E-7D || movement.lengthSqr() - d0 < 1.0E-7D) {
- if (this.fallDistance != 0.0F && d0 >= 1.0D && !this.isFallingBlock) {
+ if (d0 > 1.0E-7D || this.physics.afterOrEqual(1_21_2) && movement.lengthSqr() - d0 < 1.0E-7D || this.physics.before(1_14_0)) { // Sakura - configure cannon physics
+ if (this.fallDistance != 0.0F && d0 >= 1.0D && !this.isFallingBlock && this.physics.afterOrEqual(1_18_2)) { // Sakura - configure cannon physics
BlockHitResult clipResult = this.level().clip(new ClipContext(this.position(), this.position().add(vec3d1), ClipContext.Block.FALLDAMAGE_RESETTING, ClipContext.Fluid.WATER, this));
if (clipResult.getType() != HitResult.Type.MISS) {
this.resetFallDistance();
@@ -1195,6 +1202,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
} else {
if (this.horizontalCollision) {
Vec3 vec3d2 = this.getDeltaMovement();
+ // Sakura start - configure cannon physics
+ if (movedX && movedZ && this.physics.isWithin(1_14_0, 1_18_1)) {
+ movedX = false;
+ }
+ // Sakura end - configure cannon physics
this.setDeltaMovement(movedX ? 0.0D : vec3d2.x, vec3d2.y, movedZ ? 0.0D : vec3d2.z);
}
@@ -1586,7 +1598,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
bb = currBoundingBox.expandTowards(movement.x, movement.y, movement.z);
}
this.collectCollisions(bb, voxelList, bbList);
- return ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.performCollisions(movement, currBoundingBox, voxelList, bbList);
+ return ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.performCollisions(movement, currBoundingBox, voxelList, bbList, this.physics); // Sakura - configure cannon physics
}
private Vec3 collideAxisScan(Vec3 movement, AABB currBoundingBox, List<VoxelShape> voxelList, List<AABB> bbList) {
@@ -1594,7 +1606,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
double y = movement.y;
double z = movement.z;
- boolean xSmaller = Math.abs(x) < Math.abs(z);
+ // Sakura start - configure cannon physics
+ boolean xSmaller = this.physics == null || this.physics.afterOrEqual(1_14_0) ? Math.abs(x) < Math.abs(z)
+ : this.physics.isLegacy() && Math.abs(x) > Math.abs(z);
+ // Sakura end - configure cannon physics
if (y != 0.0) {
y = this.scanY(currBoundingBox, y, voxelList, bbList);
@@ -1692,7 +1707,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_FLAG_CHECK_BORDER | this.getExtraCollisionFlags(), null // Sakura - load chunks on movement
);
potentialCollisionsBB.addAll(entityAABBs);
- final Vec3 collided = ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.performCollisions(movement, currentBox, potentialCollisionsVoxel, potentialCollisionsBB);
+ final Vec3 collided = ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.performCollisions(movement, currentBox, potentialCollisionsVoxel, potentialCollisionsBB, this.physics); // Sakura - configure cannon physics
final boolean collidedX = collided.x != movement.x;
final boolean collidedY = collided.y != movement.y;
@@ -1851,9 +1866,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
for (Entity.Movement movement : movements) {
Vec3 vec3 = movement.from();
Vec3 vec31 = movement.to();
- AABB aabb = this.makeBoundingBox(vec31).deflate(1.0E-5F);
-
- for (BlockPos blockPos : BlockGetter.boxTraverseBlocks(vec3, vec31, aabb)) {
+ // Sakura start - configure cannon physics
+ double margin = this.physics.afterOrEqual(1_21_2) ? 1.0E-5f : this.physics.afterOrEqual(1_19_3) ? 1.0E-7 : 0.001;
+ AABB aabb = this.makeBoundingBox(vec31).deflate(margin);
+ final Iterable<BlockPos> positions;
+ if (this.physics.afterOrEqual(1_21_2)) {
+ positions = BlockGetter.boxTraverseBlocks(vec3, vec31, aabb);
+ } else {
+ positions = BlockPos.betweenClosed(aabb);
+ }
+ for (BlockPos blockPos : positions) {
+ // Sakura end - configure cannon physics
if (!this.isAlive()) {
return;
}
diff --git a/net/minecraft/world/entity/item/FallingBlockEntity.java b/net/minecraft/world/entity/item/FallingBlockEntity.java
index f525262a153919deeeb1e6df20009b78f9e8e601..6a2bb2d4fa2ff76f85648ea39c8f0abd9b4b7e95 100644
--- a/net/minecraft/world/entity/item/FallingBlockEntity.java
+++ b/net/minecraft/world/entity/item/FallingBlockEntity.java
@@ -119,6 +119,43 @@ public class FallingBlockEntity extends Entity implements me.samsuik.sakura.enti
return itemEntity;
}
// Sakura end - merge cannon entities
+ // Sakura start - configure cannon physics
+ @Override
+ public final double distanceToSqr(Vec3 vector) {
+ if (!this.physics.isLegacy())
+ return super.distanceToSqr(vector);
+ double x = this.getX() - vector.x;
+ double y = this.getEyeY() - vector.y;
+ double z = this.getZ() - vector.z;
+ return x * x + y * y + z * z;
+ }
+
+ private BlockPos patchedBlockPosition() {
+ // mitigate the floating point issue for sand breaking below y-0
+ // 1.0e-12 allows tech that uses indirect collision clipping to still function
+ return BlockPos.containing(this.getX(), this.getY() + 1.0e-12, this.getZ());
+ }
+
+ private boolean isAbleToStackOnBlock() {
+ BlockPos pos = BlockPos.containing(this.getX(), this.getY() - 0.001f, this.getZ());
+ BlockState state = this.level().getBlockState(pos);
+ return !FallingBlock.isFree(state);
+ }
+
+ private void removeBlockOnFall(Block block) {
+ BlockPos blockposition = this.blockPosition();
+ BlockState blockstate = this.level().getBlockState(blockposition);
+
+ if (blockstate.is(block) && CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState())) {
+ this.level().removeBlock(blockposition, false);
+ } else {
+ if (blockstate.is(block)) {
+ ((ServerLevel) this.level()).getChunkSource().blockChanged(blockposition);
+ }
+ this.discard(EntityRemoveEvent.Cause.DESPAWN);
+ }
+ }
+ // Sakura end - configure cannon physics
public FallingBlockEntity(EntityType<? extends FallingBlockEntity> entityType, Level level) {
super(entityType, level);
@@ -138,6 +175,10 @@ public class FallingBlockEntity extends Entity implements me.samsuik.sakura.enti
this.yo = y;
this.zo = z;
this.setStartPos(this.blockPosition());
+ // Sakura start - configure cannon physics
+ this.physics = level.localConfig().config(this.blockPosition()).physicsVersion;
+ this.eyeHeight = this.physics.isLegacy() ? 0.49f : this.eyeHeight;
+ // Sakura end - configure cannon physics
}
// Sakura start - falling block height parity api
@@ -158,7 +199,11 @@ public class FallingBlockEntity extends Entity implements me.samsuik.sakura.enti
: blockState
);
if (!CraftEventFactory.callEntityChangeBlockEvent(fallingBlockEntity, pos, blockState.getFluidState().createLegacyBlock())) return fallingBlockEntity; // CraftBukkit
- level.setBlock(pos, blockState.getFluidState().createLegacyBlock(), 3);
+ // Sakura start - configure cannon physics
+ if (fallingBlockEntity.physics.afterOrEqual(1_18_2)) {
+ level.setBlock(pos, blockState.getFluidState().createLegacyBlock(), 3);
+ }
+ // Sakura end - configure cannon physics
level.addFreshEntity(fallingBlockEntity);
return fallingBlockEntity;
}
@@ -202,7 +247,7 @@ public class FallingBlockEntity extends Entity implements me.samsuik.sakura.enti
@Override
protected double getDefaultGravity() {
- return 0.04;
+ return this.physics.before(1_14_0) ? 0.04f : 0.04; // Sakura - configure cannon physics
}
@Override
@@ -211,6 +256,11 @@ public class FallingBlockEntity extends Entity implements me.samsuik.sakura.enti
this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
} else {
Block block = this.blockState.getBlock();
+ // Sakura start - configure cannon physics
+ if (this.time == 0 && this.physics.before(1_18_2)) {
+ this.removeBlockOnFall(block);
+ }
+ // Sakura end - configure cannon physics
this.time++;
this.applyGravity();
this.moveStripped(MoverType.SELF, this.getDeltaMovement()); // Sakura - optimise cannon entity movement
@@ -225,8 +275,15 @@ public class FallingBlockEntity extends Entity implements me.samsuik.sakura.enti
}
// Paper end - Configurable falling blocks height nerf
this.handlePortal();
+ // Sakura start - configure cannon physics
+ if (this.physics.before(1_12_0)) {
+ this.setDeltaMovement(this.getDeltaMovement().scale(0.98F));
+ }
if (this.level() instanceof ServerLevel serverLevel && (this.isAlive() || this.forceTickAfterTeleportToDuplicate)) {
- BlockPos blockPos = this.blockPosition();
+ // Patching the floating point issue on modern versions can break some cannons that rely on it.
+ // However, it makes sense for legacy versions pre-1.17 before the world height change.
+ BlockPos blockPos = this.physics.before(1_17_0) ? this.patchedBlockPosition() : this.blockPosition();
+ // Sakura end - configure cannon physics
boolean flag = this.level().sakuraConfig().cannons.sand.concreteSolidifyInWater && this.blockState.getBlock() instanceof ConcretePowderBlock; // Sakura - configure concrete solidifying in water
boolean flag1 = flag && this.level().getFluidState(blockPos).is(FluidTags.WATER);
double d = this.getDeltaMovement().lengthSqr();
@@ -253,8 +310,11 @@ public class FallingBlockEntity extends Entity implements me.samsuik.sakura.enti
}
} else {
BlockState blockState = this.level().getBlockState(blockPos);
- this.setDeltaMovement(this.getDeltaMovement().multiply(0.7, -0.5, 0.7));
- if (!blockState.is(Blocks.MOVING_PISTON)) {
+ // Sakura start - configure cannon physics
+ double friction = this.physics.before(1_14_0) ? 0.7f : 0.7;
+ this.setDeltaMovement(this.getDeltaMovement().multiply(friction, -0.5, friction));
+ if (!blockState.is(Blocks.MOVING_PISTON) && (flag1 || !this.physics.isWithin(1_9_0, 1_12_0) || this.isAbleToStackOnBlock())) {
+ // Sakura end - configure cannon physics
if (!this.cancelDrop) {
boolean canBeReplaced = blockState.canBeReplaced(
new DirectionalPlaceContext(this.level(), blockPos, Direction.DOWN, ItemStack.EMPTY, Direction.UP)
@@ -326,7 +386,12 @@ public class FallingBlockEntity extends Entity implements me.samsuik.sakura.enti
}
}
- this.setDeltaMovement(this.getDeltaMovement().scale(0.98));
+ // Sakura start - configure cannon physics
+ if (this.physics.afterOrEqual(1_12_0)) {
+ double drag = this.physics.before(1_14_0) ? 0.98f : 0.98;
+ this.setDeltaMovement(this.getDeltaMovement().scale(drag));
+ }
+ // Sakura end - configure cannon physics
}
}
diff --git a/net/minecraft/world/entity/item/PrimedTnt.java b/net/minecraft/world/entity/item/PrimedTnt.java
index 438a8974cc0b8e0ef4e7a2268c61f45f5fd6b959..87c5669d534365d361b177407a0912d0698f19bd 100644
--- a/net/minecraft/world/entity/item/PrimedTnt.java
+++ b/net/minecraft/world/entity/item/PrimedTnt.java
@@ -80,6 +80,22 @@ public class PrimedTnt extends Entity implements TraceableEntity, me.samsuik.sak
this.mergeData.setCount(count); // Sakura - specialised explosions
}
// Sakura end - merge cannon entities
+ // Sakura start - configure cannon physics
+ @Override
+ public final double getEyeY() {
+ return this.physics.isLegacy() ? super.getEyeY() : this.getY();
+ }
+
+ @Override
+ public final double distanceToSqr(net.minecraft.world.phys.Vec3 vector) {
+ if (!this.physics.isLegacy())
+ return super.distanceToSqr(vector);
+ double x = this.getX() - vector.x;
+ double y = this.getEyeY() - vector.y;
+ double z = this.getZ() - vector.z;
+ return x * x + y * y + z * z;
+ }
+ // Sakura end - configure cannon physics
public PrimedTnt(EntityType<? extends PrimedTnt> entityType, Level level) {
super(entityType, level);
@@ -105,6 +121,13 @@ public class PrimedTnt extends Entity implements TraceableEntity, me.samsuik.sak
case Y -> this.setDeltaMovement(this.getDeltaMovement().multiply(0.0, 1.0, 0.0));
}
// Sakura end - configure cannon mechanics
+ // Sakura start - configure cannon physics
+ this.physics = level.localConfig().config(this.blockPosition()).physicsVersion;
+ this.eyeHeight = this.physics.isLegacy() ? 0.49f : this.eyeHeight;
+ if (this.physics.isLegacy()) {
+ this.setDeltaMovement(this.getDeltaMovement().multiply(0.0, 1.0, 0.0));
+ }
+ // Sakura end - configure cannon physics
}
// Sakura start - optimise tnt fluid state
@@ -140,7 +163,7 @@ public class PrimedTnt extends Entity implements TraceableEntity, me.samsuik.sak
@Override
protected double getDefaultGravity() {
- return 0.04;
+ return this.physics.before(1_14_0) ? 0.04f : 0.04; // Sakura - configure cannon physics
}
@Override
@@ -156,14 +179,18 @@ public class PrimedTnt extends Entity implements TraceableEntity, me.samsuik.sak
return;
}
// Paper end - Configurable TNT height nerf
- this.setDeltaMovement(this.getDeltaMovement().scale(0.98));
+ // Sakura start - configure cannon physics
+ double drag = this.physics.before(1_14_0) ? 0.98f : 0.98;
+ this.setDeltaMovement(this.getDeltaMovement().scale(drag));
if (this.onGround()) {
- this.setDeltaMovement(this.getDeltaMovement().multiply(0.7, -0.5, 0.7));
+ double friction = this.physics.before(1_14_0) ? 0.7f : 0.7;
+ this.setDeltaMovement(this.getDeltaMovement().multiply(friction, -0.5, friction));
+ // Sakura end - configure cannon physics
}
int i = this.getFuse() - 1;
this.setFuse(i);
- if (i <= 0) {
+ if (this.physics.before(1_9_0) ? (i < 0) : (i <= 0)) { // Sakura - configure cannon physics
// CraftBukkit start - Need to reverse the order of the explosion and the entity death so we have a location for the event
//this.discard();
this.respawnEntity(); // Sakura - merge cannon entities
@@ -216,13 +243,14 @@ public class PrimedTnt extends Entity implements TraceableEntity, me.samsuik.sak
return;
}
// CraftBukkit end
+ double explosionY = this.physics.before(1_10_0) ? this.getY() + (double) 0.49f : this.getY(0.0625D); // Sakura - configure cannon physics
this.level()
.explode(
this,
Explosion.getDefaultDamageSource(this.level(), this),
this.usedPortal ? USED_PORTAL_DAMAGE_CALCULATOR : null,
this.getX(),
- this.getY(0.0625),
+ explosionY, // Sakura - configure cannon physics
this.getZ(),
event.getRadius(), // CraftBukkit
event.getFire(), // CraftBukkit
@@ -310,7 +338,7 @@ public class PrimedTnt extends Entity implements TraceableEntity, me.samsuik.sak
// Paper start - Option to prevent TNT from moving in water
@Override
public boolean isPushedByFluid() {
- return !this.level().paperConfig().fixes.preventTntFromMovingInWater && this.level().sakuraConfig().cannons.mechanics.tntFlowsInWater && super.isPushedByFluid(); // Sakura - configure cannon mechanics
+ return !this.level().paperConfig().fixes.preventTntFromMovingInWater && this.level().sakuraConfig().cannons.mechanics.tntFlowsInWater && !this.physics.isLegacy() && super.isPushedByFluid(); // Sakura - physics version api // Sakura - configure cannon mechanics
}
// Paper end - Option to prevent TNT from moving in water
}
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index 19aa5010b019e343d0fb085359eac98bcb5b5efa..eeb37d088cec5b2b8e1ac4bd48b4491eed0822e2 100644
--- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java
@@ -837,6 +837,170 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
return chunk != null ? chunk.getNoiseBiome(x, y, z) : this.getUncachedNoiseBiome(x, y, z);
}
// Paper end - optimise random ticking
+ // Sakura start - configure cannon physics
+ public final net.minecraft.world.phys.BlockHitResult.Type clipLegacy(Vec3 from, Vec3 to) {
+ int toX = Mth.floor(to.x);
+ int toY = Mth.floor(to.y);
+ int toZ = Mth.floor(to.z);
+ int fromX = Mth.floor(from.x);
+ int fromY = Mth.floor(from.y);
+ int fromZ = Mth.floor(from.z);
+
+ BlockPos.MutableBlockPos blockPos = new BlockPos.MutableBlockPos(fromX, fromY, fromZ);
+ LevelChunk chunk = this.getChunkIfLoaded(fromX >> 4, fromZ >> 4);
+ if (chunk == null) {
+ return net.minecraft.world.phys.BlockHitResult.Type.MISS;
+ }
+
+ BlockState blockstate = chunk.getBlockState(blockPos);
+ VoxelShape shape = blockstate.getShape(this, blockPos);
+ for (AABB bb : shape.toAabbs()) {
+ if (this.clip(bb, blockPos, from, to)) {
+ return net.minecraft.world.phys.BlockHitResult.Type.BLOCK;
+ }
+ }
+
+ for (int steps = 0; steps < 16; ++steps) {
+ if (fromX == toX && fromY == toY && fromZ == toZ) {
+ return net.minecraft.world.phys.BlockHitResult.Type.MISS;
+ }
+
+ boolean moveX = true;
+ boolean moveY = true;
+ boolean moveZ = true;
+ double d0 = 999.0D;
+ double d1 = 999.0D;
+ double d2 = 999.0D;
+
+ if (toX > fromX) {
+ d0 = (double) fromX + 1.0D;
+ } else if (toX < fromX) {
+ d0 = (double) fromX + 0.0D;
+ } else {
+ moveX = false;
+ }
+
+ if (toY > fromY) {
+ d1 = (double) fromY + 1.0D;
+ } else if (toY < fromY) {
+ d1 = (double) fromY + 0.0D;
+ } else {
+ moveY = false;
+ }
+
+ if (toZ > fromZ) {
+ d2 = (double) fromZ + 1.0D;
+ } else if (toZ < fromZ) {
+ d2 = (double) fromZ + 0.0D;
+ } else {
+ moveZ = false;
+ }
+
+ double d3 = 999.0D;
+ double d4 = 999.0D;
+ double d5 = 999.0D;
+ double d6 = to.x - from.x;
+ double d7 = to.y - from.y;
+ double d8 = to.z - from.z;
+
+ if (moveX) d3 = (d0 - from.x) / d6;
+ if (moveY) d4 = (d1 - from.y) / d7;
+ if (moveZ) d5 = (d2 - from.z) / d8;
+
+ if (d3 == -0.0D) d3 = -1.0E-4D;
+ if (d4 == -0.0D) d4 = -1.0E-4D;
+ if (d5 == -0.0D) d5 = -1.0E-4D;
+
+ Direction moveDir;
+ if (d3 < d4 && d3 < d5) {
+ moveDir = toX > fromX ? Direction.WEST : Direction.EAST;
+ from = new Vec3(d0, from.y + d7 * d3, from.z + d8 * d3);
+ } else if (d4 < d5) {
+ moveDir = toY > fromY ? Direction.DOWN : Direction.UP;
+ from = new Vec3(from.x + d6 * d4, d1, from.z + d8 * d4);
+ } else {
+ moveDir = toZ > fromZ ? Direction.NORTH : Direction.SOUTH;
+ from = new Vec3(from.x + d6 * d5, from.y + d7 * d5, d2);
+ }
+
+ fromX = Mth.floor(from.x) - (moveDir == Direction.EAST ? 1 : 0);
+ fromY = Mth.floor(from.y) - (moveDir == Direction.UP ? 1 : 0);
+ fromZ = Mth.floor(from.z) - (moveDir == Direction.SOUTH ? 1 : 0);
+ blockPos.set(fromX, fromY, fromZ);
+
+ int chunkX = fromX >> 4;
+ int chunkZ = fromZ >> 4;
+ if (chunkX != chunk.locX || chunkZ != chunk.locZ) {
+ chunk = this.getChunkIfLoaded(chunkX, chunkZ);
+ }
+ if (chunk == null) {
+ return net.minecraft.world.phys.BlockHitResult.Type.MISS;
+ }
+
+ blockstate = chunk.getBlockState(blockPos);
+ shape = blockstate.getShape(this, blockPos);
+ for (AABB bb : shape.toAabbs()) {
+ if (this.clip(bb, blockPos, from, to)) {
+ return net.minecraft.world.phys.BlockHitResult.Type.BLOCK;
+ }
+ }
+ }
+ return net.minecraft.world.phys.BlockHitResult.Type.MISS;
+ }
+
+ private boolean clip(AABB bb, BlockPos blockposition, net.minecraft.world.phys.Vec3 vec3d, net.minecraft.world.phys.Vec3 vec3d1) {
+ vec3d = vec3d.subtract(blockposition.getX(), blockposition.getY(), blockposition.getZ());
+ vec3d1 = vec3d1.subtract(blockposition.getX(), blockposition.getY(), blockposition.getZ());
+
+ double x = vec3d1.x - vec3d.x;
+ double y = vec3d1.y - vec3d.y;
+ double z = vec3d1.z - vec3d.z;
+
+ double minXd = this.clip(bb.minX, x, vec3d.x);
+ double minYd = this.clip(bb.minY, y, vec3d.y);
+ double minZd = this.clip(bb.minZ, z, vec3d.z);
+ double maxXd = this.clip(bb.maxX, x, vec3d.x);
+ double maxYd = this.clip(bb.maxY, y, vec3d.y);
+ double maxZd = this.clip(bb.maxZ, z, vec3d.z);
+
+ return this.clipX(vec3d, bb, minXd, y, z) || this.clipY(vec3d, bb, minYd, x, z) || this.clipZ(vec3d, bb, minZd, x, y)
+ || this.clipX(vec3d, bb, maxXd, y, z) || this.clipY(vec3d, bb, maxYd, x, z) || this.clipZ(vec3d, bb, maxZd, x, y);
+ }
+
+ private double clip(double bound, double axisD, double axisN) {
+ if (axisD * axisD < 1.0000000116860974E-7D) {
+ return -1.0;
+ }
+ return (bound - axisN) / axisD;
+ }
+
+ private boolean clipX(Vec3 vec3d, AABB bb, double n, double y, double z) {
+ if (n < 0.0 || n > 1.0) {
+ return false;
+ }
+ y = vec3d.y + y * n;
+ z = vec3d.z + z * n;
+ return y >= bb.minY && y <= bb.maxY && z >= bb.minZ && z <= bb.maxZ;
+ }
+
+ private boolean clipY(Vec3 vec3d, AABB bb, double n, double x, double z) {
+ if (n < 0.0 || n > 1.0) {
+ return false;
+ }
+ x = vec3d.x + x * n;
+ z = vec3d.z + z * n;
+ return x >= bb.minX && x <= bb.maxX && z >= bb.minZ && z <= bb.maxZ;
+ }
+
+ private boolean clipZ(Vec3 vec3d, AABB bb, double n, double x, double y) {
+ if (n < 0.0 || n > 1.0) {
+ return false;
+ }
+ x = vec3d.x + x * n;
+ y = vec3d.y + y * n;
+ return x >= bb.minX && x <= bb.maxX && y >= bb.minY && y <= bb.maxY;
+ }
+ // Sakura end - configure cannon physics
public final me.samsuik.sakura.entity.merge.EntityMergeHandler mergeHandler = new me.samsuik.sakura.entity.merge.EntityMergeHandler(); // Sakura - merge cannon entities
public final me.samsuik.sakura.explosion.density.BlockDensityCache densityCache = new me.samsuik.sakura.explosion.density.BlockDensityCache(); // Sakura - explosion density cache
public final me.samsuik.sakura.explosion.durable.DurableBlockManager durabilityManager = new me.samsuik.sakura.explosion.durable.DurableBlockManager(); // Sakura - explosion durable blocks
diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java
index 43203ac9a40106ee4ffbb63d89e2d59b24723642..7e430d476ecd3b0b5c2dc4960a86d74669e0183f 100644
--- a/net/minecraft/world/level/ServerExplosion.java
+++ b/net/minecraft/world/level/ServerExplosion.java
@@ -412,6 +412,7 @@ public class ServerExplosion implements Explosion {
return this.damageCalculator.getBlockExplosionResistance(this, this.level, pos, blockState, fluidState);
}
// Sakura end - explosion durable blocks
+ protected final me.samsuik.sakura.physics.PhysicsVersion physics; // Sakura - configure cannon physics
public ServerExplosion(
ServerLevel level,
@@ -433,6 +434,7 @@ public class ServerExplosion implements Explosion {
this.damageCalculator = damageCalculator == null ? this.makeDamageCalculator(source) : damageCalculator;
this.yield = this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F; // CraftBukkit
this.consistentRadius = level.localConfig().config(BlockPos.containing(this.center)).consistentRadius; // Sakura - consistent explosion radius
+ this.physics = source != null ? source.physics() : level.localConfig().config(BlockPos.containing(this.center)).physicsVersion; // Sakura - configure cannon physics
}
private ExplosionDamageCalculator makeDamageCalculator(@Nullable Entity entity) {
@@ -462,8 +464,13 @@ public class ServerExplosion implements Explosion {
final float density = entity.level().densityCache.getKnownDensity(vec3);
if (density != me.samsuik.sakura.explosion.density.BlockDensityCache.UNKNOWN_DENSITY) {
hitResult = density != 0.0f ? net.minecraft.world.phys.HitResult.Type.MISS : net.minecraft.world.phys.HitResult.Type.BLOCK;
+ // Sakura start - configure cannon physics
+ } else if (entity.physics().before(1_14_0)) {
+ hitResult = entity.level().clipLegacy(vec3, explosionVector);
} else {
- hitResult = entity.level().clip(new ClipContext(vec3, explosionVector, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, entity)).getType();
+ final ClipContext.Block blockContext = entity.physics().afterOrEqual(1_16_0) ? ClipContext.Block.COLLIDER : ClipContext.Block.OUTLINE;
+ hitResult = entity.level().clip(new ClipContext(vec3, explosionVector, blockContext, ClipContext.Fluid.NONE, entity)).getType();
+ // Sakura end - configure cannon physics
}
if (hitResult == HitResult.Type.MISS) {
// Sakura end - replace density cache
@@ -562,6 +569,14 @@ public class ServerExplosion implements Explosion {
}
if (cachedBlock.outOfWorld) {
+ // Sakura start - configure cannon physics
+ if (this.physics.before(1_17_0)) {
+ currX += incX;
+ currY += incY;
+ currZ += incZ;
+ continue;
+ }
+ // Sakura end - configure cannon physics
break;
}
final BlockState iblockdata = cachedBlock.blockState;
@@ -657,6 +672,12 @@ public class ServerExplosion implements Explosion {
double d2 = (entity instanceof PrimedTnt ? entity.getY() : entity.getEyeY()) - this.center.y;
double d3 = entity.getZ() - this.center.z;
double squareRoot = Math.sqrt(d1 * d1 + d2 * d2 + d3 * d3);
+ // Sakura start - configure cannon physics
+ if (this.physics.before(1_17_0)) {
+ d = (float) d;
+ squareRoot = (float) squareRoot;
+ }
+ // Sakura end - configure cannon physics
if (squareRoot != 0.0) {
d1 /= squareRoot;
d2 /= squareRoot;
@@ -948,7 +969,7 @@ public class ServerExplosion implements Explosion {
// Sakura start - replace density cache
float blockDensity = this.level.densityCache.getDensity(vec3d, entity);
if (blockDensity == me.samsuik.sakura.explosion.density.BlockDensityCache.UNKNOWN_DENSITY) {
- blockDensity = this.getSeenFraction(vec3d, entity, this.directMappedBlockCache, this.mutablePos); // Paper - collision optimisations
+ blockDensity = this.sakura_getSeenPercent(vec3d, entity); // Sakura - configure cannon physics
this.level.densityCache.putDensity(vec3d, entity, blockDensity);
// Sakura end - replace density cache
}
@@ -956,6 +977,16 @@ public class ServerExplosion implements Explosion {
return blockDensity;
}
+ // Sakura start - configure cannon physics
+ private float sakura_getSeenPercent(Vec3 vec3d, Entity entity) {
+ if (this.physics.afterOrEqual(1_16_0)) {
+ return this.getSeenFraction(vec3d, entity, this.directMappedBlockCache, this.mutablePos); // Paper - collision optimisations
+ } else {
+ return getSeenPercent(vec3d, entity);
+ }
+ }
+ // Sakura end - configure cannon physics
+
static class CacheKey {
private final Level world;
private final double posX, posY, posZ;
diff --git a/net/minecraft/world/level/block/FallingBlock.java b/net/minecraft/world/level/block/FallingBlock.java
index 1a787426acb68cf8f9491bdd8f903c7e0c00e29f..d410720b27d97dae2a7bbc4455f227064759001a 100644
--- a/net/minecraft/world/level/block/FallingBlock.java
+++ b/net/minecraft/world/level/block/FallingBlock.java
@@ -45,6 +45,15 @@ public abstract class FallingBlock extends Block implements Fallable {
return super.updateShape(state, level, scheduledTickAccess, pos, direction, neighborPos, neighborState, random);
}
+ // Sakura start - configure cannon physics
+ @Override
+ public void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, net.minecraft.world.level.redstone.Orientation wireOrientation, boolean notify) {
+ if (world.localConfig().config(pos).physicsVersion.before(1_18_2)) {
+ world.scheduleTick(pos, this, this.getDelayAfterPlace());
+ }
+ }
+ // Sakura end - configure cannon physics
+
@Override
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (isFree(level.getBlockState(pos.below())) && pos.getY() >= level.getMinY()) {
diff --git a/net/minecraft/world/level/block/FenceGateBlock.java b/net/minecraft/world/level/block/FenceGateBlock.java
index 438f1492ab5b8c7bb2a32828c83e8178c2e04712..81f94bf9351355640c1ffd214638035c6582d87a 100644
--- a/net/minecraft/world/level/block/FenceGateBlock.java
+++ b/net/minecraft/world/level/block/FenceGateBlock.java
@@ -224,8 +224,14 @@ public class FenceGateBlock extends HorizontalDirectionalBlock {
hasNeighborSignal = eventRedstone.getNewCurrent() > 0;
}
// CraftBukkit end
- if (state.getValue(POWERED) != hasNeighborSignal) {
- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(hasNeighborSignal)).setValue(OPEN, Boolean.valueOf(hasNeighborSignal)), 2);
+ // Sakura start - configure cannon physics
+ final boolean legacy = level.localConfig().config(pos).physicsVersion.before(1_11_0);
+ final boolean powered = state.getValue(POWERED);
+ if (legacy ? (hasNeighborSignal || neighborBlock.defaultBlockState().isSignalSource()) : powered != hasNeighborSignal) {
+ final boolean openGate = legacy && (hasNeighborSignal == powered || state.getValue(OPEN) != powered)
+ ? state.getValue(OPEN) : hasNeighborSignal;
+ level.setBlock(pos, (state.setValue(POWERED, hasNeighborSignal)).setValue(OPEN, openGate), 2);
+ // Sakura end - configure cannon physics
if (state.getValue(OPEN) != hasNeighborSignal) {
level.playSound(
null,
diff --git a/net/minecraft/world/level/block/HoneyBlock.java b/net/minecraft/world/level/block/HoneyBlock.java
index bab3ac2c4be08ea7589752b8472c1e13bcaab76a..fdf8306a569edd074d0debeb07be67da9ada5e77 100644
--- a/net/minecraft/world/level/block/HoneyBlock.java
+++ b/net/minecraft/world/level/block/HoneyBlock.java
@@ -70,11 +70,19 @@ public class HoneyBlock extends HalfTransparentBlock {
super.entityInside(state, level, pos, entity);
}
- private static double getOldDeltaY(double deltaY) {
+ // Sakura start - configure cannon physics
+ private static double getOldDeltaY(double deltaY, Entity entity) {
+ if (entity.physics().before(1_21_2)) {
+ return deltaY;
+ }
return deltaY / 0.98F + 0.08;
}
- private static double getNewDeltaY(double deltaY) {
+ private static double getNewDeltaY(double deltaY, Entity entity) {
+ if (entity.physics().before(1_21_2)) {
+ return deltaY;
+ }
+ // Sakura end - configure cannon physics
return (deltaY - 0.08) * 0.98F;
}
@@ -83,7 +91,7 @@ public class HoneyBlock extends HalfTransparentBlock {
return false;
} else if (entity.getY() > pos.getY() + 0.9375 - 1.0E-7) {
return false;
- } else if (getOldDeltaY(entity.getDeltaMovement().y) >= -0.08) {
+ } else if (getOldDeltaY(entity.getDeltaMovement().y, entity) >= -0.08) { // Sakura - configure cannon physics
return false;
} else {
double abs = Math.abs(pos.getX() + 0.5 - entity.getX());
@@ -101,11 +109,13 @@ public class HoneyBlock extends HalfTransparentBlock {
private void doSlideMovement(Entity entity) {
Vec3 deltaMovement = entity.getDeltaMovement();
- if (getOldDeltaY(entity.getDeltaMovement().y) < -0.13) {
- double d = -0.05 / getOldDeltaY(entity.getDeltaMovement().y);
- entity.setDeltaMovement(new Vec3(deltaMovement.x * d, getNewDeltaY(-0.05), deltaMovement.z * d));
+ // Sakura start - configure cannon physics
+ if (getOldDeltaY(entity.getDeltaMovement().y, entity) < -0.13) {
+ double d = -0.05 / getOldDeltaY(entity.getDeltaMovement().y, entity);
+ entity.setDeltaMovement(new Vec3(deltaMovement.x * d, getNewDeltaY(-0.05, entity), deltaMovement.z * d));
} else {
- entity.setDeltaMovement(new Vec3(deltaMovement.x, getNewDeltaY(-0.05), deltaMovement.z));
+ entity.setDeltaMovement(new Vec3(deltaMovement.x, getNewDeltaY(-0.05, entity), deltaMovement.z));
+ // Sakura end - configure cannon physics
}
entity.resetFallDistance();
diff --git a/net/minecraft/world/level/block/LadderBlock.java b/net/minecraft/world/level/block/LadderBlock.java
index 352aa47ba6d4e434bcf2af8e70c5abcb734056eb..c615d4fa56d9237f9b71800ee77f6be219ce18c7 100644
--- a/net/minecraft/world/level/block/LadderBlock.java
+++ b/net/minecraft/world/level/block/LadderBlock.java
@@ -35,6 +35,21 @@ public class LadderBlock extends Block implements SimpleWaterloggedBlock {
private static final VoxelShape SOUTH_AABB_COPY = SOUTH_AABB.copy();
private static final VoxelShape NORTH_AABB_COPY = NORTH_AABB.copy();
// Sakura end - protect block shapes against plugins
+ // Sakura start - configure cannon physics
+ protected static final VoxelShape LEGACY_EAST_AABB = Block.box(0.0, 0.0, 0.0, 2.0, 16.0, 16.0);
+ protected static final VoxelShape LEGACY_WEST_AABB = Block.box(14.0, 0.0, 0.0, 16.0, 16.0, 16.0);
+ protected static final VoxelShape LEGACY_SOUTH_AABB = Block.box(0.0, 0.0, 0.0, 16.0, 16.0, 2.0);
+ protected static final VoxelShape LEGACY_NORTH_AABB = Block.box(0.0, 0.0, 14.0, 16.0, 16.0, 16.0);
+
+ private static VoxelShape legacyShape(Direction facing) {
+ return switch (facing) {
+ case NORTH -> LEGACY_NORTH_AABB;
+ case SOUTH -> LEGACY_SOUTH_AABB;
+ case WEST -> LEGACY_WEST_AABB;
+ default -> LEGACY_EAST_AABB;
+ };
+ }
+ // Sakura end - configure cannon physics
@Override
public MapCodec<LadderBlock> codec() {
@@ -46,8 +61,18 @@ public class LadderBlock extends Block implements SimpleWaterloggedBlock {
this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(WATERLOGGED, Boolean.valueOf(false)));
}
+ // Sakura start - configure cannon physics
+ @Override
+ public final boolean hasDynamicShape() {
+ return true;
+ }
+
@Override
protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
+ if (level instanceof net.minecraft.world.level.Level gameLevel && gameLevel.localConfig().config(pos).physicsVersion.before(1_9_0)) {
+ return legacyShape(state.getValue(FACING));
+ }
+ // Sakura end - configure cannon physics
switch ((Direction)state.getValue(FACING)) {
case NORTH:
// Sakura start - protect block shapes against plugins
diff --git a/net/minecraft/world/level/block/LiquidBlock.java b/net/minecraft/world/level/block/LiquidBlock.java
index 78aa0ae9ce937b7232eac1d65fd987c21489979d..e719be50ff73610046696a21053671332951ca9c 100644
--- a/net/minecraft/world/level/block/LiquidBlock.java
+++ b/net/minecraft/world/level/block/LiquidBlock.java
@@ -190,7 +190,20 @@ public class LiquidBlock extends Block implements BucketPickup {
for (Direction direction : POSSIBLE_FLOW_DIRECTIONS) {
BlockPos blockPos = pos.relative(direction.getOpposite());
if (level.getFluidState(blockPos).is(FluidTags.WATER)) {
- Block block = level.getFluidState(pos).isSource() ? Blocks.OBSIDIAN : Blocks.COBBLESTONE;
+ // Sakura start - configure cannon physics
+ final FluidState fluidState = state.getFluidState();
+ final Block block = fluidState.isSource() ? Blocks.OBSIDIAN : Blocks.COBBLESTONE;
+ if (block == Blocks.COBBLESTONE) {
+ final me.samsuik.sakura.physics.PhysicsVersion physics = level.localConfig().config(pos).physicsVersion;
+
+ // SANITY: In legacy a patch by paper removes the fluid level condition from vanilla.
+ if (physics.before(1_16_0) && !physics.isLegacy() &&
+ (physics.before(1_13_0) || !(fluidState.getHeight(level, pos) >= 0.44444445f)) &&
+ (physics.afterOrEqual(1_13_0) || FlowingFluid.getLegacyLevel(fluidState) > 4)) {
+ return true;
+ }
+ }
+ // Sakura end - configure cannon physics
// CraftBukkit start
if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, block.defaultBlockState())) {
this.fizz(level, pos);
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
index efdcee032174af1f9a14183e9e8af3e7c4694942..d763a636ecb92a12786f49e2096a95827a3d1717 100644
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
@@ -572,6 +572,10 @@ public class RedStoneWireBlock extends Block {
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {
if (!player.getAbilities().mayBuild) {
return InteractionResult.PASS;
+ // Sakura start - configure cannon physics
+ } else if (level.localConfig().config(pos).physicsVersion.before(1_16_0)) {
+ return InteractionResult.PASS;
+ // Sakura end - configure cannon physics
} else {
if (isCross(state) || isDot(state)) {
BlockState blockState = isCross(state) ? this.defaultBlockState() : this.crossState;
diff --git a/net/minecraft/world/level/block/WaterlilyBlock.java b/net/minecraft/world/level/block/WaterlilyBlock.java
index f085671bcef6dd9758240f91dfe7c58ef6212f0b..1209bc07200ea1c1752e578363fee9d5d3f542b2 100644
--- a/net/minecraft/world/level/block/WaterlilyBlock.java
+++ b/net/minecraft/world/level/block/WaterlilyBlock.java
@@ -17,6 +17,7 @@ import net.minecraft.world.phys.shapes.VoxelShape;
public class WaterlilyBlock extends BushBlock {
public static final MapCodec<WaterlilyBlock> CODEC = simpleCodec(WaterlilyBlock::new);
protected static final VoxelShape AABB = Block.box(1.0, 0.0, 1.0, 15.0, 1.5, 15.0);
+ protected static final VoxelShape LEGACY_AABB = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 0.25D, 16.0D); // Sakura - configure cannon physics
@Override
public MapCodec<WaterlilyBlock> codec() {
@@ -41,8 +42,18 @@ public class WaterlilyBlock extends BushBlock {
}
}
+ // Sakura start - configure cannon physics
+ @Override
+ public final boolean hasDynamicShape() {
+ return true;
+ }
+
@Override
protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
+ if (level instanceof net.minecraft.world.level.Level gameLevel && gameLevel.localConfig().config(pos).physicsVersion.before(1_9_0)) {
+ return LEGACY_AABB;
+ }
+ // Sakura end - configure cannon physics
return AABB;
}
diff --git a/net/minecraft/world/level/block/piston/MovingPistonBlock.java b/net/minecraft/world/level/block/piston/MovingPistonBlock.java
index f14e84e67746208dd188525fb91ab30b190d332b..1d66e5848a7f1b3c5e6b70f2e38351667f62ee25 100644
--- a/net/minecraft/world/level/block/piston/MovingPistonBlock.java
+++ b/net/minecraft/world/level/block/piston/MovingPistonBlock.java
@@ -110,6 +110,16 @@ public class MovingPistonBlock extends BaseEntityBlock {
@Override
protected VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
PistonMovingBlockEntity blockEntity = this.getBlockEntity(level, pos);
+ // Sakura start - configure cannon physics
+ if (blockEntity != null && level instanceof Level gameLevel && gameLevel.localConfig().config(pos).physicsVersion.before(1_9_0)) {
+ final VoxelShape shape = blockEntity.getCollisionShapeFromProgress(level, pos);
+ if (context.isAbove(shape, pos, false)) {
+ return shape;
+ } else {
+ return blockEntity.getMovedState().getCollisionShape(level, pos);
+ }
+ }
+ // Sakura end - configure cannon physics
return blockEntity != null ? blockEntity.getCollisionShape(level, pos) : Shapes.empty();
}
diff --git a/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/net/minecraft/world/level/block/piston/PistonBaseBlock.java
index ca22b585ef05fef2473bab5387b739f0ec358aad..7a8c7ff8a9c5e77ccb8b914694d02cdafb4be69d 100644
--- a/net/minecraft/world/level/block/piston/PistonBaseBlock.java
+++ b/net/minecraft/world/level/block/piston/PistonBaseBlock.java
@@ -145,6 +145,11 @@ public class PistonBaseBlock extends DirectionalBlock {
i = 2;
}
+ // Sakura start - configure cannon physics
+ if (level.localConfig().config(pos).physicsVersion.before(1_9_0)) {
+ level.setBlock(pos, state.setValue(PistonBaseBlock.EXTENDED, false), 18);
+ }
+ // Sakura end - configure cannon physics
level.blockEvent(pos, this, i, direction.get3DDataValue());
}
}
diff --git a/net/minecraft/world/level/block/piston/PistonHeadBlock.java b/net/minecraft/world/level/block/piston/PistonHeadBlock.java
index a89a42a3ad6cecd5cc4d44e4456d52a2997ba2e5..9c3c0305aa96b4a1b40841d1c1f145af8e86af40 100644
--- a/net/minecraft/world/level/block/piston/PistonHeadBlock.java
+++ b/net/minecraft/world/level/block/piston/PistonHeadBlock.java
@@ -151,6 +151,11 @@ public class PistonHeadBlock extends DirectionalBlock {
@Override
protected boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) {
BlockState blockState = level.getBlockState(pos.relative(state.getValue(FACING).getOpposite()));
+ // Sakura start - configure cannon physics
+ if (level instanceof Level gameLevel && gameLevel.localConfig().config(pos).physicsVersion.before(1_9_0)) {
+ return this.isFittingBase(state, blockState);
+ }
+ // Sakura end - configure cannon physics
return this.isFittingBase(state, blockState) || blockState.is(Blocks.MOVING_PISTON) && blockState.getValue(FACING) == state.getValue(FACING);
}
@@ -162,6 +167,10 @@ public class PistonHeadBlock extends DirectionalBlock {
neighborBlock,
ExperimentalRedstoneUtils.withFront(orientation, state.getValue(FACING).getOpposite())
);
+ // Sakura start - configure cannon physics
+ } else if (level.localConfig().config(pos).physicsVersion.before(1_9_0)) {
+ level.setBlock(pos, Blocks.AIR.defaultBlockState(), 19);
+ // Sakura end - configure cannon physics
}
}
diff --git a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
index a6413663112685554afd79f13d3d76f1cd753801..184a9c681b4d1359d028d227dc0a74d7b78b7667 100644
--- a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
+++ b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
@@ -165,6 +165,12 @@ public class PistonMovingBlockEntity extends BlockEntity {
double d4 = 0.0;
+ // Sakura start - configure cannon physics
+ if (entity.physics().before(1_11_0)) {
+ moveEntityByPistonFromDirection(movementDirection, entity, aabb);
+ return;
+ }
+ // Sakura end - configure cannon physics
for (AABB aabb1 : list) {
AABB movementArea = PistonMath.getMovementArea(moveByPositionAndProgress(pos, aabb1, piston), movementDirection, d);
AABB boundingBox = entity.getBoundingBox();
@@ -292,17 +298,170 @@ public class PistonMovingBlockEntity extends BlockEntity {
}
}
+ // Sakura start - configure cannon physics
+ @javax.annotation.Nullable
+ private AABB getBoundsFromProgress(BlockGetter level, BlockPos pos, BlockState state, float progress, Direction dir, boolean absolute) {
+ if (!state.is(Blocks.MOVING_PISTON) && !state.isAir()) {
+ VoxelShape shape = this.movedState.getCollisionShape(level, pos);
+ // bounds on an empty shape causes an exception
+ if (shape.isEmpty()) return null;
+ if (absolute) shape = shape.move(pos.getX(), pos.getY(), pos.getZ());
+ AABB bounds = shape.bounds();
+
+ double minX = bounds.minX;
+ double minY = bounds.minY;
+ double minZ = bounds.minZ;
+ double maxX = bounds.maxX;
+ double maxY = bounds.maxY;
+ double maxZ = bounds.maxZ;
+
+ if (dir.getStepX() < 0) {
+ minX -= (float) dir.getStepX() * progress;
+ } else {
+ maxX -= (float) dir.getStepX() * progress;
+ }
+
+ if (dir.getStepY() < 0) {
+ minY -= (float) dir.getStepY() * progress;
+ } else {
+ maxY -= (float) dir.getStepY() * progress;
+ }
+
+ if (dir.getStepZ() < 0) {
+ minZ -= (float) dir.getStepZ() * progress;
+ } else {
+ maxZ -= (float) dir.getStepZ() * progress;
+ }
+
+ return this.fixZeroWidthBB(new AABB(minX, minY, minZ, maxX, maxY, maxZ), dir);
+ }
+
+ return null;
+ }
+
+ private AABB fixZeroWidthBB(AABB bb, Direction dir) {
+ // Legacy behaviour relied on entities being able to collide with zero width shapes
+ // This is no longer possible, so we have to create a difference here for it to work
+ double expandX = bb.getXsize() == 0.0 ? 1.0e-5 * dir.getStepX() : 0;
+ double expandY = bb.getYsize() == 0.0 ? 1.0e-5 * dir.getStepY() : 0;
+ double expandZ = bb.getZsize() == 0.0 ? 1.0e-5 * dir.getStepZ() : 0;
+
+ if (expandX != 0 || expandY != 0 || expandZ != 0) {
+ bb = bb.expandTowards(expandX, expandY, expandZ);
+ }
+
+ return bb;
+ }
+
+ public final VoxelShape getCollisionShapeFromProgress(BlockGetter level, BlockPos pos) {
+ float progress = this.getProgress(0.0f);
+
+ if (this.extending) {
+ progress = 1.0F - progress;
+ }
+
+ AABB bb = this.getBoundsFromProgress(level, pos, this.movedState, progress, this.direction, false);
+ return bb == null ? Shapes.empty() : Shapes.create(bb);
+ }
+
+ private void moveEntities(Level level, float f1) {
+ float f = this.progress;
+
+ if (this.extending) {
+ f = 1.0F - f;
+ } else {
+ --f;
+ }
+
+ AABB bb = this.getBoundsFromProgress(level, this.worldPosition, this.movedState, f, this.direction, true);
+
+ if (bb == null || bb.getSize() == 0.0) {
+ return;
+ }
+
+ List<Entity> entities = level.getEntities(null, bb);
+
+ if (entities.isEmpty()) {
+ return;
+ }
+
+ for (Entity entity : entities) {
+ if (this.movedState.is(Blocks.SLIME_BLOCK) && this.extending) {
+ Vec3 movement = entity.getDeltaMovement();
+ double x = movement.x;
+ double y = movement.y;
+ double z = movement.z;
+
+ switch (this.direction.getAxis()) {
+ case X -> x = direction.getStepX();
+ case Y -> y = direction.getStepY();
+ case Z -> z = direction.getStepZ();
+ }
+
+ entity.setDeltaMovement(x, y, z);
+ } else {
+ entity.move(MoverType.PISTON, new Vec3(f1 * (float) this.direction.getStepX(), f1 * (float) this.direction.getStepY(), f1 * (float) this.direction.getStepZ()));
+ }
+ }
+ }
+
+ private static void moveEntityByPistonFromDirection(Direction direction, Entity entity, AABB blockBB) {
+ AABB entityBB = entity.getBoundingBox();
+ double movX = 0.0;
+ double movY = 0.0;
+ double movZ = 0.0;
+
+ switch (direction.getAxis()) {
+ case X -> {
+ if (direction.getAxisDirection() == Direction.AxisDirection.POSITIVE) {
+ movX = blockBB.maxX - entityBB.minX;
+ } else {
+ movX = entityBB.maxX - blockBB.minX;
+ }
+ movX += 0.01D;
+ }
+ case Y -> {
+ if (direction.getAxisDirection() == Direction.AxisDirection.POSITIVE) {
+ movY = blockBB.maxY - entityBB.minY;
+ } else {
+ movY = entityBB.maxY - blockBB.minY;
+ }
+ movY += 0.01D;
+ }
+ case Z -> {
+ if (direction.getAxisDirection() == Direction.AxisDirection.POSITIVE) {
+ movZ = blockBB.maxZ - entityBB.minZ;
+ } else {
+ movZ = entityBB.maxZ - blockBB.minZ;
+ }
+ movZ += 0.01D;
+ }
+ }
+
+ entity.move(MoverType.PISTON, new Vec3(movX * direction.getStepX(), movY * direction.getStepY(), movZ * direction.getStepZ()));
+ }
+ // Sakura end - configure cannon physics
+
public Direction getPushDirection() {
return this.extending ? this.direction : this.direction.getOpposite();
}
public static void tick(Level level, BlockPos pos, BlockState state, PistonMovingBlockEntity blockEntity) {
+ final me.samsuik.sakura.physics.PhysicsVersion physics = level.localConfig().config(pos).physicsVersion; // Sakura - configure cannon physics
blockEntity.lastTicked = level.getGameTime();
blockEntity.progressO = blockEntity.progress;
if (blockEntity.progressO >= 1.0F) {
if (level.isClientSide && blockEntity.deathTicks < 5) {
blockEntity.deathTicks++;
} else {
+ // Sakura start - configure cannon physics
+ if (physics.isWithin(1_9_0, 1_10_0)) {
+ moveCollidedEntities(level, pos, 1.0f, blockEntity);
+ moveStuckEntities(level, pos, 1.0f, blockEntity);
+ } else if (physics.before(1_9_0)) {
+ blockEntity.moveEntities(level, 0.25f);
+ }
+ // Sakura end - configure cannon physics
level.removeBlockEntity(pos);
blockEntity.setRemoved();
if (level.getBlockState(pos).is(Blocks.MOVING_PISTON)) {
@@ -324,12 +483,22 @@ public class PistonMovingBlockEntity extends BlockEntity {
}
} else {
float f = blockEntity.progress + 0.5F;
+ // Sakura start - physics version api
+ if (physics.afterOrEqual(1_11_0)) {
moveCollidedEntities(level, pos, f, blockEntity);
moveStuckEntities(level, pos, f, blockEntity);
+ }
blockEntity.progress = f;
if (blockEntity.progress >= 1.0F) {
blockEntity.progress = 1.0F;
}
+ if (physics.isWithin(1_9_0, 1_10_0)) {
+ moveCollidedEntities(level, pos, f, blockEntity);
+ moveStuckEntities(level, pos, f, blockEntity);
+ } else if (blockEntity.extending && physics.before(1_9_0)) {
+ blockEntity.moveEntities(level, blockEntity.progress - blockEntity.progressO + 0.0625f);
+ }
+ // Sakura end - physics version api
}
}
diff --git a/net/minecraft/world/level/material/LavaFluid.java b/net/minecraft/world/level/material/LavaFluid.java
index 3ee197e533460ef4fa87bebe18d02ffc76de8550..9b714ddad7208dd9509bf9f8434f1acea5a6f213 100644
--- a/net/minecraft/world/level/material/LavaFluid.java
+++ b/net/minecraft/world/level/material/LavaFluid.java
@@ -172,7 +172,10 @@ public abstract class LavaFluid extends FlowingFluid {
@Override
public boolean canBeReplacedWith(FluidState fluidState, BlockGetter blockReader, BlockPos pos, Fluid fluid, Direction direction) {
- return fluidState.getHeight(blockReader, pos) >= 0.44444445F && fluid.is(FluidTags.WATER);
+ // Sakura start - configure cannon physics
+ return fluidState.getHeight(blockReader, pos) >= 0.44444445F && fluid.is(FluidTags.WATER)
+ && blockReader instanceof Level level && level.localConfig().config(pos).physicsVersion.afterOrEqual(1_13_0);
+ // Sakura end - configure cannon physics
}
@Override
diff --git a/net/minecraft/world/level/material/WaterFluid.java b/net/minecraft/world/level/material/WaterFluid.java
index 56781b47aeddf0c84d64ddf8b1aad7b26730b68c..6f478324e9edaf52f8938fb6e24208495463454f 100644
--- a/net/minecraft/world/level/material/WaterFluid.java
+++ b/net/minecraft/world/level/material/WaterFluid.java
@@ -114,7 +114,12 @@ public abstract class WaterFluid extends FlowingFluid {
@Override
public boolean canBeReplacedWith(FluidState fluidState, BlockGetter blockReader, BlockPos pos, Fluid fluid, Direction direction) {
- return direction == Direction.DOWN && !fluid.is(FluidTags.WATER);
+ // Sakura start - configure cannon physics
+ if (direction == Direction.DOWN && !fluid.is(FluidTags.WATER) || !(blockReader instanceof Level level)) {
+ return true;
+ }
+ return fluid.is(FluidTags.LAVA) && level.localConfig().config(pos).physicsVersion.before(1_13_0);
+ // Sakura end - configure cannon physics
}
@Override