diff --git a/.gitignore b/.gitignore index 189e9859..97018307 100644 --- a/.gitignore +++ b/.gitignore @@ -39,4 +39,5 @@ old_changelog.txt !updateResources.bat /.apt_generated_tests/ -model \ No newline at end of file +model +/.run diff --git a/build.gradle b/build.gradle index 0e18ece0..025f719f 100644 --- a/build.gradle +++ b/build.gradle @@ -74,11 +74,10 @@ dependencies { annotationProcessor 'org.ow2.asm:asm-util:7.2' // These are 1.20.1 dependencies - compileOnly fg.deobf('generic:curios:forge-5.2.0-beta.3+1.20.1') - compileOnly fg.deobf('generic:Patchouli:1.20.1-81-FORGE') - compileOnly fg.deobf('generic:caelus:forge-3.1.0+1.20') - compileOnly fg.deobf('generic:jei:1.18.2-forge-10.2.1.283-stripped') - compileOnly fg.deobf('generic:WorldNameRandomizer:FORGE-1.19.2-v1.5.0') + implementation fg.deobf('generic:curios:forge-5.2.0-beta.3+1.20.1') + implementation fg.deobf('generic:Patchouli:1.20.1-81-FORGE') + implementation fg.deobf('generic:caelus:forge-3.1.0+1.20') + implementation fg.deobf('generic:jei:1.18.2-forge-10.2.1.283-stripped') // These are 1.19 dependencies //compileOnly fg.deobf('generic:curios:forge-1.19.4-5.1.5.3') diff --git a/gradle.properties b/gradle.properties index fb3c93d2..235ca6a1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # Gradle org.gradle.jvmargs=-Xmx4G -Xms4G -org.gradle.daemon=false +#org.gradle.daemon=false # The Acknowledgment Edition the_acknowledgment_edition=20 @@ -17,7 +17,7 @@ mod_author=Aizistral mod_description=This mod is designed to provide tools that will aid you in exploring seemingly endless reaches of Minecraft's worlds. As well as new resources, powerful gear and ancient relics - to reward you for doing so. Despite revolving around themes of arcane and mystery, Enigmatic Legacy doesn't stray too far away from what vanilla has to offer, instead attempting to expand upon it's mechanics and fill in the holes left open. -mod_credits=Terraria and some of it's mods, for inspiring my creations functionally and visually; Minecraft Dungeons, for blocks and models that make me question why we don't have anything like this in Minecraft itself; Botania and it's creator known as Vazkii, for some basic code I could conveniently borrow instead of having to re-invent the wheel; frdovahkick, for amazing work over some of the textures in the mod; SkySem, for some models and textures created on-comission; SoulRacer65, for some textures overhauls and entirely new textures. +mod_credits=Terraria and some of it's mods, for inspiring my creations functionally and visually; Minecraft Dungeons, for blocks and models that make me question why we don't have anything like this in Minecraft itself; Botania and it's creator known as Vazkii, for some basic code I could conveniently borrow instead of having to re-invent the wheel; frdovahkick, for amazing work over some of the textures in the mod; SkySem, for some models and textures created on-comission; SoulRacer65, for some textures overhauls and entirely new textures; Cartoony Clangs (hit with spade)_16bit.wav by Timbre -- https://freesound.org/s/91696/ -- License: Attribution NonCommercial 4.0; Shovel Thwack 1.wav by snardin42 -- https://freesound.org/s/73200/ -- License: Creative Commons 0 mod_icon=EL_logo.png mod_license=Enigmatic Legacy License diff --git a/src/main/java/com/aizistral/enigmaticlegacy/EnigmaticLegacy.java b/src/main/java/com/aizistral/enigmaticlegacy/EnigmaticLegacy.java index d35ecb78..0a8cd000 100644 --- a/src/main/java/com/aizistral/enigmaticlegacy/EnigmaticLegacy.java +++ b/src/main/java/com/aizistral/enigmaticlegacy/EnigmaticLegacy.java @@ -437,7 +437,6 @@ private void onServerStarted(ServerStartedEvent event) { /** * Alright boys, it's cleanup time! - * @param event */ public void performCleanup() { diff --git a/src/main/java/com/aizistral/enigmaticlegacy/api/materials/EnigmaticMaterials.java b/src/main/java/com/aizistral/enigmaticlegacy/api/materials/EnigmaticMaterials.java index 99bbb829..491090a4 100644 --- a/src/main/java/com/aizistral/enigmaticlegacy/api/materials/EnigmaticMaterials.java +++ b/src/main/java/com/aizistral/enigmaticlegacy/api/materials/EnigmaticMaterials.java @@ -4,6 +4,7 @@ import java.util.Objects; import java.util.function.Supplier; +import com.aizistral.enigmaticlegacy.items.EldritchPan; import com.aizistral.etherium.core.IEtheriumConfig; import net.minecraft.resources.ResourceLocation; @@ -19,8 +20,9 @@ */ public enum EnigmaticMaterials implements Tier { - FORBIDDENAXE(0, 2000, 6.0F, 3.0F, 16, () -> Ingredient.EMPTY), - ENDERSLAYER(0, 2000, 6.0F, 3.0F, 16, () -> Ingredient.of(Blocks.OBSIDIAN)), + ELDRITCH_PAN(0, 4000, 6.0F, 3.0F, 24, EldritchPan::getRepairMaterial), + FORBIDDEN_AXE(0, 2000, 6.0F, 3.0F, 16, () -> Ingredient.EMPTY), + ENDER_SLAYER(0, 2000, 6.0F, 3.0F, 16, () -> Ingredient.of(Blocks.OBSIDIAN)), ETHERIUM(5, 3000, 8.0F, 5.0F, 32, () -> getEtheriumConfig().getRepairMaterial()), CREATION(6, 10000, 32.0F, 0.0F, 40, () -> Ingredient.EMPTY); diff --git a/src/main/java/com/aizistral/enigmaticlegacy/blocks/BlockEndAnchor.java b/src/main/java/com/aizistral/enigmaticlegacy/blocks/BlockEndAnchor.java index b19a64c7..0a17514f 100644 --- a/src/main/java/com/aizistral/enigmaticlegacy/blocks/BlockEndAnchor.java +++ b/src/main/java/com/aizistral/enigmaticlegacy/blocks/BlockEndAnchor.java @@ -80,6 +80,9 @@ public ItemStack execute(BlockSource source, ItemStack stack) { stack.shrink(1); this.setSuccess(true); return stack; + } else { + this.setSuccess(false); + return stack; } } diff --git a/src/main/java/com/aizistral/enigmaticlegacy/effects/GrowingBloodlustEffect.java b/src/main/java/com/aizistral/enigmaticlegacy/effects/GrowingBloodlustEffect.java new file mode 100644 index 00000000..9bd542f2 --- /dev/null +++ b/src/main/java/com/aizistral/enigmaticlegacy/effects/GrowingBloodlustEffect.java @@ -0,0 +1,74 @@ +package com.aizistral.enigmaticlegacy.effects; + +import com.aizistral.enigmaticlegacy.api.generic.SubscribeConfig; +import com.aizistral.omniconfig.Configuration; +import com.aizistral.omniconfig.wrappers.Omniconfig; +import com.aizistral.omniconfig.wrappers.OmniconfigWrapper; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectCategory; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.entity.ai.attributes.Attributes; + +public class GrowingBloodlustEffect extends MobEffect { + public static Omniconfig.DoubleParameter damageBoost = null; + public static Omniconfig.DoubleParameter lifestealBoost = null; + public static Omniconfig.DoubleParameter healthLossLimit = null; + public static Omniconfig.IntParameter healthLossTicks = null; + public static Omniconfig.IntParameter ticksPerLevel = null; + + @SubscribeConfig(receiveClient = true) + public static void onConfig(OmniconfigWrapper builder) { + builder.pushPrefix("GrowingBloodlust"); + + if (builder.config.getSidedType() != Configuration.SidedConfigType.CLIENT) { + damageBoost = builder + .comment("Damage boost granted by the Growing Bloodlust, per level of effect.") + .max(100) + .getDouble("DamageBoost", 0.05); + + lifestealBoost = builder + .comment("Lifesteal granted by the Growing Bloodlust, per level of effect.") + .max(100) + .getDouble("LifestealBoost", 0.025); + + healthLossTicks = builder + .comment("How often the player loses 1 HP at level one of Growing Bloodlust, in ticks.") + .getInt("HealthLossTicks", 160); + + healthLossLimit = builder + .comment("How much health Growing Bloodlust leaves the player with, as a fraction of max health.") + .getDouble("HealthLossLimit", 0.3); + + ticksPerLevel = builder + .comment("How lock the The Voracious Pan needs to be held, in ticks, to increase the strength " + + "of the Growing Bloodlust effect by one level.") + .getInt("TicksPerLevel", 300); + } + + builder.popPrefix(); + } + + public GrowingBloodlustEffect() { + super(MobEffectCategory.BENEFICIAL, 0xC30018); + this.addAttributeModifier(Attributes.ATTACK_DAMAGE, "d88f6930-fefb-4bf7-a418-f368458355ff", + damageBoost.getValue(), AttributeModifier.Operation.MULTIPLY_TOTAL); + } + + @Override + public void applyEffectTick(LivingEntity living, int amplifier) { + if (living instanceof ServerPlayer player && !player.isCreative() && !player.isSpectator()) { + if ((player.getHealth() / player.getMaxHealth()) > healthLossLimit.getValue()) { + player.setHealth(player.getHealth() - 1); + } + } + } + + @Override + public boolean isDurationEffectTick(int duration, int amplifier) { + int period = healthLossTicks.getValue() / (1 + amplifier); + return duration % period == 0; + } + +} diff --git a/src/main/java/com/aizistral/enigmaticlegacy/effects/GrowingHungerEffect.java b/src/main/java/com/aizistral/enigmaticlegacy/effects/GrowingHungerEffect.java new file mode 100644 index 00000000..a341ae89 --- /dev/null +++ b/src/main/java/com/aizistral/enigmaticlegacy/effects/GrowingHungerEffect.java @@ -0,0 +1,69 @@ +package com.aizistral.enigmaticlegacy.effects; + +import com.aizistral.enigmaticlegacy.api.generic.SubscribeConfig; +import com.aizistral.omniconfig.Configuration; +import com.aizistral.omniconfig.wrappers.Omniconfig; +import com.aizistral.omniconfig.wrappers.OmniconfigWrapper; +import com.google.common.collect.ImmutableList; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.damagesource.DamageType; +import net.minecraft.world.damagesource.DamageTypes; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectCategory; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.entity.ai.attributes.Attributes; + +import java.util.List; +import java.util.Map; + +public class GrowingHungerEffect extends MobEffect { + public static Omniconfig.DoubleParameter damageBoost = null; + public static Omniconfig.DoubleParameter exhaustionGain = null; + public static Omniconfig.IntParameter ticksPerLevel = null; + + @SubscribeConfig(receiveClient = true) + public static void onConfig(OmniconfigWrapper builder) { + builder.pushPrefix("GrowingHunger"); + + if (builder.config.getSidedType() != Configuration.SidedConfigType.CLIENT) { + damageBoost = builder + .comment("Damage boost granted by the Growing Hunger, per level of effect.") + .max(100) + .getDouble("DamageBoost", 0.1); + + exhaustionGain = builder + .comment("Exhaustion applied by Growing Hunger every 4 ticks, per level of effect.") + .getDouble("ExhaustionGain", 0.5); + + ticksPerLevel = builder + .comment("How lock the The Voracious Pan needs to be held, in ticks, to increase the strength " + + "of the Growing Hunger effect by one level.") + .getInt("TicksPerLevel", 300); + } + + builder.popPrefix(); + } + + public GrowingHungerEffect() { + super(MobEffectCategory.BENEFICIAL, 0xBD1BE5); + this.addAttributeModifier(Attributes.ATTACK_DAMAGE, "c281d54f-3277-4e4c-899e-c27f4f697b24", + damageBoost.getValue(), AttributeModifier.Operation.MULTIPLY_TOTAL); + } + + @Override + public void applyEffectTick(LivingEntity living, int amplifier) { + if (living instanceof ServerPlayer player) { + player.causeFoodExhaustion((float) (exhaustionGain.getValue() * (1 + amplifier))); + } + } + + @Override + public boolean isDurationEffectTick(int duration, int amplifier) { + return duration % 4 == 0; + } + +} \ No newline at end of file diff --git a/src/main/java/com/aizistral/enigmaticlegacy/handlers/EnigmaticEventHandler.java b/src/main/java/com/aizistral/enigmaticlegacy/handlers/EnigmaticEventHandler.java index 1651b9da..23dce1ec 100644 --- a/src/main/java/com/aizistral/enigmaticlegacy/handlers/EnigmaticEventHandler.java +++ b/src/main/java/com/aizistral/enigmaticlegacy/handlers/EnigmaticEventHandler.java @@ -12,6 +12,13 @@ import java.util.UUID; import java.util.WeakHashMap; +import com.aizistral.enigmaticlegacy.effects.GrowingBloodlustEffect; +import com.aizistral.enigmaticlegacy.effects.GrowingHungerEffect; +import com.aizistral.enigmaticlegacy.items.*; +import com.google.common.collect.ImmutableList; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.item.crafting.SmeltingRecipe; import org.apache.commons.lang3.tuple.Triple; import com.aizistral.enigmaticlegacy.EnigmaticLegacy; @@ -38,27 +45,6 @@ import com.aizistral.enigmaticlegacy.helpers.ItemLoreHelper; import com.aizistral.enigmaticlegacy.helpers.ItemNBTHelper; import com.aizistral.enigmaticlegacy.helpers.PotionHelper; -import com.aizistral.enigmaticlegacy.items.AngelBlessing; -import com.aizistral.enigmaticlegacy.items.AvariceScroll; -import com.aizistral.enigmaticlegacy.items.BerserkEmblem; -import com.aizistral.enigmaticlegacy.items.BlazingCore; -import com.aizistral.enigmaticlegacy.items.CosmicScroll; -import com.aizistral.enigmaticlegacy.items.CursedRing; -import com.aizistral.enigmaticlegacy.items.CursedScroll; -import com.aizistral.enigmaticlegacy.items.EnderSlayer; -import com.aizistral.enigmaticlegacy.items.EnigmaticAmulet; -import com.aizistral.enigmaticlegacy.items.EyeOfNebula; -import com.aizistral.enigmaticlegacy.items.ForbiddenAxe; -import com.aizistral.enigmaticlegacy.items.ForbiddenFruit; -import com.aizistral.enigmaticlegacy.items.HunterGuidebook; -import com.aizistral.enigmaticlegacy.items.InfernalShield; -import com.aizistral.enigmaticlegacy.items.MiningCharm; -import com.aizistral.enigmaticlegacy.items.MonsterCharm; -import com.aizistral.enigmaticlegacy.items.OceanStone; -import com.aizistral.enigmaticlegacy.items.RevelationTome; -import com.aizistral.enigmaticlegacy.items.TheInfinitum; -import com.aizistral.enigmaticlegacy.items.TheTwist; -import com.aizistral.enigmaticlegacy.items.VoidPearl; import com.aizistral.enigmaticlegacy.items.EnigmaticAmulet.AmuletColor; import com.aizistral.enigmaticlegacy.items.generic.ItemSpellstoneCurio; import com.aizistral.enigmaticlegacy.mixin.AccessorAbstractArrowEntity; @@ -293,6 +279,8 @@ import top.theillusivec4.curios.api.type.capability.ICurio.DropRule; import top.theillusivec4.curios.client.gui.CuriosScreen; +import javax.tools.Tool; + /** * Generic event handler of the whole mod. * @author Integral @@ -480,6 +468,47 @@ public void onCommandRegistry(RegisterCommandsEvent event) { .executes(EnigmaticEventHandler::handleSetRingTime))); event.getDispatcher().register(builder); + + builder = Commands.literal("setnoringtime").requires((source) -> source.hasPermission(4)) + .then(Commands.argument("player", EntityArgument.player()) + .then(Commands.argument("ticks", LongArgumentType.longArg(0)) + .executes(EnigmaticEventHandler::handleSetNoRingTime))); + + event.getDispatcher().register(builder); + + builder = Commands.literal("getnoringtime").requires((source) -> source.hasPermission(4)) + .then(Commands.argument("player", EntityArgument.player()) + .executes(EnigmaticEventHandler::handleGetNoRingTime)); + + event.getDispatcher().register(builder); + } + + private static int handleGetNoRingTime(CommandContext source) throws CommandSyntaxException { + ServerPlayer player = EntityArgument.getPlayer(source, "player"); + IPlaytimeCounter counter = IPlaytimeCounter.get(player); + String name = player.getDisplayName().getString(); + long time = counter.getTimeWithoutCurses(); + String percent = SuperpositionHandler.getNoSufferingTime(player); + + Component reply = Component.literal(name + " is not bearing the Seven Curses for " + time + + " ticks, or " + percent + " of their time in this world.").withStyle(ChatFormatting.GREEN); + source.getSource().sendSuccess(() -> reply, true); + return Command.SINGLE_SUCCESS; + } + + private static int handleSetNoRingTime(CommandContext source) throws CommandSyntaxException { + ServerPlayer player = EntityArgument.getPlayer(source, "player"); + long ticks = LongArgumentType.getLong(source, "ticks"); + IPlaytimeCounter counter = IPlaytimeCounter.get(player); + String name = player.getDisplayName().getString(); + + counter.setTimeWithoutCurses(ticks); + ticks = counter.getTimeWithoutCurses(); + + Component reply = Component.literal(name + "'s time without Seven Curses was set to " + ticks + + " ticks.").withStyle(ChatFormatting.GREEN); + source.getSource().sendSuccess(() -> reply, true); + return Command.SINGLE_SUCCESS; } private static int handleGetRingTime(CommandContext source) throws CommandSyntaxException { @@ -971,7 +1000,7 @@ private void syncPlayTime(Player player) { } @SubscribeEvent - public void onPlayerTick(PlayerChangedDimensionEvent event) { + public void onPlayerTravel(PlayerChangedDimensionEvent event) { if (event.getEntity() instanceof ServerPlayer player) { LAST_SOUL_COMPASS_UPDATE.remove(player); @@ -1145,7 +1174,7 @@ public void onPlayerTick(LivingTickEvent event) { } */ - if (player instanceof ServerPlayer) { + if (player instanceof ServerPlayer serverPlayer) { /* * Handler for players' spellstone cooldowns. @@ -1197,6 +1226,38 @@ public void onPlayerTick(LivingTickEvent event) { } } } + + /* + * Handle Growing Hunger application. + */ + + List handItems = ImmutableList.of(player.getMainHandItem()/*, player.getOffhandItem()*/); + + if (handItems.stream().anyMatch(s -> s.is(EnigmaticItems.ELDRITCH_PAN))) { + int currentTicks = EldritchPan.HOLDING_DURATIONS.getOrDefault(player, 0); + + if (SuperpositionHandler.cannotHunger(player)) { + int bloodlustAmplifier = currentTicks / GrowingBloodlustEffect.ticksPerLevel.getValue(); + + bloodlustAmplifier = Math.min(bloodlustAmplifier, 9); + + player.addEffect(new MobEffectInstance(EnigmaticEffects.GROWING_BLOODLUST, + MobEffectInstance.INFINITE_DURATION, bloodlustAmplifier, true, true)); + } else { + int hungerAmplifier = currentTicks / GrowingHungerEffect.ticksPerLevel.getValue(); + + hungerAmplifier = Math.min(hungerAmplifier, 9); + + player.addEffect(new MobEffectInstance(EnigmaticEffects.GROWING_HUNGER, + MobEffectInstance.INFINITE_DURATION, hungerAmplifier, true, true)); + } + + EldritchPan.HOLDING_DURATIONS.put(player, currentTicks + 1); + } else { + EldritchPan.HOLDING_DURATIONS.put(player, 0); + player.removeEffect(EnigmaticEffects.GROWING_HUNGER); + player.removeEffect(EnigmaticEffects.GROWING_BLOODLUST); + } } } @@ -1309,9 +1370,22 @@ public void onConfirmedDeath(LivingDeathEvent event) { SuperpositionHandler.setPersistentInteger(player, "TimesKilledWither", killedWither); } } + + if (event.getSource().getDirectEntity() instanceof ServerPlayer attacker) { + ItemStack weapon = attacker.getMainHandItem(); + + if (weapon.is(EnigmaticItems.ELDRITCH_PAN)) { + ResourceLocation killedType = ForgeRegistries.ENTITY_TYPES.getKey(event.getEntity().getType()); + + if (EldritchPan.addKillIfNotPresent(weapon, killedType)) { + attacker.sendSystemMessage(Component.translatable("message.enigmaticlegacy.eldritch_pan_buff") + .withStyle(ChatFormatting.GOLD)); + } + } + } } - @SubscribeEvent + @SubscribeEvent public void onCurioDrops(DropRulesEvent event) { event.addOverride(stack -> stack.getEnchantmentLevel(EnigmaticEnchantments.ETERNAL_BINDING) > 0, DropRule.ALWAYS_KEEP); @@ -1379,6 +1453,60 @@ private boolean isThereLava(Level world, BlockPos pos) { return false; } +// @OnlyIn(Dist.CLIENT) +// @SubscribeEvent(priority = EventPriority.HIGHEST) +// public void onEarlyTooltip(ItemTooltipEvent event) { +// if (event.getItemStack().is(EnigmaticItems.ELDRITCH_PAN)) { +// List modifierIndexes = new ArrayList<>(); +// +// for (int i = 0; i < event.getToolTip().size(); i++) { +// Component line = event.getToolTip().get(i); +// +// if (line.getContents() instanceof TranslatableContents contents) { +// if (contents.getKey().startsWith("item.modifiers.") +// || contents.getKey().startsWith("attribute.modifier.")) { +// modifierIndexes.add(i); +// } +// } +// } +// +// List modifierIndexesCopy = new ArrayList<>(modifierIndexes); +// +// for (int i = 0; i < modifierIndexesCopy.size(); i++) { +// int prevIndex = i - 1; +// int currentValue = modifierIndexesCopy.get(i); +// +// if (prevIndex < 0) { +// modifierIndexes.add(currentValue - 1); +// continue; +// } +// +// int prevValue = modifierIndexesCopy.get(prevIndex); +// +// if (currentValue - prevValue > 1) { +// modifierIndexes.add(currentValue - 1); +// } +// } +// +// //modifierIndexes.stream().map(event.getToolTip()::get).forEach(event.getToolTip()::remove); +// +// List removedLines = new ArrayList<>(); +// +// try { +// for (int index : modifierIndexes) { +// Component line = event.getToolTip().get(index); +// removedLines.add(line); +// } +// +// for (Component line : removedLines) { +// event.getToolTip().remove(line); +// } +// } catch (Throwable ex) { +// ex.printStackTrace(); +// } +// } +// } + @SubscribeEvent(priority = EventPriority.HIGHEST) public void onLivingDeath(LivingDeathEvent event) { @@ -1793,9 +1921,55 @@ public void onEntityDamaged(LivingDamageEvent event) { } } + if (player.getMainHandItem() != null && player.getMainHandItem().getItem() == EnigmaticItems.ELDRITCH_PAN) { + if (SuperpositionHandler.isTheWorthyOne(player)) { + lifesteal += event.getAmount() * EldritchPan.lifeSteal.getValue(); + } + } + + if (player.hasEffect(EnigmaticEffects.GROWING_BLOODLUST)) { + int amplifier = 1 + player.getEffect(EnigmaticEffects.GROWING_BLOODLUST).getAmplifier(); + lifesteal += event.getAmount() * (GrowingBloodlustEffect.lifestealBoost.getValue() * amplifier); + } + if (lifesteal > 0) { player.heal(lifesteal); } + + float hungersteal = 0F; + + if (player.getMainHandItem() != null && player.getMainHandItem().getItem() == EnigmaticItems.ELDRITCH_PAN) { + if (SuperpositionHandler.isTheWorthyOne(player)) { + hungersteal += EldritchPan.hungerSteal.getValue(); + } + } + + if (hungersteal > 0) { + boolean noHunger = SuperpositionHandler.cannotHunger(player); + + if (event.getEntity() instanceof ServerPlayer victim) { + FoodData victimFood = victim.getFoodData(); + FoodData attackerFood = player.getFoodData(); + + int foodSteal = Math.min((int) Math.ceil(hungersteal), victimFood.getFoodLevel()); + float saturationSteal = Math.min(hungersteal / 5F, victimFood.getSaturationLevel()); + + victimFood.setSaturation(victimFood.getSaturationLevel() - saturationSteal); + victimFood.setFoodLevel(victimFood.getFoodLevel() - foodSteal); + + if (noHunger) { + player.heal((float) foodSteal / 2); + } else { + attackerFood.eat(foodSteal, saturationSteal); + } + } else { + if (noHunger) { + player.heal(hungersteal / 2); + } else { + player.getFoodData().eat((int) Math.ceil(hungersteal), hungersteal / 5F); + } + } + } } } @@ -1937,6 +2111,10 @@ public void onEntityHurt(LivingHurtEvent event) { player.addEffect(new MobEffectInstance(MobEffects.DIG_SLOWDOWN, 300, 3, false, true)); player.addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 100, 3, false, true)); } + } else if (mainhandStack.is(EnigmaticItems.ELDRITCH_PAN)) { + if (!SuperpositionHandler.isTheWorthyOne(player)) { + event.setCanceled(true); + } } else if (mainhandStack.is(EnigmaticItems.ENDER_SLAYER)) { if (SuperpositionHandler.isTheCursedOne(player)) { if (EnigmaticItems.ENDER_SLAYER.isEndDweller(event.getEntity())) { @@ -2094,7 +2272,9 @@ public void onEntityHurt(LivingHurtEvent event) { boolean bypass = false; if (event.getSource().getDirectEntity() == player) - if (player.getMainHandItem().getItem() == EnigmaticItems.THE_TWIST || player.getMainHandItem().getItem() == EnigmaticItems.THE_INFINITUM) { + if (player.getMainHandItem().getItem() == EnigmaticItems.THE_TWIST + || player.getMainHandItem().getItem() == EnigmaticItems.THE_INFINITUM + || player.getMainHandItem().getItem() == EnigmaticItems.ELDRITCH_PAN) { // Don't do worthiness check since event is gonna be canceled for non-worthy already bypass = true; } @@ -2480,6 +2660,37 @@ public void onLivingDrops(LivingDropsEvent event) { @SubscribeEvent(priority = EventPriority.LOWEST) public void onLivingDropsLowest(LivingDropsEvent event) { + Level level = event.getEntity().level(); + + /* + * Eldritch Pan cooking logic. + */ + + if (event.getSource().getDirectEntity() instanceof ServerPlayer player) + if (SuperpositionHandler.isTheWorthyOne(player)) + if (player.getMainHandItem().is(EnigmaticItems.ELDRITCH_PAN) + || player.getOffhandItem().is(EnigmaticItems.ELDRITCH_PAN)) + for (ItemEntity drop : new ArrayList<>(event.getDrops())) { + ItemStack stack = drop.getItem(); + Optional optional = level.getRecipeManager().getRecipeFor( + RecipeType.SMELTING, new SimpleContainer(stack), level); + + optional.ifPresent(recipe -> { + ItemStack result = recipe.getResultItem(level.registryAccess()); + + if (!result.isEmpty()) { + ItemStack cooked = result.copyWithCount(stack.getCount() * result.getCount()); + + event.getDrops().remove(drop); + this.addDrop(event, cooked); + } + }); + } + + /* + * Escape Scroll logic. + */ + if (event.getEntity() instanceof ServerPlayer player) { CompoundTag deathLocation = new CompoundTag(); deathLocation.putDouble("x", player.getX()); @@ -2576,7 +2787,7 @@ public void onLivingDropsLowest(LivingDropsEvent event) { } /* - * Unique drops for Ring of the Seven Curses. + * Ender Slayer XP conversion. */ if (event.isRecentlyHit() && event.getSource() != null && event.getSource().getEntity() instanceof Player && SuperpositionHandler.isTheCursedOne((Player) event.getSource().getEntity())) { diff --git a/src/main/java/com/aizistral/enigmaticlegacy/handlers/SuperpositionHandler.java b/src/main/java/com/aizistral/enigmaticlegacy/handlers/SuperpositionHandler.java index aa2c02e5..cfe21b1b 100644 --- a/src/main/java/com/aizistral/enigmaticlegacy/handlers/SuperpositionHandler.java +++ b/src/main/java/com/aizistral/enigmaticlegacy/handlers/SuperpositionHandler.java @@ -21,6 +21,16 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import com.aizistral.enigmaticlegacy.items.*; +import net.minecraft.core.particles.ItemParticleOption; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.world.Difficulty; +import net.minecraft.world.entity.projectile.Fireball; +import net.minecraft.world.entity.projectile.LargeFireball; +import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.food.FoodData; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.gameevent.GameEvent; import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.commons.lang3.tuple.ImmutableTriple; import org.joml.Matrix4f; @@ -34,9 +44,6 @@ import com.aizistral.enigmaticlegacy.api.quack.IProperShieldUser; import com.aizistral.enigmaticlegacy.config.OmniconfigHandler; import com.aizistral.enigmaticlegacy.helpers.AdvancedSpawnLocationHelper; -import com.aizistral.enigmaticlegacy.items.GolemHeart; -import com.aizistral.enigmaticlegacy.items.InfernalShield; -import com.aizistral.enigmaticlegacy.items.TheAcknowledgment; import com.aizistral.enigmaticlegacy.items.generic.ItemSpellstoneCurio; import com.aizistral.enigmaticlegacy.objects.DimensionalPosition; import com.aizistral.enigmaticlegacy.objects.EnigmaticTransience; @@ -154,6 +161,9 @@ import top.theillusivec4.curios.api.type.inventory.IDynamicStackHandler; import top.theillusivec4.curios.api.type.util.ICuriosHelper; +import java.math.BigDecimal; +import java.math.RoundingMode; + /** * The core and vessel for most most of the handling methods in the Enigmatic Legacy. * @@ -1326,59 +1336,75 @@ public static boolean hasArchitectsFavor(Player player) { public static boolean isTheWorthyOne(Player player) { if (isTheCursedOne(player)) { - var counter = IPlaytimeCounter.get(player); - long timeWithRing = counter.getTimeWithCurses(); - long timeWithoutRing = counter.getTimeWithoutCurses(); - - if (timeWithRing <= 0) - return false; - else if (timeWithoutRing <= 0) - return true; - - return timeWithRing/timeWithoutRing >= 199L; + return getSufferingFraction(player) >= CursedRing.superCursedTime.getValue(); } else return false; } - public static String getSufferingTime(@Nullable Player player) { + public static double getSufferingFraction(@Nullable Player player) { if (player == null) - return "0%"; - else { - var counter = IPlaytimeCounter.get(player); - long timeWithRing = counter.getTimeWithCurses(); - long timeWithoutRing = counter.getTimeWithoutCurses(); + return 0; + + var counter = IPlaytimeCounter.get(player); + long timeWithRing = counter.getTimeWithCurses(); + long timeWithoutRing = counter.getTimeWithoutCurses(); + + if (timeWithRing <= 0) + return 0; + else if (timeWithoutRing <= 0) + return 1; + + if (timeWithRing > 100000 || timeWithoutRing > 100000) { + timeWithRing = timeWithRing / 100; + timeWithoutRing = timeWithoutRing / 100; + if (timeWithRing <= 0) - return "0%"; + return 0; else if (timeWithoutRing <= 0) - return "100%"; + return 1; + } - if (timeWithRing > 100000 || timeWithoutRing > 100000) { - timeWithRing = timeWithRing / 100; - timeWithoutRing = timeWithoutRing / 100; + double total = timeWithRing + timeWithoutRing; + double ringFraction = (timeWithRing / total); + ringFraction = roundToPlaces(ringFraction, 3); - if (timeWithRing <= 0) - return "0%"; - else if (timeWithoutRing <= 0) - return "100%"; - } + return ringFraction; + } - double total = timeWithRing + timeWithoutRing; - double ringPercent = (timeWithRing / total) * 100; - ringPercent = Math.round(ringPercent * 10.0)/10.0; - String text = ""; + public static String getSufferingTime(@Nullable Player player) { + String text = ""; - if (ringPercent - Math.round(ringPercent) == 0) { - text += ((int)ringPercent) + "%"; - } else { - text += ringPercent + "%"; - } + double ringPercent = 100 * getSufferingFraction(player); - if ("99.5%".equals(text) && !isTheWorthyOne(player)) { - text = "99.4%"; - } + ringPercent = roundToPlaces(ringPercent, 1); + if (ringPercent - Math.floor(ringPercent) == 0) { + text += ((int) ringPercent) + "%"; + } else { + text += ringPercent + "%"; + } + + return text; + } + + public static String getNoSufferingTime(@Nullable Player player) { + String text = ""; - return text; + double noRingPercent = 100 * (1.0 - getSufferingFraction(player)); + + if (noRingPercent - Math.floor(noRingPercent) == 0) { + text += ((int) noRingPercent) + "%"; + } else { + text += noRingPercent + "%"; } + + return text; + } + + public static double roundToPlaces(double value, int places) { + BigDecimal bd = new BigDecimal(Double.toString(value)); + bd = bd.setScale(places, RoundingMode.HALF_UP); + + return bd.doubleValue(); } public static float getMissingHealthPool(Player player) { @@ -1720,32 +1746,35 @@ public static boolean canUnequipBoundRelics(Player player) { return player.isCreative() || EnigmaticLegacy.SOUL_OF_THE_ARCHITECT.equals(player.getUUID()); } - public static void onDamageSourceBlocking(LivingEntity blocker, ItemStack useItem, DamageSource source, CallbackInfoReturnable info) { + public static boolean onDamageSourceBlocking(LivingEntity blocker, ItemStack useItem, DamageSource source, + CallbackInfoReturnable info) { if (blocker instanceof Player player && useItem != null) { boolean blocking = ((IProperShieldUser)blocker).isActuallyReallyBlocking(); - if (blocking && useItem.getItem() instanceof InfernalShield) { + if (!blocking) + return false; + + if (useItem.getItem() instanceof InfernalShield) { boolean piercingArrow = false; Entity entity = source.getDirectEntity(); - if (entity instanceof AbstractArrow) { - AbstractArrow abstractarrow = (AbstractArrow)entity; - if (abstractarrow.getPierceLevel() > 0) { + if (entity instanceof AbstractArrow arrow) { + if (arrow.getPierceLevel() > 0) { piercingArrow = true; } } piercingArrow = false; // defend against Piercing... for now - if (!source.is(DamageTypeTags.BYPASSES_SHIELD) && ((IProperShieldUser) blocker).isActuallyReallyBlocking() && !piercingArrow) { + if (!source.is(DamageTypeTags.BYPASSES_SHIELD) && !piercingArrow) { Vec3 sourcePos = source.getSourcePosition(); + if (sourcePos != null) { Vec3 lookVec = blocker.getViewVector(1.0F); Vec3 sourceToSelf = sourcePos.vectorTo(blocker.position()).normalize(); sourceToSelf = new Vec3(sourceToSelf.x, 0.0D, sourceToSelf.z); - if (sourceToSelf.dot(lookVec) < 0.0D) { - info.setReturnValue(true); + if (sourceToSelf.dot(lookVec) < 0.0D) { int strength = -1; if (player.hasEffect(EnigmaticEffects.BLAZING_STRENGTH)) { @@ -1773,15 +1802,72 @@ public static void onDamageSourceBlocking(LivingEntity blocker, ItemStack useIte } } - return; + return true; + } + } + } + } else if (useItem.getItem() instanceof EldritchPan) { + Entity projectile = source.getDirectEntity(); + + if (!(projectile instanceof Projectile)) + return false; + + if (!source.is(DamageTypeTags.BYPASSES_SHIELD)) { + Vec3 sourcePos = source.getSourcePosition(); + + if (sourcePos != null) { + Vec3 lookVec = blocker.getViewVector(1.0F); + Vec3 sourceToSelf = sourcePos.vectorTo(blocker.position()).normalize(); + sourceToSelf = new Vec3(sourceToSelf.x, 0.0D, sourceToSelf.z); + + if (sourceToSelf.dot(lookVec) < 0.0D) { + projectile.kill(); + + FoodData data = player.getFoodData(); + data.eat(4, 0.5F); + + player.level().playSound(null, player.getX(), player.getY(), player.getZ(), + SoundEvents.PLAYER_BURP, SoundSource.PLAYERS, 0.5F, + player.level().random.nextFloat() * 0.1F + 0.9F); + + player.gameEvent(GameEvent.EAT); + + if (projectile instanceof LargeFireball fireball) { + fireball.explosionPower = 0; + } + + if (player.level() instanceof ServerLevel level) { + Vec3 angle = player.getLookAngle(); + angle.multiply(1, 0, 1).normalize().multiply(0.5, 0.5, 0.5); + + level.sendParticles(new ItemParticleOption(ParticleTypes.ITEM, + new ItemStack(Items.FIRE_CHARGE)), player.getX() + angle.x, + player.getY() + player.getEyeHeight() - 0.1, player.getZ() + angle.z, + 10, 0.3D, 0.3D, 0.3D, 0.03D); + } + + return true; } } } + } + } + + return false; + } - info.setReturnValue(false); - return; + public static boolean cannotHunger(@Nullable Player player) { + boolean noHunger = false; + + if (player != null) { + if (EnigmaticItems.FORBIDDEN_FRUIT.haveConsumedFruit(player)) { + noHunger = true; + } else if (player.level().getDifficulty() == Difficulty.PEACEFUL) { + noHunger = true; } } + + return noHunger; } public static > void sortByKey(Map map) { diff --git a/src/main/java/com/aizistral/enigmaticlegacy/helpers/ItemLoreHelper.java b/src/main/java/com/aizistral/enigmaticlegacy/helpers/ItemLoreHelper.java index 7f962084..714ef128 100644 --- a/src/main/java/com/aizistral/enigmaticlegacy/helpers/ItemLoreHelper.java +++ b/src/main/java/com/aizistral/enigmaticlegacy/helpers/ItemLoreHelper.java @@ -7,6 +7,7 @@ import com.aizistral.enigmaticlegacy.EnigmaticLegacy; import com.aizistral.enigmaticlegacy.handlers.SuperpositionHandler; +import com.aizistral.enigmaticlegacy.items.CursedRing; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.nbt.CompoundTag; @@ -47,11 +48,17 @@ public static void indicateWorthyOnesOnly(List list) { format = SuperpositionHandler.isTheWorthyOne(Minecraft.getInstance().player) ? ChatFormatting.GOLD : ChatFormatting.DARK_RED; } + double requiredCurse = SuperpositionHandler.roundToPlaces(100 * CursedRing.superCursedTime.getValue(), 1); + list.add(Component.translatable("tooltip.enigmaticlegacy.worthyOnesOnly1")); - list.add(Component.translatable("tooltip.enigmaticlegacy.worthyOnesOnly2")); + list.add(Component.translatable("tooltip.enigmaticlegacy.worthyOnesOnly2", + Component.literal(requiredCurse + "%").withStyle(ChatFormatting.GOLD)) + .withStyle(format)); list.add(Component.translatable("tooltip.enigmaticlegacy.worthyOnesOnly3")); list.add(Component.translatable("tooltip.enigmaticlegacy.void")); - list.add(Component.translatable("tooltip.enigmaticlegacy.worthyOnesOnly4").withStyle(format).append(Component.literal(" " + SuperpositionHandler.getSufferingTime(player)).withStyle(ChatFormatting.LIGHT_PURPLE))); + list.add(Component.translatable("tooltip.enigmaticlegacy.worthyOnesOnly4") + .withStyle(format).append(Component.literal(" " + SuperpositionHandler.getSufferingTime(player)) + .withStyle(ChatFormatting.LIGHT_PURPLE))); } @OnlyIn(Dist.CLIENT) diff --git a/src/main/java/com/aizistral/enigmaticlegacy/items/CursedRing.java b/src/main/java/com/aizistral/enigmaticlegacy/items/CursedRing.java index f0fd8c90..5b0396bf 100644 --- a/src/main/java/com/aizistral/enigmaticlegacy/items/CursedRing.java +++ b/src/main/java/com/aizistral/enigmaticlegacy/items/CursedRing.java @@ -79,6 +79,8 @@ public class CursedRing extends ItemBaseCurio { public static Omniconfig.BooleanParameter autoEquip; public static final List neutralAngerBlacklist = new ArrayList<>(); + public static Omniconfig.DoubleParameter superCursedTime; + @SubscribeConfig(receiveClient = true) public static void onConfig(OmniconfigWrapper builder) { String prevCategory = builder.getCurrentCategory(); @@ -170,6 +172,10 @@ public static void onConfig(OmniconfigWrapper builder) { .min(8) .getDouble("EndermenRandomportRange", 32); + superCursedTime = builder + .comment("A fraction of time the player should bear the Seven Curses to use Abyssal Artifacts.") + .getDouble("SuperCursedTime", 0.995); + builder.popCategory(); builder.pushCategory("Save the Bees", "This category exists solely because of Jusey1z who really wanted to protect his bees." + Configuration.NEW_LINE + "Btw Jusey, when I said 'very cute though', I meant you. Bees are cute either of course."); diff --git a/src/main/java/com/aizistral/enigmaticlegacy/items/EldritchPan.java b/src/main/java/com/aizistral/enigmaticlegacy/items/EldritchPan.java new file mode 100644 index 00000000..cf564fe7 --- /dev/null +++ b/src/main/java/com/aizistral/enigmaticlegacy/items/EldritchPan.java @@ -0,0 +1,416 @@ +package com.aizistral.enigmaticlegacy.items; + +import java.util.*; + +import com.aizistral.enigmaticlegacy.EnigmaticLegacy; +import com.aizistral.enigmaticlegacy.api.generic.SubscribeConfig; +import com.aizistral.enigmaticlegacy.api.items.ICreativeTabMember; +import com.aizistral.enigmaticlegacy.api.items.ICursed; +import com.aizistral.enigmaticlegacy.api.items.ITaintable; +import com.aizistral.enigmaticlegacy.api.materials.EnigmaticMaterials; +import com.aizistral.enigmaticlegacy.handlers.SuperpositionHandler; +import com.aizistral.enigmaticlegacy.helpers.ItemLoreHelper; +import com.aizistral.enigmaticlegacy.items.generic.ItemBase; +import com.aizistral.enigmaticlegacy.items.generic.ItemBaseTool; +import com.aizistral.enigmaticlegacy.registries.EnigmaticItems; +import com.aizistral.enigmaticlegacy.registries.EnigmaticSounds; +import com.aizistral.enigmaticlegacy.registries.EnigmaticTabs; +import com.aizistral.omniconfig.wrappers.Omniconfig; +import com.aizistral.omniconfig.wrappers.OmniconfigWrapper; +import com.google.common.collect.*; + +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.StringTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.tags.BlockTags; +import net.minecraft.world.Difficulty; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.*; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.DispenserBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.ToolAction; +import net.minecraftforge.common.ToolActions; +import org.jetbrains.annotations.Nullable; + +public class EldritchPan extends TieredItem implements Vanishable, ICursed, ICreativeTabMember { + private static final UUID ARMOR_MODIFIER_UUID = UUID.fromString("2d5cac0e-598f-475b-97cb-c7ab4741d0f5"); + private static final ItemStack UNSUSPECTING_DIAMOND_SWORD = new ItemStack(Items.DIAMOND_SWORD); + public static final Map HOLDING_DURATIONS = new WeakHashMap<>(); + + // TODO: + // The Forbidden Fruit interaction + // Metal clang sound effect + // Make enchantable with sword enchants + // Repair with food + // The Acknowledgment lore + + public static Omniconfig.DoubleParameter attackDamage = null; + public static Omniconfig.DoubleParameter attackSpeed = null; + public static Omniconfig.DoubleParameter armorValue = null; + public static Omniconfig.DoubleParameter lifeSteal = null; + public static Omniconfig.DoubleParameter hungerSteal = null; + public static Omniconfig.DoubleParameter uniqueDamageGain = null; + public static Omniconfig.DoubleParameter uniqueArmorGain = null; + public static Omniconfig.IntParameter uniqueGainLimit = null; + + @SubscribeConfig + public static void onConfig(OmniconfigWrapper builder) { + builder.pushPrefix("EldritchPan"); + + attackDamage = builder + .comment("The base attack damage of The Voracious Pan.") + .max(32768).getDouble("AttackDamage", 31); + + attackSpeed = builder + .comment("The base attack speed of The Voracious Pan.") + .minMax(32768).getDouble("AttackSpeed", -3.2); + + armorValue = builder + .comment("The base armor value of The Voracious Pan.") + .max(32768).getDouble("ArmorValue", 4); + + lifeSteal = builder + .comment("Base Lifesteal fraction of The Voracious Pan.") + .max(32768).getDouble("LifeSteal", 0.15); + + hungerSteal = builder + .comment("Base Hungersteal value of The Voracious Pan.") + .max(32768).getDouble("HungerSteal", 2); + + uniqueDamageGain = builder + .comment("Base damage gain from unique mob kills for The Voracious Pan.") + .max(32768).getDouble("UniqueDamageGain", 0.5); + + uniqueArmorGain = builder + .comment("Base armor gain from unique mob kills for The Voracious Pan.") + .max(32768).getDouble("UniqueArmorGain", 0.5); + + uniqueGainLimit = builder + .comment("How many unique mob kills will count towards increasing the stats of The Voracious Pan.") + .max(32768).getInt("UniqueGainLimit", 100); + + builder.popPrefix(); + } + + private final Multimap defaultModifiers; + //private final float attackDamage, attackSpeed, armorValue; + + public EldritchPan() { + super(EnigmaticMaterials.ELDRITCH_PAN, + ItemBaseTool.getDefaultProperties() + .defaultDurability(4000) + .rarity(Rarity.EPIC) + .fireResistant()); + + + ImmutableMultimap.Builder builder = ImmutableMultimap.builder(); + builder.put(Attributes.ATTACK_DAMAGE, new AttributeModifier(BASE_ATTACK_DAMAGE_UUID, "Weapon modifier", attackDamage.getValue(), AttributeModifier.Operation.ADDITION)); + builder.put(Attributes.ATTACK_SPEED, new AttributeModifier(BASE_ATTACK_SPEED_UUID, "Weapon modifier", attackSpeed.getValue(), AttributeModifier.Operation.ADDITION)); + builder.put(Attributes.ARMOR, new AttributeModifier(ARMOR_MODIFIER_UUID, "Weapon modifier", armorValue.getValue(), AttributeModifier.Operation.ADDITION)); + this.defaultModifiers = builder.build(); + + DispenserBlock.registerBehavior(this, ArmorItem.DISPENSE_ITEM_BEHAVIOR); + } + + @Override + public Multimap getDefaultAttributeModifiers(EquipmentSlot slot) { + if (slot != EquipmentSlot.MAINHAND && slot != EquipmentSlot.OFFHAND) + return super.getDefaultAttributeModifiers(slot); + + return this.defaultModifiers; + } + + @Override + public Multimap getAttributeModifiers(EquipmentSlot slot, ItemStack stack) { + if (slot != EquipmentSlot.MAINHAND && slot != EquipmentSlot.OFFHAND) + return super.getDefaultAttributeModifiers(slot); + + int kills = getKillCount(stack); + + if (kills <= 0) + return super.getAttributeModifiers(slot, stack); + + double armor = armorValue.getValue() + (uniqueArmorGain.getValue() * kills); + ImmutableMultimap.Builder builder = ImmutableMultimap.builder(); + + builder.put(Attributes.ARMOR, new AttributeModifier(ARMOR_MODIFIER_UUID, "Weapon modifier", + armor, AttributeModifier.Operation.ADDITION)); + + if (slot != EquipmentSlot.MAINHAND) + return builder.build(); + + double damage = attackDamage.getValue() + (uniqueDamageGain.getValue() * kills); + + builder.put(Attributes.ATTACK_SPEED, new AttributeModifier(BASE_ATTACK_SPEED_UUID, "Weapon modifier", + attackSpeed.getValue(), AttributeModifier.Operation.ADDITION)); + builder.put(Attributes.ATTACK_DAMAGE, new AttributeModifier(BASE_ATTACK_DAMAGE_UUID, "Weapon modifier", + damage, AttributeModifier.Operation.ADDITION)); + + return builder.build(); + } + + @Override + public boolean hurtEnemy(ItemStack stack, LivingEntity target, LivingEntity attacker) { + if (attacker.getRandom().nextDouble() < 0.0001) { + attacker.level().playSound(null, attacker.getX(), attacker.getY(), attacker.getZ(), + EnigmaticSounds.PAN_CLANG_FR, SoundSource.PLAYERS, 1F, + attacker.level().random.nextFloat() * 0.2F + 0.8F); + } else { + attacker.level().playSound(null, attacker.getX(), attacker.getY(), attacker.getZ(), + EnigmaticSounds.PAN_CLANG, SoundSource.PLAYERS, 0.5F, + attacker.level().random.nextFloat() * 0.1F + 0.9F); + } + + stack.hurtAndBreak(1, attacker, (entity) -> { + entity.broadcastBreakEvent(EquipmentSlot.MAINHAND); + }); + + return true; + } + + public boolean mineBlock(ItemStack stack, Level level, BlockState state, BlockPos pos, LivingEntity entity) { + if (state.getDestroySpeed(level, pos) != 0.0F) { + stack.hurtAndBreak(2, entity, (living) -> { + living.broadcastBreakEvent(EquipmentSlot.MAINHAND); + }); + } + + return true; + } + + @Override + public void inventoryTick(ItemStack stack, Level worldIn, Entity entityIn, int itemSlot, boolean isSelected) { + // NO-OP + } + + @Override + @OnlyIn(Dist.CLIENT) + public void appendHoverText(ItemStack stack, Level worldIn, List tooltip, TooltipFlag flagIn) { + if (Screen.hasShiftDown()) { + String life = "+" + this.toString(100 * lifeSteal.getValue()) + "%"; + String hunger = "+" + this.toString(hungerSteal.getValue()); + String damageGain = "+" + this.toString(uniqueDamageGain.getValue()); + String armorGain = "+" + this.toString(uniqueArmorGain.getValue()); + + boolean noHunger = SuperpositionHandler.cannotHunger((EnigmaticLegacy.PROXY.getClientPlayer())); + + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.eldritchPan1"); + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.eldritchPan2"); + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.void"); + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.eldritchPan3", + ChatFormatting.GOLD, life); + + if (!noHunger) { + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.eldritchPan4", + ChatFormatting.GOLD, hunger); + } else { + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.eldritchPan4_alt", + ChatFormatting.GOLD, hunger); + } + + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.void"); + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.eldritchPan5"); + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.eldritchPan6"); + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.void"); + + if (!noHunger) { + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.eldritchPan7"); + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.eldritchPan8"); + } else { + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.eldritchPan7_alt"); + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.eldritchPan8_alt"); + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.eldritchPan8p_alt"); + } + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.void"); + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.eldritchPan9", + ChatFormatting.GOLD, damageGain); + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.eldritchPan10", + ChatFormatting.GOLD, armorGain); + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.void"); + ItemLoreHelper.indicateWorthyOnesOnly(tooltip); + } else { + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.eldritchPanLore1"); + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.void"); + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.holdShift"); + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.void"); + this.writeKillCount(tooltip, stack); + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.void"); + ItemLoreHelper.indicateCursedOnesOnly(tooltip); + } + } + + @Override + public UseAnim getUseAnimation(ItemStack stack) { + return UseAnim.BLOCK; + } + + @Override + public int getUseDuration(ItemStack stack) { + return 72000; + } + + @Override + public InteractionResultHolder use(Level world, Player player, InteractionHand hand) { + ItemStack stack = player.getItemInHand(hand); + + if (hand == InteractionHand.MAIN_HAND) { + ItemStack offhandStack = player.getOffhandItem(); + + if (offhandStack.getItem().getUseAnimation(offhandStack) == UseAnim.BLOCK) + return InteractionResultHolder.pass(stack); + } + + if (SuperpositionHandler.isTheCursedOne(player)) { + player.startUsingItem(hand); + return InteractionResultHolder.consume(stack); + } else + return InteractionResultHolder.pass(stack); + } + + @Override + public boolean canPerformAction(ItemStack stack, ToolAction toolAction) { + // TODO: make it consume projectiles for hunger + return ToolActions.DEFAULT_SHIELD_ACTIONS.contains(toolAction); + } + + private void writeKillCount(List tooltip, ItemStack pan) { + int kills = getKillCount(pan); + + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.eldritchPanKills1", + ChatFormatting.GOLD, kills); + + if (kills >= uniqueGainLimit.getValue()) { + ItemLoreHelper.addLocalizedString(tooltip, "tooltip.enigmaticlegacy.eldritchPanKillsMax"); + } + } + + @Override + public @Nullable CreativeModeTab getCreativeTab() { + return EnigmaticTabs.MAIN; + } + + private String toString(double value) { + if (Math.floor(value) == value) { + return Integer.toString((int) value); + } else { + return Double.toString(value); + } + } + + public static int getKillCount(ItemStack pan) { + CompoundTag tag = pan.getTag(); + + if (tag == null || !tag.contains("PanUniqueKills", Tag.TAG_LIST)) + return 0; + + ListTag list = tag.getList("PanUniqueKills", Tag.TAG_STRING); + + return list.size(); + } + + public static List getUniqueKills(ItemStack pan) { + CompoundTag tag = pan.getTag(); + + if (tag == null || !tag.contains("PanUniqueKills", Tag.TAG_LIST)) + return Collections.emptyList(); + + ListTag list = tag.getList("PanUniqueKills", Tag.TAG_STRING); + + return list.stream().map(e -> new ResourceLocation(((StringTag) e).getAsString())).toList(); + } + + public static void setUniqueKills(ItemStack pan, List mobs) { + CompoundTag tag = pan.getOrCreateTag(); + + ListTag list = new ListTag(); + mobs.forEach(entity -> list.add(StringTag.valueOf(entity.toString()))); + tag.put("PanUniqueKills", list); + + pan.setTag(tag); + } + + public static void addUniqueKill(ItemStack pan, ResourceLocation mob) { + CompoundTag tag = pan.getOrCreateTag(); + ListTag list; + + if (!tag.contains("PanUniqueKills", Tag.TAG_LIST)) { + list = new ListTag(); + } else { + list = tag.getList("PanUniqueKills", Tag.TAG_STRING); + } + + list.add(StringTag.valueOf(mob.toString())); + + tag.put("PanUniqueKills", list); + pan.setTag(tag); + } + + public static boolean addKillIfNotPresent(ItemStack pan, ResourceLocation mob) { + List kills = getUniqueKills(pan); + + if (kills.size() < 100 && !kills.contains(mob)) { + addUniqueKill(pan, mob); + return true; + } + + return false; + } + + public static Ingredient getRepairMaterial() { + return Ingredient.of( + Items.BEEF, + Items.PORKCHOP, + Items.MUTTON, + Items.ROTTEN_FLESH, + Items.APPLE, + Items.GOLDEN_APPLE, + Items.ENCHANTED_GOLDEN_APPLE, + Items.POISONOUS_POTATO + ); + } + + @Override + public boolean isEnchantable(ItemStack stack) { + return true; + } + + @Override + public int getEnchantmentValue(ItemStack stack) { + return 24; + } + + @Override + public boolean isBookEnchantable(ItemStack stack, ItemStack book) { + return Items.DIAMOND_SWORD.isBookEnchantable(UNSUSPECTING_DIAMOND_SWORD, book); + } + + @Override + public boolean canApplyAtEnchantingTable(ItemStack stack, Enchantment enchantment) { + return Items.DIAMOND_SWORD.canApplyAtEnchantingTable(UNSUSPECTING_DIAMOND_SWORD, enchantment); + } + +} diff --git a/src/main/java/com/aizistral/enigmaticlegacy/items/EnderSlayer.java b/src/main/java/com/aizistral/enigmaticlegacy/items/EnderSlayer.java index 0adf387c..ffd27925 100644 --- a/src/main/java/com/aizistral/enigmaticlegacy/items/EnderSlayer.java +++ b/src/main/java/com/aizistral/enigmaticlegacy/items/EnderSlayer.java @@ -6,12 +6,13 @@ import javax.annotation.Nullable; -import com.aizistral.enigmaticlegacy.EnigmaticLegacy; import com.aizistral.enigmaticlegacy.api.generic.SubscribeConfig; +import com.aizistral.enigmaticlegacy.api.items.ICreativeTabMember; import com.aizistral.enigmaticlegacy.api.items.ICursed; import com.aizistral.enigmaticlegacy.api.materials.EnigmaticMaterials; import com.aizistral.enigmaticlegacy.helpers.ItemLoreHelper; import com.aizistral.enigmaticlegacy.items.generic.ItemBaseTool; +import com.aizistral.enigmaticlegacy.registries.EnigmaticTabs; import com.aizistral.omniconfig.wrappers.Omniconfig; import com.aizistral.omniconfig.wrappers.OmniconfigWrapper; @@ -24,16 +25,13 @@ import net.minecraft.world.entity.monster.EnderMan; import net.minecraft.world.entity.monster.Endermite; import net.minecraft.world.entity.monster.Shulker; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Rarity; -import net.minecraft.world.item.SwordItem; -import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.*; import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.registries.ForgeRegistries; -public class EnderSlayer extends SwordItem implements ICursed { +public class EnderSlayer extends SwordItem implements ICursed, ICreativeTabMember { public static final List endDwellers = new ArrayList<>(); public static Omniconfig.IntParameter attackDamage; @@ -74,7 +72,7 @@ public static void onConfig(OmniconfigWrapper builder) { } public EnderSlayer() { - super(EnigmaticMaterials.ENDERSLAYER, attackDamage.getValue(), (float) attackSpeed.getValue(), ItemBaseTool.getDefaultProperties().defaultDurability(2000).rarity(Rarity.EPIC).fireResistant()); + super(EnigmaticMaterials.ENDER_SLAYER, attackDamage.getValue(), (float) attackSpeed.getValue(), ItemBaseTool.getDefaultProperties().defaultDurability(2000).rarity(Rarity.EPIC).fireResistant()); } public boolean isEndDweller(LivingEntity entity) { @@ -120,4 +118,9 @@ public void appendHoverText(ItemStack stack, @Nullable Level worldIn, List list @Override public InteractionResult useOn(UseOnContext context) { ItemStack stack = context.getItemInHand(); - int savedCount = stack.getCount(); + Level level = context.getLevel(); + BlockPos pos = context.getClickedPos(); - InteractionResult result = Items.BONE_MEAL.useOn(context); - stack.setCount(savedCount); + boolean success = tryApply(stack, level, pos, Optional.of(context.getPlayer()), Optional.of(context.getClickedFace())); - if (result == InteractionResult.PASS) { - BlockPos pos = context.getClickedPos(); - Level world = context.getLevel(); - BlockState state = world.getBlockState(pos); - Block block = state.getBlock(); + if (success) + return InteractionResult.sidedSuccess(level.isClientSide); + else + return InteractionResult.PASS; + } - if (block instanceof CactusBlock || block instanceof SugarCaneBlock) { - BlockPos topMostPos = this.findTopmostGrowable(world, pos, block, true); - BlockState topMostState = world.getBlockState(topMostPos); + private static boolean tryApply(ItemStack stack, Level world, BlockPos pos, Optional optionalPlayer, + Optional clickedFace) { + ItemStack stackCopy = new ItemStack(stack.getItem()); - if (topMostState.hasProperty(BlockStateProperties.AGE_15) && world.isEmptyBlock(topMostPos.above())) { - int age = topMostState.getValue(BlockStateProperties.AGE_15); + if (applyVanillaBonemeal(stackCopy, world, pos, optionalPlayer, clickedFace)) { + if (!world.isClientSide) { + world.levelEvent(1505, pos, 0); + } - int plantHeight; - for(plantHeight = 1; world.getBlockState(topMostPos.below(plantHeight)).is(block); ++plantHeight) {} + return true; + } - if (plantHeight >= 3) - return result; + BlockState state = world.getBlockState(pos); + Block block = state.getBlock(); - if (!world.isClientSide) { - world.levelEvent(2005, pos, 0); - } + if (block instanceof CactusBlock || block instanceof SugarCaneBlock) { + BlockPos topMostPos = findTopmostGrowable(world, pos, block, true); + BlockState topMostState = world.getBlockState(topMostPos); - age += world.random.nextInt(20); - world.setBlock(topMostPos, topMostState.setValue(BlockStateProperties.AGE_15, Integer.valueOf(Math.min(age, 15))), 4); + if (topMostState.hasProperty(BlockStateProperties.AGE_15) && world.isEmptyBlock(topMostPos.above())) { + int age = topMostState.getValue(BlockStateProperties.AGE_15); - if (world instanceof ServerLevel) { - world.getBlockState(topMostPos).randomTick((ServerLevel)world, topMostPos, world.random); - } + int plantHeight; + for(plantHeight = 1; world.getBlockState(topMostPos.below(plantHeight)).is(block); ++plantHeight) {} - return InteractionResult.sidedSuccess(world.isClientSide); - } - } else if (block instanceof VineBlock) { - if (!block.isRandomlyTicking(state)) - return result; + if (plantHeight >= 3) + return false; - if (world.isClientSide) { - EnigmaticLegacy.PROXY.spawnBonemealParticles(world, pos, 0); + if (!world.isClientSide) { + world.levelEvent(2005, pos, 0); } - int cycles = 7+world.random.nextInt(7); + age += world.random.nextInt(20); + world.setBlock(topMostPos, topMostState.setValue(BlockStateProperties.AGE_15, Integer.valueOf(Math.min(age, 15))), 4); if (world instanceof ServerLevel) { - for (int i = 0; i <= cycles; i++) { - state.randomTick((ServerLevel)world, pos, world.random); - } - - state.updateNeighbourShapes(world, pos, 4); + world.getBlockState(topMostPos).randomTick((ServerLevel)world, topMostPos, world.random); } - return InteractionResult.sidedSuccess(world.isClientSide); - } else if (block instanceof NetherWartBlock) { - if (!block.isRandomlyTicking(state)) - return result; + return true; + } + } else if (block instanceof VineBlock) { + if (!block.isRandomlyTicking(state)) + return false; - if (!world.isClientSide) { - world.levelEvent(2005, pos, 0); - } + if (world.isClientSide) { + EnigmaticLegacy.PROXY.spawnBonemealParticles(world, pos, 0); + } - int cycles = 1+world.random.nextInt(1); - cycles*=11; + int cycles = 7+world.random.nextInt(7); - if (world instanceof ServerLevel) { - for (int i = 0; i <= cycles; i++) { - state.randomTick((ServerLevel)world, pos, world.random); - } + if (world instanceof ServerLevel) { + for (int i = 0; i <= cycles; i++) { + state.randomTick((ServerLevel)world, pos, world.random); } - return InteractionResult.sidedSuccess(world.isClientSide); - } else if (block instanceof ChorusPlantBlock || block instanceof ChorusFlowerBlock) { - if (!world.isClientSide) { - world.levelEvent(2005, pos, 0); - } + state.updateNeighbourShapes(world, pos, 4); + } + + return true; + } else if (block instanceof NetherWartBlock) { + if (!block.isRandomlyTicking(state)) + return false; - if (world instanceof ServerLevel serverWorld) { - List flowers = this.findChorusFlowers(world, pos); + if (!world.isClientSide) { + world.levelEvent(2005, pos, 0); + } - flowers.forEach(flowerPos -> { - int cycles = 1 + world.random.nextInt(2); - cycles *= 11; + int cycles = 1+world.random.nextInt(1); + cycles*=11; - for (int i = 0; i <= cycles; i++) { - BlockState flowerState = world.getBlockState(flowerPos); - flowerState.randomTick(serverWorld, flowerPos, world.random); - } - }); + if (world instanceof ServerLevel) { + for (int i = 0; i <= cycles; i++) { + state.randomTick((ServerLevel)world, pos, world.random); } + } - return InteractionResult.sidedSuccess(world.isClientSide); + return true; + } else if (block instanceof ChorusPlantBlock || block instanceof ChorusFlowerBlock) { + if (!world.isClientSide) { + world.levelEvent(2005, pos, 0); } + + if (world instanceof ServerLevel serverWorld) { + List flowers = findChorusFlowers(world, pos); + + flowers.forEach(flowerPos -> { + int cycles = 1 + world.random.nextInt(2); + cycles *= 11; + + for (int i = 0; i <= cycles; i++) { + BlockState flowerState = world.getBlockState(flowerPos); + flowerState.randomTick(serverWorld, flowerPos, world.random); + } + }); + } + + return true; } - return result; + return false; + } + + public static boolean applyVanillaBonemeal(ItemStack stack, Level level, BlockPos pos, Optional optionalPlayer, + Optional clickedFace) { + if (!growCrop(stack, level, pos, optionalPlayer)) + return BoneMealItem.growWaterPlant(stack, level, pos, clickedFace.orElse(null)); + else + return true; + } + + public static boolean growCrop(ItemStack stack, Level level, BlockPos pos, Optional optionalPlayer) { + if (!optionalPlayer.isPresent()) { + if (level instanceof ServerLevel) + return BoneMealItem.applyBonemeal(stack, level, pos, FakePlayerFactory.getMinecraft((ServerLevel)level)); + return false; + } else + return BoneMealItem.applyBonemeal(stack, level, pos, optionalPlayer.get()); } - private List findChorusFlowers(Level level, BlockPos pos) { + private static List findChorusFlowers(Level level, BlockPos pos) { List chorusTree = new ArrayList<>(); chorusTree.add(pos); while (true) { int formerSize = chorusTree.size(); for (BlockPos treePos : new ArrayList<>(chorusTree)) { - chorusTree.addAll(this.getNeighboringBlocks(level, treePos, chorusTree, ChorusFlowerBlock.class, + chorusTree.addAll(getNeighboringBlocks(level, treePos, chorusTree, ChorusFlowerBlock.class, ChorusPlantBlock.class)); } @@ -177,14 +237,14 @@ private List findChorusFlowers(Level level, BlockPos pos) { } @SafeVarargs - private List getNeighboringBlocks(Level level, BlockPos pos, List exclude, Class... classes) { + private static List getNeighboringBlocks(Level level, BlockPos pos, List exclude, Class... classes) { BlockPos[] neighbors = new BlockPos[] { pos.above(), pos.below(), pos.east(), pos.north(), pos.south(), pos.west() }; return Arrays.stream(neighbors).filter(neighbor -> !exclude.contains(neighbor) && Arrays.stream(classes) .anyMatch(theClass -> theClass.isInstance(level.getBlockState(neighbor).getBlock()))).collect(Collectors.toList()); } - private BlockPos findTopmostGrowable(Level world, BlockPos pos, Block block, boolean goUp) { + private static BlockPos findTopmostGrowable(Level world, BlockPos pos, Block block, boolean goUp) { BlockPos top = pos; while (true) { diff --git a/src/main/java/com/aizistral/enigmaticlegacy/items/LootGenerator.java b/src/main/java/com/aizistral/enigmaticlegacy/items/LootGenerator.java index b78d408f..3b6c6efe 100644 --- a/src/main/java/com/aizistral/enigmaticlegacy/items/LootGenerator.java +++ b/src/main/java/com/aizistral/enigmaticlegacy/items/LootGenerator.java @@ -95,6 +95,12 @@ public LootGenerator() { this.lootList.add(BuiltInLootTables.VILLAGE_TAIGA_HOUSE); this.lootList.add(BuiltInLootTables.VILLAGE_SNOWY_HOUSE); this.lootList.add(BuiltInLootTables.VILLAGE_SAVANNA_HOUSE); + this.lootList.add(BuiltInLootTables.DESERT_WELL_ARCHAEOLOGY); + this.lootList.add(BuiltInLootTables.DESERT_PYRAMID_ARCHAEOLOGY); + this.lootList.add(BuiltInLootTables.TRAIL_RUINS_ARCHAEOLOGY_COMMON); + this.lootList.add(BuiltInLootTables.TRAIL_RUINS_ARCHAEOLOGY_RARE); + this.lootList.add(BuiltInLootTables.OCEAN_RUIN_WARM_ARCHAEOLOGY); + this.lootList.add(BuiltInLootTables.OCEAN_RUIN_COLD_ARCHAEOLOGY); } @Override diff --git a/src/main/java/com/aizistral/enigmaticlegacy/items/TheJudgement.java b/src/main/java/com/aizistral/enigmaticlegacy/items/TheJudgement.java index d6d30592..55a51975 100644 --- a/src/main/java/com/aizistral/enigmaticlegacy/items/TheJudgement.java +++ b/src/main/java/com/aizistral/enigmaticlegacy/items/TheJudgement.java @@ -50,7 +50,7 @@ import net.minecraftforge.api.distmarker.OnlyIn; public class TheJudgement extends ItemBase { - public static final float ATTACK_DAMAGE = 1000F; + public static final float ATTACK_DAMAGE = Float.POSITIVE_INFINITY; public static final double ATTACK_RADIUS = 64D; private final Multimap defaultModifiers; diff --git a/src/main/java/com/aizistral/enigmaticlegacy/mixin/MixinLivingEntity.java b/src/main/java/com/aizistral/enigmaticlegacy/mixin/MixinLivingEntity.java index 1f9d6218..a4622f22 100644 --- a/src/main/java/com/aizistral/enigmaticlegacy/mixin/MixinLivingEntity.java +++ b/src/main/java/com/aizistral/enigmaticlegacy/mixin/MixinLivingEntity.java @@ -30,7 +30,9 @@ public MixinLivingEntity(EntityType type, Level world) { @Inject(method = "isDamageSourceBlocked", at = @At("HEAD"), cancellable = true) private void onDamageSourceBlocking(DamageSource source, CallbackInfoReturnable info) { - SuperpositionHandler.onDamageSourceBlocking(((LivingEntity)(Object)this), this.useItem, source, info); + if (SuperpositionHandler.onDamageSourceBlocking(((LivingEntity)(Object)this), this.useItem, source, info)) { + info.setReturnValue(true); + } } @Override diff --git a/src/main/java/com/aizistral/enigmaticlegacy/objects/SpecialLootModifier.java b/src/main/java/com/aizistral/enigmaticlegacy/objects/SpecialLootModifier.java index 541b3cda..ac176763 100644 --- a/src/main/java/com/aizistral/enigmaticlegacy/objects/SpecialLootModifier.java +++ b/src/main/java/com/aizistral/enigmaticlegacy/objects/SpecialLootModifier.java @@ -1,19 +1,26 @@ package com.aizistral.enigmaticlegacy.objects; +import java.util.List; import java.util.function.Supplier; import javax.annotation.Nonnull; import org.jetbrains.annotations.NotNull; +import com.aizistral.enigmaticlegacy.api.generic.SubscribeConfig; import com.aizistral.enigmaticlegacy.config.OmniconfigHandler; import com.aizistral.enigmaticlegacy.handlers.SuperpositionHandler; import com.aizistral.enigmaticlegacy.registries.EnigmaticItems; +import com.aizistral.omniconfig.Configuration; +import com.aizistral.omniconfig.wrappers.Omniconfig; +import com.aizistral.omniconfig.wrappers.OmniconfigWrapper; import com.google.common.base.Suppliers; +import com.google.common.collect.ImmutableList; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; @@ -26,6 +33,29 @@ public class SpecialLootModifier extends LootModifier { public static final Supplier> CODEC = Suppliers.memoize(() -> RecordCodecBuilder.create(inst -> codecStart(inst).apply(inst, SpecialLootModifier::new))); + public static final List SUSPICIOUS_TABLES = ImmutableList.of( + new ResourceLocation("minecraft", "archaeology/desert_pyramid"), + new ResourceLocation("minecraft", "archaeology/desert_well"), + new ResourceLocation("minecraft", "archaeology/ocean_ruin_cold"), + new ResourceLocation("minecraft", "archaeology/ocean_ruin_warm"), + new ResourceLocation("minecraft", "archaeology/trail_ruins_common"), + new ResourceLocation("minecraft", "archaeology/trail_ruins_rare") + ); + + public static Omniconfig.DoubleParameter earthHeartChance; + + @SubscribeConfig(receiveClient = true) + public static void onConfig(OmniconfigWrapper builder) { + builder.pushPrefix("CustomLoot"); + + if (builder.config.getSidedType() != Configuration.SidedConfigType.CLIENT) { + earthHeartChance = builder + .comment("The chance for Heart of the Earth to be obtained from suspicious blocks (default is 3%).") + .getDouble("EarthHeartChance", 0.03); + } + + builder.popPrefix(); + } protected SpecialLootModifier(LootItemCondition[] conditions) { super(conditions); @@ -63,6 +93,14 @@ protected SpecialLootModifier(LootItemCondition[] conditions) { } } } + + if (OmniconfigHandler.isItemEnabled(EnigmaticItems.EARTH_HEART)) + if (SUSPICIOUS_TABLES.stream().anyMatch(table -> table.equals(context.getQueriedLootTableId()))) { + if (context.getRandom().nextDouble() < earthHeartChance.getValue()) { + generatedLoot.clear(); + generatedLoot.add(new ItemStack(EnigmaticItems.EARTH_HEART, 1)); + } + } } return generatedLoot; diff --git a/src/main/java/com/aizistral/enigmaticlegacy/proxy/ClientProxy.java b/src/main/java/com/aizistral/enigmaticlegacy/proxy/ClientProxy.java index 2b503c03..090b7ffc 100644 --- a/src/main/java/com/aizistral/enigmaticlegacy/proxy/ClientProxy.java +++ b/src/main/java/com/aizistral/enigmaticlegacy/proxy/ClientProxy.java @@ -191,11 +191,16 @@ private , R extends LivingEnt } } + private void registerBlockingProperty(Item item) { + ItemProperties.register(item, new ResourceLocation("blocking"), + (stack, world, entity, seed) -> entity != null && entity.isUsingItem() + && entity.getUseItem() == stack ? 1 : 0); + } + @OnlyIn(Dist.CLIENT) public void onClientSetup(FMLClientSetupEvent event) { - ItemProperties.register(EnigmaticItems.INFERNAL_SHIELD, new ResourceLocation("blocking"), - (stack, world, entity, seed) -> entity != null && entity.isUsingItem() - && entity.getUseItem() == stack ? 1 : 0); + this.registerBlockingProperty(EnigmaticItems.INFERNAL_SHIELD); + this.registerBlockingProperty(EnigmaticItems.ELDRITCH_PAN); ItemProperties.register(EnigmaticItems.THE_INFINITUM, new ResourceLocation(EnigmaticLegacy.MODID, "the_infinitum_open"), (stack, world, entity, seed) -> { if (entity instanceof Player player) { diff --git a/src/main/java/com/aizistral/enigmaticlegacy/registries/EnigmaticEffects.java b/src/main/java/com/aizistral/enigmaticlegacy/registries/EnigmaticEffects.java index b7cd2c44..b5fc760a 100644 --- a/src/main/java/com/aizistral/enigmaticlegacy/registries/EnigmaticEffects.java +++ b/src/main/java/com/aizistral/enigmaticlegacy/registries/EnigmaticEffects.java @@ -19,10 +19,18 @@ public class EnigmaticEffects extends AbstractRegistry { @ObjectHolder(value = MODID + ":molten_heart", registryName = "mob_effect") public static final MoltenHeartEffect MOLTEN_HEART = null; + @ObjectHolder(value = MODID + ":growing_hunger", registryName = "mob_effect") + public static final GrowingHungerEffect GROWING_HUNGER = null; + + @ObjectHolder(value = MODID + ":growing_bloodlust", registryName = "mob_effect") + public static final GrowingBloodlustEffect GROWING_BLOODLUST = null; + private EnigmaticEffects() { super(ForgeRegistries.MOB_EFFECTS); this.register("blazing_strength", BlazingStrengthEffect::new); this.register("molten_heart", MoltenHeartEffect::new); + this.register("growing_hunger", GrowingHungerEffect::new); + this.register("growing_bloodlust", GrowingBloodlustEffect::new); } } diff --git a/src/main/java/com/aizistral/enigmaticlegacy/registries/EnigmaticItems.java b/src/main/java/com/aizistral/enigmaticlegacy/registries/EnigmaticItems.java index a0c96e7f..f84537dc 100644 --- a/src/main/java/com/aizistral/enigmaticlegacy/registries/EnigmaticItems.java +++ b/src/main/java/com/aizistral/enigmaticlegacy/registries/EnigmaticItems.java @@ -435,6 +435,10 @@ public class EnigmaticItems extends AbstractRegistry { @ObjectHolder(value = MODID + ":soul_dust", registryName = "item") public static final Item SOUL_DUST = null; + @ConfigurableItem("Eldritch Frying Pan") + @ObjectHolder(value = MODID + ":eldritch_pan", registryName = "item") + public static final Item ELDRITCH_PAN = null; + private EnigmaticItems() { super(ForgeRegistries.ITEMS); this.register("enigmatic_item", EnigmaticItem::new); @@ -534,6 +538,7 @@ private EnigmaticItems() { this.register("deception_amulet", DeceptionAmulet::new); this.register("the_judgement", TheJudgement::new); this.register("soul_dust", SoulDust::new); + this.register("eldritch_pan", EldritchPan::new); this.register("common_potion", () -> new UltimatePotionBase(Rarity.COMMON, PotionType.COMMON)); this.register("common_potion_splash", () -> new UltimatePotionSplash(Rarity.COMMON, PotionType.COMMON)); diff --git a/src/main/java/com/aizistral/enigmaticlegacy/registries/EnigmaticSounds.java b/src/main/java/com/aizistral/enigmaticlegacy/registries/EnigmaticSounds.java index 3559cf22..39fc784e 100644 --- a/src/main/java/com/aizistral/enigmaticlegacy/registries/EnigmaticSounds.java +++ b/src/main/java/com/aizistral/enigmaticlegacy/registries/EnigmaticSounds.java @@ -37,6 +37,12 @@ public class EnigmaticSounds extends AbstractRegistry { @ObjectHolder(value = MODID + ":misc.uneat", registryName = "sound_event") public static final SoundEvent EAT_REVERSE = null; + @ObjectHolder(value = MODID + ":misc.pan_clang", registryName = "sound_event") + public static final SoundEvent PAN_CLANG = null; + + @ObjectHolder(value = MODID + ":misc.pan_clang_fr", registryName = "sound_event") + public static final SoundEvent PAN_CLANG_FR = null; + private EnigmaticSounds() { super(ForgeRegistries.SOUND_EVENTS); this.register("misc.hhon"); @@ -47,6 +53,8 @@ private EnigmaticSounds() { this.register("misc.learn"); this.register("misc.sword_hit_reject"); this.register("misc.uneat"); + this.register("misc.pan_clang"); + this.register("misc.pan_clang_fr"); } private void register(String name) { diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 7bfed750..40e93b83 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -73,4 +73,5 @@ public net.minecraft.world.damagesource.DamageSources m_268998_(Lnet/minecraft/r public net.minecraft.world.damagesource.DamageSources m_269298_(Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/entity/Entity;)Lnet/minecraft/world/damagesource/DamageSource; #source public net.minecraft.world.damagesource.DamageSources m_269079_(Lnet/minecraft/resources/ResourceKey;)Lnet/minecraft/world/damagesource/DamageSource; #source -public net.minecraft.world.entity.item.ItemEntity f_31988_ #thrower \ No newline at end of file +public net.minecraft.world.entity.item.ItemEntity f_31988_ #thrower +public net.minecraft.world.entity.projectile.LargeFireball f_37197_ #explosionPower \ No newline at end of file diff --git a/src/main/resources/assets/enigmaticlegacy/lang/en_us.json b/src/main/resources/assets/enigmaticlegacy/lang/en_us.json index 31851314..6a3941ea 100644 --- a/src/main/resources/assets/enigmaticlegacy/lang/en_us.json +++ b/src/main/resources/assets/enigmaticlegacy/lang/en_us.json @@ -112,6 +112,7 @@ "item.enigmaticlegacy.deception_amulet": "Amulet of Deception [WIP]", "item.enigmaticlegacy.the_judgement": "The Judgement", "item.enigmaticlegacy.soul_dust": "Soul Dust", + "item.enigmaticlegacy.eldritch_pan": "The Voracious Pan", "block.enigmaticlegacy.big_lamp": "Lamp", "block.enigmaticlegacy.massive_lamp": "Encased Lamp", @@ -123,6 +124,8 @@ "effect.enigmaticlegacy.blazing_strength": "Blazing Might", "effect.enigmaticlegacy.molten_heart": "Molten Heart", + "effect.enigmaticlegacy.growing_hunger": "Growing Hunger", + "effect.enigmaticlegacy.growing_bloodlust": "Growing Bloodlust", "stat.enigmaticlegacy.play_time_with_seven_curses": "Time Played with Seven Curses", "stat.enigmaticlegacy.play_time_without_seven_curses": "Time Played without Seven Curses", @@ -248,6 +251,7 @@ "death.attack.darkness": "%1$s was devoured by darkness", "message.enigmaticlegacy.permadeath": "In attempting the feat, one proves their courage.\nMay your fractured soul at last find rest.", "message.enigmaticlegacy.cursed_sleep": "Seven Curses awaken unspeakable fear and gnawing uncertainty within as you approach the tempting realm of dreams. No hope for the hopeless, no sleep for the sleepless...", + "message.enigmaticlegacy.eldritch_pan_buff": "With the taste of this new soul, The Voracious Pan grows ever stronger.", "message.enigmaticlegacy.gen_sim_complete": "Estimated generation complete in §632768§5 instances; check §6latest.log§5 file to see the results.", "message.enigmaticlegacy.animal_analysis_complete": "Entity registry analysis is complete; check §6latest.log§5 file to see the results.", "message.enigmaticlegacy.voiceover_experimental": "§eHello there! §6Enigmatic Legacy§e developer on the line. Since voiceover is not a common thing for mods to add, I would like you to know that this feature is experimental, and I am actively looking for player feedback on it. Join my §6Discord§e and inform me of your impression once you play with it for some while: §6https://discord.gg/fuWK8ns", @@ -1024,6 +1028,24 @@ "tooltip.enigmaticlegacy.theJudgementMode0": "§6Normal", "tooltip.enigmaticlegacy.theJudgementMode1": "§6Clear Drops", + "tooltip.enigmaticlegacy.eldritchPan1": "§5Alteration of the §6Fourth Curse§d:", + "tooltip.enigmaticlegacy.eldritchPan2": "§6- Always deals its full damage.", + "tooltip.enigmaticlegacy.eldritchPan3": "§6%s §dLifesteal", + "tooltip.enigmaticlegacy.eldritchPan4": "§6%s §dHungersteal", + "tooltip.enigmaticlegacy.eldritchPan4_alt": "§6%s §dHungersteal (converts to health)", + "tooltip.enigmaticlegacy.eldritchPan5": "§5Cooks the meat of slain creatures.", + "tooltip.enigmaticlegacy.eldritchPan6": "§5Can be used as a shield, and consume projectiles while blocking.", + "tooltip.enigmaticlegacy.eldritchPan7": "§5Continuosly holding the pan grants a §6Growing Hunger§5 effect,", + "tooltip.enigmaticlegacy.eldritchPan8": "§5which makes you hungrier, but stronger.", + "tooltip.enigmaticlegacy.eldritchPan7_alt": "§5Continuosly holding the pan grants a §6Growing Bloodlust§5 effect,", + "tooltip.enigmaticlegacy.eldritchPan8_alt": "§5which makes you lose health, but grants strength and lifesteal.", + "tooltip.enigmaticlegacy.eldritchPan8p_alt": "§5This effect cannot kill you.", + "tooltip.enigmaticlegacy.eldritchPan9": "§5Each new creature slain with the pan gives it a permanent §6%s", + "tooltip.enigmaticlegacy.eldritchPan10": "§5§dDamage§5 and §6%s §dArmor§5 when held.", + "tooltip.enigmaticlegacy.eldritchPanLore1": "§5Raw and primal hunger given form.", + "tooltip.enigmaticlegacy.eldritchPanKills1": "§dUnique Kills: %s", + "tooltip.enigmaticlegacy.eldritchPanKillsMax": "§6The pan is sated... but you are not.", + "gui.enigmaticlegacy.lore_inscriber": "Write Name & Lore", "gui.enigmaticlegacy.blazing_core_bar_title": "Heat", "gui.enigmaticlegacy.blazing_core_bar_offsetX": "0", @@ -1825,7 +1847,17 @@ "book.enigmaticlegacy.entry.end_anchor.page.3": "cheaper Glowstone. As a repayment for increased maintenance costs - it can function where Respawn Anchor cannot, and has a noticeable chance to not spend a charge upon your revival. Things such as Potion of Recall will work with it much as they do with its predecessor, and Dispenser can still be used to automate recharging.Only one thing remains of concern. Even for higher beings, space between worlds", "book.enigmaticlegacy.entry.end_anchor.page.4": "is not the safest of places to traverse, most so when stripped of flesh... You cannot help but wonder what terrible places await those who are mislead by the light of their beacons, and what grisly fate befalls them in there.", + + + "book.enigmaticlegacy.entry.eldritch_pan.name": "The Voracious Pan", + "book.enigmaticlegacy.entry.eldritch_pan.page.1": "The very bones of the universe, both celestial and eldritch, lay at your fingertips. And yet, you still crave more...Fortunately, the unthinkable nature of Heart of the Abyss can be employed in this pursuit of yours. Less fortunately, another kind of insatiable craving now plagues your mind and body alike.", + "book.enigmaticlegacy.entry.eldritch_pan.page.2": "This boundless hunger demands that you keep hunting for all manner of creature that walk the lands of this, and many other worlds. Consumed by it, you cannot quite tell if this influence fully comes from the artifact that you have forged,", + "book.enigmaticlegacy.entry.eldritch_pan.page.3": "or it has become so deeply engraved in your soul that it will continue haunting you even without it.The maw of The Voracious Pan stays ever-open, leading into what you presume is a stomach belonging to a vast entity of incomprehensible dimensions. Has this being granted you the Heart of the Abyss, or is it merely an entity that shares the same insatiable appetite you suffer from? It might be better not to know.", + "book.enigmaticlegacy.entry.eldritch_pan.page.4": "The promise of The Forbidden Fruit to quench any hunger once and for all is more tempting than ever, but you remain cautious. Things are never quite so simple for a cursed being such as yourself, and once you lose your ability to hunger, some other calamity will surely take its place.Few dare to cross paths with you now. Ones that witnessed flesh torn and consumed, hearts crushed and forgotten, and veins sucked dry of blood", + "book.enigmaticlegacy.entry.eldritch_pan.page.5": "in your never-ending feast, are shaken. Those you struck down have not returned to tell the tales.What, or indeed who, will be your next meal?", + + "book.enigmaticlegacy.landing_text": "In front of you lies the well of great knowledge, a place where some of this world's greatest mysteries belong, scrupulously researched and carefully cataloged.As your journey continues and the world reveals itself to you, you may revisit and behold knowledge you gathered within these pages.", "item.enigmaticlegacy.cosmic_scroll": "The Architect's Favor", diff --git a/src/main/resources/assets/enigmaticlegacy/models/item/eldritch_pan.json b/src/main/resources/assets/enigmaticlegacy/models/item/eldritch_pan.json new file mode 100644 index 00000000..1ce169b6 --- /dev/null +++ b/src/main/resources/assets/enigmaticlegacy/models/item/eldritch_pan.json @@ -0,0 +1,16 @@ +{ + "overrides": [ + { + "predicate": { + "blocking": 0 + }, + "model": "enigmaticlegacy:item/eldritch_pan_idle" + }, + { + "predicate": { + "blocking": 1 + }, + "model": "enigmaticlegacy:item/eldritch_pan_blocking" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/enigmaticlegacy/models/item/eldritch_pan_blocking.json b/src/main/resources/assets/enigmaticlegacy/models/item/eldritch_pan_blocking.json new file mode 100644 index 00000000..a3afe0bc --- /dev/null +++ b/src/main/resources/assets/enigmaticlegacy/models/item/eldritch_pan_blocking.json @@ -0,0 +1,24 @@ +{ + "loader": "forge:separate_transforms", + "gui_light": "front", + "base": { + "parent": "enigmaticlegacy:item/eldritch_pan_in_inventory" + }, + "perspectives": { + "firstperson_righthand": { + "parent": "enigmaticlegacy:item/eldritch_pan_blocking_in_hand" + }, + "firstperson_lefthand": { + "parent": "enigmaticlegacy:item/eldritch_pan_blocking_in_hand" + }, + "thirdperson_righthand": { + "parent": "enigmaticlegacy:item/eldritch_pan_blocking_in_hand" + }, + "thirdperson_lefthand": { + "parent": "enigmaticlegacy:item/eldritch_pan_blocking_in_hand" + }, + "head": { + "parent": "enigmaticlegacy:item/eldritch_pan_blocking_in_hand" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/enigmaticlegacy/models/item/eldritch_pan_blocking_in_hand.json b/src/main/resources/assets/enigmaticlegacy/models/item/eldritch_pan_blocking_in_hand.json new file mode 100644 index 00000000..6474b26e --- /dev/null +++ b/src/main/resources/assets/enigmaticlegacy/models/item/eldritch_pan_blocking_in_hand.json @@ -0,0 +1,25 @@ +{ + "parent": "enigmaticlegacy:item/eldritch_pan_idle_in_hand", + "display": { + "thirdperson_righthand": { + "rotation": [-92.13, -30.82, -40], + "translation": [1, 4, -2.5], + "scale": [0.85, 0.85, 0.85] + }, + "thirdperson_lefthand": { + "rotation": [-92.13, -30.82, -40], + "translation": [1, 4, -2.5], + "scale": [0.85, 0.85, 0.85] + }, + "firstperson_righthand": { + "rotation": [-98.84, 21.29, 9], + "translation": [-4.5, 1.5, -2.5], + "scale": [0.85, 0.85, 0.85] + }, + "firstperson_lefthand": { + "rotation": [-98.84, 21.29, 9], + "translation": [-4.5, 1.5, -2.5], + "scale": [0.85, 0.85, 0.85] + } + } +} diff --git a/src/main/resources/assets/enigmaticlegacy/models/item/eldritch_pan_idle.json b/src/main/resources/assets/enigmaticlegacy/models/item/eldritch_pan_idle.json new file mode 100644 index 00000000..1fe8d0a5 --- /dev/null +++ b/src/main/resources/assets/enigmaticlegacy/models/item/eldritch_pan_idle.json @@ -0,0 +1,24 @@ +{ + "loader": "forge:separate_transforms", + "gui_light": "front", + "base": { + "parent": "enigmaticlegacy:item/eldritch_pan_in_inventory" + }, + "perspectives": { + "firstperson_righthand": { + "parent": "enigmaticlegacy:item/eldritch_pan_idle_in_hand" + }, + "firstperson_lefthand": { + "parent": "enigmaticlegacy:item/eldritch_pan_idle_in_hand" + }, + "thirdperson_righthand": { + "parent": "enigmaticlegacy:item/eldritch_pan_idle_in_hand" + }, + "thirdperson_lefthand": { + "parent": "enigmaticlegacy:item/eldritch_pan_idle_in_hand" + }, + "head": { + "parent": "enigmaticlegacy:item/eldritch_pan_idle_in_hand" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/enigmaticlegacy/models/item/eldritch_pan_idle_in_hand.json b/src/main/resources/assets/enigmaticlegacy/models/item/eldritch_pan_idle_in_hand.json new file mode 100644 index 00000000..e4c0548a --- /dev/null +++ b/src/main/resources/assets/enigmaticlegacy/models/item/eldritch_pan_idle_in_hand.json @@ -0,0 +1,244 @@ +{ + "gui_light": "front", + "credit": "Made with Blockbench", + "texture_size": [64, 64], + "textures": { + "0": "enigmaticlegacy:item/eldritch_pan_model", + "particle": "enigmaticlegacy:item/eldritch_pan_model" + }, + "elements": [ + { + "from": [7, 0.25, -2], + "to": [9, 2.25, 8], + "rotation": {"angle": 0, "axis": "y", "origin": [7, 0.25, 0]}, + "faces": { + "north": {"uv": [5.25, 13.25, 5.75, 13.75], "texture": "#0"}, + "east": {"uv": [2.75, 13.25, 5.25, 13.75], "texture": "#0"}, + "south": {"uv": [8.25, 13.25, 8.75, 13.75], "texture": "#0"}, + "west": {"uv": [5.75, 13.25, 8.25, 13.75], "texture": "#0"}, + "up": {"uv": [5.75, 13.25, 5.25, 10.75], "texture": "#0"}, + "down": {"uv": [6.25, 10.75, 5.75, 13.25], "texture": "#0"} + } + }, + { + "from": [2, 0, 8], + "to": [14, 2, 20], + "rotation": {"angle": 0, "axis": "y", "origin": [7, 0, 8]}, + "faces": { + "north": {"uv": [3, 3, 6, 3.5], "texture": "#0"}, + "east": {"uv": [0, 3, 3, 3.5], "texture": "#0"}, + "south": {"uv": [9, 3, 12, 3.5], "texture": "#0"}, + "west": {"uv": [6, 3, 9, 3.5], "texture": "#0"}, + "up": {"uv": [6, 3, 3, 0], "texture": "#0"}, + "down": {"uv": [9, 0, 6, 3], "texture": "#0"} + } + }, + { + "from": [13, 2, 8], + "to": [14, 3, 20], + "rotation": {"angle": 0, "axis": "y", "origin": [7, 1, 8]}, + "faces": { + "north": {"uv": [6.5, 6.75, 6.75, 7], "texture": "#0"}, + "east": {"uv": [3.5, 6.75, 6.5, 7], "texture": "#0"}, + "south": {"uv": [9.75, 6.75, 10, 7], "texture": "#0"}, + "west": {"uv": [6.75, 6.75, 9.75, 7], "texture": "#0"}, + "up": {"uv": [6.75, 6.75, 6.5, 3.75], "texture": "#0"}, + "down": {"uv": [7, 3.75, 6.75, 6.75], "texture": "#0"} + } + }, + { + "from": [3, 7, 16.25], + "to": [13, 7, 19.25], + "rotation": {"angle": 22.5, "axis": "x", "origin": [6, 5, 8.25]}, + "faces": { + "north": {"uv": [7, 6.75, 9.5, 6.75], "texture": "#0"}, + "east": {"uv": [6.25, 6.75, 7, 6.75], "texture": "#0"}, + "south": {"uv": [10.25, 6.75, 12.75, 6.75], "texture": "#0"}, + "west": {"uv": [9.5, 6.75, 10.25, 6.75], "texture": "#0"}, + "up": {"uv": [9.5, 6.75, 7, 6], "texture": "#0"}, + "down": {"uv": [12, 6, 9.5, 6.75], "texture": "#0"} + } + }, + { + "from": [3, 7, 8.75], + "to": [13, 7, 11.75], + "rotation": {"angle": -22.5, "axis": "x", "origin": [6, 5, 19.75]}, + "faces": { + "north": {"uv": [7, 4.25, 9.5, 4.25], "texture": "#0"}, + "east": {"uv": [6.25, 4.25, 7, 4.25], "texture": "#0"}, + "south": {"uv": [10.25, 4.25, 12.75, 4.25], "texture": "#0"}, + "west": {"uv": [9.5, 4.25, 10.25, 4.25], "texture": "#0"}, + "up": {"uv": [9.5, 4.25, 7, 3.5], "texture": "#0"}, + "down": {"uv": [12, 3.5, 9.5, 4.25], "texture": "#0"} + } + }, + { + "from": [10, 7, 9], + "to": [13, 7, 19], + "rotation": {"angle": -22.5, "axis": "z", "origin": [2, 5, 12]}, + "faces": { + "north": {"uv": [5, 6, 5.75, 6], "texture": "#0"}, + "east": {"uv": [2.5, 6, 5, 6], "texture": "#0"}, + "south": {"uv": [8.25, 6, 9, 6], "texture": "#0"}, + "west": {"uv": [5.75, 6, 8.25, 6], "texture": "#0"}, + "up": {"uv": [5.75, 6, 5, 3.5], "texture": "#0"}, + "down": {"uv": [6.5, 3.5, 5.75, 6], "texture": "#0"} + } + }, + { + "from": [2.5, 7, 9], + "to": [5.5, 7, 19], + "rotation": {"angle": 22.5, "axis": "z", "origin": [13.5, 5, 12]}, + "faces": { + "north": {"uv": [3.5, 6, 4.25, 6], "texture": "#0"}, + "east": {"uv": [1, 6, 3.5, 6], "texture": "#0"}, + "south": {"uv": [6.75, 6, 7.5, 6], "texture": "#0"}, + "west": {"uv": [4.25, 6, 6.75, 6], "texture": "#0"}, + "up": {"uv": [4.25, 6, 3.5, 3.5], "texture": "#0"}, + "down": {"uv": [5, 3.5, 4.25, 6], "texture": "#0"} + } + }, + { + "from": [4.75, 5, 7.5], + "to": [7.75, 5, 14.5], + "rotation": {"angle": 22.5, "axis": "x", "origin": [0.75, 3, 6.5]}, + "faces": { + "north": {"uv": [3, 8.75, 3.75, 8.75], "texture": "#0"}, + "east": {"uv": [1.25, 8.75, 3, 8.75], "texture": "#0"}, + "south": {"uv": [5.5, 8.75, 6.25, 8.75], "texture": "#0"}, + "west": {"uv": [3.75, 8.75, 5.5, 8.75], "texture": "#0"}, + "up": {"uv": [3.75, 8.75, 3, 7], "texture": "#0"}, + "down": {"uv": [4.5, 7, 3.75, 8.75], "texture": "#0"} + } + }, + { + "from": [3.75, 4.465, 1.18963], + "to": [7.75, 4.465, 8.18963], + "rotation": {"angle": 0, "axis": "y", "origin": [0.75, 2.465, 0.18963]}, + "faces": { + "north": {"uv": [7, 6, 8, 6], "texture": "#0"}, + "east": {"uv": [5.25, 6, 7, 6], "texture": "#0"}, + "south": {"uv": [9.75, 6, 10.75, 6], "texture": "#0"}, + "west": {"uv": [8, 6, 9.75, 6], "texture": "#0"}, + "up": {"uv": [8, 6, 7, 4.25], "texture": "#0"}, + "down": {"uv": [9, 4.25, 8, 6], "texture": "#0"} + } + }, + { + "from": [2, 2, 8], + "to": [3, 3, 20], + "rotation": {"angle": 0, "axis": "y", "origin": [-4, 1, 8]}, + "faces": { + "north": {"uv": [3, 6.5, 3.25, 6.75], "texture": "#0"}, + "east": {"uv": [0, 6.5, 3, 6.75], "texture": "#0"}, + "south": {"uv": [6.25, 6.5, 6.5, 6.75], "texture": "#0"}, + "west": {"uv": [3.25, 6.5, 6.25, 6.75], "texture": "#0"}, + "up": {"uv": [3.25, 6.5, 3, 3.5], "texture": "#0"}, + "down": {"uv": [3.5, 3.5, 3.25, 6.5], "texture": "#0"} + } + }, + { + "from": [3, 2, 8], + "to": [13, 3, 9], + "rotation": {"angle": 0, "axis": "y", "origin": [-5, 1, 8]}, + "faces": { + "north": {"uv": [4.75, 7.25, 7.25, 7.5], "texture": "#0"}, + "east": {"uv": [4.5, 7.25, 4.75, 7.5], "texture": "#0"}, + "south": {"uv": [7.5, 7.25, 10, 7.5], "texture": "#0"}, + "west": {"uv": [7.25, 7.25, 7.5, 7.5], "texture": "#0"}, + "up": {"uv": [7.25, 7.25, 4.75, 7], "texture": "#0"}, + "down": {"uv": [9.75, 7, 7.25, 7.25], "texture": "#0"} + } + }, + { + "from": [3, 2, 19], + "to": [13, 3, 20], + "rotation": {"angle": 0, "axis": "y", "origin": [6, 1, 8]}, + "faces": { + "north": {"uv": [4.75, 7.75, 7.25, 8], "texture": "#0"}, + "east": {"uv": [4.5, 7.75, 4.75, 8], "texture": "#0"}, + "south": {"uv": [7.5, 7.75, 10, 8], "texture": "#0"}, + "west": {"uv": [7.25, 7.75, 7.5, 8], "texture": "#0"}, + "up": {"uv": [7.25, 7.75, 4.75, 7.5], "texture": "#0"}, + "down": {"uv": [9.75, 7.5, 7.25, 7.75], "texture": "#0"} + } + }, + { + "from": [8, 1.75, 19.25], + "to": [11, 3.75, 21.25], + "rotation": {"angle": 0, "axis": "y", "origin": [9, 1.75, 19.25]}, + "faces": { + "north": {"uv": [0.5, 2, 1.25, 2.5], "texture": "#0"}, + "east": {"uv": [0, 2, 0.5, 2.5], "texture": "#0"}, + "south": {"uv": [1.75, 2, 2.5, 2.5], "texture": "#0"}, + "west": {"uv": [1.25, 2, 1.75, 2.5], "texture": "#0"}, + "up": {"uv": [1.25, 2, 0.5, 1.5], "texture": "#0"}, + "down": {"uv": [2, 1.5, 1.25, 2], "texture": "#0"} + } + }, + { + "from": [1.75, 1.75, 12], + "to": [2.75, 3.75, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [0.75, 1.75, 13]}, + "faces": { + "north": {"uv": [0.75, 4.25, 1, 4.75], "texture": "#0"}, + "east": {"uv": [0, 4.25, 0.75, 4.75], "texture": "#0"}, + "south": {"uv": [1.75, 4.25, 2, 4.75], "texture": "#0"}, + "west": {"uv": [1, 4.25, 1.75, 4.75], "texture": "#0"}, + "up": {"uv": [1, 4.25, 0.75, 3.5], "texture": "#0"}, + "down": {"uv": [1.25, 3.5, 1, 4.25], "texture": "#0"} + } + }, + { + "from": [13.25, 1.75, 10], + "to": [15.25, 3.75, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [12.25, 1.75, 11]}, + "faces": { + "north": {"uv": [1, 1, 1.5, 1.5], "texture": "#0"}, + "east": {"uv": [0, 1, 1, 1.5], "texture": "#0"}, + "south": {"uv": [2.5, 1, 3, 1.5], "texture": "#0"}, + "west": {"uv": [1.5, 1, 2.5, 1.5], "texture": "#0"}, + "up": {"uv": [1.5, 1, 1, 0], "texture": "#0"}, + "down": {"uv": [2, 0, 1.5, 1], "texture": "#0"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [-95.1, 0, 113], + "translation": [-5.25, 2, 3.5], + "scale": [0.85, 0.85, 0.85] + }, + "thirdperson_lefthand": { + "rotation": [-95.1, 0, 113], + "translation": [-5.25, 2, 3.5], + "scale": [0.85, 0.85, 0.85] + }, + "firstperson_righthand": { + "rotation": [-98.84, 21.29, 128.68], + "translation": [-5.25, 3.5, 3.5], + "scale": [0.85, 0.85, 0.85] + }, + "firstperson_lefthand": { + "rotation": [-98.84, 21.29, 128.68], + "translation": [-5.25, 3.5, 3.5], + "scale": [0.85, 0.85, 0.85] + }, + "ground": { + "translation": [0, 5, 0] + }, + "gui": { + "rotation": [50, 135, 0], + "translation": [-2.5, 1.25, 0], + "scale": [0.79, 0.79, 0.79] + }, + "head": { + "rotation": [-180, -46, -180], + "translation": [3.25, 14.5, 3.25] + }, + "fixed": { + "rotation": [-90, 45, 0], + "translation": [-2, -2.25, -7] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/enigmaticlegacy/models/item/eldritch_pan_in_inventory.json b/src/main/resources/assets/enigmaticlegacy/models/item/eldritch_pan_in_inventory.json new file mode 100644 index 00000000..ac363bbb --- /dev/null +++ b/src/main/resources/assets/enigmaticlegacy/models/item/eldritch_pan_in_inventory.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "enigmaticlegacy:item/eldritch_pan" + } +} diff --git a/src/main/resources/assets/enigmaticlegacy/patchouli_books/the_acknowledgment/en_us/entries/tools/eldritch_pan.json b/src/main/resources/assets/enigmaticlegacy/patchouli_books/the_acknowledgment/en_us/entries/tools/eldritch_pan.json new file mode 100644 index 00000000..c88335f4 --- /dev/null +++ b/src/main/resources/assets/enigmaticlegacy/patchouli_books/the_acknowledgment/en_us/entries/tools/eldritch_pan.json @@ -0,0 +1,38 @@ +{ + "name": "book.enigmaticlegacy.entry.eldritch_pan.name", + "icon": "enigmaticlegacy:eldritch_pan", + "category": "enigmaticlegacy:tools", + "advancement": "enigmaticlegacy:book/tools/eldritch_pan", + "secret": false, + "priority": false, + "read_by_default": false, + "sortnum": 120, + "pages": [ + { + "type": "text", + "text": "book.enigmaticlegacy.entry.eldritch_pan.page.1" + }, + { + "type": "crafting", + "recipe": "enigmaticlegacy:eldritch_pan", + "title": " ", + "text": "book.enigmaticlegacy.entry.eldritch_pan.page.2" + }, + { + "type": "text", + "text": "book.enigmaticlegacy.entry.eldritch_pan.page.3" + }, + { + "type": "text", + "text": "book.enigmaticlegacy.entry.eldritch_pan.page.4" + }, + { + "type": "text", + "text": "book.enigmaticlegacy.entry.eldritch_pan.page.5" + }, + { + "type": "empty", + "draw_filler": false + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/enigmaticlegacy/sounds.json b/src/main/resources/assets/enigmaticlegacy/sounds.json index 0dac4475..a026b64b 100644 --- a/src/main/resources/assets/enigmaticlegacy/sounds.json +++ b/src/main/resources/assets/enigmaticlegacy/sounds.json @@ -50,6 +50,28 @@ } ] }, + "misc.pan_clang": { + "sounds": [ + { + "name": "enigmaticlegacy:misc/pan_clang_1", + "stream": false + }, { + "name": "enigmaticlegacy:misc/pan_clang_2", + "stream": false + }, { + "name": "enigmaticlegacy:misc/pan_clang_3", + "stream": false + } + ] + }, + "misc.pan_clang_fr": { + "sounds": [ + { + "name": "enigmaticlegacy:misc/pan_clang_fr", + "stream": false + } + ] + }, "misc.uneat": { "sounds": [ { diff --git a/src/main/resources/assets/enigmaticlegacy/sounds/misc/pan_clang_1.ogg b/src/main/resources/assets/enigmaticlegacy/sounds/misc/pan_clang_1.ogg new file mode 100644 index 00000000..d29a30a7 Binary files /dev/null and b/src/main/resources/assets/enigmaticlegacy/sounds/misc/pan_clang_1.ogg differ diff --git a/src/main/resources/assets/enigmaticlegacy/sounds/misc/pan_clang_2.ogg b/src/main/resources/assets/enigmaticlegacy/sounds/misc/pan_clang_2.ogg new file mode 100644 index 00000000..e98d9599 Binary files /dev/null and b/src/main/resources/assets/enigmaticlegacy/sounds/misc/pan_clang_2.ogg differ diff --git a/src/main/resources/assets/enigmaticlegacy/sounds/misc/pan_clang_3.ogg b/src/main/resources/assets/enigmaticlegacy/sounds/misc/pan_clang_3.ogg new file mode 100644 index 00000000..50cdd7bf Binary files /dev/null and b/src/main/resources/assets/enigmaticlegacy/sounds/misc/pan_clang_3.ogg differ diff --git a/src/main/resources/assets/enigmaticlegacy/sounds/misc/pan_clang_fr.ogg b/src/main/resources/assets/enigmaticlegacy/sounds/misc/pan_clang_fr.ogg new file mode 100644 index 00000000..c081651c Binary files /dev/null and b/src/main/resources/assets/enigmaticlegacy/sounds/misc/pan_clang_fr.ogg differ diff --git a/src/main/resources/assets/enigmaticlegacy/textures/item/eldritch_pan.png b/src/main/resources/assets/enigmaticlegacy/textures/item/eldritch_pan.png new file mode 100644 index 00000000..2592c1f6 Binary files /dev/null and b/src/main/resources/assets/enigmaticlegacy/textures/item/eldritch_pan.png differ diff --git a/src/main/resources/assets/enigmaticlegacy/textures/item/eldritch_pan.png.mcmeta b/src/main/resources/assets/enigmaticlegacy/textures/item/eldritch_pan.png.mcmeta new file mode 100644 index 00000000..4f27dbe9 --- /dev/null +++ b/src/main/resources/assets/enigmaticlegacy/textures/item/eldritch_pan.png.mcmeta @@ -0,0 +1,19 @@ +{ + "animation": { + "frames": [ + {"index": 0, "time": 20}, + {"index": 1, "time": 32}, + {"index": 2, "time": 17}, + {"index": 3, "time": 25}, + {"index": 4, "time": 10}, + {"index": 5, "time": 45}, + {"index": 6, "time": 2}, + {"index": 7, "time": 2}, + {"index": 8, "time": 2}, + {"index": 9, "time": 2}, + {"index": 10, "time": 2}, + {"index": 11, "time": 2} + ], + "frametime": 1 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/enigmaticlegacy/textures/item/eldritch_pan_model.png b/src/main/resources/assets/enigmaticlegacy/textures/item/eldritch_pan_model.png new file mode 100644 index 00000000..b770f5fd Binary files /dev/null and b/src/main/resources/assets/enigmaticlegacy/textures/item/eldritch_pan_model.png differ diff --git a/src/main/resources/assets/enigmaticlegacy/textures/item/eldritch_pan_model.png.mcmeta b/src/main/resources/assets/enigmaticlegacy/textures/item/eldritch_pan_model.png.mcmeta new file mode 100644 index 00000000..19e44aaf --- /dev/null +++ b/src/main/resources/assets/enigmaticlegacy/textures/item/eldritch_pan_model.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "frames": [{"index": 0, "time": 96}, 1, 2, 3, 4, 5, 6], + "frametime": 1 + } +} diff --git a/src/main/resources/assets/enigmaticlegacy/textures/item/eldritch_pan_temp.png b/src/main/resources/assets/enigmaticlegacy/textures/item/eldritch_pan_temp.png new file mode 100644 index 00000000..53b2566b Binary files /dev/null and b/src/main/resources/assets/enigmaticlegacy/textures/item/eldritch_pan_temp.png differ diff --git a/src/main/resources/assets/enigmaticlegacy/textures/mob_effect/growing_bloodlust.png b/src/main/resources/assets/enigmaticlegacy/textures/mob_effect/growing_bloodlust.png new file mode 100644 index 00000000..f66c7744 Binary files /dev/null and b/src/main/resources/assets/enigmaticlegacy/textures/mob_effect/growing_bloodlust.png differ diff --git a/src/main/resources/assets/enigmaticlegacy/textures/mob_effect/growing_hunger.png b/src/main/resources/assets/enigmaticlegacy/textures/mob_effect/growing_hunger.png new file mode 100644 index 00000000..f3b29e92 Binary files /dev/null and b/src/main/resources/assets/enigmaticlegacy/textures/mob_effect/growing_hunger.png differ diff --git a/src/main/resources/data/enigmaticlegacy/advancements/book/tools/eldritch_pan.json b/src/main/resources/data/enigmaticlegacy/advancements/book/tools/eldritch_pan.json new file mode 100644 index 00000000..a26237dc --- /dev/null +++ b/src/main/resources/data/enigmaticlegacy/advancements/book/tools/eldritch_pan.json @@ -0,0 +1,17 @@ +{ + "parent": "enigmaticlegacy:book/root", + "rewards": {}, + "criteria": { + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "enigmaticlegacy:eldritch_pan" + } + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/main/resources/data/enigmaticlegacy/advancements/recipes/generic/eldritch_pan.json b/src/main/resources/data/enigmaticlegacy/advancements/recipes/generic/eldritch_pan.json new file mode 100644 index 00000000..13839312 --- /dev/null +++ b/src/main/resources/data/enigmaticlegacy/advancements/recipes/generic/eldritch_pan.json @@ -0,0 +1,50 @@ +{ + "parent": "enigmaticlegacy:recipes/root", + "rewards": { + "recipes": [ + "enigmaticlegacy:eldritch_pan" + ] + }, + "criteria": { + "has_items": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "items": ["enigmaticlegacy:abyssal_heart"] + } + ] + } + }, + "has_recipe_result": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "items": ["enigmaticlegacy:eldritch_pan"] + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "enigmaticlegacy:eldritch_pan" + } + }, + "is_cursed_one": { + "trigger": "enigmaticlegacy:equip_cursed_ring" + } + }, + "requirements": [ + [ + "has_recipe_result", + "has_the_recipe", + "has_items" + ], + [ + "is_cursed_one", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/main/resources/data/enigmaticlegacy/recipes/eldritch_pan.json b/src/main/resources/data/enigmaticlegacy/recipes/eldritch_pan.json new file mode 100644 index 00000000..46ee29df --- /dev/null +++ b/src/main/resources/data/enigmaticlegacy/recipes/eldritch_pan.json @@ -0,0 +1,37 @@ +{ + "type": "minecraft:crafting_shaped", + "conditions": [ + { + "type": "enigmaticlegacy:is_enabled", + "item": "enigmaticlegacy:eldritch_pan" + } + ], + "pattern": [ + "ESE", + "IHI", + "TRT" + ], + "key": { + "E": { + "item": "enigmaticlegacy:evil_essence" + }, + "T": { + "item": "minecraft:ghast_tear" + }, + "H": { + "item": "enigmaticlegacy:abyssal_heart" + }, + "I": { + "item": "enigmaticlegacy:evil_ingot" + }, + "S": { + "item": "enigmaticlegacy:void_stone" + }, + "R": { + "item": "enigmaticlegacy:ender_rod" + } + }, + "result": { + "item": "enigmaticlegacy:eldritch_pan" + } +} \ No newline at end of file