PageRenderTime 220ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java

https://gitlab.com/Skull3x/WorldEdit
Java | 870 lines | 475 code | 111 blank | 284 comment | 55 complexity | e9d81aa4e7d6e19b44d044f7c7be2787 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;
  20. import com.sk89q.worldedit.CuboidClipboard.FlipDirection;
  21. import com.sk89q.worldedit.blocks.BaseBlock;
  22. import com.sk89q.worldedit.blocks.BaseItem;
  23. import com.sk89q.worldedit.blocks.BlockType;
  24. import com.sk89q.worldedit.entity.Player;
  25. import com.sk89q.worldedit.event.extent.EditSessionEvent;
  26. import com.sk89q.worldedit.event.platform.BlockInteractEvent;
  27. import com.sk89q.worldedit.event.platform.InputType;
  28. import com.sk89q.worldedit.event.platform.PlayerInputEvent;
  29. import com.sk89q.worldedit.extension.factory.BlockFactory;
  30. import com.sk89q.worldedit.extension.factory.ItemFactory;
  31. import com.sk89q.worldedit.extension.factory.MaskFactory;
  32. import com.sk89q.worldedit.extension.factory.PatternFactory;
  33. import com.sk89q.worldedit.extension.input.ParserContext;
  34. import com.sk89q.worldedit.extension.platform.Actor;
  35. import com.sk89q.worldedit.extension.platform.Platform;
  36. import com.sk89q.worldedit.extension.platform.PlatformManager;
  37. import com.sk89q.worldedit.extent.inventory.BlockBag;
  38. import com.sk89q.worldedit.function.mask.Masks;
  39. import com.sk89q.worldedit.function.pattern.Patterns;
  40. import com.sk89q.worldedit.masks.Mask;
  41. import com.sk89q.worldedit.patterns.Pattern;
  42. import com.sk89q.worldedit.scripting.CraftScriptContext;
  43. import com.sk89q.worldedit.scripting.CraftScriptEngine;
  44. import com.sk89q.worldedit.scripting.RhinoCraftScriptEngine;
  45. import com.sk89q.worldedit.session.SessionManager;
  46. import com.sk89q.worldedit.session.request.Request;
  47. import com.sk89q.worldedit.util.eventbus.EventBus;
  48. import com.sk89q.worldedit.util.io.file.FileSelectionAbortedException;
  49. import com.sk89q.worldedit.util.io.file.FilenameException;
  50. import com.sk89q.worldedit.util.io.file.FilenameResolutionException;
  51. import com.sk89q.worldedit.util.io.file.InvalidFilenameException;
  52. import com.sk89q.worldedit.util.logging.WorldEditPrefixHandler;
  53. import com.sk89q.worldedit.world.registry.BundledBlockData;
  54. import javax.script.ScriptException;
  55. import java.io.DataInputStream;
  56. import java.io.File;
  57. import java.io.FileInputStream;
  58. import java.io.IOException;
  59. import java.io.InputStream;
  60. import java.util.HashMap;
  61. import java.util.HashSet;
  62. import java.util.Map;
  63. import java.util.Set;
  64. import java.util.logging.Level;
  65. import java.util.logging.Logger;
  66. import static com.google.common.base.Preconditions.checkNotNull;
  67. import static com.sk89q.worldedit.event.platform.Interaction.HIT;
  68. import static com.sk89q.worldedit.event.platform.Interaction.OPEN;
  69. /**
  70. * The entry point and container for a working implementation of WorldEdit.
  71. *
  72. * <p>An instance handles event handling; block, mask, pattern, etc. registration;
  73. * the management of sessions; the creation of {@link EditSession}s; and more.
  74. * In order to use WorldEdit, at least one {@link Platform} must be registered
  75. * with WorldEdit using {@link PlatformManager#register(Platform)} on the
  76. * manager retrieved using {@link WorldEdit#getPlatformManager()}.</p>
  77. *
  78. * <p>An instance of WorldEdit can be retrieved using the static
  79. * method {@link WorldEdit#getInstance()}, which is shared among all
  80. * platforms within the same classloader hierarchy.</p>
  81. */
  82. public class WorldEdit {
  83. public static final Logger logger = Logger.getLogger(WorldEdit.class.getCanonicalName());
  84. private final static WorldEdit instance = new WorldEdit();
  85. private static String version;
  86. private final EventBus eventBus = new EventBus();
  87. private final PlatformManager platformManager = new PlatformManager(this);
  88. private final EditSessionFactory editSessionFactory = new EditSessionFactory.EditSessionFactoryImpl(eventBus);
  89. private final SessionManager sessions = new SessionManager(this);
  90. private final BlockFactory blockFactory = new BlockFactory(this);
  91. private final ItemFactory itemFactory = new ItemFactory(this);
  92. private final MaskFactory maskFactory = new MaskFactory(this);
  93. private final PatternFactory patternFactory = new PatternFactory(this);
  94. static {
  95. WorldEditPrefixHandler.register("com.sk89q.worldedit");
  96. getVersion();
  97. BundledBlockData.getInstance(); // Load block registry
  98. }
  99. private WorldEdit() {
  100. }
  101. /**
  102. * Gets the current instance of this class.
  103. *
  104. * <p>An instance will always be available, but no platform may yet be
  105. * registered with WorldEdit, meaning that a number of operations
  106. * may fail. However, event handlers can be registered.</p>
  107. *
  108. * @return an instance of WorldEdit.
  109. */
  110. public static WorldEdit getInstance() {
  111. return instance;
  112. }
  113. /**
  114. * Get the platform manager, where platforms (that implement WorldEdit)
  115. * can be registered and information about registered platforms can
  116. * be queried.
  117. *
  118. * @return the platform manager
  119. */
  120. public PlatformManager getPlatformManager() {
  121. return platformManager;
  122. }
  123. /**
  124. * Get the event bus for WorldEdit.
  125. *
  126. * <p>Event handlers can be registered on the event bus.</p>
  127. *
  128. * @return the event bus
  129. */
  130. public EventBus getEventBus() {
  131. return eventBus;
  132. }
  133. /**
  134. * Get the block factory from which new {@link BaseBlock}s can be
  135. * constructed.
  136. *
  137. * @return the block factory
  138. */
  139. public BlockFactory getBlockFactory() {
  140. return blockFactory;
  141. }
  142. /**
  143. * Get the item factory from which new {@link BaseItem}s can be
  144. * constructed.
  145. *
  146. * @return the item factory
  147. */
  148. public ItemFactory getItemFactory() {
  149. return itemFactory;
  150. }
  151. /**
  152. * Get the mask factory from which new {@link com.sk89q.worldedit.function.mask.Mask}s
  153. * can be constructed.
  154. *
  155. * @return the mask factory
  156. */
  157. public MaskFactory getMaskFactory() {
  158. return maskFactory;
  159. }
  160. /**
  161. * Get the pattern factory from which new {@link com.sk89q.worldedit.function.pattern.Pattern}s
  162. * can be constructed.
  163. *
  164. * @return the pattern factory
  165. */
  166. public PatternFactory getPatternFactory() {
  167. return patternFactory;
  168. }
  169. /**
  170. * Return the session manager.
  171. *
  172. * @return the session manager
  173. */
  174. public SessionManager getSessionManager() {
  175. return sessions;
  176. }
  177. /**
  178. * @deprecated Use {@link #getSessionManager()}
  179. */
  180. @Deprecated
  181. public LocalSession getSession(String player) {
  182. return sessions.findByName(player);
  183. }
  184. /**
  185. * @deprecated use {@link #getSessionManager()}
  186. */
  187. @Deprecated
  188. public LocalSession getSession(Player player) {
  189. return sessions.get(player);
  190. }
  191. /**
  192. * @deprecated use {@link #getSessionManager()}
  193. */
  194. @Deprecated
  195. public void removeSession(Player player) {
  196. sessions.remove(player);
  197. }
  198. /**
  199. * @deprecated use {@link #getSessionManager()}
  200. */
  201. @Deprecated
  202. public void clearSessions() {
  203. sessions.clear();
  204. }
  205. /**
  206. * @deprecated use {@link #getSessionManager()}
  207. */
  208. @Deprecated
  209. public boolean hasSession(Player player) {
  210. return sessions.contains(player);
  211. }
  212. /**
  213. * @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromInput(String, ParserContext)}
  214. */
  215. @SuppressWarnings("deprecation")
  216. @Deprecated
  217. public BaseBlock getBlock(Player player, String arg, boolean allAllowed) throws WorldEditException {
  218. return getBlock(player, arg, allAllowed, false);
  219. }
  220. /**
  221. * @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromInput(String, ParserContext)}
  222. */
  223. @SuppressWarnings("deprecation")
  224. @Deprecated
  225. public BaseBlock getBlock(Player player, String arg, boolean allAllowed, boolean allowNoData) throws WorldEditException {
  226. ParserContext context = new ParserContext();
  227. context.setActor(player);
  228. context.setWorld(player.getWorld());
  229. context.setSession(getSession(player));
  230. context.setRestricted(!allAllowed);
  231. context.setPreferringWildcard(allowNoData);
  232. return getBlockFactory().parseFromInput(arg, context);
  233. }
  234. /**
  235. * @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromInput(String, ParserContext)}
  236. */
  237. @SuppressWarnings("deprecation")
  238. @Deprecated
  239. public BaseBlock getBlock(Player player, String id) throws WorldEditException {
  240. return getBlock(player, id, false);
  241. }
  242. /**
  243. * @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromListInput(String, ParserContext)}
  244. */
  245. @Deprecated
  246. @SuppressWarnings("deprecation")
  247. public Set<BaseBlock> getBlocks(Player player, String list, boolean allAllowed, boolean allowNoData) throws WorldEditException {
  248. String[] items = list.split(",");
  249. Set<BaseBlock> blocks = new HashSet<BaseBlock>();
  250. for (String id : items) {
  251. blocks.add(getBlock(player, id, allAllowed, allowNoData));
  252. }
  253. return blocks;
  254. }
  255. /**
  256. * @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromInput(String, ParserContext)}
  257. */
  258. @Deprecated
  259. @SuppressWarnings("deprecation")
  260. public Set<BaseBlock> getBlocks(Player player, String list, boolean allAllowed) throws WorldEditException {
  261. return getBlocks(player, list, allAllowed, false);
  262. }
  263. /**
  264. * @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromListInput(String, ParserContext)}
  265. */
  266. @Deprecated
  267. @SuppressWarnings("deprecation")
  268. public Set<BaseBlock> getBlocks(Player player, String list) throws WorldEditException {
  269. return getBlocks(player, list, false);
  270. }
  271. /**
  272. * @deprecated Use {@link #getBlockFactory()} and {@link BlockFactory#parseFromListInput(String, ParserContext)}
  273. */
  274. @Deprecated
  275. @SuppressWarnings("deprecation")
  276. public Set<Integer> getBlockIDs(Player player, String list, boolean allBlocksAllowed) throws WorldEditException {
  277. String[] items = list.split(",");
  278. Set<Integer> blocks = new HashSet<Integer>();
  279. for (String s : items) {
  280. blocks.add(getBlock(player, s, allBlocksAllowed).getType());
  281. }
  282. return blocks;
  283. }
  284. /**
  285. * @deprecated Use {@link #getPatternFactory()} and {@link BlockFactory#parseFromInput(String, ParserContext)}
  286. */
  287. @Deprecated
  288. @SuppressWarnings("deprecation")
  289. public Pattern getBlockPattern(Player player, String input) throws WorldEditException {
  290. ParserContext context = new ParserContext();
  291. context.setActor(player);
  292. context.setWorld(player.getWorld());
  293. context.setSession(getSession(player));
  294. return Patterns.wrap(getPatternFactory().parseFromInput(input, context));
  295. }
  296. /**
  297. * @deprecated Use {@link #getMaskFactory()} ()} and {@link MaskFactory#parseFromInput(String, ParserContext)}
  298. */
  299. @Deprecated
  300. @SuppressWarnings("deprecation")
  301. public Mask getBlockMask(Player player, LocalSession session, String input) throws WorldEditException {
  302. ParserContext context = new ParserContext();
  303. context.setActor(player);
  304. context.setWorld(player.getWorld());
  305. context.setSession(session);
  306. return Masks.wrap(getMaskFactory().parseFromInput(input, context));
  307. }
  308. /**
  309. * Gets the path to a file. This method will check to see if the filename
  310. * has valid characters and has an extension. It also prevents directory
  311. * traversal exploits by checking the root directory and the file directory.
  312. * On success, a {@code java.io.File} object will be returned.
  313. *
  314. * @param player the player
  315. * @param dir sub-directory to look in
  316. * @param filename filename (user-submitted)
  317. * @param defaultExt append an extension if missing one, null to not use
  318. * @param extensions list of extensions, null for any
  319. * @return a file
  320. * @throws FilenameException thrown if the filename is invalid
  321. */
  322. public File getSafeSaveFile(Player player, File dir, String filename, String defaultExt, String... extensions) throws FilenameException {
  323. return getSafeFile(player, dir, filename, defaultExt, extensions, true);
  324. }
  325. /**
  326. * Gets the path to a file. This method will check to see if the filename
  327. * has valid characters and has an extension. It also prevents directory
  328. * traversal exploits by checking the root directory and the file directory.
  329. * On success, a {@code java.io.File} object will be returned.
  330. *
  331. * @param player the player
  332. * @param dir sub-directory to look in
  333. * @param filename filename (user-submitted)
  334. * @param defaultExt append an extension if missing one, null to not use
  335. * @param extensions list of extensions, null for any
  336. * @return a file
  337. * @throws FilenameException thrown if the filename is invalid
  338. */
  339. public File getSafeOpenFile(Player player, File dir, String filename, String defaultExt, String... extensions) throws FilenameException {
  340. return getSafeFile(player, dir, filename, defaultExt, extensions, false);
  341. }
  342. /**
  343. * Get a safe path to a file.
  344. *
  345. * @param player the player
  346. * @param dir sub-directory to look in
  347. * @param filename filename (user-submitted)
  348. * @param defaultExt append an extension if missing one, null to not use
  349. * @param extensions list of extensions, null for any
  350. * @param isSave true if the purpose is for saving
  351. * @return a file
  352. * @throws FilenameException thrown if the filename is invalid
  353. */
  354. private File getSafeFile(Player player, File dir, String filename, String defaultExt, String[] extensions, boolean isSave) throws FilenameException {
  355. if (extensions != null && (extensions.length == 1 && extensions[0] == null)) extensions = null;
  356. File f;
  357. if (filename.equals("#")) {
  358. if (isSave) {
  359. f = player.openFileSaveDialog(extensions);
  360. } else {
  361. f = player.openFileOpenDialog(extensions);
  362. }
  363. if (f == null) {
  364. throw new FileSelectionAbortedException("No file selected");
  365. }
  366. } else {
  367. if (defaultExt != null && filename.lastIndexOf('.') == -1) {
  368. filename += "." + defaultExt;
  369. }
  370. if (!filename.matches("^[A-Za-z0-9_\\- \\./\\\\'\\$@~!%\\^\\*\\(\\)\\[\\]\\+\\{\\},\\?]+\\.[A-Za-z0-9]+$")) {
  371. throw new InvalidFilenameException(filename, "Invalid characters or extension missing");
  372. }
  373. f = new File(dir, filename);
  374. }
  375. try {
  376. String filePath = f.getCanonicalPath();
  377. String dirPath = dir.getCanonicalPath();
  378. if (!filePath.substring(0, dirPath.length()).equals(dirPath) && !getConfiguration().allowSymlinks) {
  379. throw new FilenameResolutionException(filename,
  380. "Path is outside allowable root");
  381. }
  382. return f;
  383. } catch (IOException e) {
  384. throw new FilenameResolutionException(filename,
  385. "Failed to resolve path");
  386. }
  387. }
  388. /**
  389. * Checks to see if the specified radius is within bounds.
  390. *
  391. * @param radius the radius
  392. * @throws MaxRadiusException
  393. */
  394. public void checkMaxRadius(double radius) throws MaxRadiusException {
  395. if (getConfiguration().maxRadius > 0 && radius > getConfiguration().maxRadius) {
  396. throw new MaxRadiusException();
  397. }
  398. }
  399. /**
  400. * Checks to see if the specified brush radius is within bounds.
  401. *
  402. * @param radius the radius
  403. * @throws MaxBrushRadiusException
  404. */
  405. public void checkMaxBrushRadius(double radius) throws MaxBrushRadiusException {
  406. if (getConfiguration().maxBrushRadius > 0 && radius > getConfiguration().maxBrushRadius) {
  407. throw new MaxBrushRadiusException();
  408. }
  409. }
  410. /**
  411. * Get a file relative to the defined working directory. If the specified
  412. * path is absolute, then the working directory is not used.
  413. *
  414. * @param path the subpath under the working directory
  415. * @return a working directory
  416. */
  417. public File getWorkingDirectoryFile(String path) {
  418. File f = new File(path);
  419. if (f.isAbsolute()) {
  420. return f;
  421. }
  422. return new File(getConfiguration().getWorkingDirectory(), path);
  423. }
  424. /**
  425. * Get the direction vector for a player's direction. May return
  426. * null if a direction could not be found.
  427. *
  428. * @param player the player
  429. * @param dirStr the direction string
  430. * @return a direction vector
  431. * @throws UnknownDirectionException thrown if the direction is not known
  432. */
  433. public Vector getDirection(Player player, String dirStr) throws UnknownDirectionException {
  434. dirStr = dirStr.toLowerCase();
  435. final PlayerDirection dir = getPlayerDirection(player, dirStr);
  436. switch (dir) {
  437. case WEST:
  438. case EAST:
  439. case SOUTH:
  440. case NORTH:
  441. case UP:
  442. case DOWN:
  443. return dir.vector();
  444. default:
  445. throw new UnknownDirectionException(dir.name());
  446. }
  447. }
  448. /**
  449. * Get the direction vector for a player's direction. May return
  450. * null if a direction could not be found.
  451. *
  452. * @param player the player
  453. * @param dirStr the direction string
  454. * @return a direction enum value
  455. * @throws UnknownDirectionException thrown if the direction is not known
  456. */
  457. private PlayerDirection getPlayerDirection(Player player, String dirStr) throws UnknownDirectionException {
  458. final PlayerDirection dir;
  459. switch (dirStr.charAt(0)) {
  460. case 'w':
  461. dir = PlayerDirection.WEST;
  462. break;
  463. case 'e':
  464. dir = PlayerDirection.EAST;
  465. break;
  466. case 's':
  467. if (dirStr.indexOf('w') > 0) {
  468. return PlayerDirection.SOUTH_WEST;
  469. }
  470. if (dirStr.indexOf('e') > 0) {
  471. return PlayerDirection.SOUTH_EAST;
  472. }
  473. dir = PlayerDirection.SOUTH;
  474. break;
  475. case 'n':
  476. if (dirStr.indexOf('w') > 0) {
  477. return PlayerDirection.NORTH_WEST;
  478. }
  479. if (dirStr.indexOf('e') > 0) {
  480. return PlayerDirection.NORTH_EAST;
  481. }
  482. dir = PlayerDirection.NORTH;
  483. break;
  484. case 'u':
  485. dir = PlayerDirection.UP;
  486. break;
  487. case 'd':
  488. dir = PlayerDirection.DOWN;
  489. break;
  490. case 'm': // me
  491. case 'f': // forward
  492. dir = player.getCardinalDirection(0);
  493. break;
  494. case 'b': // back
  495. dir = player.getCardinalDirection(180);
  496. break;
  497. case 'l': // left
  498. dir = player.getCardinalDirection(-90);
  499. break;
  500. case 'r': // right
  501. dir = player.getCardinalDirection(90);
  502. break;
  503. default:
  504. throw new UnknownDirectionException(dirStr);
  505. }
  506. return dir;
  507. }
  508. /**
  509. * Get diagonal direction vector for a player's direction. May return
  510. * null if a direction could not be found.
  511. *
  512. * @param player the player
  513. * @param dirStr the direction string
  514. * @return a direction vector
  515. * @throws UnknownDirectionException thrown if the direction is not known
  516. */
  517. public Vector getDiagonalDirection(Player player, String dirStr) throws UnknownDirectionException {
  518. return getPlayerDirection(player, dirStr.toLowerCase()).vector();
  519. }
  520. /**
  521. * Get the flip direction for a player's direction.
  522. *
  523. * @param player the player
  524. * @param dirStr the direction string
  525. * @return a direction vector
  526. * @throws UnknownDirectionException thrown if the direction is not known
  527. */
  528. public FlipDirection getFlipDirection(Player player, String dirStr) throws UnknownDirectionException {
  529. final PlayerDirection dir = getPlayerDirection(player, dirStr);
  530. switch (dir) {
  531. case WEST:
  532. case EAST:
  533. return FlipDirection.WEST_EAST;
  534. case NORTH:
  535. case SOUTH:
  536. return FlipDirection.NORTH_SOUTH;
  537. case UP:
  538. case DOWN:
  539. return FlipDirection.UP_DOWN;
  540. default:
  541. throw new UnknownDirectionException(dir.name());
  542. }
  543. }
  544. /**
  545. * Flush a block bag's changes to a player.
  546. *
  547. * @param actor the actor
  548. * @param editSession the edit session
  549. */
  550. public void flushBlockBag(Actor actor, EditSession editSession) {
  551. BlockBag blockBag = editSession.getBlockBag();
  552. if (blockBag != null) {
  553. blockBag.flushChanges();
  554. }
  555. Map<Integer, Integer> missingBlocks = editSession.popMissingBlocks();
  556. if (!missingBlocks.isEmpty()) {
  557. StringBuilder str = new StringBuilder();
  558. str.append("Missing these blocks: ");
  559. int size = missingBlocks.size();
  560. int i = 0;
  561. for (Integer id : missingBlocks.keySet()) {
  562. BlockType type = BlockType.fromID(id);
  563. str.append(type != null
  564. ? type.getName() + " (" + id + ")"
  565. : id.toString());
  566. str.append(" [Amt: ").append(missingBlocks.get(id)).append("]");
  567. ++i;
  568. if (i != size) {
  569. str.append(", ");
  570. }
  571. }
  572. actor.printError(str.toString());
  573. }
  574. }
  575. /**
  576. * Called on arm swing.
  577. *
  578. * @param player the player
  579. * @return true if the swing was handled
  580. */
  581. public boolean handleArmSwing(Player player) {
  582. PlayerInputEvent event = new PlayerInputEvent(player, InputType.PRIMARY);
  583. getEventBus().post(event);
  584. return event.isCancelled();
  585. }
  586. /**
  587. * Called on right click (not on a block).
  588. *
  589. * @param player the player
  590. * @return true if the right click was handled
  591. */
  592. public boolean handleRightClick(Player player) {
  593. PlayerInputEvent event = new PlayerInputEvent(player, InputType.SECONDARY);
  594. getEventBus().post(event);
  595. return event.isCancelled();
  596. }
  597. /**
  598. * Called on right click.
  599. *
  600. * @param player the player
  601. * @param clicked the clicked block
  602. * @return false if you want the action to go through
  603. */
  604. public boolean handleBlockRightClick(Player player, WorldVector clicked) {
  605. BlockInteractEvent event = new BlockInteractEvent(player, clicked.toLocation(), OPEN);
  606. getEventBus().post(event);
  607. return event.isCancelled();
  608. }
  609. /**
  610. * Called on left click.
  611. *
  612. * @param player the player
  613. * @param clicked the clicked block
  614. * @return false if you want the action to go through
  615. */
  616. public boolean handleBlockLeftClick(Player player, WorldVector clicked) {
  617. BlockInteractEvent event = new BlockInteractEvent(player, clicked.toLocation(), HIT);
  618. getEventBus().post(event);
  619. return event.isCancelled();
  620. }
  621. /**
  622. * Executes a WorldEdit script.
  623. *
  624. * @param player the player
  625. * @param f the script file to execute
  626. * @param args arguments for the script
  627. * @throws WorldEditException
  628. */
  629. public void runScript(Player player, File f, String[] args) throws WorldEditException {
  630. Request.reset();
  631. String filename = f.getPath();
  632. int index = filename.lastIndexOf(".");
  633. String ext = filename.substring(index + 1, filename.length());
  634. if (!ext.equalsIgnoreCase("js")) {
  635. player.printError("Only .js scripts are currently supported");
  636. return;
  637. }
  638. String script;
  639. try {
  640. InputStream file;
  641. if (!f.exists()) {
  642. file = WorldEdit.class.getResourceAsStream("craftscripts/" + filename);
  643. if (file == null) {
  644. player.printError("Script does not exist: " + filename);
  645. return;
  646. }
  647. } else {
  648. file = new FileInputStream(f);
  649. }
  650. DataInputStream in = new DataInputStream(file);
  651. byte[] data = new byte[in.available()];
  652. in.readFully(data);
  653. in.close();
  654. script = new String(data, 0, data.length, "utf-8");
  655. } catch (IOException e) {
  656. player.printError("Script read error: " + e.getMessage());
  657. return;
  658. }
  659. LocalSession session = getSessionManager().get(player);
  660. CraftScriptContext scriptContext = new CraftScriptContext(this, getServer(), getConfiguration(), session, player, args);
  661. CraftScriptEngine engine = null;
  662. try {
  663. engine = new RhinoCraftScriptEngine();
  664. } catch (NoClassDefFoundError e) {
  665. player.printError("Failed to find an installed script engine.");
  666. player.printError("Please see http://wiki.sk89q.com/wiki/WorldEdit/Installation");
  667. return;
  668. }
  669. engine.setTimeLimit(getConfiguration().scriptTimeout);
  670. Map<String, Object> vars = new HashMap<String, Object>();
  671. vars.put("argv", args);
  672. vars.put("context", scriptContext);
  673. vars.put("player", player);
  674. try {
  675. engine.evaluate(script, filename, vars);
  676. } catch (ScriptException e) {
  677. player.printError("Failed to execute:");
  678. player.printRaw(e.getMessage());
  679. logger.log(Level.WARNING, "Failed to execute script", e);
  680. } catch (NumberFormatException e) {
  681. throw e;
  682. } catch (WorldEditException e) {
  683. throw e;
  684. } catch (Throwable e) {
  685. player.printError("Failed to execute (see console):");
  686. player.printRaw(e.getClass().getCanonicalName());
  687. logger.log(Level.WARNING, "Failed to execute script", e);
  688. } finally {
  689. for (EditSession editSession : scriptContext.getEditSessions()) {
  690. editSession.flushQueue();
  691. session.remember(editSession);
  692. }
  693. }
  694. }
  695. /**
  696. * Get Worldedit's configuration.
  697. *
  698. * @return a configuration
  699. */
  700. public LocalConfiguration getConfiguration() {
  701. return getPlatformManager().getConfiguration();
  702. }
  703. /**
  704. * Get the server interface.
  705. *
  706. * @return the server interface
  707. */
  708. public ServerInterface getServer() {
  709. return getPlatformManager().getServerInterface();
  710. }
  711. /**
  712. * Get a factory for {@link EditSession}s.
  713. */
  714. public EditSessionFactory getEditSessionFactory() {
  715. return editSessionFactory;
  716. }
  717. /**
  718. * @deprecated EditSessionFactories are no longer used. Please register an {@link EditSessionEvent} event
  719. * with the event bus in order to override or catch changes to the world
  720. */
  721. @Deprecated
  722. public void setEditSessionFactory(EditSessionFactory factory) {
  723. checkNotNull(factory);
  724. logger.severe("Got request to set EditSessionFactory of type " +
  725. factory.getClass().getName() + " from " + factory.getClass().getPackage().getName() +
  726. " but EditSessionFactories have been removed in favor of extending EditSession's extents.\n\n" +
  727. "This may mean that any block logger / intercepters addons/plugins/mods that you have installed will not " +
  728. "intercept WorldEdit's changes! Please notify the maintainer of the other addon about this.");
  729. }
  730. /**
  731. * Get the version.
  732. *
  733. * @return the version of WorldEdit
  734. */
  735. public static String getVersion() {
  736. if (version != null) {
  737. return version;
  738. }
  739. Package p = WorldEdit.class.getPackage();
  740. if (p == null) {
  741. p = Package.getPackage("com.sk89q.worldedit");
  742. }
  743. if (p == null) {
  744. version = "(unknown)";
  745. } else {
  746. version = p.getImplementationVersion();
  747. if (version == null) {
  748. version = "(unknown)";
  749. }
  750. }
  751. return version;
  752. }
  753. /**
  754. * @deprecated Declare your platform version with {@link Platform#getPlatformVersion()}
  755. */
  756. @Deprecated
  757. public static void setVersion(String version) {
  758. }
  759. }