Mojmap + Stonecutter

This commit is contained in:
lowercasebtw
2025-11-23 17:08:22 -05:00
parent 46f36864c2
commit 1ad6c1f588
48 changed files with 847 additions and 755 deletions

View File

@@ -0,0 +1,66 @@
package eu.midnightdust.swordblocking;
import eu.midnightdust.swordblocking.config.SwordBlockingConfig;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.ShieldItem;
//? fabric {
/*import dev.kikugie.fletching_table.annotation.fabric.Entrypoint;
import net.fabricmc.api.ClientModInitializer;
*///?} else {
import net.neoforged.api.distmarker.Dist;
import net.neoforged.fml.common.Mod;
//?}
//? fabric
/*@Entrypoint*/
//? neoforge
@Mod(value = SwordBlockingClient.MOD_ID, dist = Dist.CLIENT)
public final class SwordBlockingClient
//? fabric
/*implements ClientModInitializer*/
{
public static final String MOD_ID = "@MODID@";
// TODO/NOTE: I know this can be condensed more but i'm tired so will recheck later
public static boolean canEntityBlock(ItemStack mainHandStack, ItemStack offHandStack) {
return SwordBlockingConfig.enabled && canShieldSwordBlock(mainHandStack, offHandStack);
}
// TODO/NOTE: I know this can be condensed more but i'm tired so will recheck later
public static boolean canShieldSwordBlock(ItemStack mainHandStack, ItemStack offHandStack) {
if (SwordBlockingConfig.enabled && (offHandStack.getItem() instanceof ShieldItem || mainHandStack.getItem() instanceof ShieldItem)) {
final Item weaponItem = offHandStack.getItem() instanceof ShieldItem ? mainHandStack.getItem() : offHandStack.getItem();
return weaponItem.components().has(DataComponents.DAMAGE);
} else {
return false;
}
}
// TODO/NOTE: I know this can be condensed more but i'm tired so will recheck later
public static boolean shouldHideShield(ItemStack mainHandStack, ItemStack offHandStack, ItemStack stack) {
if (SwordBlockingConfig.enabled && stack.getItem() instanceof ShieldItem) {
return (SwordBlockingConfig.alwaysHideShield && SwordBlockingConfig.hideShield) ||
(SwordBlockingConfig.hideShield && SwordBlockingClient.canShieldSwordBlock(mainHandStack, offHandStack));
} else {
return false;
}
}
private void initialize() {
SwordBlockingConfig.init(MOD_ID, SwordBlockingConfig.class);
}
//? neoforge {
public SwordBlockingClient() {
initialize();
}
//?} else {
/*@Override
public void onInitializeClient() {
initialize();
}
*///?}
}

View File

@@ -0,0 +1,26 @@
package eu.midnightdust.swordblocking.config;
import eu.midnightdust.lib.config.MidnightConfig;
public class SwordBlockingConfig extends MidnightConfig {
@Entry
public static boolean enabled = true;
@Entry
public static boolean hideShield = true;
@Entry
public static boolean alwaysHideShield = true;
@Entry
public static boolean hideOffhandSlot = false;
@Entry
public static boolean disableUseEquipAnimation = false;
@Entry
public static boolean lockBlockingArmPosition = false;
@Entry
public static boolean blockHitAnimation = false;
}

View File

@@ -0,0 +1,10 @@
package eu.midnightdust.swordblocking.ducks;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.item.ItemStack;
public interface ArmedItemStackData {
ItemStack swordblocking$getItemHeldByArm(HumanoidArm humanoidArm);
void swordblocking$setItemHeldByArm(HumanoidArm arm, ItemStack itemStack);
}

View File

