From 8035f1525bdaeb1462d5ee66d3293faa17311735 Mon Sep 17 00:00:00 2001 From: Justinas Launikonis <95593194+JustinasLa@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:12:43 +0200 Subject: [PATCH] feat: fry eggs, grill mushrooms and pop chopped corn into popcorn in the frying pan A cooking option can now name an output food (types.yml cooking-options ..output). In the frying pan the piece cooks raw, then turns into that food once it's done or burnt, keeping its stars, ageing tracks, lineage and ingredients (and its origin when the output names none), and goes on cooking by the same clock, so popcorn left too long burns as popcorn. It takes the output's name. A type whose only options have outputs carries no Raw tag until it's in the pan, and a piece taken off before it turned comes back as it went in. Chopped corn pops into Popcorn, and vanilla brown and red mushrooms (new mushroom type and conversions) grill into Grilled Mushroom, with burnt and rotten looks for both. Co-Authored-By: Claude Opus 5.5 --- .../tfmc_cooking/contents/categories.yml | 6 + .../tfmc_cooking/contents/intermediates.yml | 28 ++ ItemsAdder/tfmc_cooking/contents/items.yml | 14 + .../intermediate/grilled_mushroom_burnt.json | 4 + .../intermediate/grilled_mushroom_rotten.json | 4 + .../item/intermediate/popcorn_burnt.json | 4 + .../item/intermediate/popcorn_rotten.json | 4 + .../item/vanilla/brown_mushroom_rotten.json | 4 + .../item/vanilla/red_mushroom_rotten.json | 4 + .../intermediate/grilled_mushroom_burnt.png | Bin 0 -> 215 bytes .../intermediate/grilled_mushroom_rotten.png | Bin 0 -> 229 bytes .../item/intermediate/popcorn_burnt.png | Bin 0 -> 337 bytes .../item/intermediate/popcorn_rotten.png | Bin 0 -> 366 bytes .../item/vanilla/brown_mushroom_rotten.png | Bin 0 -> 139 bytes .../item/vanilla/red_mushroom_rotten.png | Bin 0 -> 148 bytes README.md | 2 +- .../cooking/cooking/CookingOutput.java | 96 +++++++ .../cooking/cooking/CookingReference.java | 14 + .../cooking/cooking/FryingReference.java | 25 +- .../tfminecraft/cooking/item/FoodItem.java | 2 +- .../cooking/item/data/CookData.java | 16 +- .../cooking/item/data/CookParameter.java | 20 ++ .../cooking/utils/ItemBuilder.java | 51 ++-- src/main/resources/config.yml | 1 + src/main/resources/conversions.yml | 2 + src/main/resources/models.yml | 117 ++++++++ src/main/resources/types.yml | 60 +++- .../cooking/cooking/PanFoodsCoverageTest.java | 263 ++++++++++++++++++ .../utils/ItemBuilderCoverageTest.java | 8 + 29 files changed, 720 insertions(+), 29 deletions(-) create mode 100644 ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/intermediate/grilled_mushroom_burnt.json create mode 100644 ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/intermediate/grilled_mushroom_rotten.json create mode 100644 ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/intermediate/popcorn_burnt.json create mode 100644 ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/intermediate/popcorn_rotten.json create mode 100644 ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/vanilla/brown_mushroom_rotten.json create mode 100644 ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/vanilla/red_mushroom_rotten.json create mode 100644 ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/intermediate/grilled_mushroom_burnt.png create mode 100644 ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/intermediate/grilled_mushroom_rotten.png create mode 100644 ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/intermediate/popcorn_burnt.png create mode 100644 ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/intermediate/popcorn_rotten.png create mode 100644 ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/vanilla/brown_mushroom_rotten.png create mode 100644 ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/vanilla/red_mushroom_rotten.png create mode 100644 src/main/java/net/tfminecraft/cooking/cooking/CookingOutput.java create mode 100644 src/test/java/net/tfminecraft/cooking/cooking/PanFoodsCoverageTest.java diff --git a/ItemsAdder/tfmc_cooking/contents/categories.yml b/ItemsAdder/tfmc_cooking/contents/categories.yml index 687220e..619cd3d 100644 --- a/ItemsAdder/tfmc_cooking/contents/categories.yml +++ b/ItemsAdder/tfmc_cooking/contents/categories.yml @@ -82,6 +82,8 @@ categories: - tfmc_cooking:carrot_rotten - tfmc_cooking:wheat_rotten - tfmc_cooking:apple_rotten + - tfmc_cooking:brown_mushroom_rotten + - tfmc_cooking:red_mushroom_rotten - tfmc_cooking:egg_rotten - tfmc_cooking:beetroot_rotten - tfmc_cooking:potato_rotten @@ -307,12 +309,16 @@ categories: - tfmc_cooking:fried_egg_burnt - tfmc_cooking:fried_egg_rotten - tfmc_cooking:grilled_mushroom + - tfmc_cooking:grilled_mushroom_burnt + - tfmc_cooking:grilled_mushroom_rotten - tfmc_cooking:maple_syrup - tfmc_cooking:mashed_potatoes - tfmc_cooking:mustard - tfmc_cooking:mustard_seeds - tfmc_cooking:olive_oil - tfmc_cooking:popcorn + - tfmc_cooking:popcorn_burnt + - tfmc_cooking:popcorn_rotten - tfmc_cooking:rice - tfmc_cooking:stock - tfmc_cooking:sunflower_seeds diff --git a/ItemsAdder/tfmc_cooking/contents/intermediates.yml b/ItemsAdder/tfmc_cooking/contents/intermediates.yml index 4b74aae..2394993 100644 --- a/ItemsAdder/tfmc_cooking/contents/intermediates.yml +++ b/ItemsAdder/tfmc_cooking/contents/intermediates.yml @@ -203,3 +203,31 @@ items: material: PAPER generate: false model_path: item/intermediate/tomato_sauce + + grilled_mushroom_burnt: + display_name: "Grilled Mushroom Burnt" + resource: + material: PAPER + generate: false + model_path: item/intermediate/grilled_mushroom_burnt + + grilled_mushroom_rotten: + display_name: "Grilled Mushroom Rotten" + resource: + material: PAPER + generate: false + model_path: item/intermediate/grilled_mushroom_rotten + + popcorn_burnt: + display_name: "Popcorn Burnt" + resource: + material: PAPER + generate: false + model_path: item/intermediate/popcorn_burnt + + popcorn_rotten: + display_name: "Popcorn Rotten" + resource: + material: PAPER + generate: false + model_path: item/intermediate/popcorn_rotten diff --git a/ItemsAdder/tfmc_cooking/contents/items.yml b/ItemsAdder/tfmc_cooking/contents/items.yml index ae06fee..48a3457 100644 --- a/ItemsAdder/tfmc_cooking/contents/items.yml +++ b/ItemsAdder/tfmc_cooking/contents/items.yml @@ -1626,3 +1626,17 @@ items: material: TROPICAL_FISH generate: false model_path: item/ingredients/poultry/poultry_roast_filet_rotten + + brown_mushroom_rotten: + display_name: "Brown Mushroom Rotten" + resource: + material: PAPER + generate: false + model_path: item/vanilla/brown_mushroom_rotten + + red_mushroom_rotten: + display_name: "Red Mushroom Rotten" + resource: + material: PAPER + generate: false + model_path: item/vanilla/red_mushroom_rotten diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/intermediate/grilled_mushroom_burnt.json b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/intermediate/grilled_mushroom_burnt.json new file mode 100644 index 0000000..ce244ce --- /dev/null +++ b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/intermediate/grilled_mushroom_burnt.json @@ -0,0 +1,4 @@ +{ + "parent": "minecraft:item/generated", + "textures": { "layer0": "tfmc_cooking:item/intermediate/grilled_mushroom_burnt" } +} diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/intermediate/grilled_mushroom_rotten.json b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/intermediate/grilled_mushroom_rotten.json new file mode 100644 index 0000000..f10a3c4 --- /dev/null +++ b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/intermediate/grilled_mushroom_rotten.json @@ -0,0 +1,4 @@ +{ + "parent": "minecraft:item/generated", + "textures": { "layer0": "tfmc_cooking:item/intermediate/grilled_mushroom_rotten" } +} diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/intermediate/popcorn_burnt.json b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/intermediate/popcorn_burnt.json new file mode 100644 index 0000000..c42d908 --- /dev/null +++ b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/intermediate/popcorn_burnt.json @@ -0,0 +1,4 @@ +{ + "parent": "minecraft:item/generated", + "textures": { "layer0": "tfmc_cooking:item/intermediate/popcorn_burnt" } +} diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/intermediate/popcorn_rotten.json b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/intermediate/popcorn_rotten.json new file mode 100644 index 0000000..70d32fd --- /dev/null +++ b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/intermediate/popcorn_rotten.json @@ -0,0 +1,4 @@ +{ + "parent": "minecraft:item/generated", + "textures": { "layer0": "tfmc_cooking:item/intermediate/popcorn_rotten" } +} diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/vanilla/brown_mushroom_rotten.json b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/vanilla/brown_mushroom_rotten.json new file mode 100644 index 0000000..e07677c --- /dev/null +++ b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/vanilla/brown_mushroom_rotten.json @@ -0,0 +1,4 @@ +{ + "parent": "minecraft:item/generated", + "textures": { "layer0": "tfmc_cooking:item/vanilla/brown_mushroom_rotten" } +} diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/vanilla/red_mushroom_rotten.json b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/vanilla/red_mushroom_rotten.json new file mode 100644 index 0000000..0d33ac2 --- /dev/null +++ b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/vanilla/red_mushroom_rotten.json @@ -0,0 +1,4 @@ +{ + "parent": "minecraft:item/generated", + "textures": { "layer0": "tfmc_cooking:item/vanilla/red_mushroom_rotten" } +} diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/intermediate/grilled_mushroom_burnt.png b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/intermediate/grilled_mushroom_burnt.png new file mode 100644 index 0000000000000000000000000000000000000000..ea7e5cda23def375e84e9cbeaced9351544ee6eb GIT binary patch literal 215 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`^E_P~Ln>}1cWk(vxPZm@!Wjln z$9exVW>hdcNG)lp{4bo$VQALO>ufY(1LKVx^-~NpoGb(DET#!QWKI^Ct-XLn>}1SA2WTz^po>F^%m- zcE^AB!$+hUE+s5d|9#)XS){K}vMJPflbZmWB-^1IJc_5vW+<}oHe{A<2xv-{PL4ES z+t_Kuuq49KPeQv*vgtZQ3a{eAZU5iqYz;iZA<1CI^6byb;LQix4*UqPWOHIOXb@?2 zvuNPW$m#lbP0l+XkK>{m{r literal 0 HcmV?d00001 diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/intermediate/popcorn_burnt.png b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/intermediate/popcorn_burnt.png new file mode 100644 index 0000000000000000000000000000000000000000..d10b26f807727eed803a90470c6b6ea85e8ff349 GIT binary patch literal 337 zcmV-X0j~auP)yu#*b6+p>=W-w3!ECw>!ONf1HlD04tDBmh71%)v5BW>&t1SjOwaFzA#~@#t1Q jruhF09OsVm8q4Ar)1W&}^5W)d00000NkvXXu0mjfp<|Rc literal 0 HcmV?d00001 diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/intermediate/popcorn_rotten.png b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/intermediate/popcorn_rotten.png new file mode 100644 index 0000000000000000000000000000000000000000..63e402efb03d5203d2f485c6366a602295c3ab8b GIT binary patch literal 366 zcmV-!0g?WRP)~p5^ykEKmi4ED###oFMtd|P7iR+pil*w+R+ye zmH-(N7-|mI2*NN|fWieOA%Qp`&AX0vf^7sTo-{K97!HkK8s-I<0a%kVNCKo8WC%#% znVU1gieUi-3rw7O0ofae&QFB<6Bba&Nf&2kLXLl!Vq`I@4Ll21GBWtQ@p;i(BDo7_I)kUHpUXO@geCxot}O}x literal 0 HcmV?d00001 diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/vanilla/red_mushroom_rotten.png b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/vanilla/red_mushroom_rotten.png new file mode 100644 index 0000000000000000000000000000000000000000..fb98b0eaa4ad2c260a02f271a685abce4b7af126 GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`(Vi}jAr-fh6C_v{H%v>ow{PWt zb@r%3hMu!l>s|>kY5t+$vn4HsIpGhdw{(Xw%aRQT+{D)j9$|ZEVXJDOc2axxx3GWn vEwo?S-(;+OdGXPI1!oPTg!3!w_5khZ)^}UVIYoCH&>99$S3j3^P6 kept = new ArrayList<>(); + for (TagTrack track : piece.getTagTracks()) { + if (track.isAgeable() || COOKED_TRACK.equals(track.getId())) { + kept.add(track); + } + } + for (TagTrack track : kept) { + turned.addOrModifyTrack(track); + turned.setAgeRemainder(track.getId(), piece.getAgeRemainder(track.getId())); + } + int stars = piece.getEffectiveQuality() - TagQuality.stars(kept); + turned.setQualityRange(stars, stars); + turned.setLineage(piece.getLineage()); + for (String ingredient : piece.getIngredients()) { + turned.addIngredient(ingredient); + } + CookData clock = new CookData(turned, piece.getCookData()); + clock.getParameters().replaceAll((m, parameter) -> parameter.withoutOutput()); + turned.cookData = clock; + turned.setLastUpdate(piece.getLastUpdate()); + return turned; + } + + private static String output(FoodItem piece, Method method) { + CookParameter parameter = piece.getCookData().getParameters().get(method); + return parameter == null ? null : parameter.getOutput(); + } +} diff --git a/src/main/java/net/tfminecraft/cooking/cooking/CookingReference.java b/src/main/java/net/tfminecraft/cooking/cooking/CookingReference.java index 2dc6275..3251364 100644 --- a/src/main/java/net/tfminecraft/cooking/cooking/CookingReference.java +++ b/src/main/java/net/tfminecraft/cooking/cooking/CookingReference.java @@ -8,6 +8,7 @@ import org.bukkit.Sound; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; import net.tfminecraft.cooking.cache.ItemCache; import net.tfminecraft.cooking.enums.Method; @@ -90,8 +91,20 @@ public void tick() { } protected void applySlotUpdate(String slot, FoodItem item) { + applySlotUpdate(slot, item, null); + } + + /** Redraws a slot's piece for its food; a non-null name renames it, for a piece that has become another food. */ + // Keep the existing legacy text representation of item names. + @SuppressWarnings("deprecation") + protected void applySlotUpdate(String slot, FoodItem item, String displayName) { if (!f.hasActiveSlot(slot)) return; ItemStack stack = f.getActiveSlot(slot).get().getCurrentItem(); + if (displayName != null && stack != null && stack.hasItemMeta()) { + ItemMeta meta = stack.getItemMeta(); + meta.setDisplayName(displayName); + stack.setItemMeta(meta); + } stack = ItemUpdater.applyItemUpdate(stack, item, f.getId()); if (stack == null) return; f.getActiveSlot(slot).get().forceModel(stack); @@ -196,6 +209,7 @@ public void slotAdd(FurnitureSlotItemAddEvent e) { e.setCancelled(true); return; } + CookingOutput.startRaw(fi, method); if(!fi.hasTag(Tag.RAW)) { e.setCancelled(true); return; diff --git a/src/main/java/net/tfminecraft/cooking/cooking/FryingReference.java b/src/main/java/net/tfminecraft/cooking/cooking/FryingReference.java index b443c36..fc6308d 100644 --- a/src/main/java/net/tfminecraft/cooking/cooking/FryingReference.java +++ b/src/main/java/net/tfminecraft/cooking/cooking/FryingReference.java @@ -20,6 +20,7 @@ import net.tfminecraft.cooking.quality.CompositionQualityResolver; import net.tfminecraft.cooking.quality.CompositionResult; import net.tfminecraft.cooking.utils.IngredientConverter; +import net.tfminecraft.cooking.utils.ItemBuilder; import net.tfminecraft.cooking.utils.ItemUpdater; import net.tfminecraft.cooking.utils.WarmthUtils; import net.tfminecraft.interactiblefurniture.events.FurnitureInteractEvent; @@ -67,24 +68,37 @@ private void handleParticlesAndDanger() { private void handleCookingSlots() { for (Map.Entry entry : slots.entrySet()) { - String slot = entry.getKey(); FoodItem item = entry.getValue(); if (!item.canBeCooked()) continue; if (!item.getCookData().tick()) continue; - applySlotUpdate(slot, item); + showCookStep(entry); } } private void burnAllSlots() { for (Map.Entry entry : slots.entrySet()) { - String slot = entry.getKey(); FoodItem item = entry.getValue(); if (!item.canBeCooked()) continue; item.getCookData().setCurrentTime(item.getCookData().getParameters().get(method).getBurnTime()); - super.applySlotUpdate(slot, item); + showCookStep(entry); } } + /** + * Shows a piece's new cook step. A piece whose pan option names an output becomes that food here (chopped corn + * pops into Popcorn), taking the output's name. + */ + private void showCookStep(Map.Entry entry) { + FoodItem item = entry.getValue(); + FoodItem turned = CookingOutput.turn(item, method); + if (turned == item) { + applySlotUpdate(entry.getKey(), item); + return; + } + entry.setValue(turned); + applySlotUpdate(entry.getKey(), turned, ItemBuilder.displayName(turned)); + } + @Override public void interact(FurnitureInteractEvent e) { Player p = e.getPlayer(); @@ -207,7 +221,8 @@ public void slotRemove(FurnitureSlotItemTakeEvent e) { e.setCancelled(true); return; } - if (data.getCurrentTime() < 5) { + // A piece that hasn't turned into its output yet comes back as it went in, and leaves the butter. + if (CookingOutput.restoreInput(fi, method) || data.getCurrentTime() < 5) { ItemStack returned = ItemUpdater.applyItemUpdate(item, fi, null); if (returned != null) { e.setItem(returned); diff --git a/src/main/java/net/tfminecraft/cooking/item/FoodItem.java b/src/main/java/net/tfminecraft/cooking/item/FoodItem.java index dfabce2..f25b183 100644 --- a/src/main/java/net/tfminecraft/cooking/item/FoodItem.java +++ b/src/main/java/net/tfminecraft/cooking/item/FoodItem.java @@ -203,7 +203,7 @@ public FoodItem(FoodItem other) { for (TagTrack t : other.tags.values()) this.tags.put(t.getId(), new TagTrack(t)); - if(this.canBeCooked() && !hasTagTrack("cooked")) addOrModifyTrack(TrackLoader.getByString("cooked")); + if(cookData.cooksInPlace() && !hasTagTrack("cooked")) addOrModifyTrack(TrackLoader.getByString("cooked")); } diff --git a/src/main/java/net/tfminecraft/cooking/item/data/CookData.java b/src/main/java/net/tfminecraft/cooking/item/data/CookData.java index 7dcb0ac..e97b6cc 100644 --- a/src/main/java/net/tfminecraft/cooking/item/data/CookData.java +++ b/src/main/java/net/tfminecraft/cooking/item/data/CookData.java @@ -20,7 +20,8 @@ public CookData(String id, ConfigurationSection config) { for(String key : config.getKeys(false)) { ConfigurationSection param = config.getConfigurationSection(key); try { - parameters.put(Method.valueOf(key.toUpperCase(java.util.Locale.ROOT)), new CookParameter(param.getInt("tag", 1), param.getInt("time", 15), param.getInt("burn", 30))); + parameters.put(Method.valueOf(key.toUpperCase(java.util.Locale.ROOT)), new CookParameter(param.getInt("tag", 1), param.getInt("time", 15), param.getInt("burn", 30), + param.getString("output", null))); } catch (Exception e) { Bukkit.getLogger().info("Failed to create cooking data for "+id); } @@ -52,6 +53,19 @@ public FoodItem getFoodItem() { public boolean hasMethod(Method m) { return parameters.containsKey(m); } + + /** + * True when some method cooks this food as itself, so it carries a cooked track (Raw) from the start. A food whose + * only options name an output (chopped corn, which pops into popcorn) is not raw until it's in the cookware. + */ + public boolean cooksInPlace() { + for (CookParameter parameter : parameters.values()) { + if (parameter.getOutput() == null) { + return true; + } + } + return false; + } public Method getCurrentMethod() { return currentMethod; } diff --git a/src/main/java/net/tfminecraft/cooking/item/data/CookParameter.java b/src/main/java/net/tfminecraft/cooking/item/data/CookParameter.java index c5fd651..d44158a 100644 --- a/src/main/java/net/tfminecraft/cooking/item/data/CookParameter.java +++ b/src/main/java/net/tfminecraft/cooking/item/data/CookParameter.java @@ -1,14 +1,24 @@ package net.tfminecraft.cooking.item.data; +/** + * One cooking option of a food type (types.yml cooking-options.<method>): the cooked tag it reaches, when, when + * it burns, and optionally the food it turns into once it's done (output), such as chopped corn popping into popcorn. + */ public class CookParameter { private int tag; private int time; private int burntime; + private final String output; public CookParameter(int tag, int time, int burntime) { + this(tag, time, burntime, null); + } + + public CookParameter(int tag, int time, int burntime, String output) { this.tag = tag; this.time = time; this.burntime = burntime; + this.output = output == null || output.isBlank() ? null : output.trim(); } public int getTag() { @@ -20,4 +30,14 @@ public int getTime() { public int getBurnTime() { return burntime; } + + /** The food string this option turns the piece into once it's no longer raw, or null if it stays itself. */ + public String getOutput() { + return output; + } + + /** The same timings without an output: what the piece keeps cooking by once it has turned into its output. */ + public CookParameter withoutOutput() { + return output == null ? this : new CookParameter(tag, time, burntime); + } } diff --git a/src/main/java/net/tfminecraft/cooking/utils/ItemBuilder.java b/src/main/java/net/tfminecraft/cooking/utils/ItemBuilder.java index 3110c62..8fb6bb6 100644 --- a/src/main/java/net/tfminecraft/cooking/utils/ItemBuilder.java +++ b/src/main/java/net/tfminecraft/cooking/utils/ItemBuilder.java @@ -85,27 +85,8 @@ private static ItemStack buildSingleWithQuality(FoodItem template, ItemStack bas item.setAmount(1); - String origin = item.getOrigin(); - String displayName = displayNameOverride != null ? displayNameOverride : item.getName(); + String displayName = displayNameOverride != null ? displayNameOverride : displayName(item, base); - if (displayNameOverride == null) { - if (origin != null) { - OverrideData od = item.getOverrides().get(origin.toUpperCase(Locale.ROOT)); - if (od != null) { - if (od.getName() != null) displayName = od.getName(); - } - } - if (displayName.contains("{inherit}") && base != null) { - displayName = displayName.replace("{inherit}", StringFormatter.getName(base)); - } else if (displayName.contains("{inherit}")) { - displayName = displayName.replace("{inherit}", WordUtils.capitalize(origin != null ? origin : "unknown")); - } - // Names like "{prefixes}{fillers}Bread" are filled from the food's tags and ingredients (Sweet Banana Bread). - if (displayName.equals(item.getName()) && NAME_TOKENS.matcher(displayName).find()) { - displayName = NameComposer.compose(item, Map.of()); - } - } - if (item.getModel() == null) { if (base == null || base.getType().isAir()) return null; item.setModel(new FoodModel(base)); @@ -130,6 +111,36 @@ private static ItemStack buildSingleWithQuality(FoodItem template, ItemStack bas return stack; } + /** The name a new stack of this food gets; see {@link #displayName(FoodItem, ItemStack)}. */ + public static String displayName(FoodItem item) { + return displayName(item, null); + } + + /** + * The name a new stack of this food gets: its origin's override name, else its type's, with {inherit} filled from + * the base item's name or else the origin, and name tokens filled from its tags and ingredients. + */ + private static String displayName(FoodItem item, ItemStack base) { + String origin = item.getOrigin(); + String displayName = item.getName(); + if (origin != null) { + OverrideData od = item.getOverrides().get(origin.toUpperCase(Locale.ROOT)); + if (od != null) { + if (od.getName() != null) displayName = od.getName(); + } + } + if (displayName.contains("{inherit}") && base != null) { + displayName = displayName.replace("{inherit}", StringFormatter.getName(base)); + } else if (displayName.contains("{inherit}")) { + displayName = displayName.replace("{inherit}", WordUtils.capitalize(origin != null ? origin : "unknown")); + } + // Names like "{prefixes}{fillers}Bread" are filled from the food's tags and ingredients (Sweet Banana Bread). + if (displayName.equals(item.getName()) && NAME_TOKENS.matcher(displayName).find()) { + displayName = NameComposer.compose(item, Map.of()); + } + return displayName; + } + static boolean writesAgeClock(FoodItem item) { return item != null && item.shouldUpdate(); } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index f75ba64..4050983 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -180,6 +180,7 @@ dictionary: sauce: "#997950Sauce" garnish: "#0b5394Garnish" liquid: "#3d85c6Liquid" + snack: "#e8c56bSnack" sauce-dict: - ffffff ia.tfmc_cooking:milk|ia.tfmc_cooking:milk_plated diff --git a/src/main/resources/conversions.yml b/src/main/resources/conversions.yml index db68ea1..fd1e3ab 100644 --- a/src/main/resources/conversions.yml +++ b/src/main/resources/conversions.yml @@ -9,6 +9,8 @@ conversions: - v.egg egg(type=egg;origin=Egg;tags=freshness.0:cooked.0) - v.blue_egg egg(type=egg;origin=Egg;tags=freshness.0:cooked.0) - v.brown_egg egg(type=egg;origin=Egg;tags=freshness.0:cooked.0) + - v.brown_mushroom vegetable(type=mushroom;origin=Brown Mushroom;tags=freshness.0) + - v.red_mushroom vegetable(type=mushroom;origin=Red Mushroom;tags=freshness.0) - v.melon fruit(type=fruit_1;origin=Melon;tags=freshness.0) - v.melon_slice fruit(type=fruit_1;origin=Melon Slice;tags=freshness.0) - v.pumpkin vegetable(type=vegetable_1;origin=Pumpkin;tags=freshness.0) diff --git a/src/main/resources/models.yml b/src/main/resources/models.yml index 1112595..c094ed2 100644 --- a/src/main/resources/models.yml +++ b/src/main/resources/models.yml @@ -1882,6 +1882,11 @@ corn_cut: item: ia.tfmc_cooking:cut_corn_rotten corn_chopped: + # Lying flat in the frying pan, like the popcorn it pops into (types.yml vegetable_chopped_2 output). + display-data-furniture: + frying_pan: + rotation: + x: 90 raw: weight: 1 tags: @@ -3598,3 +3603,115 @@ egg: z: 3 position: y: 0.05 + +# Pan foods: vanilla mushrooms, grilled mushrooms and popcorn (types.yml mushroom, grilled_mushroom, popcorn). +# Their items are flat, so in furniture they're turned to lie down (rotation x 90), as chopped corn is in the pan. +brown_mushroom: + fresh: + weight: 1 + gui: + item: v.brown_mushroom + display: + item: v.brown_mushroom + display-data: + rotation: + x: 90 + rotten: + weight: 2 + tags: + - rotten + gui: + item: ia.tfmc_cooking:brown_mushroom_rotten + display: + item: ia.tfmc_cooking:brown_mushroom_rotten + display-data: + rotation: + x: 90 + +red_mushroom: + fresh: + weight: 1 + gui: + item: v.red_mushroom + display: + item: v.red_mushroom + display-data: + rotation: + x: 90 + rotten: + weight: 2 + tags: + - rotten + gui: + item: ia.tfmc_cooking:red_mushroom_rotten + display: + item: ia.tfmc_cooking:red_mushroom_rotten + display-data: + rotation: + x: 90 + +grilled_mushroom: + cooked: + weight: 1 + gui: + item: ia.tfmc_cooking:grilled_mushroom + display: + item: ia.tfmc_cooking:grilled_mushroom + display-data: + rotation: + x: 90 + burnt: + weight: 2 + tags: + - burnt + gui: + item: ia.tfmc_cooking:grilled_mushroom_burnt + display: + item: ia.tfmc_cooking:grilled_mushroom_burnt + display-data: + rotation: + x: 90 + rotten: + weight: 3 + tags: + - rotten + gui: + item: ia.tfmc_cooking:grilled_mushroom_rotten + display: + item: ia.tfmc_cooking:grilled_mushroom_rotten + display-data: + rotation: + x: 90 + +popcorn: + cooked: + weight: 1 + gui: + item: ia.tfmc_cooking:popcorn + display: + item: ia.tfmc_cooking:popcorn + display-data: + rotation: + x: 90 + burnt: + weight: 2 + tags: + - burnt + gui: + item: ia.tfmc_cooking:popcorn_burnt + display: + item: ia.tfmc_cooking:popcorn_burnt + display-data: + rotation: + x: 90 + rotten: + weight: 3 + tags: + - rotten + gui: + item: ia.tfmc_cooking:popcorn_rotten + display: + item: ia.tfmc_cooking:popcorn_rotten + display-data: + rotation: + x: 90 diff --git a/src/main/resources/types.yml b/src/main/resources/types.yml index df944bf..eb62fd3 100644 --- a/src/main/resources/types.yml +++ b/src/main/resources/types.yml @@ -298,7 +298,7 @@ vegetable_chopped: warmth: 450 freshness: 4 -###Veggies — chopped garnish CustomCrops +###Veggies — chopped garnish CustomCrops (chopped corn pops into popcorn in the frying pan) vegetable_chopped_2: name: "#5dad58{inherit} (Chopped)" valuable: true @@ -316,6 +316,17 @@ vegetable_chopped_2: model: tomato_chopped food: 11 nutrition: 7.5 + # output: the food (a food string) the piece turns into once it's done, here popcorn. It keeps the piece's stars, + # freshness, lineage and ingredients, and its origin when the string names none, and goes on cooking by the same + # clock, so it burns as popcorn. A type whose only options have an output isn't raw until it's in the pan, so + # chopped tomatoes keep their values. The pan's slot whitelist (InteractibleFurniture) lets only corn in: + # c.garnish(type=vegetable_chopped_2;origin=Corn). + cooking-options: + frying_pan: + tag: 1 + time: 15 + burn: 30 + output: snack(type=popcorn;origin=Corn) age: warmth: 450 freshness: 4 @@ -657,3 +668,50 @@ egg: freshness: stale: "#c3db81Stale" rotten: "#8B7355Rotten" + +###Mushrooms — vanilla brown and red mushrooms (conversions.yml), grilled in the frying pan into grilled mushrooms. +# Like a vanilla vegetable, with no cut step: one mushroom is one piece. +mushroom: + name: "#b08b6a{inherit}" + overrides: + BROWN MUSHROOM: + model: brown_mushroom + RED MUSHROOM: + model: red_mushroom + model: brown_mushroom + food: 6 + nutrition: 4.5 + cooking-options: + frying_pan: + tag: 1 + time: 12 + burn: 25 + output: vegetable(type=grilled_mushroom) + age: + warmth: 450 + freshness: 7 + +###Grilled mushroom: what a mushroom becomes in the frying pan; keeps its origin (Brown or Red Mushroom). +grilled_mushroom: + name: "#a0785aGrilled Mushroom" + model: grilled_mushroom + food: 6 + nutrition: 4.5 + age: + warmth: 450 + freshness: 7 + +###Popcorn: chopped corn popped in the frying pan (vegetable_chopped_2 output). Burnt, it stays popcorn. +# A light snack, a little less filling than the chopped corn it came from; dry, it keeps three times as long. +popcorn: + name: "#f3e3a6Popcorn" + model: popcorn + food: 10 + nutrition: 6 + age: + warmth: 450 + freshness: 12 + tag-labels: + freshness: + stale: "#c3db81Stale" + rotten: "#8B7355Mouldy" diff --git a/src/test/java/net/tfminecraft/cooking/cooking/PanFoodsCoverageTest.java b/src/test/java/net/tfminecraft/cooking/cooking/PanFoodsCoverageTest.java new file mode 100644 index 0000000..0c7870d --- /dev/null +++ b/src/test/java/net/tfminecraft/cooking/cooking/PanFoodsCoverageTest.java @@ -0,0 +1,263 @@ +package net.tfminecraft.cooking.cooking; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import org.bukkit.Material; +import org.bukkit.configuration.MemoryConfiguration; +import org.bukkit.inventory.ItemStack; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import net.tfminecraft.cooking.crafting.CraftingStationCoverageTest.Environment; +import net.tfminecraft.cooking.enums.Method; +import net.tfminecraft.cooking.item.FoodItem; +import net.tfminecraft.cooking.item.IngredientLineage; +import net.tfminecraft.cooking.item.data.CookData; +import net.tfminecraft.cooking.item.data.CookParameter; +import net.tfminecraft.cooking.item.model.FoodModel; +import net.tfminecraft.cooking.item.tag.TagTrack; +import net.tfminecraft.cooking.loader.FoodLoader; +import net.tfminecraft.cooking.loader.TrackLoader; +import net.tfminecraft.cooking.utils.FoodParser; +import net.tfminecraft.cooking.utils.ItemBuilder; +import net.tfminecraft.cooking.utils.ItemUpdater; +import net.tfminecraft.interactiblefurniture.events.FurnitureSlotItemAddEvent; +import net.tfminecraft.interactiblefurniture.events.FurnitureSlotItemTakeEvent; +import net.tfminecraft.interactiblefurniture.furniture.PlacedSlot; + +/** Pan foods: a frying pan option with an output turns the piece into that food (chopped corn pops into popcorn). */ +class PanFoodsCoverageTest { + static final String POPCORN = "snack(type=popcorn;origin=Corn)"; + static final String GRILLED = "vegetable(type=grilled_mushroom)"; + + Environment env; + FryingReference pan; + + @BeforeEach void open() { + env = new Environment(); + pan = new FryingReference(env.furniture, Method.FRYING_PAN); + env.parser.when(() -> FoodParser.parse(POPCORN)).thenAnswer(inv -> parsed("popcorn", "#f3e3a6Popcorn", "snack", "Corn")); + env.parser.when(() -> FoodParser.parse(GRILLED)) + .thenAnswer(inv -> parsed("grilled_mushroom", "#a0785aGrilled Mushroom", "vegetable", "")); + env.parser.when(() -> FoodParser.parse("snack(type=missing)")).thenReturn(null); + env.builder.when(() -> ItemBuilder.displayName(any())).thenAnswer(inv -> ((FoodItem) inv.getArgument(0)).getName()); + } + + @AfterEach void close() { env.close(); } + + static FoodItem type(String id, String name) { + MemoryConfiguration config = new MemoryConfiguration(); + config.set("name", name); config.set("update", false); + FoodItem food = new FoodItem(id, config); + food.setModel(new FoodModel(new ItemStack(Material.CARROT))); + return food; + } + + static FoodParser.Result parsed(String id, String name, String category, String origin) { + FoodParser.Result result = new FoodParser.Result(); + result.template = new FoodItem(type(id, name)); + result.template.setCategory(category); + result.template.setOrigin(origin); + return result; + } + + /** A piece whose only pan option names an output, like chopped corn: no cooked track of its own. */ + FoodItem piece(String id, String category, String origin, String output, int time, int burn) { + FoodItem food = env.food(id, origin); + food.setCategory(category); + food.getCookData().getParameters().put(Method.FRYING_PAN, new CookParameter(1, time, burn, output)); + return food; + } + + FoodItem choppedCorn() { + FoodItem corn = piece("vegetable_chopped_2", "garnish", "Corn", POPCORN, 5, 8); + corn.setQualityRange(4, 4); + TagTrack cut = new TagTrack(TrackLoader.getByString("cut")); + cut.setValue(1); + corn.addOrModifyTrack(cut); + TagTrack freshness = new TagTrack(TrackLoader.getByString("freshness")); + freshness.setValue(90000); + corn.addOrModifyTrack(freshness); + corn.setAgeRemainder("freshness", 0.5); + corn.addIngredient("Corn"); + corn.setLineage(IngredientLineage.ofMain("Corn")); + return corn; + } + + /** Puts a piece in the pan the way InteractibleFurniture does: the add event, then the shown item in the slot. */ + PlacedSlot add(FoodItem food, String slot) { + FurnitureSlotItemAddEvent event = env.addEvent(slot, env.stack(food, Material.WHEAT, 3)); + pan.slotAdd(event); + assertFalse(event.isCancelled()); + assertEquals(1, event.getItem().getAmount()); + return env.place(slot, event.getItem()); + } + + FurnitureSlotItemTakeEvent take(String slot) { + FurnitureSlotItemTakeEvent event = env.takeEvent(slot, env.active.get(slot).getCurrentItem()); + pan.slotRemove(event); + return event; + } + + void tick(int times) { for (int i = 0; i < times; i++) pan.tick(); } + int cooked(FoodItem food) { return food.getTagTrack("cooked").getValue(); } + + @Test void choppedCornPopsIntoNamedPopcornKeepingItsStarsFreshnessAndLineageThenBurnsAsPopcorn() { + pan.getSecondaries().put("butter", -1); + FoodItem corn = choppedCorn(); + add(corn, "input_1"); + assertEquals(0, cooked(pan.getSlot("input_1")), "In the pan, the chopped corn is raw"); + + tick(4); + assertSame(corn, pan.getSlot("input_1")); + tick(1); + FoodItem popcorn = pan.getSlot("input_1"); + assertEquals("popcorn", popcorn.getId()); + assertEquals("snack", popcorn.getCategory()); + assertEquals("Corn", popcorn.getOrigin()); + assertEquals(1, cooked(popcorn)); + assertEquals(4, popcorn.getEffectiveQuality()); + assertEquals(90000, popcorn.getTagTrack("freshness").getValue()); + assertEquals(0.5, popcorn.getAgeRemainder("freshness")); + assertFalse(popcorn.hasTagTrack("cut"), "Chopped stays with the corn"); + assertEquals(List.of("Corn"), popcorn.getIngredients()); + assertEquals(List.of("Corn"), popcorn.getLineage().mains()); + assertNull(popcorn.getCookData().getParameters().get(Method.FRYING_PAN).getOutput()); + env.updater.verify(() -> ItemUpdater.applyItemUpdate( + argThat(stack -> stack != null && popcorn.getName().equals(stack.getItemMeta().getDisplayName())), + same(popcorn), eq("board"))); + + tick(3); + assertSame(popcorn, pan.getSlot("input_1"), "Burnt popcorn stays popcorn"); + assertEquals(2, cooked(popcorn)); + + FurnitureSlotItemTakeEvent taken = take("input_1"); + assertFalse(taken.isCancelled()); + assertSame(popcorn, env.resolve(taken.getItem())); + assertTrue(popcorn.hasTagTrack("warmth")); + assertFalse(pan.getSecondaries().containsKey("butter"), "Taking a piece off uses up the butter"); + } + + @Test void cornTakenOffBeforeItPopsComesBackAsTheChoppedCornThatWentIn() { + pan.getSecondaries().put("butter", -1); + FoodItem early = choppedCorn(); + add(early, "input_1"); + tick(1); + FurnitureSlotItemTakeEvent quick = take("input_1"); + assertFalse(quick.isCancelled()); + assertSame(early, env.resolve(quick.getItem())); + assertFalse(early.hasTagTrack("cooked"), "No Raw tag on chopped corn"); + assertNull(pan.getSlot("input_1")); + + FoodItem late = piece("vegetable_chopped_2", "garnish", "Corn", POPCORN, 10, 20); + add(late, "input_2"); + tick(6); + FurnitureSlotItemTakeEvent slow = take("input_2"); + assertFalse(slow.isCancelled()); + assertFalse(late.hasTagTrack("cooked")); + assertFalse(late.hasTagTrack("warmth"), "Not cooked, so not served hot"); + assertTrue(pan.getSecondaries().containsKey("butter"), "The butter is still in the pan"); + } + + @Test void cornLeftWithoutButterBurnsAndPopsBurnt() { + add(piece("vegetable_chopped_2", "garnish", "Corn", POPCORN, 15, 30), "input_1"); + tick(10); + FoodItem popcorn = pan.getSlot("input_1"); + assertEquals("popcorn", popcorn.getId()); + assertEquals(2, cooked(popcorn)); + tick(1); + assertSame(popcorn, pan.getSlot("input_1")); + } + + @Test void aGrilledMushroomKeepsTheMushroomsOriginWhenTheOutputNamesNone() { + pan.getSecondaries().put("butter", -1); + add(piece("mushroom", "vegetable", "Brown Mushroom", GRILLED, 2, 4), "input_1"); + tick(2); + FoodItem grilled = pan.getSlot("input_1"); + assertEquals("grilled_mushroom", grilled.getId()); + assertEquals("Brown Mushroom", grilled.getOrigin()); + assertEquals("vegetable", grilled.getCategory()); + } + + @Test void anOutputThatDoesNotParseLeavesThePieceCookingAsItself() { + pan.getSecondaries().put("butter", -1); + FoodItem corn = piece("vegetable_chopped_2", "garnish", "Corn", "snack(type=missing)", 5, 20); + add(corn, "input_1"); + tick(6); + assertSame(corn, pan.getSlot("input_1")); + assertEquals(1, cooked(corn)); + FurnitureSlotItemTakeEvent taken = take("input_1"); + assertFalse(taken.isCancelled()); + assertTrue(corn.hasTagTrack("cooked"), "Done, so it keeps its cooked tag"); + } + + @Test void foodThatCooksAsItselfIsUntouchedByOutputs() { + pan.getSecondaries().put("butter", -1); + FoodItem steak = env.food("steak", "Beef", Method.FRYING_PAN); + add(steak, "input_1"); + tick(2); + assertSame(steak, pan.getSlot("input_1")); + assertEquals(1, cooked(steak)); + } + + @Test void onlyTypesThatCookAsThemselvesCarryARawTrack() { + MemoryConfiguration options = new MemoryConfiguration(); + options.set("frying_pan.time", 15); options.set("frying_pan.burn", 30); options.set("frying_pan.output", POPCORN); + CookData popping = new CookData("vegetable_chopped_2", options); + assertFalse(popping.cooksInPlace()); + assertEquals(POPCORN, popping.getParameters().get(Method.FRYING_PAN).getOutput()); + options.set("pot.time", 15); + assertTrue(new CookData("vegetable_chopped_2", options).cooksInPlace()); + assertFalse(new CookData().cooksInPlace()); + + CookParameter plain = new CookParameter(1, 2, 3, " "); + assertNull(plain.getOutput()); + assertSame(plain, plain.withoutOutput()); + CookParameter popped = new CookParameter(1, 2, 3, POPCORN).withoutOutput(); + assertEquals(List.of(1, 2, 3), List.of(popped.getTag(), popped.getTime(), popped.getBurnTime())); + assertNull(popped.getOutput()); + } + + @Test void theShippedConfigPopsCornAndGrillsMushroomsWithoutARawTagOnTheirInputs() throws Exception { + new FoodLoader().load(new File("src/main/resources/types.yml")); + FoodItem chopped = new FoodItem(FoodLoader.getByString("vegetable_chopped_2")); + assertEquals(POPCORN, chopped.getCookData().getParameters().get(Method.FRYING_PAN).getOutput()); + assertFalse(chopped.hasTagTrack("cooked"), "Chopped tomatoes keep their values"); + FoodItem mushroom = new FoodItem(FoodLoader.getByString("mushroom")); + assertEquals(GRILLED, mushroom.getCookData().getParameters().get(Method.FRYING_PAN).getOutput()); + assertFalse(mushroom.hasTagTrack("cooked")); + assertTrue(new FoodItem(FoodLoader.getByString("egg")).hasTagTrack("cooked")); + for (String id : List.of("grilled_mushroom", "popcorn")) { + assertTrue(FoodLoader.getByString(id).getCookData().getParameters().isEmpty(), id); + } + + String models = Files.readString(Path.of("src/main/resources/models.yml")); + String conversions = Files.readString(Path.of("src/main/resources/conversions.yml")); + String config = Files.readString(Path.of("src/main/resources/config.yml")); + StringBuilder items = new StringBuilder(); + for (String file : List.of("items.yml", "intermediates.yml")) { + items.append(Files.readString(Path.of("ItemsAdder/tfmc_cooking/contents/" + file))); + } + for (String model : List.of("brown_mushroom", "red_mushroom", "grilled_mushroom", "popcorn")) { + assertTrue(models.contains("\n" + model + ":\n"), model); + } + for (String id : List.of("brown_mushroom_rotten", "red_mushroom_rotten", "grilled_mushroom", "grilled_mushroom_burnt", + "grilled_mushroom_rotten", "popcorn", "popcorn_burnt", "popcorn_rotten")) { + assertTrue(models.contains("item: ia.tfmc_cooking:" + id + "\n"), id); + assertTrue(items.toString().contains("\n " + id + ":\n"), id); + String texture = id.endsWith("mushroom_rotten") && !id.startsWith("grilled") ? "vanilla/" : "intermediate/"; + assertTrue(Files.exists(Path.of("ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/" + + texture + id + ".png")), id); + } + assertTrue(conversions.contains("v.brown_mushroom vegetable(type=mushroom;origin=Brown Mushroom;tags=freshness.0)")); + assertTrue(conversions.contains("v.red_mushroom vegetable(type=mushroom;origin=Red Mushroom;tags=freshness.0)")); + assertTrue(config.contains("snack: \"#e8c56bSnack\"")); + } +} diff --git a/src/test/java/net/tfminecraft/cooking/utils/ItemBuilderCoverageTest.java b/src/test/java/net/tfminecraft/cooking/utils/ItemBuilderCoverageTest.java index 7fa9cc6..3d1ea07 100644 --- a/src/test/java/net/tfminecraft/cooking/utils/ItemBuilderCoverageTest.java +++ b/src/test/java/net/tfminecraft/cooking/utils/ItemBuilderCoverageTest.java @@ -92,6 +92,14 @@ class ItemBuilderCoverageTest { assertEquals("Rye",base.getItemMeta().getDisplayName()); } + @Test void aFoodsDisplayNameIsTheOneANewStackOfItGets() { + FoodItem grilled=food("grilled_mushroom","Grilled {inherit}"); grilled.setOrigin("brown mushroom"); + assertEquals("Grilled Brown Mushroom",ItemBuilder.displayName(grilled)); + grilled.getOverrides().put("BROWN MUSHROOM",new OverrideData("Grilled Cap",null,null)); + assertEquals("Grilled Cap",ItemBuilder.displayName(grilled)); + assertEquals(ItemBuilder.displayName(grilled),ItemBuilder.buildSingleWithQuality(grilled,2).getItemMeta().getDisplayName()); + } + @Test void composedNamesAreFilledInFromTheFoodsIngredientsWhenBuiltFromAPlainTemplate() { FoodItem bread=food("bread","{prefixes}{fillers}Bread"); bread.addIngredient("Banana");