--- a/net/minecraft/server/CraftingManager.java +++ b/net/minecraft/server/CraftingManager.java @@ -23,11 +23,13 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; // CraftBukkit + public class CraftingManager extends ResourceDataJson { private static final Gson a = (new GsonBuilder()).setPrettyPrinting().disableHtmlEscaping().create(); private static final Logger LOGGER = LogManager.getLogger(); - public Map, Map>> recipes = ImmutableMap.of(); + public Map, Object2ObjectLinkedOpenHashMap>> recipes = ImmutableMap.of(); // CraftBukkit private boolean d; public CraftingManager() { @@ -36,7 +38,12 @@ protected void a(Map map, IResourceManager iresourcemanager, GameProfilerFiller gameprofilerfiller) { this.d = false; - Map, Builder>> map1 = Maps.newHashMap(); + // CraftBukkit start - SPIGOT-5667 make sure all types are populated and mutable + Map, Object2ObjectLinkedOpenHashMap>> map1 = Maps.newHashMap(); + for (Recipes recipeType : IRegistry.RECIPE_TYPE) { + map1.put(recipeType, new Object2ObjectLinkedOpenHashMap<>()); + } + // CraftBukkit end Iterator iterator = map.entrySet().iterator(); while (iterator.hasNext()) { @@ -46,24 +53,42 @@ try { IRecipe irecipe = a(minecraftkey, ChatDeserializer.m((JsonElement) entry.getValue(), "top element")); - ((Builder) map1.computeIfAbsent(irecipe.g(), (recipes) -> { - return ImmutableMap.builder(); - })).put(minecraftkey, irecipe); + // CraftBukkit start - SPIGOT-4638: last recipe gets priority + (map1.computeIfAbsent(irecipe.g(), (recipes) -> { + return new Object2ObjectLinkedOpenHashMap<>(); + })).putAndMoveToFirst(minecraftkey, irecipe); + // CraftBukkit end } catch (IllegalArgumentException | JsonParseException jsonparseexception) { CraftingManager.LOGGER.error("Parsing error loading recipe {}", minecraftkey, jsonparseexception); } } this.recipes = (Map) map1.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry1) -> { - return ((Builder) entry1.getValue()).build(); + return (entry1.getValue()); // CraftBukkit })); CraftingManager.LOGGER.info("Loaded {} recipes", map1.size()); } + // CraftBukkit start + public void addRecipe(IRecipe irecipe) { + Object2ObjectLinkedOpenHashMap> map = this.recipes.get(irecipe.g()); // CraftBukkit + + if (map.containsKey(irecipe.getKey())) { + throw new IllegalStateException("Duplicate recipe ignored with ID " + irecipe.getKey()); + } else { + map.putAndMoveToFirst(irecipe.getKey(), irecipe); // CraftBukkit - SPIGOT-4638: last recipe gets priority + } + } + // CraftBukkit end + public > Optional craft(Recipes recipes, C c0, World world) { - return this.b(recipes).values().stream().flatMap((irecipe) -> { + // CraftBukkit start + Optional recipe = this.b(recipes).values().stream().flatMap((irecipe) -> { return SystemUtils.a(recipes.a(irecipe, world, c0)); }).findFirst(); + c0.setCurrentRecipe(recipe.orElse(null)); // CraftBukkit - Clear recipe when no recipe is found + // CraftBukkit end + return recipe; } public > List a(Recipes recipes) { @@ -81,7 +106,7 @@ } private > Map> b(Recipes recipes) { - return (Map) this.recipes.getOrDefault(recipes, Collections.emptyMap()); + return (Map) this.recipes.getOrDefault(recipes, new Object2ObjectLinkedOpenHashMap<>()); // CraftBukkit } public > NonNullList c(Recipes recipes, C c0, World world) { @@ -102,7 +127,7 @@ public Optional> a(MinecraftKey minecraftkey) { return this.recipes.values().stream().map((map) -> { - return (IRecipe) map.get(minecraftkey); + return map.get(minecraftkey); // CraftBukkit - decompile error }).filter(Objects::nonNull).findFirst(); } @@ -125,4 +150,14 @@ return new JsonSyntaxException("Invalid or unsupported recipe type '" + s + "'"); })).a(minecraftkey, jsonobject); } + + // CraftBukkit start + public void clearRecipes() { + this.recipes = Maps.newHashMap(); + + for (Recipes recipeType : IRegistry.RECIPE_TYPE) { + this.recipes.put(recipeType, new Object2ObjectLinkedOpenHashMap<>()); + } + } + // CraftBukkit end }