From eb23ae48a2942a3e0380c7639145ad94b32d334a Mon Sep 17 00:00:00 2001 From: B1n_ry Date: Thu, 22 Feb 2024 14:32:47 +0100 Subject: [PATCH] Added compatibility with orpheus' orpheus lyre Improved api-stuff to allow modification of drop rules after drop rules has been handled, based on the entire inventory component --- build.gradle | 3 ++ gradle.properties | 3 ++ .../java/com/b1n_ry/yigd/DeathHandler.java | 3 ++ .../b1n_ry/yigd/compat/CompatComponent.java | 21 ++++++++- .../com/b1n_ry/yigd/compat/InvModCompat.java | 4 ++ .../CommonProtectionApiCompat.java | 2 +- .../compat/miscCompatMods/OrpheusCompat.java | 20 +++++++++ .../yigd/components/GraveComponent.java | 4 +- .../yigd/components/InventoryComponent.java | 44 +++++++++++++++++++ .../yigd/components/RespawnComponent.java | 9 ++++ .../yigd/events/AdjustDropRuleEvent.java | 16 +++++++ .../yigd/events/ServerEventHandler.java | 2 +- 12 files changed, 126 insertions(+), 5 deletions(-) rename src/main/java/com/b1n_ry/yigd/compat/{ => miscCompatMods}/CommonProtectionApiCompat.java (96%) create mode 100644 src/main/java/com/b1n_ry/yigd/compat/miscCompatMods/OrpheusCompat.java create mode 100644 src/main/java/com/b1n_ry/yigd/events/AdjustDropRuleEvent.java diff --git a/build.gradle b/build.gradle index 6a87c478..cd2a1039 100644 --- a/build.gradle +++ b/build.gradle @@ -95,6 +95,9 @@ dependencies { modImplementation "com.terraformersmc:modmenu:${project.modmenu_version}" modCompileOnly "eu.pb4:common-protection-api:${project.protection_api_version}" + // Extra soulbound/droprule modification mods + modCompileOnly "curse.maven:orpheus-${project.orpheus_version}" + // Inventory Mods modCompileOnly "dev.emi:trinkets:${project.trinkets_version}" modCompileOnly "curse.maven:inventorio-${project.inventorio_version}" diff --git a/gradle.properties b/gradle.properties index 0fd93788..507c75c7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,6 +24,9 @@ org.gradle.parallel=true modmenu_version=7.2.2 protection_api_version=1.0.0 +# Extra soulbound/drop rule modification mods + orpheus_version=936659:5093826 + # Inventory compat trinkets_version=3.7.1 inventorio_version=491073:4619078 diff --git a/src/main/java/com/b1n_ry/yigd/DeathHandler.java b/src/main/java/com/b1n_ry/yigd/DeathHandler.java index cb1bf16f..c4918ecf 100644 --- a/src/main/java/com/b1n_ry/yigd/DeathHandler.java +++ b/src/main/java/com/b1n_ry/yigd/DeathHandler.java @@ -7,6 +7,7 @@ import com.b1n_ry.yigd.components.RespawnComponent; import com.b1n_ry.yigd.config.YigdConfig; import com.b1n_ry.yigd.data.DeathContext; +import com.b1n_ry.yigd.data.DeathInfoManager; import com.b1n_ry.yigd.data.DirectionalPos; import com.b1n_ry.yigd.data.TranslatableDeathMessage; import com.b1n_ry.yigd.events.AllowGraveGenerationEvent; @@ -89,6 +90,8 @@ public void onPlayerDeath(ServerPlayerEntity player, ServerWorld world, Vec3d po .with(Properties.HORIZONTAL_FACING, direction) .with(Properties.WATERLOGGED, waterlogged); + respawnComponent.setGraveGenerated(true); // Not guaranteed yet, but only errors can stop it from generating after this point + DeathInfoManager.INSTANCE.markDirty(); // Make sure respawn component is updated // At this point is where the END_OF_TICK would be implemented, unless it wasn't already so Yigd.END_OF_TICK.add(() -> { diff --git a/src/main/java/com/b1n_ry/yigd/compat/CompatComponent.java b/src/main/java/com/b1n_ry/yigd/compat/CompatComponent.java index e57da744..55844255 100644 --- a/src/main/java/com/b1n_ry/yigd/compat/CompatComponent.java +++ b/src/main/java/com/b1n_ry/yigd/compat/CompatComponent.java @@ -90,6 +90,25 @@ public boolean containsGraveItems() { if (!pair.getLeft().isEmpty() && pair.getRight() == DropRule.PUT_IN_GRAVE) return true; } return false; - }; + } + + /** + * Check if the component contains at least one item that matches the predicate. Will stop at first match + * @param predicate Predicate to test items against + * @return Whether the component contains at least one item that matches the predicate + */ + public boolean containsAny(Predicate predicate) { + for (Pair pair : this.getAsStackDropList()) { + if (predicate.test(pair.getLeft())) return true; + } + return false; + } + public void setDropRules(Predicate predicate, DropRule dropRule) { + for (Pair pair : this.getAsStackDropList()) { + if (predicate.test(pair.getLeft())) { + pair.setRight(dropRule); + } + } + } public abstract NbtCompound writeNbt(); } diff --git a/src/main/java/com/b1n_ry/yigd/compat/InvModCompat.java b/src/main/java/com/b1n_ry/yigd/compat/InvModCompat.java index 770a56fc..702656c2 100644 --- a/src/main/java/com/b1n_ry/yigd/compat/InvModCompat.java +++ b/src/main/java/com/b1n_ry/yigd/compat/InvModCompat.java @@ -1,5 +1,7 @@ package com.b1n_ry.yigd.compat; +import com.b1n_ry.yigd.compat.miscCompatMods.CommonProtectionApiCompat; +import com.b1n_ry.yigd.compat.miscCompatMods.OrpheusCompat; import com.b1n_ry.yigd.config.YigdConfig; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.nbt.NbtCompound; @@ -29,6 +31,8 @@ static void initModCompat() { if (loader.isModLoaded("common-protection-api")) CommonProtectionApiCompat.init(); + if (loader.isModLoaded("orpheus")) + OrpheusCompat.init(); } String getModName(); diff --git a/src/main/java/com/b1n_ry/yigd/compat/CommonProtectionApiCompat.java b/src/main/java/com/b1n_ry/yigd/compat/miscCompatMods/CommonProtectionApiCompat.java similarity index 96% rename from src/main/java/com/b1n_ry/yigd/compat/CommonProtectionApiCompat.java rename to src/main/java/com/b1n_ry/yigd/compat/miscCompatMods/CommonProtectionApiCompat.java index 0ec42e97..4c097c87 100644 --- a/src/main/java/com/b1n_ry/yigd/compat/CommonProtectionApiCompat.java +++ b/src/main/java/com/b1n_ry/yigd/compat/miscCompatMods/CommonProtectionApiCompat.java @@ -1,4 +1,4 @@ -package com.b1n_ry.yigd.compat; +package com.b1n_ry.yigd.compat.miscCompatMods; import com.b1n_ry.yigd.config.YigdConfig; import com.b1n_ry.yigd.events.AllowBlockUnderGraveGenerationEvent; diff --git a/src/main/java/com/b1n_ry/yigd/compat/miscCompatMods/OrpheusCompat.java b/src/main/java/com/b1n_ry/yigd/compat/miscCompatMods/OrpheusCompat.java new file mode 100644 index 00000000..4f1fb2cd --- /dev/null +++ b/src/main/java/com/b1n_ry/yigd/compat/miscCompatMods/OrpheusCompat.java @@ -0,0 +1,20 @@ +package com.b1n_ry.yigd.compat.miscCompatMods; + +import com.b1n_ry.yigd.events.AdjustDropRuleEvent; +import com.b1n_ry.yigd.util.DropRule; +import com.ecarrascon.orpheus.Orpheus; +import com.ecarrascon.orpheus.registry.ItemsRegistry; + +public class OrpheusCompat { + public static void init() { + AdjustDropRuleEvent.EVENT.register((inventory, context) -> { + String orpheusLyrePower = Orpheus.CONFIG_VALUES.getOrpheusLyrePower(); + + if (!orpheusLyrePower.equals("keep") && !orpheusLyrePower.equals("both")) return; + + if (inventory.containsAny(stack -> stack.isOf(ItemsRegistry.ORPHEUS_LYRE.get()), s -> true, i -> true)) { + inventory.setDropRules(stack -> true, s -> true, i -> true, DropRule.KEEP); + } + }); + } +} diff --git a/src/main/java/com/b1n_ry/yigd/components/GraveComponent.java b/src/main/java/com/b1n_ry/yigd/components/GraveComponent.java index 1063aec6..c15ca79c 100644 --- a/src/main/java/com/b1n_ry/yigd/components/GraveComponent.java +++ b/src/main/java/com/b1n_ry/yigd/components/GraveComponent.java @@ -370,6 +370,8 @@ public ActionResult claim(ServerPlayerEntity player, ServerWorld world, BlockSta InventoryComponent.dropItemIfToBeDropped(graveItem, this.pos.getX(), this.pos.getY(), this.pos.getZ(), this.world); } + this.setStatus(GraveStatus.CLAIMED); + if (!config.graveConfig.persistentGraves.enabled) { if (config.graveConfig.replaceOldWhenClaimed && previousState != null) { world.setBlockState(pos, previousState); @@ -387,8 +389,6 @@ public ActionResult claim(ServerPlayerEntity player, ServerWorld world, BlockSta } } - this.setStatus(GraveStatus.CLAIMED); - if (thisIsARobbery && config.graveConfig.graveRobbing.notifyWhenRobbed) { MinecraftServer server = world.getServer(); String robberName = player.getGameProfile().getName(); diff --git a/src/main/java/com/b1n_ry/yigd/components/InventoryComponent.java b/src/main/java/com/b1n_ry/yigd/components/InventoryComponent.java index 73a6a92b..68ef9e71 100644 --- a/src/main/java/com/b1n_ry/yigd/components/InventoryComponent.java +++ b/src/main/java/com/b1n_ry/yigd/components/InventoryComponent.java @@ -4,6 +4,7 @@ import com.b1n_ry.yigd.compat.InvModCompat; import com.b1n_ry.yigd.config.YigdConfig; import com.b1n_ry.yigd.data.DeathContext; +import com.b1n_ry.yigd.events.AdjustDropRuleEvent; import com.b1n_ry.yigd.events.DropItemEvent; import com.b1n_ry.yigd.events.DropRuleEvent; import com.b1n_ry.yigd.util.DropRule; @@ -167,6 +168,8 @@ private void handleDropRules(DeathContext context) { CompatComponent compatComponent = this.modInventoryItems.get(modName); compatComponent.handleDropRules(context); } + + AdjustDropRuleEvent.EVENT.invoker().adjustDropRule(this, context); } public void applyLoss() { @@ -412,6 +415,47 @@ private int findEmptySlot() { return -1; } + /** + * Allows for checking for specific items in specific slots and inventories + * @param itemPredicate Predicate to check for items + * @param modPredicate Predicate to check for mod name ("vanilla" for vanilla) + * @param slotPredicate Predicate to check for slot index (only applies to vanilla inventory) + * @return Whether any item in the component matches the predicates + */ + public boolean containsAny(Predicate itemPredicate, Predicate modPredicate, Predicate slotPredicate) { + if (modPredicate.test("vanilla")) { + for (int i = 0; i < this.items.size(); i++) { + Pair pair = this.items.get(i); + if (slotPredicate.test(i) && itemPredicate.test(pair.getLeft())) return true; + } + } + for (Map.Entry> entry : this.modInventoryItems.entrySet()) { + CompatComponent compatComponent = entry.getValue(); + if (modPredicate.test(entry.getKey()) && compatComponent.containsAny(itemPredicate)) return true; // Modded inventories don't use slot IDs + } + return false; + } + + /** + * Set drop rules for items in the component based on filters/predicates + * @param itemPredicate Items matching this are affected + * @param modPredicate Mods matching this are affected ("vanilla" for vanilla inventory) + * @param slotPredicate Slots matching this are affected (only applies to vanilla inventory) + * @param dropRule Drop rule to set + */ + public void setDropRules(Predicate itemPredicate, Predicate modPredicate, Predicate slotPredicate, DropRule dropRule) { + if (modPredicate.test("vanilla")) { + for (int i = 0; i < this.items.size(); i++) { + Pair pair = this.items.get(i); + if (slotPredicate.test(i) && itemPredicate.test(pair.getLeft())) pair.setRight(dropRule); + } + } + for (Map.Entry> entry : this.modInventoryItems.entrySet()) { + CompatComponent compatComponent = entry.getValue(); + if (modPredicate.test(entry.getKey())) compatComponent.setDropRules(itemPredicate, dropRule); + } + } + /** * Checks if the grave is empty, meaning no items are stored to be retrieved from the grave when it's opened * @return Whether the grave is empty diff --git a/src/main/java/com/b1n_ry/yigd/components/RespawnComponent.java b/src/main/java/com/b1n_ry/yigd/components/RespawnComponent.java index 5c1d7364..7cfc9c00 100644 --- a/src/main/java/com/b1n_ry/yigd/components/RespawnComponent.java +++ b/src/main/java/com/b1n_ry/yigd/components/RespawnComponent.java @@ -27,6 +27,8 @@ public class RespawnComponent { private ExpComponent soulboundExp; private final EffectComponent respawnEffects; + private boolean graveGenerated = false; + public RespawnComponent(ServerPlayerEntity player) { this.respawnEffects = new EffectComponent(player); } @@ -43,6 +45,13 @@ public void setSoulboundExp(@NotNull ExpComponent component) { this.soulboundExp = component; } + public void setGraveGenerated(boolean graveGenerated) { + this.graveGenerated = graveGenerated; + } + public boolean wasGraveGenerated() { + return this.graveGenerated; + } + public void primeForRespawn(GameProfile profile) { DeathInfoManager.INSTANCE.addRespawnComponent(profile, this); DeathInfoManager.INSTANCE.markDirty(); diff --git a/src/main/java/com/b1n_ry/yigd/events/AdjustDropRuleEvent.java b/src/main/java/com/b1n_ry/yigd/events/AdjustDropRuleEvent.java new file mode 100644 index 00000000..a2e8178d --- /dev/null +++ b/src/main/java/com/b1n_ry/yigd/events/AdjustDropRuleEvent.java @@ -0,0 +1,16 @@ +package com.b1n_ry.yigd.events; + +import com.b1n_ry.yigd.components.InventoryComponent; +import com.b1n_ry.yigd.data.DeathContext; +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; + +public interface AdjustDropRuleEvent { + Event EVENT = EventFactory.createArrayBacked(AdjustDropRuleEvent.class, events -> (inventory, context) -> { + for (AdjustDropRuleEvent event : events) { + event.adjustDropRule(inventory, context); + } + }); + + void adjustDropRule(InventoryComponent inventoryComponent, DeathContext context); +} diff --git a/src/main/java/com/b1n_ry/yigd/events/ServerEventHandler.java b/src/main/java/com/b1n_ry/yigd/events/ServerEventHandler.java index 53c6f87e..90663bdb 100644 --- a/src/main/java/com/b1n_ry/yigd/events/ServerEventHandler.java +++ b/src/main/java/com/b1n_ry/yigd/events/ServerEventHandler.java @@ -38,7 +38,7 @@ public static void registerEvents() { Optional respawnComponent = DeathInfoManager.INSTANCE.getRespawnComponent(newProfile); respawnComponent.ifPresent(component -> component.apply(newPlayer)); - if (YigdConfig.getConfig().graveConfig.informGraveLocation) { + if (YigdConfig.getConfig().graveConfig.informGraveLocation && respawnComponent.isPresent() && respawnComponent.get().wasGraveGenerated()) { List graves = new ArrayList<>(DeathInfoManager.INSTANCE.getBackupData(newProfile)); graves.removeIf(grave -> grave.getStatus() != GraveStatus.UNCLAIMED); if (!graves.isEmpty()) {