PageRenderTime 5665ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/mechanisms/src/main/java/com/sk89q/craftbook/mech/CauldronCookbook.java

http://github.com/sk89q/craftbook
Java | 314 lines | 163 code | 38 blank | 113 comment | 30 complexity | 0adeb8da9f345c26728caab5f657aff2 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. package com.sk89q.craftbook.mech;
  20. import com.sk89q.craftbook.util.Tuple2;
  21. import java.io.*;
  22. import java.util.*;
  23. import java.util.logging.Level;
  24. import java.util.logging.Logger;
  25. import java.util.regex.Pattern;
  26. //import java.io.*;
  27. /**
  28. * Store of recipes.
  29. *
  30. * @author sk89q
  31. * @deprecated Use {@link com.sk89q.craftbook.mech.cauldron.ImprovedCauldronCookbook} instead
  32. */
  33. @Deprecated
  34. public class CauldronCookbook {
  35. private static final Pattern AT_PATTERN = Pattern.compile("@", Pattern.LITERAL);
  36. private static final Pattern COMMA_PATTERN = Pattern.compile(",", Pattern.LITERAL);
  37. private static final Pattern COLON_PATTERN = Pattern.compile(":", Pattern.LITERAL);
  38. private static final Pattern ANYTHING_MULTIPLIED_BY_NUMBER_PATTERN = Pattern.compile("^.*\\*([0-9]+)$");
  39. /**
  40. * Constructs a CauldronCookbook - reads recipes.
  41. */
  42. public CauldronCookbook() {
  43. try {
  44. CauldronCookbook recipes = readCauldronRecipes("cauldron-recipes.txt");
  45. if (recipes.size() != 0) {
  46. log.info(recipes.size()
  47. + " cauldron recipe(s) loaded");
  48. } else {
  49. log.warning("cauldron-recipes.txt had no recipes");
  50. }
  51. } catch (FileNotFoundException e) {
  52. log.info("cauldron-recipes.txt not found: " + e.getMessage());
  53. try {
  54. log.info("Looked in: " + new File(".").getCanonicalPath() + "/plugins/CraftBookMechanisms");
  55. } catch (IOException ioe) {
  56. // Eat error
  57. }
  58. } catch (IOException e) {
  59. log.warning("cauldron-recipes.txt not loaded: " + e.getMessage());
  60. }
  61. }
  62. /**
  63. * For fast recipe lookup.
  64. */
  65. private final List<Recipe> recipes = new ArrayList<Recipe>();
  66. /**
  67. * For logging purposes.
  68. */
  69. static final Logger log = Logger.getLogger("Minecraft");
  70. /**
  71. * Adds a recipe.
  72. *
  73. * @param recipe
  74. */
  75. public void add(Recipe recipe) {
  76. recipes.add(recipe);
  77. }
  78. /**
  79. * Gets a recipe by its ingredients. If multiple recipies have the all of
  80. * the specified ingredients, the first one that matches will be selected
  81. * (the list is checked in the same order as recipes are entered in the
  82. * config file).
  83. *
  84. * @param ingredients
  85. *
  86. * @return a recipe matching the given ingredients
  87. */
  88. public Recipe find(Map<Tuple2<Integer, Short>, Integer> ingredients) {
  89. for (Recipe recipe : recipes)
  90. if (recipe.hasAllIngredients(ingredients))
  91. return recipe;
  92. return null;
  93. }
  94. /**
  95. * Get the number of recipes.
  96. *
  97. * @return the number of recipes.
  98. */
  99. public int size() {
  100. return recipes.size();
  101. }
  102. private CauldronCookbook readCauldronRecipes(String path)
  103. throws IOException {
  104. File file = new File("plugins/CraftBookMechanisms", path);
  105. FileReader input = null;
  106. try {
  107. input = new FileReader(file);
  108. BufferedReader buff = new BufferedReader(input);
  109. String line;
  110. while ((line = buff.readLine()) != null) {
  111. line = line.trim();
  112. // Blank lines
  113. if (line.isEmpty()) {
  114. continue;
  115. }
  116. // Comment
  117. if (line.charAt(0) == ';' || line.charAt(0) == '#' || line.isEmpty()) {
  118. continue;
  119. }
  120. String[] parts = COLON_PATTERN.split(line);
  121. if (parts.length < 3) {
  122. log.log(Level.WARNING, "Invalid cauldron recipe line in "
  123. + file.getName() + ": '" + line + "'");
  124. } else {
  125. String name = parts[0];
  126. List<Tuple2<Integer, Short>> ingredients = parseCauldronItems(parts[1]);
  127. List<Tuple2<Integer, Short>> results = parseCauldronItems(parts[2]);
  128. String[] groups = null;
  129. if (parts.length >= 4 && !parts[3].trim().isEmpty()) {
  130. groups = COMMA_PATTERN.split(parts[3]);
  131. }
  132. Recipe recipe =
  133. new Recipe(name, ingredients, results, groups);
  134. add(recipe);
  135. }
  136. }
  137. return this;
  138. } finally {
  139. try {
  140. if (input != null) {
  141. input.close();
  142. }
  143. } catch (IOException ignored) {
  144. }
  145. }
  146. }
  147. /**
  148. * Parse a list of cauldron items.
  149. */
  150. private List<Tuple2<Integer, Short>> parseCauldronItems(String list) {
  151. String[] parts = COMMA_PATTERN.split(list);
  152. List<Tuple2<Integer, Short>> out = new ArrayList<Tuple2<Integer, Short>>();
  153. for (String part : parts) {
  154. int multiplier = 1;
  155. try {
  156. // Multiplier
  157. if (ANYTHING_MULTIPLIED_BY_NUMBER_PATTERN.matcher(part).matches()) {
  158. int at = part.lastIndexOf('*');
  159. multiplier = Integer.parseInt(part.substring(at + 1, part.length()));
  160. part = part.substring(0, at);
  161. }
  162. try {
  163. Short s = 0;
  164. String[] split = AT_PATTERN.split(part);
  165. Integer id = Integer.valueOf(split[0]);
  166. if (split.length > 1) {
  167. s = Short.valueOf(split[1]);
  168. }
  169. for (int i = 0; i < multiplier; i++) {
  170. out.add(new Tuple2<Integer, Short>(id, s));
  171. }
  172. } catch (NumberFormatException e) {
  173. /*int item = server.getConfiguration().getItemId(part);
  174. if (item > 0) {
  175. for (int i = 0; i < multiplier; i++) {
  176. out.add(item);
  177. }
  178. } else {*/
  179. log.log(Level.WARNING, "Cauldron: Unknown item " + part);
  180. //}
  181. }
  182. } catch (NumberFormatException e) { // Bad multiplier
  183. log.log(Level.WARNING, "Cauldron: Bad multiplier in '" + part + "'");
  184. }
  185. }
  186. return out;
  187. }
  188. /**
  189. * @author sk89q
  190. */
  191. public static final class Recipe {
  192. /**
  193. * Recipe name.
  194. */
  195. private final String name;
  196. /**
  197. * Stores a list of ingredients.
  198. */
  199. private final List<Tuple2<Integer, Short>> ingredients;
  200. /**
  201. * Stores a list of ingredients.
  202. */
  203. private final Map<Tuple2<Integer, Short>, Integer> ingredientLookup
  204. = new HashMap<Tuple2<Integer, Short>, Integer>();
  205. /**
  206. * List of resulting items or blocks.
  207. */
  208. private final List<Tuple2<Integer, Short>> results;
  209. /**
  210. * List of groups that can use this recipe. This may be null.
  211. */
  212. private final String[] groups;
  213. /**
  214. * Construct the instance. The list will be sorted.
  215. *
  216. * @param name
  217. * @param ingredients
  218. * @param results
  219. * @param groups
  220. */
  221. public Recipe(String name, List<Tuple2<Integer, Short>> ingredients,
  222. List<Tuple2<Integer, Short>> results, String[] groups) {
  223. this.name = name;
  224. this.ingredients = Collections.unmodifiableList(ingredients);
  225. this.results = Collections.unmodifiableList(results);
  226. this.groups = groups;
  227. // Make a list of required ingredients by item ID
  228. for (Tuple2<Integer, Short> id : ingredients)
  229. if (ingredientLookup.containsKey(id)) {
  230. ingredientLookup.put(id, ingredientLookup.get(id) + 1);
  231. } else {
  232. ingredientLookup.put(id, 1);
  233. }
  234. }
  235. /**
  236. * @return the name
  237. */
  238. public String getName() {
  239. return name;
  240. }
  241. /**
  242. * @return the ingredients
  243. */
  244. public List<Tuple2<Integer, Short>> getIngredients() {
  245. return ingredients;
  246. }
  247. /**
  248. * @return the groups
  249. */
  250. public String[] getGroups() {
  251. return groups;
  252. }
  253. /**
  254. * Checks to see if all the ingredients are met.
  255. *
  256. * @param check
  257. */
  258. public boolean hasAllIngredients(Map<Tuple2<Integer, Short>, Integer> check) {
  259. for (Map.Entry<Tuple2<Integer, Short>, Integer> entry : ingredientLookup.entrySet()) {
  260. Tuple2<Integer, Short> id = entry.getKey();
  261. if (!check.containsKey(id))
  262. return false;
  263. else if (check.get(id) < entry.getValue())
  264. return false;
  265. }
  266. return true;
  267. }
  268. /**
  269. * @return the results
  270. */
  271. public List<Tuple2<Integer, Short>> getResults() {
  272. return results;
  273. }
  274. }
  275. }