diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ConfigManager.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ConfigManager.java index 7a6b0a7b..a9cdf205 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ConfigManager.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ConfigManager.java @@ -473,7 +473,7 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable { public abstract List> parseWeightOperation(List ops, Function validator, Function> groupProvider); - public abstract List> parseGroupWeightOperation(List gops); + public abstract List> parseGroupWeightOperation(List gops, boolean forAvailable, Function> groupProvider); @Deprecated public Map> getDefaultFormatFunctions() { diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/AddWeightOperation.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/AddWeightOperation.java index 12867b36..1a7d1ce4 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/AddWeightOperation.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/AddWeightOperation.java @@ -27,14 +27,19 @@ public class AddWeightOperation implements WeightOperation { private final MathValue arg; private final int sharedMembers; + private final boolean forAvailable; - public AddWeightOperation(MathValue arg, int sharedMembers) { + public AddWeightOperation(MathValue arg, int sharedMembers, boolean forAvailable) { this.arg = arg; this.sharedMembers = sharedMembers; + this.forAvailable = forAvailable; } @Override public Double apply(Context context, Double weight, Map weights) { + if (this.forAvailable && weight <= 0) { + return weight; + } return weight + arg.evaluate(context) / sharedMembers; } } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/CustomWeightOperation.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/CustomWeightOperation.java index f13006ef..86e4c291 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/CustomWeightOperation.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/CustomWeightOperation.java @@ -34,17 +34,22 @@ public class CustomWeightOperation implements WeightOperation { private final List otherEntries; private final List> otherGroups; private final int sharedMembers; + private final boolean forAvailable; - public CustomWeightOperation(MathValue arg, boolean hasTotalWeight, List otherEntries, List> otherGroups, int sharedMembers) { + public CustomWeightOperation(MathValue arg, boolean hasTotalWeight, List otherEntries, List> otherGroups, int sharedMembers, boolean forAvailable) { this.arg = arg; this.hasTotalWeight = hasTotalWeight; this.otherEntries = otherEntries; this.otherGroups = otherGroups; this.sharedMembers = sharedMembers; + this.forAvailable = forAvailable; } @Override public Double apply(Context context, Double weight, Map weights) { + if (this.forAvailable && weight <= 0) { + return weight; + } context.arg(ContextKeys.WEIGHT, weight); if (hasTotalWeight) { context.arg(ContextKeys.TOTAL_WEIGHT, getValidTotalWeight(weights.values())); diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/DivideWeightOperation.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/DivideWeightOperation.java index ca2200d2..f45c9f62 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/DivideWeightOperation.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/DivideWeightOperation.java @@ -26,13 +26,18 @@ import java.util.Map; public class DivideWeightOperation implements WeightOperation { private final MathValue arg; + private final boolean forAvailable; - public DivideWeightOperation(MathValue arg) { + public DivideWeightOperation(MathValue arg, boolean forAvailable) { this.arg = arg; + this.forAvailable = forAvailable; } @Override public Double apply(Context context, Double weight, Map weights) { + if (this.forAvailable && weight <= 0) { + return weight; + } return weight / arg.evaluate(context); } } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/ModuloWeightOperation.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/ModuloWeightOperation.java index 529d7a55..231349f9 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/ModuloWeightOperation.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/ModuloWeightOperation.java @@ -26,13 +26,18 @@ import java.util.Map; public class ModuloWeightOperation implements WeightOperation { private final MathValue arg; + private final boolean forAvailable; - public ModuloWeightOperation(MathValue arg) { + public ModuloWeightOperation(MathValue arg, boolean forAvailable) { this.arg = arg; + this.forAvailable = forAvailable; } @Override public Double apply(Context context, Double weight, Map weights) { + if (this.forAvailable && weight <= 0) { + return weight; + } return weight % arg.evaluate(context); } } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/MultiplyWeightOperation.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/MultiplyWeightOperation.java index 757b99dd..07eaf055 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/MultiplyWeightOperation.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/MultiplyWeightOperation.java @@ -26,13 +26,18 @@ import java.util.Map; public class MultiplyWeightOperation implements WeightOperation { private final MathValue arg; + private final boolean forAvailable; - public MultiplyWeightOperation(MathValue arg) { + public MultiplyWeightOperation(MathValue arg, boolean forAvailable) { this.arg = arg; + this.forAvailable = forAvailable; } @Override public Double apply(Context context, Double weight, Map weights) { + if (this.forAvailable && weight <= 0) { + return weight; + } return weight * arg.evaluate(context); } } diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/ReduceWeightOperation.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/ReduceWeightOperation.java index e44368a3..26526a60 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/ReduceWeightOperation.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/loot/operation/ReduceWeightOperation.java @@ -27,14 +27,19 @@ public class ReduceWeightOperation implements WeightOperation { private final MathValue arg; private final int sharedMembers; + private final boolean forAvailable; - public ReduceWeightOperation(MathValue arg, int sharedMembers) { + public ReduceWeightOperation(MathValue arg, int sharedMembers, boolean forAvailable) { this.arg = arg; this.sharedMembers = sharedMembers; + this.forAvailable = forAvailable; } @Override public Double apply(Context context, Double weight, Map weights) { + if (this.forAvailable && weight < 0) { + return weight; + } return weight - arg.evaluate(context) / sharedMembers; } } diff --git a/core/src/main/java/net/momirealms/customfishing/bukkit/config/BukkitConfigManager.java b/core/src/main/java/net/momirealms/customfishing/bukkit/config/BukkitConfigManager.java index 03d8b768..0ac6420a 100644 --- a/core/src/main/java/net/momirealms/customfishing/bukkit/config/BukkitConfigManager.java +++ b/core/src/main/java/net/momirealms/customfishing/bukkit/config/BukkitConfigManager.java @@ -30,6 +30,8 @@ import dev.dejvokep.boostedyaml.settings.loader.LoaderSettings; import dev.dejvokep.boostedyaml.settings.updater.UpdaterSettings; import dev.dejvokep.boostedyaml.utils.format.NodeRole; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; +import net.momirealms.customfishing.api.event.FishingEffectApplyEvent; +import net.momirealms.customfishing.api.event.FishingResultEvent; import net.momirealms.customfishing.api.mechanic.MechanicType; import net.momirealms.customfishing.api.mechanic.action.Action; import net.momirealms.customfishing.api.mechanic.action.ActionManager; @@ -649,7 +651,7 @@ public class BukkitConfigManager extends ConfigManager { })); } case "group-mod", "group_mod" -> { - var op = parseGroupWeightOperation(section.getStringList("value")); + var op = parseGroupWeightOperation(section.getStringList("value"), true, groupProvider); return (((effect, context, phase) -> { if (phase == 1) { effect.weightOperations(op); @@ -658,7 +660,7 @@ public class BukkitConfigManager extends ConfigManager { })); } case "group-mod-ignore-conditions", "group_mod_ignore_conditions" -> { - var op = parseGroupWeightOperation(section.getStringList("value")); + var op = parseGroupWeightOperation(section.getStringList("value"), false, groupProvider); return (((effect, context, phase) -> { if (phase == 1) { effect.weightOperationsIgnored(op); @@ -786,15 +788,15 @@ public class BukkitConfigManager extends ConfigManager { } } - private WeightOperation parseSharedGroupWeight(String op, int memberCount) { + private WeightOperation parseSharedGroupWeight(String op, int memberCount, boolean forAvailable, Function> groupProvider) { switch (op.charAt(0)) { case '-' -> { MathValue arg = MathValue.auto(op.substring(1)); - return new ReduceWeightOperation(arg, memberCount); + return new ReduceWeightOperation(arg, memberCount, forAvailable); } case '+' -> { MathValue arg = MathValue.auto(op.substring(1)); - return new AddWeightOperation(arg, memberCount); + return new AddWeightOperation(arg, memberCount, forAvailable); } case '=' -> { String expression = op.substring(1); @@ -806,43 +808,42 @@ public class BukkitConfigManager extends ConfigManager { if (placeholder.startsWith("{entry_")) { otherEntries.add(placeholder.substring("{entry_".length(), placeholder.length() - 1)); } else if (placeholder.startsWith("{group")) { - // only for loots - String groupName = placeholder.substring("{group_".length(), placeholder.length() - 1); - List members = plugin.getLootManager().getGroupMembers(groupName); + String groupExpression = placeholder.substring("{group_".length(), placeholder.length() - 1); + List members = getGroupMembers(groupExpression, groupProvider); if (members.isEmpty()) { - plugin.getPluginLogger().warn("Failed to load expression: " + expression + ". Invalid group: " + groupName); + plugin.getPluginLogger().warn("Failed to load expression: " + expression + ". Invalid group: " + groupExpression); continue; } - otherGroups.add(Pair.of(groupName, members.toArray(new String[0]))); + otherGroups.add(Pair.of(groupExpression, members.toArray(new String[0]))); } } - return new CustomWeightOperation(arg, expression.contains("{1}"), otherEntries, otherGroups, memberCount); + return new CustomWeightOperation(arg, expression.contains("{1}"), otherEntries, otherGroups, memberCount, forAvailable); } default -> throw new IllegalArgumentException("Invalid shared weight operation: " + op); } } - private WeightOperation parseWeightOperation(String op) { + private WeightOperation parseWeightOperation(String op, boolean forAvailable, Function> groupProvider) { switch (op.charAt(0)) { case '/' -> { MathValue arg = MathValue.auto(op.substring(1)); - return new DivideWeightOperation(arg); + return new DivideWeightOperation(arg, forAvailable); } case '*' -> { MathValue arg = MathValue.auto(op.substring(1)); - return new MultiplyWeightOperation(arg); + return new MultiplyWeightOperation(arg, forAvailable); } case '-' -> { MathValue arg = MathValue.auto(op.substring(1)); - return new ReduceWeightOperation(arg, 1); + return new ReduceWeightOperation(arg, 1, forAvailable); } case '%' -> { MathValue arg = MathValue.auto(op.substring(1)); - return new ModuloWeightOperation(arg); + return new ModuloWeightOperation(arg, forAvailable); } case '+' -> { MathValue arg = MathValue.auto(op.substring(1)); - return new AddWeightOperation(arg, 1); + return new AddWeightOperation(arg, 1, forAvailable); } case '=' -> { String expression = op.substring(1); @@ -854,17 +855,16 @@ public class BukkitConfigManager extends ConfigManager { if (placeholder.startsWith("{entry_")) { otherEntries.add(placeholder.substring("{entry_".length(), placeholder.length() - 1)); } else if (placeholder.startsWith("{group")) { - // only for loots - String groupName = placeholder.substring("{group_".length(), placeholder.length() - 1); - List members = plugin.getLootManager().getGroupMembers(groupName); + String groupExpression = placeholder.substring("{group_".length(), placeholder.length() - 1); + List members = getGroupMembers(groupExpression, groupProvider); if (members.isEmpty()) { - plugin.getPluginLogger().warn("Failed to load expression: " + expression + ". Invalid group: " + groupName); + plugin.getPluginLogger().warn("Failed to load expression: " + expression + ". Invalid group: " + groupExpression); continue; } - otherGroups.add(Pair.of(groupName, members.toArray(new String[0]))); + otherGroups.add(Pair.of(groupExpression, members.toArray(new String[0]))); } } - return new CustomWeightOperation(arg, expression.contains("{1}"), otherEntries, otherGroups, 1); + return new CustomWeightOperation(arg, expression.contains("{1}"), otherEntries, otherGroups, 1, forAvailable); } default -> throw new IllegalArgumentException("Invalid weight operation: " + op); } @@ -885,39 +885,68 @@ public class BukkitConfigManager extends ConfigManager { plugin.getPluginLogger().warn("Illegal weight operation: " + op + ". Id " + id + " is not valid"); continue; } - result.add(Pair.of(id, parseWeightOperation(split[1]))); + result.add(Pair.of(id, parseWeightOperation(split[1], false, groupProvider))); } else { String type = split[0]; String id = split[1]; switch (type) { case "group_for_each" -> { - List members = groupProvider.apply(id); + List members = getGroupMembers(id, groupProvider); if (members.isEmpty()) { plugin.getPluginLogger().warn("Failed to load expression: " + op + ". Invalid group: " + id); continue; } - WeightOperation operation = parseWeightOperation(split[2]); + WeightOperation operation = parseWeightOperation(split[2], false, groupProvider); + for (String member : members) { + result.add(Pair.of(member, operation)); + } + } + case "group_available_for_each" -> { + List members = getGroupMembers(id, groupProvider); + if (members.isEmpty()) { + plugin.getPluginLogger().warn("Failed to load expression: " + op + ". Invalid group: " + id); + continue; + } + WeightOperation operation = parseWeightOperation(split[2], true, groupProvider); for (String member : members) { result.add(Pair.of(member, operation)); } } case "group_total" -> { - List members = groupProvider.apply(id); + List members = getGroupMembers(id, groupProvider); if (members.isEmpty()) { plugin.getPluginLogger().warn("Failed to load expression: " + op + ". Invalid group: " + id); continue; } - WeightOperation operation = parseSharedGroupWeight(split[2], members.size()); + WeightOperation operation = parseSharedGroupWeight(split[2], members.size(), false, groupProvider); for (String member : members) { result.add(Pair.of(member, operation)); } } + case "group_available_total" -> { + List members = getGroupMembers(id, groupProvider); + if (members.isEmpty()) { + plugin.getPluginLogger().warn("Failed to load expression: " + op + ". Invalid group: " + id); + continue; + } + WeightOperation operation = parseSharedGroupWeight(split[2], members.size(), true, groupProvider); + for (String member : members) { + result.add(Pair.of(member, operation)); + } + } + case "loot_available" -> { + if (!validator.apply(id)) { + plugin.getPluginLogger().warn("Illegal weight operation: " + op + ". Id " + id + " is not valid"); + continue; + } + result.add(Pair.of(id, parseWeightOperation(split[2], true, groupProvider))); + } default -> { if (!validator.apply(id)) { plugin.getPluginLogger().warn("Illegal weight operation: " + op + ". Id " + id + " is not valid"); continue; } - result.add(Pair.of(id, parseWeightOperation(split[2]))); + result.add(Pair.of(id, parseWeightOperation(split[2], false, groupProvider))); } } } @@ -926,7 +955,7 @@ public class BukkitConfigManager extends ConfigManager { } @Override - public List> parseGroupWeightOperation(List gops) { + public List> parseGroupWeightOperation(List gops, boolean forAvailable, Function> groupProvider) { List> result = new ArrayList<>(); for (String gop : gops) { String[] split = gop.split(":", 2); @@ -934,14 +963,43 @@ public class BukkitConfigManager extends ConfigManager { plugin.getPluginLogger().warn("Illegal weight operation: " + gop); continue; } - WeightOperation operation = parseWeightOperation(split[1]); - for (String member : plugin.getLootManager().getGroupMembers(split[0])) { + WeightOperation operation = parseWeightOperation(split[1], forAvailable, groupProvider); + String groupExpression = split[0]; + for (String member : getGroupMembers(groupExpression, groupProvider)) { result.add(Pair.of(member, operation)); } } + FishingEffectApplyEvent event; + if (event.getStage() == FishingEffectApplyEvent.Stage.FISHING) { + event.getEffect().difficultyAdder(event.getEffect().difficultyAdder() + 10d); + } return result; } + private List getGroupMembers(String groupExpression, Function> groupProvider) { + if (groupExpression.contains("&")) { + String[] groups = groupExpression.split("&"); + List> groupSets = new ArrayList<>(); + for (String group : groups) { + groupSets.add(new HashSet<>(groupProvider.apply(group))); + } + Set intersection = groupSets.get(0); + for (int i = 1; i < groupSets.size(); i++) { + intersection.retainAll(groupSets.get(i)); + } + return new ArrayList<>(intersection); + } else if (groupExpression.contains("|")) { + Set members = new HashSet<>(); + String[] groups = groupExpression.split("&"); + for (String group : groups) { + members.addAll(groupProvider.apply(group)); + } + return new ArrayList<>(members); + } else { + return groupProvider.apply(groupExpression); + } + } + private void registerBuiltInHookParser() { this.registerHookParser(object -> { List lore = ListUtils.toList(object); diff --git a/core/src/main/resources/contents/item/default.yml b/core/src/main/resources/contents/item/default.yml index 98c261f6..de9bf2fa 100644 --- a/core/src/main/resources/contents/item/default.yml +++ b/core/src/main/resources/contents/item/default.yml @@ -231,7 +231,9 @@ tuna_fish: - Tuna is a kind of healthy food. - 'size: {size_formatted}cm' custom-model-data: 50001 - group: ocean + group: + - ocean + - no_star events: success: action_mending: @@ -299,7 +301,9 @@ pike_fish: - water and inland freshwater lakes - 'size: {size_formatted}cm' custom-model-data: 50004 - group: ocean + group: + - ocean + - no_star events: success: action_mending: @@ -376,7 +380,9 @@ gold_fish: bonus: 2.6 size: 2~3 custom-model-data: 50007 - group: river + group: + - no_star + - river events: success: action_mending: @@ -442,7 +448,9 @@ perch_fish: - foraging at dusk and early morning - 'size: {size_formatted}cm' custom-model-data: 50010 - group: river + group: + - no_star + - river events: success: action_mending: @@ -510,7 +518,9 @@ mullet_fish: - to treat spleen and stomach weakness - 'size: {size_formatted}cm' custom-model-data: 50013 - group: river + group: + - no_star + - river events: success: action_mending: @@ -578,7 +588,9 @@ sardine_fish: - Therefore, sardine are also called "smart food" - 'size: {size_formatted}cm' custom-model-data: 50016 - group: ocean + group: + - ocean + - no_star events: success: action_mending: @@ -643,7 +655,9 @@ carp_fish: - One of the most common edible fish - 'size: {size_formatted}cm' custom-model-data: 50019 - group: river + group: + - no_star + - river events: success: action_mending: @@ -707,7 +721,9 @@ cat_fish: - sharp jaw teeth, short intestine and stomach - 'size: {size_formatted}cm' custom-model-data: 50022 - group: river + group: + - no_star + - river events: success: action_mending: @@ -773,7 +789,9 @@ octopus: - People often use pots to catch octopus - 'size: {size_formatted}cm' custom-model-data: 50025 - group: ocean + group: + - ocean + - no_star events: success: action_mending: @@ -838,7 +856,9 @@ sunfish: - It only has one huge head - 'size: {size_formatted}cm' custom-model-data: 50028 - group: ocean + group: + - ocean + - no_star events: success: action_mending: @@ -902,7 +922,9 @@ red_snapper_fish: - with a male as the "head of the family" - 'size: {size_formatted}cm' custom-model-data: 50031 - group: ocean + group: + - ocean + - no_star events: success: action_mending: @@ -971,7 +993,9 @@ salmon_void_fish: - It's looking at you... - 'size: {size_formatted}cm' custom-model-data: 50034 - group: lava + group: + - lava + - no_star events: success: action_mending: @@ -1037,7 +1061,9 @@ woodskip_fish: - live in pools deep in the forest - 'size: {size_formatted}cm' custom-model-data: 50037 - group: river + group: + - no_star + - swamp events: success: action_mending: @@ -1060,7 +1086,7 @@ woodskip_fish_silver_star: custom-model-data: 50038 group: - silver_star - - river + - swamp events: success: action_mending: @@ -1083,7 +1109,7 @@ woodskip_fish_golden_star: custom-model-data: 50039 group: - golden_star - - river + - swamp events: success: action_mending: @@ -1103,7 +1129,9 @@ sturgeon_fish: - population. Females can live up to 150 years - 'size: {size_formatted}cm' custom-model-data: 50040 - group: river + group: + - no_star + - cave events: success: action_mending: @@ -1126,7 +1154,7 @@ sturgeon_fish_silver_star: custom-model-data: 50041 group: - silver_star - - river + - cave events: success: action_mending: @@ -1149,7 +1177,7 @@ sturgeon_fish_golden_star: custom-model-data: 50042 group: - golden_star - - river + - cave events: success: action_mending: @@ -1168,7 +1196,9 @@ blue_jellyfish: - Looks like a blue umbrella - 'size: {size_formatted}cm' custom-model-data: 50043 - group: ocean + group: + - warm_ocean + - no_star events: success: action_mending: @@ -1190,7 +1220,7 @@ blue_jellyfish_silver_star: custom-model-data: 50044 group: - silver_star - - ocean + - warm_ocean events: success: action_mending: @@ -1212,7 +1242,7 @@ blue_jellyfish_golden_star: custom-model-data: 50045 group: - golden_star - - ocean + - warm_ocean events: success: action_mending: @@ -1231,7 +1261,9 @@ pink_jellyfish: - Seems to be sweet - 'size: {size_formatted}cm' custom-model-data: 50046 - group: ocean + group: + - warm_ocean + - no_star events: success: action_mending: @@ -1253,7 +1285,7 @@ pink_jellyfish_silver_star: custom-model-data: 50047 group: - silver_star - - ocean + - warm_ocean events: success: action_mending: @@ -1275,7 +1307,7 @@ pink_jellyfish_golden_star: custom-model-data: 50048 group: - golden_star - - ocean + - warm_ocean events: success: action_mending: diff --git a/core/src/main/resources/loot-conditions.yml b/core/src/main/resources/loot-conditions.yml index 976dfd80..15484728 100644 --- a/core/src/main/resources/loot-conditions.yml +++ b/core/src/main/resources/loot-conditions.yml @@ -33,24 +33,9 @@ global-group: - apple_crate:+2 - carrot_crate:+2 - kelp:+25 - - tuna_fish:+15 - - tuna_fish_silver_star:+3 - - tuna_fish_golden_star:+1 - - pike_fish:+15 - - pike_fish_silver_star:+3 - - pike_fish_golden_star:+1 - - sardine_fish:+15 - - sardine_fish_silver_star:+3 - - sardine_fish_golden_star:+1 - - octopus:+10 - - octopus_silver_star:+2 - - octopus_golden_star:+1 - - sunfish:+15 - - sunfish_silver_star:+3 - - sunfish_golden_star:+1 - - red_snapper_fish:+20 - - red_snapper_fish_silver_star:+5 - - red_snapper_fish_golden_star:+2 + - group_for_each:ocean&no_star:+15 + - group_for_each:ocean&silver_star:+3 + - group_for_each:ocean&golden_star:+1 sub-groups: warm_ocean_fish: conditions: @@ -59,12 +44,9 @@ global-group: - minecraft:deep_lukewarm_ocean - minecraft:warm_ocean list: - - blue_jellyfish:+15 - - blue_jellyfish_silver_star:+3 - - blue_jellyfish_golden_star:+1 - - pink_jellyfish:+15 - - pink_jellyfish_silver_star:+3 - - pink_jellyfish_golden_star:+1 + - group_for_each:warm_ocean&no_star:+15 + - group_for_each:warm_ocean&silver_star:+3 + - group_for_each:warm_ocean&golden_star:+1 river_fish: conditions: '!biome': @@ -80,27 +62,15 @@ global-group: list: - rainbow_fish:+5 - stick:+15 - - gold_fish:+15 - - gold_fish_silver_star:+3 - - gold_fish_golden_star:+1 - - perch_fish:+15 - - perch_fish_silver_star:+3 - - perch_fish_golden_star:+1 - - mullet_fish:+15 - - mullet_fish_silver_star:+3 - - mullet_fish_golden_star:+1 - - carp_fish:+25 - - carp_fish_silver_star:+5 - - carp_fish_golden_star:+2 - - cat_fish:+15 - - cat_fish_silver_star:+3 - - cat_fish_golden_star:+1 + - group_for_each:river&no_star:+15 + - group_for_each:river&silver_star:+3 + - group_for_each:river&golden_star:+1 sub-groups: swamp_fish: list: - - 'woodskip_fish:+30' - - 'woodskip_fish_silver_star:+5' - - 'woodskip_fish_golden_star:+2' + - group_for_each:swamp&no_star:+15 + - group_for_each:swamp&silver_star:+3 + - group_for_each:swamp&golden_star:+1 conditions: biome: - minecraft:swamp @@ -110,9 +80,9 @@ global-group: ypos: - -64~0 list: - - 'sturgeon_fish:+9' - - 'sturgeon_fish_silver_star:+3' - - 'sturgeon_fish_golden_star:+1' + - group_for_each:cave&no_star:+9 + - group_for_each:cave&silver_star:+3 + - group_for_each:cave&golden_star:+1 # Skeletons might appear if player holds the bone_rod and fish at night skeleton_group: conditions: @@ -148,9 +118,9 @@ global-group: - 'gold_ingot:+3' - 'gold_nugget:+8' - 'magma_cube:+3' - - 'salmon_void_fish:+15' - - 'salmon_void_fish_silver_star:+3' - - 'salmon_void_fish_golden_star:+1' + - group_for_each:lava&no_star:+15 + - group_for_each:lava&silver_star:+3 + - group_for_each:lava&golden_star:+1 sub-groups: skeleton_group: conditions: