9
0
mirror of https://github.com/Samsuik/Sakura.git synced 2025-12-28 03:09:07 +00:00
Files
SakuraMC/patches/server/0043-Configure-cannon-physics-by-version.patch
Samsuik deb3177965 Updated Upstream (Paper)
Upstream has released updates that appear to apply and compile correctly

Paper Changes:
PaperMC/Paper@7fbb827 Finish API patches
PaperMC/Paper@8a37f93 62
PaperMC/Paper@2055809 117
PaperMC/Paper@0b75522 194
PaperMC/Paper@ec05cb8 279
PaperMC/Paper@0bc9aee 385
PaperMC/Paper@27e29cc 487/1053
PaperMC/Paper@083bd9e 531/1053
PaperMC/Paper@ed2ea45 538
PaperMC/Paper@ba163e1 585/1053
PaperMC/Paper@8731266 650/1053
PaperMC/Paper@52b49fb 788/1053
PaperMC/Paper@33b36cd update some patches
PaperMC/Paper@14c0336 922
PaperMC/Paper@a399f23 956
PaperMC/Paper@4140de2 960
PaperMC/Paper@6d4e235 988
PaperMC/Paper@6a34750 Move unapplied patches to the back
PaperMC/Paper@3c04f9f Fix a few compile errors
PaperMC/Paper@0d3ce2d Fix more compile issues
PaperMC/Paper@a308c7c Fix more compile issues
PaperMC/Paper@69d1d0a Pretend to fix compile errors
PaperMC/Paper@547f09d Some work on the ItemMend events
PaperMC/Paper@184a943 Adopt previous commit changes in API
PaperMC/Paper@5442bff Make it compile
PaperMC/Paper@038f8d9 Fixup and deprecate player profiles in ping event
PaperMC/Paper@66f7b67 Fix body equipmentslot and effect enum
PaperMC/Paper@38b3182 Updated Upstream (Bukkit/CraftBukkit)
PaperMC/Paper@df633e5 DataConverter 1.21
PaperMC/Paper@f569389 Update ConcurrentUtil
PaperMC/Paper@5fca3ae update generated API
PaperMC/Paper@188cff2 remove old vanilla goals
PaperMC/Paper@ffe310a remove api that was scheduled for removal
PaperMC/Paper@730882f Chunk System and Starlight WIP
PaperMC/Paper@512fd08 Update Gradle Wrapper to v8.8
PaperMC/Paper@097284d Bump tiny-remapper to 0.10.3
PaperMC/Paper@ee9b820 Update more optimization patches
PaperMC/Paper@5d834b1 rebuild patches
PaperMC/Paper@4bc15f1 Updated Upstream (Bukkit/CraftBukkit)
PaperMC/Paper@0b6701d Revert DamageSource#getCausingEntity to vanilla
PaperMC/Paper@5bd7f4e Update AbstractArrow item method implementations for 1.20.6 (#10885)
PaperMC/Paper@fb511c6 Fix Player#sendBlockState (#10855)
PaperMC/Paper@b420038 Fix ItemMeta#removeEnchantments (#10886)
PaperMC/Paper@a835ad1 Merge remote-tracking branch 'origin/dev/1.21' into dev/1.21
PaperMC/Paper@04dad71 Improve enchantWithLevels logic
PaperMC/Paper@0008fa1 Add back more optimization patches
PaperMC/Paper@56b5b7d Fix max chunk status checks
PaperMC/Paper@c1aefee correctly change enchantment registry to a 'delayed' version
PaperMC/Paper@d41636f Add back RecipeIterator fixes patch (#10887)
PaperMC/Paper@7df4725 Configurable damage tick when blocking with shield (#10877)
PaperMC/Paper@3555a77 Properly forward DispenseEvent #getItem to saddle
PaperMC/Paper@e339ec2 Deprecate BlockData#getDestroySpeed for removal
PaperMC/Paper@b090c65 Remove unnecessary changes from chunk status fix
PaperMC/Paper@5e7cd07 add some generated typed/tag keys
PaperMC/Paper@5a5412c Owen fixing stuff!!!
PaperMC/Paper@7240d9d Restore functionality to sand dupe setting
PaperMC/Paper@f873bce Fix NPE in V3808
PaperMC/Paper@1f8e7a7 address compile and test issue (#10890)
PaperMC/Paper@60f3bd8 De-deprecate BlockData#getDestroySpeed
PaperMC/Paper@752f957 Add back more patches
PaperMC/Paper@dc684c6 Remove bad server.scheduleOnMain disconnect calls from old patches
PaperMC/Paper@c84a3b5 Remove fully dropped patches
PaperMC/Paper@d8c2980 Add Adventure API to ServerLinks (#10891)
PaperMC/Paper@ec4c712 update 'improve mass craft perf' patch
PaperMC/Paper@e1c0033 Updated Upstream (Bukkit/CraftBukkit)
PaperMC/Paper@fbc2a55 Update Wither#canTravelThroughPortals
PaperMC/Paper@167961e call EntityDamageItemEvent for thorns
PaperMC/Paper@106dbae Fix getAddress connection check
PaperMC/Paper@d9111cc Registry Modification API (#10893)
PaperMC/Paper@f8ee0a0 Fix implementations of ChunkHolder#getChunkIfPresent
PaperMC/Paper@61b85e4 Fix legacy cb version in remapper
PaperMC/Paper@de8220c Update ChunkMap#distanceManager mapping patch
PaperMC/Paper@8dfb85c Enchantment and GameEvent Registry builders (#10889)
PaperMC/Paper@fb762cf remove remaining reference to 'pgive'
PaperMC/Paper@a7f6633 make EntityPortalReadyEvent#setTargetWorld work again
PaperMC/Paper@152f4fe Add back improved watchdog support patch
PaperMC/Paper@13992b1 Make chunk system loggers calm down a bit
PaperMC/Paper@bf8552f Delegate ItemStack (#10852)
PaperMC/Paper@b3e072a Fix `hasFiredAsync` parameter when `AsyncPlayerSendCommandsEvent` is called (#10896)
PaperMC/Paper@21c9a7c Rebuild patches
PaperMC/Paper@b9f7098 [ci skip] Fix javadoc mistake in EnchantmentRegistryEntry.Builder (#10898)
PaperMC/Paper@b4b8208 Fix NPE for Jukebox#setRecord
PaperMC/Paper@4514f41 Correct duplicate attribute check (#10901)
PaperMC/Paper@090775e Use ItemStack.empty() when air is passed into constructor
PaperMC/Paper@7bbe682 Fix CraftWorld#isChunkGenerated
PaperMC/Paper@126f6d7 Remove getUnloadingChunkHolder check
PaperMC/Paper@d23825a Add missing null check to getFullChunkIfLoaded
PaperMC/Paper@3b1c85b Execute chunk tasks while waiting for chunk load in isChunkGenerated
PaperMC/Paper@4ea696f Add ticket for chunk load in isChunkGenerated
PaperMC/Paper@250e78c Re-add fixlight command
PaperMC/Paper@c0268ca Copy missing diff from old chunk system patch
PaperMC/Paper@38428c0 Cleanup MCUtils patch for chunk system
PaperMC/Paper@f4ddd4a Fix ChunkHolder#getFullChunkNow returning non-null when it should not
PaperMC/Paper@e0d9d60 Add debug for chunk system unload crash
PaperMC/Paper@2df432f Re-add chunk system debug commands
PaperMC/Paper@cf60574 Fix jukebox playable component not being applied on item meta (#10922)
PaperMC/Paper@666bc4d Experimental annotation changes (#10914)
PaperMC/Paper@bab07e0 Validate speed for tool component rule (#10923)
PaperMC/Paper@2118196 Fixes exception log messages getting dropped during bootstrap (#10935)
PaperMC/Paper@8b1d26d Fix diff in sprint interruption option (Closes #10939)
PaperMC/Paper@0a1b133 Revert "Fixes exception log messages getting dropped during bootstrap (#10935)" (Closes #10945)
PaperMC/Paper@a0fad76 Fix base damage for trident (#10948)
PaperMC/Paper@d64be7e Fix NPE of AbstractArrow#getWeapon (#10933)
PaperMC/Paper@081146c Validate using_converts_to for food component (#10931)
PaperMC/Paper@0409a68 deprecate and update some entity tags (#10932)
PaperMC/Paper@9cd0201 Preserve velocity for fireball (#10934)
PaperMC/Paper@19105a9 Fix unload queue storing chunks in wrong sections
PaperMC/Paper@77c763b Fix PlayerShearBlockEvent drops ignored for Pumpkin (#10956)
PaperMC/Paper@76c2f16 Fix wrong diff applying delta twice (#10959)
PaperMC/Paper@812701d Do not crash when an exp orb attempts to mend an unrepairable item
PaperMC/Paper@19eefe9 Fix SoundEffects only to players diff  (#10966)
PaperMC/Paper@95aa440 Add missing effect cause and deprecate PATROL_CAPTAIN cause (#10958)
PaperMC/Paper@b2e5587 Expose LivingEntity#canUseSlot (#10930)
PaperMC/Paper@97afc9a Fix StackOverflowError for new dispenser interaction (#10949)
PaperMC/Paper@5ae4758 Fix speed for launched trident using api (#10936)
PaperMC/Paper@897ece4 Call EntityPortalEnterEvent on endgateways and make cancellable (#10892)
PaperMC/Paper@1d3fc0e Bump reflection-rewriter to 0.0.2 (#10927)
PaperMC/Paper@b99d071 Swap some nullable annotations (#10960)
PaperMC/Paper@dd31654 bump reflection-rewriter to 0.0.3 (#10969)
PaperMC/Paper@dd49fba Fix NPE when retrieving an entity with a null UUID
2024-06-27 20:03:23 +01:00

1269 lines
65 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Samsuik <40902469+Samsuik@users.noreply.github.com>
Date: Tue, 21 Nov 2023 17:03:08 +0000
Subject: [PATCH] Configure cannon physics by version
diff --git a/src/main/java/io/papermc/paper/util/CollisionUtil.java b/src/main/java/io/papermc/paper/util/CollisionUtil.java
index f941c4bbf94f80dc3db3153297713a41c6c8ca48..d8d98cd2290f4af61a45a1150f8230a2c6b54352 100644
--- a/src/main/java/io/papermc/paper/util/CollisionUtil.java
+++ b/src/main/java/io/papermc/paper/util/CollisionUtil.java
@@ -1457,7 +1457,15 @@ public final class CollisionUtil {
return new Vec3(x, y, z);
}
+ // Sakura start - physics version api
public static Vec3 performAABBCollisions(final Vec3 moveVector, AABB axisalignedbb, final List<AABB> potentialCollisions) {
+ 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 - physics version api
double x = moveVector.x;
double y = moveVector.y;
double z = moveVector.z;
@@ -1469,7 +1477,10 @@ public final class CollisionUtil {
}
}
- final boolean xSmaller = Math.abs(x) < Math.abs(z);
+ // Sakura start - physics version api
+ 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 - physics version api
if (xSmaller && z != 0.0) {
z = performAABBCollisionsZ(axisalignedbb, z, potentialCollisions);
@@ -1495,9 +1506,17 @@ public final class CollisionUtil {
public static Vec3 performCollisions(final Vec3 moveVector, AABB axisalignedbb,
final List<VoxelShape> voxels,
final List<AABB> aabbs) {
+ // Sakura start - physics version api
+ 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) {
if (voxels.isEmpty()) {
// fast track only AABBs
- return performAABBCollisions(moveVector, axisalignedbb, aabbs);
+ return performAABBCollisions(moveVector, axisalignedbb, aabbs, physics);
+ // Sakura end - physics version api
}
double x = moveVector.x;
@@ -1512,7 +1531,10 @@ public final class CollisionUtil {
}
}
- final boolean xSmaller = Math.abs(x) < Math.abs(z);
+ // Sakura start - physics version api
+ 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 - physics version api
if (xSmaller && z != 0.0) {
z = performAABBCollisionsZ(axisalignedbb, z, aabbs);
diff --git a/src/main/java/me/samsuik/sakura/explosion/special/SpecialisedExplosion.java b/src/main/java/me/samsuik/sakura/explosion/special/SpecialisedExplosion.java
index 55bf4424d8e995ea7384f88f43465f90ae3c6704..eaef186a6f8857e442e33087f323ea878f5799b1 100644
--- a/src/main/java/me/samsuik/sakura/explosion/special/SpecialisedExplosion.java
+++ b/src/main/java/me/samsuik/sakura/explosion/special/SpecialisedExplosion.java
@@ -172,9 +172,15 @@ public abstract class SpecialisedExplosion<T extends Entity> extends Explosion {
if (distanceFromBottom <= 1.0) {
double x = entity.getX() - pos.x;
- double y = (entity instanceof PrimedTnt ? entity.getY() : entity.getEyeY()) - this.y;
+ double y = entity.getEyeY() - pos.y; // Sakura - physics version api
double z = entity.getZ() - pos.z;
double distance = Math.sqrt(x * x + y * y + z * z);
+ // Sakura start - physics version api
+ if (this.physics.before(1_17_0)) {
+ distanceFromBottom = (float) distanceFromBottom;
+ distance = (float) distance;
+ }
+ // Sakura end - physics version api
if (distance != 0.0D) {
x /= distance;
diff --git a/src/main/java/me/samsuik/sakura/explosion/special/TntExplosion.java b/src/main/java/me/samsuik/sakura/explosion/special/TntExplosion.java
index 3888c76dc16b76ae214aeb7265e8b0e9d600b863..31700b381d495c1d1273ab45e914fdb788e712c8 100644
--- a/src/main/java/me/samsuik/sakura/explosion/special/TntExplosion.java
+++ b/src/main/java/me/samsuik/sakura/explosion/special/TntExplosion.java
@@ -37,6 +37,13 @@ public final class TntExplosion extends SpecialisedExplosion<PrimedTnt> {
this.bounds = new AABB(x, y, z, x, y, z);
}
+ // Sakura start - physics version api
+ @Override
+ protected double getExplosionOffset() {
+ return this.physics.before(1_10_0) ? (double) 0.49f : super.getExplosionOffset();
+ }
+ // Sakura end - physics version api
+
@Override
protected void startExplosion() {
for (int i = this.calculateExplosionPotential() - 1; i >= 0; --i) {
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 0946d71f8ef41f42db038c2efd527a319f55e069..2b94b7bf6cc132a54596ad71c8e2fa801e2eba77 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -385,7 +385,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
private final double[] pistonDeltas;
private long pistonDeltasGameTime;
private EntityDimensions dimensions;
- private float eyeHeight;
+ protected float eyeHeight; // Sakura - physics version
public boolean isInPowderSnow;
public boolean wasInPowderSnow;
public boolean wasOnFire;
@@ -709,6 +709,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
// Sakura end - cannon entity merging
public boolean pushedByFluid = true; // Sakura - entity pushed by fluid api
+ // Sakura start - physics version api
+ 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 - physics version api
public Entity(EntityType<?> type, Level world) {
this.id = Entity.ENTITY_COUNTER.incrementAndGet();
@@ -1216,7 +1223,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 - physics version
AABB axisalignedbb = this.getBoundingBox();
AABB axisalignedbb1 = new AABB(axisalignedbb.minX, axisalignedbb.minY - 1.0E-6D, axisalignedbb.minZ, axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.maxZ);
Optional<BlockPos> optional = this.level.findSupportingBlock(this, axisalignedbb1);
@@ -1253,7 +1260,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) { // Paper
+ if (movementType == MoverType.PISTON && this.physics.afterOrEqual(1_11_0)) { // Sakura - physics version api // Paper
movement = this.limitPistonMovement(movement);
if (movement.equals(Vec3.ZERO)) {
return;
@@ -1271,10 +1278,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
Vec3 vec3d1 = this.collideScan(movement);
double d0 = vec3d1.lengthSqr();
- if (d0 > 1.0E-7D) {
+ if (d0 > 1.0E-7D || this.physics.before(1_14_0)) { // Sakura - physics version api
// NOTE: if there are any blocks in the future that rely on fall distance make sure this is correct.
// The only block I am aware of is powdered snow that has a special case for falling blocks.
- if (this.fallDistance != 0.0F && d0 >= 1.0D && !this.isFallingBlock) {
+ if (this.fallDistance != 0.0F && d0 >= 1.0D && !this.isFallingBlock && this.physics.afterOrEqual(1_18_2)) { // Sakura - physics version api
BlockHitResult movingobjectpositionblock = this.level().clip(new ClipContext(this.position(), this.position().add(vec3d1), ClipContext.Block.FALLDAMAGE_RESETTING, ClipContext.Fluid.WATER, this));
if (movingobjectpositionblock.getType() != HitResult.Type.MISS) {
@@ -1310,6 +1317,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
if (this.horizontalCollision) {
Vec3 vec3d2 = this.getDeltaMovement();
+ // Sakura start - physics version api
+ if (flag && flag1 && this.physics.isWithin(1_14_0, 1_18_1)) {
+ flag = false;
+ }
+ // Sakura end
+
this.setDeltaMovement(flag ? 0.0D : vec3d2.x, vec3d2.y, flag1 ? 0.0D : vec3d2.z);
}
@@ -1341,7 +1354,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.setPos(this.getX() + movement.x, this.getY() + movement.y, this.getZ() + movement.z);
} else {
this.wasOnFire = this.isOnFire();
- if (movementType == MoverType.PISTON) {
+ if (movementType == MoverType.PISTON && this.physics.afterOrEqual(1_11_0)) { // Sakura - physics version api
this.activatedTick = Math.max(this.activatedTick, MinecraftServer.currentTick + 20); // Paper
this.activatedImmunityTick = Math.max(this.activatedImmunityTick, MinecraftServer.currentTick + 20); // Paper
movement = this.limitPistonMovement(movement);
@@ -1368,8 +1381,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
Vec3 vec3d1 = this.collide(movement);
double d0 = vec3d1.lengthSqr();
- if (d0 > 1.0E-7D) {
- if (this.fallDistance != 0.0F && d0 >= 1.0D) {
+ if (d0 > 1.0E-7D || this.physics.before(1_14_0)) { // Sakura - physics version api
+ if (this.fallDistance != 0.0F && d0 >= 1.0D && this.physics.afterOrEqual(1_18_2)) { // Sakura - physics version api
BlockHitResult movingobjectpositionblock = this.level().clip(new ClipContext(this.position(), this.position().add(vec3d1), ClipContext.Block.FALLDAMAGE_RESETTING, ClipContext.Fluid.WATER, this));
if (movingobjectpositionblock.getType() != HitResult.Type.MISS) {
@@ -1405,6 +1418,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
if (this.horizontalCollision) {
Vec3 vec3d2 = this.getDeltaMovement();
+ // Sakura start - physics version api
+ if (flag && flag1 && this.physics.isWithin(1_14_0, 1_18_1)) {
+ flag = false;
+ }
+ // Sakura end
+
this.setDeltaMovement(flag ? 0.0D : vec3d2.x, vec3d2.y, flag1 ? 0.0D : vec3d2.z);
}
@@ -1712,7 +1731,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
} else {
final AABB bb = currBoundingBox.expandTowards(movement.x, movement.y, movement.z);
collectCollisions(bb, potentialCollisionsVoxel, potentialCollisionsBB);
- return io.papermc.paper.util.CollisionUtil.performCollisions(movement, currBoundingBox, potentialCollisionsVoxel, potentialCollisionsBB);
+ return io.papermc.paper.util.CollisionUtil.performCollisions(movement, currBoundingBox, potentialCollisionsVoxel, potentialCollisionsBB, this.physics); // Sakura - physics version api
}
}
@@ -1721,7 +1740,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
double y = movement.y;
double z = movement.z;
- final boolean xSmaller = Math.abs(x) < Math.abs(z);
+ // Sakura start - physics version api
+ final 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 - physics version api
if (y != 0.0) {
y = scanY(currBoundingBox, y, voxelList, bbList);
@@ -1845,7 +1867,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
return movement;
}
- final Vec3 limitedMoveVector = io.papermc.paper.util.CollisionUtil.performCollisions(movement, currBoundingBox, potentialCollisionsVoxel, potentialCollisionsBB);
+ final Vec3 limitedMoveVector = io.papermc.paper.util.CollisionUtil.performCollisions(movement, currBoundingBox, potentialCollisionsVoxel, potentialCollisionsBB, this.physics); // Sakura - physics version api
if (stepHeight > 0.0
&& (onGround || (limitedMoveVector.y != movement.y && movement.y < 0.0))
@@ -2033,8 +2055,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
protected void checkInsideBlocks() {
AABB axisalignedbb = this.getBoundingBox();
- BlockPos blockposition = BlockPos.containing(axisalignedbb.minX + 1.0E-7D, axisalignedbb.minY + 1.0E-7D, axisalignedbb.minZ + 1.0E-7D);
- BlockPos blockposition1 = BlockPos.containing(axisalignedbb.maxX - 1.0E-7D, axisalignedbb.maxY - 1.0E-7D, axisalignedbb.maxZ - 1.0E-7D);
+ // Sakura start - physics version
+ double offset = this.physics.afterOrEqual(1_19_3) ? 1.0E-7D : 0.001D;
+ BlockPos blockposition = BlockPos.containing(axisalignedbb.minX + offset, axisalignedbb.minY + offset, axisalignedbb.minZ + offset);
+ BlockPos blockposition1 = BlockPos.containing(axisalignedbb.maxX - offset, axisalignedbb.maxY - offset, axisalignedbb.maxZ - offset);
+ // Sakura end
if (this.level().hasChunksAt(blockposition, blockposition1)) {
BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos();
diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
index abf41ee186fd7d8e0963112b886d833496c2fb1a..c1de583f8336e18a591ebf4a0f8bf92ac8c5735f 100644
--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
@@ -94,6 +94,8 @@ public class FallingBlockEntity extends Entity {
this.yo = y;
this.zo = z;
this.setStartPos(this.blockPosition());
+ this.physics = world.localConfig().config(this.blockPosition()).physicsVersion; // Sakura
+ this.eyeHeight = this.physics.isLegacy() ? 0.49f : this.eyeHeight; // Sakura
}
public static FallingBlockEntity fall(Level world, BlockPos pos, BlockState state) {
@@ -106,7 +108,11 @@ public class FallingBlockEntity extends Entity {
FallingBlockEntity entityfallingblock = new FallingBlockEntity(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, iblockdata.hasProperty(BlockStateProperties.WATERLOGGED) ? (BlockState) iblockdata.setValue(BlockStateProperties.WATERLOGGED, false) : iblockdata);
if (!CraftEventFactory.callEntityChangeBlockEvent(entityfallingblock, blockposition, iblockdata.getFluidState().createLegacyBlock())) return entityfallingblock; // CraftBukkit
- world.setBlock(blockposition, iblockdata.getFluidState().createLegacyBlock(), 3);
+ // Sakura start - physics version api
+ if (entityfallingblock.physics.afterOrEqual(1_18_2)) {
+ world.setBlock(blockposition, iblockdata.getFluidState().createLegacyBlock(), 3);
+ }
+ // Sakura end
world.addFreshEntity(entityfallingblock, spawnReason); // CraftBukkit
return entityfallingblock;
}
@@ -194,13 +200,50 @@ public class FallingBlockEntity extends Entity {
// Sakura start
@Override
public final double getEyeY() {
- return heightParity ? getY() : super.getEyeY();
+ return heightParity ? this.getY() : super.getEyeY();
}
// Sakura end
+ // Sakura start - physics version api
+ @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) level()).getChunkSource().blockChanged(blockposition);
+ }
+ this.discard(EntityRemoveEvent.Cause.DESPAWN);
+ }
+ }
+ // Sakura end - physics version api
@Override
protected double getDefaultGravity() {
- return 0.04D;
+ return this.physics.before(1_14_0) ? 0.04F : 0.04D; // Sakura - physics version api
}
@Override
@@ -210,6 +253,11 @@ public class FallingBlockEntity extends Entity {
} else {
Block block = this.blockState.getBlock();
+ // Sakura start - physics version api
+ if (this.time == 0 && this.physics.before(1_18_2)) {
+ this.removeBlockOnFall(block);
+ }
+ // Sakura end - physics version api
++this.time;
this.applyGravity();
this.moveBasic(MoverType.SELF, this.getDeltaMovement()); // Sakura - optimise simple entity movement
@@ -224,8 +272,15 @@ public class FallingBlockEntity extends Entity {
}
// Paper end - Configurable falling blocks height nerf
this.handlePortal();
+ // Sakura start - physics version api
+ if (this.physics.before(1_12_0)) {
+ this.scaleDeltaMovement(0.98F);
+ }
if (!this.level().isClientSide && (this.isAlive() || this.forceTickAfterTeleportToDuplicate)) {
- BlockPos blockposition = 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 blockposition = this.physics.before(1_17_0) ? this.patchedBlockPosition() : this.blockPosition();
+ // Sakura end - physics version api
boolean flag = this.blockState.getBlock() instanceof ConcretePowderBlock;
boolean flag1 = flag && this.level().getFluidState(blockposition).is(FluidTags.WATER);
double d0 = this.getDeltaMovement().lengthSqr();
@@ -250,8 +305,11 @@ public class FallingBlockEntity extends Entity {
} else {
BlockState iblockdata = this.level().getBlockState(blockposition);
- this.multiplyDeltaMovement(0.7D, -0.5D, 0.7D); // Sakura - reduce movement allocations
- if (!iblockdata.is(Blocks.MOVING_PISTON)) {
+ // Sakura start - physics version api
+ double friction = this.physics.before(1_14_0) ? 0.7F : 0.7D;
+ this.multiplyDeltaMovement(friction, -0.5D, friction); // Sakura - reduce movement allocations
+ if (!iblockdata.is(Blocks.MOVING_PISTON) && (flag1 || !this.physics.isWithin(1_9_0, 1_12_0) || this.isAbleToStackOnBlock())) {
+ // Sakura end - physics version api
if (!this.cancelDrop) {
boolean flag2 = iblockdata.canBeReplaced((BlockPlaceContext) (new DirectionalPlaceContext(this.level(), blockposition, Direction.DOWN, ItemStack.EMPTY, Direction.UP)));
boolean flag3 = FallingBlock.isFree(this.level().getBlockState(blockposition.below())) && (!flag || !flag1);
@@ -318,7 +376,12 @@ public class FallingBlockEntity extends Entity {
}
}
- this.scaleDeltaMovement(0.98D); // Sakura - reduce movement allocations
+ // Sakura start - physics version api
+ if (physics.afterOrEqual(1_12_0)) {
+ double drag = physics.before(1_14_0) ? 0.98F : 0.98D;
+ this.scaleDeltaMovement(drag); // Sakura - reduce movement allocations
+ }
+ // Sakura end - physics version api
}
}
diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
index a5b7f3bf42e43a9b3673e8725c5f20f7a3e7dbe6..cdba6fd4c79919b9f1dcb41b8df1dca8563a6174 100644
--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
+++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
@@ -78,6 +78,13 @@ public class PrimedTnt extends Entity implements TraceableEntity {
case Y -> multiplyDeltaMovement(0, 1, 0);
}
// Sakura end
+ // Sakura start - physics version api
+ this.physics = world.localConfig().config(this.blockPosition()).physicsVersion;
+ this.eyeHeight = this.physics.isLegacy() ? 0.49f : this.eyeHeight;
+ if (this.physics.isLegacy()) {
+ multiplyDeltaMovement(0, 1, 0);
+ }
+ // Sakura end - physics version api
}
@Override
@@ -125,10 +132,26 @@ public class PrimedTnt extends Entity implements TraceableEntity {
}
}
// Sakura end
+ // Sakura start - physics version api
+ @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 - physics version api
@Override
protected double getDefaultGravity() {
- return 0.04D;
+ return this.physics.before(1_14_0) ? 0.04F : 0.04D; // Sakura - physics version api
}
@Override
@@ -143,15 +166,19 @@ public class PrimedTnt extends Entity implements TraceableEntity {
return;
}
// Paper end - Configurable TNT height nerf
- this.scaleDeltaMovement(0.98D); // Sakura - reduce movement allocations
+ // Sakura start - physics version api
+ double drag = this.physics.before(1_14_0) ? 0.98F : 0.98D;
+ this.scaleDeltaMovement(drag); // Sakura - reduce movement allocations
if (this.onGround()) {
- this.multiplyDeltaMovement(0.7D, -0.5D, 0.7D); // Sakura - reduce movement allocations
+ double friction = this.physics.before(1_14_0) ? 0.7F : 0.7D;
+ this.multiplyDeltaMovement(friction, -0.5D, friction); // Sakura - reduce movement allocations
+ // Sakura end - physics version api
}
int i = this.getFuse() - 1;
this.setFuse(i);
- if (i <= 0) {
+ if (this.physics.before(1_9_0) ? (i < 0) : (i <= 0)) { // Sakura - physics version api
// 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.respawnMerged(); // Sakura
@@ -204,7 +231,10 @@ public class PrimedTnt extends Entity implements TraceableEntity {
ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent((org.bukkit.entity.Explosive)this.getBukkitEntity());
if (!event.isCancelled()) {
- this.level().explode(this, Explosion.getDefaultDamageSource(this.level(), this), this.usedPortal ? PrimedTnt.USED_PORTAL_DAMAGE_CALCULATOR : null, this.getX(), this.getY(0.0625D), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.TNT);
+ // Sakura start - physics version api
+ double pos = this.physics.before(1_10_0) ? this.getY() + (double) 0.49f : this.getY(0.0625D);
+ this.level().explode(this, Explosion.getDefaultDamageSource(this.level(), this), this.usedPortal ? PrimedTnt.USED_PORTAL_DAMAGE_CALCULATOR : null, this.getX(), pos, this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.TNT);
+ // Sakura end
}
// CraftBukkit end
}
@@ -274,7 +304,7 @@ public class PrimedTnt extends Entity implements TraceableEntity {
// Paper start - Option to prevent TNT from moving in water
@Override
public boolean isPushedByFluid() {
- return !level().paperConfig().fixes.preventTntFromMovingInWater && level().sakuraConfig().cannons.mechanics.tntFlowsInWater && super.isPushedByFluid(); // Sakura - convenience
+ return !level().paperConfig().fixes.preventTntFromMovingInWater && !this.physics.isLegacy() && level().sakuraConfig().cannons.mechanics.tntFlowsInWater && super.isPushedByFluid(); // Sakura - physics version // Sakura - convenience
}
// Paper end - Option to prevent TNT from moving in water
}
diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java
index b35a51c8e51103260f9d250e318af8a00c21533f..77fcdc8aa11df094e4ac2185bf16d0b1a8b4aacb 100644
--- a/src/main/java/net/minecraft/world/level/Explosion.java
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
@@ -77,6 +77,7 @@ public class Explosion {
public float yield;
// CraftBukkit end
private final boolean consistentRadius; // Sakura - consistent explosion radius
+ protected final me.samsuik.sakura.physics.PhysicsVersion physics; // Sakura - physics version api
public static DamageSource getDefaultDamageSource(Level world, @Nullable Entity source) {
return world.damageSources().explosion(source, Explosion.getIndirectSourceEntityInternal(source));
@@ -115,6 +116,7 @@ public class Explosion {
this.explosionSound = soundEvent;
this.yield = this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F; // CraftBukkit
this.consistentRadius = world.localConfig().config(BlockPos.containing(x, y, z)).consistentRadius; // Sakura - consistent explosion radius
+ this.physics = entity != null ? entity.physics() : world.localConfig().config(BlockPos.containing(x, y, z)).physicsVersion; // Sakura - physics version api
}
// Sakura start - optimise paper explosions
@@ -507,8 +509,12 @@ public class Explosion {
final float density = entity.level().densityCache.getKnownDensity(vec3d1);
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 - physics version api
+ } else if (entity.physics().before(1_14_0)) {
+ hitResult = entity.level().rayTrace(vec3d1, source);
} else {
- hitResult = entity.level().clip(new ClipContext(vec3d1, source, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, entity)).getType();
+ hitResult = entity.level().clip(new ClipContext(vec3d1, source, entity.physics().afterOrEqual(1_16_0) ? ClipContext.Block.COLLIDER : ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, entity)).getType();
+ // Sakura end - physics version api
}
if (hitResult == HitResult.Type.MISS) {
// Sakura end - replace density cache
@@ -613,6 +619,14 @@ public class Explosion {
}
if (cachedBlock.outOfWorld) {
+ // Sakura start - physics version api
+ if (this.physics.before(1_17_0)) {
+ d4 += d0;
+ d5 += d1;
+ d6 += d2;
+ continue;
+ }
+ // Sakura end - physics version api
break;
}
@@ -717,9 +731,15 @@ public class Explosion {
if (d7 <= 1.0D) {
double d8 = entity.getX() - this.x;
- double d9 = (entity instanceof PrimedTnt ? entity.getY() : entity.getEyeY()) - this.y;
+ double d9 = entity.getEyeY() - this.y; // Sakura - physics version api
double d10 = entity.getZ() - this.z;
double d11 = Math.sqrt(d8 * d8 + d9 * d9 + d10 * d10);
+ // Sakura start - physics version api
+ if (this.physics.before(1_17_0)) {
+ d7 = (float) d7;
+ d11 = (float) d11;
+ }
+ // Sakura end - physics version api
if (d11 != 0.0D) {
d8 /= d11;
@@ -1050,7 +1070,7 @@ public class 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, blockCache, blockPos); // Paper - optimise explosions;
+ blockDensity = this.getSeenPercent(vec3d, entity, blockCache, blockPos); // Sakura - physics version api // Paper - optimise explosions;
this.level.densityCache.putDensity(vec3d, entity, blockDensity);
// Sakura end - replace density cache
}
@@ -1058,6 +1078,17 @@ public class Explosion {
return blockDensity;
}
+ // Sakura start - physics version api
+ private float getSeenPercent(Vec3 vec3d, Entity entity, ExplosionBlockCache[] blockCache, BlockPos.MutableBlockPos blockPos) {
+ if (this.physics.afterOrEqual(1_16_0)) {
+ // Papers impl is untouched, intended to be used as a fast path.
+ return this.getSeenFraction(vec3d, entity, blockCache, blockPos);
+ } else {
+ return getSeenPercent(vec3d, entity);
+ }
+ }
+ // Sakura end - physics version api
+
static class CacheKey {
private final Level world;
private final double posX, posY, posZ;
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 7a079b432092f70bac657520a0c71d0a0b4ccdb0..8a8ea38bb3e88e27fcd7e9f9f4c604956120b1d3 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -195,6 +195,205 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
public CraftWorld getWorld() {
return this.world;
}
+ // Sakura start - physics version api
+ public net.minecraft.world.phys.BlockHitResult.Type rayTrace(net.minecraft.world.phys.Vec3 vec3d, net.minecraft.world.phys.Vec3 vec3d1) {
+ // May deviate from vanilla here; I remember noticing a bug and there's no fix commit.
+ int i = Mth.floor(vec3d1.x);
+ int j = Mth.floor(vec3d1.y);
+ int k = Mth.floor(vec3d1.z);
+ int l = Mth.floor(vec3d.x);
+ int i1 = Mth.floor(vec3d.y);
+ int j1 = Mth.floor(vec3d.z);
+ BlockPos.MutableBlockPos blockposition = new BlockPos.MutableBlockPos(l, i1, j1);
+ LevelChunk chunk = this.getChunkIfLoaded(l >> 4, j1 >> 4);
+
+ // probably a bad idea to copy this over so we don't need to do a null check
+ if (chunk == null) {
+ return net.minecraft.world.phys.BlockHitResult.Type.MISS;
+ }
+
+ BlockState iblockdata = chunk.getBlockState(blockposition);
+ net.minecraft.world.phys.shapes.VoxelShape shape = iblockdata.getShape(this, blockposition);
+
+ for (AABB bb : shape.toAabbs()) {
+ if (clip(bb, blockposition, vec3d, vec3d1)) {
+ return net.minecraft.world.phys.BlockHitResult.Type.BLOCK;
+ }
+ }
+
+ int k1 = 200;
+
+ while (k1-- >= 0) {
+ if (l == i && i1 == j && j1 == k) {
+ return net.minecraft.world.phys.BlockHitResult.Type.MISS;
+ }
+
+ boolean flag3 = true;
+ boolean flag4 = true;
+ boolean flag5 = true;
+ double d0 = 999.0D;
+ double d1 = 999.0D;
+ double d2 = 999.0D;
+
+ if (i > l) {
+ d0 = (double) l + 1.0D;
+ } else if (i < l) {
+ d0 = (double) l + 0.0D;
+ } else {
+ flag3 = false;
+ }
+
+ if (j > i1) {
+ d1 = (double) i1 + 1.0D;
+ } else if (j < i1) {
+ d1 = (double) i1 + 0.0D;
+ } else {
+ flag4 = false;
+ }
+
+ if (k > j1) {
+ d2 = (double) j1 + 1.0D;
+ } else if (k < j1) {
+ d2 = (double) j1 + 0.0D;
+ } else {
+ flag5 = false;
+ }
+
+ double d3 = 999.0D;
+ double d4 = 999.0D;
+ double d5 = 999.0D;
+ double d6 = vec3d1.x - vec3d.x;
+ double d7 = vec3d1.y - vec3d.y;
+ double d8 = vec3d1.z - vec3d.z;
+
+ if (flag3) {
+ d3 = (d0 - vec3d.x) / d6;
+ }
+
+ if (flag4) {
+ d4 = (d1 - vec3d.y) / d7;
+ }
+
+ if (flag5) {
+ d5 = (d2 - vec3d.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 enumdirection;
+
+ if (d3 < d4 && d3 < d5) {
+ enumdirection = i > l ? Direction.WEST : Direction.EAST;
+ vec3d = new net.minecraft.world.phys.Vec3(d0, vec3d.y + d7 * d3, vec3d.z + d8 * d3);
+ } else if (d4 < d5) {
+ enumdirection = j > i1 ? Direction.DOWN : Direction.UP;
+ vec3d = new net.minecraft.world.phys.Vec3(vec3d.x + d6 * d4, d1, vec3d.z + d8 * d4);
+ } else {
+ enumdirection = k > j1 ? Direction.NORTH : Direction.SOUTH;
+ vec3d = new net.minecraft.world.phys.Vec3(vec3d.x + d6 * d5, vec3d.y + d7 * d5, d2);
+ }
+
+ l = Mth.floor(vec3d.x) - (enumdirection == Direction.EAST ? 1 : 0);
+ i1 = Mth.floor(vec3d.y) - (enumdirection == Direction.UP ? 1 : 0);
+ j1 = Mth.floor(vec3d.z) - (enumdirection == Direction.SOUTH ? 1 : 0);
+ blockposition.set(l, i1, j1);
+
+ int chunkX = l >> 4;
+ int chunkZ = j1 >> 4;
+
+ if (chunkX != chunk.locX || chunkZ != chunk.locZ) {
+ chunk = this.getChunkIfLoaded(chunkX, chunkZ);
+ }
+
+ if (chunk == null) {
+ return net.minecraft.world.phys.BlockHitResult.Type.MISS;
+ }
+
+ iblockdata = chunk.getBlockState(blockposition);
+ shape = iblockdata.getShape(this, blockposition);
+
+ for (AABB bb : shape.toAabbs()) {
+ if (clip(bb, blockposition, vec3d, vec3d1)) {
+ 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 = clip(bb.minX, x, vec3d.x);
+ double minYd = clip(bb.minY, y, vec3d.y);
+ double minZd = clip(bb.minZ, z, vec3d.z);
+ double maxXd = clip(bb.maxX, x, vec3d.x);
+ double maxYd = clip(bb.maxY, y, vec3d.y);
+ double maxZd = clip(bb.maxZ, z, vec3d.z);
+
+ return clipX(vec3d, bb, minXd, y, z) || clipY(vec3d, bb, minYd, x, z) || clipZ(vec3d, bb, minZd, x, y)
+ || clipX(vec3d, bb, maxXd, y, z) || clipY(vec3d, bb, maxYd, x, z) || clipZ(vec3d, bb, maxZd, x, y);
+ }
+
+ private double clip(double bound, double axisD, double axisN) {
+ // This is my friend jerry, he was an epsilon. Unfortunately, once day
+ // he was cast to a float. Now he's spending his retirement here as a double.
+ if (axisD * axisD < 1.0000000116860974E-7D) {
+ return -1.0;
+ }
+
+ return (bound - axisN) / axisD;
+ }
+
+ private boolean clipX(net.minecraft.world.phys.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(net.minecraft.world.phys.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(net.minecraft.world.phys.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 - physics version api
public CraftServer getCraftServer() {
return (CraftServer) Bukkit.getServer();
diff --git a/src/main/java/net/minecraft/world/level/block/FallingBlock.java b/src/main/java/net/minecraft/world/level/block/FallingBlock.java
index 1ea1232a5ba3e48eef3a139d6487c9a190155ebd..71364fe94cfeefa07fac3ee6359f7abd9bb58106 100644
--- a/src/main/java/net/minecraft/world/level/block/FallingBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/FallingBlock.java
@@ -35,6 +35,15 @@ public abstract class FallingBlock extends Block implements Fallable {
return super.updateShape(state, direction, neighborState, world, pos, neighborPos);
}
+ // Sakura start - physics version api
+ @Override
+ public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) {
+ if (world.localConfig().config(pos).physicsVersion.before(1_18_2)) {
+ world.scheduleTick(pos, this, this.getDelayAfterPlace());
+ }
+ }
+ // Sakura end
+
@Override
protected void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
if (isFree(world.getBlockState(pos.below())) && pos.getY() >= world.getMinBuildHeight()) {
diff --git a/src/main/java/net/minecraft/world/level/block/FenceGateBlock.java b/src/main/java/net/minecraft/world/level/block/FenceGateBlock.java
index 26ed17e433cbafbbf788231f27f296f08048adfe..1e28d5175bbb4dc2d4c1c3080825e797b574fc06 100644
--- a/src/main/java/net/minecraft/world/level/block/FenceGateBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/FenceGateBlock.java
@@ -180,8 +180,13 @@ public class FenceGateBlock extends HorizontalDirectionalBlock {
}
// CraftBukkit end
- if ((Boolean) state.getValue(FenceGateBlock.POWERED) != flag1) {
- world.setBlock(pos, (BlockState) ((BlockState) state.setValue(FenceGateBlock.POWERED, flag1)).setValue(FenceGateBlock.OPEN, flag1), 2);
+ // Sakura start
+ final boolean legacy = world.localConfig().config(pos).physicsVersion.before(1_11_0);
+ final boolean powered = state.getValue(FenceGateBlock.POWERED);
+ if (legacy ? (flag1 || sourceBlock.defaultBlockState().isSignalSource()) : powered != flag1) {
+ final boolean openGate = legacy && (flag1 == powered || state.getValue(FenceGateBlock.OPEN) != powered) ? state.getValue(OPEN) : flag1;
+ world.setBlock(pos, (BlockState) ((BlockState) state.setValue(FenceGateBlock.POWERED, flag1)).setValue(FenceGateBlock.OPEN, openGate), 2);
+ // Sakura end
if ((Boolean) state.getValue(FenceGateBlock.OPEN) != flag1) {
world.playSound((Player) null, pos, flag1 ? this.type.fenceGateOpen() : this.type.fenceGateClose(), SoundSource.BLOCKS, 1.0F, world.getRandom().nextFloat() * 0.1F + 0.9F);
world.gameEvent((Entity) null, (Holder) (flag1 ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE), pos);
diff --git a/src/main/java/net/minecraft/world/level/block/LadderBlock.java b/src/main/java/net/minecraft/world/level/block/LadderBlock.java
index 4b402a7222f78617ef7d28d329f4daac74954347..54781ea0771327f93a7cf672bb4b2945700c47e5 100644
--- a/src/main/java/net/minecraft/world/level/block/LadderBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/LadderBlock.java
@@ -28,6 +28,21 @@ public class LadderBlock extends Block implements SimpleWaterloggedBlock {
protected static final VoxelShape WEST_AABB = Block.box(13.0, 0.0, 0.0, 16.0, 16.0, 16.0);
protected static final VoxelShape SOUTH_AABB = Block.box(0.0, 0.0, 0.0, 16.0, 16.0, 3.0);
protected static final VoxelShape NORTH_AABB = Block.box(0.0, 0.0, 13.0, 16.0, 16.0, 16.0);
+ // Sakura start - physics version api
+ 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 - physics version api
@Override
public MapCodec<LadderBlock> codec() {
@@ -39,8 +54,18 @@ public class LadderBlock extends Block implements SimpleWaterloggedBlock {
this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(WATERLOGGED, Boolean.valueOf(false)));
}
+ // Sakura start - physics version api
+ @Override
+ public final boolean hasDynamicShape() {
+ return true;
+ }
+
@Override
protected VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
+ if (world instanceof net.minecraft.world.level.Level level && level.localConfig().config(pos).physicsVersion.before(1_9_0)) {
+ return legacyShape(state.getValue(FACING));
+ }
+ // Sakura end - physics version api
switch ((Direction)state.getValue(FACING)) {
case NORTH:
return NORTH_AABB;
diff --git a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java
index 84623c632d8c2f0fa7ec939c711316d757117d23..baf791608420198493df24c68144fd29ec9fad7f 100644
--- a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java
@@ -190,8 +190,26 @@ public class LiquidBlock extends Block implements BucketPickup {
BlockPos blockposition1 = pos.relative(enumdirection.getOpposite());
if (world.getFluidState(blockposition1).is(FluidTags.WATER)) {
- Block block = world.getFluidState(pos).isSource() ? Blocks.OBSIDIAN : Blocks.COBBLESTONE;
-
+ // Sakura start
+ final FluidState fluidState = state.getFluidState();
+ final Block block;
+
+ if (fluidState.isSource()) {
+ block = Blocks.OBSIDIAN;
+ } else {
+ final me.samsuik.sakura.physics.PhysicsVersion physics = world.localConfig().config(pos).physicsVersion;
+
+ // SANITY: In legacy a patch by paper removes the fluid level condition from vanilla.
+ if (physics.afterOrEqual(1_16_0) || physics.isLegacy()
+ || physics.afterOrEqual(1_13_0) && fluidState.getHeight(world, pos) >= 0.44444445f
+ || physics.before(1_13_0) && FlowingFluid.getLegacyLevel(fluidState) <= 4
+ ) {
+ block = Blocks.COBBLESTONE;
+ } else {
+ return true;
+ }
+ }
+ // Sakura end
// CraftBukkit start
if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(world, pos, block.defaultBlockState())) {
this.fizz(world, pos);
diff --git a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java
index 88ddd1747d9786210e8faf412b3b0363df4bab43..a6f0ded367341e6b9f9c7b1c4254dd696ead2f8d 100644
--- a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java
@@ -699,6 +699,10 @@ public class RedStoneWireBlock extends Block {
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
if (!player.getAbilities().mayBuild) {
return InteractionResult.PASS;
+ // Sakura start
+ } else if (world.localConfig().config(pos).physicsVersion.before(1_16_0)) {
+ return InteractionResult.PASS;
+ // Sakura end
} else {
if (RedStoneWireBlock.isCross(state) || RedStoneWireBlock.isDot(state)) {
BlockState iblockdata1 = RedStoneWireBlock.isCross(state) ? this.defaultBlockState() : this.crossState;
diff --git a/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java b/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java
index 932831bb5632ead5850842fc77192c841571162e..fdf07b8aa7a10da15a9473bcb12e8cb0404654f8 100644
--- a/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java
@@ -21,6 +21,7 @@ public class WaterlilyBlock extends BushBlock {
public static final MapCodec<WaterlilyBlock> CODEC = simpleCodec(WaterlilyBlock::new);
protected static final VoxelShape AABB = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 1.5D, 15.0D);
+ protected static final VoxelShape LEGACY_AABB = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 0.25D, 16.0D); // Sakura
@Override
public MapCodec<WaterlilyBlock> codec() {
@@ -46,8 +47,18 @@ public class WaterlilyBlock extends BushBlock {
}
+ // Sakura start
+ @Override
+ public final boolean hasDynamicShape() {
+ return true;
+ }
+
@Override
protected VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
+ if (world instanceof net.minecraft.world.level.Level level && level.localConfig().config(pos).physicsVersion.before(1_9_0)) {
+ return LEGACY_AABB;
+ }
+ // Sakura end
return WaterlilyBlock.AABB;
}
diff --git a/src/main/java/net/minecraft/world/level/block/piston/MovingPistonBlock.java b/src/main/java/net/minecraft/world/level/block/piston/MovingPistonBlock.java
index f970fca8a8b479f2d2b927bcee2d73f02bfcd1b3..ff31e517a5f2eb51acef070d6455a0f86e40dd9f 100644
--- a/src/main/java/net/minecraft/world/level/block/piston/MovingPistonBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/piston/MovingPistonBlock.java
@@ -110,6 +110,17 @@ public class MovingPistonBlock extends BaseEntityBlock {
@Override
protected VoxelShape getCollisionShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
PistonMovingBlockEntity pistonMovingBlockEntity = this.getBlockEntity(world, pos);
+ // Sakura start - physics version api
+ if (pistonMovingBlockEntity != null && world instanceof Level level && level.localConfig().config(pos).physicsVersion.before(1_9_0)) {
+ VoxelShape shape = pistonMovingBlockEntity.getCollisionShapeFromProgress(level, pos);
+
+ if (context.isAbove(shape, pos, false)) {
+ return shape;
+ } else {
+ return pistonMovingBlockEntity.getMovedState().getCollisionShape(world, pos);
+ }
+ }
+ // Sakura end
return pistonMovingBlockEntity != null ? pistonMovingBlockEntity.getCollisionShape(world, pos) : Shapes.empty();
}
diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java
index e0c62227b279a5fe0f3868fbf9ce8c78c515a09c..3f840b82827b803a5fc594f6008cddb09926ca2d 100644
--- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java
@@ -171,6 +171,11 @@ public class PistonBaseBlock extends DirectionalBlock {
// }
// PAIL: checkME - what happened to setTypeAndData?
// CraftBukkit end
+ // Sakura start - physics version api
+ if (world.localConfig().config(pos).physicsVersion.before(1_9_0)) {
+ world.setBlock(pos, state.setValue(PistonBaseBlock.EXTENDED, false), 18);
+ }
+ // Sakura end
world.blockEvent(pos, this, b0, enumdirection.get3DDataValue());
}
diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonHeadBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonHeadBlock.java
index bf58f33a5dc11b9e36cb9a26a73558c675a429df..755cbe2925fb5230fdff6c14b94dbafb924ba2c2 100644
--- a/src/main/java/net/minecraft/world/level/block/piston/PistonHeadBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonHeadBlock.java
@@ -138,6 +138,11 @@ public class PistonHeadBlock extends DirectionalBlock {
@Override
protected boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
BlockState blockState = world.getBlockState(pos.relative(state.getValue(FACING).getOpposite()));
+ // Sakura start - physics version api
+ if (world instanceof Level level && level.localConfig().config(pos).physicsVersion.before(1_9_0)) {
+ return this.isFittingBase(state, blockState);
+ }
+ // Sakura end
return this.isFittingBase(state, blockState) || blockState.is(Blocks.MOVING_PISTON) && blockState.getValue(FACING) == state.getValue(FACING);
}
@@ -145,6 +150,10 @@ public class PistonHeadBlock extends DirectionalBlock {
protected void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) {
if (state.canSurvive(world, pos)) {
world.neighborChanged(pos.relative(state.getValue(FACING).getOpposite()), sourceBlock, sourcePos);
+ // Sakura start - physics version api
+ } else if (world.localConfig().config(pos).physicsVersion.before(1_9_0)) {
+ world.setBlock(pos, Blocks.AIR.defaultBlockState(), 19);
+ // Sakura end
}
}
diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
index d555ad1dd2f648b84920eceec6cc99e8801334b3..b2ecc615379856f661ba87bdeb28f75aa7d61602 100644
--- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
@@ -164,6 +164,12 @@ public class PistonMovingBlockEntity extends BlockEntity {
double i = 0.0;
+ // Sakura start - physics version api
+ if (entity.physics().before(1_11_0)) {
+ moveEntityByPistonFromDirection(direction, entity, aABB);
+ return;
+ }
+ // Sakura end - physics version api
for (AABB aABB2 : list2) {
AABB aABB3 = PistonMath.getMovementArea(moveByPositionAndProgress(pos, aABB2, blockEntity), direction, d);
AABB aABB4 = entity.getBoundingBox();
@@ -293,14 +299,167 @@ public class PistonMovingBlockEntity extends BlockEntity {
}
}
}
+
+ // Sakura start - physics version api
+ @javax.annotation.Nullable
+ private AABB getBoundsFromProgress(Level 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(Level 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 - physics version api
public static void tick(Level world, BlockPos pos, BlockState state, PistonMovingBlockEntity blockEntity) {
+ me.samsuik.sakura.physics.PhysicsVersion physicsVersion = world.localConfig().config(pos).physicsVersion; // Sakura - physics version api
blockEntity.lastTicked = world.getGameTime();
blockEntity.progressO = blockEntity.progress;
if (blockEntity.progressO >= 1.0F) {
if (world.isClientSide && blockEntity.deathTicks < 5) {
blockEntity.deathTicks++;
} else {
+ // Sakura start - physics version api
+ if (physicsVersion.isWithin(1_9_0, 1_10_0)) {
+ moveCollidedEntities(world, pos, 1.0f, blockEntity);
+ moveStuckEntities(world, pos, 1.0f, blockEntity);
+ } else if (physicsVersion.before(1_9_0)) {
+ blockEntity.moveEntities(world, 0.25f);
+ }
+ // Sakura end - physics version api
world.removeBlockEntity(pos);
blockEntity.setRemoved();
if (world.getBlockState(pos).is(Blocks.MOVING_PISTON)) {
@@ -320,12 +479,23 @@ public class PistonMovingBlockEntity extends BlockEntity {
}
} else {
float f = blockEntity.progress + 0.5F;
+ // Sakura start - physics version api
+ if (physicsVersion.afterOrEqual(1_11_0)) {
moveCollidedEntities(world, pos, f, blockEntity);
moveStuckEntities(world, pos, f, blockEntity);
+ }
+
blockEntity.progress = f;
if (blockEntity.progress >= 1.0F) {
blockEntity.progress = 1.0F;
}
+ if (physicsVersion.isWithin(1_9_0, 1_10_0)) {
+ moveCollidedEntities(world, pos, f, blockEntity);
+ moveStuckEntities(world, pos, f, blockEntity);
+ } else if (blockEntity.extending && physicsVersion.before(1_9_0)) {
+ blockEntity.moveEntities(world, blockEntity.progress - blockEntity.progressO + 0.0625f);
+ }
+ // Sakura end - physics version api
}
}
diff --git a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
index 5ad6880845ed699077ad355ef1edcfb1c6c7bee4..e6acf6c4bcdb8d2548aa6a8b8d9af7c56877cfd4 100644
--- a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
+++ b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
@@ -525,7 +525,7 @@ public abstract class FlowingFluid extends Fluid {
this.spread(world, pos, state);
}
- protected static int getLegacyLevel(FluidState state) {
+ public static int getLegacyLevel(FluidState state) { // Sakura - protected -> public
return state.isSource() ? 0 : 8 - Math.min(state.getAmount(), 8) + ((Boolean) state.getValue(FlowingFluid.FALLING) ? 8 : 0);
}
diff --git a/src/main/java/net/minecraft/world/level/material/LavaFluid.java b/src/main/java/net/minecraft/world/level/material/LavaFluid.java
index 3bb4a9a1a6249e8ba2de237f801210e7f4fd5825..8dfa05a586bd21ef8aeab713cad4628166982bfa 100644
--- a/src/main/java/net/minecraft/world/level/material/LavaFluid.java
+++ b/src/main/java/net/minecraft/world/level/material/LavaFluid.java
@@ -175,7 +175,10 @@ public abstract class LavaFluid extends FlowingFluid {
@Override
public boolean canBeReplacedWith(FluidState state, BlockGetter world, BlockPos pos, Fluid fluid, Direction direction) {
- return state.getHeight(world, pos) >= 0.44444445F && fluid.is(FluidTags.WATER);
+ // Sakura start
+ return state.getHeight(world, pos) >= 0.44444445F && fluid.is(FluidTags.WATER)
+ && world instanceof Level level && level.localConfig().config(pos).physicsVersion.afterOrEqual(1_13_0);
+ // Sakura end
}
@Override
diff --git a/src/main/java/net/minecraft/world/level/material/WaterFluid.java b/src/main/java/net/minecraft/world/level/material/WaterFluid.java
index 109f71401c65f476ccf6813137386fc9fef10254..786aba3810b71a543469dab6b2b2c1ff4ca2edd5 100644
--- a/src/main/java/net/minecraft/world/level/material/WaterFluid.java
+++ b/src/main/java/net/minecraft/world/level/material/WaterFluid.java
@@ -120,7 +120,10 @@ public abstract class WaterFluid extends FlowingFluid {
@Override
public boolean canBeReplacedWith(FluidState state, BlockGetter world, BlockPos pos, Fluid fluid, Direction direction) {
- return direction == Direction.DOWN && !fluid.is(FluidTags.WATER);
+ // Sakura start
+ return direction == Direction.DOWN && !fluid.is(FluidTags.WATER)
+ || fluid.is(FluidTags.LAVA) && world instanceof Level level && level.localConfig().config(pos).physicsVersion.before(1_13_0);
+ // Sakura end
}
@Override