@@ -0,0 +1,51 @@
package eu.midnightdust.swordblocking.mixins;
import eu.midnightdust.swordblocking.ducks.ArmedItemStackData;
import net.minecraft.client.renderer.entity.state.ArmedEntityRenderState;
import net.minecraft.client.renderer.item.ItemModelResolver;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ArmedEntityRenderState.class)
public abstract class MixinArmedEntityRenderState implements ArmedItemStackData {
@Unique
private ItemStack swordblocking$leftStack = ItemStack.EMPTY;
@Unique
private ItemStack swordblocking$rightStack = ItemStack.EMPTY;
@Inject(method = "extractArmedEntityRenderState", at = @At("TAIL"))
private static void swordBlocking$storeRequiredData(LivingEntity livingEntity, ArmedEntityRenderState armedEntityRenderState, ItemModelResolver itemModelResolver, CallbackInfo ci) {
ArmedItemStackData armedItemStackData = (ArmedItemStackData) armedEntityRenderState;
armedItemStackData.swordblocking$setItemHeldByArm(HumanoidArm.LEFT, livingEntity.getItemHeldByArm(HumanoidArm.LEFT));
armedItemStackData.swordblocking$setItemHeldByArm(HumanoidArm.RIGHT, livingEntity.getItemHeldByArm(HumanoidArm.RIGHT));
}
@Override
public ItemStack swordblocking$getItemHeldByArm(HumanoidArm arm) {
if (arm == HumanoidArm.LEFT) {
return swordblocking$leftStack;
} else if (arm == HumanoidArm.RIGHT) {
return swordblocking$rightStack;
} else {
throw new UnsupportedOperationException();
}
}
@Override
public void swordblocking$setItemHeldByArm(HumanoidArm arm, ItemStack itemStack) {
if (arm == HumanoidArm.LEFT) {
swordblocking$leftStack = itemStack;
} else if (arm == HumanoidArm.RIGHT) {
swordblocking$rightStack = itemStack;
} else {
throw new UnsupportedOperationException();
}
}
}

View File

