PageRenderTime 754ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/oldsrc/hmod/CraftBookListener.java

http://github.com/sk89q/craftbook
Java | 388 lines | 241 code | 63 blank | 84 comment | 78 complexity | 207f137fd87ed90e078b0db8b65ec24e MD5 | raw file
Possible License(s): GPL-3.0
  1. // $Id$
  2. /*
  3. * CraftBook
  4. * Copyright (C) 2010 sk89q <http://www.sk89q.com>
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the 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,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. import com.sk89q.craftbook.BlockType;
  20. import com.sk89q.craftbook.CraftBookDelegateListener;
  21. import com.sk89q.craftbook.InsufficientArgumentsException;
  22. import com.sk89q.craftbook.access.BaseEntityInterface;
  23. import com.sk89q.craftbook.access.MinecartInterface;
  24. import com.sk89q.craftbook.access.PlayerInterface;
  25. import com.sk89q.craftbook.access.SignInterface;
  26. import com.sk89q.craftbook.util.BlockVector;
  27. import com.sk89q.craftbook.util.Vector;
  28. import java.util.logging.Level;
  29. import java.util.logging.Logger;
  30. /**
  31. * This is CraftBook's main event listener for Hey0's server mod. "Delegate"
  32. * listeners are also used for different features and this listener acts
  33. * as a proxy for some custom hooks and events.
  34. *
  35. * @author sk89q
  36. */
  37. public class CraftBookListener extends PluginListener
  38. implements Runnable,
  39. SignPatch.ExtensionListener {
  40. /**
  41. * Logger instance.
  42. */
  43. static final Logger logger = Logger.getLogger("Minecraft.CraftBook");
  44. /**
  45. * Stores an instance of the plugin. This is used to register delegate
  46. * listeners and access some global features.
  47. */
  48. private CraftBook main;
  49. private HmodWorldImpl w;
  50. /**
  51. * Construct the object.
  52. *
  53. * @param craftBook
  54. */
  55. public CraftBookListener(CraftBook craftBook) {
  56. main = craftBook;
  57. w = main.getWorld();
  58. }
  59. public void run() {
  60. for (CraftBookDelegateListener l : main.tickListeners) { l.onTick(w); }
  61. }
  62. public void onSignAdded(int x, int y, int z) {
  63. for (CraftBookDelegateListener l : main.signCreateListeners) { l.onSignCreate(w, x, y, z); }
  64. }
  65. public boolean onSignChange(Player p, Sign sp) {
  66. PlayerInterface player = new HmodPlayerImpl(p, w);
  67. BlockVector signPosition = new BlockVector(sp.getX(), sp.getY(), sp.getZ());
  68. SignInterface s = new HmodSignImpl(w, signPosition, sp);
  69. for (CraftBookDelegateListener l : main.signChangeListeners) {
  70. if (l.onSignChange(player, w, signPosition, s)) return true;
  71. }
  72. return false;
  73. }
  74. /**
  75. * Called on command.
  76. *
  77. * @param player
  78. * @param split
  79. *
  80. * @return whether the command was processed
  81. */
  82. @Override
  83. public boolean onCommand(Player player, String[] split) {
  84. try {
  85. if (split[0].equalsIgnoreCase("/reload")
  86. && player.canUseCommand("/reload")
  87. && split.length > 1
  88. && (split[1].equalsIgnoreCase("CraftBook")
  89. || split[1].equals("*"))) {
  90. // Redirect log messages to the player's chat.
  91. LoggerToChatHandler handler = new LoggerToChatHandler(player);
  92. handler.setLevel(Level.ALL);
  93. Logger minecraftLogger = Logger.getLogger("Minecraft");
  94. minecraftLogger.addHandler(handler);
  95. try {
  96. main.loadConfiguration();
  97. player.sendMessage("CraftBook configuration reloaded.");
  98. } catch (Throwable t) {
  99. player.sendMessage("Error while reloading: "
  100. + t.getMessage());
  101. } finally {
  102. minecraftLogger.removeHandler(handler);
  103. }
  104. return !split[1].equals("*");
  105. }
  106. PlayerInterface myPlayer = new HmodPlayerImpl(player, w);
  107. for (CraftBookDelegateListener listener : main.commandListeners) {
  108. if (listener.onCommand(myPlayer, split)) return true;
  109. }
  110. return false;
  111. } catch (InsufficientArgumentsException e) {
  112. player.sendMessage(Colors.Rose + e.getMessage());
  113. return true;
  114. }
  115. }
  116. public boolean onConsoleCommand(String[] split) {
  117. for (CraftBookDelegateListener listener : main.consoleCommandListeners) {
  118. if (listener.onConsoleCommand(split)) return true;
  119. }
  120. return false;
  121. }
  122. /**
  123. * Called on redstone change.
  124. *
  125. * @param block
  126. * @param oldLevel
  127. * @param newLevel
  128. */
  129. public int onRedstoneChange(Block block, int oldLevel, int newLevel) {
  130. BlockVector v = new BlockVector(block.getX(), block.getY(), block.getZ());
  131. // Give the method a BlockVector instead of a Block
  132. boolean wasOn = oldLevel >= 1;
  133. boolean isOn = newLevel >= 1;
  134. boolean wasChange = wasOn != isOn;
  135. // For efficiency reasons, we're only going to consider changes between
  136. // off and on state, and ignore simple current changes (i.e. 15->13)
  137. if (!wasChange) {
  138. return newLevel;
  139. }
  140. int x = v.getBlockX();
  141. int y = v.getBlockY();
  142. int z = v.getBlockZ();
  143. int type = w.getId(x, y, z);
  144. // When this hook has been called, the level in the world has not
  145. // yet been updated, so we're going to do this very ugly thing of
  146. // faking the value with the new one whenever the data value of this
  147. // block is requested -- it is quite ugly
  148. try {
  149. if (type == BlockType.LEVER) {
  150. // Fake data
  151. w.fakeData(x, y, z,
  152. newLevel > 0
  153. ? w.getData(x, y, z) | 0x8
  154. : w.getData(x, y, z) & 0x7);
  155. } else if (type == BlockType.STONE_PRESSURE_PLATE) {
  156. // Fake data
  157. w.fakeData(x, y, z,
  158. newLevel > 0
  159. ? w.getData(x, y, z) | 0x1
  160. : w.getData(x, y, z) & 0x14);
  161. } else if (type == BlockType.WOODEN_PRESSURE_PLATE) {
  162. // Fake data
  163. w.fakeData(x, y, z,
  164. newLevel > 0
  165. ? w.getData(x, y, z) | 0x1
  166. : w.getData(x, y, z) & 0x14);
  167. } else if (type == BlockType.STONE_BUTTON) {
  168. // Fake data
  169. w.fakeData(x, y, z,
  170. newLevel > 0
  171. ? w.getData(x, y, z) | 0x8
  172. : w.getData(x, y, z) & 0x7);
  173. } else if (type == BlockType.REDSTONE_WIRE) {
  174. // Fake data
  175. w.fakeData(x, y, z, newLevel);
  176. int westSide = w.getId(x, y, z + 1);
  177. int westSideAbove = w.getId(x, y + 1, z + 1);
  178. int westSideBelow = w.getId(x, y - 1, z + 1);
  179. int eastSide = w.getId(x, y, z - 1);
  180. int eastSideAbove = w.getId(x, y + 1, z - 1);
  181. int eastSideBelow = w.getId(x, y - 1, z - 1);
  182. int northSide = w.getId(x - 1, y, z);
  183. int northSideAbove = w.getId(x - 1, y + 1, z);
  184. int northSideBelow = w.getId(x - 1, y - 1, z);
  185. int southSide = w.getId(x + 1, y, z);
  186. int southSideAbove = w.getId(x + 1, y + 1, z);
  187. int southSideBelow = w.getId(x + 1, y - 1, z);
  188. // Make sure that the wire points to only this block
  189. if (!BlockType.isRedstoneBlock(westSide)
  190. && !BlockType.isRedstoneBlock(eastSide)
  191. && (!BlockType.isRedstoneBlock(westSideAbove) || westSide == 0)
  192. && (!BlockType.isRedstoneBlock(eastSideAbove) || eastSide == 0)
  193. && (!BlockType.isRedstoneBlock(westSideBelow) || westSide != 0)
  194. && (!BlockType.isRedstoneBlock(eastSideBelow) || eastSide != 0)) {
  195. // Possible blocks north / south
  196. handleDirectWireInput(new Vector(x - 1, y, z), isOn, v);
  197. handleDirectWireInput(new Vector(x + 1, y, z), isOn, v);
  198. handleDirectWireInput(new Vector(x - 1, y - 1, z), isOn, v);
  199. handleDirectWireInput(new Vector(x + 1, y - 1, z), isOn, v);
  200. }
  201. if (!BlockType.isRedstoneBlock(northSide)
  202. && !BlockType.isRedstoneBlock(southSide)
  203. && (!BlockType.isRedstoneBlock(northSideAbove) || northSide == 0)
  204. && (!BlockType.isRedstoneBlock(southSideAbove) || southSide == 0)
  205. && (!BlockType.isRedstoneBlock(northSideBelow) || northSide != 0)
  206. && (!BlockType.isRedstoneBlock(southSideBelow) || southSide != 0)) {
  207. // Possible blocks west / east
  208. handleDirectWireInput(new Vector(x, y, z - 1), isOn, v);
  209. handleDirectWireInput(new Vector(x, y, z + 1), isOn, v);
  210. handleDirectWireInput(new Vector(x, y - 1, z - 1), isOn, v);
  211. handleDirectWireInput(new Vector(x, y - 1, z + 1), isOn, v);
  212. }
  213. // Can be triggered from below
  214. handleDirectWireInput(new Vector(x, y + 1, z), isOn, v);
  215. return newLevel;
  216. }
  217. // For redstone wires, the code already exited this method
  218. // Non-wire blocks proceed
  219. handleDirectWireInput(new Vector(x - 1, y, z), isOn, v);
  220. handleDirectWireInput(new Vector(x + 1, y, z), isOn, v);
  221. handleDirectWireInput(new Vector(x - 1, y - 1, z), isOn, v);
  222. handleDirectWireInput(new Vector(x + 1, y - 1, z), isOn, v);
  223. handleDirectWireInput(new Vector(x, y, z - 1), isOn, v);
  224. handleDirectWireInput(new Vector(x, y, z + 1), isOn, v);
  225. handleDirectWireInput(new Vector(x, y - 1, z - 1), isOn, v);
  226. handleDirectWireInput(new Vector(x, y - 1, z + 1), isOn, v);
  227. // Can be triggered from below
  228. handleDirectWireInput(new Vector(x, y + 1, z), isOn, v);
  229. return newLevel;
  230. } finally {
  231. w.destroyFake();
  232. }
  233. }
  234. /**
  235. * Handles direct redstone input. This method merely passes the call
  236. * onto the delegates for further processing. If a delegate throws an
  237. * exception, it will not be caught here.
  238. *
  239. * @param inputVec
  240. * @param isOn
  241. * @param changed
  242. *
  243. * @see CraftBookDelegateListener#onDirectWireInput(Vector, boolean, Vector)
  244. */
  245. public void handleDirectWireInput(Vector pt, boolean isOn, Vector changed) {
  246. // Call the direct wire input hook of delegates
  247. for (CraftBookDelegateListener listener : main.wireInputListeners) {
  248. listener.onWireInput(w, pt, isOn, changed);
  249. }
  250. }
  251. public void onDisconnect(Player p) {
  252. PlayerInterface player = new HmodPlayerImpl(p, w);
  253. for (CraftBookDelegateListener listener : main.disconnectListeners) { listener.onDisconnect(player); }
  254. }
  255. public boolean onBlockPlace(Player p, Block pp, Block cp, Item itemInHand) {
  256. PlayerInterface player = new HmodPlayerImpl(p, w);
  257. BlockVector pv = new BlockVector(pp.getX(), pp.getY(), pp.getZ());
  258. BlockVector cv = new BlockVector(cp.getX(), cp.getY(), cp.getZ());
  259. for (CraftBookDelegateListener listener : main.blockPlaceListeners) {
  260. if (listener.onBlockPlace(w, player, pv, cv, itemInHand.getItemId()))
  261. return true;
  262. }
  263. return false;
  264. }
  265. public void onBlockRightClicked(Player p, Block cp, Item itemInHand) {
  266. PlayerInterface player = new HmodPlayerImpl(p, w);
  267. BlockVector cv = new BlockVector(cp.getX(), cp.getY(), cp.getZ());
  268. for (CraftBookDelegateListener listener : main.blockRightClickListeners) {
  269. listener.onBlockRightClicked(w, player, cv, itemInHand.getItemId());
  270. }
  271. }
  272. public boolean onBlockDestroy(Player p, Block dp) {
  273. PlayerInterface player = new HmodPlayerImpl(p, w);
  274. BlockVector dv = new BlockVector(dp.getX(), dp.getY(), dp.getZ());
  275. for (CraftBookDelegateListener listener : main.blockDestroyedListeners) {
  276. if (listener.onBlockDestroy(w, player, dv, dp.getStatus()))
  277. return true;
  278. }
  279. return false;
  280. }
  281. public boolean onVehicleDamage(BaseVehicle vehicle, BaseEntity entity, int damage) {
  282. if (!(vehicle instanceof Minecart)) return false;
  283. MinecartInterface m = getMinecart((Minecart) vehicle);
  284. BaseEntityInterface e = new HmodBaseEntityImpl(entity, w);
  285. for (CraftBookDelegateListener listener : main.minecartDamageListeners) {
  286. if (listener.onMinecartDamage(w, m, e, damage))
  287. return true;
  288. }
  289. return false;
  290. }
  291. public void onVehicleUpdate(BaseVehicle vehicle) {
  292. if (!(vehicle instanceof Minecart)) return;
  293. MinecartInterface m = getMinecart((Minecart) vehicle);
  294. for (CraftBookDelegateListener listener : main.minecartVelocityChangeListeners) {
  295. listener.onMinecartVelocityChange(w, m);
  296. }
  297. }
  298. public void onVehiclePositionChange(BaseVehicle vehicle, int x, int y, int z) {
  299. if (!(vehicle instanceof Minecart)) return;
  300. MinecartInterface m = getMinecart((Minecart) vehicle);
  301. for (CraftBookDelegateListener listener : main.minecartPositionChangeListeners) {
  302. listener.onMinecartPositionChange(w, m, x, y, z);
  303. }
  304. }
  305. public void onVehicleEnter(BaseVehicle vehicle, HumanEntity entity) {
  306. if (!(vehicle instanceof Minecart)) return;
  307. MinecartInterface m = getMinecart((Minecart) vehicle);
  308. BaseEntityInterface e = new HmodBaseEntityImpl(entity, w);
  309. boolean entering = vehicle.getPassenger() == null;
  310. for (CraftBookDelegateListener listener : main.minecartEnterListeners) {
  311. listener.onMinecartEnter(w, m, e, entering);
  312. }
  313. }
  314. public void onVehicleDestroyed(BaseVehicle vehicle) {
  315. if (!(vehicle instanceof Minecart)) return;
  316. MinecartInterface m = getMinecart((Minecart) vehicle);
  317. for (CraftBookDelegateListener listener : main.minecartDestroyListeners) { listener.onMinecartDestroyed(w, m); }
  318. }
  319. private MinecartInterface getMinecart(Minecart m) {
  320. if (m.getStorage() == null)
  321. return new HmodMinecartImpl(m, w);
  322. else
  323. return new HmodStorageMinecartImpl(m, w);
  324. }
  325. }