Skip to content

Commit

Permalink
Add sword blocking to old combat
Browse files Browse the repository at this point in the history
  • Loading branch information
haykam821 committed Jan 28, 2025
1 parent ba8769b commit c2e3caa
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 3 deletions.
28 changes: 25 additions & 3 deletions src/main/java/xyz/nucleoid/plasmid/api/game/common/OldCombat.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,23 @@

import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.AttributeModifierSlot;
import net.minecraft.component.type.ConsumableComponent;
import net.minecraft.entity.attribute.EntityAttribute;
import net.minecraft.entity.attribute.EntityAttributeModifier;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.item.*;
import net.minecraft.item.consume.UseAction;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.Identifier;
import net.minecraft.util.Unit;
import xyz.nucleoid.plasmid.impl.component.PlasmidDataComponentTypes;

/**
* A utility class that allows old-style 1.8 combat to be applied to any given {@link ItemStack}.
* <p>
* This works by modifying the damage and attack speed attributes to match their 1.8 levels.
* In addition, sword blocking is reinstated.
*/
public final class OldCombat {
private static final RegistryEntry<EntityAttribute> DAMAGE_ATTRIBUTE = EntityAttributes.ATTACK_DAMAGE;
Expand All @@ -37,14 +43,31 @@ public final class OldCombat {
private static final int SWORD_BASE_DAMAGE = 3;

public static ItemStack applyTo(ItemStack stack) {
stack.set(PlasmidDataComponentTypes.OLD_COMBAT, Unit.INSTANCE);

if (stack.getItem() instanceof SwordItem) {
stack.set(DataComponentTypes.CONSUMABLE, ConsumableComponent.builder()
.consumeSeconds(Float.MAX_VALUE)
.useAction(UseAction.BLOCK)
.sound(RegistryEntry.of(SoundEvents.INTENTIONALLY_EMPTY))
.consumeParticles(false)
.build());
}

applyAttributeModifiersTo(stack);

return stack;
}

private static void applyAttributeModifiersTo(ItemStack stack) {
if (!stack.contains(DataComponentTypes.TOOL)) {
return stack;
return;
}

var material = getToolMaterial(stack);

if (material == null) {
return stack;
return;
}

var defaultModifiers = stack.get(DataComponentTypes.ATTRIBUTE_MODIFIERS);
Expand All @@ -63,7 +86,6 @@ public static ItemStack applyTo(ItemStack stack) {
}

stack.set(DataComponentTypes.ATTRIBUTE_MODIFIERS, defaultModifiers);
return stack;
}

private static EntityAttributeModifier createSpeedModifier() {
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/xyz/nucleoid/plasmid/impl/Plasmid.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import xyz.nucleoid.plasmid.impl.portal.game.SingleGamePortalConfig;
import xyz.nucleoid.plasmid.impl.command.*;
import xyz.nucleoid.plasmid.impl.compatibility.TrinketsCompatibility;
import xyz.nucleoid.plasmid.impl.component.PlasmidDataComponentTypes;
import xyz.nucleoid.plasmid.impl.portal.menu.*;

public final class Plasmid implements ModInitializer {
Expand Down Expand Up @@ -67,6 +68,8 @@ public void onInitialize() {
throw new GameOpenException(Text.translatable("text.plasmid.map.open.invalid_game", id != null ? id.toString() : context.game()));
});

PlasmidDataComponentTypes.register();

this.registerCallbacks();

if (FabricLoader.getInstance().isModLoaded("trinkets")) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package xyz.nucleoid.plasmid.impl.component;

import eu.pb4.polymer.core.api.other.PolymerComponent;
import net.minecraft.component.ComponentType;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.util.Identifier;
import net.minecraft.util.Unit;
import xyz.nucleoid.plasmid.impl.Plasmid;

public final class PlasmidDataComponentTypes {
private PlasmidDataComponentTypes() {
}

public static final ComponentType<Unit> OLD_COMBAT = register("old_combat", ComponentType.<Unit>builder()
.codec(Unit.CODEC)
.build());

private static <T> ComponentType<T> register(String path, ComponentType<T> type) {
return Registry.register(Registries.DATA_COMPONENT_TYPE, Identifier.of(Plasmid.ID, path), type);
}

public static void register() {
PolymerComponent.registerDataComponent(OLD_COMBAT);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package xyz.nucleoid.plasmid.mixin.game.common;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import com.llamalad7.mixinextras.sugar.ref.LocalFloatRef;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.item.ShieldItem;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Constant;
import org.spongepowered.asm.mixin.injection.ModifyConstant;
import xyz.nucleoid.plasmid.impl.component.PlasmidDataComponentTypes;

@Mixin(LivingEntity.class)
public class LivingEntityMixin {
@Shadow
@Final
private ItemStack activeItemStack;

@WrapOperation(
method = "blockedByShield",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/item/ItemStack;getItem()Lnet/minecraft/item/Item;"
)
)
private Item allowOldCombatSwordBlocking(ItemStack stack, Operation<Item> operation) {
// Allow fulfilling the instanceof ShieldItem check
if (stack.contains(PlasmidDataComponentTypes.OLD_COMBAT)) {
return Items.SHIELD;
}

return operation.call(stack);
}

@WrapOperation(
method = "damage",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/entity/LivingEntity;blockedByShield(Lnet/minecraft/entity/damage/DamageSource;)Z"
)
)
private boolean applyHalfDamageFromSwordBlocking(LivingEntity entity, DamageSource source, Operation<Boolean> operation, @Local(ordinal = 0, argsOnly = true) LocalFloatRef amount) {
if (operation.call(entity, source)) {
ItemStack stack = entity.getBlockingItem();

if (!stack.contains(PlasmidDataComponentTypes.OLD_COMBAT) || stack.getItem() instanceof ShieldItem) {
return true;
}

amount.set(Math.max(0, (amount.get() / 2) - 0.5f));
}

return false;
}

@ModifyConstant(
method = "getBlockingItem",
constant = @Constant(intValue = 5)
)
private int allowInstantSwordBlocking(int original) {
if (!this.activeItemStack.contains(PlasmidDataComponentTypes.OLD_COMBAT) || this.activeItemStack.getItem() instanceof ShieldItem) {
return original;
}

return 0;
}
}
1 change: 1 addition & 0 deletions src/main/resources/plasmid.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"chat.PlayerEntityMixin",
"chat.PlayerListS2CPacketEntryAccessor",
"chat.ServerPlayerEntityMixin",
"game.common.LivingEntityMixin",
"game.portal.EntityMixin",
"game.portal.SignBlockEntityMixin",
"game.rule.EquippableComponentMixin",
Expand Down

0 comments on commit c2e3caa

Please sign in to comment.