diff --git a/src/main/java/io/redspace/ironsspellbooks/api/util/Utils.java b/src/main/java/io/redspace/ironsspellbooks/api/util/Utils.java index 6c42fbe38..e5c0d5edb 100644 --- a/src/main/java/io/redspace/ironsspellbooks/api/util/Utils.java +++ b/src/main/java/io/redspace/ironsspellbooks/api/util/Utils.java @@ -1,6 +1,7 @@ package io.redspace.ironsspellbooks.api.util; import io.redspace.ironsspellbooks.IronsSpellbooks; +import io.redspace.ironsspellbooks.api.attribute.IMagicAttribute; import io.redspace.ironsspellbooks.api.entity.IMagicEntity; import io.redspace.ironsspellbooks.api.events.SpellTeleportEvent; import io.redspace.ironsspellbooks.api.magic.MagicData; @@ -41,6 +42,7 @@ import net.minecraft.world.Difficulty; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.*; +import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.monster.Enemy; @@ -65,8 +67,8 @@ import net.neoforged.neoforge.entity.PartEntity; import net.neoforged.neoforge.network.PacketDistributor; import org.jetbrains.annotations.NotNull; -import org.joml.Vector3f; import org.jetbrains.annotations.Nullable; +import org.joml.Vector3f; import top.theillusivec4.curios.api.CuriosApi; import top.theillusivec4.curios.api.SlotContext; import top.theillusivec4.curios.api.SlotResult; @@ -78,6 +80,9 @@ public class Utils { public static final RandomSource random = RandomSource.createThreadSafe(); + public static final Predicate> ONLY_MAGIC_ATTRIBUTES = (attribute) -> attribute.value() instanceof IMagicAttribute; + public static final Predicate> NON_BASE_ATTRIBUTES = (attribute) -> !(attribute == Attributes.ENTITY_INTERACTION_RANGE || attribute == Attributes.ATTACK_DAMAGE || attribute == Attributes.ATTACK_SPEED || attribute == Attributes.ATTACK_KNOCKBACK); + public static long getServerTick() { return IronsSpellbooks.OVERWORLD.getGameTime(); } diff --git a/src/main/java/io/redspace/ironsspellbooks/gui/overlays/ScreenEffectsOverlay.java b/src/main/java/io/redspace/ironsspellbooks/gui/overlays/ScreenEffectsOverlay.java index e25224404..421942988 100644 --- a/src/main/java/io/redspace/ironsspellbooks/gui/overlays/ScreenEffectsOverlay.java +++ b/src/main/java/io/redspace/ironsspellbooks/gui/overlays/ScreenEffectsOverlay.java @@ -3,15 +3,12 @@ import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; import io.redspace.ironsspellbooks.IronsSpellbooks; -import io.redspace.ironsspellbooks.api.registry.AttributeRegistry; import io.redspace.ironsspellbooks.registries.MobEffectRegistry; import net.minecraft.client.DeltaTracker; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.LayeredDraw; -import net.minecraft.client.renderer.GameRenderer; import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Player; @@ -28,8 +25,10 @@ public void render(GuiGraphics guiHelper, DeltaTracker deltaTracker) { var screenWidth = guiHelper.guiWidth(); var screenHeight = guiHelper.guiHeight(); - //guiHelper.drawString(Minecraft.getInstance().font, String.format("ice: %s", Minecraft.getInstance().player.getAttributeValue(AttributeRegistry.ICE_SPELL_POWER)), 10, 10, 0xFFFFFF); - //guiHelper.drawString(Minecraft.getInstance().font, String.format("blood: %s", Minecraft.getInstance().player.getAttributeValue(AttributeRegistry.BLOOD_SPELL_POWER)), 10, 20, 0xFFFFFF); +// if(!FMLLoader.isProduction()){ +// guiHelper.drawString(Minecraft.getInstance().font, String.format("ice: %s", Minecraft.getInstance().player.getAttributeValue(AttributeRegistry.ICE_SPELL_POWER)), 10, 10, 0xFFFFFF); +// guiHelper.drawString(Minecraft.getInstance().font, String.format("blood: %s", Minecraft.getInstance().player.getAttributeValue(AttributeRegistry.BLOOD_SPELL_POWER)), 10, 20, 0xFFFFFF); +// } Player player = Minecraft.getInstance().player; if (player == null) { diff --git a/src/main/java/io/redspace/ironsspellbooks/item/CastingItem.java b/src/main/java/io/redspace/ironsspellbooks/item/CastingItem.java index 5dadbc61e..215d6254b 100644 --- a/src/main/java/io/redspace/ironsspellbooks/item/CastingItem.java +++ b/src/main/java/io/redspace/ironsspellbooks/item/CastingItem.java @@ -1,15 +1,15 @@ package io.redspace.ironsspellbooks.item; -import io.redspace.ironsspellbooks.item.weapons.IMultihandWeapon; import net.minecraft.util.Unit; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import static io.redspace.ironsspellbooks.registries.ComponentRegistry.CASTING_IMPLEMENT; +import static io.redspace.ironsspellbooks.registries.ComponentRegistry.MULTIHAND_WEAPON; -public class CastingItem extends Item implements IMultihandWeapon { +public class CastingItem extends Item { public CastingItem(Properties pProperties) { - super(pProperties.component(CASTING_IMPLEMENT, Unit.INSTANCE)); + super(pProperties.component(CASTING_IMPLEMENT, Unit.INSTANCE).component(MULTIHAND_WEAPON, Unit.INSTANCE)); } @Override diff --git a/src/main/java/io/redspace/ironsspellbooks/item/weapons/IMultihandWeapon.java b/src/main/java/io/redspace/ironsspellbooks/item/weapons/IMultihandWeapon.java index 23d631fc6..4f20be06f 100644 --- a/src/main/java/io/redspace/ironsspellbooks/item/weapons/IMultihandWeapon.java +++ b/src/main/java/io/redspace/ironsspellbooks/item/weapons/IMultihandWeapon.java @@ -1,7 +1,8 @@ package io.redspace.ironsspellbooks.item.weapons; /** - * Marker Interface. Will apply mainhand attributes when held in the offhand, if another Multihand Weapon is not held in the mainhand, as well as adjust tooltip accordingly. + * Deprecated: Multihand functionality now determined via presence of {@link io.redspace.ironsspellbooks.registries.ComponentRegistry#MULTIHAND_WEAPON} component on the item */ +@Deprecated(forRemoval = true) public interface IMultihandWeapon { } diff --git a/src/main/java/io/redspace/ironsspellbooks/mixin/LivingEntityMixin.java b/src/main/java/io/redspace/ironsspellbooks/mixin/LivingEntityMixin.java index 397f00aed..50c74a2dd 100644 --- a/src/main/java/io/redspace/ironsspellbooks/mixin/LivingEntityMixin.java +++ b/src/main/java/io/redspace/ironsspellbooks/mixin/LivingEntityMixin.java @@ -2,10 +2,10 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; -import io.redspace.ironsspellbooks.api.attribute.IMagicAttribute; +import io.redspace.ironsspellbooks.api.util.Utils; import io.redspace.ironsspellbooks.config.ServerConfigs; import io.redspace.ironsspellbooks.effect.IMobEffectEndCallback; -import io.redspace.ironsspellbooks.item.weapons.IMultihandWeapon; +import io.redspace.ironsspellbooks.registries.ComponentRegistry; import io.redspace.ironsspellbooks.registries.MobEffectRegistry; import net.minecraft.core.Holder; import net.minecraft.world.effect.MobEffectInstance; @@ -14,7 +14,6 @@ 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.item.ItemStack; import net.minecraft.world.item.component.ItemAttributeModifiers; import org.spongepowered.asm.mixin.Mixin; @@ -27,7 +26,6 @@ import java.util.List; import java.util.Map; -import java.util.function.Predicate; @Mixin(LivingEntity.class) public abstract class LivingEntityMixin { @@ -66,8 +64,6 @@ public void isCurrentlyGlowing(CallbackInfoReturnable cir) { // The equipment change event fires 5 lines too early for this to have been able to be done via events @Inject(method = "collectEquipmentChanges", at = @At(value = "RETURN")) public void handleEquipmentChanges(CallbackInfoReturnable> cir) { - //TODO: mixin to ItemStack#getAttributeModifiers and just: if(multihand && slot == offhand) -> slot = offhand...? - // Last hand items are accurate at this point // Mainhand assigning/removing is handled by minecraft. All we are doing is fudging offhand handling // The return of this function is a map of equipmentslots to itemstacks, of itemstacks who have been changed @@ -76,41 +72,29 @@ public void handleEquipmentChanges(CallbackInfoReturnable {}", slot, oldStack, currentStack); - boolean selected = currentStack.getItem() instanceof IMultihandWeapon; - boolean deselected = oldStack.getItem() instanceof IMultihandWeapon; - if (selected || deselected) { - if (slot == EquipmentSlot.MAINHAND) { - ItemStack offhandStack = self.getOffhandItem(); - if (offhandStack.getItem() instanceof IMultihandWeapon && !ItemStack.isSameItem(offhandStack, currentStack)) { - // If we select a mainhand item, revoke offhand attributes - // If we deselect a mainhand item, reinstate offhand attributes - if (selected) { - self.getAttributes().removeAttributeModifiers(filterApplicableAttributes(offhandStack.getAttributeModifiers())); - } - if (deselected) { - self.getAttributes().addTransientAttributeModifiers(filterApplicableAttributes(offhandStack.getAttributeModifiers())); - } - } - } else if (slot == EquipmentSlot.OFFHAND) { - // If we select an offhand item, grant attributes, unless we already hold a mainhand item - // If we deselect an offhand item, revoke attributes - ItemStack mainhandStack = self.getMainHandItem(); - if (selected) { - if (!(mainhandStack.getItem() instanceof IMultihandWeapon)) { - self.getAttributes().addTransientAttributeModifiers(filterApplicableAttributes(currentStack.getAttributeModifiers())); - } - } - if (deselected && !ItemStack.isSameItem(mainhandStack, oldStack)) { - self.getAttributes().removeAttributeModifiers(filterApplicableAttributes(oldStack.getAttributeModifiers())); - } + //did we unequip a multihand item? (reveal offhand) + else if (fromStack.has(ComponentRegistry.MULTIHAND_WEAPON)) { + if (!offhandStack.isEmpty()) { + self.getAttributes().addTransientAttributeModifiers(filterApplicableAttributes(offhandStack.getAttributeModifiers())); } } } @@ -121,7 +105,7 @@ private static Multimap, AttributeModifier> filterApplicableAt var list = modifiers.modifiers().stream().filter(entry -> entry.slot() == EquipmentSlotGroup.MAINHAND).toList(); Multimap, AttributeModifier> map = HashMultimap.create(); for (ItemAttributeModifiers.Entry entry : list) { - var predicate = ServerConfigs.APPLY_ALL_MULTIHAND_ATTRIBUTES.get() ? allNonBaseAttackAttributes : onlyIronAttributes; + var predicate = ServerConfigs.APPLY_ALL_MULTIHAND_ATTRIBUTES.get() ? Utils.NON_BASE_ATTRIBUTES : Utils.ONLY_MAGIC_ATTRIBUTES; if (predicate.test(entry.attribute())) { map.put(entry.attribute(), entry.modifier()); } @@ -129,9 +113,4 @@ private static Multimap, AttributeModifier> filterApplicableAt return map; } - @Unique - private static final Predicate> allNonBaseAttackAttributes = (attribute) -> !(attribute == Attributes.ENTITY_INTERACTION_RANGE || attribute == Attributes.ATTACK_DAMAGE || attribute == Attributes.ATTACK_SPEED || attribute == Attributes.ATTACK_KNOCKBACK); - @Unique - private static final Predicate> onlyIronAttributes = (attribute) -> attribute instanceof IMagicAttribute; - } \ No newline at end of file diff --git a/src/main/java/io/redspace/ironsspellbooks/player/ClientPlayerEvents.java b/src/main/java/io/redspace/ironsspellbooks/player/ClientPlayerEvents.java index c3f71b8c9..38a80dd9b 100644 --- a/src/main/java/io/redspace/ironsspellbooks/player/ClientPlayerEvents.java +++ b/src/main/java/io/redspace/ironsspellbooks/player/ClientPlayerEvents.java @@ -1,7 +1,6 @@ package io.redspace.ironsspellbooks.player; import io.redspace.ironsspellbooks.IronsSpellbooks; -import io.redspace.ironsspellbooks.api.attribute.IMagicAttribute; import io.redspace.ironsspellbooks.api.entity.IMagicEntity; import io.redspace.ironsspellbooks.api.magic.SpellSelectionManager; import io.redspace.ironsspellbooks.api.registry.SpellRegistry; @@ -19,7 +18,6 @@ import io.redspace.ironsspellbooks.entity.mobs.dead_king_boss.DeadKingMusicManager; import io.redspace.ironsspellbooks.item.Scroll; import io.redspace.ironsspellbooks.item.SpellBook; -import io.redspace.ironsspellbooks.item.weapons.IMultihandWeapon; import io.redspace.ironsspellbooks.network.casting.CancelCastPacket; import io.redspace.ironsspellbooks.registries.ComponentRegistry; import io.redspace.ironsspellbooks.registries.MobEffectRegistry; @@ -34,6 +32,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.model.EntityModel; import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.Holder; import net.minecraft.core.component.DataComponents; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; @@ -58,6 +57,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.function.Predicate; @EventBusSubscriber(Dist.CLIENT) public class ClientPlayerEvents { @@ -207,57 +207,52 @@ public static void imbuedWeaponTooltips(ItemTooltipEvent event) { // } lines.add(1, Component.translatable("tooltip.irons_spellbooks.can_be_imbued_frame", Component.translatable("tooltip.irons_spellbooks.can_be_imbued_number", spellContainer.getActiveSpellCount(), spellContainer.getMaxSpellCount()).withStyle(ChatFormatting.YELLOW)).withStyle(ChatFormatting.GOLD)); } - if (stack.getItem() instanceof IMultihandWeapon) { - if (ServerConfigs.APPLY_ALL_MULTIHAND_ATTRIBUTES.get()) { - int i = TooltipsUtils.indexOfComponent(lines, "item.modifiers.mainhand"); - if (i >= 0) { - lines.set(i, Component.translatable("tooltip.irons_spellbooks.modifiers.multihand").withStyle(lines.get(i).getStyle())); - } - } else { - int i = TooltipsUtils.indexOfComponent(lines, "item.modifiers.mainhand"); - if (i >= 0) { - int endIndex = 0; - List linesToGrab = new ArrayList<>(); - for (int j = i; j < lines.size(); j++) { - var contents = lines.get(j).getContents(); - if (contents instanceof TranslatableContents translatableContents) { - //IronsSpellbooks.LOGGER.debug("FormatMultiTooltip translatableContents {}/{} :{}", j, lines.size(), translatableContents.getKey()); - if (translatableContents.getKey().startsWith("attribute.modifier")) { - //IronsSpellbooks.LOGGER.debug("FormatMultiTooltip attribute line: {} | args: {}", lines.get(j).getString(), translatableContents.getArgs()); - endIndex = j; - for (Object arg : translatableContents.getArgs()) { - if (arg instanceof Component component && component.getContents() instanceof TranslatableContents translatableContents2) { - //IronsSpellbooks.LOGGER.debug("attribute.modifier arg translatable key: {} ({})", translatableContents2.getKey(), getAttributeForDescriptionId(translatableContents2.getKey())); - if (getAttributeForDescriptionId(translatableContents2.getKey()) instanceof IMagicAttribute) { - linesToGrab.add(j); - } + if (stack.has(ComponentRegistry.MULTIHAND_WEAPON)) { + Predicate> predicate = ServerConfigs.APPLY_ALL_MULTIHAND_ATTRIBUTES.get() ? Utils.NON_BASE_ATTRIBUTES : Utils.ONLY_MAGIC_ATTRIBUTES; + int i = TooltipsUtils.indexOfComponent(lines, "item.modifiers.mainhand"); + if (i >= 0) { + int endIndex = 0; + List linesToGrab = new ArrayList<>(); + for (int j = i; j < lines.size(); j++) { + var contents = lines.get(j).getContents(); + if (contents instanceof TranslatableContents translatableContents) { + //IronsSpellbooks.LOGGER.debug("FormatMultiTooltip translatableContents {}/{} :{}", j, lines.size(), translatableContents.getKey()); + if (translatableContents.getKey().startsWith("attribute.modifier")) { + //IronsSpellbooks.LOGGER.debug("FormatMultiTooltip attribute line: {} | args: {}", lines.get(j).getString(), translatableContents.getArgs()); + endIndex = j; + for (Object arg : translatableContents.getArgs()) { + if (arg instanceof Component component && component.getContents() instanceof TranslatableContents translatableContents2) { + //IronsSpellbooks.LOGGER.debug("attribute.modifier arg translatable key: {} ({})", translatableContents2.getKey(), getAttributeForDescriptionId(translatableContents2.getKey())); + var atr = getAttributeForDescriptionId(translatableContents2.getKey()); + if (atr != null && predicate.test(BuiltInRegistries.ATTRIBUTE.wrapAsHolder(atr))) { + linesToGrab.add(j); } } - } else if (i != j && translatableContents.getKey().startsWith("item.modifiers")) { - break; } - } else { - //Based on the ItemStack tooltip code, the only attributes getting here should be the base UUID attributes - for (Component line : lines.get(j).getSiblings()) { - if (line.getContents() instanceof TranslatableContents translatableContents) { - if (translatableContents.getKey().startsWith("attribute.modifier")) { - endIndex = j; - } + } else if (i != j && translatableContents.getKey().startsWith("item.modifiers")) { + break; + } + } else { + //Based on the ItemStack tooltip code, the only attributes getting here should be the base UUID attributes + for (Component line : lines.get(j).getSiblings()) { + if (line.getContents() instanceof TranslatableContents translatableContents) { + if (translatableContents.getKey().startsWith("attribute.modifier")) { + endIndex = j; } } } } - //IronsSpellbooks.LOGGER.debug("FormatMultiTooltip: lines to grab: {}", linesToGrab); - if (!linesToGrab.isEmpty()) { - //IronsSpellbooks.LOGGER.debug("FormatMultiTooltip: end index: {} ({})", endIndex, lines.get(endIndex)); - lines.add(++endIndex, Component.empty()); - lines.add(++endIndex, Component.translatable("tooltip.irons_spellbooks.modifiers.multihand").withStyle(lines.get(i).getStyle())); - for (Integer index : linesToGrab) { - lines.add(++endIndex, lines.get(index)); - } - for (int j = linesToGrab.size() - 1; j >= 0; j--) { - lines.remove((int) linesToGrab.get(j)); - } + } + //IronsSpellbooks.LOGGER.debug("FormatMultiTooltip: lines to grab: {}", linesToGrab); + if (!linesToGrab.isEmpty()) { + //IronsSpellbooks.LOGGER.debug("FormatMultiTooltip: end index: {} ({})", endIndex, lines.get(endIndex)); + lines.add(++endIndex, Component.empty()); + lines.add(++endIndex, Component.translatable("tooltip.irons_spellbooks.modifiers.multihand").withStyle(lines.get(i).getStyle())); + for (Integer index : linesToGrab) { + lines.add(++endIndex, lines.get(index)); + } + for (int j = linesToGrab.size() - 1; j >= 0; j--) { + lines.remove((int) linesToGrab.get(j)); } } } diff --git a/src/main/java/io/redspace/ironsspellbooks/registries/ComponentRegistry.java b/src/main/java/io/redspace/ironsspellbooks/registries/ComponentRegistry.java index 3dc2605cc..a609353bd 100644 --- a/src/main/java/io/redspace/ironsspellbooks/registries/ComponentRegistry.java +++ b/src/main/java/io/redspace/ironsspellbooks/registries/ComponentRegistry.java @@ -36,4 +36,5 @@ private static DeferredHolder, DataComponentType> re public static final DeferredHolder, DataComponentType> WAYWARD_COMPASS = register("wayward_compass", (builder) -> builder.persistent(WaywardCompassData.CODEC).networkSynchronized(WaywardCompassData.STREAM_CODEC).cacheEncoding()); public static final DeferredHolder, DataComponentType> CROSSBOW_LOAD_STATE = register("crossbow_load_state", (builder) -> builder.persistent(AutoloaderCrossbow.LoadStateComponent.CODEC).networkSynchronized(AutoloaderCrossbow.LoadStateComponent.STREAM_CODEC).cacheEncoding()); public static final DeferredHolder, DataComponentType> CASTING_IMPLEMENT = register("casting_implement", (builder) -> builder.persistent(Unit.CODEC).networkSynchronized(StreamCodec.unit(Unit.INSTANCE)).cacheEncoding()); + public static final DeferredHolder, DataComponentType> MULTIHAND_WEAPON = register("multihand_weapon", (builder) -> builder.persistent(Unit.CODEC).networkSynchronized(StreamCodec.unit(Unit.INSTANCE)).cacheEncoding()); }