From f6723d9cd2febda60192a4249803dd2f05ff94ac Mon Sep 17 00:00:00 2001 From: Patbox <39821509+Patbox@users.noreply.github.com> Date: Thu, 27 Jun 2024 18:28:42 +0200 Subject: [PATCH] Rework config / add presets --- README.md | 11 ++ gradle.properties | 2 +- preset/default.json | 139 +++++++++++++++++ preset/minimal.json | 18 +++ .../java/eu/pb4/ouch/DamageDisplayLogic.java | 50 +++---- .../java/eu/pb4/ouch/DeathDisplayLogic.java | 110 -------------- src/main/java/eu/pb4/ouch/DefaultDisplay.java | 77 ---------- src/main/java/eu/pb4/ouch/FloatingText.java | 6 +- .../java/eu/pb4/ouch/HealDisplayLogic.java | 10 +- src/main/java/eu/pb4/ouch/ModInit.java | 63 +++++--- .../eu/pb4/ouch/{Config.java => Preset.java} | 26 ++-- src/main/java/eu/pb4/ouch/Presets.java | 141 ++++++++++++++++++ .../eu/pb4/ouch/api/DefaultDisplayEvents.java | 116 +++++++++----- 13 files changed, 471 insertions(+), 298 deletions(-) create mode 100644 preset/default.json create mode 100644 preset/minimal.json delete mode 100644 src/main/java/eu/pb4/ouch/DeathDisplayLogic.java delete mode 100644 src/main/java/eu/pb4/ouch/DefaultDisplay.java rename src/main/java/eu/pb4/ouch/{Config.java => Preset.java} (74%) create mode 100644 src/main/java/eu/pb4/ouch/Presets.java diff --git a/README.md b/README.md index cb2b303..90292ce 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,17 @@ It can also display multiple particles with different setting for same damage, a # Configuration. This mod config file is stored as `./config/ouch.json`. +## Preset selection config. +By default, config is in a format of preset selection, allowing you to choose default style/look that's built into the mod. +```json5 +{ + "preset": "default" +} +``` +Available presets: `default`, `minimal` +## Full config. +This config allows you to change any text and it's behaviour. Can be used for advanced configuration. +Default values used by presets can be found here: https://github.com/Patbox/ouch/tree/master/preset All custom text within it uses the [QuickText format](https://placeholders.pb4.eu/user/quicktext/). All predicates use are supplied by [Predicate API, using this format](https://github.com/Patbox/PredicateAPI/blob/1.21/BUILTIN.md). Lines prefixed with `//` aren't part of real config and are here just to explain it. diff --git a/gradle.properties b/gradle.properties index 1a62b6b..0f860d8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ org.gradle.parallel=true loader_version=0.15.11 # Mod Properties - mod_version = 1.0.1 + mod_version = 1.1.0 maven_group = eu.pb4 archives_base_name = ouch diff --git a/preset/default.json b/preset/default.json new file mode 100644 index 0000000..973bfdc --- /dev/null +++ b/preset/default.json @@ -0,0 +1,139 @@ +{ + "damage": [ + [ + { + "text": "<#ff0000>-${value}โ˜€", + "type": "minecraft:dry_out" + }, + { + "text": "<#ff0000>-${value}๐Ÿ”ฑ", + "type": "minecraft:trident" + }, + { + "text": "<#ff0000>-${value}โ˜ƒ", + "type": "minecraft:bad_respawn_point" + }, + { + "text": "<#ff0000>-${value}๐Ÿ–", + "type": "minecraft:starve" + }, + { + "text": "<#ff0000>-${value}๐Ÿ”ฑ", + "type": "minecraft:trident" + }, + { + "text": "<#ff0000>-${value}โ™ฆ", + "type": "minecraft:cramming" + }, + { + "text": "<#ff0000>-${value}โ˜„", + "type": "minecraft:fall" + }, + { + "text": "<#ff0000>-${value}โ˜„", + "type": "minecraft:fly_into_wall" + }, + { + "text": "<#ff0000>-${value}โ–’", + "type": "minecraft:in_wall" + }, + { + "text": "<#ff0000>-${value}โ˜€", + "type": "minecraft:sonic_boom" + }, + { + "text": "<#ff0000>-${value}โ˜„", + "type": "minecraft:spit" + }, + { + "text": "<#ff0000>-${value}โ–ฝ", + "type": "minecraft:sting" + }, + { + "text": "<#ff0000>-${value}โ–ณ", + "type": "minecraft:thorns" + }, + { + "text": "<#ff0000>-${value}๐Ÿ—ก", + "type": [ + "minecraft:mob_attack", + "minecraft:player_attack", + "minecraft:mob_attack_no_aggro" + ] + }, + { + "text": "<#ff0000>-${value}โš ", + "type": [ + "minecraft:out_of_world", + "minecraft:outside_border" + ] + }, + { + "text": "<#ff0000>-${value}๐Ÿงช", + "type": [ + "minecraft:magic", + "minecraft:indirect_magic", + "minecraft:dragon_breath" + ] + }, + { + "text": "<#ff0000>-${value}๐Ÿงช", + "type": [ + "minecraft:wither", + "minecraft:wither_skull" + ] + }, + { + "text": "<#ff0000>-${value}โ™ฆ", + "type": [ + "minecraft:cactus", + "minecraft:sweet_berry_bush" + ] + }, + { + "text": "<#ff0000>-${value}โ˜„", + "type": [ + "minecraft:falling_stalactite", + "minecraft:falling_anvil", + "minecraft:falling_block" + ] + }, + { + "text": "<#ff0000>-${value}๐Ÿ”ฅ", + "type": "#minecraft:is_fire" + }, + { + "text": "<#ff0000>-${value}โ˜€", + "type": "#minecraft:is_explosion" + }, + { + "text": "<#ff0000>-${value}๐Ÿน", + "type": "#minecraft:is_projectile" + }, + { + "text": "<#ff0000>-${value}๐ŸŒŠ", + "type": "#minecraft:is_drowning" + }, + { + "text": "<#ff0000>-${value}โ„", + "type": "#minecraft:is_freezing" + }, + { + "text": "<#ff0000>-${value}โšก", + "type": "#minecraft:is_lightning" + }, + { + "text": "<#ff0000>-${value}", + "type": [] + } + ] + ], + "healing": [ + [ + { + "text": "<#00FF00>+${value}" + } + ] + ], + "death": [] +} \ No newline at end of file diff --git a/preset/minimal.json b/preset/minimal.json new file mode 100644 index 0000000..a8d3707 --- /dev/null +++ b/preset/minimal.json @@ -0,0 +1,18 @@ +{ + "damage": [ + [ + { + "text": "<#ff0000>-${value}", + "type": [] + } + ] + ], + "healing": [ + [ + { + "text": "<#00FF00>+${value}" + } + ] + ], + "death": [] +} \ No newline at end of file diff --git a/src/main/java/eu/pb4/ouch/DamageDisplayLogic.java b/src/main/java/eu/pb4/ouch/DamageDisplayLogic.java index e4c4c9f..6154e62 100644 --- a/src/main/java/eu/pb4/ouch/DamageDisplayLogic.java +++ b/src/main/java/eu/pb4/ouch/DamageDisplayLogic.java @@ -2,7 +2,6 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import eu.pb4.ouch.api.DefaultDisplayEvents; import eu.pb4.placeholders.api.ParserContext; import eu.pb4.placeholders.api.PlaceholderContext; import eu.pb4.placeholders.api.parsers.NodeParser; @@ -24,7 +23,7 @@ import net.minecraft.text.Text; import net.minecraft.util.math.MathHelper; -import java.util.List; +import java.util.Arrays; import java.util.Optional; import java.util.function.BiConsumer; import java.util.function.Function; @@ -76,39 +75,29 @@ public static DamageDisplayLogic of(float chance, MinecraftPredicate predicate, ); } - public static DamageDisplayLogic of(RegistryWrapper.WrapperLookup wrapper, RegistryKey type, String format) { - return new DamageDisplayLogic(Optional.of(RegistryEntryList.of(wrapper.getWrapperOrThrow(RegistryKeys.DAMAGE_TYPE).getOrThrow(type))), - BuiltinPredicates.alwaysTrue(), - BuiltinPredicates.alwaysTrue(), - BuiltinPredicates.alwaysTrue(), - 1, - WrappedText.from(PARSER, DefaultDisplayEvents.MODIFY_DISPLAY_LOGIC.invoker().modify(wrapper, List.of(type), format)), - FloatingText.DisplaySettings.GENERAL - ); - } - public static DamageDisplayLogic of(RegistryWrapper.WrapperLookup wrapper, List> type, String format) { - return new DamageDisplayLogic(Optional.of(RegistryEntryList.of(type.stream().map(wrapper.getWrapperOrThrow(RegistryKeys.DAMAGE_TYPE)::getOrThrow).toList())), - BuiltinPredicates.alwaysTrue(), - BuiltinPredicates.alwaysTrue(), - BuiltinPredicates.alwaysTrue(), - 1, - WrappedText.from(PARSER, DefaultDisplayEvents.MODIFY_DISPLAY_LOGIC.invoker().modify(wrapper, type, format)), + public static DamageDisplayLogic of(RegistryWrapper.WrapperLookup wrapper, String format, float chance, MinecraftPredicate victimPredicate, MinecraftPredicate sourcePredicate, MinecraftPredicate attackerPredicate, RegistryKey... type) { + var x = wrapper.getWrapperOrThrow(RegistryKeys.DAMAGE_TYPE); + return new DamageDisplayLogic(Optional.of(RegistryEntryList.of(Arrays.stream(type).map(x::getOrThrow).toList())), + victimPredicate, + attackerPredicate, + sourcePredicate, + chance, + WrappedText.from(PARSER, format), FloatingText.DisplaySettings.GENERAL ); } - - public static DamageDisplayLogic of(RegistryWrapper.WrapperLookup wrapper, TagKey tag, String format) { + public static DamageDisplayLogic of(RegistryWrapper.WrapperLookup wrapper, String format, float chance, MinecraftPredicate victimPredicate, MinecraftPredicate sourcePredicate, MinecraftPredicate attackerPredicate, TagKey tag) { return new DamageDisplayLogic(Optional.of(wrapper.getWrapperOrThrow(RegistryKeys.DAMAGE_TYPE).getOrThrow(tag)), - BuiltinPredicates.alwaysTrue(), - BuiltinPredicates.alwaysTrue(), - BuiltinPredicates.alwaysTrue(), - 1, + victimPredicate, + attackerPredicate, + sourcePredicate, + chance, WrappedText.from(PARSER, format), FloatingText.DisplaySettings.GENERAL ); } - public void provide(LivingEntity entity, DamageSource source, float amount, BiConsumer consumer) { + public void provideDamage(LivingEntity entity, DamageSource source, float amount, BiConsumer consumer) { consumer.accept(this.text.textNode().toText(PlaceholderContext.of(entity).asParserContext().with(PLACEHOLDER_KEY, key -> switch (key) { case "value" -> Text.literal(MathHelper.floor(amount) + "." + (MathHelper.floor(amount * 10) % 10)); case "value_rounded" -> Text.literal("" + Math.round(amount)); @@ -117,6 +106,15 @@ public void provide(LivingEntity entity, DamageSource source, float amount, BiCo })), this.displaySettings); } + public void provideDeath(LivingEntity entity, DamageSource source, BiConsumer consumer) { + consumer.accept(this.text.textNode().toText(PlaceholderContext.of(entity).asParserContext().with(PLACEHOLDER_KEY, key -> switch (key) { + case "message" -> source.getDeathMessage(entity); + case "victim" -> entity.getDisplayName(); + case "attacker" -> source.getAttacker() != null ? source.getAttacker().getDisplayName() : Text.empty(); + case null, default -> Text.empty(); + })), this.displaySettings); + } + public boolean match(LivingEntity entity, DamageSource source, PredicateContext predicateContext, PredicateContext attackerContext, PredicateContext sourceContext) { return (this.type.isEmpty() || this.type.get().contains(source.getTypeRegistryEntry())) && this.victimPredicate.test(predicateContext).success() diff --git a/src/main/java/eu/pb4/ouch/DeathDisplayLogic.java b/src/main/java/eu/pb4/ouch/DeathDisplayLogic.java deleted file mode 100644 index ead03bf..0000000 --- a/src/main/java/eu/pb4/ouch/DeathDisplayLogic.java +++ /dev/null @@ -1,110 +0,0 @@ -package eu.pb4.ouch; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import eu.pb4.placeholders.api.ParserContext; -import eu.pb4.placeholders.api.PlaceholderContext; -import eu.pb4.placeholders.api.parsers.NodeParser; -import eu.pb4.placeholders.api.parsers.WrappedText; -import eu.pb4.predicate.api.BuiltinPredicates; -import eu.pb4.predicate.api.MinecraftPredicate; -import eu.pb4.predicate.api.PredicateContext; -import eu.pb4.predicate.api.PredicateRegistry; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.damage.DamageSource; -import net.minecraft.entity.damage.DamageType; -import net.minecraft.registry.RegistryCodecs; -import net.minecraft.registry.RegistryKey; -import net.minecraft.registry.RegistryKeys; -import net.minecraft.registry.RegistryWrapper; -import net.minecraft.registry.entry.RegistryEntryList; -import net.minecraft.registry.tag.TagKey; -import net.minecraft.text.Text; - -import java.util.List; -import java.util.Optional; -import java.util.function.BiConsumer; -import java.util.function.Function; - -public record DeathDisplayLogic(Optional> type, - MinecraftPredicate victimPredicate, - MinecraftPredicate attackerPredicate, - MinecraftPredicate sourcePredicate, - float chance, - WrappedText text, - FloatingText.DisplaySettings displaySettings) { - static final ParserContext.Key> PLACEHOLDER_KEY = DamageDisplayLogic.PLACEHOLDER_KEY; - - static final NodeParser PARSER = DamageDisplayLogic.PARSER; - - - public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - RegistryCodecs.entryList(RegistryKeys.DAMAGE_TYPE).optionalFieldOf("type").forGetter(DeathDisplayLogic::type), - PredicateRegistry.CODEC.optionalFieldOf("victim", BuiltinPredicates.alwaysTrue()).forGetter(DeathDisplayLogic::victimPredicate), - PredicateRegistry.CODEC.optionalFieldOf("attacker", BuiltinPredicates.alwaysTrue()).forGetter(DeathDisplayLogic::attackerPredicate), - PredicateRegistry.CODEC.optionalFieldOf("source", BuiltinPredicates.alwaysTrue()).forGetter(DeathDisplayLogic::sourcePredicate), - Codec.floatRange(0, 1).optionalFieldOf("chance", 1f).forGetter(DeathDisplayLogic::chance), - PARSER.codec().fieldOf("text").forGetter(DeathDisplayLogic::text), - FloatingText.DisplaySettings.CODEC.orElse(FloatingText.DisplaySettings.GENERAL).forGetter(DeathDisplayLogic::displaySettings) - ).apply(instance, DeathDisplayLogic::new)); - - public static DeathDisplayLogic of(String format) { - return new DeathDisplayLogic(Optional.empty(), - BuiltinPredicates.alwaysTrue(), - BuiltinPredicates.alwaysTrue(), - BuiltinPredicates.alwaysTrue(), - 1, - WrappedText.from(PARSER, format), - FloatingText.DisplaySettings.DEATH - ); - } - - public static DeathDisplayLogic of(RegistryWrapper.WrapperLookup wrapper, RegistryKey type, String format) { - return new DeathDisplayLogic(Optional.of(RegistryEntryList.of(wrapper.getWrapperOrThrow(RegistryKeys.DAMAGE_TYPE).getOrThrow(type))), - BuiltinPredicates.alwaysTrue(), - BuiltinPredicates.alwaysTrue(), - BuiltinPredicates.alwaysTrue(), - 1, - WrappedText.from(PARSER, format), - FloatingText.DisplaySettings.DEATH - ); - } - public static DeathDisplayLogic of(RegistryWrapper.WrapperLookup wrapper, List> type, String format) { - return new DeathDisplayLogic(Optional.of(RegistryEntryList.of(type.stream().map(wrapper.getWrapperOrThrow(RegistryKeys.DAMAGE_TYPE)::getOrThrow).toList())), - BuiltinPredicates.alwaysTrue(), - BuiltinPredicates.alwaysTrue(), - BuiltinPredicates.alwaysTrue(), - 1, - WrappedText.from(PARSER, format), - FloatingText.DisplaySettings.DEATH - ); - } - - public static DeathDisplayLogic of(RegistryWrapper.WrapperLookup wrapper, TagKey tag, String format) { - return new DeathDisplayLogic(Optional.of(wrapper.getWrapperOrThrow(RegistryKeys.DAMAGE_TYPE).getOrThrow(tag)), - BuiltinPredicates.alwaysTrue(), - BuiltinPredicates.alwaysTrue(), - BuiltinPredicates.alwaysTrue(), - 1, - WrappedText.from(PARSER, format), - FloatingText.DisplaySettings.DEATH - ); - } - - public void provide(LivingEntity entity, DamageSource source, BiConsumer consumer) { - consumer.accept(this.text.textNode().toText(PlaceholderContext.of(entity).asParserContext().with(PLACEHOLDER_KEY, key -> switch (key) { - case "message" -> source.getDeathMessage(entity); - case "victim" -> entity.getDisplayName(); - case "attacker" -> source.getAttacker() != null ? source.getAttacker().getDisplayName() : Text.empty(); - case null, default -> Text.empty(); - })), this.displaySettings); - } - - public boolean match(LivingEntity entity, DamageSource source, PredicateContext predicateContext, PredicateContext attackerContext, PredicateContext sourceContext) { - return (this.type.isEmpty() || this.type.get().contains(source.getTypeRegistryEntry())) - && this.victimPredicate.test(predicateContext).success() - && this.attackerPredicate.test(attackerContext).success() - && this.sourcePredicate.test(sourceContext).success() - && entity.getRandom().nextFloat() <= this.chance; - } -} diff --git a/src/main/java/eu/pb4/ouch/DefaultDisplay.java b/src/main/java/eu/pb4/ouch/DefaultDisplay.java deleted file mode 100644 index 99cabd3..0000000 --- a/src/main/java/eu/pb4/ouch/DefaultDisplay.java +++ /dev/null @@ -1,77 +0,0 @@ -package eu.pb4.ouch; - -import eu.pb4.ouch.api.DefaultDisplayEvents; -import eu.pb4.predicate.api.BuiltinPredicates; -import net.minecraft.entity.damage.DamageType; -import net.minecraft.entity.damage.DamageTypes; -import net.minecraft.registry.DynamicRegistryManager; -import net.minecraft.registry.RegistryKey; -import net.minecraft.registry.tag.DamageTypeTags; -import net.minecraft.util.Pair; - -import java.util.ArrayList; -import java.util.List; - -public interface DefaultDisplay { - static void createDefault(List damage, List heal, List death, - ArrayList damageExtra, DynamicRegistryManager.Immutable lookup) { - damage.add(DamageDisplayLogic.of(lookup, DamageTypes.DRY_OUT, "<#ff0000>-${value}โ˜€")); - damage.add(DamageDisplayLogic.of(lookup, DamageTypes.TRIDENT, "<#ff0000>-${value}\uD83D\uDD31")); - damage.add(DamageDisplayLogic.of(lookup, DamageTypes.BAD_RESPAWN_POINT, "<#ff0000>-${value}โ˜ƒ")); - damage.add(DamageDisplayLogic.of(lookup, DamageTypes.STARVE, "<#ff0000>-${value}\uD83C\uDF56")); - damage.add(DamageDisplayLogic.of(lookup, DamageTypes.TRIDENT, "<#ff0000>-${value}\uD83D\uDD31")); - damage.add(DamageDisplayLogic.of(lookup, DamageTypes.CRAMMING, "<#ff0000>-${value}โ™ฆ")); - damage.add(DamageDisplayLogic.of(lookup, DamageTypes.FALL, "<#ff0000>-${value}โ˜„")); - damage.add(DamageDisplayLogic.of(lookup, DamageTypes.FLY_INTO_WALL, "<#ff0000>-${value}โ˜„")); - damage.add(DamageDisplayLogic.of(lookup, DamageTypes.IN_WALL, "<#ff0000>-${value}โ–’")); - damage.add(DamageDisplayLogic.of(lookup, DamageTypes.SONIC_BOOM, "<#ff0000>-${value}โ˜€")); - damage.add(DamageDisplayLogic.of(lookup, DamageTypes.SPIT, "<#ff0000>-${value}โ˜„")); - damage.add(DamageDisplayLogic.of(lookup, DamageTypes.STING, "<#ff0000>-${value}โ–ฝ")); - damage.add(DamageDisplayLogic.of(lookup, DamageTypes.THORNS, "<#ff0000>-${value}โ–ณ")); - - damage.add(DamageDisplayLogic.of(lookup, List.of(DamageTypes.MOB_ATTACK, DamageTypes.PLAYER_ATTACK, DamageTypes.MOB_ATTACK_NO_AGGRO), "<#ff0000>-${value}\uD83D\uDDE1")); - damage.add(DamageDisplayLogic.of(lookup, List.of(DamageTypes.OUT_OF_WORLD, DamageTypes.OUTSIDE_BORDER), "<#ff0000>-${value}โš ")); - damage.add(DamageDisplayLogic.of(lookup, List.of(DamageTypes.MAGIC, DamageTypes.INDIRECT_MAGIC, DamageTypes.DRAGON_BREATH), "<#ff0000>-${value}\uD83E\uDDEA")); - damage.add(DamageDisplayLogic.of(lookup, List.of(DamageTypes.WITHER, DamageTypes.WITHER_SKULL), "<#ff0000>-${value}\uD83E\uDDEA")); - damage.add(DamageDisplayLogic.of(lookup, List.of(DamageTypes.CACTUS, DamageTypes.SWEET_BERRY_BUSH), "<#ff0000>-${value}โ™ฆ")); - damage.add(DamageDisplayLogic.of(lookup, List.of(DamageTypes.FALLING_STALACTITE, DamageTypes.FALLING_ANVIL, DamageTypes.FALLING_BLOCK), - "<#ff0000>-${value}โ˜„")); - - damage.add(DamageDisplayLogic.of(lookup, DamageTypeTags.IS_FIRE, "<#ff0000>-${value}\uD83D\uDD25")); - damage.add(DamageDisplayLogic.of(lookup, DamageTypeTags.IS_EXPLOSION, "<#ff0000>-${value}โ˜€")); - damage.add(DamageDisplayLogic.of(lookup, DamageTypeTags.IS_PROJECTILE, "<#ff0000>-${value}\uD83C\uDFF9")); - damage.add(DamageDisplayLogic.of(lookup, DamageTypeTags.IS_DROWNING, "<#ff0000>-${value}\uD83C\uDF0A")); - damage.add(DamageDisplayLogic.of(lookup, DamageTypeTags.IS_FREEZING, "<#ff0000>-${value}โ„")); - damage.add(DamageDisplayLogic.of(lookup, DamageTypeTags.IS_LIGHTNING, "<#ff0000>-${value}โšก")); - damage.add(DamageDisplayLogic.of("<#ff0000>-${value}")); - - heal.add(HealDisplayLogic.of("<#00FF00>+${value}")); - - LogicsImpl logics = new LogicsImpl(); - DefaultDisplayEvents.APPEND_DISPLAY_LOGIC.invoker().append(lookup, logics); - logics.getLogics().forEach(pair -> damage.add(DamageDisplayLogic.of(lookup, pair.getLeft(), pair.getRight()))); - } - - static void createShowcase(List damage, List heal, List death, - ArrayList damageExtra, DynamicRegistryManager.Immutable lookup) { - createDefault(damage, heal, death, damageExtra, lookup); - - death.add(DeathDisplayLogic.of("${message}")); - damageExtra.add(DamageDisplayLogic.of(0.03f, BuiltinPredicates.alwaysTrue(), "Ouch!")); - } - - class LogicsImpl implements DefaultDisplayEvents.AppendDisplayLogic.Logics { - - final List>, String>> logics = new ArrayList<>(); - - @Override - @SafeVarargs - public final void add(String format, RegistryKey... types) { - this.logics.add(new Pair<>(List.of(types), format)); - } - - List>, String>> getLogics() { - return this.logics; - } - } -} diff --git a/src/main/java/eu/pb4/ouch/FloatingText.java b/src/main/java/eu/pb4/ouch/FloatingText.java index fe5eacc..4bca039 100644 --- a/src/main/java/eu/pb4/ouch/FloatingText.java +++ b/src/main/java/eu/pb4/ouch/FloatingText.java @@ -79,15 +79,15 @@ public boolean startWatching(ServerPlayNetworkHandler player) { } public static void createDamage(LivingEntity entity, DamageSource source, float amount) { - Config.get().selectDamage(entity, source, amount, (text, displaySettings) -> createText(entity, source.getPosition(), text, displaySettings)); + Preset.get().selectDamage(entity, source, amount, (text, displaySettings) -> createText(entity, source.getPosition(), text, displaySettings)); } public static void createDeath(LivingEntity entity, DamageSource source) { - Config.get().selectDeath(entity, source, (text, displaySettings) -> createText(entity, source.getPosition(), text, displaySettings)); + Preset.get().selectDeath(entity, source, (text, displaySettings) -> createText(entity, source.getPosition(), text, displaySettings)); } public static void createHealing(LivingEntity entity, float amount) { - Config.get().selectHealing(entity, amount, (text, displaySettings) -> createText(entity, null, text, displaySettings)); + Preset.get().selectHealing(entity, amount, (text, displaySettings) -> createText(entity, null, text, displaySettings)); } private static void createText(LivingEntity entity, @Nullable Vec3d source, Text text, DisplaySettings displaySettings) { diff --git a/src/main/java/eu/pb4/ouch/HealDisplayLogic.java b/src/main/java/eu/pb4/ouch/HealDisplayLogic.java index 5faaa14..2a275da 100644 --- a/src/main/java/eu/pb4/ouch/HealDisplayLogic.java +++ b/src/main/java/eu/pb4/ouch/HealDisplayLogic.java @@ -1,6 +1,5 @@ package eu.pb4.ouch; -import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import eu.pb4.placeholders.api.ParserContext; @@ -12,14 +11,9 @@ import eu.pb4.predicate.api.PredicateContext; import eu.pb4.predicate.api.PredicateRegistry; import net.minecraft.entity.LivingEntity; -import net.minecraft.registry.RegistryCodecs; -import net.minecraft.registry.RegistryKeys; import net.minecraft.text.Text; import net.minecraft.util.math.MathHelper; -import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; import java.util.function.BiConsumer; import java.util.function.Function; @@ -37,8 +31,8 @@ public record HealDisplayLogic(MinecraftPredicate entityPredicate, FloatingText.DisplaySettings.CODEC.orElse(FloatingText.DisplaySettings.GENERAL).forGetter(HealDisplayLogic::displaySettings) ).apply(instance, HealDisplayLogic::new)); - public static HealDisplayLogic of(String format) { - return new HealDisplayLogic(BuiltinPredicates.alwaysTrue(), 1, WrappedText.from(PARSER, format), FloatingText.DisplaySettings.GENERAL); + public static HealDisplayLogic of(String format, float chance, MinecraftPredicate predicate) { + return new HealDisplayLogic(predicate, chance, WrappedText.from(PARSER, format), FloatingText.DisplaySettings.GENERAL); } public void provide(LivingEntity entity, float amount, BiConsumer consumer) { diff --git a/src/main/java/eu/pb4/ouch/ModInit.java b/src/main/java/eu/pb4/ouch/ModInit.java index c80075f..91eb0da 100644 --- a/src/main/java/eu/pb4/ouch/ModInit.java +++ b/src/main/java/eu/pb4/ouch/ModInit.java @@ -3,22 +3,23 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonParser; +import com.mojang.datafixers.util.Either; import com.mojang.serialization.JsonOps; -import eu.pb4.predicate.api.PredicateRegistry; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.registry.DynamicRegistryManager; import net.minecraft.util.Identifier; -import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.StandardOpenOption; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; public class ModInit implements ModInitializer { public static final String ID = "ouch"; @@ -26,13 +27,15 @@ public class ModInit implements ModInitializer { public static final Logger LOGGER = LoggerFactory.getLogger("Ouch!"); public static final boolean DEV_ENV = FabricLoader.getInstance().isDevelopmentEnvironment(); public static final boolean DEV_MODE = VERSION.contains("-dev.") || DEV_ENV; - @Nullable - public static Config config; + public static Preset config = Preset.EMPTY; + private static Either configValue = null; public static Identifier id(String path) { return Identifier.of(ID, path); } + public static Map PRESETS = new HashMap<>(); + @Override public void onInitialize() { if (VERSION.contains("-dev.")) { @@ -44,31 +47,43 @@ public void onInitialize() { } ServerLifecycleEvents.SERVER_STARTED.register(server -> this.setup(server.getRegistryManager())); - ServerLifecycleEvents.SERVER_STOPPED.register(server -> config = null); + ServerLifecycleEvents.SERVER_STOPPED.register(server -> { + config = Preset.EMPTY; + configValue = null; + PRESETS.clear(); + }); ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, success) -> this.setup(server.getRegistryManager())); } @SuppressWarnings("ConstantValue") private void setup(DynamicRegistryManager.Immutable registryManager) { + PRESETS.clear(); + Presets.setupPresets(PRESETS::put, registryManager); + var gson = new GsonBuilder().disableHtmlEscaping().setLenient().setPrettyPrinting().create(); + + if (DEV_MODE) { + var path = FabricLoader.getInstance().getGameDir().resolve("../preset"); + try { + Files.createDirectories(path); + for (var preset : PRESETS.entrySet()) { + Files.writeString(path.resolve(preset.getKey() + ".json"), gson.toJson(Preset.SELF_CODEC.encodeStart( + registryManager.getOps(JsonOps.INSTANCE), preset.getValue() + ).getOrThrow()), StandardCharsets.UTF_8, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + //noinspection PointlessBooleanExpression - var dev = DEV_ENV && false; config = null; var configPath = FabricLoader.getInstance().getConfigDir().resolve("ouch.json"); - if (!Files.exists(configPath) || dev) { - var damage = new ArrayList(); - var damageExtra = new ArrayList(); - var death = new ArrayList(); - var healing = new ArrayList(); - - DefaultDisplay.createDefault(damage, healing, death, damageExtra, registryManager); - config = new Config(List.of(damage, damageExtra), List.of(healing), List.of(death)); - if (dev) { - return; - } + if (!Files.exists(configPath)) { + configValue = Either.left(Presets.DEFAULT); } else { try { - config = Config.CODEC.decode( + configValue = Preset.CODEC.decode( registryManager.getOps(JsonOps.INSTANCE), JsonParser.parseString(Files.readString(configPath, StandardCharsets.UTF_8)) ).getOrThrow().getFirst(); } catch (Throwable e) { @@ -77,11 +92,11 @@ private void setup(DynamicRegistryManager.Immutable registryManager) { } } - try { - var gson = new GsonBuilder().disableHtmlEscaping().setLenient().setPrettyPrinting().create(); + config = configValue.map(x -> PRESETS.getOrDefault(x, Preset.EMPTY), Function.identity()); - Files.writeString(configPath, gson.toJson(Config.CODEC.encodeStart( - registryManager.getOps(JsonOps.INSTANCE), config + try { + Files.writeString(configPath, gson.toJson(Preset.CODEC.encodeStart( + registryManager.getOps(JsonOps.INSTANCE), configValue ).getOrThrow()), StandardCharsets.UTF_8, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); } catch (Throwable e) { LOGGER.error("Failed to write config file (ouch.json)", e); diff --git a/src/main/java/eu/pb4/ouch/Config.java b/src/main/java/eu/pb4/ouch/Preset.java similarity index 74% rename from src/main/java/eu/pb4/ouch/Config.java rename to src/main/java/eu/pb4/ouch/Preset.java index a115986..e0a41c9 100644 --- a/src/main/java/eu/pb4/ouch/Config.java +++ b/src/main/java/eu/pb4/ouch/Preset.java @@ -1,28 +1,30 @@ package eu.pb4.ouch; +import com.mojang.datafixers.util.Either; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import eu.pb4.predicate.api.PredicateContext; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.damage.DamageSource; import net.minecraft.text.Text; -import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Objects; import java.util.function.BiConsumer; -public record Config(List> damage, List> healing, List> death) { - public static final Config EMPTY = new Config(List.of(), List.of(), List.of()); - public static Config get() { - return ModInit.config != null ? ModInit.config : EMPTY; +public record Preset(List> damage, List> healing, List> death) { + public static final Preset EMPTY = new Preset(List.of(), List.of(), List.of()); + public static Preset get() { + return ModInit.config; } - public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - DamageDisplayLogic.CODEC.listOf().listOf().fieldOf("damage").forGetter(Config::damage), - HealDisplayLogic.CODEC.listOf().listOf().fieldOf("healing").forGetter(Config::healing), - DeathDisplayLogic.CODEC.listOf().listOf().fieldOf("death").forGetter(Config::death) - ).apply(instance, Config::new)); + public static final Codec SELF_CODEC = RecordCodecBuilder.create(instance -> instance.group( + DamageDisplayLogic.CODEC.listOf().listOf().fieldOf("damage").forGetter(Preset::damage), + HealDisplayLogic.CODEC.listOf().listOf().fieldOf("healing").forGetter(Preset::healing), + DamageDisplayLogic.CODEC.listOf().listOf().fieldOf("death").forGetter(Preset::death) + ).apply(instance, Preset::new)); + + public static final Codec> CODEC = Codec.either(Codec.STRING.fieldOf("preset").codec(), SELF_CODEC); public void selectDamage(LivingEntity entity, DamageSource source, float amount, BiConsumer consumer) { var predicateContext = PredicateContext.of(entity); @@ -31,7 +33,7 @@ public void selectDamage(LivingEntity entity, DamageSource source, float amount, for (var a : this.damage) { for (var e : a) { if (e.match(entity, source, predicateContext, attackerContext, sourceContext)) { - e.provide(entity, source, amount, consumer); + e.provideDamage(entity, source, amount, consumer); break; } } @@ -45,7 +47,7 @@ public void selectDeath(LivingEntity entity, DamageSource source, BiConsumer consumer, RegistryWrapper.WrapperLookup lookup) { + consumer.accept(DEFAULT, createDefault(new BuilderImpl(lookup)).build()); + consumer.accept(MINIMAL, createMinimal(new BuilderImpl(lookup)).build()); + } + + static BuilderImpl createDefault(BuilderImpl builder) { + builder.addDamage("<#ff0000>-${value}โ˜€", DamageTypes.DRY_OUT); + builder.addDamage("<#ff0000>-${value}\uD83D\uDD31", DamageTypes.TRIDENT); + builder.addDamage("<#ff0000>-${value}โ˜ƒ", DamageTypes.BAD_RESPAWN_POINT); + builder.addDamage("<#ff0000>-${value}\uD83C\uDF56", DamageTypes.STARVE); + builder.addDamage("<#ff0000>-${value}\uD83D\uDD31", DamageTypes.TRIDENT); + builder.addDamage("<#ff0000>-${value}โ™ฆ", DamageTypes.CRAMMING); + builder.addDamage("<#ff0000>-${value}โ˜„", DamageTypes.FALL); + builder.addDamage("<#ff0000>-${value}โ˜„", DamageTypes.FLY_INTO_WALL); + builder.addDamage("<#ff0000>-${value}โ–’", DamageTypes.IN_WALL); + builder.addDamage("<#ff0000>-${value}โ˜€", DamageTypes.SONIC_BOOM); + builder.addDamage("<#ff0000>-${value}โ˜„", DamageTypes.SPIT); + builder.addDamage("<#ff0000>-${value}โ–ฝ", DamageTypes.STING); + builder.addDamage("<#ff0000>-${value}โ–ณ", DamageTypes.THORNS); + + builder.addDamage("<#ff0000>-${value}\uD83D\uDDE1", DamageTypes.MOB_ATTACK, DamageTypes.PLAYER_ATTACK, DamageTypes.MOB_ATTACK_NO_AGGRO); + builder.addDamage("<#ff0000>-${value}โš ", DamageTypes.OUT_OF_WORLD, DamageTypes.OUTSIDE_BORDER); + builder.addDamage("<#ff0000>-${value}\uD83E\uDDEA", DamageTypes.MAGIC, DamageTypes.INDIRECT_MAGIC, DamageTypes.DRAGON_BREATH); + builder.addDamage("<#ff0000>-${value}\uD83E\uDDEA", DamageTypes.WITHER, DamageTypes.WITHER_SKULL); + builder.addDamage("<#ff0000>-${value}โ™ฆ", DamageTypes.CACTUS, DamageTypes.SWEET_BERRY_BUSH); + builder.addDamage("<#ff0000>-${value}โ˜„", DamageTypes.FALLING_STALACTITE, DamageTypes.FALLING_ANVIL, DamageTypes.FALLING_BLOCK); + + builder.addDamage("<#ff0000>-${value}\uD83D\uDD25", DamageTypeTags.IS_FIRE); + builder.addDamage("<#ff0000>-${value}โ˜€", DamageTypeTags.IS_EXPLOSION); + builder.addDamage("<#ff0000>-${value}\uD83C\uDFF9", DamageTypeTags.IS_PROJECTILE); + builder.addDamage("<#ff0000>-${value}\uD83C\uDF0A", DamageTypeTags.IS_DROWNING); + builder.addDamage("<#ff0000>-${value}โ„", DamageTypeTags.IS_FREEZING); + builder.addDamage("<#ff0000>-${value}โšก", DamageTypeTags.IS_LIGHTNING); + builder.addDamage(0, 1000, "<#ff0000>-${value}", 1, BuiltinPredicates.alwaysTrue(), BuiltinPredicates.alwaysTrue(), BuiltinPredicates.alwaysTrue()); + builder.addHealing(0, 1000, "<#00FF00>+${value}", 1, BuiltinPredicates.alwaysTrue()); + + DefaultDisplayEvents.APPEND_DISPLAY_LOGIC.invoker().append(builder, DEFAULT); + return builder; + } + + static BuilderImpl createMinimal(BuilderImpl builder) { + builder.addDamage(0, 1000, "<#ff0000>-${value}", 1, BuiltinPredicates.alwaysTrue(), BuiltinPredicates.alwaysTrue(), BuiltinPredicates.alwaysTrue()); + builder.addHealing(0, 1000, "<#00FF00>+${value}", 1, BuiltinPredicates.alwaysTrue()); + //DefaultDisplayEvents.APPEND_DISPLAY_LOGIC.invoker().append(builder, MINIMAL); + return builder; + } + + class BuilderImpl implements DefaultDisplayEvents.AppendDisplayLogic.Builder { + RegistryWrapper.WrapperLookup lookup; + Int2ObjectMap>> damageDisplays = new Int2ObjectOpenHashMap<>(); + Int2ObjectMap>> healingDisplays = new Int2ObjectOpenHashMap<>(); + Int2ObjectMap>> deathDisplays = new Int2ObjectOpenHashMap<>(); + + public BuilderImpl(RegistryWrapper.WrapperLookup lookup) { + this.lookup = lookup; + } + + public Preset build() { + var death = new ArrayList>(); + var damage = new ArrayList>(); + var healing = new ArrayList>(); + + sortAndAdd(damage, this.damageDisplays, DamageDisplayLogic::chance, DamageDisplayLogic::type); + sortAndAdd(death, this.deathDisplays, DamageDisplayLogic::chance, DamageDisplayLogic::type); + sortAndAdd(healing, this.healingDisplays, HealDisplayLogic::chance, x -> Optional.empty()); + + return new Preset(damage, healing, death); + } + + private static void sortAndAdd(List> out, Int2ObjectMap>> entries, Function chance, + Function>> damageTypes) { + var entriesList = new ArrayList<>(entries.int2ObjectEntrySet()); + var comparator = Comparator.>comparingInt(Pair::getFirst) + .thenComparingInt(x -> damageTypes.apply(x.getSecond()).map(registryEntries -> registryEntries.getTagKey().isPresent() ? 3 : 1).orElse(5)) + .thenComparingDouble(x -> chance.apply(x.getSecond())); + + entriesList.sort(Comparator.comparing(Int2ObjectMap.Entry::getIntKey)); + for (var x : entriesList) { + x.getValue().sort(comparator); + out.add(x.getValue().stream().map(Pair::getSecond).toList()); + } + } + + @Override + public void addDamage(int layer, int priority, String format, float chance, MinecraftPredicate victimPredicate, MinecraftPredicate sourcePredicate, MinecraftPredicate attackerPredicate, RegistryKey... types) { + this.damageDisplays.computeIfAbsent(layer, x -> new ArrayList<>()) + .add(new Pair<>(priority, DamageDisplayLogic.of(lookup, format, chance, victimPredicate, sourcePredicate, attackerPredicate, types))); + } + + @Override + public void addDamage(int layer, int priority, String format, float chance, MinecraftPredicate victimPredicate, MinecraftPredicate sourcePredicate, MinecraftPredicate attackerPredicate, TagKey tag) { + this.damageDisplays.computeIfAbsent(layer, x -> new ArrayList<>()) + .add(new Pair<>(priority, DamageDisplayLogic.of(lookup, format, chance, victimPredicate, sourcePredicate, attackerPredicate, tag))); + } + + @Override + public void addDeath(int layer, int priority, String format, float chance, MinecraftPredicate victimPredicate, MinecraftPredicate sourcePredicate, MinecraftPredicate attackerPredicate, RegistryKey... types) { + this.deathDisplays.computeIfAbsent(layer, x -> new ArrayList<>()) + .add(new Pair<>(priority, DamageDisplayLogic.of(lookup, format, chance, victimPredicate, sourcePredicate, attackerPredicate, types))); + } + + @Override + public void addDeath(int layer, int priority, String format, float chance, MinecraftPredicate victimPredicate, MinecraftPredicate sourcePredicate, MinecraftPredicate attackerPredicate, TagKey tag) { + this.deathDisplays.computeIfAbsent(layer, x -> new ArrayList<>()) + .add(new Pair<>(priority, DamageDisplayLogic.of(lookup, format, chance, victimPredicate, sourcePredicate, attackerPredicate, tag))); + } + + @Override + public void addHealing(int layer, int priority, String format, float chance, MinecraftPredicate entityPredicate) { + this.healingDisplays.computeIfAbsent(layer, x -> new ArrayList<>()) + .add(new Pair<>(priority, HealDisplayLogic.of(format, chance, entityPredicate))); + } + } +} diff --git a/src/main/java/eu/pb4/ouch/api/DefaultDisplayEvents.java b/src/main/java/eu/pb4/ouch/api/DefaultDisplayEvents.java index 5c122f5..04b671d 100644 --- a/src/main/java/eu/pb4/ouch/api/DefaultDisplayEvents.java +++ b/src/main/java/eu/pb4/ouch/api/DefaultDisplayEvents.java @@ -1,14 +1,14 @@ package eu.pb4.ouch.api; +import eu.pb4.predicate.api.BuiltinPredicates; +import eu.pb4.predicate.api.MinecraftPredicate; import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.EventFactory; import net.minecraft.entity.damage.DamageType; import net.minecraft.registry.RegistryKey; -import net.minecraft.registry.RegistryWrapper; +import net.minecraft.registry.tag.TagKey; import org.jetbrains.annotations.ApiStatus; -import java.util.List; - public final class DefaultDisplayEvents { /** @@ -25,51 +25,93 @@ public final class DefaultDisplayEvents { * } * */ - public static final Event APPEND_DISPLAY_LOGIC = EventFactory.createArrayBacked(AppendDisplayLogic.class, callbacks -> (lookup, _logics) -> { - AppendDisplayLogic.Logics logics = _logics; + public static final Event APPEND_DISPLAY_LOGIC = EventFactory.createArrayBacked(AppendDisplayLogic.class, callbacks -> (builder, preset) -> { for (AppendDisplayLogic callback : callbacks) { - logics = callback.append(lookup, logics); + callback.append(builder, preset); } - return logics; - }); - - /** - * This event allows to modify a format applied on one or more {@link DamageType} for the default configuration. - * Example: - *
-	 * {@code
-	 *  DefaultDisplayEvents.MODIFY_DISPLAY_LOGIC.register((lookup, types, format) -> {
-	 *      if (types.contains(DamageTypes.OUT_OF_WORLD)) {
-	 *          return yourModifiedFormat;
-	 *      }
-	 *      return format;
-	 *  });
-	 * }
-	 * 
- */ - public static final Event MODIFY_DISPLAY_LOGIC = EventFactory.createArrayBacked(ModifyDisplayLogic.class, callbacks -> (lookup, types, _format) -> { - String format = _format; - for (ModifyDisplayLogic callback : callbacks) { - format = callback.modify(lookup, types, format); - } - return format; }); @FunctionalInterface public interface AppendDisplayLogic { - Logics append(RegistryWrapper.WrapperLookup lookup, Logics logics); + void append(Builder builder, String preset); @ApiStatus.NonExtendable - interface Logics { + @SuppressWarnings("unchecked") + interface Builder { + default void addDamage(String format, RegistryKey... types) { + addDamage(format, 1, types); + }; + default void addDamage(int layer, String format, RegistryKey... types) { + addDamage(layer, format, 1, types); + } + default void addDamage(String format, TagKey tag) { + addDamage(format, 1, tag); + };; + default void addDamage(int layer, String format, TagKey tag) { + addDamage(layer, format, 1, tag); + } - void add(String format, RegistryKey... types); - } - } + default void addDamage(String format, float chance, RegistryKey... types) { + addDamage(0, format, chance, types); + } + default void addDamage(String format, float chance, TagKey tag) { + addDamage(0, format, chance, tag); + } + default void addDamage(int layer, String format, float chance, RegistryKey... types) { + addDamage(0, format, chance, BuiltinPredicates.alwaysTrue(), types); + }; + default void addDamage(int layer, String format, float chance, TagKey tag) { + addDamage(0, format, chance, BuiltinPredicates.alwaysTrue(), tag); + } - @FunctionalInterface - public interface ModifyDisplayLogic { + default void addDamage(int layer, String format, float chance, MinecraftPredicate victimPredicate, RegistryKey... types) { + addDamage(layer, 100, format, chance, victimPredicate, BuiltinPredicates.alwaysTrue(), BuiltinPredicates.alwaysTrue(), types); + }; + default void addDamage(int layer, String format, float chance, MinecraftPredicate victimPredicate, TagKey tag) { + addDamage(layer, 200, format, chance, victimPredicate, BuiltinPredicates.alwaysTrue(), BuiltinPredicates.alwaysTrue(), tag); + }; + + void addDamage(int layer, int priority, String format, float chance, MinecraftPredicate victimPredicate, MinecraftPredicate sourcePredicate, MinecraftPredicate attackerPredicate, RegistryKey... types); + void addDamage(int layer, int priority, String format, float chance, MinecraftPredicate victimPredicate, MinecraftPredicate sourcePredicate, MinecraftPredicate attackerPredicate, TagKey tag); - String modify(RegistryWrapper.WrapperLookup lookup, List> types, String format); + default void addDeath(String format, RegistryKey... types) { + addDeath(format, 1, types); + }; + default void addDeath(int layer, String format, RegistryKey... types) { + addDeath(layer, format, 1, types); + } + default void addDeath(String format, TagKey tag) { + addDeath(format, 1, tag); + };; + default void addDeath(int layer, String format, TagKey tag) { + addDeath(layer, format, 1, tag); + } + + default void addDeath(String format, float chance, RegistryKey... types) { + addDeath(0, format, chance, types); + } + default void addDeath(String format, float chance, TagKey tag) { + addDeath(0, format, chance, tag); + } + default void addDeath(int layer, String format, float chance, RegistryKey... types) { + addDeath(0, format, chance, BuiltinPredicates.alwaysTrue(), types); + }; + default void addDeath(int layer, String format, float chance, TagKey tag) { + addDeath(0, format, chance, BuiltinPredicates.alwaysTrue(), tag); + } + + default void addDeath(int layer, String format, float chance, MinecraftPredicate victimPredicate, RegistryKey... types) { + addDeath(layer, 100, format, chance, victimPredicate, BuiltinPredicates.alwaysTrue(), BuiltinPredicates.alwaysTrue(), types); + }; + default void addDeath(int layer, String format, float chance, MinecraftPredicate victimPredicate, TagKey tag) { + addDeath(layer, 200, format, chance, victimPredicate, BuiltinPredicates.alwaysTrue(), BuiltinPredicates.alwaysTrue(), tag); + }; + + void addDeath(int layer, int priority, String format, float chance, MinecraftPredicate victimPredicate, MinecraftPredicate sourcePredicate, MinecraftPredicate attackerPredicate, RegistryKey... types); + void addDeath(int layer, int priority, String format, float chance, MinecraftPredicate victimPredicate, MinecraftPredicate sourcePredicate, MinecraftPredicate attackerPredicate, TagKey tag); + + void addHealing(int layer, int priority, String format, float chance, MinecraftPredicate entityPredicate); + } } }