diff --git a/src/main/java/net/tfminecraft/cooking/cooking/CookingReference.java b/src/main/java/net/tfminecraft/cooking/cooking/CookingReference.java index 224f0ad..f0f1389 100644 --- a/src/main/java/net/tfminecraft/cooking/cooking/CookingReference.java +++ b/src/main/java/net/tfminecraft/cooking/cooking/CookingReference.java @@ -184,6 +184,8 @@ public void rebuildFromFurniture() { public void slotAdd(FurnitureSlotItemAddEvent e) { ItemStack item = e.getItem(); FoodItem fi = FoodItem.fromItem(item); + // Non-food the slot whitelists (the pot's ladle rest) is the furniture's business. + if (fi == null) return; if(!fi.canBeCooked()) { e.setCancelled(true); return; diff --git a/src/main/java/net/tfminecraft/cooking/cooking/PotReference.java b/src/main/java/net/tfminecraft/cooking/cooking/PotReference.java index a7a2e62..1ec630f 100644 --- a/src/main/java/net/tfminecraft/cooking/cooking/PotReference.java +++ b/src/main/java/net/tfminecraft/cooking/cooking/PotReference.java @@ -359,14 +359,9 @@ public void mash(Player p) { item.addOrModifyTrack(new TagTrack(TrackLoader.getByString("mashed"))); applySlotUpdate(entry.getKey(), item); updateModel(); - DisplayData mashed = new DisplayData(); - mashed.setxScale(0); - mashed.setyScale(0); - mashed.setzScale(0); - mashed.setyPos(-0.4f); if (!f.hasActiveSlot(entry.getKey())) continue; PlacedSlot slot = f.getActiveSlot(entry.getKey()).get(); - slot.applyDisplayData(mashed); + slot.applyDisplayData(mashedDisplay()); found = true; } if(found) { @@ -581,16 +576,64 @@ public void updateModel() { applySoupLevel(); } + /** Mashed pieces sink out of sight; the soup liquid shows them. */ + private static DisplayData mashedDisplay() { + DisplayData mashed = new DisplayData(); + mashed.setxScale(0); + mashed.setyScale(0); + mashed.setzScale(0); + mashed.setyPos(-0.4f); + return mashed; + } + @Override public void rebuildFromFurniture() { super.rebuildFromFurniture(); + restoreMains(); restoreExtras(); if (f != null && f.hasActiveSlot("liquid")) { secondaries.put("liquid", -1); } + restoreColours(); applySoupLevel(); } + /** + * The base rebuild keeps raw food only. Soup is mashed and boiled pieces are cooked, so a + * chunk reload or restart would drop them: the ladle found no soup and a break dropped them. + */ + private void restoreMains() { + if (f == null || f.getType() == null) return; + for (String slotId : f.getType().getSlots().keySet()) { + if (!slotId.contains("input") || slots.containsKey(slotId)) continue; + PlacedSlot placed = f.getActiveSlot(slotId).orElse(null); + if (placed == null) continue; + FoodItem fi = FoodItem.fromItem(placed.getCurrentItem()); + if (!keepsOnRebuild(fi)) continue; + slots.put(slotId, fi); + if (fi.hasTag(Tag.MASHED)) { + placed.applyDisplayData(mashedDisplay()); + } + } + } + + /** True for food the pot holds as a main: soup pieces and anything that boils. */ + public static boolean keepsOnRebuild(FoodItem fi) { + if (fi == null) return false; + if (fi.hasTag(Tag.MASHED)) return true; + return fi.canBeCooked() && fi.getCookData().hasMethod(Method.POT); + } + + /** Colours are not saved, so rebuild them in the order the pot was filled: water first. */ + private void restoreColours() { + if (f == null || f.getType() == null || !secondaries.containsKey("liquid")) return; + addColour("3d85c6"); + for (String slotId : f.getType().getSlots().keySet()) { + if (!slots.containsKey(slotId) || isExtraSlot(slotId)) continue; + f.getActiveSlot(slotId).ifPresent(placed -> addColour(ItemCache.getColour(placed.getCurrentItem()))); + } + } + /** Each scoop keeps the soup template food. Serving count does not scale it. */ public static double scoopFood(double templateFood) { return templateFood; diff --git a/src/test/java/net/tfminecraft/cooking/item/PotMashTest.java b/src/test/java/net/tfminecraft/cooking/item/PotMashTest.java index adc499e..43ceb86 100644 --- a/src/test/java/net/tfminecraft/cooking/item/PotMashTest.java +++ b/src/test/java/net/tfminecraft/cooking/item/PotMashTest.java @@ -9,6 +9,9 @@ import org.junit.jupiter.api.Test; import net.tfminecraft.cooking.cooking.PotReference; +import net.tfminecraft.cooking.enums.Method; +import net.tfminecraft.cooking.item.data.CookParameter; +import net.tfminecraft.cooking.item.tag.TagStep; import net.tfminecraft.cooking.item.tag.TagTrack; class PotMashTest { @@ -30,6 +33,32 @@ void markBoiledForcesCookedTrackToBoiled() { assertEquals(3, raw.getTagTrack("cooked").getValue()); } + @Test + void rebuildKeepsSoupAndBoilingPiecesOnly() { + FoodItem mashed = piece(); + mashed.addOrModifyTrack(new TagTrack("mashed", false, List.of(step("mashed")))); + assertTrue(PotReference.keepsOnRebuild(mashed)); + + FoodItem boiled = piece(); + boiled.addOrModifyTrack(new TagTrack("cooked", false, List.of(step("cooked")))); + boiled.getCookData().getParameters().put(Method.POT, new CookParameter(1, 15, 30)); + assertTrue(PotReference.keepsOnRebuild(boiled)); + + FoodItem panOnly = piece(); + panOnly.getCookData().getParameters().put(Method.FRYING_PAN, new CookParameter(1, 15, 30)); + assertFalse(PotReference.keepsOnRebuild(panOnly)); + assertFalse(PotReference.keepsOnRebuild(piece())); + assertFalse(PotReference.keepsOnRebuild(null)); + } + + private static FoodItem piece() { + return new FoodItem("vegetable_cut", "Carrot", true); + } + + private static TagStep step(String key) { + return new TagStep(key, key, 0, 1.0, 1.0); + } + private static FoodItem food(boolean mashable, int cooked) { FoodItem item = new FoodItem("meat_red_meat", "Steak", true); item.setMashable(mashable);