PageRenderTime 60ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/java/za/dats/bukkit/memorystone/util/StructureManager.java

https://github.com/ryantheleach/MemoryStone
Java | 433 lines | 335 code | 81 blank | 17 comment | 73 complexity | 36a15a0ce9ec102ecb2575d16c505cb6 MD5 | raw file
  1. package za.dats.bukkit.memorystone.util;
  2. import java.io.File;
  3. import java.util.ArrayList;
  4. import java.util.Arrays;
  5. import java.util.Collections;
  6. import java.util.Comparator;
  7. import java.util.HashMap;
  8. import java.util.HashSet;
  9. import java.util.List;
  10. import java.util.Map;
  11. import java.util.Set;
  12. import java.util.logging.Logger;
  13. import org.bukkit.Material;
  14. import org.bukkit.World;
  15. import org.bukkit.block.Block;
  16. import org.bukkit.entity.Player;
  17. import org.bukkit.event.block.BlockBreakEvent;
  18. import org.bukkit.plugin.java.JavaPlugin;
  19. import org.bukkit.util.config.Configuration;
  20. import org.bukkit.util.config.ConfigurationNode;
  21. import za.dats.bukkit.memorystone.util.structure.BlockOffset;
  22. import za.dats.bukkit.memorystone.util.structure.Rotator;
  23. import za.dats.bukkit.memorystone.util.structure.Structure;
  24. import za.dats.bukkit.memorystone.util.structure.StructureType;
  25. /**
  26. *
  27. * @author tim (Originally HTTotemManager)
  28. * @author cmdrdats
  29. */
  30. public class StructureManager {
  31. private static final Logger log = Logger.getLogger("Minecraft");
  32. private final JavaPlugin plugin;
  33. private final StructureBlockListener blockListener;
  34. private final String structureTypes_filename = "structuretypes.yml";
  35. private final String structures_filename = "structures.yml";
  36. private List<StructureType> structureTypes;
  37. private List<Structure> structures;
  38. private List<StructureListener> listeners = new ArrayList<StructureListener>();
  39. HashMap<BlockHashable, Set<Structure>> blockhash;
  40. HashMap<String, Set<Structure>> ownerhash;
  41. private final String logPrefix;
  42. public StructureManager(JavaPlugin plugin, String logPrefix) {
  43. this.plugin = plugin;
  44. this.logPrefix = logPrefix;
  45. this.structureTypes = new ArrayList<StructureType>();
  46. this.structures = new ArrayList<Structure>();
  47. this.blockhash = new HashMap<BlockHashable, Set<Structure>>();
  48. this.ownerhash = new HashMap<String, Set<Structure>>();
  49. blockListener = new StructureBlockListener(plugin, this);
  50. }
  51. public void registerEvents() {
  52. blockListener.registerEvents();
  53. loadStructureTypesOrDefault();
  54. loadStructures();
  55. }
  56. public List<Structure> getStructures() {
  57. return new ArrayList<Structure>(this.structures);
  58. }
  59. public List<StructureType> getStructureTypes() {
  60. return new ArrayList<StructureType>(this.structureTypes);
  61. }
  62. public void addStructure(Player player, Structure structure) {
  63. this.structures.add(structure);
  64. // add to block hash
  65. for (Block block : structure.getBlocks()) {
  66. BlockHashable bh = new BlockHashable(block);
  67. Set<Structure> existing = this.blockhash.get(bh);
  68. if (existing == null) {
  69. this.blockhash.put(bh, new HashSet<Structure>(Arrays.asList(structure)));
  70. } else {
  71. existing.add(structure);
  72. }
  73. }
  74. // add to owner hash
  75. String owner = structure.getOwner();
  76. Set<Structure> existing = this.ownerhash.get(owner);
  77. if (existing == null) {
  78. this.ownerhash.put(owner, new HashSet<Structure>(Arrays.asList(structure)));
  79. } else {
  80. existing.add(structure);
  81. }
  82. if (player != null) {
  83. for (StructureListener listener : listeners) {
  84. listener.structurePlaced(player, structure);
  85. }
  86. }
  87. }
  88. public void removeStructure(BlockBreakEvent event, Structure structure) {
  89. this.structures.remove(structure);
  90. // remove from block hash
  91. for (Block block : structure.getBlocks()) {
  92. BlockHashable bh = new BlockHashable(block);
  93. Set<Structure> existing = this.blockhash.get(bh);
  94. existing.remove(structure);
  95. if (existing.isEmpty()) {
  96. this.blockhash.remove(bh);
  97. }
  98. }
  99. // remove from owner hash
  100. String owner = structure.getOwner();
  101. Set<Structure> existing = this.ownerhash.get(owner);
  102. existing.remove(structure);
  103. if (existing.isEmpty()) {
  104. this.ownerhash.remove(owner);
  105. }
  106. for (StructureListener listener : listeners) {
  107. listener.structureDestroyed(event.getPlayer(), structure);
  108. }
  109. }
  110. public Set<Structure> getStructuresFromBlock(Block block) {
  111. BlockHashable bh = new BlockHashable(block);
  112. Set<Structure> structureSet = this.blockhash.get(bh);
  113. if (structureSet == null)
  114. return null;
  115. return new HashSet<Structure>(structureSet);
  116. }
  117. public Set<Structure> getStructuresFromPlayer(Player player) {
  118. String owner = player.getName();
  119. Set<Structure> structureSet = this.ownerhash.get(owner);
  120. if (structureSet == null)
  121. return null;
  122. return new HashSet<Structure>(structureSet);
  123. }
  124. public StructureType getStructureType(String name) {
  125. for (StructureType type : this.structureTypes) {
  126. if (type.getName().equals(name)) {
  127. return type;
  128. }
  129. }
  130. return null;
  131. }
  132. // ---------- Structure type loading/saving ------------------
  133. public void loadStructureTypesOrDefault() {
  134. File structureTypesFile = new File(this.plugin.getDataFolder(), this.structureTypes_filename);
  135. if (!structureTypesFile.isFile()) {
  136. try {
  137. structureTypesFile.getParentFile().mkdirs();
  138. structureTypesFile.createNewFile();
  139. this.saveDefaultStructureTypes();
  140. } catch (Exception ex) {
  141. log.warning(logPrefix+"could not create file " + structureTypesFile.getName());
  142. }
  143. }
  144. this.loadStructureTypes();
  145. }
  146. private void loadStructureTypes() {
  147. File structureTypesFile = new File(this.plugin.getDataFolder(), this.structureTypes_filename);
  148. Configuration conf = new Configuration(structureTypesFile);
  149. conf.load();
  150. List<ConfigurationNode> nodelist = conf.getNodeList("structuretypes", new ArrayList<ConfigurationNode>());
  151. for (ConfigurationNode node : nodelist) {
  152. StructureType structureType = this.yaml2StructureType(node);
  153. if (structureType == null) {
  154. log.warning(logPrefix+"a structure type couldn't be loaded");
  155. } else {
  156. this.structureTypes.add(structureType);
  157. }
  158. }
  159. /*
  160. * Sort the StructureTypes by structure size. This way, larger totems will be found before smaller totems (and
  161. * possibly subtotems).
  162. */
  163. Collections.sort(this.structureTypes, new Comparator<StructureType>() {
  164. public int compare(StructureType o1, StructureType o2) {
  165. return o1.getBlockCount() - o2.getBlockCount();
  166. }
  167. });
  168. Collections.reverse(this.structureTypes);
  169. log.info(logPrefix+"loaded " + this.structureTypes.size() + " structure types");
  170. }
  171. private void saveDefaultStructureTypes() {
  172. File structureTypesFile = new File(this.plugin.getDataFolder(), this.structureTypes_filename);
  173. Configuration conf = new Configuration(structureTypesFile);
  174. List<StructureType> types = new ArrayList<StructureType>();
  175. for (StructureListener listener : listeners) {
  176. listener.generatingDefaultStructureTypes(types);
  177. }
  178. List<Object> yamllist = new ArrayList<Object>();
  179. for (StructureType structureType : types) {
  180. yamllist.add(structureType2yaml(structureType));
  181. }
  182. conf.setProperty("structuretypes", yamllist);
  183. conf.save();
  184. }
  185. private Map<String, Object> structureType2yaml(StructureType structuretype) {
  186. HashMap<String, Object> yamlmap = new HashMap<String, Object>();
  187. yamlmap.put("name", structuretype.getName());
  188. yamlmap.put("rotator", structuretype.getRotator().toString());
  189. yamlmap.put("structure", this.structureTypePattern2yaml(structuretype));
  190. yamlmap.put("metadata", structuretype.getMetadata());
  191. return yamlmap;
  192. }
  193. private List<Object> structureTypePattern2yaml(StructureType structuretype) {
  194. List<Object> yamllist = new ArrayList<Object>();
  195. for (BlockOffset offset : structuretype.getPattern().keySet()) {
  196. Material material = structuretype.getPattern().get(offset);
  197. HashMap<String, Object> part = new HashMap<String, Object>();
  198. part.put("x", offset.getX());
  199. part.put("y", offset.getY());
  200. part.put("z", offset.getZ());
  201. part.put("material", material.toString());
  202. yamllist.add(part);
  203. }
  204. return yamllist;
  205. }
  206. private StructureType yaml2StructureType(ConfigurationNode node) {
  207. StructureType.Prototype prototype = new StructureType.Prototype();
  208. String name = node.getString("name", null);
  209. if (name == null) {
  210. log.warning(logPrefix+"Structure type's name is not set");
  211. return null;
  212. }
  213. prototype.setName(name);
  214. String rotatorstr = node.getString("rotator", null);
  215. if (rotatorstr == null) {
  216. log.warning(logPrefix+"Structure type's rotator is not set");
  217. rotatorstr = ":(";
  218. }
  219. Rotator rotator = Rotator.matchRotator(rotatorstr);
  220. if (rotator == null) {
  221. log.warning(logPrefix+"Structure type's rotator is not valid, using default");
  222. rotator = Rotator.getDefault();
  223. }
  224. prototype.setRotator(rotator);
  225. List<ConfigurationNode> structuretypenodes = node.getNodeList("structure", new ArrayList<ConfigurationNode>());
  226. if (structuretypenodes.isEmpty()) {
  227. log.warning(logPrefix+"Structure type's structure is not set");
  228. return null;
  229. }
  230. for (ConfigurationNode structureNode : structuretypenodes) {
  231. int x = structureNode.getInt("x", Integer.MIN_VALUE);
  232. int y = structureNode.getInt("y", Integer.MIN_VALUE);
  233. int z = structureNode.getInt("z", Integer.MIN_VALUE);
  234. if (x == Integer.MIN_VALUE || y == Integer.MIN_VALUE || z == Integer.MIN_VALUE) {
  235. log.warning(logPrefix+"Structure's x, y, or z is not set");
  236. }
  237. String materialstr = structureNode.getString("material", null);
  238. if (materialstr == null) {
  239. log.warning(logPrefix+"Structure's material is not set");
  240. }
  241. Material material = Material.matchMaterial(materialstr);
  242. if (material == null) {
  243. log.warning(logPrefix+"Structure's material is not recognized");
  244. }
  245. prototype.addBlock(x, y, z, material);
  246. }
  247. prototype.setMetadata((Map<String, String>) node.getProperty("metadata"));
  248. if (prototype.getBlockCount() < 3) {
  249. log.warning(logPrefix+"For technical reasons, the structure's block count must be at least 3");
  250. return null;
  251. }
  252. return new StructureType(prototype);
  253. }
  254. // ---------- Structure loading/saving -----------------------
  255. public void loadStructures() {
  256. File structuresFile = new File(this.plugin.getDataFolder(), this.structures_filename);
  257. Configuration conf = new Configuration(structuresFile);
  258. conf.load();
  259. List<ConfigurationNode> nodelist = conf.getNodeList("structures", new ArrayList<ConfigurationNode>());
  260. for (ConfigurationNode node : nodelist) {
  261. Structure structure = this.yaml2Structure(node);
  262. if (structure == null) {
  263. log.warning(logPrefix+"A structure couldn't be loaded");
  264. } else {
  265. for (StructureListener listener : listeners) {
  266. listener.structureLoaded(structure, node);
  267. }
  268. this.addStructure(null, structure);
  269. }
  270. }
  271. log.info(logPrefix+"Loaded " + this.structures.size() + " structure(s)");
  272. }
  273. public void saveStructures() {
  274. File structuresfile = new File(this.plugin.getDataFolder(), this.structures_filename);
  275. Configuration conf = new Configuration(structuresfile);
  276. List<Object> yamllist = new ArrayList<Object>();
  277. for (Structure structure : this.structures) {
  278. Map<String, Object> structure2yaml = this.structure2yaml(structure);
  279. for (StructureListener listener : listeners) {
  280. listener.structureSaving(structure, structure2yaml);
  281. }
  282. yamllist.add(structure2yaml);
  283. }
  284. log.info(logPrefix+"Saved " + this.structures.size() + " structures");
  285. conf.setProperty("structures", yamllist);
  286. conf.save();
  287. }
  288. private Map<String, Object> structure2yaml(Structure structure) {
  289. HashMap<String, Object> yamlmap = new HashMap<String, Object>();
  290. yamlmap.put("world", structure.getRootBlock().getWorld().getName());
  291. yamlmap.put("x", structure.getRootBlock().getX());
  292. yamlmap.put("y", structure.getRootBlock().getY());
  293. yamlmap.put("z", structure.getRootBlock().getZ());
  294. yamlmap.put("type", structure.getStructureType().getName());
  295. String owner = structure.getOwner();
  296. if (structure.getOwner() != null) {
  297. yamlmap.put("owner", owner);
  298. }
  299. return yamlmap;
  300. }
  301. private Structure yaml2Structure(ConfigurationNode node) {
  302. String name = node.getString("name", "structure");
  303. String worldstr = node.getString("world", null);
  304. if (worldstr == null) {
  305. log.warning(logPrefix+name+": world is not set");
  306. return null;
  307. }
  308. int x = node.getInt("x", Integer.MIN_VALUE);
  309. int y = node.getInt("y", Integer.MIN_VALUE);
  310. int z = node.getInt("z", Integer.MIN_VALUE);
  311. if (x == Integer.MIN_VALUE || y == Integer.MIN_VALUE || z == Integer.MIN_VALUE) {
  312. log.warning(logPrefix+name+": x, y, or z is not set");
  313. return null;
  314. }
  315. String structureTypeStr = node.getString("type", null);
  316. if (structureTypeStr == null) {
  317. log.warning(logPrefix+name+": type is not set");
  318. return null;
  319. }
  320. String owner = node.getString("owner", null);
  321. if (owner == null) {
  322. // log.warning("totem's owner is not set");
  323. // do nothing
  324. }
  325. World world = this.plugin.getServer().getWorld(worldstr);
  326. if (world == null) {
  327. log.warning(logPrefix+name+": world is not recognized");
  328. return null;
  329. }
  330. StructureType structureType = this.getStructureType(structureTypeStr);
  331. if (structureType == null) {
  332. log.warning(logPrefix+name+": type of "+structureTypeStr+" is not recognized");
  333. return null;
  334. }
  335. Block block = world.getBlockAt(x, y, z);
  336. Structure structure = new Structure(structureType, block, owner);
  337. if (!structure.verifyStructure()) {
  338. log.warning(logPrefix+name+": structure was bad");
  339. return null;
  340. }
  341. return structure;
  342. }
  343. public void addStructureListener(StructureListener listener) {
  344. listeners.add(listener);
  345. }
  346. public void removeStructureListener(StructureListener listener) {
  347. listeners.remove(listener);
  348. }
  349. public Structure checkForStone(Player player, Block behind) {
  350. return blockListener.checkPlacedBlock(player, behind, null);
  351. }
  352. }