PageRenderTime 495ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java

https://gitlab.com/Skull3x/WorldEdit
Java | 477 lines | 286 code | 62 blank | 129 comment | 29 complexity | a4e11346ef93e54001e1ec63f53f05b5 MD5 | raw file
  1. /*
  2. * WorldEdit, a Minecraft world manipulation toolkit
  3. * Copyright (C) sk89q <http://www.sk89q.com>
  4. * Copyright (C) WorldEdit team and contributors
  5. *
  6. * This program is free software: you can redistribute it and/or modify it
  7. * under the terms of the GNU Lesser General Public License as published by the
  8. * Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful, but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
  14. * for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package com.sk89q.worldedit.bukkit;
  20. import com.google.common.base.Joiner;
  21. import com.sk89q.util.yaml.YAMLProcessor;
  22. import com.sk89q.wepif.PermissionsResolverManager;
  23. import com.sk89q.worldedit.EditSession;
  24. import com.sk89q.worldedit.IncompleteRegionException;
  25. import com.sk89q.worldedit.LocalPlayer;
  26. import com.sk89q.worldedit.LocalSession;
  27. import com.sk89q.worldedit.ServerInterface;
  28. import com.sk89q.worldedit.WorldEdit;
  29. import com.sk89q.worldedit.WorldEditOperation;
  30. import com.sk89q.worldedit.bukkit.adapter.AdapterLoadException;
  31. import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
  32. import com.sk89q.worldedit.bukkit.adapter.BukkitImplLoader;
  33. import com.sk89q.worldedit.bukkit.selections.CuboidSelection;
  34. import com.sk89q.worldedit.bukkit.selections.CylinderSelection;
  35. import com.sk89q.worldedit.bukkit.selections.Polygonal2DSelection;
  36. import com.sk89q.worldedit.bukkit.selections.Selection;
  37. import com.sk89q.worldedit.event.platform.CommandEvent;
  38. import com.sk89q.worldedit.event.platform.CommandSuggestionEvent;
  39. import com.sk89q.worldedit.event.platform.PlatformReadyEvent;
  40. import com.sk89q.worldedit.extension.platform.Actor;
  41. import com.sk89q.worldedit.extension.platform.Capability;
  42. import com.sk89q.worldedit.extension.platform.Platform;
  43. import com.sk89q.worldedit.extent.inventory.BlockBag;
  44. import com.sk89q.worldedit.regions.CuboidRegion;
  45. import com.sk89q.worldedit.regions.CylinderRegion;
  46. import com.sk89q.worldedit.regions.Polygonal2DRegion;
  47. import com.sk89q.worldedit.regions.Region;
  48. import com.sk89q.worldedit.regions.RegionSelector;
  49. import com.sk89q.worldedit.util.Java8Detector;
  50. import org.bukkit.World;
  51. import org.bukkit.command.Command;
  52. import org.bukkit.command.CommandSender;
  53. import org.bukkit.command.TabCompleter;
  54. import org.bukkit.entity.Player;
  55. import org.bukkit.plugin.java.JavaPlugin;
  56. import javax.annotation.Nullable;
  57. import java.io.File;
  58. import java.io.FileNotFoundException;
  59. import java.io.FileOutputStream;
  60. import java.io.IOException;
  61. import java.io.InputStream;
  62. import java.util.List;
  63. import java.util.jar.JarFile;
  64. import java.util.logging.Level;
  65. import java.util.logging.Logger;
  66. import java.util.zip.ZipEntry;
  67. import static com.google.common.base.Preconditions.checkNotNull;
  68. /**
  69. * Plugin for Bukkit.
  70. */
  71. @SuppressWarnings("deprecation")
  72. public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
  73. private static final Logger log = Logger.getLogger(WorldEditPlugin.class.getCanonicalName());
  74. public static final String CUI_PLUGIN_CHANNEL = "WECUI";
  75. private static WorldEditPlugin INSTANCE;
  76. private BukkitImplAdapter bukkitAdapter;
  77. private BukkitServerInterface server;
  78. private final WorldEditAPI api = new WorldEditAPI(this);
  79. private BukkitConfiguration config;
  80. /**
  81. * Called on plugin enable.
  82. */
  83. @SuppressWarnings("AccessStaticViaInstance")
  84. @Override
  85. public void onEnable() {
  86. this.INSTANCE = this;
  87. //noinspection ResultOfMethodCallIgnored
  88. getDataFolder().mkdirs();
  89. WorldEdit worldEdit = WorldEdit.getInstance();
  90. loadConfig(); // Load configuration
  91. PermissionsResolverManager.initialize(this); // Setup permission resolver
  92. // Setup platform
  93. server = new BukkitServerInterface(this, getServer());
  94. worldEdit.getPlatformManager().register(server);
  95. // Register CUI
  96. getServer().getMessenger().registerIncomingPluginChannel(this, CUI_PLUGIN_CHANNEL, new CUIChannelListener(this));
  97. getServer().getMessenger().registerOutgoingPluginChannel(this, CUI_PLUGIN_CHANNEL);
  98. // Now we can register events
  99. getServer().getPluginManager().registerEvents(new WorldEditListener(this), this);
  100. // If we are on MCPC+/Cauldron, then Forge will have already loaded
  101. // Forge WorldEdit and there's (probably) not going to be any other
  102. // platforms to be worried about... at the current time of writing
  103. WorldEdit.getInstance().getEventBus().post(new PlatformReadyEvent());
  104. loadAdapter(); // Need an adapter to work with special blocks with NBT data
  105. // Check Java version
  106. Java8Detector.notifyIfNot8();
  107. }
  108. private void loadConfig() {
  109. createDefaultConfiguration("config.yml"); // Create the default configuration file
  110. config = new BukkitConfiguration(new YAMLProcessor(new File(getDataFolder(), "config.yml"), true), this);
  111. config.load();
  112. }
  113. private void loadAdapter() {
  114. WorldEdit worldEdit = WorldEdit.getInstance();
  115. // Attempt to load a Bukkit adapter
  116. BukkitImplLoader adapterLoader = new BukkitImplLoader();
  117. try {
  118. adapterLoader.addFromPath(getClass().getClassLoader());
  119. } catch (IOException e) {
  120. log.log(Level.WARNING, "Failed to search path for Bukkit adapters");
  121. }
  122. try {
  123. adapterLoader.addFromJar(getFile());
  124. } catch (IOException e) {
  125. log.log(Level.WARNING, "Failed to search " + getFile() + " for Bukkit adapters", e);
  126. }
  127. try {
  128. bukkitAdapter = adapterLoader.loadAdapter();
  129. log.log(Level.INFO, "Using " + bukkitAdapter.getClass().getCanonicalName() + " as the Bukkit adapter");
  130. } catch (AdapterLoadException e) {
  131. Platform platform = worldEdit.getPlatformManager().queryCapability(Capability.WORLD_EDITING);
  132. if (platform instanceof BukkitServerInterface) {
  133. log.log(Level.WARNING, e.getMessage());
  134. } else {
  135. log.log(Level.INFO, "WorldEdit could not find a Bukkit adapter for this MC version, " +
  136. "but it seems that you have another implementation of WorldEdit installed (" + platform.getPlatformName() + ") " +
  137. "that handles the world editing.");
  138. }
  139. }
  140. }
  141. /**
  142. * Called on plugin disable.
  143. */
  144. @Override
  145. public void onDisable() {
  146. WorldEdit worldEdit = WorldEdit.getInstance();
  147. worldEdit.clearSessions();
  148. worldEdit.getPlatformManager().unregister(server);
  149. if (config != null) {
  150. config.unload();
  151. }
  152. if (server != null) {
  153. server.unregisterCommands();
  154. }
  155. this.getServer().getScheduler().cancelTasks(this);
  156. }
  157. /**
  158. * Loads and reloads all configuration.
  159. */
  160. protected void loadConfiguration() {
  161. config.unload();
  162. config.load();
  163. getPermissionsResolver().load();
  164. }
  165. /**
  166. * Create a default configuration file from the .jar.
  167. *
  168. * @param name the filename
  169. */
  170. protected void createDefaultConfiguration(String name) {
  171. File actual = new File(getDataFolder(), name);
  172. if (!actual.exists()) {
  173. InputStream input = null;
  174. try {
  175. JarFile file = new JarFile(getFile());
  176. ZipEntry copy = file.getEntry("defaults/" + name);
  177. if (copy == null) throw new FileNotFoundException();
  178. input = file.getInputStream(copy);
  179. } catch (IOException e) {
  180. getLogger().severe("Unable to read default configuration: " + name);
  181. }
  182. if (input != null) {
  183. FileOutputStream output = null;
  184. try {
  185. output = new FileOutputStream(actual);
  186. byte[] buf = new byte[8192];
  187. int length;
  188. while ((length = input.read(buf)) > 0) {
  189. output.write(buf, 0, length);
  190. }
  191. getLogger().info("Default configuration file written: " + name);
  192. } catch (IOException e) {
  193. getLogger().log(Level.WARNING, "Failed to write default config file", e);
  194. } finally {
  195. try {
  196. input.close();
  197. } catch (IOException ignored) {}
  198. try {
  199. if (output != null) {
  200. output.close();
  201. }
  202. } catch (IOException ignored) {}
  203. }
  204. }
  205. }
  206. }
  207. @Override
  208. public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
  209. // Add the command to the array because the underlying command handling
  210. // code of WorldEdit expects it
  211. String[] split = new String[args.length + 1];
  212. System.arraycopy(args, 0, split, 1, args.length);
  213. split[0] = cmd.getName();
  214. CommandEvent event = new CommandEvent(wrapCommandSender(sender), Joiner.on(" ").join(split));
  215. getWorldEdit().getEventBus().post(event);
  216. return true;
  217. }
  218. @Override
  219. public List<String> onTabComplete(CommandSender sender, Command cmd, String commandLabel, String[] args) {
  220. // Add the command to the array because the underlying command handling
  221. // code of WorldEdit expects it
  222. String[] split = new String[args.length + 1];
  223. System.arraycopy(args, 0, split, 1, args.length);
  224. split[0] = cmd.getName();
  225. CommandSuggestionEvent event = new CommandSuggestionEvent(wrapCommandSender(sender), Joiner.on(" ").join(split));
  226. getWorldEdit().getEventBus().post(event);
  227. return event.getSuggestions();
  228. }
  229. /**
  230. * Gets the session for the player.
  231. *
  232. * @param player a player
  233. * @return a session
  234. */
  235. public LocalSession getSession(Player player) {
  236. return WorldEdit.getInstance().getSession(wrapPlayer(player));
  237. }
  238. /**
  239. * Gets the session for the player.
  240. *
  241. * @param player a player
  242. * @return a session
  243. */
  244. public EditSession createEditSession(Player player) {
  245. LocalPlayer wePlayer = wrapPlayer(player);
  246. LocalSession session = WorldEdit.getInstance().getSession(wePlayer);
  247. BlockBag blockBag = session.getBlockBag(wePlayer);
  248. EditSession editSession = WorldEdit.getInstance().getEditSessionFactory()
  249. .getEditSession(wePlayer.getWorld(), session.getBlockChangeLimit(), blockBag, wePlayer);
  250. editSession.enableQueue();
  251. return editSession;
  252. }
  253. /**
  254. * Remember an edit session.
  255. *
  256. * @param player a player
  257. * @param editSession an edit session
  258. */
  259. public void remember(Player player, EditSession editSession) {
  260. LocalPlayer wePlayer = wrapPlayer(player);
  261. LocalSession session = WorldEdit.getInstance().getSession(wePlayer);
  262. session.remember(editSession);
  263. editSession.flushQueue();
  264. WorldEdit.getInstance().flushBlockBag(wePlayer, editSession);
  265. }
  266. /**
  267. * Wrap an operation into an EditSession.
  268. *
  269. * @param player a player
  270. * @param op the operation
  271. * @throws Throwable on any error
  272. * @deprecated use the regular API
  273. */
  274. @Deprecated
  275. public void perform(Player player, WorldEditOperation op) throws Throwable {
  276. LocalPlayer wePlayer = wrapPlayer(player);
  277. LocalSession session = WorldEdit.getInstance().getSession(wePlayer);
  278. EditSession editSession = createEditSession(player);
  279. try {
  280. op.run(session, wePlayer, editSession);
  281. } finally {
  282. remember(player, editSession);
  283. }
  284. }
  285. /**
  286. * Get the API.
  287. *
  288. * @return the API
  289. * @deprecated use the regular API
  290. */
  291. @Deprecated
  292. public WorldEditAPI getAPI() {
  293. return api;
  294. }
  295. /**
  296. * Returns the configuration used by WorldEdit.
  297. *
  298. * @return the configuration
  299. */
  300. public BukkitConfiguration getLocalConfiguration() {
  301. return config;
  302. }
  303. /**
  304. * Get the permissions resolver in use.
  305. *
  306. * @return the permissions resolver
  307. */
  308. public PermissionsResolverManager getPermissionsResolver() {
  309. return PermissionsResolverManager.getInstance();
  310. }
  311. /**
  312. * Used to wrap a Bukkit Player as a LocalPlayer.
  313. *
  314. * @param player a player
  315. * @return a wrapped player
  316. */
  317. public BukkitPlayer wrapPlayer(Player player) {
  318. return new BukkitPlayer(this, this.server, player);
  319. }
  320. public Actor wrapCommandSender(CommandSender sender) {
  321. if (sender instanceof Player) {
  322. return wrapPlayer((Player) sender);
  323. }
  324. return new BukkitCommandSender(this, sender);
  325. }
  326. /**
  327. * Get the server interface.
  328. *
  329. * @return the server interface
  330. */
  331. public ServerInterface getServerInterface() {
  332. return server;
  333. }
  334. BukkitServerInterface getInternalPlatform() {
  335. return server;
  336. }
  337. /**
  338. * Get WorldEdit.
  339. *
  340. * @return an instance
  341. */
  342. public WorldEdit getWorldEdit() {
  343. return WorldEdit.getInstance();
  344. }
  345. /**
  346. * Gets the region selection for the player.
  347. *
  348. * @param player aplayer
  349. * @return the selection or null if there was none
  350. */
  351. public Selection getSelection(Player player) {
  352. if (player == null) {
  353. throw new IllegalArgumentException("Null player not allowed");
  354. }
  355. if (!player.isOnline()) {
  356. throw new IllegalArgumentException("Offline player not allowed");
  357. }
  358. LocalSession session = WorldEdit.getInstance().getSession(wrapPlayer(player));
  359. RegionSelector selector = session.getRegionSelector(BukkitUtil.getLocalWorld(player.getWorld()));
  360. try {
  361. Region region = selector.getRegion();
  362. World world = BukkitAdapter.asBukkitWorld(session.getSelectionWorld()).getWorld();
  363. if (region instanceof CuboidRegion) {
  364. return new CuboidSelection(world, selector, (CuboidRegion) region);
  365. } else if (region instanceof Polygonal2DRegion) {
  366. return new Polygonal2DSelection(world, selector, (Polygonal2DRegion) region);
  367. } else if (region instanceof CylinderRegion) {
  368. return new CylinderSelection(world, selector, (CylinderRegion) region);
  369. } else {
  370. return null;
  371. }
  372. } catch (IncompleteRegionException e) {
  373. return null;
  374. }
  375. }
  376. /**
  377. * Sets the region selection for a player.
  378. *
  379. * @param player the player
  380. * @param selection a selection
  381. */
  382. public void setSelection(Player player, Selection selection) {
  383. if (player == null) {
  384. throw new IllegalArgumentException("Null player not allowed");
  385. }
  386. if (!player.isOnline()) {
  387. throw new IllegalArgumentException("Offline player not allowed");
  388. }
  389. if (selection == null) {
  390. throw new IllegalArgumentException("Null selection not allowed");
  391. }
  392. LocalSession session = WorldEdit.getInstance().getSession(wrapPlayer(player));
  393. RegionSelector sel = selection.getRegionSelector();
  394. session.setRegionSelector(BukkitUtil.getLocalWorld(player.getWorld()), sel);
  395. session.dispatchCUISelection(wrapPlayer(player));
  396. }
  397. /**
  398. * Gets the instance of this plugin.
  399. *
  400. * @return an instance of the plugin
  401. * @throws NullPointerException if the plugin hasn't been enabled
  402. */
  403. static WorldEditPlugin getInstance() {
  404. return checkNotNull(INSTANCE);
  405. }
  406. /**
  407. * Get the Bukkit implementation adapter.
  408. *
  409. * @return the adapter
  410. */
  411. @Nullable
  412. BukkitImplAdapter getBukkitImplAdapter() {
  413. return bukkitAdapter;
  414. }
  415. }