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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Cooking makes food an interactive part of everyday life. Players grow and gather
- **Food preparation** — milling stones, mixing bowls, butter churns, sausage makers, and baking trays provide different ways to transform ingredients.
- **Sandwiches** — lay a slice of bread on a cutting board, add spreads, cheese and vegetables, close it with another slice and pick it up. Its fillings name it, and its food, quality and freshness come from its layers (`sandwiches.yml`). Its layers also earn it bonuses such as Hearty, Buttered or Well-Rounded (`bonuses` in `sandwiches.yml`).
- **Pizzas** — place a pizza peel, put dough on it, spread a paste and add cheese, vegetables, fruit, sausage and spices, then carry the peel into a lit oven to bake. A baked pizza is taken off a slice at a time. Its toppings name it, and its food, quality and freshness come from its layers (`pizzas.yml`). Its toppings also earn it bonuses such as Saucy, Extra Cheesy or Well Seasoned (`bonuses` in `pizzas.yml`).
- **Salads** — right-click a placed bowl with chopped or cooked veg, fruit, cheese or meat, add a dressing or seasoning, and toss it with an empty hand. It stays in the bowl and is eaten from it. Its ingredients name it, its kind (fruit, greek, carrot, mixed) gives it its look, and it earns bonuses such as Dressed or Crisp (`salads.yml`).
- **Serving and sharing** — plate dishes, ladle soup into bowls, and carve foods into portions for the table.
- **Quality and freshness** — ingredient quality and composition influence finished dishes, while aging and food tags carry preparation history through the kitchen.
- **Farming and husbandry** — crop fertility and harvest quality sit alongside animal care, breeding, genetics, and produce collection.
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/net/tfminecraft/cooking/Cooking.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
import net.tfminecraft.cooking.pizza.PizzaHandler;
import net.tfminecraft.cooking.condiment.CondimentConfig;
import net.tfminecraft.cooking.condiment.SapTapListener;
import net.tfminecraft.cooking.salad.SaladConfig;
import net.tfminecraft.cooking.salad.SaladHandler;
import net.tfminecraft.cooking.sandwich.SandwichConfig;
import net.tfminecraft.cooking.sandwich.SandwichHandler;
import net.tfminecraft.cooking.milling.MillingRecipeLoader;
Expand Down Expand Up @@ -142,6 +144,8 @@ public class Cooking extends JavaPlugin {
private final SandwichHandler sandwichHandler = new SandwichHandler();
private final PizzaConfig pizzaConfig = new PizzaConfig();
private final PizzaHandler pizzaHandler = new PizzaHandler();
private final SaladConfig saladConfig = new SaladConfig();
private final SaladHandler saladHandler = new SaladHandler();
private final MillingStoneHandler millingStoneHandler = new MillingStoneHandler();
private final TroughHandler troughHandler = new TroughHandler();
private final TroughAging troughAging = new TroughAging();
Expand Down Expand Up @@ -268,6 +272,7 @@ public void loadConfigs() {
sandwichConfig.load(new File(getDataFolder(), "sandwiches.yml"));
pizzaConfig.load(new File(getDataFolder(), "pizzas.yml"));
condimentConfig.load(new File(getDataFolder(), "condiments.yml"));
saladConfig.load(new File(getDataFolder(), "salads.yml"));
millingRecipeLoader.load(new File(getDataFolder(), "milling-recipes.yml"));
stationLoader.load(new File(getDataFolder(), "crafting-stations.yml"));
trackLoader.load(new File(getDataFolder(), "tags.yml"));
Expand Down Expand Up @@ -334,6 +339,7 @@ public void registerListeners() {
getServer().getPluginManager().registerEvents(sandwichHandler, this);
getServer().getPluginManager().registerEvents(pizzaHandler, this);
getServer().getPluginManager().registerEvents(new SapTapListener(), this);
getServer().getPluginManager().registerEvents(saladHandler, this);
getServer().getPluginManager().registerEvents(millingStoneHandler, this);
getServer().getPluginManager().registerEvents(troughHandler, this);
getServer().getPluginManager().registerEvents(ovenLifecycleHandler, this);
Expand Down Expand Up @@ -430,6 +436,7 @@ public void createConfigs() {
"sandwiches.yml",
"pizzas.yml",
"condiments.yml",
"salads.yml",
"milling-recipes.yml",
"cookware.yml",
"tags.yml",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import net.tfminecraft.cooking.cache.FurnitureCache;
import net.tfminecraft.cooking.cache.ItemCache;
import net.tfminecraft.cooking.item.FoodItem;
import net.tfminecraft.cooking.salad.SaladHandler;
import net.tfminecraft.cooking.utils.Encoder;
import net.tfminecraft.cooking.utils.FoodParser;
import net.tfminecraft.cooking.utils.HeldStack;
Expand Down Expand Up @@ -187,6 +188,10 @@ public void addSoup(Player p, Furniture f, FoodItem soup, ItemStack base) {
if (f.getType() == null || f.getType().getSlot("food_item") == null) return;
PlacedSlot current = f.getActiveSlot("food_item").orElse(null);
if (current != null && current.getCurrentItem() != null && !current.getCurrentItem().getType().isAir()) return;
if (SaladHandler.isMaking(f)) {
p.sendMessage("§7There's a salad in this bowl; toss it or take it out first.");
return;
}
ItemStack emptyLadle = TLibs.getItemAPI().getCreator().getItemFromPath(ItemCache.ladle);
if (emptyLadle == null || emptyLadle.getType().isAir()) return;
Map<String, ItemStack> map = Encoder.decodeSlots(base.getItemMeta().getPersistentDataContainer().get(Keys.SLOT_DATA, PersistentDataType.STRING));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import net.tfminecraft.cooking.cache.FurnitureCache;
import net.tfminecraft.cooking.item.FoodItem;
import net.tfminecraft.cooking.manager.PlateManager;
import net.tfminecraft.cooking.salad.SaladConfig;
import net.tfminecraft.cooking.utils.PlayerActionContext;
import net.tfminecraft.interactiblefurniture.events.FurnitureInteractEvent;
import net.tfminecraft.interactiblefurniture.furniture.Furniture;
Expand Down Expand Up @@ -56,7 +57,7 @@ public void onInteract(FurnitureInteractEvent event) {
}

FoodItem food = FoodItem.fromItem(soupStack);
if (food == null || !food.getCategory().equalsIgnoreCase("soup")) {
if (food == null || !(food.getCategory().equalsIgnoreCase("soup") || SaladConfig.isSalad(food))) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public enum CompositionContext {
SAUSAGE_MAKER(true),
SANDWICH(true),
PIZZA(true),
SALAD(true),
MILLING(false),
BAKING(false);

Expand Down
151 changes: 151 additions & 0 deletions src/main/java/net/tfminecraft/cooking/salad/SaladConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package net.tfminecraft.cooking.salad;

import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;

import net.tfminecraft.cooking.item.FoodItem;
import net.tfminecraft.cooking.sandwich.DishBonus;
import net.tfminecraft.cooking.sandwich.SandwichLayer;
import net.tfminecraft.interactiblefurniture.furniture.Furniture;

/** salads.yml: the bowls salads are tossed in, what they take, the kinds they make and the bonuses they earn. */
public final class SaladConfig {
private static final Pattern TYPE = Pattern.compile("type=([^;)]+)");

private static Set<String> furniture = Set.of();
private static int maxIngredients = 5;
private static int minIngredients = 2;
private static int maxExtras = 3;
private static String output = "meal(type=salad;origin=Mixed)";
private static String outputType = "salad";
private static List<SandwichLayer> ingredients = List.of();
private static List<SandwichLayer> extras = List.of();
private static Set<String> once = Set.of();
private static Set<String> returnsBottle = Set.of();
private static List<SaladKind> kinds = List.of();
private static List<DishBonus> bonuses = List.of();

public void load(File file) {
YamlConfiguration config = YamlConfiguration.loadConfiguration(file);
Set<String> bowls = new HashSet<>();
for (String id : config.getStringList("furniture")) bowls.add(id.toLowerCase(Locale.ROOT));
furniture = bowls;
maxIngredients = Math.max(1, config.getInt("max-ingredients", 5));
minIngredients = Math.max(1, Math.min(maxIngredients, config.getInt("min-ingredients", 2)));
maxExtras = Math.max(0, config.getInt("max-extras", 3));
output = config.getString("output", "meal(type=salad;origin=Mixed)");
Matcher type = TYPE.matcher(output);
outputType = type.find() ? type.group(1).trim().toLowerCase(Locale.ROOT) : "salad";
ingredients = layers(config.getConfigurationSection("ingredients"), null, null);
Set<String> single = new HashSet<>();
Set<String> bottles = new HashSet<>();
extras = layers(config.getConfigurationSection("extras"), single, bottles);
once = single;
returnsBottle = bottles;
List<SaladKind> loaded = new ArrayList<>();
ConfigurationSection section = config.getConfigurationSection("kinds");
if (section != null) {
for (String origin : section.getKeys(false)) {
ConfigurationSection kind = section.getConfigurationSection(origin);
if (kind != null) loaded.add(new SaladKind(origin, kind));
}
}
kinds = loaded;
bonuses = DishBonus.load(config.getConfigurationSection("bonuses"));
}

private static List<SandwichLayer> layers(ConfigurationSection section, Set<String> single, Set<String> bottles) {
List<SandwichLayer> loaded = new ArrayList<>();
if (section == null) return loaded;
for (String id : section.getKeys(false)) {
ConfigurationSection layer = section.getConfigurationSection(id);
if (layer == null) continue;
loaded.add(new SandwichLayer(id, layer));
if (single != null && layer.getBoolean("once", false)) single.add(id.toLowerCase(Locale.ROOT));
if (bottles != null && layer.getBoolean("returns-bottle", false)) bottles.add(id.toLowerCase(Locale.ROOT));
}
return loaded;
}

public static boolean isSaladFurniture(Furniture f) {
return f != null && f.getType() != null && furniture.contains(f.getType().getId().toLowerCase(Locale.ROOT));
}

/** The ingredient layer this food makes (shown in the bowl), or null. */
public static SandwichLayer ingredientFor(FoodItem food) {
for (SandwichLayer layer : ingredients) {
if (layer.matches(food)) return layer;
}
return null;
}

/** The extra (dressing, seasoning) this food makes, or null. Extras don't show and don't name the salad. */
public static SandwichLayer extraFor(FoodItem food) {
for (SandwichLayer layer : extras) {
if (layer.matches(food)) return layer;
}
return null;
}

/** The ingredient or extra this food makes, or null. */
public static SandwichLayer layerFor(FoodItem food) {
SandwichLayer layer = ingredientFor(food);
return layer != null ? layer : extraFor(food);
}

public static boolean isExtra(SandwichLayer layer) {
return extras.contains(layer);
}

/** Only one food of this extra goes in a salad (one dressing). */
public static boolean isOnce(SandwichLayer layer) {
return once.contains(layer.getId().toLowerCase(Locale.ROOT));
}

/** This extra comes in a bottle the player keeps (olive oil, vinegar). */
public static boolean returnsBottle(SandwichLayer layer) {
return returnsBottle.contains(layer.getId().toLowerCase(Locale.ROOT));
}

/** A finished salad: the output's type. */
public static boolean isSalad(FoodItem food) {
return food != null && food.getId() != null && food.getId().equalsIgnoreCase(outputType);
}

/** The first kind these ingredients make, or null when none takes them. */
public static SaladKind kindFor(List<FoodItem> foods, List<SandwichLayer> made) {
for (SaladKind kind : kinds) {
if (kind.matches(foods, made)) return kind;
}
return null;
}

public static int maxIngredients() {
return maxIngredients;
}

public static int minIngredients() {
return minIngredients;
}

public static int maxExtras() {
return maxExtras;
}

public static String output() {
return output;
}

public static List<DishBonus> bonuses() {
return bonuses;
}
}
Loading
Loading