Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions src/main/java/net/tfminecraft/cooking/manager/PlateManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
Expand All @@ -31,6 +32,7 @@
import net.tfminecraft.interactiblefurniture.events.FurnitureBreakEvent;
import net.tfminecraft.interactiblefurniture.events.FurnitureInteractEvent;
import net.tfminecraft.interactiblefurniture.events.FurnitureSlotItemAddEvent;
import net.tfminecraft.interactiblefurniture.events.FurnitureSlotItemTakeEvent;
import net.tfminecraft.interactiblefurniture.furniture.Furniture;
import net.tfminecraft.interactiblefurniture.furniture.PlacedSlot;
import net.tfminecraft.interactiblefurniture.furniture.data.DisplayData;
Expand All @@ -56,6 +58,11 @@ public void run() {
}

public void update(Furniture f) {
// Also clears plates saved with leftover sauce before the take handler existed.
if(hasLeftoverSauce(f, null)) {
f.removeActiveSlot("sauce");
InteractibleFurniture.getInstance().getFurnitureManager().persistFurniture(f);
}
for(PlacedSlot slot : f.getActiveSlots().values()) {
if(slot.getId().contains("display")) continue;
ItemStack item = slot.getCurrentItem();
Expand Down Expand Up @@ -99,10 +106,51 @@ public boolean hasSauce(Furniture f) {
return false;
}

/**
* True when the plate shows a sauce visual but no food would remain once {@code leavingSlot}
* is gone. A leftover sauce visual makes hasSauce reject the next dish on the plate.
*/
boolean hasLeftoverSauce(Furniture f, String leavingSlot) {
if(!f.hasActiveSlot("sauce")) return false;
return !hasFood(f, leavingSlot);
}

// An active food slot counts even without a loaded item: restore can leave the item unset
// while the display still shows the food.
private boolean hasFood(Furniture f, String ignoredSlot) {
for(String id : f.getActiveSlots().keySet()) {
if(id.equals("sauce") || id.contains("display") || id.equals(ignoredSlot)) continue;
return true;
}
return false;
}

// Food addSauce can actually apply the sauce to.
private boolean hasSauceableFood(Furniture f) {
for(PlacedSlot slot : f.getActiveSlots().values()) {
if(slot.getId().equals("sauce") || slot.getId().contains("display")) continue;
ItemStack item = slot.getCurrentItem();
if(item != null && FoodItem.fromItem(item) != null) return true;
}
return false;
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void takeItem(FurnitureSlotItemTakeEvent e) {
Furniture f = e.getFurniture();
if(!FurnitureCache.isPlate(f)) return;
// The taken slot is still active here; InteractibleFurniture removes it and saves the plate next.
if(hasLeftoverSauce(f, e.getSlot().getId())) {
f.removeActiveSlot("sauce");
}
}

// Keep the existing legacy text representation, formatting, and exact-string comparisons.
@SuppressWarnings("deprecation")
public void addSauce(Player p, Furniture f, FoodItem sauce, ItemStack base) {
if (hasSauce(f)) return;
// Sauce with no food to take it would never reach food added later, so keep the ladle full.
if (!hasSauceableFood(f)) return;

// Replace player ladle with empty ladle
p.getInventory().setItemInMainHand(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,79 @@ public boolean hasItemMeta() {

assertFalse(new PlateManager().hasSauce(plate));
}

@Test
void sauceIsLeftoverOnceTheLastFoodLeaves() {
Furniture plate = plateWithSauceVisual();
plate.getActiveSlots().put("item_1", new PlacedSlot(plate, "item_1"));

assertFalse(new PlateManager().hasLeftoverSauce(plate, null));
assertTrue(new PlateManager().hasLeftoverSauce(plate, "item_1"));
}

@Test
void sauceStaysWhileOtherFoodRemains() {
Furniture plate = plateWithSauceVisual();
plate.getActiveSlots().put("item_1", new PlacedSlot(plate, "item_1"));
plate.getActiveSlots().put("item_2", new PlacedSlot(plate, "item_2"));

assertFalse(new PlateManager().hasLeftoverSauce(plate, "item_1"));
}

@Test
void sauceAloneOnAPlateIsLeftover() {
assertTrue(new PlateManager().hasLeftoverSauce(plateWithSauceVisual(), null));
}

@Test
void plateWithoutSauceHasNoLeftover() {
Furniture plate = new Furniture("plate", null, UUID.randomUUID());
plate.getActiveSlots().put("item_1", new PlacedSlot(plate, "item_1"));

assertFalse(new PlateManager().hasLeftoverSauce(plate, null));
assertFalse(new PlateManager().hasLeftoverSauce(plate, "item_1"));
}

@Test
void sauceOnAnEmptyPlateReturnsBeforeTouchingThePlayerOrLadle() {
Furniture plate = new Furniture("plate", null, UUID.randomUUID());

// Null interaction arguments ensure the empty-plate attempt exits before using them.
assertDoesNotThrow(() -> new PlateManager().addSauce(null, plate, null, null));
assertTrue(plate.getActiveSlots().isEmpty());
}

@Test
void sauceOnAPlateWithoutLoadedFoodReturnsBeforeTouchingThePlayerOrLadle() {
Furniture plate = new Furniture("plate", null, UUID.randomUUID());
plate.getActiveSlots().put("item_1", new PlacedSlot(plate, "item_1"));
PlacedSlot unrecognized = new PlacedSlot(plate, "item_2");
unrecognized.setModel(new ItemStack() {
@Override
public boolean hasItemMeta() {
return false;
}
});
plate.getActiveSlots().put("item_2", unrecognized);

assertDoesNotThrow(() -> new PlateManager().addSauce(null, plate, null, null));
assertFalse(plate.hasActiveSlot("sauce"));
}

@Test
void displaySlotsDoNotCountAsFood() {
Furniture plate = plateWithSauceVisual();
plate.getActiveSlots().put("display_1", new PlacedSlot(plate, "display_1"));

assertTrue(new PlateManager().hasLeftoverSauce(plate, null));
}

@Test
void sauceOnADisplayOnlyPlateReturnsBeforeTouchingThePlayerOrLadle() {
Furniture plate = new Furniture("plate", null, UUID.randomUUID());
plate.getActiveSlots().put("display_1", new PlacedSlot(plate, "display_1"));

assertDoesNotThrow(() -> new PlateManager().addSauce(null, plate, null, null));
assertFalse(plate.hasActiveSlot("sauce"));
}
}