
com.sk89q.worldedit.bukkit.WorldEditPlugin Maven / Gradle / Ivy
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q
* Copyright (C) WorldEdit team and contributors
*
* 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
* (at your option) 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 com.sk89q.worldedit.bukkit;
import com.fastasyncworldedit.bukkit.BukkitPermissionAttachmentManager;
import com.fastasyncworldedit.bukkit.FaweBukkit;
import com.fastasyncworldedit.core.util.UpdateNotification;
import com.fastasyncworldedit.core.Fawe;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.sk89q.bukkit.util.ClassSourceValidator;
import com.sk89q.util.yaml.YAMLProcessor;
import com.sk89q.wepif.PermissionsResolverManager;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.bukkit.adapter.AdapterLoadException;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplLoader;
import com.sk89q.worldedit.event.platform.CommandEvent;
import com.sk89q.worldedit.event.platform.CommandSuggestionEvent;
import com.sk89q.worldedit.event.platform.PlatformReadyEvent;
import com.sk89q.worldedit.event.platform.PlatformUnreadyEvent;
import com.sk89q.worldedit.event.platform.PlatformsRegisteredEvent;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.internal.anvil.ChunkDeleter;
import com.sk89q.worldedit.internal.command.CommandUtil;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.util.lifecycle.Lifecycled;
import com.sk89q.worldedit.util.lifecycle.SimpleLifecycled;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockCategory;
import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.gamemode.GameModes;
import com.sk89q.worldedit.world.item.ItemCategory;
import com.sk89q.worldedit.world.weather.WeatherTypes;
import io.papermc.lib.PaperLib;
import org.apache.logging.log4j.Logger;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.Tag;
import org.bukkit.block.Biome;
import org.bukkit.command.BlockCommandSender;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.enginehub.piston.CommandManager;
import org.incendo.serverlib.ServerLib;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.worldedit.internal.anvil.ChunkDeleter.DELCHUNKS_FILE_NAME;
/**
* Plugin for Bukkit.
*/
//FAWE start - Don't implement TabCompleter, we use Paper's AsyncTabCompleteListener
public class WorldEditPlugin extends JavaPlugin {
//FAWE end
private static final Logger LOGGER = LogManagerCompat.getLogger();
public static final String CUI_PLUGIN_CHANNEL = "worldedit:cui";
private static WorldEditPlugin INSTANCE;
private static final int BSTATS_ID = 1403;
private final SimpleLifecycled adapter =
SimpleLifecycled.invalid();
private BukkitServerInterface platform;
private BukkitConfiguration config;
private BukkitPermissionAttachmentManager permissionAttachmentManager;
@Override
public void onLoad() {
//FAWE start
// This is already covered by Spigot, however, a more pesky warning with a proper explanation over "Ambiguous plugin name..." can't hurt.
Plugin[] plugins = Bukkit.getServer().getPluginManager().getPlugins();
for (Plugin p : plugins) {
if (p.getName().equals("WorldEdit")) {
LOGGER.warn(
"You installed WorldEdit alongside FastAsyncWorldEdit. That is unneeded and will cause unforeseen issues, " +
"because FastAsyncWorldEdit already provides WorldEdit. " +
"Stop your server and delete the 'worldedit-bukkit' jar from your plugins folder.");
}
}
//FAWE end
INSTANCE = this;
//noinspection ResultOfMethodCallIgnored
getDataFolder().mkdirs();
WorldEdit worldEdit = WorldEdit.getInstance();
// Setup platform
platform = new BukkitServerInterface(this, getServer());
worldEdit.getPlatformManager().register(platform);
//FAWE start - Migrate from config-legacy to worldedit-config
migrateLegacyConfig();
//FAWE end
//FAWE start - Modify WorldEdit config name
config = new BukkitConfiguration(new YAMLProcessor(new File(getDataFolder(), "worldedit-config.yml"), true), this);
//FAWE end
//FAWE start - Setup permission attachments
permissionAttachmentManager = new BukkitPermissionAttachmentManager(this);
//FAWE end
Path delChunks = Paths.get(getDataFolder().getPath(), DELCHUNKS_FILE_NAME);
if (Files.exists(delChunks)) {
ChunkDeleter.runFromFile(delChunks, true);
}
//FAWE start - Delete obsolete DummyFawe from pre 1.14 days
if (this.getDataFolder().getParentFile().listFiles(file -> {
if (file.getName().equals("DummyFawe.jar")) {
file.delete();
return true;
}
return false;
}).length > 0) {
LOGGER.warn("DummyFawe detected and automatically deleted! This file is no longer necessary.");
}
//FAWE end
}
/**
* Called on plugin enable.
*/
@Override
public void onEnable() {
// Catch bad things being done by naughty plugins that include
// WorldEdit's classes
ClassSourceValidator verifier = new ClassSourceValidator(this);
verifier.reportMismatches(ImmutableList.of(World.class, CommandManager.class, EditSession.class, Actor.class));
//FAWE start
new FaweBukkit(this);
//FAWE end
config.load(); // Load config before we say we've loaded platforms as it is used in listeners of the event
WorldEdit.getInstance().getEventBus().post(new PlatformsRegisteredEvent());
PermissionsResolverManager.initialize(this); // Setup permission resolver
// Register CUI
getServer().getMessenger().registerIncomingPluginChannel(this, CUI_PLUGIN_CHANNEL, new CUIChannelListener(this));
getServer().getMessenger().registerOutgoingPluginChannel(this, CUI_PLUGIN_CHANNEL);
// Now we can register events
getServer().getPluginManager().registerEvents(new WorldEditListener(this), this);
// register async tab complete, if available
if (PaperLib.isPaper()) {
getServer().getPluginManager().registerEvents(new AsyncTabCompleteListener(), this);
}
initializeRegistries(); // this creates the objects matching Bukkit's enums - but doesn't fill them with data yet
if (Bukkit.getWorlds().isEmpty()) {
setupPreWorldData();
// register this so we can load world-dependent data right as the first world is loading
getServer().getPluginManager().registerEvents(new WorldInitListener(), this);
} else {
//FAWE start
LOGGER.warn(
"Server reload detected. This may cause various issues with FastAsyncWorldEdit and dependent plugins. Reloading the server is not advised.");
LOGGER.warn("For more information why reloading is bad, see https://madelinemiller.dev/blog/problem-with-reload/");
//FAWE end
try {
setupPreWorldData();
// since worlds are loaded already, we can do this now
setupWorldData();
} catch (Throwable ignored) {
}
}
// Enable metrics
new Metrics(this, BSTATS_ID);
// Check if we are in a safe environment
ServerLib.checkUnsafeForks();
// Check if a new build is available
UpdateNotification.doUpdateCheck();
}
private void setupPreWorldData() {
loadAdapter();
WorldEdit.getInstance().loadMappings();
}
private void setupWorldData() {
// datapacks aren't loaded until just before the world is, and bukkit has no event for this
// so the earliest we can do this is in WorldInit
setupTags();
setupBiomes(false); // FAWE - load biomes later. Initialize biomes twice to allow for the registry to be present for
// plugins requiring WE biomes during startup, as well as allowing custom biomes loaded later on to be present in WE.
WorldEdit.getInstance().getEventBus().post(new PlatformReadyEvent(platform));
}
@SuppressWarnings({"deprecation", "unchecked"})
private void initializeRegistries() {
// FAWE start - move Biomes to their own method. Initialize biomes twice to allow for the registry to be present for
// plugins requiring WE biomes during startup, as well as allowing custom biomes loaded later on to be present in WE.
setupBiomes(true);
// FAWE end
/*
// Block & Item
for (Material material : Material.values()) {
if (material.isBlock() && !material.isLegacy()) {
BlockType.REGISTRY.register(material.getKey().toString(), new BlockType(material.getKey().toString(), blockState -> {
// TODO Use something way less hacky than this.
ParserContext context = new ParserContext();
context.setPreferringWildcard(true);
context.setTryLegacy(false);
context.setRestricted(false);
try {
FuzzyBlockState state = (FuzzyBlockState) WorldEdit.getInstance().getBlockFactory().parseFromInput(
BukkitAdapter.adapt(blockState.getBlockType()).createBlockData().getAsString(), context
).toImmutableState();
BlockState defaultState = blockState.getBlockType().getAllStates().get(0);
for (Map.Entry, Object> propertyObjectEntry : state.getStates().entrySet()) {
//noinspection unchecked
defaultState = defaultState.with((Property
© 2015 - 2025 Weber Informatics LLC | Privacy Policy