@@ -0,0 +1,21 @@
package eu.midnightdust.swordblocking.mixins;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import eu.midnightdust.swordblocking.config.SwordBlockingConfig;
import net.minecraft.client.gui.Gui;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.ShieldItem;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@Mixin(Gui.class)
public abstract class MixinGui {
@ModifyExpressionValue(method = "renderItemHotbar", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getOffhandItem()Lnet/minecraft/world/item/ItemStack;"))
public ItemStack swordBlocking$hideOffHandSlot(ItemStack original) {
if (SwordBlockingConfig.enabled && SwordBlockingConfig.hideOffhandSlot && original.getItem() instanceof ShieldItem) {
return ItemStack.EMPTY;
} else {
return original;
}
}
}

View File

@@ -0,0 +1,48 @@
package eu.midnightdust.swordblocking.mixins;
import eu.midnightdust.swordblocking.SwordBlockingClient;
import eu.midnightdust.swordblocking.config.SwordBlockingConfig;
import eu.midnightdust.swordblocking.ducks.ArmedItemStackData;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.renderer.entity.state.HumanoidRenderState;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.ShieldItem;
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.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(HumanoidModel.class)
public abstract class MixinHumanoidModel {
@Shadow
protected abstract void poseLeftArm(HumanoidRenderState renderState, HumanoidModel.ArmPose pose);
@Shadow
protected abstract void poseRightArm(HumanoidRenderState renderState, HumanoidModel.ArmPose pose);
@Inject(method = "setupAnim(Lnet/minecraft/client/renderer/entity/state/HumanoidRenderState;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/model/HumanoidModel;setupAttackAnimation(Lnet/minecraft/client/renderer/entity/state/HumanoidRenderState;F)V", shift = At.Shift.BEFORE))
private void swordBlocking$setBlockingAngles(HumanoidRenderState renderState, CallbackInfo ci) {
final ArmedItemStackData armedItemStackData = (ArmedItemStackData) renderState;
final ItemStack offHandStack = armedItemStackData.swordblocking$getItemHeldByArm(HumanoidArm.LEFT);
final ItemStack mainHandStack = armedItemStackData.swordblocking$getItemHeldByArm(HumanoidArm.RIGHT);
if (renderState.isUsingItem && SwordBlockingClient.canEntityBlock(mainHandStack, offHandStack)) {
if (offHandStack.getItem() instanceof ShieldItem) {
this.poseRightArm(renderState, HumanoidModel.ArmPose.BLOCK);
} else {
this.poseLeftArm(renderState, HumanoidModel.ArmPose.BLOCK);
}
}
}
@Redirect(method = "poseBlockingArm", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Mth;clamp(FFF)F"))
private float swordBlocking$lockArmPosition(float value, float min, float max) {
if (SwordBlockingConfig.enabled && SwordBlockingConfig.lockBlockingArmPosition) {
return 0F;
} else {
return value;
}
}
}

View File

@@ -0,0 +1,28 @@
package eu.midnightdust.swordblocking.mixins;
import com.llamalad7.mixinextras.sugar.Local;
import eu.midnightdust.swordblocking.SwordBlockingClient;
import eu.midnightdust.swordblocking.config.SwordBlockingConfig;
import eu.midnightdust.swordblocking.ducks.ArmedItemStackData;
import net.minecraft.client.model.ArmedModel;
import net.minecraft.client.model.EntityModel;
import net.minecraft.client.renderer.entity.layers.ItemInHandLayer;
import net.minecraft.client.renderer.entity.state.ArmedEntityRenderState;
import net.minecraft.client.renderer.item.ItemStackRenderState;
import net.minecraft.world.entity.HumanoidArm;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(ItemInHandLayer.class)
public abstract class MixinItemInHandLayer<S extends ArmedEntityRenderState, M extends EntityModel<S> & ArmedModel> {
@Redirect(method = "renderArmWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/item/ItemStackRenderState;isEmpty()Z"))
private boolean swordBlocking$hideShield(ItemStackRenderState instance, @Local(argsOnly = true) S renderState, @Local(argsOnly = true) HumanoidArm arm) {
if (SwordBlockingConfig.enabled) {
final ArmedItemStackData armedItemStackData = (ArmedItemStackData) renderState;
return SwordBlockingClient.shouldHideShield(armedItemStackData.swordblocking$getItemHeldByArm(HumanoidArm.RIGHT), armedItemStackData.swordblocking$getItemHeldByArm(HumanoidArm.LEFT), armedItemStackData.swordblocking$getItemHeldByArm(arm));
}
return instance.isEmpty();
}
}

View File

