9
0
mirror of https://github.com/Xiao-MoMi/Custom-Crops.git synced 2025-12-19 15:09:25 +00:00

WorldEdit support

This commit is contained in:
XiaoMoMi
2024-09-07 23:54:36 +08:00
parent 6ca6281507
commit d4a40f5b5c
15 changed files with 511 additions and 15 deletions

View File

@@ -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);
}
}

View File

@@ -91,6 +91,8 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable {
protected HashSet<Material> 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, '.');

View File

@@ -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();
}

View File

@@ -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);

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) <2024> <XiaoMoMi>
*
* 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 <https://www.gnu.org/licenses/>.
*/
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);
}
}
}

View File

@@ -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")

View File

@@ -0,0 +1,74 @@
/*
* Copyright (C) <2024> <XiaoMoMi>
*
* 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 <https://www.gnu.org/licenses/>.
*/
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<CustomCropsWorld<?>> optionalWorld = BukkitCustomCropsPlugin.getInstance().getWorldManager().getWorld(weWorld.getName());
optionalWorld.ifPresent(customCropsWorld -> this.world = customCropsWorld);
}
@Override
public <T extends BlockStateHolder<T>> 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);
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (C) <2024> <XiaoMoMi>
*
* 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 <https://www.gnu.org/licenses/>.
*/
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();
}
}
}

View File

@@ -0,0 +1,254 @@
/*
* Copyright (C) <2024> <XiaoMoMi>
*
* 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 <https://www.gnu.org/licenses/>.
*/
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<CustomCropsWorld<?>> optionalWorld = BukkitCustomCropsPlugin.getInstance().getWorldManager().getWorld(world.getName());
if (optionalWorld.isEmpty()) {
return;
}
CustomCropsWorld<?> customWorld = optionalWorld.get();
HashMap<BlockVector3, CustomCropsBlockState> 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<CustomCropsBlockState> 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<BlockVector3, CustomCropsBlockState> entry : tempMap.entrySet()) {
BaseBlock baseBlock = clipboard.getFullBlock(entry.getKey());
CustomCropsBlockState state = entry.getValue();
CompoundTag tag = baseBlock.getNbtData();
if (tag != null) {
Map<String, Tag> 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<CustomCropsBlockState> optionalState = customWorld.getBlockState(pos3);
if (optionalState.isPresent()) {
BaseBlock baseBlock = clipboard.getFullBlock(vector3);
CustomCropsBlockState state = optionalState.get();
CompoundTag tag = baseBlock.getNbtData();
if (tag != null) {
Map<String, Tag> 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);
}
}
}
}
}
}
});
});
}
}

View File

@@ -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

View File

@@ -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));
}

View File

@@ -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) {

View File

@@ -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!");

View File

@@ -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

View File

@@ -16,4 +16,5 @@ softdepend:
- RealisticSeasons
- AdvancedSeasons
- SlimeWorldManager
- MythicMobs
- MythicMobs
- WorldEdit