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

Paper Changes:
PaperMC/Paper@914fb08 Fix Entity#updateFluidHeightAndDoFluidPushing inconsistency with Vanilla
PaperMC/Paper@e9fa3a7 Use correct queue when blocking on futures
PaperMC/Paper@0ff899d Prevent world mutation on copper golem spawn cancel (#13152)
PaperMC/Paper@bae47d3 Update to 1.21.10 (#13127)
PaperMC/Paper@8339bb3 Update DataConverter constants for 1.21.10
PaperMC/Paper@3982efa Sync Moonrise
PaperMC/Paper@fa57d4b Remove Vanilla packet processing at start of tick
PaperMC/Paper@fba780d Rebuild patches
2025-10-07 20:21:51 +01:00

1210 lines
68 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 82dac4fbaf3572391dad61356ba5351b725194ff..0f0f1cb55bc167071e84ec998469001374995e8f 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 server mechanics
+ return performAABBCollisions(moveVector, axisalignedbb, potentialCollisions, null);
+ }
+ public static Vec3 performAABBCollisions(final Vec3 moveVector, AABB axisalignedbb,
+ final List<AABB> potentialCollisions,
+ final me.samsuik.sakura.mechanics.MinecraftMechanicsTarget mechanicsTarget) {
+ // Sakura end - configure server mechanics
double x = moveVector.x;
double y = moveVector.y;
double z = moveVector.z;
@@ -1785,7 +1792,7 @@ public final class CollisionUtil {
}
}
- final boolean xSmaller = Math.abs(x) < Math.abs(z);
+ final boolean xSmaller = me.samsuik.sakura.mechanics.EntityBehaviour.prioritiseXFirst(x, z, mechanicsTarget); // Sakura - configure server mechanics
if (xSmaller && z != 0.0) {
z = performAABBCollisionsZ(axisalignedbb, z, potentialCollisions);
@@ -1811,9 +1818,21 @@ public final class CollisionUtil {
public static Vec3 performCollisions(final Vec3 moveVector, AABB axisalignedbb,
final List<VoxelShape> voxels,
final List<AABB> aabbs) {
+ // Sakura start - configure server mechanics
+ 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.mechanics.MinecraftMechanicsTarget mechanicsTarget) {
+ if (mechanicsTarget.isServerType(me.samsuik.sakura.mechanics.ServerType.PAPER) && mechanicsTarget.between(me.samsuik.sakura.mechanics.MechanicVersion.v1_18_2, me.samsuik.sakura.mechanics.MechanicVersion.v1_20_2)) {
+ me.samsuik.sakura.mechanics.EntityBehaviour.convertVoxelsIntoAABBs(moveVector, axisalignedbb, voxels, aabbs);
+ }
+ // Sakura end - configure server mechanics
if (voxels.isEmpty()) {
// fast track only AABBs
- return performAABBCollisions(moveVector, axisalignedbb, aabbs);
+ return performAABBCollisions(moveVector, axisalignedbb, aabbs, mechanicsTarget); // Sakura - configure server mechanics
}
double x = moveVector.x;
@@ -1828,7 +1847,7 @@ public final class CollisionUtil {
}
}
- final boolean xSmaller = Math.abs(x) < Math.abs(z);
+ final boolean xSmaller = me.samsuik.sakura.mechanics.EntityBehaviour.prioritiseXFirst(x, z, mechanicsTarget); // Sakura - configure server mechanics
if (xSmaller && z != 0.0) {
z = performAABBCollisionsZ(axisalignedbb, z, aabbs);
diff --git a/net/minecraft/core/dispenser/DispenseItemBehavior.java b/net/minecraft/core/dispenser/DispenseItemBehavior.java
index 703a75c7c6cd05a95afb630973250898dbc7223d..1531f0c275814e1346fef34dc06ea97643de382c 100644
--- a/net/minecraft/core/dispenser/DispenseItemBehavior.java
+++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java
@@ -471,6 +471,14 @@ public interface DispenseItemBehavior {
}
}
+ // Sakura start - configure server mechanics
+ final me.samsuik.sakura.mechanics.MinecraftMechanicsTarget mechanicTarget = serverLevel.localConfig().at(blockPos).mechanicsTarget;
+ if (!mechanicTarget.isServerType(me.samsuik.sakura.mechanics.ServerType.VANILLA)
+ && mechanicTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_9)
+ && !mechanicTarget.isLegacy()) {
+ event.getVelocity().setY(event.getVelocity().getY() + 0.5);
+ }
+ // Sakura end - configure server mechanics
PrimedTnt primedTnt = new PrimedTnt(serverLevel, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), null);
// CraftBukkit end
serverLevel.addFreshEntity(primedTnt);
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 128f62186d18186b7ba3a0c40a2723b8a933e8fb..c9f5accf384bae21b0a177526e77429f9795d975 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -588,6 +588,13 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
}
}
// Sakura end - merge cannon entities
+ // Sakura start - configure server mechanics
+ protected me.samsuik.sakura.mechanics.MinecraftMechanicsTarget mechanicsTarget = me.samsuik.sakura.mechanics.MinecraftMechanicsTarget.latest();
+
+ public final me.samsuik.sakura.mechanics.MinecraftMechanicsTarget mechanicsTarget() {
+ return this.mechanicsTarget;
+ }
+ // Sakura end - configure server mechanics
public Entity(EntityType<?> entityType, Level level) {
this.type = entityType;
@@ -1116,7 +1123,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
}
protected void checkSupportingBlock(boolean onGround, @Nullable Vec3 movement) {
- if (onGround) {
+ if (onGround && this.mechanicsTarget.atLeast(me.samsuik.sakura.mechanics.MechanicVersion.v1_20)) { // Sakura - configure server mechanics
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);
@@ -1170,7 +1177,10 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
this.verticalCollisionBelow = false;
this.minorHorizontalCollision = false;
} else {
- if (type == MoverType.PISTON) {
+ // Sakura start - configure server mechanics
+ final me.samsuik.sakura.mechanics.MinecraftMechanicsTarget mechanicsTarget = this.mechanicsTarget;
+ if (type == MoverType.PISTON && mechanicsTarget.atLeast(me.samsuik.sakura.mechanics.MechanicVersion.v1_11)) {
+ // Sakura end - configure server mechanics
// Paper start - EAR 2
this.activatedTick = Math.max(this.activatedTick, net.minecraft.server.MinecraftServer.currentTick + 20);
this.activatedImmunityTick = Math.max(this.activatedImmunityTick, net.minecraft.server.MinecraftServer.currentTick + 20);
@@ -1202,10 +1212,17 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
movement = this.maybeBackOffFromEdge(movement, type);
Vec3 vec3 = this.collide(movement);
double d = vec3.lengthSqr();
- if (d > 1.0E-7 || movement.lengthSqr() - d < 1.0E-7) {
- if (this.fallDistance != 0.0 && d >= 1.0 && !this.isFallingBlock) { // Sakura - optimise cannon entity movement
- double min = Math.min(vec3.length(), 8.0);
- Vec3 vec31 = this.position().add(vec3.normalize().scale(min));
+ // Sakura start - configure server mechanics
+ if (me.samsuik.sakura.mechanics.EntityBehaviour.canMoveEntity(d, movement, mechanicsTarget)) {
+ if (this.fallDistance != 0.0 && d >= 1.0 && !this.isFallingBlock && mechanicsTarget.atLeast(me.samsuik.sakura.mechanics.MechanicVersion.v1_18_2)) { // Sakura - optimise cannon entity movement
+ final Vec3 vec31;
+ if (mechanicsTarget.atLeast(me.samsuik.sakura.mechanics.MechanicVersion.v1_21_9)) {
+ double min = Math.min(Math.sqrt(d), 8.0);
+ vec31 = this.position().add(vec3.normalize().scale(min));
+ } else {
+ vec31 = this.position().add(vec3);
+ }
+ // Sakura end - configure server mechanics
BlockHitResult blockHitResult = this.level()
.clip(new ClipContext(this.position(), vec31, ClipContext.Block.FALLDAMAGE_RESETTING, ClipContext.Fluid.WATER, this));
if (blockHitResult.getType() != HitResult.Type.MISS) {
@@ -1214,9 +1231,15 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
}
Vec3 vec32 = this.position();
- Vec3 vec33 = vec32.add(vec3);
- this.addMovementThisTick(new Entity.Movement(vec32, vec33, movement));
- this.setPos(vec33);
+ // Sakura start - configure server mechanics
+ if (mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_21_6)) {
+ me.samsuik.sakura.mechanics.EntityBehaviour.changeEntityPosition(this, vec32, vec3, mechanicsTarget);
+ } else {
+ Vec3 vec33 = vec32.add(vec3);
+ this.addMovementThisTick(new Entity.Movement(vec32, vec33, movement));
+ this.setPos(vec33);
+ }
+ // Sakura end - configure server mechanics
}
profilerFiller.pop();
@@ -1247,6 +1270,11 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
} else {
if (this.horizontalCollision) {
Vec3 deltaMovement = this.getDeltaMovement();
+ // Sakura start - configure server mechanics
+ if (flag && flag1 && mechanicsTarget.between(me.samsuik.sakura.mechanics.MechanicVersion.v1_14, me.samsuik.sakura.mechanics.MechanicVersion.v1_18_2)) {
+ flag = false;
+ }
+ // Sakura end - configure server mechanics
this.setDeltaMovement(flag ? 0.0 : deltaMovement.x, deltaMovement.y, flag1 ? 0.0 : deltaMovement.z);
}
@@ -1588,7 +1616,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
}
this.collectCollisions(bb, voxelList, bbList, ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_FLAG_CHECK_BORDER);
- 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.mechanicsTarget); // Sakura - configure server mechanics
}
private Vec3 collideAxisScan(final Vec3 movement, AABB currBoundingBox, final List<VoxelShape> voxelList, final List<AABB> bbList) {
@@ -1596,7 +1624,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
double y = movement.y;
double z = movement.z;
- final boolean xSmaller = Math.abs(x) < Math.abs(z);
+ final boolean xSmaller = me.samsuik.sakura.mechanics.EntityBehaviour.prioritiseXFirst(x, z, mechanicsTarget); // Sakura - configure server mechanics
if (y != 0.0) {
y = this.scanY(currBoundingBox, y, voxelList, bbList);
@@ -1718,7 +1746,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
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.mechanicsTarget); // Sakura - configure server mechanics
final boolean collidedX = collided.x != movement.x;
final boolean collidedY = collided.y != movement.y;
@@ -1841,25 +1869,37 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
private void checkInsideBlocks(List<Entity.Movement> movements, InsideBlockEffectApplier.StepBasedCollector stepBasedCollector) {
if (this.isAffectedByBlocks()) {
LongSet set = this.visitedBlocks;
+ final me.samsuik.sakura.mechanics.MinecraftMechanicsTarget mechanicsTarget = this.mechanicsTarget; // Sakura - configure server mechanics
for (Entity.Movement movement : movements) {
Vec3 vec3 = movement.from;
Vec3 vec31 = movement.to().subtract(movement.from());
int i = 16;
- if (movement.axisDependentOriginalMovement().isPresent() && vec31.lengthSqr() > 0.0) {
- for (Direction.Axis axis : Direction.axisStepOrder(movement.axisDependentOriginalMovement().get())) {
+ // Sakura start - configure server mechanics
+ final Optional<Vec3> axisDependentMovement = movement.axisDependentOriginalMovement();
+ if (axisDependentMovement.isPresent() && vec31.lengthSqr() > 0.0 && mechanicsTarget.atLeast(me.samsuik.sakura.mechanics.MechanicVersion.v1_21_5)) {
+ final Vec3 stepOrderVec = mechanicsTarget.atLeast(me.samsuik.sakura.mechanics.MechanicVersion.v1_21_9)
+ ? axisDependentMovement.get()
+ : vec31;
+
+ // The axis order here may differ from the order during movement in versions below 1.21.9
+ for (Direction.Axis axis : Direction.axisStepOrder(stepOrderVec)) {
double d = vec31.get(axis);
if (d != 0.0) {
Vec3 vec32 = vec3.relative(axis.getPositive(), d);
- i -= this.checkInsideBlocks(vec3, vec32, stepBasedCollector, set, i);
+ final int stepsTaken = this.checkInsideBlocks(vec3, vec32, stepBasedCollector, set, i);
+ if (mechanicsTarget.atLeast(me.samsuik.sakura.mechanics.MechanicVersion.v1_21_9)) {
+ i -= stepsTaken;
+ }
vec3 = vec32;
}
}
- } else {
+ } else if (mechanicsTarget.atLeast(me.samsuik.sakura.mechanics.MechanicVersion.v1_21_2)) {
i -= this.checkInsideBlocks(movement.from(), movement.to(), stepBasedCollector, set, 16);
}
- if (i <= 0) {
+ if (i <= 0 || mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_21_2)) {
+ // Sakura end - configure server mechanics
this.checkInsideBlocks(movement.to(), movement.to(), stepBasedCollector, set, 1);
}
}
@@ -1869,8 +1909,20 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
}
private int checkInsideBlocks(Vec3 from, Vec3 to, InsideBlockEffectApplier.StepBasedCollector stepBasedCollector, LongSet visited, int maxSteps) {
- AABB aabb = this.makeBoundingBox(to).deflate(1.0E-5F);
- boolean flag = from.distanceToSqr(to) > Mth.square(0.9999900000002526);
+ // Sakura start - configure server mechanics
+ final me.samsuik.sakura.mechanics.MinecraftMechanicsTarget mechanicsTarget = this.mechanicsTarget;
+ final double margin;
+ if (mechanicsTarget.atLeast(me.samsuik.sakura.mechanics.MechanicVersion.v1_21_2)) {
+ margin = 1.0e-5f;
+ } else if (mechanicsTarget.atLeast(me.samsuik.sakura.mechanics.MechanicVersion.v1_19_3)) {
+ margin = 1.0e-7f;
+ } else {
+ margin = 0.001;
+ }
+ final AABB aabb = this.makeBoundingBox(to).deflate(margin);
+ boolean flag = mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_21_10)
+ || from.distanceToSqr(to) > Mth.square(0.9999900000002526);
+ // Sakura end - configure server mechanics
boolean flag1 = this.level instanceof ServerLevel serverLevel
&& serverLevel.getServer().debugSubscribers().hasAnySubscriberFor(DebugSubscriptions.ENTITY_BLOCK_INTERSECTIONS);
AtomicInteger atomicInteger = new AtomicInteger();
@@ -1878,6 +1930,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name
from,
to,
aabb,
+ mechanicsTarget, // Sakura - configure server mechanics
(pos, index) -> {
if (!this.isAlive()) {
return false;
diff --git a/net/minecraft/world/entity/item/FallingBlockEntity.java b/net/minecraft/world/entity/item/FallingBlockEntity.java
index 0344ba2a6d063a4ee5d6f9a8985ae8ca8c5816ce..02dc6c5965354047fc05ad3d3293c7f6277f50cd 100644
--- a/net/minecraft/world/entity/item/FallingBlockEntity.java
+++ b/net/minecraft/world/entity/item/FallingBlockEntity.java
@@ -130,6 +130,25 @@ public class FallingBlockEntity extends Entity implements me.samsuik.sakura.enti
return this.sakura$collide(movement);
}
// Sakura end - optimise cannon entity movement
+ // Sakura start - configure server mechanics
+ @Override
+ public final double distanceToSqr(final Vec3 vector) {
+ if (!this.mechanicsTarget.isLegacy()) {
+ return super.distanceToSqr(vector);
+ }
+ final double x = this.getX() - vector.x;
+ final double y = this.getEyeY() - vector.y;
+ final double z = this.getZ() - vector.z;
+ return x * x + y * y + z * z;
+ }
+
+ private BlockPos patchedBlockPosition() {
+ // Mitigates MC-261789 - falling blocks breaking when landing on a block below y 0
+ // This fix allows some tech that uses "indirect clipping" to still function.
+ // L stackers and midairs may still encounter issues if they shoot too high.
+ return BlockPos.containing(this.getX(), this.getY() + 1.0e-12, this.getZ());
+ }
+ // Sakura end - configure server mechanics
public FallingBlockEntity(EntityType<? extends FallingBlockEntity> entityType, Level level) {
super(entityType, level);
@@ -150,6 +169,10 @@ public class FallingBlockEntity extends Entity implements me.samsuik.sakura.enti
this.yo = y;
this.zo = z;
this.setStartPos(this.blockPosition());
+ // Sakura start - configure server mechanics
+ this.mechanicsTarget = level.localConfig().at(this.blockPosition()).mechanicsTarget;
+ this.eyeHeight = this.mechanicsTarget.isLegacy() ? 0.49f : this.eyeHeight;
+ // Sakura end - configure server mechanics
}
// Sakura start - falling block height parity api
@@ -181,7 +204,11 @@ public class FallingBlockEntity extends Entity implements me.samsuik.sakura.enti
blockState.hasProperty(BlockStateProperties.WATERLOGGED) ? blockState.setValue(BlockStateProperties.WATERLOGGED, false) : blockState
);
if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(fallingBlockEntity, pos, blockState.getFluidState().createLegacyBlock())) return fallingBlockEntity; // CraftBukkit
- level.setBlock(pos, blockState.getFluidState().createLegacyBlock(), 3);
+ // Sakura start - configure server mechanics
+ if (fallingBlockEntity.mechanicsTarget.atLeast(me.samsuik.sakura.mechanics.MechanicVersion.v1_18_2)) {
+ level.setBlock(pos, blockState.getFluidState().createLegacyBlock(), 3);
+ }
+ // Sakura end - configure server mechanics
level.addFreshEntity(fallingBlockEntity);
return fallingBlockEntity;
}
@@ -225,7 +252,7 @@ public class FallingBlockEntity extends Entity implements me.samsuik.sakura.enti
@Override
protected double getDefaultGravity() {
- return 0.04;
+ return this.mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_14) ? 0.04f : 0.04; // Sakura - configure server mechanics
}
@Override
@@ -234,6 +261,12 @@ public class FallingBlockEntity extends Entity implements me.samsuik.sakura.enti
this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
} else {
Block block = this.blockState.getBlock();
+ // Sakura start - configure server mechanics
+ final me.samsuik.sakura.mechanics.MinecraftMechanicsTarget mechanicsTarget = this.mechanicsTarget;
+ if (this.time == 0 && mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_18_2)) {
+ me.samsuik.sakura.mechanics.FallingBlockBehaviour.removeBlockOnFall(this, block);
+ }
+ // Sakura end - configure server mechanics
this.time++;
this.applyGravity();
this.move(MoverType.SELF, this.getDeltaMovement());
@@ -248,8 +281,15 @@ public class FallingBlockEntity extends Entity implements me.samsuik.sakura.enti
}
// Paper end - Configurable falling blocks height nerf
this.handlePortal();
+ // Sakura start - configure server mechanics
+ if (mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_12)) {
+ this.setDeltaMovement(this.getDeltaMovement().scale(0.98F));
+ }
if (this.level() instanceof ServerLevel serverLevel && (this.isAlive() || this.forceTickAfterTeleportToDuplicate)) {
- BlockPos blockPos = this.blockPosition();
+ BlockPos blockPos = mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_17)
+ ? this.patchedBlockPosition() // Mitigate MC-261789
+ : this.blockPosition();
+ // Sakura end - configure server mechanics
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();
@@ -276,8 +316,13 @@ 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 server mechanics
+ final double friction = mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_14)
+ ? 0.7f
+ : 0.7;
+ this.setDeltaMovement(this.getDeltaMovement().multiply(friction, -0.5, friction));
+ if (!blockState.is(Blocks.MOVING_PISTON) && (flag1 || me.samsuik.sakura.mechanics.FallingBlockBehaviour.isAbleToStackOnBlock(this, mechanicsTarget))) {
+ // Sakura end - configure server mechanics
if (!this.cancelDrop) {
boolean canBeReplaced = blockState.canBeReplaced(
new DirectionalPlaceContext(this.level(), blockPos, Direction.DOWN, ItemStack.EMPTY, Direction.UP)
@@ -349,7 +394,14 @@ public class FallingBlockEntity extends Entity implements me.samsuik.sakura.enti
}
}
- this.setDeltaMovement(this.getDeltaMovement().scale(0.98));
+ // Sakura start - configure server mechanics
+ if (mechanicsTarget.atLeast(me.samsuik.sakura.mechanics.MechanicVersion.v1_12)) {
+ final double drag = mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_14)
+ ? 0.98f
+ : 0.98;
+ this.setDeltaMovement(this.getDeltaMovement().scale(drag));
+ }
+ // Sakura end - configure server mechanics
}
}
diff --git a/net/minecraft/world/entity/item/PrimedTnt.java b/net/minecraft/world/entity/item/PrimedTnt.java
index 05003798585d98406cd1affb89403b9f955bacdc..cb2241e99f4b3bee099ff1eea566beb9bd80c57d 100644
--- a/net/minecraft/world/entity/item/PrimedTnt.java
+++ b/net/minecraft/world/entity/item/PrimedTnt.java
@@ -88,6 +88,23 @@ public class PrimedTnt extends Entity implements TraceableEntity, me.samsuik.sak
return this.sakura$collide(movement);
}
// Sakura end - optimise cannon entity movement
+ // Sakura start - configure server mechanics
+ @Override
+ public final double getEyeY() {
+ return this.mechanicsTarget.isLegacy() ? super.getEyeY() : this.getY();
+ }
+
+ @Override
+ public final double distanceToSqr(final net.minecraft.world.phys.Vec3 vector) {
+ if (!this.mechanicsTarget.isLegacy()) {
+ return super.distanceToSqr(vector);
+ }
+ final double x = this.getX() - vector.x;
+ final double y = this.getEyeY() - vector.y;
+ final double z = this.getZ() - vector.z;
+ return x * x + y * y + z * z;
+ }
+ // Sakura end - configure server mechanics
public PrimedTnt(EntityType<? extends PrimedTnt> entityType, Level level) {
super(entityType, level);
@@ -113,6 +130,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 server mechanics
+ this.mechanicsTarget = level.localConfig().at(this.blockPosition()).mechanicsTarget;
+ this.eyeHeight = this.mechanicsTarget.isLegacy() ? 0.49f : this.eyeHeight;
+ if (this.mechanicsTarget.isLegacy()) {
+ this.setDeltaMovement(this.getDeltaMovement().multiply(0.0, 1.0, 0.0));
+ }
+ // Sakura end - configure server mechanics
}
// Sakura start - optimise tnt fluid state
@@ -148,7 +172,7 @@ public class PrimedTnt extends Entity implements TraceableEntity, me.samsuik.sak
@Override
protected double getDefaultGravity() {
- return 0.04;
+ return this.mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_14) ? 0.04f : 0.04; // Sakura - configure server mechanics
}
@Override
@@ -164,14 +188,23 @@ 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 server mechanics
+ final me.samsuik.sakura.mechanics.MinecraftMechanicsTarget mechanicsTarget = this.mechanicsTarget;
+ final double drag = mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_14)
+ ? 0.98f
+ : 0.98;
+ this.setDeltaMovement(this.getDeltaMovement().scale(drag));
if (this.onGround()) {
- this.setDeltaMovement(this.getDeltaMovement().multiply(0.7, -0.5, 0.7));
+ final double friction = mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_14)
+ ? 0.7f
+ : 0.7;
+ this.setDeltaMovement(this.getDeltaMovement().multiply(friction, -0.5, friction));
+ // Sakura end - configure server mechanics
}
int i = this.getFuse() - 1;
this.setFuse(i);
- if (i <= 0) {
+ if (mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_9) ? (i < 0) : (i <= 0)) { // Sakura - configure server mechanics
// 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.tryToRespawnEntity(); // Sakura - merge cannon entities
@@ -210,13 +243,19 @@ public class PrimedTnt extends Entity implements TraceableEntity, me.samsuik.sak
return;
}
// CraftBukkit end
+ // Sakura start - configure server mechanics
+ // Undocumented on the minecraft wiki but the explosion position did change in 1.10
+ final double explosionY = this.mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_10)
+ ? this.getY() + (double) 0.49f
+ : this.getY(0.0625D);
+ // Sakura end - configure server mechanics
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 server mechanics
this.getZ(),
event.getRadius(), // CraftBukkit
event.getFire(), // CraftBukkit
@@ -307,7 +346,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.mechanicsTarget.isLegacy() && super.isPushedByFluid(); // Sakura - configure server mechanics // Sakura - configure cannon mechanics
}
// Paper end - Option to prevent TNT from moving in water
}
diff --git a/net/minecraft/world/level/BlockGetter.java b/net/minecraft/world/level/BlockGetter.java
index 41c036324499d4e408030d1e19f78468b6b3d8a6..ba2e7efe147b26bea5d73eac1f4b2fe6ee4bd5c2 100644
--- a/net/minecraft/world/level/BlockGetter.java
+++ b/net/minecraft/world/level/BlockGetter.java
@@ -8,6 +8,8 @@ import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
import javax.annotation.Nullable;
+
+import me.samsuik.sakura.mechanics.MechanicVersion;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
@@ -212,8 +214,23 @@ public interface BlockGetter extends LevelHeightAccessor {
}
static boolean forEachBlockIntersectedBetween(Vec3 from, Vec3 to, AABB boundingBox, BlockGetter.BlockStepVisitor visitor) {
+ // Sakura start - configure server mechanics
+ return forEachBlockIntersectedBetween(from, to, boundingBox, null, visitor);
+ }
+
+ static boolean forEachBlockIntersectedBetween(
+ final Vec3 from,
+ final Vec3 to,
+ final AABB boundingBox,
+ final @Nullable me.samsuik.sakura.mechanics.MinecraftMechanicsTarget mechanicsTarget,
+ final BlockGetter.BlockStepVisitor visitor
+ ) {
Vec3 vec3 = to.subtract(from);
- if (vec3.lengthSqr() < Mth.square(1.0E-5F)) {
+ final double margin = mechanicsTarget != null && mechanicsTarget.atLeast(MechanicVersion.v1_21_9)
+ ? 1.0E-5F
+ : 0.99999F;
+ if (vec3.lengthSqr() < Mth.square(margin) || mechanicsTarget != null && mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_21_2)) {
+ // Sakura end - configure server mechanics
for (BlockPos blockPos : BlockPos.betweenClosed(boundingBox)) {
if (!visitor.visit(blockPos, 0)) {
return false;
diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java
index b13aae809e974b42bc1b17f4f4455999adca6f5f..0a279388e965a8d059189a8dfdbec3ff951af876 100644
--- a/net/minecraft/world/level/ServerExplosion.java
+++ b/net/minecraft/world/level/ServerExplosion.java
@@ -378,6 +378,17 @@ public class ServerExplosion implements Explosion {
return this.damageCalculator.getBlockExplosionResistance(this, this.level, pos, blockState, fluidState);
}
// Sakura end - explosion durable blocks
+ // Sakura start - configure server mechanics
+ protected final me.samsuik.sakura.mechanics.MinecraftMechanicsTarget mechanicsTarget;
+
+ private float sakura$getSeenPercent(final Vec3 explosionPos, final Entity entity) {
+ if (this.mechanicsTarget.atLeast(me.samsuik.sakura.mechanics.MechanicVersion.v1_16)) {
+ return this.getSeenFraction(explosionPos, entity, this.directMappedBlockCache, this.mutablePos); // Paper - collision optimisations
+ } else {
+ return getSeenPercent(explosionPos, entity);
+ }
+ }
+ // Sakura end - configure server mechanics
public ServerExplosion(
ServerLevel level,
@@ -402,6 +413,7 @@ public class ServerExplosion implements Explosion {
this.yield = Double.isFinite(this.yield) ? this.yield : 0; // Paper - Don't allow infinite default yields
// Paper end - add yield
this.consistentExplosionRadius = level.localConfig().at(this.center).consistentExplosionRadius; // Sakura - consistent explosion radius
+ this.mechanicsTarget = source != null ? source.mechanicsTarget() : level.localConfig().at(this.center).mechanicsTarget; // Sakura - configure server mechanics
}
private ExplosionDamageCalculator makeDamageCalculator(@Nullable Entity entity) {
@@ -431,8 +443,15 @@ 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 server mechanics
+ } else if (entity.mechanicsTarget().before(me.samsuik.sakura.mechanics.MechanicVersion.v1_14)) {
+ hitResult = me.samsuik.sakura.mechanics.LegacyExplosionBlockClipping.clip(entity.level(), vec3, explosionVector);
} else {
- hitResult = entity.level().clip(new ClipContext(vec3, explosionVector, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, entity)).getType();
+ final ClipContext.Block blockContext = entity.mechanicsTarget().atLeast(me.samsuik.sakura.mechanics.MechanicVersion.v1_16)
+ ? ClipContext.Block.COLLIDER
+ : ClipContext.Block.OUTLINE;
+ hitResult = entity.level().clip(new ClipContext(vec3, explosionVector, blockContext, ClipContext.Fluid.NONE, entity)).getType();
+ // Sakura end - configure server mechanics
}
if (hitResult == HitResult.Type.MISS) {
// Sakura end - replace density cache
@@ -530,6 +549,15 @@ public class ServerExplosion implements Explosion {
}
if (cachedBlock.outOfWorld) {
+ // Sakura start - configure server mechanics
+ if (this.mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_17)) {
+ power -= 0.22500001F;
+ currX += incX;
+ currY += incY;
+ currZ += incZ;
+ continue;
+ }
+ // Sakura end - configure server mechanics
break;
}
final BlockState iblockdata = cachedBlock.blockState;
@@ -594,7 +622,27 @@ public class ServerExplosion implements Explosion {
double d = Math.sqrt(entity.distanceToSqr(this.center)) / f;
if (!(d > 1.0)) {
Vec3 vec3 = entity instanceof PrimedTnt ? entity.position() : entity.getEyePosition();
- Vec3 vec31 = vec3.subtract(this.center).normalize();
+ // Sakura start - configure server mechanics
+ final double dirX = vec3.x - this.center.x;
+ final double dirY = vec3.y - this.center.y;
+ final double dirZ = vec3.z - this.center.z;
+ double magnitude = Math.sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ);
+
+ if (this.mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_17)) {
+ d = (float) d;
+ magnitude = (float) magnitude;
+ }
+
+ final Vec3 vec31;
+ if (magnitude < 1.0e-5f && this.mechanicsTarget.atLeast(me.samsuik.sakura.mechanics.MechanicVersion.v1_21_9)) {
+ vec31 = Vec3.ZERO;
+ } else {
+ final double normalisedX = dirX / magnitude;
+ final double normalisedY = dirY / magnitude;
+ final double normalisedZ = dirZ / magnitude;
+ vec31 = new Vec3(normalisedX, normalisedY, normalisedZ);
+ }
+ // Sakura end - configure server mechanics
boolean shouldDamageEntity = this.damageCalculator.shouldDamageEntity(this, entity);
float knockbackMultiplier = this.damageCalculator.getKnockbackMultiplier(entity);
float f1 = !shouldDamageEntity && knockbackMultiplier == 0.0F ? 0.0F : this.getBlockDensity(this.center, entity); // Paper - Optimize explosions
@@ -868,7 +916,7 @@ public class ServerExplosion implements Explosion {
// Sakura start - replace density cache
float blockDensity = this.level.densityCache.getBlockDensity(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 server mechanics
this.level.densityCache.putDensity(vec3d, entity, blockDensity);
// Sakura end - replace density cache
}
diff --git a/net/minecraft/world/level/block/FallingBlock.java b/net/minecraft/world/level/block/FallingBlock.java
index 4fa238d1cd6b19f16c0d0a8a9a913e9e42debbed..96a02601636cdf7cf6e360fc933e5764fbb7eab8 100644
--- a/net/minecraft/world/level/block/FallingBlock.java
+++ b/net/minecraft/world/level/block/FallingBlock.java
@@ -45,6 +45,22 @@ public abstract class FallingBlock extends Block implements Fallable {
return super.updateShape(state, level, scheduledTickAccess, pos, direction, neighborPos, neighborState, random);
}
+ // Sakura start - configure server mechanics
+ @Override
+ public void neighborChanged(
+ final BlockState state,
+ final Level level,
+ final BlockPos pos,
+ final Block sourceBlock,
+ final net.minecraft.world.level.redstone.Orientation wireOrientation,
+ final boolean notify
+ ) {
+ if (level.localConfig().at(pos).mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_18_2)) {
+ level.scheduleTick(pos, this, this.getDelayAfterPlace());
+ }
+ }
+ // Sakura end - configure server mechanics
+
@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 0c6ae65fc58d63a0b80f3bc1ffa0c9a1bb33de83..f291dc3b3f3e3b8da221f42580ed26c4b8f569a7 100644
--- a/net/minecraft/world/level/block/FenceGateBlock.java
+++ b/net/minecraft/world/level/block/FenceGateBlock.java
@@ -210,8 +210,15 @@ public class FenceGateBlock extends HorizontalDirectionalBlock {
hasNeighborSignal = eventRedstone.getNewCurrent() > 0;
}
// CraftBukkit end
- if (state.getValue(POWERED) != hasNeighborSignal) {
- level.setBlock(pos, state.setValue(POWERED, hasNeighborSignal).setValue(OPEN, hasNeighborSignal), 2);
+ // Sakura start - configure server mechanics
+ final boolean pre1_10_0 = level.localConfig().at(pos).mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_10);
+ final boolean powered = state.getValue(POWERED);
+ if (pre1_10_0 ? (hasNeighborSignal || neighborBlock.defaultBlockState().isSignalSource()) : powered != hasNeighborSignal) {
+ final boolean openGate = pre1_10_0 && (hasNeighborSignal == powered || state.getValue(OPEN) != powered)
+ ? state.getValue(OPEN)
+ : hasNeighborSignal;
+ level.setBlock(pos, state.setValue(POWERED, hasNeighborSignal).setValue(OPEN, openGate), 2);
+ // Sakura end - configure server mechanics
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 009f6b118e227b8a037a7b39b7d4a319518e5765..0a9009dc26edb0c6904cdf484463c5c33e5099de 100644
--- a/net/minecraft/world/level/block/HoneyBlock.java
+++ b/net/minecraft/world/level/block/HoneyBlock.java
@@ -71,11 +71,19 @@ public class HoneyBlock extends HalfTransparentBlock {
super.entityInside(state, level, pos, entity, effectApplier, flag);
}
- private static double getOldDeltaY(double deltaY) {
+ // Sakura start - configure server mechanics
+ private static double getOldDeltaY(final double deltaY, final Entity entity) {
+ if (entity.mechanicsTarget().before(me.samsuik.sakura.mechanics.MechanicVersion.v1_21_2)) {
+ return deltaY;
+ }
return deltaY / 0.98F + 0.08;
}
- private static double getNewDeltaY(double deltaY) {
+ private static double getNewDeltaY(final double deltaY, final Entity entity) {
+ if (entity.mechanicsTarget().before(me.samsuik.sakura.mechanics.MechanicVersion.v1_21_2)) {
+ return deltaY;
+ }
+ // Sakura end - configure server mechanics
return (deltaY - 0.08) * 0.98F;
}
@@ -84,7 +92,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 server mechanics
return false;
} else {
double abs = Math.abs(pos.getX() + 0.5 - entity.getX());
@@ -102,11 +110,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 server mechanics
+ 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 server mechanics
}
entity.resetFallDistance();
diff --git a/net/minecraft/world/level/block/LadderBlock.java b/net/minecraft/world/level/block/LadderBlock.java
index f9c305de60a323b450a26c9d7de50a824492cf5a..c4987294763a82f5f065f726d48fa61dda097f6a 100644
--- a/net/minecraft/world/level/block/LadderBlock.java
+++ b/net/minecraft/world/level/block/LadderBlock.java
@@ -33,6 +33,15 @@ public class LadderBlock extends Block implements SimpleWaterloggedBlock {
return CODEC;
}
+ // Sakura start - configure server mechanics
+ public static final Map<Direction, VoxelShape> LEGACY_SHAPES = Shapes.rotateHorizontal(Block.boxZ(16.0, 14.0, 16.0));
+
+ @Override
+ public boolean hasDynamicShape() {
+ return true;
+ }
+ // Sakura end - configure server mechanics
+
protected LadderBlock(BlockBehaviour.Properties properties) {
super(properties);
this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(WATERLOGGED, false));
@@ -40,6 +49,11 @@ public class LadderBlock extends Block implements SimpleWaterloggedBlock {
@Override
protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
+ // Sakura start - configure server mechanics
+ if (level instanceof net.minecraft.world.level.Level gameLevel && gameLevel.localConfig().at(pos).mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_9)) {
+ return LEGACY_SHAPES.get(state.getValue(FACING));
+ }
+ // Sakura end - configure server mechanics
return SHAPES.get(state.getValue(FACING));
}
diff --git a/net/minecraft/world/level/block/LiquidBlock.java b/net/minecraft/world/level/block/LiquidBlock.java
index 0b1ec05fcd799536c8d7393bb42dc4b2f46ca48b..5968a30d21367b882501bbb70029b9e0069cca9f 100644
--- a/net/minecraft/world/level/block/LiquidBlock.java
+++ b/net/minecraft/world/level/block/LiquidBlock.java
@@ -199,7 +199,14 @@ public class LiquidBlock extends Block implements BucketPickup {
}
// Sakura end - configure fluid ticking outside the world border
if (level.getFluidState(blockPos).is(FluidTags.WATER)) {
- Block block = level.getFluidState(pos).isSource() ? Blocks.OBSIDIAN : Blocks.COBBLESTONE;
+ // Sakura start - configure server mechanics
+ final FluidState fluidState = state.getFluidState();
+ final Block block = fluidState.isSource() ? Blocks.OBSIDIAN : Blocks.COBBLESTONE;
+ final me.samsuik.sakura.mechanics.MinecraftMechanicsTarget mechanicsTarget = level.localConfig().at(pos).mechanicsTarget;
+ if (block == Blocks.COBBLESTONE && !me.samsuik.sakura.mechanics.LegacyBlockFormation.canLiquidFormBlock(level, pos, fluidState, mechanicsTarget)) {
+ return true;
+ }
+ // Sakura end - configure server mechanics
// CraftBukkit start
if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, block.defaultBlockState(), 3)) {
this.fizz(level, pos);
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
index 4c6c68eedba2d5acdde6cf760e53b8e81f75f001..ce27dfb14974d452f50c191a3eeec65d3deff6a3 100644
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
@@ -322,6 +322,10 @@ public class RedStoneWireBlock extends Block {
private void updatePowerStrength(Level level, BlockPos pos, BlockState state, @Nullable Orientation orientation, boolean updateShape) {
if (useExperimentalEvaluator(level)) {
new ExperimentalRedstoneWireEvaluator(this).updatePowerStrength(level, pos, state, orientation, updateShape);
+ // Sakura start - configure server mechanics
+ } else if (level.localConfig().at(pos).mechanicsTarget.isLegacy()) {
+ new me.samsuik.sakura.redstone.PandaRedstoneWireEvaluator(this).updatePowerStrength(level, pos, state, orientation, updateShape);
+ // Sakura end - configure server mechanics
} else {
this.evaluator.updatePowerStrength(level, pos, state, orientation, updateShape);
}
@@ -542,7 +546,7 @@ public class RedStoneWireBlock extends Block {
@Override
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {
- if (!player.getAbilities().mayBuild) {
+ if (!player.getAbilities().mayBuild || isCross(state) && level.localConfig().at(pos).mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_16)) { // Sakura - configure server mechanics
return InteractionResult.PASS;
} else {
if (isCross(state) || isDot(state)) {
diff --git a/net/minecraft/world/level/block/WaterlilyBlock.java b/net/minecraft/world/level/block/WaterlilyBlock.java
index cbb81c8bf5f689f276e74548ce324a8c35357e3a..bdd0b1bcb97d9505d49994737f4c847e3423b1f9 100644
--- a/net/minecraft/world/level/block/WaterlilyBlock.java
+++ b/net/minecraft/world/level/block/WaterlilyBlock.java
@@ -24,6 +24,15 @@ public class WaterlilyBlock extends VegetationBlock {
return CODEC;
}
+ // Sakura start - configure server mechanics
+ protected static final VoxelShape LEGACY_SHAPE = Block.column(16.0, 0.0, 0.25);
+
+ @Override
+ public boolean hasDynamicShape() {
+ return true;
+ }
+ // Sakura end - configure server mechanics
+
protected WaterlilyBlock(BlockBehaviour.Properties properties) {
super(properties);
}
@@ -44,6 +53,11 @@ public class WaterlilyBlock extends VegetationBlock {
@Override
protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
+ // Sakura start - configure server mechanics
+ if (level instanceof net.minecraft.world.level.Level gameLevel && gameLevel.localConfig().at(pos).mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_9)) {
+ return LEGACY_SHAPE;
+ }
+ // Sakura end - configure server mechanics
return SHAPE;
}
diff --git a/net/minecraft/world/level/block/piston/MovingPistonBlock.java b/net/minecraft/world/level/block/piston/MovingPistonBlock.java
index 16f14dffcbca21e0c6d369d557ab6c036523b8bd..f459cee5a4d0eafccc525c246964acc9272429f5 100644
--- a/net/minecraft/world/level/block/piston/MovingPistonBlock.java
+++ b/net/minecraft/world/level/block/piston/MovingPistonBlock.java
@@ -100,6 +100,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 server mechanics
+ if (blockEntity != null && level instanceof Level gameLevel && gameLevel.localConfig().at(pos).mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_9)) {
+ 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 server mechanics
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 384eb75c644489fecd78fff904612ebe1e3e1706..87bc3222c33a00a46c5fdff792ca11f8248a61cd 100644
--- a/net/minecraft/world/level/block/piston/PistonBaseBlock.java
+++ b/net/minecraft/world/level/block/piston/PistonBaseBlock.java
@@ -122,6 +122,11 @@ public class PistonBaseBlock extends DirectionalBlock {
i = 2;
}
+ // Sakura start - configure server mechanics
+ if (level.localConfig().at(pos).mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_9)) {
+ level.setBlock(pos, state.setValue(PistonBaseBlock.EXTENDED, false), Block.UPDATE_CLIENTS | Block.UPDATE_KNOWN_SHAPE);
+ }
+ // Sakura end - configure server mechanics
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 72e39ceeca8d684569c4250263b41034362f8abd..0f723f8eb814931f949b1a467b79266e9a6e7f9e 100644
--- a/net/minecraft/world/level/block/piston/PistonHeadBlock.java
+++ b/net/minecraft/world/level/block/piston/PistonHeadBlock.java
@@ -3,6 +3,8 @@ package net.minecraft.world.level.block.piston;
import com.mojang.serialization.MapCodec;
import java.util.Map;
import javax.annotation.Nullable;
+
+import me.samsuik.sakura.mechanics.MechanicVersion;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
@@ -105,6 +107,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 server mechanics
+ if (level instanceof Level gameLevel && gameLevel.localConfig().at(pos).mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_9)) {
+ return this.isFittingBase(state, blockState);
+ }
+ // Sakura end - configure server mechanics
return this.isFittingBase(state, blockState) || blockState.is(Blocks.MOVING_PISTON) && blockState.getValue(FACING) == state.getValue(FACING);
}
@@ -116,6 +123,10 @@ public class PistonHeadBlock extends DirectionalBlock {
neighborBlock,
ExperimentalRedstoneUtils.withFront(orientation, state.getValue(FACING).getOpposite())
);
+ // Sakura start - configure server mechanics
+ } else if (level.localConfig().at(pos).mechanicsTarget.before(MechanicVersion.v1_9)) {
+ level.setBlock(pos, Blocks.AIR.defaultBlockState(), 19);
+ // Sakura end - configure server mechanics
}
}
diff --git a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
index 4c4dbd7ade2b8836064242bb43eeb871cac023ce..7816e0ab95634d93ced2dea47aa58edc087f2caa 100644
--- a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
+++ b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
@@ -64,6 +64,165 @@ public class PistonMovingBlockEntity extends BlockEntity {
this.isSourcePiston = isSourcePiston;
}
+ // Sakura start - configure server mechanics
+ @org.jspecify.annotations.Nullable
+ private AABB getBoundsFromProgress(
+ final BlockGetter level,
+ final BlockPos pos,
+ final BlockState state,
+ final float progress,
+ final Direction dir,
+ final boolean absolute
+ ) {
+ if (state.is(Blocks.MOVING_PISTON) || state.isAir()) {
+ return null;
+ }
+
+ VoxelShape shape = this.movedState.getCollisionShape(level, pos);
+ if (shape.isEmpty()) {
+ return null;
+ }
+
+ if (absolute) {
+ shape = shape.move(pos.getX(), pos.getY(), pos.getZ());
+ }
+
+ final 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);
+ }
+
+ private AABB fixZeroWidthBB(AABB bb, final 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
+ final double expandX = bb.getXsize() == 0.0 ? 1.0e-5 * dir.getStepX() : 0.0;
+ final double expandY = bb.getYsize() == 0.0 ? 1.0e-5 * dir.getStepY() : 0.0;
+ final double expandZ = bb.getZsize() == 0.0 ? 1.0e-5 * dir.getStepZ() : 0.0;
+
+ if (expandX != 0 || expandY != 0 || expandZ != 0) {
+ bb = bb.expandTowards(expandX, expandY, expandZ);
+ }
+
+ return bb;
+ }
+
+ public final VoxelShape getCollisionShapeFromProgress(final BlockGetter level, final BlockPos pos) {
+ float progress = this.getProgress(0.0f);
+ if (this.extending) {
+ progress = 1.0F - progress;
+ }
+
+ final AABB bb = this.getBoundsFromProgress(level, pos, this.movedState, progress, this.direction, false);
+ return bb == null ? Shapes.empty() : Shapes.create(bb);
+ }
+
+ private void moveEntities(final Level level, final float relativeProgress) {
+ float remaining = this.progress;
+ if (this.extending) {
+ remaining = 1.0F - remaining;
+ } else {
+ --remaining;
+ }
+
+ final Direction direction = this.direction;
+ final AABB bb = this.getBoundsFromProgress(level, this.worldPosition, this.movedState, remaining, direction, true);
+ if (bb == null || bb.getSize() == 0.0) {
+ return;
+ }
+
+ for (final Entity entity : level.getEntities(null, bb)) {
+ if (this.movedState.is(Blocks.SLIME_BLOCK) && this.extending) {
+ final Vec3 movement = entity.getDeltaMovement();
+ double moveX = movement.x;
+ double moveY = movement.y;
+ double moveZ = movement.z;
+
+ switch (direction.getAxis()) {
+ case X -> moveX = direction.getStepX();
+ case Y -> moveY = direction.getStepY();
+ case Z -> moveZ = direction.getStepZ();
+ }
+
+ entity.setDeltaMovement(moveX, moveY, moveZ);
+ } else {
+ final Vec3 pistonMovement = new Vec3(
+ relativeProgress * (float) direction.getStepX(),
+ relativeProgress * (float) direction.getStepY(),
+ relativeProgress * (float) direction.getStepZ()
+ );
+ entity.move(MoverType.PISTON, pistonMovement);
+ entity.applyEffectsFromBlocks(entity.position(), entity.position());
+ }
+ }
+ }
+
+ private static void moveEntityByPistonInDirection(final Direction direction, final Entity entity, final AABB movingBB) {
+ final AABB entityBB = entity.getBoundingBox();
+ double moveX = 0.0;
+ double moveY = 0.0;
+ double moveZ = 0.0;
+
+ switch (direction.getAxis()) {
+ case X -> {
+ if (direction.getAxisDirection() == Direction.AxisDirection.POSITIVE) {
+ moveX = movingBB.maxX - entityBB.minX;
+ } else {
+ moveX = entityBB.maxX - movingBB.minX;
+ }
+ moveX += 0.01D;
+ }
+ case Y -> {
+ if (direction.getAxisDirection() == Direction.AxisDirection.POSITIVE) {
+ moveY = movingBB.maxY - entityBB.minY;
+ } else {
+ moveY = entityBB.maxY - movingBB.minY;
+ }
+ moveY += 0.01D;
+ }
+ case Z -> {
+ if (direction.getAxisDirection() == Direction.AxisDirection.POSITIVE) {
+ moveZ = movingBB.maxZ - entityBB.minZ;
+ } else {
+ moveZ = entityBB.maxZ - movingBB.minZ;
+ }
+ moveZ += 0.01D;
+ }
+ }
+
+ final Vec3 pistonMovement = new Vec3(
+ moveX * direction.getStepX(),
+ moveY * direction.getStepY(),
+ moveZ * direction.getStepZ()
+ );
+ entity.move(MoverType.PISTON, pistonMovement);
+ entity.applyEffectsFromBlocks(entity.position(), entity.position());
+ }
+ // Sakura end - configure server mechanics
+
@Override
public CompoundTag getUpdateTag(HolderLookup.Provider registries) {
return this.saveCustomOnly(registries);
@@ -168,6 +327,12 @@ public class PistonMovingBlockEntity extends BlockEntity {
double d4 = 0.0;
+ // Sakura start - configure server mechanics
+ if (entity.mechanicsTarget().before(me.samsuik.sakura.mechanics.MechanicVersion.v1_11)) {
+ moveEntityByPistonInDirection(movementDirection, entity, aabb);
+ return;
+ }
+ // Sakura end - configure server mechanics
for (AABB aabb1 : list) {
AABB movementArea = PistonMath.getMovementArea(moveByPositionAndProgress(pos, aabb1, piston), movementDirection, d);
AABB boundingBox = entity.getBoundingBox();
@@ -195,6 +360,11 @@ public class PistonMovingBlockEntity extends BlockEntity {
NOCLIP.set(noClipDirection);
Vec3 vec3 = entity.position();
entity.move(MoverType.PISTON, new Vec3(progress * direction.getStepX(), progress * direction.getStepY(), progress * direction.getStepZ()));
+ // Sakura start - configure server mechanics
+ if (entity.mechanicsTarget().before(me.samsuik.sakura.mechanics.MechanicVersion.v1_21_5)) {
+ vec3 = entity.oldPosition();
+ }
+ // Sakura end - configure server mechanics
entity.applyEffectsFromBlocks(vec3, entity.position());
entity.removeLatestMovementRecording();
NOCLIP.set(null);
@@ -307,12 +477,21 @@ public class PistonMovingBlockEntity extends BlockEntity {
}
public static void tick(Level level, BlockPos pos, BlockState state, PistonMovingBlockEntity blockEntity) {
+ final me.samsuik.sakura.mechanics.MinecraftMechanicsTarget mechanicsTarget = level.localConfig().at(pos).mechanicsTarget; // Sakura - configure server mechanics
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 server mechanics
+ if (mechanicsTarget.between(me.samsuik.sakura.mechanics.MechanicVersion.v1_9, me.samsuik.sakura.mechanics.MechanicVersion.v1_10)) {
+ moveCollidedEntities(level, pos, 1.0f, blockEntity);
+ moveStuckEntities(level, pos, 1.0f, blockEntity);
+ } else if (mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_9)) {
+ blockEntity.moveEntities(level, 0.25f);
+ }
+ // Sakura end - configure server mechanics
level.removeBlockEntity(pos);
blockEntity.setRemoved();
if (level.getBlockState(pos).is(Blocks.MOVING_PISTON)) {
@@ -334,12 +513,22 @@ public class PistonMovingBlockEntity extends BlockEntity {
}
} else {
float f = blockEntity.progress + 0.5F;
- moveCollidedEntities(level, pos, f, blockEntity);
- moveStuckEntities(level, pos, f, blockEntity);
+ // Sakura start - configure server mechanics
+ if (mechanicsTarget.atLeast(me.samsuik.sakura.mechanics.MechanicVersion.v1_11)) {
+ moveCollidedEntities(level, pos, f, blockEntity);
+ moveStuckEntities(level, pos, f, blockEntity);
+ }
blockEntity.progress = f;
if (blockEntity.progress >= 1.0F) {
blockEntity.progress = 1.0F;
}
+ if (mechanicsTarget.between(me.samsuik.sakura.mechanics.MechanicVersion.v1_9, me.samsuik.sakura.mechanics.MechanicVersion.v1_10)) {
+ moveCollidedEntities(level, pos, f, blockEntity);
+ moveStuckEntities(level, pos, f, blockEntity);
+ } else if (blockEntity.extending && mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_9)) {
+ blockEntity.moveEntities(level, blockEntity.progress - blockEntity.progressO + 0.0625f);
+ }
+ // Sakura end - configure server mechanics
}
}
diff --git a/net/minecraft/world/level/material/LavaFluid.java b/net/minecraft/world/level/material/LavaFluid.java
index c8e427907c17ae6ac6c4dbe6abe74955c8030ead..f7209a487a48e434fde91daa39466de16ead03f2 100644
--- a/net/minecraft/world/level/material/LavaFluid.java
+++ b/net/minecraft/world/level/material/LavaFluid.java
@@ -185,6 +185,11 @@ public abstract class LavaFluid extends FlowingFluid {
@Override
public boolean canBeReplacedWith(FluidState fluidState, BlockGetter blockReader, BlockPos pos, Fluid fluid, Direction direction) {
+ // Sakura start - configure server mechanics
+ if (blockReader instanceof Level level && level.localConfig().at(pos).mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_13)) {
+ return false;
+ }
+ // Sakura end - configure server mechanics
return fluidState.getHeight(blockReader, pos) >= 0.44444445F && fluid.is(FluidTags.WATER);
}
diff --git a/net/minecraft/world/level/material/WaterFluid.java b/net/minecraft/world/level/material/WaterFluid.java
index 10e3c644e31650b0e1aad6349a83a763cf744ec8..62b90ee5c3ecdd82e0fbb7a7812cd59e8cbde567 100644
--- a/net/minecraft/world/level/material/WaterFluid.java
+++ b/net/minecraft/world/level/material/WaterFluid.java
@@ -124,7 +124,13 @@ 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 server mechanics
+ final boolean canReplace = direction == Direction.DOWN
+ || blockReader instanceof Level level
+ && level.localConfig().at(pos).mechanicsTarget.before(me.samsuik.sakura.mechanics.MechanicVersion.v1_13);
+ // Before 1.13 lava could replace water
+ return canReplace && !fluid.is(FluidTags.WATER);
+ // Sakura end - configure server mechanics
}
@Override