From 90fdde2a3447d7f52c82e4cc0f8cb4295608bcf1 Mon Sep 17 00:00:00 2001 From: Pim van der Loos Date: Sun, 21 Jun 2026 11:26:47 +0200 Subject: [PATCH 1/7] Add 26.2 module --- core/pom.xml | 2 +- nms/pom.xml | 3 +- nms/{v26_R1 => v26_1_R1}/pom.xml | 2 +- .../NMS/CraftBlockDataFactory_V26_1_R1.java} | 4 +- .../NMS/CustomCraftFallingBlock_V26_R1.java | 2 +- ...tomEntityFallingBlockGenerator_V26_R1.java | 0 .../NMS/CustomEntityFallingBlock_V26_R1.java | 0 .../FallingBlockFactoryProvider_V26_R1.java | 2 +- .../NMS/FallingBlockFactory_V26_R1.java | 0 .../bigDoors/NMS/NMSBlock_V26_R1.java | 2 +- nms/v26_2_R1/pom.xml | 34 +++ .../NMS/CraftBlockDataFactory_V26_2_R1.java | 63 +++++ .../NMS/CustomCraftFallingBlock_V26_2_R1.java | 164 ++++++++++++ ...mEntityFallingBlockGenerator_V26_2_R1.java | 27 ++ .../CustomEntityFallingBlock_V26_2_R1.java | 114 ++++++++ .../FallingBlockFactoryProvider_V26_2_R1.java | 41 +++ .../NMS/FallingBlockFactory_V26_2_R1.java | 68 +++++ .../bigDoors/NMS/NMSBlock_V26_2_R1.java | 249 ++++++++++++++++++ 18 files changed, 769 insertions(+), 8 deletions(-) rename nms/{v26_R1 => v26_1_R1}/pom.xml (96%) rename nms/{v26_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CraftBlockDataFactory.java => v26_1_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CraftBlockDataFactory_V26_1_R1.java} (95%) rename nms/{v26_R1 => v26_1_R1}/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomCraftFallingBlock_V26_R1.java (97%) rename nms/{v26_R1 => v26_1_R1}/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomEntityFallingBlockGenerator_V26_R1.java (100%) rename nms/{v26_R1 => v26_1_R1}/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomEntityFallingBlock_V26_R1.java (100%) rename nms/{v26_R1 => v26_1_R1}/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactoryProvider_V26_R1.java (94%) rename nms/{v26_R1 => v26_1_R1}/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactory_V26_R1.java (100%) rename nms/{v26_R1 => v26_1_R1}/src/main/java/nl/pim16aap2/bigDoors/NMS/NMSBlock_V26_R1.java (98%) create mode 100644 nms/v26_2_R1/pom.xml create mode 100644 nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CraftBlockDataFactory_V26_2_R1.java create mode 100644 nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomCraftFallingBlock_V26_2_R1.java create mode 100644 nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomEntityFallingBlockGenerator_V26_2_R1.java create mode 100644 nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomEntityFallingBlock_V26_2_R1.java create mode 100644 nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactoryProvider_V26_2_R1.java create mode 100644 nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactory_V26_2_R1.java create mode 100644 nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/NMSBlock_V26_2_R1.java diff --git a/core/pom.xml b/core/pom.xml index bafe138b9..f12e68df5 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -235,7 +235,7 @@ nl.pim16aap2.BigDoors - v26_R1 + v26_1_R1 0.1.8.68-SNAPSHOT compile diff --git a/nms/pom.xml b/nms/pom.xml index f22e89cd6..dca41f268 100644 --- a/nms/pom.xml +++ b/nms/pom.xml @@ -51,7 +51,8 @@ v1_21_R6 v1_21_R7 - v26_R1 + v26_1_R1 + v26_2_R1 diff --git a/nms/v26_R1/pom.xml b/nms/v26_1_R1/pom.xml similarity index 96% rename from nms/v26_R1/pom.xml rename to nms/v26_1_R1/pom.xml index d4bd95a21..6b3250517 100644 --- a/nms/v26_R1/pom.xml +++ b/nms/v26_1_R1/pom.xml @@ -2,7 +2,7 @@ 4.0.0 jar - v26_R1 + v26_1_R1 nl.pim16aap2.BigDoors diff --git a/nms/v26_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CraftBlockDataFactory.java b/nms/v26_1_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CraftBlockDataFactory_V26_1_R1.java similarity index 95% rename from nms/v26_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CraftBlockDataFactory.java rename to nms/v26_1_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CraftBlockDataFactory_V26_1_R1.java index d26555a12..04c964d95 100644 --- a/nms/v26_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CraftBlockDataFactory.java +++ b/nms/v26_1_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CraftBlockDataFactory_V26_1_R1.java @@ -6,11 +6,11 @@ import java.lang.reflect.Method; import java.util.function.Function; -final class CraftBlockDataFactory +final class CraftBlockDataFactory_V26_1_R1 { private static final Function FROM_STATE = findFromStateFunction(); - private CraftBlockDataFactory() + private CraftBlockDataFactory_V26_1_R1() { } diff --git a/nms/v26_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomCraftFallingBlock_V26_R1.java b/nms/v26_1_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomCraftFallingBlock_V26_R1.java similarity index 97% rename from nms/v26_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomCraftFallingBlock_V26_R1.java rename to nms/v26_1_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomCraftFallingBlock_V26_R1.java index 6b9cb14b4..ad74f0da0 100644 --- a/nms/v26_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomCraftFallingBlock_V26_R1.java +++ b/nms/v26_1_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomCraftFallingBlock_V26_R1.java @@ -87,7 +87,7 @@ public boolean isInWorld() @Override public @NotNull BlockData getBlockData() { - return CraftBlockDataFactory.fromState(this.getHandle().getBlockState()); + return CraftBlockDataFactory_V26_1_R1.fromState(this.getHandle().getBlockState()); } @Override diff --git a/nms/v26_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomEntityFallingBlockGenerator_V26_R1.java b/nms/v26_1_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomEntityFallingBlockGenerator_V26_R1.java similarity index 100% rename from nms/v26_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomEntityFallingBlockGenerator_V26_R1.java rename to nms/v26_1_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomEntityFallingBlockGenerator_V26_R1.java diff --git a/nms/v26_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomEntityFallingBlock_V26_R1.java b/nms/v26_1_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomEntityFallingBlock_V26_R1.java similarity index 100% rename from nms/v26_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomEntityFallingBlock_V26_R1.java rename to nms/v26_1_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomEntityFallingBlock_V26_R1.java diff --git a/nms/v26_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactoryProvider_V26_R1.java b/nms/v26_1_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactoryProvider_V26_R1.java similarity index 94% rename from nms/v26_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactoryProvider_V26_R1.java rename to nms/v26_1_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactoryProvider_V26_R1.java index 63ebea48b..72f0b4c88 100644 --- a/nms/v26_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactoryProvider_V26_R1.java +++ b/nms/v26_1_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactoryProvider_V26_R1.java @@ -30,7 +30,7 @@ private static boolean checkPreconditions() { try { - return CraftBlockDataFactory.isInitialized(); + return CraftBlockDataFactory_V26_1_R1.isInitialized(); } catch (Throwable t) { diff --git a/nms/v26_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactory_V26_R1.java b/nms/v26_1_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactory_V26_R1.java similarity index 100% rename from nms/v26_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactory_V26_R1.java rename to nms/v26_1_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactory_V26_R1.java diff --git a/nms/v26_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/NMSBlock_V26_R1.java b/nms/v26_1_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/NMSBlock_V26_R1.java similarity index 98% rename from nms/v26_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/NMSBlock_V26_R1.java rename to nms/v26_1_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/NMSBlock_V26_R1.java index bdc1902ac..8c0cd91a4 100644 --- a/nms/v26_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/NMSBlock_V26_R1.java +++ b/nms/v26_1_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/NMSBlock_V26_R1.java @@ -95,7 +95,7 @@ private void updateBlockData() private void updateCraftBlockData() { - this.craftBlockData = CraftBlockDataFactory.fromState(blockData); + this.craftBlockData = CraftBlockDataFactory_V26_1_R1.fromState(blockData); } @Override diff --git a/nms/v26_2_R1/pom.xml b/nms/v26_2_R1/pom.xml new file mode 100644 index 000000000..805f3d3c6 --- /dev/null +++ b/nms/v26_2_R1/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + jar + v26_2_R1 + + + nl.pim16aap2.BigDoors + nms + 0.1.8.68-SNAPSHOT + + + + 8 + 8 + UTF-8 + + + + + org.spigotmc + spigot + 26.2-R0.1-SNAPSHOT + provided + + + + nl.pim16aap2.BigDoors + nms-api + 0.1.8.68-SNAPSHOT + provided + + + diff --git a/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CraftBlockDataFactory_V26_2_R1.java b/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CraftBlockDataFactory_V26_2_R1.java new file mode 100644 index 000000000..e6df0bd57 --- /dev/null +++ b/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CraftBlockDataFactory_V26_2_R1.java @@ -0,0 +1,63 @@ +package nl.pim16aap2.bigDoors.NMS; + +import net.minecraft.world.level.block.state.BlockState; +import org.bukkit.craftbukkit.block.data.CraftBlockData; + +import java.lang.reflect.Method; +import java.util.function.Function; + +final class CraftBlockDataFactory_V26_2_R1 +{ + private static final Function FROM_STATE = findFromStateFunction(); + + private CraftBlockDataFactory_V26_2_R1() + { + } + + public static CraftBlockData fromState(BlockState state) + { + return FROM_STATE.apply(state); + } + + static boolean isInitialized() + { + return true; + } + + private static Function findFromStateFunction() + { + // On Spigot, we can use CraftBlockData#fromData(BlockState) without reflection. + // On Paper, it's CraftBlockData#createData(BlockState), which is not present in Spigot, so we'll use reflection. + try + { + CraftBlockData.class.getMethod("fromData", BlockState.class); + return CraftBlockData::fromData; + } + catch (NoSuchMethodException ignored) + { + // Ignored + } + + try + { + Method method = CraftBlockData.class.getMethod("createData", BlockState.class); + method.setAccessible(true); + return state -> + { + try + { + return (CraftBlockData) method.invoke(null, state); + } + catch (Exception e) + { + throw new RuntimeException("Failed to create block data from state: " + state, e); + } + }; + } + catch (NoSuchMethodException ignored) + { + // ignored + } + throw new IllegalStateException("Failed to find method to create CraftBlockData from state"); + } +} diff --git a/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomCraftFallingBlock_V26_2_R1.java b/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomCraftFallingBlock_V26_2_R1.java new file mode 100644 index 000000000..25daaa02c --- /dev/null +++ b/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomCraftFallingBlock_V26_2_R1.java @@ -0,0 +1,164 @@ +package nl.pim16aap2.bigDoors.NMS; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.data.BlockData; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.entity.CraftEntity; +import org.bukkit.craftbukkit.util.CraftMagicNumbers; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntitySnapshot; +import org.bukkit.entity.FallingBlock; +import org.bukkit.util.EulerAngle; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; +import org.jspecify.annotations.NonNull; + +@SuppressWarnings("UnstableApiUsage") +public class CustomCraftFallingBlock_V26_2_R1 extends CraftEntity implements FallingBlock, CustomCraftFallingBlock +{ + public CustomCraftFallingBlock_V26_2_R1(final CraftServer server, final CustomEntityFallingBlock_V26_2_R1 entity) + { + super(server, entity); + setVelocity(new Vector(0, 0, 0)); + setDropItem(false); + } + + @Override + public CustomEntityFallingBlock_V26_2_R1 getHandle() + { + return (CustomEntityFallingBlock_V26_2_R1) entity; + } + + @Override + public boolean isOnGround() + { + return false; + } + + @Override + public String toString() + { + return "CraftFallingBlock"; + } + + @Override + public void setVisibleByDefault(boolean flag) + { + } + + @Override + public boolean isVisibleByDefault() + { + return true; + } + + @Override + public boolean isInWorld() + { + return false; + } + + @Override + public @NonNull EntitySnapshot createSnapshot() + { + throw new UnsupportedOperationException("Not implemented for animated blocks!"); + } + + @Override + public @NonNull Entity copy() + { + throw new UnsupportedOperationException("Not implemented for animated blocks!"); + } + + @Override + public @NonNull Entity copy(@NotNull Location location) + { + throw new UnsupportedOperationException("Not implemented for animated blocks!"); + } + + @Override + @Deprecated + public @NotNull Material getMaterial() + { + return CraftMagicNumbers.getMaterial(getHandle().getBlockState()).getItemType(); + } + + @Override + public @NotNull BlockData getBlockData() + { + return CraftBlockDataFactory_V26_2_R1.fromState(this.getHandle().getBlockState()); + } + + @Override + public boolean getDropItem() + { + return false; + } + + @Override + public void setDropItem(final boolean drop) + { + } + + @Override + public boolean getCancelDrop() + { + return true; + } + + @Override + public void setCancelDrop(boolean b) + { + } + + @Override + public boolean canHurtEntities() + { + return false; + } + + @Override + public void setHurtEntities(final boolean hurtEntities) + { + } + + @Override + public float getDamagePerBlock() + { + return 0; + } + + @Override + public void setDamagePerBlock(float damage) + { + } + + @Override + public int getMaxDamage() + { + return 0; + } + + @Override + public void setMaxDamage(int damage) + { + } + + @Override + public void setTicksLived(final int value) + { + super.setTicksLived(value); + getHandle().setTicksLived(value); + } + + @Override + public void setHeadPose(EulerAngle pose) + { + } + + @Override + public void setBodyPose(EulerAngle eulerAngle) + { + } +} diff --git a/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomEntityFallingBlockGenerator_V26_2_R1.java b/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomEntityFallingBlockGenerator_V26_2_R1.java new file mode 100644 index 000000000..75d7760bb --- /dev/null +++ b/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomEntityFallingBlockGenerator_V26_2_R1.java @@ -0,0 +1,27 @@ +package nl.pim16aap2.bigDoors.NMS; + +/** + * Represents a class that can generate a subclass of {@link CustomEntityFallingBlock_V26_2_R1}. + */ +class CustomEntityFallingBlockGenerator_V26_2_R1 +{ + /** + * Gets a {@link FallingBlockFactory_V26_2_R1.CustomEntityFallingBlockFactory} that can be used to create new + * {@link CustomEntityFallingBlock_V26_2_R1} instances. + * + * @return The supplier for new {@link CustomEntityFallingBlock_V26_2_R1} instances. + */ + public FallingBlockFactory_V26_2_R1.CustomEntityFallingBlockFactory getEntityFallingBlockSupplier() + { + return (world, x, y, z, blockState) -> { + try + { + return new CustomEntityFallingBlock_V26_2_R1(world, x, y, z, blockState); + } + catch (Exception e) + { + throw new RuntimeException("Failed to create a new CustomEntityFallingBlock instance!", e); + } + }; + } +} diff --git a/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomEntityFallingBlock_V26_2_R1.java b/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomEntityFallingBlock_V26_2_R1.java new file mode 100644 index 000000000..f915384f8 --- /dev/null +++ b/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/CustomEntityFallingBlock_V26_2_R1.java @@ -0,0 +1,114 @@ +package nl.pim16aap2.bigDoors.NMS; + +import net.minecraft.CrashReportCategory; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.EntityTypes; +import net.minecraft.world.entity.MoverType; +import net.minecraft.world.entity.item.FallingBlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; +import net.minecraft.world.phys.Vec3; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.EntityRemoveEvent; +import org.jspecify.annotations.NonNull; + +public class CustomEntityFallingBlock_V26_2_R1 extends FallingBlockEntity implements CustomEntityFallingBlock +{ + // We need to keep our own blockstate as the parent is private without setter. + private BlockState blockState; + private final CraftWorld world; + + public CustomEntityFallingBlock_V26_2_R1( + final org.bukkit.World world, + final double spawnX, + final double spawnY, + final double spawnZ, + final BlockState blockState + ) + { + super( + EntityTypes.FALLING_BLOCK, + ((CraftWorld) world).getHandle() + ); + + this.world = (CraftWorld) world; + this.blockState = blockState; + + applyDefaultSettings(); + + super.setPos(spawnX, spawnY, spawnZ); + super.setStartPos(BlockPos.containing(spawnX, spawnY, spawnZ)); + super.setDeltaMovement(new Vec3(0.0F, 0.0F, 0.0F)); + + spawn(); + } + + private void applyDefaultSettings() + { + super.time = 0; + super.hurtEntities = false; + super.noPhysics = true; + super.setNoGravity(true); + } + + public void spawn() + { + this.world.addEntityToWorld(this, CreatureSpawnEvent.SpawnReason.CUSTOM); + } + + private void die() + { + this.discard(EntityRemoveEvent.Cause.PLUGIN); + } + + @Override + public void tick() + { + if (this.blockState.isAir()) + { + die(); + return; + } + + move(MoverType.SELF, getDeltaMovement()); + if (++super.time > 12000) + die(); + + setDeltaMovement(getDeltaMovement().multiply(0.9800000190734863D, 1.0D, 0.9800000190734863D)); + } + + @Override + protected void addAdditionalSaveData(@NonNull ValueOutput valueOutput) + { + super.addAdditionalSaveData(valueOutput); + applyDefaultSettings(); + } + + @Override + protected void readAdditionalSaveData(@NonNull ValueInput valueInput) + { + super.readAdditionalSaveData(valueInput); + this.blockState = super.getBlockState(); + setTicksLived(0); + } + + @Override + public void fillCrashReportCategory(@NonNull CrashReportCategory crashReportCategory) + { + super.fillCrashReportCategory(crashReportCategory); + crashReportCategory.setDetail("Animated BigDoors block with state: ", blockState.toString()); + } + + @Override + public @NonNull BlockState getBlockState() + { + return blockState; + } + + void setTicksLived(int ticks) + { + this.time = ticks; + } +} diff --git a/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactoryProvider_V26_2_R1.java b/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactoryProvider_V26_2_R1.java new file mode 100644 index 000000000..9908b8fe2 --- /dev/null +++ b/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactoryProvider_V26_2_R1.java @@ -0,0 +1,41 @@ +package nl.pim16aap2.bigDoors.NMS; + +/** + * Provides a specialized {@link FallingBlockFactory} for the given version. + *

+ * The exact type of {@link FallingBlockFactory} returned depends on the specific build of Spigot/Paper/etc. + *

+ * Use {@link #getFactory()} to get a new {@link FallingBlockFactory} instance. + */ +public class FallingBlockFactoryProvider_V26_2_R1 +{ + /** + * Creates a new {@link FallingBlockFactory} instance for a specific version of Minecraft for the current server build. + * + * @return A new {@link FallingBlockFactory} instance. + */ + public static FallingBlockFactory getFactory() + { + if (!checkPreconditions()) + { + return null; + } + + return new FallingBlockFactory_V26_2_R1( + new CustomEntityFallingBlockGenerator_V26_2_R1().getEntityFallingBlockSupplier() + ); + } + + private static boolean checkPreconditions() + { + try + { + return CraftBlockDataFactory_V26_2_R1.isInitialized(); + } + catch (Throwable t) + { + t.printStackTrace(); + return false; + } + } +} diff --git a/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactory_V26_2_R1.java b/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactory_V26_2_R1.java new file mode 100644 index 000000000..1b2bdf90d --- /dev/null +++ b/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/FallingBlockFactory_V26_2_R1.java @@ -0,0 +1,68 @@ +package nl.pim16aap2.bigDoors.NMS; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.Identifier; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.CraftWorld; + +class FallingBlockFactory_V26_2_R1 implements FallingBlockFactory +{ + private final CustomEntityFallingBlockFactory customEntityFallingBlockFactory; + private final ResourceKey blockInfoResourceKey; + + FallingBlockFactory_V26_2_R1(CustomEntityFallingBlockFactory customEntityFallingBlockFactory) + { + this.customEntityFallingBlockFactory = customEntityFallingBlockFactory; + this.blockInfoResourceKey = ResourceKey.create( + Registries.BLOCK, + Identifier.fromNamespaceAndPath("big-doors", "block-info") + ); + } + + @Override + public CustomCraftFallingBlock createFallingBlock(Location loc, NMSBlock block, byte matData, Material mat) + { + final BlockState blockData = ((NMSBlock_V26_2_R1) block).getMyBlockData(); + final CustomEntityFallingBlock_V26_2_R1 fBlockNMS = + customEntityFallingBlockFactory.newEntityFallingBlock( + loc.getWorld(), + loc.getX(), + loc.getY(), + loc.getZ(), + blockData + ); + + return new CustomCraftFallingBlock_V26_2_R1((CraftServer) Bukkit.getServer(), fBlockNMS); + } + + @Override + public NMSBlock nmsBlockFactory(World world, int x, int y, int z) + { + final BlockBehaviour.Properties blockInfo = + BlockBehaviour.Properties.ofFullCopy(((CraftWorld) world).getHandle().getBlockState(new BlockPos(x, y, z)).getBlock()).setId(blockInfoResourceKey); + return new NMSBlock_V26_2_R1(world, x, y, z, blockInfo); + } + + /** + * Factory for creating {@link CustomEntityFallingBlock} instances. + */ + interface CustomEntityFallingBlockFactory + { + CustomEntityFallingBlock_V26_2_R1 newEntityFallingBlock( + World world, + double x, + double y, + double z, + BlockState blockData + ); + } +} diff --git a/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/NMSBlock_V26_2_R1.java b/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/NMSBlock_V26_2_R1.java new file mode 100644 index 000000000..e50db555f --- /dev/null +++ b/nms/v26_2_R1/src/main/java/nl/pim16aap2/bigDoors/NMS/NMSBlock_V26_2_R1.java @@ -0,0 +1,249 @@ +package nl.pim16aap2.bigDoors.NMS; + +import com.cryptomorin.xseries.XMaterial; +import com.mojang.serialization.MapCodec; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.RotatedPillarBlock; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import nl.pim16aap2.bigDoors.util.DoorDirection; +import nl.pim16aap2.bigDoors.util.NMSUtil; +import nl.pim16aap2.bigDoors.util.RotateDirection; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.MultipleFacing; +import org.bukkit.block.data.Waterlogged; +import org.bukkit.block.data.type.Fence; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.block.data.CraftBlockData; +import org.jspecify.annotations.NonNull; + +import java.util.Objects; +import java.util.Set; + +public class NMSBlock_V26_2_R1 extends BlockBehaviour implements NMSBlock +{ + private static final MapCodec CODEC = + simpleCodec(properties -> + { + throw new UnsupportedOperationException("Custom block data cannot be deserialized from codec"); + }); + + private BlockState blockData; + private CraftBlockData craftBlockData; + private final XMaterial xMat; + private Location loc; + + public NMSBlock_V26_2_R1( + World world, + int x, + int y, + int z, + BlockBehaviour.Properties blockInfo + ) + { + super(blockInfo); + + loc = new Location(world, x, y, z); + + craftBlockData = (CraftBlockData) world.getBlockAt(x, y, z).getBlockData(); + if (craftBlockData instanceof Waterlogged) + { + ((Waterlogged) craftBlockData).setWaterlogged(false); + } + + updateBlockData(); + + xMat = XMaterial.matchXMaterial(world.getBlockAt(x, y, z).getType().toString()).orElse(XMaterial.BEDROCK); + } + + @Override + public boolean canRotate() + { + return craftBlockData instanceof MultipleFacing; + } + + @Override + public void rotateBlock(RotateDirection rotDir) + { + Rotation rot; + switch (rotDir) + { + case CLOCKWISE: + rot = Rotation.CLOCKWISE_90; + break; + case COUNTERCLOCKWISE: + rot = Rotation.COUNTERCLOCKWISE_90; + break; + default: + rot = Rotation.NONE; + } + blockData = blockData.rotate(rot); + updateCraftBlockData(); + } + + private void updateBlockData() + { + blockData = craftBlockData.getState(); + } + + private void updateCraftBlockData() + { + this.craftBlockData = CraftBlockDataFactory_V26_2_R1.fromState(blockData); + } + + @Override + public void putBlock(Location loc) + { + this.loc = loc; + + if (craftBlockData instanceof MultipleFacing) + { + updateCraftBlockDataMultipleFacing(); + } + + final CraftWorld craftWorld = Objects.requireNonNull((CraftWorld) loc.getWorld()); + + craftWorld + .getHandle() + .setBlock(BlockPos.containing(loc.getX(), loc.getY(), loc.getZ()), blockData, 1); + } + + private void updateCraftBlockDataMultipleFacing() + { + final Set allowedFaces = ((MultipleFacing) craftBlockData).getAllowedFaces(); + allowedFaces.forEach( + (blockFace) -> + { + final org.bukkit.block.Block otherBlock = + loc.clone().add(blockFace.getModX(), blockFace.getModY(), blockFace.getModZ()).getBlock(); + final org.bukkit.block.data.BlockData otherData = otherBlock.getBlockData(); + + if (blockFace.equals(BlockFace.UP)) + { + ((MultipleFacing) craftBlockData).setFace(blockFace, true); + } + else if (otherBlock.getType().isSolid()) + { + + ((MultipleFacing) craftBlockData).setFace(blockFace, true); + + final boolean isOtherMultipleFacing = otherData instanceof MultipleFacing; + final boolean materialMatch = otherBlock.getType().equals(xMat.parseMaterial()); + final boolean areBothFence = craftBlockData instanceof Fence && otherData instanceof Fence; + + if (isOtherMultipleFacing && (materialMatch || areBothFence)) + { + final Set otherAllowedFaces = ((MultipleFacing) otherData).getAllowedFaces(); + if (otherAllowedFaces.contains(blockFace.getOppositeFace())) + { + ((MultipleFacing) otherData).setFace(blockFace.getOppositeFace(), true); + otherBlock.setBlockData(otherData); + } + } + } + else + { + ((MultipleFacing) craftBlockData).setFace(blockFace, false); + } + }); + this.updateBlockData(); + } + + @Override + public void rotateVerticallyInDirection(DoorDirection openDirection) + { + NMSUtil.rotateVerticallyInDirection(openDirection, craftBlockData); + this.updateBlockData(); + } + + @Override + public void rotateBlockUpDown(boolean ns) + { + Direction.Axis axis = blockData.getValue(RotatedPillarBlock.AXIS); + Direction.Axis newAxis = axis; + switch (axis) + { + case X: + newAxis = ns ? Direction.Axis.X : Direction.Axis.Y; + break; + case Y: + newAxis = ns ? Direction.Axis.Z : Direction.Axis.X; + break; + case Z: + newAxis = ns ? Direction.Axis.Y : Direction.Axis.Z; + break; + } + blockData = blockData.setValue(RotatedPillarBlock.AXIS, newAxis); + this.updateCraftBlockData(); + } + + @Override + public void rotateCylindrical(RotateDirection rotDir) + { + if (rotDir.equals(RotateDirection.CLOCKWISE)) + { + blockData = blockData.rotate(Rotation.CLOCKWISE_90); + } + else + { + blockData = blockData.rotate(Rotation.COUNTERCLOCKWISE_90); + } + this.updateCraftBlockData(); + } + + /** + * Gets the BlockState (NMS) of this block. + * + * @return The BlockState (NMS) of this block. + */ + BlockState getMyBlockData() + { + return blockData; + } + + @Override + public String toString() + { + return blockData.toString(); + } + + @Override + public void deleteOriginalBlock(boolean applyPhysics) + { + final World world = Objects.requireNonNull(loc.getWorld()); + if (!applyPhysics) + { + world.getBlockAt(loc).setType(Material.AIR, false); + } + else + { + world.getBlockAt(loc).setType(Material.CAVE_AIR, false); + world.getBlockAt(loc).setType(Material.AIR, true); + } + } + + @Override + protected @NonNull MapCodec codec() + { + return CODEC; + } + + @Override + public @NonNull Item asItem() + { + throw new UnsupportedOperationException("Custom block data cannot be converted to an item"); + } + + @Override + protected @NonNull Block asBlock() + { + return this.blockData.getBlock(); + } +} From c88f3ae8b3551495598a467cb1e2eb459f178853 Mon Sep 17 00:00:00 2001 From: Pim van der Loos Date: Sun, 21 Jun 2026 13:34:23 +0200 Subject: [PATCH 2/7] Add MC 26.1 code generation support --- .../codegeneration/FallbackGeneratorManager.java | 6 ++++++ .../codegeneration/ReflectionRepository.java | 14 ++++++++++++-- .../pim16aap2/bigDoors/reflection/asm/ASMUtil.java | 8 ++++++-- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/nl/pim16aap2/bigDoors/codegeneration/FallbackGeneratorManager.java b/core/src/main/java/nl/pim16aap2/bigDoors/codegeneration/FallbackGeneratorManager.java index c90c60c3a..18586ad8d 100644 --- a/core/src/main/java/nl/pim16aap2/bigDoors/codegeneration/FallbackGeneratorManager.java +++ b/core/src/main/java/nl/pim16aap2/bigDoors/codegeneration/FallbackGeneratorManager.java @@ -55,6 +55,7 @@ private static FallingBlockFactory generateFallingBlockFactory() try { + ensureReflectionLookupSuccess(); final String mappingsVersion = getMappingsVersion(); final ClassGenerator entityFallingBlockClassGenerator = new EntityFallingBlockClassGenerator(mappingsVersion); @@ -106,6 +107,11 @@ private static FallingBlockFactory generateFallingBlockFactory() } } + private static void ensureReflectionLookupSuccess() + { + ReflectionRepository.noop(); + } + @SuppressWarnings("unchecked") private static String getPaperMappingsVersion() { diff --git a/core/src/main/java/nl/pim16aap2/bigDoors/codegeneration/ReflectionRepository.java b/core/src/main/java/nl/pim16aap2/bigDoors/codegeneration/ReflectionRepository.java index a6dd8f2fa..078622183 100644 --- a/core/src/main/java/nl/pim16aap2/bigDoors/codegeneration/ReflectionRepository.java +++ b/core/src/main/java/nl/pim16aap2/bigDoors/codegeneration/ReflectionRepository.java @@ -55,6 +55,7 @@ final class ReflectionRepository public static final Class classCraftBlockData; public static final Class classBlockStateEnum; public static final Class classEntityTypes; + public static final Class classEntityType; public static final Class classRegistries; public static final Class classResourceKey; public static final Class classMinecraftKey; @@ -187,7 +188,8 @@ final class ReflectionRepository classEnumDirectionAxis = findClass("net.minecraft.core.Direction$Axis").get(); classEnumBlockRotation = findClass("net.minecraft.world.level.block.Rotation").get(); classBlockRotatable = findClass("net.minecraft.world.level.block.RotatedPillarBlock").get(); - classEntityTypes = findClass("net.minecraft.world.entity.EntityType").get(); + classEntityTypes = findClass("net.minecraft.world.entity.EntityTypes").get(); + classEntityType = findClass("net.minecraft.world.entity.EntityType").get(); classRegistries = findClass("net.minecraft.core.registries.Registries").get(); classResourceKey = findClass("net.minecraft.resources.ResourceKey").get(); classIWorldReader = findClass("net.minecraft.world.level.LevelReader").get(); @@ -202,7 +204,7 @@ final class ReflectionRepository .get(); cTorPublicNMSFallingBlockEntity = findConstructor() .inClass(classEntityFallingBlock) - .withParameters(classEntityTypes, classNMSWorld) + .withParameters(classEntityType, classNMSWorld) .get(); cTorVec3D = findConstructor() .inClass(classVec3D) @@ -565,6 +567,14 @@ final class ReflectionRepository } } + /** + * This method is used to ensure that the static initializer of this class is executed. + *

+ * It does nothing and is only used for its side effect of triggering the static initializer. + */ + static void noop() { + } + private static Method getMethodCraftBockDataFromNMSBlockData() { Method method = findMethod() diff --git a/core/src/main/java/nl/pim16aap2/bigDoors/reflection/asm/ASMUtil.java b/core/src/main/java/nl/pim16aap2/bigDoors/reflection/asm/ASMUtil.java index 5662c3fd1..0544f82c6 100644 --- a/core/src/main/java/nl/pim16aap2/bigDoors/reflection/asm/ASMUtil.java +++ b/core/src/main/java/nl/pim16aap2/bigDoors/reflection/asm/ASMUtil.java @@ -87,10 +87,14 @@ else if (executable instanceof Constructor) try { - return Objects.requireNonNull( + StaticFieldFinder staticFieldFinder = Objects.requireNonNull( ASMUtil.processMethod(executable, null, (a, n, d, s, e) -> StaticFieldFinder.create(a, n, d, s, e, fieldType, 1)) - ).fields[0]; + ); + + return Objects.requireNonNull( + staticFieldFinder.fields[0] + ); } catch (IOException e) { From ad56f02285771440cbea657775642c199b2a3fe2 Mon Sep 17 00:00:00 2001 From: Pim van der Loos Date: Sun, 21 Jun 2026 13:38:08 +0200 Subject: [PATCH 3/7] Add compilation of 26.2 to CI pipeline --- .github/nms-groups.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/nms-groups.yml b/.github/nms-groups.yml index 6ee5af347..392ee19ac 100644 --- a/.github/nms-groups.yml +++ b/.github/nms-groups.yml @@ -44,3 +44,4 @@ java21: java25: - "26.1.2" # 26_1_R1 + - "26.2" # 26_2_R1 From 47ccd2837d5af77a4edb9033052279a4e136a93e Mon Sep 17 00:00:00 2001 From: Pim van der Loos Date: Sun, 21 Jun 2026 13:58:51 +0200 Subject: [PATCH 4/7] Add MC 26.2 resource pack version --- .../pim16aap2/bigDoors/util/ResourcePackDetails.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/nl/pim16aap2/bigDoors/util/ResourcePackDetails.java b/core/src/main/java/nl/pim16aap2/bigDoors/util/ResourcePackDetails.java index 54dd49439..261178158 100644 --- a/core/src/main/java/nl/pim16aap2/bigDoors/util/ResourcePackDetails.java +++ b/core/src/main/java/nl/pim16aap2/bigDoors/util/ResourcePackDetails.java @@ -152,8 +152,15 @@ public enum ResourcePackDetails "https://www.dropbox.com/scl/fi/drls9p9bhg28zbinty3d6/BigDoorsResourcePack-Format84.zip?rlkey=zrulj21mbwz4tzpbyys5pzq1f&st=v3vz19ml&dl=1", "b10c21defae3548afd124e7dc48de1cfe1fe3ecc", Semver.of(26, 0, 0), - Semver.of(26, 1, 1) - ) + Semver.of(26, 1, 2) + ), + + FORMAT_88( + "https://www.dropbox.com/scl/fi/2ucdkpbyhhdr8wzomwnky/BigDoorsResourcePack-Format88.zip?rlkey=7m95e23vxtwqcwkw2atjuivs0&st=9k4wr5gg&dl=1", + "57789486b18b0d79de1e0f1ad68047580068ffb5", + Semver.of(26, 2, 0), + Semver.of(26, 2, 1) + ), ; From 8f941531ea992b0b31bb38d89a3df4478d32c286 Mon Sep 17 00:00:00 2001 From: Pim van der Loos Date: Sun, 21 Jun 2026 13:59:05 +0200 Subject: [PATCH 5/7] Add full MC 26.1 support --- NEXT_RELEASE_CHANGELOG.md | 1 + core/pom.xml | 7 +++++++ core/src/main/java/nl/pim16aap2/bigDoors/BigDoors.java | 5 +++++ 3 files changed, 13 insertions(+) diff --git a/NEXT_RELEASE_CHANGELOG.md b/NEXT_RELEASE_CHANGELOG.md index e69de29bb..ce6cd20b1 100644 --- a/NEXT_RELEASE_CHANGELOG.md +++ b/NEXT_RELEASE_CHANGELOG.md @@ -0,0 +1 @@ +- Added support for MC 26.2. diff --git a/core/pom.xml b/core/pom.xml index f12e68df5..3551551d9 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -240,6 +240,13 @@ compile + + nl.pim16aap2.BigDoors + v26_2_R1 + 0.1.8.68-SNAPSHOT + compile + + ${dependency.xseries.groupid} XSeries diff --git a/core/src/main/java/nl/pim16aap2/bigDoors/BigDoors.java b/core/src/main/java/nl/pim16aap2/bigDoors/BigDoors.java index 889f88d73..122a17472 100644 --- a/core/src/main/java/nl/pim16aap2/bigDoors/BigDoors.java +++ b/core/src/main/java/nl/pim16aap2/bigDoors/BigDoors.java @@ -15,6 +15,7 @@ import nl.pim16aap2.bigDoors.NMS.FallingBlockFactoryProvider_V1_21_R5; import nl.pim16aap2.bigDoors.NMS.FallingBlockFactoryProvider_V1_21_R6; import nl.pim16aap2.bigDoors.NMS.FallingBlockFactoryProvider_V1_21_R7; +import nl.pim16aap2.bigDoors.NMS.FallingBlockFactoryProvider_V26_2_R1; import nl.pim16aap2.bigDoors.NMS.FallingBlockFactoryProvider_V26_R1; import nl.pim16aap2.bigDoors.NMS.FallingBlockFactory_V1_11_R1; import nl.pim16aap2.bigDoors.NMS.FallingBlockFactory_V1_12_R1; @@ -931,6 +932,10 @@ public static boolean isOnFlattenedVersion() case 2: return FallingBlockFactoryProvider_V26_R1.getFactory(); } + case 2: + { + return FallingBlockFactoryProvider_V26_2_R1.getFactory(); + } } } } From 1bf99a0d235d04c2619a033bec3328161aeb4d86 Mon Sep 17 00:00:00 2001 From: Pim van der Loos Date: Sun, 21 Jun 2026 15:00:34 +0200 Subject: [PATCH 6/7] Update XSeries for 26.2 materials support --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3336f23f5..93276ae84 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ 3.4.0 3.5.4 - 38decc68d5 + 27883fb37a com.github.PimvanderLoos From fd89ead80670598770c3dab88d59639bcbb8415c Mon Sep 17 00:00:00 2001 From: Pim van der Loos Date: Sun, 21 Jun 2026 15:07:10 +0200 Subject: [PATCH 7/7] Fix accidental fallthrough - Whoops. Too used to the new switches ;) --- core/src/main/java/nl/pim16aap2/bigDoors/BigDoors.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/main/java/nl/pim16aap2/bigDoors/BigDoors.java b/core/src/main/java/nl/pim16aap2/bigDoors/BigDoors.java index 122a17472..839c99fd1 100644 --- a/core/src/main/java/nl/pim16aap2/bigDoors/BigDoors.java +++ b/core/src/main/java/nl/pim16aap2/bigDoors/BigDoors.java @@ -931,11 +931,17 @@ public static boolean isOnFlattenedVersion() case 1: case 2: return FallingBlockFactoryProvider_V26_R1.getFactory(); + default: + logger.severe("Unexpected patch version '" + SERVER_VERSION.getPatch() + "' for 26.1.x!"); + return null; } case 2: { return FallingBlockFactoryProvider_V26_2_R1.getFactory(); } + default: + logger.severe("Unexpected minor version '" + SERVER_VERSION.getMinor() + "' for 26.x!"); + return null; } } }