diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/AbstractCustomEventListener.java b/api/src/main/java/net/momirealms/customcrops/api/core/AbstractCustomEventListener.java index d52e96d..57d73f4 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/AbstractCustomEventListener.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/AbstractCustomEventListener.java @@ -412,4 +412,10 @@ public abstract class AbstractCustomEventListener implements Listener { } }); } + + @EventHandler(ignoreCancelled = true) + public void onBurn(BlockBurnEvent event) { + Block block = event.getBlock(); + itemManager.handlePhysicsBreak(block.getLocation(), block.getBlockData().getAsString(), event); + } } diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/ConfigManager.java b/api/src/main/java/net/momirealms/customcrops/api/core/ConfigManager.java index 55f3981..6162fa3 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/ConfigManager.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/ConfigManager.java @@ -91,6 +91,8 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable { protected HashSet overriddenCrops = new HashSet<>(); + protected boolean worldeditSupport = false; + public ConfigManager(BukkitCustomCropsPlugin plugin) { this.plugin = plugin; instance = this; @@ -188,6 +190,10 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable { return instance.overriddenCrops; } + public static boolean worldeditSupport() { + return instance.worldeditSupport; + } + @Override public YamlDocument loadConfig(String filePath) { return loadConfig(filePath, '.'); diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsBlockState.java b/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsBlockState.java index 4b6b44b..0ccff86 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsBlockState.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsBlockState.java @@ -18,7 +18,10 @@ package net.momirealms.customcrops.api.core.world; import com.flowpowered.nbt.CompoundMap; +import com.flowpowered.nbt.CompoundTag; import net.momirealms.customcrops.api.core.block.CustomCropsBlock; +import net.momirealms.customcrops.api.util.TagUtils; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; /** @@ -44,4 +47,12 @@ public interface CustomCropsBlockState extends DataBlock { static CustomCropsBlockState create(CustomCropsBlock owner, CompoundMap compoundMap) { return new CustomCropsBlockStateImpl(owner, compoundMap); } + + @ApiStatus.Internal + static CustomCropsBlockState create(CustomCropsBlock owner, byte[] nbtBytes) { + return new CustomCropsBlockStateImpl(owner, ((CompoundTag) TagUtils.fromBytes(nbtBytes)).getValue()); + } + + @ApiStatus.Internal + byte[] getNBTDataAsBytes(); } diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsBlockStateImpl.java b/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsBlockStateImpl.java index aabdf5c..b38bcca 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsBlockStateImpl.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsBlockStateImpl.java @@ -18,9 +18,11 @@ package net.momirealms.customcrops.api.core.world; import com.flowpowered.nbt.CompoundMap; +import com.flowpowered.nbt.CompoundTag; import com.flowpowered.nbt.Tag; import net.momirealms.customcrops.api.core.SynchronizedCompoundMap; import net.momirealms.customcrops.api.core.block.CustomCropsBlock; +import net.momirealms.customcrops.api.util.TagUtils; import org.jetbrains.annotations.NotNull; public class CustomCropsBlockStateImpl implements CustomCropsBlockState { @@ -39,6 +41,11 @@ public class CustomCropsBlockStateImpl implements CustomCropsBlockState { return owner; } + @Override + public byte[] getNBTDataAsBytes() { + return TagUtils.toBytes(new CompoundTag("data", compoundMap.originalMap())); + } + @Override public Tag set(String key, Tag tag) { return compoundMap.put(key, tag); diff --git a/api/src/main/java/net/momirealms/customcrops/api/util/TagUtils.java b/api/src/main/java/net/momirealms/customcrops/api/util/TagUtils.java new file mode 100644 index 0000000..9a92fa0 --- /dev/null +++ b/api/src/main/java/net/momirealms/customcrops/api/util/TagUtils.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) <2024> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.momirealms.customcrops.api.util; + +import com.flowpowered.nbt.Tag; +import com.flowpowered.nbt.stream.NBTInputStream; +import com.flowpowered.nbt.stream.NBTOutputStream; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.ByteOrder; + +public class TagUtils { + + public static Tag fromBytes(byte[] bytes) { + try { + NBTInputStream nbtInputStream = new NBTInputStream( + new ByteArrayInputStream(bytes), + NBTInputStream.NO_COMPRESSION, + ByteOrder.BIG_ENDIAN + ); + return nbtInputStream.readTag(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static byte[] toBytes(Tag tag) { + try { + ByteArrayOutputStream outByteStream = new ByteArrayOutputStream(); + NBTOutputStream outStream = new NBTOutputStream( + outByteStream, + NBTInputStream.NO_COMPRESSION, + ByteOrder.BIG_ENDIAN + ); + outStream.writeTag(tag); + return outByteStream.toByteArray(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/compatibility/build.gradle.kts b/compatibility/build.gradle.kts index 0e61b34..1960f0a 100644 --- a/compatibility/build.gradle.kts +++ b/compatibility/build.gradle.kts @@ -13,12 +13,14 @@ repositories { maven("https://nexus.betonquest.org/repository/betonquest/") // betonquest maven("https://repo.dmulloy2.net/repository/public/") // betonquest needs packet wrapper? maven("https://oss.sonatype.org/content/repositories/snapshots") + maven("https://repo.rapture.pw/repository/maven-releases/") // flow nbt } dependencies { compileOnly(project(":common")) compileOnly(project(":api")) compileOnly("dev.dejvokep:boosted-yaml:${rootProject.properties["boosted_yaml_version"]}") + compileOnly("com.flowpowered:flow-nbt:${rootProject.properties["flow_nbt_version"]}") compileOnly("net.kyori:adventure-api:${rootProject.properties["adventure_bundle_version"]}") { exclude(module = "adventure-bom") exclude(module = "checker-qual") diff --git a/compatibility/src/main/java/net/momirealms/customcrops/bukkit/integration/worldedit/CustomCropsDelegateExtent.java b/compatibility/src/main/java/net/momirealms/customcrops/bukkit/integration/worldedit/CustomCropsDelegateExtent.java new file mode 100644 index 0000000..147eadc --- /dev/null +++ b/compatibility/src/main/java/net/momirealms/customcrops/bukkit/integration/worldedit/CustomCropsDelegateExtent.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) <2024> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.momirealms.customcrops.bukkit.integration.worldedit; + +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.event.extent.EditSessionEvent; +import com.sk89q.worldedit.extent.AbstractDelegateExtent; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.block.BaseBlock; +import com.sk89q.worldedit.world.block.BlockStateHolder; +import net.momirealms.customcrops.api.BukkitCustomCropsPlugin; +import net.momirealms.customcrops.api.core.InternalRegistries; +import net.momirealms.customcrops.api.core.block.CustomCropsBlock; +import net.momirealms.customcrops.api.core.world.CustomCropsBlockState; +import net.momirealms.customcrops.api.core.world.CustomCropsWorld; +import net.momirealms.customcrops.api.core.world.Pos3; +import net.momirealms.customcrops.common.util.Key; + +import java.util.Optional; + +public class CustomCropsDelegateExtent extends AbstractDelegateExtent { + + private CustomCropsWorld world = null; + + protected CustomCropsDelegateExtent(EditSessionEvent editSessionEvent) { + super(editSessionEvent.getExtent()); + World weWorld = editSessionEvent.getWorld(); + if (weWorld == null) return; + Optional> optionalWorld = BukkitCustomCropsPlugin.getInstance().getWorldManager().getWorld(weWorld.getName()); + optionalWorld.ifPresent(customCropsWorld -> this.world = customCropsWorld); + } + + @Override + public > boolean setBlock(BlockVector3 location, T block) throws WorldEditException { + if (world != null) { + BaseBlock baseBlock = block.toBaseBlock(); + Pos3 pos3 = new Pos3(location.getBlockX(), location.getBlockY(), location.getBlockZ()); + world.removeBlockState(pos3); + CompoundTag tag = baseBlock.getNbtData(); + if (tag != null) { + String type = tag.getString("cc_type"); + if (type != null) { + Key key = Key.key(type); + CustomCropsBlock customCropsBlock = InternalRegistries.BLOCK.get(key); + if (customCropsBlock != null) { + byte[] bytes = tag.getByteArray("cc_data"); + if (bytes != null) { + CustomCropsBlockState state = CustomCropsBlockState.create(customCropsBlock, bytes); + world.addBlockState(pos3, state); + } + } + } + } + } + return super.setBlock(location, block); + } +} diff --git a/compatibility/src/main/java/net/momirealms/customcrops/bukkit/integration/worldedit/WorldEditHook.java b/compatibility/src/main/java/net/momirealms/customcrops/bukkit/integration/worldedit/WorldEditHook.java new file mode 100644 index 0000000..38eceff --- /dev/null +++ b/compatibility/src/main/java/net/momirealms/customcrops/bukkit/integration/worldedit/WorldEditHook.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) <2024> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.momirealms.customcrops.bukkit.integration.worldedit; + +public class WorldEditHook { + + private static WorldEditListener listener; + private static boolean registered; + + public static void register() { + if (registered) return; + try { + if (listener == null) { + listener = new WorldEditListener(); + } + listener.load(); + registered= true; + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static void unregister() { + if (!registered) return; + try { + if (listener != null) { + listener.unload(); + registered = false; + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/compatibility/src/main/java/net/momirealms/customcrops/bukkit/integration/worldedit/WorldEditListener.java b/compatibility/src/main/java/net/momirealms/customcrops/bukkit/integration/worldedit/WorldEditListener.java new file mode 100644 index 0000000..4afff31 --- /dev/null +++ b/compatibility/src/main/java/net/momirealms/customcrops/bukkit/integration/worldedit/WorldEditListener.java @@ -0,0 +1,254 @@ +/* + * Copyright (C) <2024> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.momirealms.customcrops.bukkit.integration.worldedit; + +import com.sk89q.jnbt.ByteArrayTag; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.StringTag; +import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.*; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.event.extent.EditSessionEvent; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.session.ClipboardHolder; +import com.sk89q.worldedit.session.SessionManager; +import com.sk89q.worldedit.util.eventbus.EventHandler; +import com.sk89q.worldedit.util.eventbus.Subscribe; +import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.block.BaseBlock; +import com.sk89q.worldedit.world.block.BlockState; +import net.momirealms.customcrops.api.BukkitCustomCropsPlugin; +import net.momirealms.customcrops.api.core.ConfigManager; +import net.momirealms.customcrops.api.core.world.CustomCropsBlockState; +import net.momirealms.customcrops.api.core.world.CustomCropsWorld; +import net.momirealms.customcrops.api.core.world.Pos3; +import net.momirealms.customcrops.api.util.PluginUtils; +import net.momirealms.customcrops.common.plugin.feature.Reloadable; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public class WorldEditListener implements Reloadable, Listener { + + private Constructor baseBlockConstructor; + + public WorldEditListener() { + try { + baseBlockConstructor = BaseBlock.class.getDeclaredConstructor(BlockState.class, CompoundTag.class); + baseBlockConstructor.setAccessible(true); +// if (PluginUtils.isEnabled("FastAsyncWorldEdit")) { +// BukkitCustomCropsPlugin.getInstance().getPluginLogger().info("FastAsyncWorldEdit detected. Don't forget to add `" + CustomCropsDelegateExtent.class.getCanonicalName() + "` to allowed-plugins."); +// } + } catch (ReflectiveOperationException e) { + BukkitCustomCropsPlugin.getInstance().getPluginLogger().warn("Not a supported WorldEdit version", e); + } + } + + @Override + public void unload() { + WorldEdit.getInstance().getEventBus().unregister(this); + HandlerList.unregisterAll(this); + } + + @Override + public void load() { + WorldEdit.getInstance().getEventBus().register(this); + Bukkit.getPluginManager().registerEvents(this, BukkitCustomCropsPlugin.getInstance().getBoostrap()); + } + + @Subscribe(priority = EventHandler.Priority.LATE) + public void onEditSession(EditSessionEvent event) { + if (!ConfigManager.worldeditSupport()) return; + if (event.getStage() != EditSession.Stage.BEFORE_CHANGE) { + return; + } + try { + event.setExtent(new CustomCropsDelegateExtent(event)); + } catch (Exception e) { + BukkitCustomCropsPlugin.getInstance().debug(e.getMessage()); + } + } + + @org.bukkit.event.EventHandler(ignoreCancelled = true) + private void onCommand(PlayerCommandPreprocessEvent event) { + if (!ConfigManager.worldeditSupport()) return; + String string = event.getMessage(); + if (string.startsWith("//copy")) { + Player player = event.getPlayer(); + BukkitCustomCropsPlugin.getInstance().getScheduler().sync().runLater(() -> + updateCopyClipBoard(player), 1, player.getLocation()); + } + + if (string.startsWith("//cut")) { + updateCutClipBoard(event.getPlayer()); + } + } + + public void updateCutClipBoard(Player player) { + com.sk89q.worldedit.entity.Player actor = BukkitAdapter.adapt(player); + SessionManager manager = WorldEdit.getInstance().getSessionManager(); + LocalSession localSession = manager.get(actor); + World world = actor.getWorld(); + Region region; + try { + region = localSession.getRegionSelector(world).getRegion(); + } catch (IncompleteRegionException e) { + return; + } + Optional> optionalWorld = BukkitCustomCropsPlugin.getInstance().getWorldManager().getWorld(world.getName()); + if (optionalWorld.isEmpty()) { + return; + } + CustomCropsWorld customWorld = optionalWorld.get(); + + HashMap tempMap = new HashMap<>(); + + BlockVector3 maxPoint = region.getMaximumPoint(); + BlockVector3 minPoint = region.getMinimumPoint(); + int minX = Math.min(minPoint.getBlockX(), maxPoint.getBlockX()); + int minY = Math.min(minPoint.getBlockY(), maxPoint.getBlockY()); + int minZ = Math.min(minPoint.getBlockZ(), maxPoint.getBlockZ()); + int maxX = Math.max(maxPoint.getBlockX(), minPoint.getBlockX()); + int maxY = Math.max(maxPoint.getBlockY(), minPoint.getBlockY()); + int maxZ = Math.max(maxPoint.getBlockZ(), minPoint.getBlockZ()); + for (int x = minX; x <= maxX; x++) { + for (int y = minY; y <= maxY; y++) { + for (int z = minZ; z <= maxZ; z++) { + Pos3 pos3 = new Pos3(x, y, z); + BlockVector3 vector3 = BlockVector3.at(x, y, z); + Optional optionalState = customWorld.getBlockState(pos3); + optionalState.ifPresent(customCropsBlockState -> tempMap.put(vector3, customCropsBlockState)); + } + } + } + + BukkitCustomCropsPlugin.getInstance().getScheduler().sync().runLater(() -> { + ClipboardHolder holder; + try { + holder = localSession.getClipboard(); + } catch (EmptyClipboardException e) { + return; + } + Clipboard clipboard = holder.getClipboard(); + for (Map.Entry entry : tempMap.entrySet()) { + BaseBlock baseBlock = clipboard.getFullBlock(entry.getKey()); + CustomCropsBlockState state = entry.getValue(); + CompoundTag tag = baseBlock.getNbtData(); + if (tag != null) { + Map map = tag.getValue(); + map.put("cc_type", new StringTag(state.type().type().asString())); + map.put("cc_data", new ByteArrayTag(state.getNBTDataAsBytes())); + } else { + try { + clipboard.setBlock(entry.getKey(), (BaseBlock) baseBlockConstructor.newInstance( + baseBlock.toImmutableState(), + new CompoundTag( + new HashMap<>( + Map.of( + "cc_type", new StringTag(state.type().type().asString()), + "cc_data", new ByteArrayTag(state.getNBTDataAsBytes()) + ) + ) + ) + )); + } catch (WorldEditException | InvocationTargetException | + InstantiationException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + } + }, 1, player.getLocation()); + } + + public void updateCopyClipBoard(Player player) { + com.sk89q.worldedit.entity.Player actor = BukkitAdapter.adapt(player); + SessionManager manager = WorldEdit.getInstance().getSessionManager(); + LocalSession localSession = manager.get(actor); + ClipboardHolder holder; + try { + holder = localSession.getClipboard(); + } catch (EmptyClipboardException e) { + return; + } + Clipboard clipboard = holder.getClipboard(); + + Region region = clipboard.getRegion(); + World world = region.getWorld(); + if (world == null) return; + + BukkitCustomCropsPlugin.getInstance().getWorldManager().getWorld(world.getName()) + .ifPresent(customWorld -> { + BukkitCustomCropsPlugin.getInstance().getScheduler().async().execute(() -> { + BlockVector3 maxPoint = region.getMaximumPoint(); + BlockVector3 minPoint = region.getMinimumPoint(); + int minX = Math.min(minPoint.getBlockX(), maxPoint.getBlockX()); + int minY = Math.min(minPoint.getBlockY(), maxPoint.getBlockY()); + int minZ = Math.min(minPoint.getBlockZ(), maxPoint.getBlockZ()); + int maxX = Math.max(maxPoint.getBlockX(), minPoint.getBlockX()); + int maxY = Math.max(maxPoint.getBlockY(), minPoint.getBlockY()); + int maxZ = Math.max(maxPoint.getBlockZ(), minPoint.getBlockZ()); + for (int x = minX; x <= maxX; x++) { + for (int y = minY; y <= maxY; y++) { + for (int z = minZ; z <= maxZ; z++) { + Pos3 pos3 = new Pos3(x, y, z); + BlockVector3 vector3 = BlockVector3.at(x, y, z); + Optional optionalState = customWorld.getBlockState(pos3); + if (optionalState.isPresent()) { + BaseBlock baseBlock = clipboard.getFullBlock(vector3); + CustomCropsBlockState state = optionalState.get(); + CompoundTag tag = baseBlock.getNbtData(); + if (tag != null) { + Map map = tag.getValue(); + map.put("cc_type", new StringTag(state.type().type().asString())); + map.put("cc_data", new ByteArrayTag(state.getNBTDataAsBytes())); + } else { + try { + clipboard.setBlock(vector3, (BaseBlock) baseBlockConstructor.newInstance( + baseBlock.toImmutableState(), + new CompoundTag( + new HashMap<>( + Map.of( + "cc_type", new StringTag(state.type().type().asString()), + "cc_data", new ByteArrayTag(state.getNBTDataAsBytes()) + ) + ) + ) + )); + } catch (WorldEditException | InvocationTargetException | + InstantiationException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + } + } + } + } + }); + }); + } +} diff --git a/gradle.properties b/gradle.properties index 1c46bf8..d756763 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # Project settings # Rule: [major update].[feature update].[bug fix] -project_version=3.6.4 -config_version=38 +project_version=3.6.5 +config_version=39 project_group=net.momirealms # Dependency settings diff --git a/plugin/src/main/java/net/momirealms/customcrops/bukkit/BukkitCustomCropsPluginImpl.java b/plugin/src/main/java/net/momirealms/customcrops/bukkit/BukkitCustomCropsPluginImpl.java index 42b1617..9e84467 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/bukkit/BukkitCustomCropsPluginImpl.java +++ b/plugin/src/main/java/net/momirealms/customcrops/bukkit/BukkitCustomCropsPluginImpl.java @@ -33,11 +33,14 @@ import net.momirealms.customcrops.api.misc.HologramManager; import net.momirealms.customcrops.api.misc.cooldown.CoolDownManager; import net.momirealms.customcrops.api.misc.placeholder.BukkitPlaceholderManager; import net.momirealms.customcrops.api.util.EventUtils; +import net.momirealms.customcrops.api.util.PluginUtils; import net.momirealms.customcrops.bukkit.action.BlockActionManager; import net.momirealms.customcrops.bukkit.action.PlayerActionManager; import net.momirealms.customcrops.bukkit.command.BukkitCommandManager; import net.momirealms.customcrops.bukkit.config.BukkitConfigManager; import net.momirealms.customcrops.bukkit.integration.BukkitIntegrationManager; +import net.momirealms.customcrops.bukkit.integration.worldedit.CustomCropsDelegateExtent; +import net.momirealms.customcrops.bukkit.integration.worldedit.WorldEditHook; import net.momirealms.customcrops.bukkit.item.BukkitItemManager; import net.momirealms.customcrops.bukkit.requirement.BlockRequirementManager; import net.momirealms.customcrops.bukkit.requirement.PlayerRequirementManager; @@ -191,21 +194,18 @@ public class BukkitCustomCropsPluginImpl extends BukkitCustomCropsPlugin { }); } + Runnable delayedInitTask = () -> { + ((SimpleRegistryAccess) registryAccess).freeze(); + logger.info("Registry access has been frozen"); + ((BukkitItemManager) itemManager).setAntiGriefLib(AntiGriefLib.builder((JavaPlugin) getBoostrap()).silentLogs(true).ignoreOP(true).build()); + EventUtils.fireAndForget(new CustomCropsReloadEvent(this)); + }; + // delayed init task if (VersionHelper.isFolia()) { - Bukkit.getGlobalRegionScheduler().run(getBoostrap(), (scheduledTask) -> { - ((SimpleRegistryAccess) registryAccess).freeze(); - logger.info("Registry access has been frozen"); - ((BukkitItemManager) itemManager).setAntiGriefLib(AntiGriefLib.builder((JavaPlugin) getBoostrap()).silentLogs(true).ignoreOP(true).build()); - EventUtils.fireAndForget(new CustomCropsReloadEvent(this)); - }); + Bukkit.getGlobalRegionScheduler().run(getBoostrap(), (scheduledTask) -> delayedInitTask.run()); } else { - Bukkit.getScheduler().runTask(getBoostrap(), () -> { - ((SimpleRegistryAccess) registryAccess).freeze(); - logger.info("Registry access has been frozen"); - ((BukkitItemManager) itemManager).setAntiGriefLib(AntiGriefLib.builder((JavaPlugin) getBoostrap()).silentLogs(false).ignoreOP(true).build()); - EventUtils.fireAndForget(new CustomCropsReloadEvent(this)); - }); + Bukkit.getScheduler().runTask(getBoostrap(), delayedInitTask); } } @@ -236,6 +236,11 @@ public class BukkitCustomCropsPluginImpl extends BukkitCustomCropsPlugin { this.worldManager.load(); + if (ConfigManager.worldeditSupport() && PluginUtils.isEnabled("WorldEdit")) { + WorldEditHook.register(); + } else { + WorldEditHook.unregister(); + } EventUtils.fireAndForget(new CustomCropsReloadEvent(this)); } diff --git a/plugin/src/main/java/net/momirealms/customcrops/bukkit/config/BukkitConfigManager.java b/plugin/src/main/java/net/momirealms/customcrops/bukkit/config/BukkitConfigManager.java index 83f7884..755652d 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/bukkit/config/BukkitConfigManager.java +++ b/plugin/src/main/java/net/momirealms/customcrops/bukkit/config/BukkitConfigManager.java @@ -140,6 +140,8 @@ public class BukkitConfigManager extends ConfigManager { preventTrampling = config.getBoolean("mechanics.vanilla-farmland.prevent-trampling", false); disableMoistureMechanic = config.getBoolean("mechanics.vanilla-farmland.disable-moisture-mechanic", false); + worldeditSupport = config.getBoolean("other-settings.worldedit-support", false); + offsets.clear(); Section section = config.getSection("mechanics.hologram-offset-correction"); if (section != null) { diff --git a/plugin/src/main/java/net/momirealms/customcrops/bukkit/integration/BukkitIntegrationManager.java b/plugin/src/main/java/net/momirealms/customcrops/bukkit/integration/BukkitIntegrationManager.java index 69c7537..b9a0508 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/bukkit/integration/BukkitIntegrationManager.java +++ b/plugin/src/main/java/net/momirealms/customcrops/bukkit/integration/BukkitIntegrationManager.java @@ -57,6 +57,7 @@ public class BukkitIntegrationManager implements IntegrationManager { @Override public void disable() { this.levelerProviders.clear(); + this.entityProviders.clear(); } @Override @@ -126,6 +127,24 @@ public class BukkitIntegrationManager implements IntegrationManager { } } + private boolean doesPluginExists(String hooked) { + return Bukkit.getPluginManager().getPlugin(hooked) != null; + } + + @SuppressWarnings("deprecation") + private boolean doesPluginExists(String hooked, String... versionPrefix) { + Plugin p = Bukkit.getPluginManager().getPlugin(hooked); + if (p != null) { + String ver = p.getDescription().getVersion(); + for (String prefix : versionPrefix) { + if (ver.startsWith(prefix)) { + return true; + } + } + } + return false; + } + private boolean isHooked(String hooked) { if (Bukkit.getPluginManager().getPlugin(hooked) != null) { plugin.getPluginLogger().info(hooked + " hooked!"); diff --git a/plugin/src/main/resources/config.yml b/plugin/src/main/resources/config.yml index 8e0721b..86659b7 100644 --- a/plugin/src/main/resources/config.yml +++ b/plugin/src/main/resources/config.yml @@ -141,3 +141,5 @@ other-settings: # Whether to verify if a block/furniture matches the data in CustomCrops # Enable this if using Oraxen, as its API is more reliable double-check: false + # Enable WorldEdit support (Experimental) + worldedit-support: false diff --git a/plugin/src/main/resources/plugin.yml b/plugin/src/main/resources/plugin.yml index c45847b..80d0445 100644 --- a/plugin/src/main/resources/plugin.yml +++ b/plugin/src/main/resources/plugin.yml @@ -16,4 +16,5 @@ softdepend: - RealisticSeasons - AdvancedSeasons - SlimeWorldManager - - MythicMobs \ No newline at end of file + - MythicMobs + - WorldEdit \ No newline at end of file