@@ -0,0 +1,82 @@
package eu.midnightdust.swordblocking.mixins;
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.sugar.Local;
import com.mojang.blaze3d.vertex.PoseStack;
import eu.midnightdust.swordblocking.SwordBlockingClient;
import eu.midnightdust.swordblocking.config.SwordBlockingConfig;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.renderer.ItemInHandRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.ItemUseAnimation;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ItemInHandRenderer.class)
public abstract class MixinItemInHandRenderer {
@Shadow
@Final
private Minecraft minecraft;
@Shadow
protected abstract void applyItemArmAttackTransform(PoseStack poseStack, HumanoidArm hand, float swingProgress);
@WrapMethod(method = "renderItem")
public void swordBlocking$hideShield(LivingEntity entity, ItemStack stack, ItemDisplayContext displayContext, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, Operation<Void> original) {
if (!SwordBlockingClient.shouldHideShield(entity.getMainHandItem(), entity.getOffhandItem(), stack)) {
original.call(entity, stack, displayContext, poseStack, bufferSource, packedLight);
}
}
@Redirect(method = "renderArmWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/AbstractClientPlayer;getUsedItemHand()Lnet/minecraft/world/InteractionHand;", ordinal = 1))
private InteractionHand swordBlocking$changeActiveHand(AbstractClientPlayer instance) {
final InteractionHand activeHand = instance.getUsedItemHand();
if (SwordBlockingClient.canEntityBlock(instance.getMainHandItem(), instance.getOffhandItem())) {
return swordBlocking$getBlockingHand(activeHand);
} else {
return activeHand;
}
}
@Redirect(method = "renderArmWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;getUseAnimation()Lnet/minecraft/world/item/ItemUseAnimation;"))
private ItemUseAnimation swordBlocking$changeItemAction(ItemStack stack, @Local(argsOnly = true) AbstractClientPlayer player, @Local(argsOnly = true) InteractionHand interactionHand) {
final ItemUseAnimation defaultUseAction = stack.getUseAnimation();
if (SwordBlockingClient.canEntityBlock(player.getMainHandItem(), player.getOffhandItem())) {
return swordBlocking$getBlockingHand(player.getUsedItemHand()) == interactionHand ? ItemUseAnimation.BLOCK : defaultUseAction;
} else {
return defaultUseAction;
}
}
@Inject(method = "renderArmWithItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;applyItemArmTransform(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/world/entity/HumanoidArm;F)V", ordinal = 3, shift = At.Shift.AFTER))
private void swordBlocking$applySwingOffset(AbstractClientPlayer player, float partialTicks, float pitch, InteractionHand hand, float swingProgress, ItemStack stack, float equippedProgress, PoseStack poseStack, MultiBufferSource buffer, int combinedLight, CallbackInfo ci, @Local HumanoidArm arm) {
if (SwordBlockingConfig.enabled && SwordBlockingConfig.blockHitAnimation) {
this.applyItemArmAttackTransform(poseStack, arm, swingProgress);
}
}
@WrapMethod(method = "itemUsed")
private void swordBlocking$disableEquipAnimation(InteractionHand hand, Operation<Void> original) {
if (!SwordBlockingConfig.disableUseEquipAnimation || this.minecraft.player == null || !this.minecraft.player.isUsingItem()) {
original.call(hand);
}
}
@Unique
private InteractionHand swordBlocking$getBlockingHand(InteractionHand interactionHand) {
return interactionHand == InteractionHand.MAIN_HAND ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND;
}
}

View File

@@ -0,0 +1,41 @@
package eu.midnightdust.swordblocking.mixins;
import eu.midnightdust.swordblocking.SwordBlockingClient;
import eu.midnightdust.swordblocking.config.SwordBlockingConfig;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.ShieldItem;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
//? fabric {
/*import net.fabricmc.api.Environment;
import net.fabricmc.api.EnvType;
*///? }
@Mixin(PlayerRenderer.class)
public abstract class MixinPlayerRenderer {
//? fabric
/*@Environment(EnvType.CLIENT)*/
@Inject(method = "getArmPose(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/InteractionHand;)Lnet/minecraft/client/model/HumanoidModel$ArmPose;", at = @At(value = "RETURN"), cancellable = true)
private static void swordBlocking$getArmPose(Player player, ItemStack stack, InteractionHand hand, CallbackInfoReturnable<HumanoidModel.ArmPose> cir) {
if (SwordBlockingConfig.enabled) {
final ItemStack handStack = player.getItemInHand(hand);
final ItemStack offStack = player.getItemInHand(hand.equals(InteractionHand.MAIN_HAND) ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND);
if (!SwordBlockingConfig.alwaysHideShield && (handStack.getItem() instanceof ShieldItem) && !SwordBlockingClient.canShieldSwordBlock(player.getMainHandItem(), player.getOffhandItem())) {
return;
}
if (offStack.getItem() instanceof ShieldItem && SwordBlockingClient.canEntityBlock(player.getMainHandItem(), player.getOffhandItem())) {
cir.setReturnValue(HumanoidModel.ArmPose.BLOCK);
} else if (handStack.getItem() instanceof ShieldItem && SwordBlockingConfig.hideShield && (cir.getReturnValue() == HumanoidModel.ArmPose.ITEM || cir.getReturnValue() == HumanoidModel.ArmPose.BLOCK)) {
cir.setReturnValue(HumanoidModel.ArmPose.EMPTY);
}
}
}
}

View File

