Repository navigation
feat: let MMOItems crafting stations take Cooking food #67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
d038eb9
feat: let MMOItems crafting stations take Cooking food
XxFran10xX d1c4b4b
fix: claim ItemsAdder-modelled food and build refunds on their item
XxFran10xX f982275
fix: refund the food the plain item becomes, aged out
XxFran10xX bde7e67
fix: pick refund bases by food identity and set pinned tags
XxFran10xX 0f530ba
fix: age tracks a recipe names without a value
XxFran10xX File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| 2cbd119bf1961c28788310963dc80ba65f58cdeec1dd139c8bdb1240faa2c36f libs/gson-2.14.0.jar | ||
| feca4db853371704338621c120acc5cc32300d8af635fa42414b6213301e216b libs/joml-1.10.9.jar | ||
| 225aa7f75d4e6e6ae6b3ad87a7ca678c025c027f00374ab1062275d24f3a73c9 libs/MythicLib-1.7.1-SNAPSHOT.jar | ||
| a37f7789fcdcd11c9e5890a2fac742aa4501749588af23182991953e06ee1d17 libs/MMOItems-6.10.1-SNAPSHOT.jar | ||
| 81d511d0830951f988615b6533cc93e82d00a83fb31e8ccbb36441ae3e8157ef libs/MMOCore-1.13.1-SNAPSHOT.jar | ||
| 93317bf08c9dae4a645644caa313b5436b19e65cc13abf9f3e0afb951bd6c1d2 libs/CustomCrops-3.6.56.jar | ||
| 7d3083bd05998d8cafd7114ced74a6fa2ec1c4d36f75dbbaee9f20d499a7c3ad libs/CustomFishing-2.3.27.jar |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
196 changes: 196 additions & 0 deletions
196
src/main/java/net/tfminecraft/cooking/mmoitems/CookingStationIngredient.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,196 @@ | ||
| package net.tfminecraft.cooking.mmoitems; | ||
|
|
||
| import java.util.HashMap; | ||
| import java.util.List; | ||
| import java.util.Locale; | ||
| import java.util.Map; | ||
| import java.util.Set; | ||
|
|
||
| import org.bukkit.Material; | ||
| import org.bukkit.inventory.ItemStack; | ||
| import org.bukkit.inventory.meta.ItemMeta; | ||
|
|
||
| import io.lumine.mythic.lib.api.MMOLineConfig; | ||
| import net.Indyuce.mmoitems.api.crafting.ingredient.Ingredient; | ||
| import net.Indyuce.mmoitems.api.player.RPGPlayer; | ||
| import net.tfminecraft.cooking.item.CookingPathHandler; | ||
| import net.tfminecraft.cooking.item.FoodItem; | ||
| import net.tfminecraft.cooking.item.tag.AgeScale; | ||
| import net.tfminecraft.cooking.item.tag.TagStep; | ||
| import net.tfminecraft.cooking.item.tag.TagTrack; | ||
| import net.tfminecraft.cooking.loader.TrackLoader; | ||
| import net.tfminecraft.cooking.utils.FoodParser; | ||
| import net.tfminecraft.cooking.utils.ItemBuilder; | ||
|
|
||
| /** | ||
| * {@code cooking{item="seafood(type=seafood_whole;origin=Salmon)",amount=64,display="Salmon"}}. | ||
| * {@code item} is a Cooking path without the {@code c.} prefix, matched like every other | ||
| * {@code c.} path. It must name a food type: MMOItems hands that food back when a queued craft | ||
| * is cancelled. | ||
| */ | ||
| public class CookingStationIngredient extends Ingredient<CookingStationPlayerIngredient> { | ||
| private final String path; | ||
| private final Map<String, String> fields; | ||
| private final String display; | ||
|
|
||
| public CookingStationIngredient(MMOLineConfig config) { | ||
| super(MMOItemsIngredients.ID, config); | ||
| config.validate("item"); | ||
| path = CookingPathHandler.stripPrefix(config.getString("item")); | ||
| int paren = path.indexOf('('); | ||
| fields = paren < 0 || !path.endsWith(")") ? Map.of() | ||
| : FoodParser.extractFields(path.substring(paren + 1, path.length() - 1)); | ||
| String type = field("type"); | ||
| if (type == null) { | ||
| throw new IllegalArgumentException("cooking ingredient item=\"" + path | ||
| + "\" needs a food type, e.g. seafood(type=seafood_whole;origin=Salmon)"); | ||
| } | ||
| String origin = field("origin"); | ||
| display = config.getString("display", origin != null ? origin : words(type)); | ||
| } | ||
|
|
||
| private String field(String key) { | ||
| for (Map.Entry<String, String> entry : fields.entrySet()) { | ||
| if (entry.getKey().trim().equalsIgnoreCase(key) && !entry.getValue().isBlank()) { | ||
| return entry.getValue().trim(); | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| private static String words(String id) { | ||
| StringBuilder out = new StringBuilder(); | ||
| for (String word : id.split("_+")) { | ||
| if (word.isEmpty()) { | ||
| continue; | ||
| } | ||
| if (out.length() > 0) { | ||
| out.append(' '); | ||
| } | ||
| out.append(word.substring(0, 1).toUpperCase(Locale.ROOT)).append(word.substring(1)); | ||
| } | ||
| return out.toString(); | ||
| } | ||
|
|
||
| public String getPath() { | ||
| return path; | ||
| } | ||
|
|
||
| public String getDisplayName() { | ||
| return display; | ||
| } | ||
|
|
||
| @Override | ||
| public String formatDisplay(String format) { | ||
| return format.replace("#item#", display).replace("#amount#", String.valueOf(getAmount())); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean matches(CookingStationPlayerIngredient ingredient) { | ||
| return CookingPathHandler.matches(ingredient.getFood(), path); | ||
| } | ||
|
|
||
| /** | ||
| * The food is what its plain item becomes on pickup (a whole salmon, wheat with its freshness | ||
| * track), else the food the path names, with the tag values the line pins. The preview shows | ||
| * it fresh. A refund (forDisplay false) cannot know what was spent, so it is the least the | ||
| * line accepts: its lowest quality, aged out on every track the line leaves open. Cancelling | ||
| * never improves food. | ||
| */ | ||
| @Override | ||
| public ItemStack generateItemStack(RPGPlayer player, boolean forDisplay) { | ||
| FoodParser.Result parsed = FoodParser.parse(path); | ||
| ItemStack source = StationFood.plainSource(path); | ||
| FoodItem food = source != null ? StationFood.describe(source) : parsed == null ? null : parsed.template; | ||
| ItemStack stack = null; | ||
| if (food != null) { | ||
| Map<String, Integer> pins = pinnedTracks(); | ||
| applyPins(food, pins); | ||
| if (!forDisplay) { | ||
| ageOpenTracks(food, pins.keySet()); | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| } | ||
| boolean explicit = parsed != null && parsed.explicitQuality; | ||
| stack = ItemBuilder.buildSingleWithQuality(food, source, | ||
| explicit ? parsed.template._parsedQualMin : StationFood.PLAIN_QUALITY); | ||
| } | ||
| if (stack == null) { | ||
| // Cooking does not know this food type (yet). | ||
| stack = placeholder(); | ||
| } | ||
| stack.setAmount(forDisplay ? Math.max(1, Math.min(getAmount(), stack.getMaxStackSize())) : getAmount()); | ||
| return stack; | ||
| } | ||
|
|
||
| private static void applyPins(FoodItem food, Map<String, Integer> pins) { | ||
| for (Map.Entry<String, Integer> pin : pins.entrySet()) { | ||
| TagTrack track = track(food, pin.getKey()); | ||
| if (track != null) { | ||
| track.forceSetValue(pin.getValue()); | ||
| continue; | ||
| } | ||
| TagTrack base = TrackLoader.getByString(pin.getKey()); | ||
| if (base != null) { | ||
| TagTrack added = new TagTrack(base); | ||
| added.forceSetValue(pin.getValue()); | ||
| food.addOrModifyTrack(added); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private static TagTrack track(FoodItem food, String id) { | ||
| for (TagTrack track : food.getTagTracks()) { | ||
| if (track.getId().equalsIgnoreCase(id)) { | ||
| return track; | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| private static void ageOpenTracks(FoodItem food, Set<String> pinned) { | ||
| for (TagTrack track : food.getTagTracks()) { | ||
| List<TagStep> steps = track.getSteps(); | ||
| if (track.isAgeable() && !steps.isEmpty() && !pinned.contains(track.getId().toLowerCase(Locale.ROOT))) { | ||
| track.forceSetValue((int) steps.get(steps.size() - 1).getRequiredValue()); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Track id to the value the line requires. Matching ignores a tag without a usable value, so | ||
| * such a tag constrains nothing and its track still ages out on a refund. | ||
| */ | ||
| private Map<String, Integer> pinnedTracks() { | ||
| Map<String, Integer> pinned = new HashMap<>(); | ||
| String tags = field("tags"); | ||
| if (tags != null) { | ||
| for (String tag : tags.split("[,:]")) { | ||
| String[] parts = tag.split("\\.", 2); | ||
| if (parts.length < 2) { | ||
| continue; | ||
| } | ||
| String raw = parts[0].trim(); | ||
| try { | ||
| int value = AgeScale.migrateTrackValue(raw, Integer.parseInt(parts[1].trim())); | ||
| pinned.put(AgeScale.migrateTrackId(raw).toLowerCase(Locale.ROOT), value); | ||
| } catch (NumberFormatException e) { | ||
| // Not a number: the line accepts nothing for this tag, so there is no value to keep. | ||
| } | ||
| } | ||
| } | ||
| return pinned; | ||
| } | ||
|
|
||
| @SuppressWarnings("deprecation") | ||
| private ItemStack placeholder() { | ||
| ItemStack stack = new ItemStack(Material.PAPER); | ||
| ItemMeta meta = stack.getItemMeta(); | ||
| meta.setDisplayName(display); | ||
| stack.setItemMeta(meta); | ||
| return stack; | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| return "cooking{item=\"" + path + "\",amount=" + getAmount() + "}"; | ||
| } | ||
| } | ||
19 changes: 19 additions & 0 deletions
19
src/main/java/net/tfminecraft/cooking/mmoitems/CookingStationPlayerIngredient.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package net.tfminecraft.cooking.mmoitems; | ||
|
|
||
| import io.lumine.mythic.lib.api.item.NBTItem; | ||
| import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.PlayerIngredient; | ||
| import net.tfminecraft.cooking.item.FoodItem; | ||
|
|
||
| /** An inventory stack MMOItems sorted into the cooking ingredient type, with the food it counts as. */ | ||
| public class CookingStationPlayerIngredient extends PlayerIngredient { | ||
| private final FoodItem food; | ||
|
|
||
| public CookingStationPlayerIngredient(NBTItem item) { | ||
| super(item); | ||
| food = StationFood.describe(item.getItem()); | ||
| } | ||
|
|
||
| public FoodItem getFood() { | ||
| return food; | ||
| } | ||
| } |
52 changes: 52 additions & 0 deletions
52
src/main/java/net/tfminecraft/cooking/mmoitems/MMOItemsIngredients.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| package net.tfminecraft.cooking.mmoitems; | ||
|
|
||
| import java.util.List; | ||
| import java.util.logging.Logger; | ||
|
|
||
| import net.Indyuce.mmoitems.MMOItems; | ||
| import net.Indyuce.mmoitems.api.crafting.ConditionalDisplay; | ||
| import net.Indyuce.mmoitems.api.crafting.ingredient.IngredientType; | ||
| import net.Indyuce.mmoitems.manager.CraftingManager; | ||
|
|
||
| /** | ||
| * Registers the {@code cooking} crafting station ingredient. MMOItems checks newly registered | ||
| * types first, so Cooking food and the plain items Cooking converts are claimed here before the | ||
| * {@code vanilla} type, which only accepts unnamed items. Use {@code cooking{...}} for them. | ||
| */ | ||
| public final class MMOItemsIngredients { | ||
| public static final String ID = "cooking"; | ||
|
|
||
| private MMOItemsIngredients() {} | ||
|
|
||
| static void register(Logger logger) { | ||
| register(MMOItems.plugin.getCrafting(), logger); | ||
| } | ||
|
|
||
| static void register(CraftingManager crafting, Logger logger) { | ||
| crafting.registerIngredient(ID, CookingStationIngredient::new, | ||
| new ConditionalDisplay("&a✔ &7#amount# #item#", "&c✖ &7#amount# #item#"), | ||
| nbt -> StationFood.describe(nbt.getItem()) != null, | ||
| CookingStationPlayerIngredient::new); | ||
| logger.info("Registered the MMOItems crafting station ingredient cooking{item=...}."); | ||
| } | ||
|
|
||
| static void claimFirst(Logger logger) { | ||
| claimFirst(MMOItems.plugin.getCrafting(), logger); | ||
| } | ||
|
|
||
| /** | ||
| * MMOItems registers its ItemsAdder (and Nexo, Oraxen, MythicMobs) types while it enables, | ||
| * after onLoad, and each goes in front. Cooking food built on an ItemsAdder model would then | ||
| * be read as an ItemsAdder item, so put cooking back in front once everything has enabled. | ||
| */ | ||
| static void claimFirst(CraftingManager crafting, Logger logger) { | ||
| List<IngredientType<?>> types = crafting.getIngredients(); | ||
| for (int i = 1; i < types.size(); i++) { | ||
| if (ID.equals(types.get(i).getId())) { | ||
| types.add(0, types.remove(i)); | ||
| logger.info("Moved the cooking station ingredient ahead of " + types.get(1).getId() + "."); | ||
| return; | ||
| } | ||
| } | ||
| } | ||
| } |
36 changes: 36 additions & 0 deletions
36
src/main/java/net/tfminecraft/cooking/mmoitems/MMOItemsSupport.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| package net.tfminecraft.cooking.mmoitems; | ||
|
|
||
| import java.util.logging.Level; | ||
| import java.util.logging.Logger; | ||
|
|
||
| import org.bukkit.plugin.PluginManager; | ||
|
|
||
| /** | ||
| * Keeps MMOItems classes out of Cooking unless MMOItems is installed. Register from onLoad: | ||
| * MMOItems reads its crafting stations when it enables, and the ingredient type must exist by then. | ||
| */ | ||
| public final class MMOItemsSupport { | ||
| private MMOItemsSupport() {} | ||
|
|
||
| public static boolean registerIfPresent(PluginManager plugins, Logger logger) { | ||
| return run(plugins, logger, () -> MMOItemsIngredients.register(logger), "register"); | ||
| } | ||
|
|
||
| /** Call once every plugin has enabled (the first server tick). */ | ||
| public static boolean claimFirstIfPresent(PluginManager plugins, Logger logger) { | ||
| return run(plugins, logger, () -> MMOItemsIngredients.claimFirst(logger), "order"); | ||
| } | ||
|
|
||
| private static boolean run(PluginManager plugins, Logger logger, Runnable step, String what) { | ||
| if (plugins.getPlugin("MMOItems") == null) { | ||
| return false; | ||
| } | ||
| try { | ||
| step.run(); | ||
| return true; | ||
| } catch (RuntimeException | LinkageError e) { | ||
| logger.log(Level.WARNING, "Could not " + what + " the MMOItems cooking ingredient", e); | ||
| return false; | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.