FastAsyncWorldedit/bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java

432 lines
17 KiB
Java
Raw Normal View History

package com.boydti.fawe.bukkit;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.IFawe;
import com.boydti.fawe.bukkit.regions.FactionsFeature;
2016-04-21 07:53:37 +02:00
import com.boydti.fawe.bukkit.regions.FactionsOneFeature;
import com.boydti.fawe.bukkit.regions.FactionsUUIDFeature;
import com.boydti.fawe.bukkit.regions.GriefPreventionFeature;
import com.boydti.fawe.bukkit.regions.PlotMeFeature;
import com.boydti.fawe.bukkit.regions.PreciousStonesFeature;
import com.boydti.fawe.bukkit.regions.ResidenceFeature;
import com.boydti.fawe.bukkit.regions.TownyFeature;
import com.boydti.fawe.bukkit.regions.Worldguard;
2016-04-21 17:41:54 +02:00
import com.boydti.fawe.bukkit.v0.BukkitQueue_All;
import com.boydti.fawe.bukkit.v0.ChunkListener;
2016-08-10 09:36:28 +02:00
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweCommand;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.regions.FaweMaskManager;
import com.boydti.fawe.util.MainUtil;
2016-04-22 18:11:46 +02:00
import com.boydti.fawe.util.ReflectionUtils;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
2016-09-20 10:46:49 +02:00
import com.sk89q.worldedit.bukkit.EditSessionBlockChangeDelegate;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
2016-04-23 22:41:07 +02:00
import com.sk89q.worldedit.world.World;
2016-04-02 07:58:42 +02:00
import java.io.File;
2016-12-27 13:28:43 +01:00
import java.io.FileOutputStream;
2016-04-22 18:11:46 +02:00
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
2016-12-27 13:28:43 +01:00
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
2016-04-02 07:58:42 +02:00
import java.util.ArrayList;
import java.util.Collection;
import java.util.UUID;
2016-04-02 07:58:42 +02:00
import org.bukkit.Bukkit;
2016-08-10 09:36:28 +02:00
import org.bukkit.command.ConsoleCommandSender;
2016-04-02 07:58:42 +02:00
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.ChunkPopulateEvent;
import org.bukkit.event.world.ChunkUnloadEvent;
2016-04-02 07:58:42 +02:00
import org.bukkit.plugin.Plugin;
import org.primesoft.blockshub.BlocksHubBukkit;
public class FaweBukkit implements IFawe, Listener {
2016-03-31 11:23:10 +02:00
private final BukkitMain plugin;
private VaultUtil vault;
private WorldEditPlugin worldedit;
2016-03-31 11:23:10 +02:00
public VaultUtil getVault() {
2016-03-31 11:23:10 +02:00
return this.vault;
}
2016-03-31 11:23:10 +02:00
public WorldEditPlugin getWorldEditPlugin() {
2016-03-31 11:23:10 +02:00
if (this.worldedit == null) {
this.worldedit = (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit");
}
2016-03-31 11:23:10 +02:00
return this.worldedit;
}
2016-03-31 11:23:10 +02:00
public FaweBukkit(BukkitMain plugin) {
this.plugin = plugin;
try {
Fawe.set(this);
setupInjector();
2017-03-05 17:19:14 +01:00
com.sk89q.worldedit.bukkit.BukkitPlayer.inject();
new BrushListener(plugin);
if (Bukkit.getVersion().contains("git-Spigot")) {
debug("====== USE PAPER ======");
2016-06-18 06:19:56 +02:00
debug("DOWNLOAD: https://ci.destroystokyo.com/job/PaperSpigot/");
2016-04-22 18:11:46 +02:00
debug("GUIDE: https://www.spigotmc.org/threads/21726/");
debug(" - This is only a recommendation");
debug("==============================");
}
2016-04-02 07:58:42 +02:00
} catch (final Throwable e) {
MainUtil.handleError(e);
Bukkit.getServer().shutdown();
}
TaskManager.IMP.task(new Runnable() {
@Override
public void run() {
Bukkit.getPluginManager().registerEvents(FaweBukkit.this, FaweBukkit.this.plugin);
new ChunkListener();
}
});
}
public void setupInjector() {
2016-12-27 13:28:43 +01:00
if (Bukkit.getPluginManager().getPlugin("WorldEdit") == null) {
try {
File output = new File(getDirectory().getParentFile(), "WorldEdit.jar");
2017-02-18 10:54:15 +01:00
URL worldEditUrl = new URL("http://builds.enginehub.org/job/worldedit/9672/download/worldedit-bukkit-6.1.7-SNAPSHOT-dist.jar");
2016-12-27 13:28:43 +01:00
try (ReadableByteChannel rbc = Channels.newChannel(worldEditUrl.openStream())) {
try (FileOutputStream fos = new FileOutputStream(output)) {
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
}
}
Bukkit.getPluginManager().loadPlugin(output);
} catch (Throwable e) {
e.printStackTrace();
Fawe.debug("====== INSTALL WORLDEDIT ======");
Fawe.debug("FAWE requires WorldEdit to function correctly");
Fawe.debug("Info: https://github.com/boy0001/FastAsyncWorldedit/releases/");
Fawe.debug("===============================");
return;
}
}
2016-12-27 13:28:43 +01:00
Fawe.setupInjector();
// Inject
EditSessionBlockChangeDelegate.inject();
}
2016-03-31 11:23:10 +02:00
@Override
public void debug(final String s) {
2016-08-10 09:36:28 +02:00
ConsoleCommandSender console = Bukkit.getConsoleSender();
if (console != null) {
console.sendMessage(BBC.color(s));
} else {
Bukkit.getLogger().info(BBC.color(s));
}
}
2016-03-31 11:23:10 +02:00
@Override
public File getDirectory() {
return plugin.getDataFolder();
}
2016-03-31 11:23:10 +02:00
@Override
public void setupCommand(final String label, final FaweCommand cmd) {
plugin.getCommand(label).setExecutor(new BukkitCommand(cmd));
}
2016-03-31 11:23:10 +02:00
@Override
public FawePlayer<Player> wrap(final Object obj) {
if (obj.getClass() == String.class) {
String name = (String) obj;
FawePlayer existing = Fawe.get().getCachedPlayer(name);
if (existing != null) {
return existing;
}
return new BukkitPlayer(Bukkit.getPlayer(name));
} else if (obj instanceof Player) {
Player player = (Player) obj;
FawePlayer existing = Fawe.get().getCachedPlayer(player.getName());
return existing != null ? existing : new BukkitPlayer(player);
} else {
return null;
}
}
2016-03-31 11:23:10 +02:00
2016-04-02 07:58:42 +02:00
@Override
public void startMetrics() {
Metrics metrics = new Metrics(plugin);
2016-04-02 07:58:42 +02:00
metrics.start();
}
/**
* Vault isn't required, but used for setting player permissions (WorldEdit bypass)
* @return
*/
@Override
public void setupVault() {
try {
2016-03-31 11:23:10 +02:00
this.vault = new VaultUtil();
} catch (final Throwable e) {
2016-12-12 07:37:16 +01:00
this.debug("&dVault is used for persistent `/wea` toggles.");
}
}
2016-03-31 11:23:10 +02:00
/**
* The task manager handles sync/async tasks
*/
@Override
public TaskManager getTaskManager() {
return new BukkitTaskMan(plugin);
}
2016-03-31 11:23:10 +02:00
2016-04-13 12:04:01 +02:00
private int[] version;
2016-04-21 17:41:54 +02:00
private boolean hasNMS = true;
private boolean playerChunk = false;
2016-04-21 17:41:54 +02:00
@Override
public FaweQueue getNewQueue(String world, boolean fast) {
if (playerChunk != (playerChunk = true)) {
try {
Field fieldDirtyCount = ReflectionUtils.getRefClass("{nms}.PlayerChunk").getField("dirtyCount").getRealField();
fieldDirtyCount.setAccessible(true);
int mod = fieldDirtyCount.getModifiers();
if ((mod & Modifier.VOLATILE) == 0) {
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(fieldDirtyCount, mod + Modifier.VOLATILE);
}
} catch (Throwable ignore) {}
}
try {
return plugin.getQueue(world);
2016-09-29 22:12:08 +02:00
} catch (Throwable ignore) {
// Disable incompatible settings
Settings.IMP.QUEUE.PARALLEL_THREADS = 1; // BukkitAPI placer is too slow to parallel thread at the chunk level
Settings.IMP.HISTORY.COMBINE_STAGES = false; // Performing a chunk copy (if possible) wouldn't be faster using the BukkitAPI
2016-09-29 22:12:08 +02:00
if (hasNMS) {
ignore.printStackTrace();
debug("====== NO NMS BLOCK PLACER FOUND ======");
debug("FAWE couldn't find a fast block placer");
debug("Bukkit version: " + Bukkit.getVersion());
debug("NMS label: " + plugin.getClass().getSimpleName().split("_")[1]);
debug("Fallback placer: " + BukkitQueue_All.class);
debug("=======================================");
debug("Download the version of FAWE for your platform");
debug(" - http://ci.athion.net/job/FastAsyncWorldEdit/lastSuccessfulBuild/artifact/target");
debug("=======================================");
TaskManager.IMP.laterAsync(new Runnable() {
@Override
public void run() {
MainUtil.sendAdmin("&cNo NMS placer found, see console!");
}
}, 1);
hasNMS = false;
}
return new BukkitQueue_All(world);
}
}
/**
* The FaweQueue is a core part of block placement<br>
* - The queue returned here is used in the SetQueue class (SetQueue handles the implementation specific queue)<br>
* - Block changes are grouped by chunk (as it's more efficient for lighting/packet sending)<br>
* - The FaweQueue returned here will provide the wrapper around the chunk object (FaweChunk)<br>
* - When a block change is requested, the SetQueue will first check if the chunk exists in the queue, or it will create and add it<br>
*/
@Override
public FaweQueue getNewQueue(World world, boolean fast) {
if (fast) {
if (playerChunk != (playerChunk = true)) {
try {
Field fieldDirtyCount = ReflectionUtils.getRefClass("{nms}.PlayerChunk").getField("dirtyCount").getRealField();
fieldDirtyCount.setAccessible(true);
int mod = fieldDirtyCount.getModifiers();
if ((mod & Modifier.VOLATILE) == 0) {
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(fieldDirtyCount, mod + Modifier.VOLATILE);
}
} catch (Throwable ignore) {
}
}
try {
return plugin.getQueue(world);
} catch (Throwable ignore) {
}
// Disable incompatible settings
Settings.IMP.QUEUE.PARALLEL_THREADS = 1; // BukkitAPI placer is too slow to parallel thread at the chunk level
Settings.IMP.HISTORY.COMBINE_STAGES = false; // Performing a chunk copy (if possible) wouldn't be faster using the BukkitAPI
if (hasNMS) {
debug("====== NO NMS BLOCK PLACER FOUND ======");
debug("FAWE couldn't find a fast block placer");
debug("Bukkit version: " + Bukkit.getVersion());
debug("NMS label: " + plugin.getClass().getSimpleName().split("_")[1]);
debug("Fallback placer: " + BukkitQueue_All.class);
debug("=======================================");
debug("Download the version of FAWE for your platform");
debug(" - http://ci.athion.net/job/FastAsyncWorldEdit/lastSuccessfulBuild/artifact/target");
debug("=======================================");
TaskManager.IMP.laterAsync(new Runnable() {
@Override
public void run() {
MainUtil.sendAdmin("&cNo NMS placer found, see console!");
}
}, 1);
hasNMS = false;
}
2016-03-02 22:51:41 +01:00
}
return new BukkitQueue_All(world);
}
2016-03-31 11:23:10 +02:00
public BukkitMain getPlugin() {
return plugin;
}
2016-04-23 22:41:07 +02:00
@Override
public String getWorldName(World world) {
return world.getName();
}
/**
* A mask manager handles region restrictions e.g. PlotSquared plots / WorldGuard regions
*/
@Override
public Collection<FaweMaskManager> getMaskManagers() {
final Plugin worldguardPlugin = Bukkit.getServer().getPluginManager().getPlugin("WorldGuard");
final ArrayList<FaweMaskManager> managers = new ArrayList<>();
if ((worldguardPlugin != null) && worldguardPlugin.isEnabled()) {
2016-02-09 11:15:03 +01:00
try {
managers.add(new Worldguard(worldguardPlugin, this));
Fawe.debug("Plugin 'WorldGuard' found. Using it now.");
2016-03-31 11:23:10 +02:00
} catch (final Throwable e) {
MainUtil.handleError(e);
2016-02-09 11:15:03 +01:00
}
}
final Plugin plotmePlugin = Bukkit.getServer().getPluginManager().getPlugin("PlotMe");
if ((plotmePlugin != null) && plotmePlugin.isEnabled()) {
2016-02-09 11:15:03 +01:00
try {
managers.add(new PlotMeFeature(plotmePlugin, this));
Fawe.debug("Plugin 'PlotMe' found. Using it now.");
2016-03-31 11:23:10 +02:00
} catch (final Throwable e) {
MainUtil.handleError(e);
2016-02-09 11:15:03 +01:00
}
}
final Plugin townyPlugin = Bukkit.getServer().getPluginManager().getPlugin("Towny");
if ((townyPlugin != null) && townyPlugin.isEnabled()) {
2016-02-09 11:15:03 +01:00
try {
managers.add(new TownyFeature(townyPlugin, this));
Fawe.debug("Plugin 'Towny' found. Using it now.");
2016-03-31 11:23:10 +02:00
} catch (final Throwable e) {
MainUtil.handleError(e);
2016-02-09 11:15:03 +01:00
}
}
final Plugin factionsPlugin = Bukkit.getServer().getPluginManager().getPlugin("Factions");
if ((factionsPlugin != null) && factionsPlugin.isEnabled()) {
try {
managers.add(new FactionsFeature(factionsPlugin, this));
Fawe.debug("Plugin 'Factions' found. Using it now.");
} catch (final Throwable e) {
2016-04-21 07:53:37 +02:00
try {
managers.add(new FactionsUUIDFeature(factionsPlugin, this));
Fawe.debug("Plugin 'FactionsUUID' found. Using it now.");
} catch (Throwable e2) {
try {
managers.add(new FactionsOneFeature(factionsPlugin, this));
Fawe.debug("Plugin 'FactionsUUID' found. Using it now.");
} catch (Throwable e3) {
MainUtil.handleError(e);
2016-04-21 07:53:37 +02:00
}
}
}
}
final Plugin residencePlugin = Bukkit.getServer().getPluginManager().getPlugin("Residence");
if ((residencePlugin != null) && residencePlugin.isEnabled()) {
2016-02-09 11:15:03 +01:00
try {
managers.add(new ResidenceFeature(residencePlugin, this));
Fawe.debug("Plugin 'Residence' found. Using it now.");
2016-03-31 11:23:10 +02:00
} catch (final Throwable e) {
MainUtil.handleError(e);
2016-02-09 11:15:03 +01:00
}
}
final Plugin griefpreventionPlugin = Bukkit.getServer().getPluginManager().getPlugin("GriefPrevention");
if ((griefpreventionPlugin != null) && griefpreventionPlugin.isEnabled()) {
2016-02-09 11:15:03 +01:00
try {
managers.add(new GriefPreventionFeature(griefpreventionPlugin, this));
Fawe.debug("Plugin 'GriefPrevention' found. Using it now.");
2016-03-31 11:23:10 +02:00
} catch (final Throwable e) {
MainUtil.handleError(e);
2016-02-09 11:15:03 +01:00
}
}
final Plugin preciousstonesPlugin = Bukkit.getServer().getPluginManager().getPlugin("PreciousStones");
if ((preciousstonesPlugin != null) && preciousstonesPlugin.isEnabled()) {
2016-02-09 11:15:03 +01:00
try {
managers.add(new PreciousStonesFeature(preciousstonesPlugin, this));
Fawe.debug("Plugin 'PreciousStones' found. Using it now.");
2016-03-31 11:23:10 +02:00
} catch (final Throwable e) {
MainUtil.handleError(e);
2016-02-09 11:15:03 +01:00
}
}
return managers;
}
@EventHandler
public void onChunkLoad(ChunkLoadEvent event) {
SetQueue.IMP.runMiscTasks();
}
@EventHandler
public void onChunkUnload(ChunkUnloadEvent event) {
SetQueue.IMP.runMiscTasks();
}
@EventHandler
public void onChunkPopulate(ChunkPopulateEvent event) {
SetQueue.IMP.runMiscTasks();
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
FawePlayer fp = FawePlayer.wrap(player);
2017-02-04 07:44:33 +01:00
if (fp != null) {
fp.unregister();
}
Fawe.get().unregister(event.getPlayer().getName());
}
2016-04-20 20:22:47 +02:00
@Override
public String getPlatform() {
2016-11-29 05:05:18 +01:00
return "bukkit";
2016-04-20 20:22:47 +02:00
}
@Override
public UUID getUUID(String name) {
return Bukkit.getOfflinePlayer(name).getUniqueId();
}
@Override
public String getName(UUID uuid) {
return Bukkit.getOfflinePlayer(uuid).getName();
}
private boolean enabledBlocksHub = true;
@Override
public Object getBlocksHubApi() {
if (!enabledBlocksHub) {
return null;
}
Plugin blocksHubPlugin = Bukkit.getPluginManager().getPlugin("BlocksHub");
if (blocksHubPlugin == null) {
enabledBlocksHub = false;
return null;
}
return ((BlocksHubBukkit) blocksHubPlugin).getApi();
}
}