@@ -0,0 +1,30 @@
modLoader = "javafml"
loaderVersion = "[1,)"
license = "${license}"
issueTrackerURL = "${issues}"
[[mods]]
modId = "${id}"
version = "${version}"
displayName = "${name}"
description = "${description}"
logoFile = "assets/${id}/icon.png"
authors = ["Motschen", "TeamMidnightDust", "lowercasebtw"]
displayURL = "${modrinth}"
[[mixins]]
config = "${id}.mixins.json"
[[dependencies.${id}]]
modId = "neoforge"
mandatory = true
versionRange = "[${neoforge_version},)"
ordering = "NONE"
side = "CLIENT"
[[dependencies.${id}]]
modId = "minecraft"
mandatory = true
versionRange = "${minecraft_version_range}"
ordering = "NONE"
side = "CLIENT"

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -0,0 +1,11 @@
{
"swordblocking.midnightconfig.title": "Sword Blocking Config",
"swordblocking.midnightconfig.enabled": "Enabled",
"swordblocking.midnightconfig.hideShield": "Hide Shield",
"swordblocking.midnightconfig.alwaysHideShield": "Always Hide Shield",
"swordblocking.midnightconfig.hideOffhandSlot": "Hide Offhand Slot",
"swordblocking.midnightconfig.hideOffhandSlot.tooltip": "Hides the offhand slot when a shield is in the offhand.",
"swordblocking.midnightconfig.disableUseEquipAnimation": "Remove the equip animation when blocking.",
"swordblocking.midnightconfig.lockBlockingArmPosition": "Disable arm moving when blocking.",
"swordblocking.midnightconfig.blockHitAnimation": "Enable block hitting animation."
}

View File

@@ -0,0 +1,11 @@
{
"swordblocking.midnightconfig.title": "Конфигурация Sword Blocking",
"swordblocking.midnightconfig.enabled": "Включено",
"swordblocking.midnightconfig.hideShield": "Спрятать щит",
"swordblocking.midnightconfig.alwaysHideShield": "Всегда прятать щит",
"swordblocking.midnightconfig.hideOffhandSlot": "Скрывать слот второй руки",
"swordblocking.midnightconfig.hideOffhandSlot.tooltip": "Скрывает слот второй руки, если в ней находится щит.",
"swordblocking.midnightconfig.disableUseEquipAnimation": "Удалять анимацию оснащения при блокировании.",
"swordblocking.midnightconfig.lockBlockingArmPosition": "Отключить движение руки при блокировании.",
"swordblocking.midnightconfig.blockHitAnimation": "Включить анимацию удара по блоку."
}

View File

@@ -0,0 +1,35 @@
{
"schemaVersion": 1,
"id": "${id}",
"version": "${version}",
"name": "${name}",
"description": "${description}",
"authors": [
"Motschen",
"TeamMidnightDust",
"lowercasebtw"
],
"contact": {
"sources": "${source}",
"issues": "${issues}"
},
"license": "${license}",
"icon": "assets/${id}/icon.png",
"environment": "client",
"depends": {
"fabricloader": ">=${fabric_loader_version}",
"minecraft": "${minecraft_version_range}",
"fabric-api": "*",
"midnightlib": "*"
},
"custom": {
"modmenu": {
"links": {
"modmenu.discord": "${discord}",
"modmenu.modrinth": "${modrinth}",
"modmenu.curseforge": "${curseforge}"
},
"update_checker": true
}
}
}

View File

@@ -0,0 +1,19 @@
{
"required": true,
"package": "eu.midnightdust.swordblocking.mixins",
"compatibilityLevel": "JAVA_17",
"client": [
"MixinGui",
"MixinArmedEntityRenderState",
"MixinHumanoidModel",
"MixinItemInHandLayer",
"MixinItemInHandRenderer",
"MixinPlayerRenderer"
],
"injectors": {
"defaultRequire": 1
},
"mixinextras": {
"minVersion": "0.5.0"
}
}