Skip to content

Commit

Permalink
make multihand weapon handling component based
Browse files Browse the repository at this point in the history
  • Loading branch information
iron431 committed Oct 17, 2024
1 parent 855dc0f commit 34e64f4
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 102 deletions.
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -78,6 +80,9 @@ public class Utils {

public static final RandomSource random = RandomSource.createThreadSafe();

public static final Predicate<Holder<Attribute>> ONLY_MAGIC_ATTRIBUTES = (attribute) -> attribute.value() instanceof IMagicAttribute;
public static final Predicate<Holder<Attribute>> 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();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;


Expand All @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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 {
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -27,7 +26,6 @@

import java.util.List;
import java.util.Map;
import java.util.function.Predicate;

@Mixin(LivingEntity.class)
public abstract class LivingEntityMixin {
Expand Down Expand Up @@ -66,8 +64,6 @@ public void isCurrentlyGlowing(CallbackInfoReturnable<Boolean> 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<Map<EquipmentSlot, ItemStack>> 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
Expand All @@ -76,41 +72,29 @@ public void handleEquipmentChanges(CallbackInfoReturnable<Map<EquipmentSlot, Ite
return;
}
LivingEntity self = (LivingEntity) (Object) this;
for (EquipmentSlot slot : handSlots) {
ItemStack currentStack = changedEquipment.get(slot);
if (currentStack == null) {
// If this stack was not changed, continue
continue;
ItemStack toStack = changedEquipment.get(EquipmentSlot.MAINHAND);
if (toStack == null) {
// If this stack was not changed, continue
return;
}
ItemStack fromStack = getLastHandItem(EquipmentSlot.MAINHAND);
ItemStack offhandStack = self.getOffhandItem();
//offhand swap
if (fromStack == offhandStack) {
return;
}
//Do we even care
if (!offhandStack.isEmpty() && offhandStack.has(ComponentRegistry.MULTIHAND_WEAPON)) {
//did we equip a multihand item? (hide offhand)
if (toStack.has(ComponentRegistry.MULTIHAND_WEAPON)) {
if (!toStack.isEmpty()) {
self.getAttributes().removeAttributeModifiers(filterApplicableAttributes(offhandStack.getAttributeModifiers()));
}
}
ItemStack oldStack = getLastHandItem(slot);
//IronsSpellbooks.LOGGER.debug("LivingMixin.handleEquipmentChanges - Hands: {}| {} -> {}", 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()));
}
}
}
Expand All @@ -121,17 +105,12 @@ private static Multimap<Holder<Attribute>, AttributeModifier> filterApplicableAt
var list = modifiers.modifiers().stream().filter(entry -> entry.slot() == EquipmentSlotGroup.MAINHAND).toList();
Multimap<Holder<Attribute>, 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());
}
}
return map;
}

@Unique
private static final Predicate<Holder<Attribute>> allNonBaseAttackAttributes = (attribute) -> !(attribute == Attributes.ENTITY_INTERACTION_RANGE || attribute == Attributes.ATTACK_DAMAGE || attribute == Attributes.ATTACK_SPEED || attribute == Attributes.ATTACK_KNOCKBACK);
@Unique
private static final Predicate<Holder<Attribute>> onlyIronAttributes = (attribute) -> attribute instanceof IMagicAttribute;

}
Loading

0 comments on commit 34e64f4

Please sign in to comment.