From 192ddae196c5cd039a4f8f71b014ad2ec4e448ff Mon Sep 17 00:00:00 2001 From: dueris Date: Thu, 22 Aug 2024 01:31:25 -0700 Subject: [PATCH] Release 1.2.0 --- API-DOCS.md | 29 ++-- .../dueris/originspaper/OriginScheduler.java | 10 -- .../dueris/originspaper/OriginsPaper.java | 26 ++-- .../originspaper/command/ResourceCommand.java | 1 - .../types/entity/FallFlyingCondition.java | 5 +- .../github/dueris/originspaper/mixin/At.java | 8 + .../originspaper/mixin/CreeperMixin.java | 14 ++ .../mixin/ItemEnchantmentsMixin.java | 1 - .../originspaper/mixin/LivingEntityMixin.java | 13 ++ .../originspaper/mixin/PlayerMixin.java | 35 +++++ .../originspaper/power/ElytraFlightPower.java | 4 +- .../dueris/originspaper/power/PowerType.java | 7 - .../power/origins/LikeWaterPower.java | 31 ++++ .../power/origins/ScareCreepersPower.java | 41 ++++++ .../power/origins/WaterBreathingPower.java | 87 +++++++++++ .../power/provider/OriginSimpleContainer.java | 36 ----- .../power/provider/PowerProvider.java | 14 -- .../power/provider/origins/LikeWater.java | 38 ----- .../power/provider/origins/ScareCreepers.java | 97 ------------ .../power/provider/origins/WaterBreathe.java | 138 ------------------ .../storage/PowerHolderComponent.java | 8 - .../github/dueris/originspaper/util/Util.java | 20 +++ .../util/entity/PlayerManager.java | 1 - .../origins/power/shulker_inventory.json | 2 +- 24 files changed, 282 insertions(+), 384 deletions(-) create mode 100644 origins/src/main/java/io/github/dueris/originspaper/mixin/CreeperMixin.java create mode 100644 origins/src/main/java/io/github/dueris/originspaper/mixin/PlayerMixin.java create mode 100644 origins/src/main/java/io/github/dueris/originspaper/power/origins/LikeWaterPower.java create mode 100644 origins/src/main/java/io/github/dueris/originspaper/power/origins/ScareCreepersPower.java create mode 100644 origins/src/main/java/io/github/dueris/originspaper/power/origins/WaterBreathingPower.java delete mode 100644 origins/src/main/java/io/github/dueris/originspaper/power/provider/OriginSimpleContainer.java delete mode 100644 origins/src/main/java/io/github/dueris/originspaper/power/provider/PowerProvider.java delete mode 100644 origins/src/main/java/io/github/dueris/originspaper/power/provider/origins/LikeWater.java delete mode 100644 origins/src/main/java/io/github/dueris/originspaper/power/provider/origins/ScareCreepers.java delete mode 100644 origins/src/main/java/io/github/dueris/originspaper/power/provider/origins/WaterBreathe.java diff --git a/API-DOCS.md b/API-DOCS.md index a21e113a3..47f77f2d2 100644 --- a/API-DOCS.md +++ b/API-DOCS.md @@ -62,10 +62,10 @@ public class ApoliExamplePower extends PowerType { ``` In Calio/Apoli, a PowerType is an object that defines the main logic and handling of powers for the players it has assigned to it. -To create an instance of any class inside Calio during parsing, it reads the InstanceDefiner, which is defined by the -method ``static InstanceDefiner buildFactory()``. InstanceDefiners are definition of a Constructor for the FactoryHolder. The first instance +To create an instance of any class inside Calio during parsing, it reads the SerializableData, which is defined by the +method ``static SerializableData buildFactory()``. SerializableDatas are definition of a Constructor for the FactoryHolder. The first instance added is the first arg, the second being the second arg, etc. It also provides the key for the `"type"` field. However, in Calio, there -is a required argument of a ResourceLocation at the beginning of the constructor your InstanceDefiner is creating, which is the `"key"` argument. +is a required argument of a ResourceLocation at the beginning of the constructor your SerializableData is creating, which is the `"key"` argument. The key argument is the argument assigned to the instance upon instance creation, named after the Namesace and Key of the json. With adding the constructor, it becomes: @@ -77,7 +77,7 @@ public class ApoliExamplePower extends PowerType { } ``` -Adding the method to create the InstanceDefiner: +Adding the method to create the SerializableData: ```java public class ApoliExamplePower extends PowerType { @@ -89,7 +89,7 @@ public class ApoliExamplePower extends PowerType { // from the base instead of Copy/Pasting its buildFactory method and adding to it. // By default, the PowerType class does not contain a Namespace, which is why ofNamespace needs to be added. // The way this is made allows for creating easy extensions of any power without too much struggle. - public static InstanceDefiner buildFactory() { + public static SerializableData buildFactory() { return PowerType.buildFactory().typedRegistry(ResourceLocation.fromNamespaceAndPath("example", "apoli")); } } @@ -102,9 +102,9 @@ create your own! | Method Name | Description | |----------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------| -| required(String key, SerializableDataBuilder dataType) | Adds a required field to the InstanceDefiner | -| add(String key, SerializableDataBuilder dataType) | Adds a nullable field to the InstanceDefiner, when the field is not present, it returns null | -| add(String key, SerializableDataBuilder dataType, T defaultValue) | Adds a field to the InstanceDefiner with a default value that is provided when the field is not present | +| required(String key, SerializableDataBuilder dataType) | Adds a required field to the SerializableData | +| add(String key, SerializableDataBuilder dataType) | Adds a nullable field to the SerializableData, when the field is not present, it returns null | +| add(String key, SerializableDataBuilder dataType, T defaultValue) | Adds a field to the SerializableData with a default value that is provided when the field is not present | ```java public class ApoliExamplePower extends PowerType { @@ -114,7 +114,7 @@ public class ApoliExamplePower extends PowerType { super(key, type, name, description, hidden, condition, loadingPriority); } - public static InstanceDefiner buildFactory() { + public static SerializableData buildFactory() { return PowerType.buildFactory().typedRegistry(ResourceLocation.fromNamespaceAndPath("example", "apoli")) /* | Field name | SerializableDataType instance | Default value | */ .add("welcome_message", SerializableDataTypes.STRING, "Hello World!"); @@ -157,7 +157,7 @@ public class ApoliExamplePower extends PowerType { super(key, type, name, description, hidden, condition, loadingPriority); } - public static InstanceDefiner buildFactory() { + public static SerializableData buildFactory() { return PowerType.buildFactory().typedRegistry(ResourceLocation.fromNamespaceAndPath("example", "apoli")) .add("welcome_message", SerializableDataTypes.STRING, "Hello World!"); } @@ -186,7 +186,7 @@ public class ApoliExamplePower extends PowerType { super(key, type, name, description, hidden, condition, loadingPriority); } - public static InstanceDefiner buildFactory() { + public static SerializableData buildFactory() { return PowerType.buildFactory().typedRegistry(ResourceLocation.fromNamespaceAndPath("example", "apoli")) .add("welcome_message", SerializableDataTypes.STRING, "Hello World!"); } @@ -235,14 +235,13 @@ Now, we are going to add our `"type"` param, which defines the type associated i register(new ConditionFactory<>(ResourceLocation.fromNamespaceAndPath("test", "example"))); ``` -The 2nd arg is an InstanceDefiner, which functions exactly how the PowerType instance definer works for building! The 3rd -and final arg is a `BiPredicate`. A DeserializedFactoryJson is similar to the Apoli SerializableData.Instance -class, which acts as an accessor for getting values defined in the InstanceDefiner. +The 2nd arg is an SerializableData, which functions exactly how the PowerType instance definer works for building! The 3rd +and final arg is a `BiPredicate`. A SerializableData.Instance acts as an accessor for getting values defined in the SerializableData. ```java register(new ConditionFactory<>( ResourceLocation.fromNamespaceAndPath("test", "example"), - InstanceDefiner.instanceDefiner(), + SerializableData.serializableData(), (data, entity) -> { return entity.isAlive(); } diff --git a/origins/src/main/java/io/github/dueris/originspaper/OriginScheduler.java b/origins/src/main/java/io/github/dueris/originspaper/OriginScheduler.java index e93911ace..52b7ec145 100644 --- a/origins/src/main/java/io/github/dueris/originspaper/OriginScheduler.java +++ b/origins/src/main/java/io/github/dueris/originspaper/OriginScheduler.java @@ -2,8 +2,6 @@ import io.github.dueris.originspaper.power.CreativeFlightPower; import io.github.dueris.originspaper.power.PowerType; -import io.github.dueris.originspaper.power.provider.OriginSimpleContainer; -import io.github.dueris.originspaper.power.provider.PowerProvider; import io.github.dueris.originspaper.registry.Registries; import io.github.dueris.originspaper.storage.PowerHolderComponent; import net.minecraft.world.entity.player.Player; @@ -71,14 +69,6 @@ public void run() { } } } - - for (PowerProvider provider : OriginSimpleContainer.location2PowerMap.values()) { - provider.tick(); - - for (org.bukkit.entity.Player p : Bukkit.getOnlinePlayers()) { - provider.tick(p); - } - } } public void tickAsyncScheduler() { diff --git a/origins/src/main/java/io/github/dueris/originspaper/OriginsPaper.java b/origins/src/main/java/io/github/dueris/originspaper/OriginsPaper.java index 2676ef132..1faa1ede7 100644 --- a/origins/src/main/java/io/github/dueris/originspaper/OriginsPaper.java +++ b/origins/src/main/java/io/github/dueris/originspaper/OriginsPaper.java @@ -21,7 +21,6 @@ import io.github.dueris.originspaper.origin.OriginLayer; import io.github.dueris.originspaper.power.PowerType; import io.github.dueris.originspaper.power.RecipePower; -import io.github.dueris.originspaper.power.provider.origins.WaterBreathe; import io.github.dueris.originspaper.registry.BuiltinRegistry; import io.github.dueris.originspaper.registry.Registries; import io.github.dueris.originspaper.screen.ChoosingPage; @@ -88,6 +87,18 @@ public final class OriginsPaper extends JavaPlugin implements Listener { private static OriginsPaper plugin; public IRegistry registry; + public OriginsPaper() { + if (!Bootstrap.BOOTSTRAPPED.get()) { + Bootstrap bootstrap = new Bootstrap(); + bootstrap.bootstrap(null); + } + + Bootstrap.BOOTSTRAPPED.set(false); + + plugin = this; + OriginsMixins.init(Bootstrap.MIXIN_LOADER.get()); + } + public static OriginScheduler.MainTickerThread getScheduler() { return scheduler; } @@ -159,18 +170,6 @@ public void finalizePreboot() { } } - @Override - public void onLoad() { - if (!Bootstrap.BOOTSTRAPPED.get()) { - Bootstrap bootstrap = new Bootstrap(); - bootstrap.bootstrap(null); - } - - Bootstrap.BOOTSTRAPPED.set(false); - plugin = this; - OriginsMixins.init(Bootstrap.MIXIN_LOADER.get()); - } - @Override public void onEnable() { Getter startup = () -> { @@ -327,7 +326,6 @@ private void start() { } }); BukkitRunnable[] independentTickers = new BukkitRunnable[]{new GuiTicker(), new OriginCommand()}; - WaterBreathe.start(); for (BukkitRunnable runnable : independentTickers) { runnable.runTaskTimerAsynchronously(getPlugin(), 0L, 1L); diff --git a/origins/src/main/java/io/github/dueris/originspaper/command/ResourceCommand.java b/origins/src/main/java/io/github/dueris/originspaper/command/ResourceCommand.java index 1f31ea7fe..af81b0630 100644 --- a/origins/src/main/java/io/github/dueris/originspaper/command/ResourceCommand.java +++ b/origins/src/main/java/io/github/dueris/originspaper/command/ResourceCommand.java @@ -217,7 +217,6 @@ public static void register(CommandDispatcher dispatcher) { ResourcePower.getDisplayedBar(player, resourcePower.getTag()) .ifPresentOrElse( bar -> { - System.out.println(bar.getMappedProgress() + setTo); bar.change(setTo, "add"); context.getSource() .sendSystemMessage( diff --git a/origins/src/main/java/io/github/dueris/originspaper/condition/types/entity/FallFlyingCondition.java b/origins/src/main/java/io/github/dueris/originspaper/condition/types/entity/FallFlyingCondition.java index bf5fe4460..7a9370421 100644 --- a/origins/src/main/java/io/github/dueris/originspaper/condition/types/entity/FallFlyingCondition.java +++ b/origins/src/main/java/io/github/dueris/originspaper/condition/types/entity/FallFlyingCondition.java @@ -3,6 +3,8 @@ import io.github.dueris.calio.parser.SerializableData; import io.github.dueris.originspaper.OriginsPaper; import io.github.dueris.originspaper.condition.ConditionFactory; +import io.github.dueris.originspaper.power.ElytraFlightPower; +import io.github.dueris.originspaper.storage.PowerHolderComponent; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import org.jetbrains.annotations.NotNull; @@ -14,7 +16,8 @@ public class FallFlyingCondition { OriginsPaper.apoliIdentifier("fall_flying"), SerializableData.serializableData(), (data, entity) -> { - return entity instanceof LivingEntity && ((LivingEntity) entity).isFallFlying(); + return entity instanceof LivingEntity && (((LivingEntity) entity).isFallFlying() || + PowerHolderComponent.doesHaveConditionedPower(entity.getBukkitEntity(), ElytraFlightPower.class, (p) -> p.getGlidingPlayers().contains(entity.getBukkitEntity().getUniqueId()))); } ); } diff --git a/origins/src/main/java/io/github/dueris/originspaper/mixin/At.java b/origins/src/main/java/io/github/dueris/originspaper/mixin/At.java index 858704f70..cef5dd20f 100644 --- a/origins/src/main/java/io/github/dueris/originspaper/mixin/At.java +++ b/origins/src/main/java/io/github/dueris/originspaper/mixin/At.java @@ -12,6 +12,7 @@ import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.item.ItemEntity; @@ -86,6 +87,13 @@ public enum Value { } catch (NoSuchMethodException e) { throw new RuntimeException(e); } + }).get()), + IN_WATER_OR_RAIN_CHECK(((ObjectProvider) () -> { + try { + return new HLocatorMethodInvoke(Entity.class.getDeclaredMethod("isInWaterOrRain"), PostPreState.PRE, (i) -> i == 0); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } }).get()); private final HookLocator locator; diff --git a/origins/src/main/java/io/github/dueris/originspaper/mixin/CreeperMixin.java b/origins/src/main/java/io/github/dueris/originspaper/mixin/CreeperMixin.java new file mode 100644 index 000000000..163212d62 --- /dev/null +++ b/origins/src/main/java/io/github/dueris/originspaper/mixin/CreeperMixin.java @@ -0,0 +1,14 @@ +package io.github.dueris.originspaper.mixin; + +import com.dragoncommissions.mixbukkit.api.shellcode.impl.api.CallbackInfo; +import io.github.dueris.originspaper.power.origins.ScareCreepersPower; +import net.minecraft.world.entity.monster.Creeper; + +@Mixin(Creeper.class) +public class CreeperMixin { + + @Inject(method = "registerGoals", locator = At.Value.RETURN) + public static void origins$scareCreepers(Creeper creeper, CallbackInfo info) { + ScareCreepersPower.modifyGoals(creeper); + } +} diff --git a/origins/src/main/java/io/github/dueris/originspaper/mixin/ItemEnchantmentsMixin.java b/origins/src/main/java/io/github/dueris/originspaper/mixin/ItemEnchantmentsMixin.java index 27876f473..04c5b195d 100644 --- a/origins/src/main/java/io/github/dueris/originspaper/mixin/ItemEnchantmentsMixin.java +++ b/origins/src/main/java/io/github/dueris/originspaper/mixin/ItemEnchantmentsMixin.java @@ -18,7 +18,6 @@ public class ItemEnchantmentsMixin { public static void mark(ItemEnchantments itemEnchantments, ModifyEnchantmentLevelPower power) { TO_MODIFY.put(itemEnchantments, power); - System.out.println(itemEnchantments.toString()); } public static void unmark(ItemEnchantments itemEnchantments) { diff --git a/origins/src/main/java/io/github/dueris/originspaper/mixin/LivingEntityMixin.java b/origins/src/main/java/io/github/dueris/originspaper/mixin/LivingEntityMixin.java index f712327c7..3f2aa288a 100644 --- a/origins/src/main/java/io/github/dueris/originspaper/mixin/LivingEntityMixin.java +++ b/origins/src/main/java/io/github/dueris/originspaper/mixin/LivingEntityMixin.java @@ -3,6 +3,7 @@ import com.dragoncommissions.mixbukkit.api.shellcode.impl.api.CallbackInfo; import io.github.dueris.originspaper.data.types.modifier.ModifierUtil; import io.github.dueris.originspaper.power.*; +import io.github.dueris.originspaper.power.origins.WaterBreathingPower; import io.github.dueris.originspaper.storage.PowerHolderComponent; import net.minecraft.core.Holder; import net.minecraft.tags.EntityTypeTags; @@ -132,4 +133,16 @@ public class LivingEntityMixin { info.setReturned(true); } + @Inject(method = "canBreatheUnderwater", locator = At.Value.RETURN) + public static void origins$waterBreathing(@NotNull LivingEntity instance, @NotNull CallbackInfo info) { + info.setReturned(true); + boolean original = instance.getType().is(EntityTypeTags.CAN_BREATHE_UNDER_WATER); + info.setReturnValue(original || PowerHolderComponent.hasPower(instance.getBukkitEntity(), "origins:water_breathing")); + } + + @Inject(method = "baseTick", locator = At.Value.RETURN) + public static void origins$waterBreathingTick(LivingEntity instance, CallbackInfo info) { + WaterBreathingPower.tick(instance); + } + } diff --git a/origins/src/main/java/io/github/dueris/originspaper/mixin/PlayerMixin.java b/origins/src/main/java/io/github/dueris/originspaper/mixin/PlayerMixin.java new file mode 100644 index 000000000..c7b3d6610 --- /dev/null +++ b/origins/src/main/java/io/github/dueris/originspaper/mixin/PlayerMixin.java @@ -0,0 +1,35 @@ +package io.github.dueris.originspaper.mixin; + +import com.dragoncommissions.mixbukkit.api.shellcode.impl.api.CallbackInfo; +import io.github.dueris.originspaper.power.origins.LikeWaterPower; +import io.github.dueris.originspaper.storage.PowerHolderComponent; +import net.minecraft.tags.FluidTags; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import org.bukkit.event.entity.EntityPotionEffectEvent; +import org.jetbrains.annotations.NotNull; + +@Mixin(Player.class) +public class PlayerMixin { + + @Inject(method = "tick", locator = At.Value.HEAD) + public static void apoli$likeWater(Player instance, CallbackInfo info) { + LikeWaterPower.tick((org.bukkit.entity.Player) instance.getBukkitEntity()); + } + + @Inject(method = "turtleHelmetTick", locator = At.Value.HEAD) + public static void apoli$turtleHelmetTick(@NotNull Player instance, CallbackInfo info) { + ItemStack itemstack = instance.getItemBySlot(EquipmentSlot.HEAD); + + if (itemstack.is(Items.TURTLE_HELMET) && PowerHolderComponent.hasPower(instance.getBukkitEntity(), "origins:water_breathing") == instance.isEyeInFluid(FluidTags.WATER)) { + instance.addEffect(new MobEffectInstance(MobEffects.WATER_BREATHING, 200, 0, false, false, true), EntityPotionEffectEvent.Cause.TURTLE_HELMET); + } + + info.setReturned(true); + + } +} diff --git a/origins/src/main/java/io/github/dueris/originspaper/power/ElytraFlightPower.java b/origins/src/main/java/io/github/dueris/originspaper/power/ElytraFlightPower.java index 1e01541be..0c22482f3 100644 --- a/origins/src/main/java/io/github/dueris/originspaper/power/ElytraFlightPower.java +++ b/origins/src/main/java/io/github/dueris/originspaper/power/ElytraFlightPower.java @@ -35,7 +35,7 @@ import java.util.UUID; public class ElytraFlightPower extends PowerType { - public static ArrayList glidingPlayers = new ArrayList<>(); + private final ArrayList glidingPlayers = new ArrayList<>(); public ElytraFlightPower(@NotNull ResourceLocation key, @NotNull ResourceLocation type, Component name, Component description, boolean hidden, ConditionFactory condition, int loadingPriority) { super(key, type, name, description, hidden, condition, loadingPriority); @@ -45,7 +45,7 @@ public static SerializableData buildFactory() { return PowerType.buildFactory().typedRegistry(OriginsPaper.apoliIdentifier("elytra_flight")); } - public static ArrayList getGlidingPlayers() { + public ArrayList getGlidingPlayers() { return glidingPlayers; } diff --git a/origins/src/main/java/io/github/dueris/originspaper/power/PowerType.java b/origins/src/main/java/io/github/dueris/originspaper/power/PowerType.java index e247eaaae..9285fc17e 100644 --- a/origins/src/main/java/io/github/dueris/originspaper/power/PowerType.java +++ b/origins/src/main/java/io/github/dueris/originspaper/power/PowerType.java @@ -9,10 +9,6 @@ import io.github.dueris.originspaper.OriginsPaper; import io.github.dueris.originspaper.condition.ConditionFactory; import io.github.dueris.originspaper.data.ApoliDataTypes; -import io.github.dueris.originspaper.power.provider.OriginSimpleContainer; -import io.github.dueris.originspaper.power.provider.origins.LikeWater; -import io.github.dueris.originspaper.power.provider.origins.ScareCreepers; -import io.github.dueris.originspaper.power.provider.origins.WaterBreathe; import io.github.dueris.originspaper.util.LangFile; import net.kyori.adventure.text.TextComponent; import net.minecraft.nbt.CompoundTag; @@ -118,9 +114,6 @@ public boolean addAll(@NotNull Collection> } INSTANCE_TYPES.addAll(holders); - OriginSimpleContainer.registerPower(LikeWater.class); - OriginSimpleContainer.registerPower(ScareCreepers.class); - OriginSimpleContainer.registerPower(WaterBreathe.class); } public ResourceLocation key() { diff --git a/origins/src/main/java/io/github/dueris/originspaper/power/origins/LikeWaterPower.java b/origins/src/main/java/io/github/dueris/originspaper/power/origins/LikeWaterPower.java new file mode 100644 index 000000000..0e6a42c0e --- /dev/null +++ b/origins/src/main/java/io/github/dueris/originspaper/power/origins/LikeWaterPower.java @@ -0,0 +1,31 @@ +package io.github.dueris.originspaper.power.origins; + +import io.github.dueris.originspaper.OriginsPaper; +import io.github.dueris.originspaper.storage.PowerHolderComponent; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeModifier; +import org.bukkit.craftbukkit.util.CraftNamespacedKey; +import org.bukkit.entity.Player; + +public class LikeWaterPower { + private static final AttributeModifier modifier = new AttributeModifier(CraftNamespacedKey.fromMinecraft(OriginsPaper.originIdentifier("likewater")), -1, AttributeModifier.Operation.MULTIPLY_SCALAR_1); + private static final String cachedPowerRefrenceString = "origins:like_water"; + + public static void tick(Player p) { + if (!PowerHolderComponent.hasPower(p, cachedPowerRefrenceString)) { + if (p.getAttribute(Attribute.GENERIC_GRAVITY).getModifiers().contains(modifier)) { + p.getAttribute(Attribute.GENERIC_GRAVITY).removeModifier(modifier); + } + return; + } + if (p.isInWaterOrBubbleColumn() && !p.isSneaking()) { + if (!p.getAttribute(Attribute.GENERIC_GRAVITY).getModifiers().contains(modifier)) { + p.getAttribute(Attribute.GENERIC_GRAVITY).addTransientModifier(modifier); + } + } else { + if (p.getAttribute(Attribute.GENERIC_GRAVITY).getModifiers().contains(modifier)) { + p.getAttribute(Attribute.GENERIC_GRAVITY).removeModifier(modifier); + } + } + } +} diff --git a/origins/src/main/java/io/github/dueris/originspaper/power/origins/ScareCreepersPower.java b/origins/src/main/java/io/github/dueris/originspaper/power/origins/ScareCreepersPower.java new file mode 100644 index 000000000..876aa9935 --- /dev/null +++ b/origins/src/main/java/io/github/dueris/originspaper/power/origins/ScareCreepersPower.java @@ -0,0 +1,41 @@ +package io.github.dueris.originspaper.power.origins; + +import io.github.dueris.originspaper.storage.PowerHolderComponent; +import net.minecraft.world.entity.EntitySelector; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.PathfinderMob; +import net.minecraft.world.entity.ai.goal.AvoidEntityGoal; +import net.minecraft.world.entity.ai.goal.GoalSelector; +import net.minecraft.world.entity.ai.goal.WrappedGoal; +import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; +import net.minecraft.world.entity.player.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; + +public class ScareCreepersPower { + + public static void modifyGoals(@NotNull PathfinderMob pathAwareEntity) { + + GoalSelector targetSelector = pathAwareEntity.targetSelector; + GoalSelector goalSelector = pathAwareEntity.goalSelector; + + Iterator oldTargetPrioGoals = targetSelector.getAvailableGoals().iterator(); + + // Remove old NearestAttackableTargetGoals so we can add a new one + while (oldTargetPrioGoals.hasNext()) { + + WrappedGoal oldTargetPrioGoal = oldTargetPrioGoals.next(); + if (!(oldTargetPrioGoal.getGoal() instanceof NearestAttackableTargetGoal)) { + continue; + } + + oldTargetPrioGoals.remove(); + + } + + goalSelector.addGoal(3, new AvoidEntityGoal<>(pathAwareEntity, LivingEntity.class, e -> PowerHolderComponent.hasPower(e.getBukkitEntity(), "origins:scare_creepers"), 6.0F, 1.0D, 1.2D, EntitySelector.NO_CREATIVE_OR_SPECTATOR::test)); + goalSelector.addGoal(1, new NearestAttackableTargetGoal<>(pathAwareEntity, Player.class, true, (e) -> !PowerHolderComponent.hasPower(e.getBukkitEntity(), "origins:scare_creepers"))); + + } +} diff --git a/origins/src/main/java/io/github/dueris/originspaper/power/origins/WaterBreathingPower.java b/origins/src/main/java/io/github/dueris/originspaper/power/origins/WaterBreathingPower.java new file mode 100644 index 000000000..43c5dff2a --- /dev/null +++ b/origins/src/main/java/io/github/dueris/originspaper/power/origins/WaterBreathingPower.java @@ -0,0 +1,87 @@ +package io.github.dueris.originspaper.power.origins; + +import io.github.dueris.originspaper.OriginsPaper; +import io.github.dueris.originspaper.storage.PowerHolderComponent; +import io.github.dueris.originspaper.util.Util; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.tags.FluidTags; +import net.minecraft.world.damagesource.DamageType; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.LivingEntity; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class WaterBreathingPower { + public static final ResourceKey NO_WATER_FOR_GILLS = ResourceKey.create(Registries.DAMAGE_TYPE, OriginsPaper.originIdentifier("no_water_for_gills")); + + public static boolean shouldDrown(@NotNull LivingEntity entity) { + return !entity.isEyeInFluid(FluidTags.WATER) + && !entity.hasEffect(MobEffects.WATER_BREATHING) + && !entity.hasEffect(MobEffects.CONDUIT_POWER); + } + + private static int callGetNextAirOnLand(int a, LivingEntity entity) { + try { + Method toInvoke = LivingEntity.class.getDeclaredMethod("increaseAirSupply", int.class); + toInvoke.setAccessible(true); + return (int) toInvoke.invoke(entity, a); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + throw new RuntimeException("Unable to call 'getNextAirOnLand' for WaterBreathingPower", e); + } + } + + private static int callGetNextAirUnderwater(int a, LivingEntity entity) { + try { + Method toInvoke = LivingEntity.class.getDeclaredMethod("decreaseAirSupply", int.class); + toInvoke.setAccessible(true); + return (int) toInvoke.invoke(entity, a); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + public static void tick(@NotNull LivingEntity entity) { + + if (!PowerHolderComponent.hasPower(entity.getBukkitEntity(), "origins:water_breathing")) { + return; + } + + if (shouldDrown(entity)) { + + int landGain = callGetNextAirOnLand(0, entity); + int landLoss = callGetNextAirUnderwater(entity.getAirSupply(), entity); + + if (!entity.isInRain()) { + + entity.setAirSupply(landLoss - landGain); + if (entity.getAirSupply() != -20) { + return; + } + + entity.setAirSupply(0); + entity.hurt(Util.getDamageSource(Util.DAMAGE_REGISTRY.get(NO_WATER_FOR_GILLS)), 2.0F); + + for (int i = 0; i < 8; ++i) { + + double dx = entity.getRandom().nextDouble() - entity.getRandom().nextDouble(); + double dy = entity.getRandom().nextDouble() - entity.getRandom().nextDouble(); + double dz = entity.getRandom().nextDouble() - entity.getRandom().nextDouble(); + + entity.level().addParticle(ParticleTypes.BUBBLE, entity.getRandomX(0.5), entity.getEyeHeight(entity.getPose()), entity.getRandomZ(0.5), dx * 0.5, dy * 0.5 + 0.25, dz * 0.5); + + } + + } else { + entity.setAirSupply(entity.getAirSupply() - landGain); + } + + } else if (entity.getAirSupply() < entity.getMaxAirSupply()) { + entity.setAirSupply(callGetNextAirOnLand(entity.getAirSupply(), entity)); + } + + } +} diff --git a/origins/src/main/java/io/github/dueris/originspaper/power/provider/OriginSimpleContainer.java b/origins/src/main/java/io/github/dueris/originspaper/power/provider/OriginSimpleContainer.java deleted file mode 100644 index 2d97e92bf..000000000 --- a/origins/src/main/java/io/github/dueris/originspaper/power/provider/OriginSimpleContainer.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.github.dueris.originspaper.power.provider; - -import io.github.dueris.calio.util.ReflectionUtils; -import io.github.dueris.originspaper.OriginsPaper; -import io.github.dueris.originspaper.power.SimplePower; -import net.minecraft.resources.ResourceLocation; -import org.bukkit.Bukkit; -import org.bukkit.event.Listener; -import org.jetbrains.annotations.NotNull; -import org.mineskin.com.google.common.base.Preconditions; - -import java.util.HashMap; - -public class OriginSimpleContainer { - public static HashMap location2PowerMap = new HashMap<>(); - - public static void registerPower(@NotNull Class clz) { - try { - Preconditions.checkArgument(clz.newInstance() instanceof PowerProvider, "Power isn't an instance of a PowerProvider power. This is required to make it so that its marked as able to be its own originPower"); - Preconditions.checkArgument(clz.getDeclaredField("powerReference") != null, "Unable to access required field \"powerReference\" inside Power. This is required to point to what powerFile this PowerProvider will use"); - - PowerProvider instance = (PowerProvider) clz.newInstance(); - location2PowerMap.put((ResourceLocation) ReflectionUtils.getStaticFieldValue(clz, "powerReference"), instance); - if (instance instanceof Listener || Listener.class.isAssignableFrom(clz)) { - Bukkit.getServer().getPluginManager().registerEvents((Listener) instance, OriginsPaper.getPlugin()); - } - } catch (SecurityException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException | - InstantiationException e) { - e.printStackTrace(); - } - } - - public static PowerProvider getFromSimple(@NotNull SimplePower simplePower) { - return location2PowerMap.get(simplePower.key()); - } -} diff --git a/origins/src/main/java/io/github/dueris/originspaper/power/provider/PowerProvider.java b/origins/src/main/java/io/github/dueris/originspaper/power/provider/PowerProvider.java deleted file mode 100644 index 26a036443..000000000 --- a/origins/src/main/java/io/github/dueris/originspaper/power/provider/PowerProvider.java +++ /dev/null @@ -1,14 +0,0 @@ -package io.github.dueris.originspaper.power.provider; - -import org.bukkit.entity.Player; - -public interface PowerProvider { - default void tick(Player player) { - } - - default void tick() { - } - - default void onRemove(Player player) { - } -} \ No newline at end of file diff --git a/origins/src/main/java/io/github/dueris/originspaper/power/provider/origins/LikeWater.java b/origins/src/main/java/io/github/dueris/originspaper/power/provider/origins/LikeWater.java deleted file mode 100644 index ec22a5260..000000000 --- a/origins/src/main/java/io/github/dueris/originspaper/power/provider/origins/LikeWater.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.github.dueris.originspaper.power.provider.origins; - -import io.github.dueris.originspaper.OriginsPaper; -import io.github.dueris.originspaper.power.provider.PowerProvider; -import io.github.dueris.originspaper.storage.PowerHolderComponent; -import net.minecraft.resources.ResourceLocation; -import org.bukkit.attribute.Attribute; -import org.bukkit.attribute.AttributeModifier; -import org.bukkit.entity.Player; -import org.bukkit.event.Listener; -import org.jetbrains.annotations.NotNull; - -public class LikeWater implements Listener, PowerProvider { - private static final AttributeModifier modifier = new AttributeModifier("LikeWater", -1, AttributeModifier.Operation.MULTIPLY_SCALAR_1); - protected static ResourceLocation powerReference = OriginsPaper.originIdentifier("like_water"); - private static final String cachedPowerRefrenceString = powerReference.toString(); - - @Override - public void tick(Player p) { - if (!PowerHolderComponent.hasPower(p, cachedPowerRefrenceString)) return; - if (p.isInWaterOrBubbleColumn() && !p.isSneaking()) { - if (!p.getAttribute(Attribute.GENERIC_GRAVITY).getModifiers().contains(modifier)) { - p.getAttribute(Attribute.GENERIC_GRAVITY).addTransientModifier(modifier); - } - } else { - if (p.getAttribute(Attribute.GENERIC_GRAVITY).getModifiers().contains(modifier)) { - p.getAttribute(Attribute.GENERIC_GRAVITY).removeModifier(modifier); - } - } - } - - @Override - public void onRemove(@NotNull Player player) { - if (player.getAttribute(Attribute.GENERIC_GRAVITY).getModifiers().contains(modifier)) { - player.getAttribute(Attribute.GENERIC_GRAVITY).removeModifier(modifier); - } - } -} diff --git a/origins/src/main/java/io/github/dueris/originspaper/power/provider/origins/ScareCreepers.java b/origins/src/main/java/io/github/dueris/originspaper/power/provider/origins/ScareCreepers.java deleted file mode 100644 index f1366d82c..000000000 --- a/origins/src/main/java/io/github/dueris/originspaper/power/provider/origins/ScareCreepers.java +++ /dev/null @@ -1,97 +0,0 @@ -package io.github.dueris.originspaper.power.provider.origins; - -import io.github.dueris.originspaper.OriginsPaper; -import io.github.dueris.originspaper.power.provider.PowerProvider; -import io.github.dueris.originspaper.storage.PowerHolderComponent; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.PathfinderMob; -import net.minecraft.world.entity.ai.goal.AvoidEntityGoal; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.entity.CraftEntity; -import org.bukkit.craftbukkit.util.CraftNamespacedKey; -import org.bukkit.entity.*; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntitySpawnEvent; -import org.bukkit.event.entity.EntityTargetLivingEntityEvent; -import org.bukkit.event.world.EntitiesLoadEvent; -import org.bukkit.persistence.PersistentDataType; -import org.bukkit.scheduler.BukkitRunnable; -import org.jetbrains.annotations.NotNull; - -public class ScareCreepers implements Listener, PowerProvider { - protected static ResourceLocation powerReference = OriginsPaper.originIdentifier("scare_creepers"); - private final ResourceLocation hitByPlayerKey = OriginsPaper.identifier("hit-by-player"); - - @EventHandler - public void load(@NotNull EntitySpawnEvent event) { - if (event.getEntity() instanceof Creeper creeper) { - applyPatch(creeper); - } - } - - @EventHandler - public void load(@NotNull EntitiesLoadEvent event) { - for (Entity entity : event.getEntities()) { - if (entity instanceof Creeper creeper) { - applyPatch(creeper); - } - } - } - - public void applyPatch(Creeper creeper) { - Bukkit.getMobGoals().addGoal(creeper, 0, new AvoidEntityGoal<>( - (PathfinderMob) ((CraftEntity) creeper).getHandle(), net.minecraft.world.entity.player.Player.class, 6, 1, 1.2, - livingEntity -> { - if (livingEntity.getBukkitEntity() instanceof Player player) { - if (PowerHolderComponent.hasPower(player, powerReference.toString())) { - String data = creeper.getPersistentDataContainer().get(CraftNamespacedKey.fromMinecraft(hitByPlayerKey), PersistentDataType.STRING); - if (data == null) { - return true; - } - return !data.equals(player.getName()); - } - } - return false; - } - ).asPaperVanillaGoal()); - } - - @EventHandler - public void onEntityDamageByEntity(@NotNull EntityDamageByEntityEvent event) { - if (event.getEntity().getType().equals(EntityType.CREEPER)) { - Player player; - if (event.getDamager() instanceof Projectile projectile) { - if (projectile.getShooter() instanceof org.bukkit.entity.Player shooter) player = shooter; - else return; - } else if (event.getDamager() instanceof org.bukkit.entity.Player damager) { - player = damager; - } else { - return; - } - event.getEntity().getPersistentDataContainer().set(CraftNamespacedKey.fromMinecraft(hitByPlayerKey), PersistentDataType.STRING, player.getName()); - } - } - - @EventHandler - public void onEntityTargetLivingEntity(@NotNull EntityTargetLivingEntityEvent event) { - if (event.getEntity().getType().equals(EntityType.CREEPER)) { - if (event.getTarget() instanceof Player player) { - new BukkitRunnable() { - @Override - public void run() { - String data = event.getEntity().getPersistentDataContainer().get(CraftNamespacedKey.fromMinecraft(hitByPlayerKey), PersistentDataType.STRING); - if (data == null) { - event.setCancelled(true); - return; - } - if (!data.equals(player.getName())) { - event.setCancelled(true); - } - } - }.runTask(OriginsPaper.getPlugin()); - } - } - } -} diff --git a/origins/src/main/java/io/github/dueris/originspaper/power/provider/origins/WaterBreathe.java b/origins/src/main/java/io/github/dueris/originspaper/power/provider/origins/WaterBreathe.java deleted file mode 100644 index 45b73eb70..000000000 --- a/origins/src/main/java/io/github/dueris/originspaper/power/provider/origins/WaterBreathe.java +++ /dev/null @@ -1,138 +0,0 @@ -package io.github.dueris.originspaper.power.provider.origins; - -import io.github.dueris.originspaper.OriginsPaper; -import io.github.dueris.originspaper.power.provider.PowerProvider; -import io.github.dueris.originspaper.storage.PowerHolderComponent; -import io.github.dueris.originspaper.util.Util; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.damagesource.DamageType; -import net.minecraft.world.effect.MobEffects; -import org.bukkit.Bukkit; -import org.bukkit.GameMode; -import org.bukkit.Material; -import org.bukkit.Particle; -import org.bukkit.block.Block; -import org.bukkit.craftbukkit.entity.CraftPlayer; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityAirChangeEvent; -import org.bukkit.event.player.PlayerItemConsumeEvent; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; - -public class WaterBreathe implements Listener, PowerProvider { - private static final ArrayList originsExecuting = new ArrayList<>(); - public static ArrayList outofAIR = new ArrayList<>(); - protected static ResourceLocation powerReference = OriginsPaper.originIdentifier("water_breathing"); - private static final String cachedPowerRefrenceString = powerReference.toString(); - - public static boolean isInBreathableWater(@NotNull Player player) { - Block block = player.getEyeLocation().getBlock(); - Material material = block.getType(); - if (block.getType().equals(Material.WATER)) { - return true; - } else return player.isInWater() && !material.equals(Material.AIR); - } - - public static void start() { - WaterBreathe waterBreathe = new WaterBreathe(); - Bukkit.getScheduler().runTaskTimer(OriginsPaper.getPlugin(), () -> waterBreathe.tick(), 0, 20); - } - - @EventHandler - public void interuptMinecraft(@NotNull EntityAirChangeEvent e) { - if (e.getEntity() instanceof Player player) { - if (PowerHolderComponent.hasPower(player, cachedPowerRefrenceString)) { - if (!originsExecuting.contains(player)) { - e.setCancelled(true); - e.setAmount(0); - } - } - } - } - - @EventHandler - public void drinkWater(@NotNull PlayerItemConsumeEvent e) { - if (PowerHolderComponent.hasPower(e.getPlayer(), cachedPowerRefrenceString) && e.getItem().getType().equals(Material.POTION)) { - originsExecuting.add(e.getPlayer()); - e.getPlayer().setRemainingAir(e.getPlayer().getRemainingAir() + 60); - originsExecuting.remove(e.getPlayer()); - } - } - - @Override - public void tick(@NotNull Player p) { - if (p.getGameMode().equals(GameMode.CREATIVE) || p.getGameMode().equals(GameMode.SPECTATOR)) return; - if (PowerHolderComponent.hasPower(p, cachedPowerRefrenceString)) { - originsExecuting.add(p); - int addonAir = 4; - int lowestAir = -10; - int tickDownAir = 1; - boolean shouldDamage = true; - if (((CraftPlayer) (p)).getHandle().hasEffect(MobEffects.WATER_BREATHING) - || p.isInRain() - || ((CraftPlayer) p).getHandle().hasEffect(MobEffects.CONDUIT_POWER) - || p.getGameMode().equals(GameMode.SPECTATOR) - || p.getGameMode().equals(GameMode.CREATIVE) - ) { - addonAir = 0; - tickDownAir = 0; - shouldDamage = false; - } - if (isInBreathableWater(p)) { - if (p.getRemainingAir() < 290) { - p.setRemainingAir(p.getRemainingAir() + addonAir); - } else { - p.setRemainingAir(310); - } - outofAIR.remove(p); - } else { - int remainingAir = p.getRemainingAir(); - if (remainingAir <= 5) { - p.setRemainingAir(lowestAir); - outofAIR.add(p); - } else { - p.setRemainingAir(remainingAir - tickDownAir); - outofAIR.remove(p); - } - } - if (!shouldDamage) { - outofAIR.remove(p); - } else if (outofAIR.contains(p)) { - if (p.getRemainingAir() > 20) { - outofAIR.remove(p); - } - } - originsExecuting.remove(p); - } - } - - public void tick() { - for (Player p : Bukkit.getOnlinePlayers()) { - ServerPlayer player = ((CraftPlayer) p).getHandle(); - if (outofAIR.contains(p)) { - int remainingAir = p.getRemainingAir(); - if (remainingAir <= 5) { - for (int i = 0; i < 8; ++i) { - p.spawnParticle(Particle.BUBBLE, player.getRandomX(0.5), player.getEyeY() + player.random.nextGaussian() * 0.08D, player.getRandomZ(0.5), 1); - } - - float finalDmg = 1; - if (p.getInventory().getHelmet() != null) { - if (p.getInventory().getHelmet().getType() == Material.TURTLE_HELMET) { - finalDmg = 0.5f; - } else if (p.getInventory().getHelmet().containsEnchantment(Enchantment.RESPIRATION)) { - finalDmg = 0.5f; - } - } - DamageType dmgType = Util.DAMAGE_REGISTRY.get(ResourceLocation.fromNamespaceAndPath("origins", "no_water_for_gills")); - ((CraftPlayer) p).getHandle().hurt(Util.getDamageSource(dmgType), finalDmg); - } - } - } - } -} diff --git a/origins/src/main/java/io/github/dueris/originspaper/storage/PowerHolderComponent.java b/origins/src/main/java/io/github/dueris/originspaper/storage/PowerHolderComponent.java index 3d587dbaf..d4f6c896b 100644 --- a/origins/src/main/java/io/github/dueris/originspaper/storage/PowerHolderComponent.java +++ b/origins/src/main/java/io/github/dueris/originspaper/storage/PowerHolderComponent.java @@ -7,9 +7,6 @@ import io.github.dueris.originspaper.origin.OriginLayer; import io.github.dueris.originspaper.power.MultiplePower; import io.github.dueris.originspaper.power.PowerType; -import io.github.dueris.originspaper.power.SimplePower; -import io.github.dueris.originspaper.power.provider.OriginSimpleContainer; -import io.github.dueris.originspaper.power.provider.PowerProvider; import io.github.dueris.originspaper.registry.Registries; import io.github.dueris.originspaper.screen.ScreenNavigator; import io.github.dueris.originspaper.util.BstatsMetrics; @@ -244,11 +241,6 @@ public static void unloadPower(Player player, PowerType power, OriginLayer layer if (power != null) { if (isNew) { power.onRemoved(((CraftPlayer) player).getHandle()); - - if (power instanceof SimplePower simplePower) { - PowerProvider provider = OriginSimpleContainer.getFromSimple(simplePower); - provider.onRemove(player); - } } PlayerPowerRepository.getOrCreateRepo(getNMS(player)).removePower(power, layer); power.removePlayer(((CraftPlayer) player).getHandle()); diff --git a/origins/src/main/java/io/github/dueris/originspaper/util/Util.java b/origins/src/main/java/io/github/dueris/originspaper/util/Util.java index d39245f36..61e237fc5 100644 --- a/origins/src/main/java/io/github/dueris/originspaper/util/Util.java +++ b/origins/src/main/java/io/github/dueris/originspaper/util/Util.java @@ -612,6 +612,26 @@ public static String readResource(String resourcePath) { } } + public static Predicate combineOr(Predicate a, Predicate b) { + if (a == null) { + return b; + } + if (b == null) { + return a; + } + return a.or(b); + } + + public static Predicate combineAnd(Predicate a, Predicate b) { + if (a == null) { + return b; + } + if (b == null) { + return a; + } + return a.and(b); + } + public static boolean attemptToTeleport(Entity entity, ServerLevel serverWorld, double destX, double destY, double destZ, double offsetX, double offsetY, double offsetZ, double areaHeight, boolean loadedChunksOnly, Heightmap.Types heightmap, Predicate landingBlockCondition, Predicate landingCondition) { BlockPos.MutableBlockPos blockPos = BlockPos.containing(destX, destY, destZ).mutable(); diff --git a/origins/src/main/java/io/github/dueris/originspaper/util/entity/PlayerManager.java b/origins/src/main/java/io/github/dueris/originspaper/util/entity/PlayerManager.java index d1b918fc8..3b6253c91 100644 --- a/origins/src/main/java/io/github/dueris/originspaper/util/entity/PlayerManager.java +++ b/origins/src/main/java/io/github/dueris/originspaper/util/entity/PlayerManager.java @@ -22,7 +22,6 @@ import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; import org.bukkit.scheduler.BukkitRunnable; -import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; diff --git a/origins/src/main/resources/data/origins/origins/power/shulker_inventory.json b/origins/src/main/resources/data/origins/origins/power/shulker_inventory.json index feed776d7..32c61dba8 100644 --- a/origins/src/main/resources/data/origins/origins/power/shulker_inventory.json +++ b/origins/src/main/resources/data/origins/origins/power/shulker_inventory.json @@ -1,6 +1,6 @@ { "type": "origins:inventory", - "title": "container.shulker_inventory_power", + "title": "Shulker Inventory", "drop_on_death": false, "key": { "key": "key.origins.primary_active",