diff --git a/bukkit/compatibility/build.gradle.kts b/bukkit/compatibility/build.gradle.kts index f6795ac32..1ca637479 100644 --- a/bukkit/compatibility/build.gradle.kts +++ b/bukkit/compatibility/build.gradle.kts @@ -70,6 +70,8 @@ dependencies { compileOnly("com.github.Archy-X:AureliumSkills:Beta1.3.21") // Zaphkiel compileOnly("ink.ptms:ZaphkielAPI:2.1.0") + // WorldGuard + compileOnly(files("${rootProject.rootDir}/libs/worldguard-bukkit-7.0.14-dist.jar")) } java { diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java index 303f3790b..78afe6f1b 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java @@ -11,6 +11,7 @@ import net.momirealms.craftengine.bukkit.compatibility.mythicmobs.MythicItemDrop import net.momirealms.craftengine.bukkit.compatibility.mythicmobs.MythicSkillHelper; import net.momirealms.craftengine.bukkit.compatibility.papi.PlaceholderAPIUtils; import net.momirealms.craftengine.bukkit.compatibility.permission.LuckPermsEventListeners; +import net.momirealms.craftengine.bukkit.compatibility.region.WorldGuardRegionCondition; import net.momirealms.craftengine.bukkit.compatibility.skript.SkriptHook; import net.momirealms.craftengine.bukkit.compatibility.slimeworld.SlimeFormatStorageAdaptor; import net.momirealms.craftengine.bukkit.compatibility.viaversion.ViaVersionUtils; @@ -20,9 +21,13 @@ import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.core.entity.furniture.ExternalModel; import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.loot.LootConditions; import net.momirealms.craftengine.core.plugin.compatibility.CompatibilityManager; import net.momirealms.craftengine.core.plugin.compatibility.LevelerProvider; import net.momirealms.craftengine.core.plugin.compatibility.ModelProvider; +import net.momirealms.craftengine.core.plugin.context.condition.AlwaysFalseCondition; +import net.momirealms.craftengine.core.plugin.context.condition.AlwaysTrueCondition; +import net.momirealms.craftengine.core.plugin.context.event.EventConditions; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.WorldManager; @@ -117,6 +122,15 @@ public class BukkitCompatibilityManager implements CompatibilityManager { new MythicItemDropListener(this.plugin); logHook("MythicMobs"); } + Key worldGuardRegion = Key.of("worldguard:region"); + if (this.isPluginEnabled("WorldGuard")) { + EventConditions.register(worldGuardRegion, new WorldGuardRegionCondition.FactoryImpl<>()); + LootConditions.register(worldGuardRegion, new WorldGuardRegionCondition.FactoryImpl<>()); + logHook("WorldGuard"); + } else { + EventConditions.register(worldGuardRegion, new AlwaysFalseCondition.FactoryImpl<>()); + LootConditions.register(worldGuardRegion, new AlwaysFalseCondition.FactoryImpl<>()); + } } @Override diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/region/WorldGuardRegionCondition.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/region/WorldGuardRegionCondition.java new file mode 100644 index 000000000..5594a4525 --- /dev/null +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/region/WorldGuardRegionCondition.java @@ -0,0 +1,95 @@ +package net.momirealms.craftengine.bukkit.compatibility.region; + +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldguard.WorldGuard; +import com.sk89q.worldguard.protection.ApplicableRegionSet; +import com.sk89q.worldguard.protection.managers.RegionManager; +import com.sk89q.worldguard.protection.regions.ProtectedRegion; +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.condition.ConditionFactory; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.MiscUtils; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import net.momirealms.craftengine.core.world.WorldPosition; +import org.bukkit.World; + +import java.util.*; +import java.util.function.BiFunction; +import java.util.function.Predicate; + +public class WorldGuardRegionCondition implements Condition { + private static final Key TYPE = Key.of("worldguard:region"); + private final MatchMode mode; + private final List regions; + + public WorldGuardRegionCondition(MatchMode mode, List regions) { + this.mode = mode; + this.regions = regions; + } + + @Override + public boolean test(CTX ctx) { + if (this.regions.isEmpty()) return false; + Optional optionalPos = ctx.getOptionalParameter(DirectContextParameters.POSITION); + if (optionalPos.isEmpty()) { + return false; + } + WorldPosition position = optionalPos.get(); + RegionManager regionManager = WorldGuard.getInstance().getPlatform().getRegionContainer().get(BukkitAdapter.adapt((World) position.world().platformWorld())); + if (regionManager != null) { + ApplicableRegionSet set = regionManager.getApplicableRegions(BlockVector3.at(position.x(), position.y(), position.z())); + List regionsAtThisPos = new ArrayList<>(set.size()); + for (ProtectedRegion region : set) { + String id = region.getId(); + regionsAtThisPos.add(id); + } + Predicate predicate = regionsAtThisPos::contains; + return this.mode.matcher.apply(predicate, this.regions); + } + return false; + } + + @Override + public Key type() { + return TYPE; + } + + public enum MatchMode { + ANY((p, regions) -> { + for (String region : regions) { + if (p.test(region)) { + return true; + } + } + return false; + }), + ALL((p, regions) -> { + for (String region : regions) { + if (!p.test(region)) { + return false; + } + } + return true; + }); + + private final BiFunction, List, Boolean> matcher; + + MatchMode(BiFunction, List, Boolean> matcher) { + this.matcher = matcher; + } + } + + public static class FactoryImpl implements ConditionFactory { + + @Override + public Condition create(Map arguments) { + int mode = ResourceConfigUtils.getAsInt(arguments.getOrDefault("mode", 1), "mode") - 1; + MatchMode matchMode = MatchMode.values()[mode]; + List regions = MiscUtils.getAsStringList(arguments.get("regions")); + return new WorldGuardRegionCondition<>(matchMode, regions); + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java index 24da42748..07115036f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java @@ -15,7 +15,9 @@ import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.item.CustomItem; import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.loot.LootContext; import net.momirealms.craftengine.core.loot.LootTable; +import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.context.ContextHolder; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; @@ -174,6 +176,9 @@ public final class BlockEventListener implements Listener { // override vanilla block loots if (player.getGameMode() != GameMode.CREATIVE) { this.plugin.vanillaLootManager().getBlockLoot(stateId).ifPresent(it -> { + if (!event.isDropItems()) { + return; + } if (it.override()) { event.setDropItems(false); event.setExpToDrop(0); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/LiquidCollisionBlockItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/LiquidCollisionBlockItemBehavior.java index 896c742af..051838931 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/LiquidCollisionBlockItemBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/LiquidCollisionBlockItemBehavior.java @@ -3,6 +3,8 @@ package net.momirealms.craftengine.bukkit.item.behavior; import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MFluids; +import net.momirealms.craftengine.bukkit.util.DirectionUtils; import net.momirealms.craftengine.bukkit.util.LocationUtils; import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.entity.player.InteractionResult; @@ -45,11 +47,15 @@ public class LiquidCollisionBlockItemBehavior extends BlockItemBehavior { try { if (player == null) return InteractionResult.FAIL; Object blockHitResult = CoreReflections.method$Item$getPlayerPOVHitResult.invoke(null, world.serverWorld(), player.serverPlayer(), CoreReflections.instance$ClipContext$Fluid$SOURCE_ONLY); - Object blockPos = CoreReflections.field$BlockHitResul$blockPos.get(blockHitResult); + Object blockPos = FastNMS.INSTANCE.field$BlockHitResul$blockPos(blockHitResult); BlockPos above = new BlockPos(FastNMS.INSTANCE.field$Vec3i$x(blockPos), FastNMS.INSTANCE.field$Vec3i$y(blockPos) + offsetY, FastNMS.INSTANCE.field$Vec3i$z(blockPos)); - Direction direction = Direction.values()[(int) CoreReflections.method$Direction$ordinal.invoke(CoreReflections.field$BlockHitResul$direction.get(blockHitResult))]; - boolean miss = CoreReflections.field$BlockHitResul$miss.getBoolean(blockHitResult); + Direction direction = DirectionUtils.fromNMSDirection(FastNMS.INSTANCE.field$BlockHitResul$direction(blockHitResult)); + boolean miss = FastNMS.INSTANCE.field$BlockHitResul$miss(blockHitResult); Vec3d hitPos = LocationUtils.fromVec(CoreReflections.field$HitResult$location.get(blockHitResult)); + Object fluidType = FastNMS.INSTANCE.method$FluidState$getType(FastNMS.INSTANCE.method$BlockGetter$getFluidState(world.serverWorld(), blockPos)); + if (fluidType != MFluids.WATER && fluidType != MFluids.LAVA) { + return InteractionResult.PASS; + } if (miss) { return super.useOnBlock(new UseOnContext(player, hand, BlockHitResult.miss(hitPos, direction, above))); } else { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/DirectionUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/DirectionUtils.java index cf0ef5d0c..41ce992b8 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/DirectionUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/DirectionUtils.java @@ -43,12 +43,9 @@ public final class DirectionUtils { } public static Direction fromNMSDirection(Object direction) { - try { - int index = (int) CoreReflections.method$Direction$ordinal.invoke(direction); - return Direction.values()[index]; - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } + Enum directionEnum = (Enum) direction; + int index = directionEnum.ordinal(); + return Direction.values()[index]; } public static boolean isYAxis(Object nmsDirection) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java index 99313220e..f68ae92f7 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java @@ -42,6 +42,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.scanner.ScannerException; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; @@ -543,6 +544,19 @@ public abstract class AbstractPackManager implements PackManager { } catch (IOException e) { AbstractPackManager.this.plugin.logger().severe("Error while reading config file: " + path, e); return FileVisitResult.CONTINUE; + } catch (ScannerException e) { + if (e.getMessage() != null && e.getMessage().contains("TAB") && e.getMessage().contains("indentation")) { + try { + String content = Files.readString(path); + content = content.replace("\t", " "); + Files.writeString(path, content); + } catch (Exception ex) { + AbstractPackManager.this.plugin.logger().severe("Failed to fix tab indentation in config file: " + path, ex); + } + } else { + AbstractPackManager.this.plugin.logger().severe("Error found while reading config file: " + path, e); + } + return FileVisitResult.CONTINUE; } catch (LocalizedException e) { e.setArgument(0, path.toString()); TranslationManager.instance().log(e.node(), e.arguments()); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/AlwaysFalseCondition.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/AlwaysFalseCondition.java new file mode 100644 index 000000000..127070193 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/AlwaysFalseCondition.java @@ -0,0 +1,23 @@ +package net.momirealms.craftengine.core.plugin.context.condition; + +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.util.Key; + +import java.util.Map; + +public class AlwaysFalseCondition implements Condition { + + @Override + public Key type() { + return CommonConditions.ALWAYS_FALSE; + } + + public static class FactoryImpl implements ConditionFactory { + + @Override + public Condition create(Map arguments) { + return new AlwaysFalseCondition<>(); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/EmptyCondition.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/AlwaysTrueCondition.java similarity index 77% rename from core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/EmptyCondition.java rename to core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/AlwaysTrueCondition.java index dda586d78..c36d53cb9 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/EmptyCondition.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/AlwaysTrueCondition.java @@ -6,11 +6,11 @@ import net.momirealms.craftengine.core.util.Key; import java.util.Map; -public class EmptyCondition implements Condition { +public class AlwaysTrueCondition implements Condition { @Override public Key type() { - return CommonConditions.EMPTY; + return CommonConditions.ALWAYS_TRUE; } @Override @@ -22,7 +22,7 @@ public class EmptyCondition implements Condition { @Override public Condition create(Map arguments) { - return new EmptyCondition<>(); + return new AlwaysTrueCondition<>(); } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java index d9a1eadae..156c17856 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java @@ -5,7 +5,8 @@ import net.momirealms.craftengine.core.util.Key; public final class CommonConditions { private CommonConditions() {} - public static final Key EMPTY = Key.of("craftengine:empty"); + public static final Key ALWAYS_TRUE = Key.of("craftengine:always_true"); + public static final Key ALWAYS_FALSE = Key.of("craftengine:always_false"); public static final Key ALL_OF = Key.of("craftengine:all_of"); public static final Key ANY_OF = Key.of("craftengine:any_of"); public static final Key INVERTED = Key.of("craftengine:inverted"); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/ExpressionCondition.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/ExpressionCondition.java index 7ae158e1f..3dc4a67e2 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/ExpressionCondition.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/ExpressionCondition.java @@ -27,7 +27,7 @@ public class ExpressionCondition implements Condition @Override public boolean test(CTX ctx) { - String exp = expression.get(ctx); + String exp = this.expression.get(ctx); Expression expr = new Expression(exp); try { return expr.evaluate().getBooleanValue(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/CEChunk.java b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/CEChunk.java index 7684dea88..37f6e5a6e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/CEChunk.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/CEChunk.java @@ -60,7 +60,10 @@ public class CEChunk { } public void removeBlockEntity(BlockPos blockPos) { - + BlockEntity removedBlockEntity = this.blockEntities.remove(blockPos); + if (removedBlockEntity != null) { + removedBlockEntity.setValid(false); + } } public void setBlockEntity(BlockEntity blockEntity) { @@ -84,11 +87,27 @@ public class CEChunk { public BlockEntity getBlockEntity(BlockPos pos) { BlockEntity blockEntity = this.blockEntities.get(pos); if (blockEntity == null) { - + blockEntity = createBlockEntity(pos); + if (blockEntity != null) { + this.addBlockEntity(blockEntity); + } + } else { + if (!blockEntity.isValid()) { + this.blockEntities.remove(pos); + return null; + } } return blockEntity; } + private BlockEntity createBlockEntity(BlockPos pos) { + ImmutableBlockState blockState = this.getBlockState(pos); + if (!blockState.hasBlockEntity()) { + return null; + } + return blockState.blockEntityType().factory().create(pos, blockState); + } + public Map blockEntities() { return Collections.unmodifiableMap(this.blockEntities); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/serialization/DefaultBlockEntitySerializer.java b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/serialization/DefaultBlockEntitySerializer.java index f8b91a5f0..246a77363 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/serialization/DefaultBlockEntitySerializer.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/serialization/DefaultBlockEntitySerializer.java @@ -16,7 +16,10 @@ public final class DefaultBlockEntitySerializer { public static ListTag serialize(Map tiles) { ListTag result = new ListTag(); for (Map.Entry entry : tiles.entrySet()) { - result.add(entry.getValue().saveAsTag()); + BlockEntity entity = entry.getValue(); + if (entity.isValid()) { + result.add(entity.saveAsTag()); + } } return result; } diff --git a/gradle.properties b/gradle.properties index 2bc460d2f..a17071ff4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx1G # Project settings # Rule: [major update].[feature update].[bug fix] -project_version=0.0.62.6 +project_version=0.0.62.8 config_version=45 lang_version=25 project_group=net.momirealms @@ -49,8 +49,8 @@ mojang_brigadier_version=1.0.18 byte_buddy_version=1.17.5 ahocorasick_version=0.6.3 snake_yaml_version=2.4 -anti_grief_version=0.19 -nms_helper_version=1.0.67 +anti_grief_version=0.20 +nms_helper_version=1.0.69 evalex_version=3.5.0 reactive_streams_version=1.0.4 amazon_awssdk_version=2.31.23 diff --git a/libs/worldguard-bukkit-7.0.14-dist.jar b/libs/worldguard-bukkit-7.0.14-dist.jar new file mode 100644 index 000000000..69d590e5e Binary files /dev/null and b/libs/worldguard-bukkit-7.0.14-dist.jar differ