Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading