From 6c4e5d099024d473d555d9e87bf994013048a019 Mon Sep 17 00:00:00 2001
From: Daomephsta <10936237+Daomephsta@users.noreply.github.com>
Date: Sun, 5 Jun 2022 08:06:55 +1200
Subject: [PATCH] Make getKnockbackResistance() work for all materials (#2129)

* Make getKnockbackResistance() work for all materials

* Add missing license to ArmorItemMixin.java

* Fix all build failures

* Document ArmorItemMixin
---
 .../fabric/mixin/item/ArmorItemMixin.java     |  55 ++++++++++++
 .../resources/fabric-item-api-v1.mixins.json  |   3 +-
 .../item/ArmorKnockbackResistanceTest.java    |  80 ++++++++++++++++++
 .../models/item/wooden_boots.json             |   8 ++
 .../textures/models/armor/wood_layer_1.png    | Bin 0 -> 273 bytes
 .../textures/models/armor/wood_layer_2.png    | Bin 0 -> 204 bytes
 .../src/testmod/resources/fabric.mod.json     |   3 +-
 7 files changed, 147 insertions(+), 2 deletions(-)
 create mode 100644 fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/ArmorItemMixin.java
 create mode 100644 fabric-item-api-v1/src/testmod/java/net/fabricmc/fabric/test/item/ArmorKnockbackResistanceTest.java
 create mode 100644 fabric-item-api-v1/src/testmod/resources/assets/fabric-item-api-v1-testmod/models/item/wooden_boots.json
 create mode 100644 fabric-item-api-v1/src/testmod/resources/assets/minecraft/textures/models/armor/wood_layer_1.png
 create mode 100644 fabric-item-api-v1/src/testmod/resources/assets/minecraft/textures/models/armor/wood_layer_2.png

diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/ArmorItemMixin.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/ArmorItemMixin.java
new file mode 100644
index 000000000..7e2ebe7b7
--- /dev/null
+++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/ArmorItemMixin.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016, 2017, 2018, 2019 FabricMC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.fabricmc.fabric.mixin.item;
+
+import java.util.UUID;
+
+import com.google.common.collect.ImmutableMultimap;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.ModifyVariable;
+import org.spongepowered.asm.mixin.Final;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+
+import net.minecraft.entity.attribute.EntityAttributeModifier;
+import net.minecraft.entity.attribute.EntityAttributes;
+import net.minecraft.entity.attribute.EntityAttribute;
+import net.minecraft.entity.EquipmentSlot;
+import net.minecraft.item.ArmorItem;
+import net.minecraft.item.ArmorMaterial;
+import net.minecraft.item.ArmorMaterials;
+
+@Mixin(ArmorItem.class)
+public class ArmorItemMixin {
+	@Shadow private static @Final UUID[] MODIFIERS;
+	@Shadow protected @Final float knockbackResistance;
+
+	/* Vanilla only adds a knockback resistance modifier to ArmorItems made of ArmorMaterials.NETHERITE. This mixin
+	 * adds a knockback resistance modifier to any ArmorItem if knockbackResistance is > 0.0F.
+	 */
+	@ModifyVariable(method = "<init>", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/ImmutableMultimap$Builder;build()Lcom/google/common/collect/ImmutableMultimap;"))
+	private ImmutableMultimap.Builder<EntityAttribute, EntityAttributeModifier> fabric_knockbackResistance(ImmutableMultimap.Builder<EntityAttribute, EntityAttributeModifier> builder, ArmorMaterial material, EquipmentSlot slot) {
+		// Vanilla handles netherite
+		if (material != ArmorMaterials.NETHERITE && knockbackResistance > 0.0F) {
+			builder.put(EntityAttributes.GENERIC_KNOCKBACK_RESISTANCE, new EntityAttributeModifier(
+					MODIFIERS[slot.getEntitySlotId()], "Armor knockback resistance",
+					knockbackResistance, EntityAttributeModifier.Operation.ADDITION));
+		}
+
+		return builder;
+	}
+}
diff --git a/fabric-item-api-v1/src/main/resources/fabric-item-api-v1.mixins.json b/fabric-item-api-v1/src/main/resources/fabric-item-api-v1.mixins.json
index 524c59b9a..69d431532 100644
--- a/fabric-item-api-v1/src/main/resources/fabric-item-api-v1.mixins.json
+++ b/fabric-item-api-v1/src/main/resources/fabric-item-api-v1.mixins.json
@@ -5,7 +5,8 @@
   "mixins": [
     "ItemStackMixin",
     "ItemMixin",
-    "LivingEntityMixin"
+    "LivingEntityMixin",
+    "ArmorItemMixin"
   ],
   "client": [
     "client.ClientPlayerInteractionManagerMixin",
diff --git a/fabric-item-api-v1/src/testmod/java/net/fabricmc/fabric/test/item/ArmorKnockbackResistanceTest.java b/fabric-item-api-v1/src/testmod/java/net/fabricmc/fabric/test/item/ArmorKnockbackResistanceTest.java
new file mode 100644
index 000000000..cfd3b68c4
--- /dev/null
+++ b/fabric-item-api-v1/src/testmod/java/net/fabricmc/fabric/test/item/ArmorKnockbackResistanceTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2016, 2017, 2018, 2019 FabricMC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.fabricmc.fabric.test.item;
+
+import net.minecraft.entity.EquipmentSlot;
+import net.minecraft.item.ArmorItem;
+import net.minecraft.item.ArmorMaterial;
+import net.minecraft.item.Item;
+import net.minecraft.recipe.Ingredient;
+import net.minecraft.sound.SoundEvent;
+import net.minecraft.sound.SoundEvents;
+import net.minecraft.tag.ItemTags;
+import net.minecraft.util.Identifier;
+import net.minecraft.util.registry.Registry;
+
+import net.fabricmc.api.ModInitializer;
+
+public class ArmorKnockbackResistanceTest implements ModInitializer {
+	private static final ArmorMaterial WOOD_ARMOR = new ArmorMaterial() {
+		@Override
+		public int getDurability(EquipmentSlot slot) {
+			return 50;
+		}
+
+		@Override
+		public int getProtectionAmount(EquipmentSlot slot) {
+			return 5;
+		}
+
+		@Override
+		public int getEnchantability() {
+			return 1;
+		}
+
+		@Override
+		public SoundEvent getEquipSound() {
+			return SoundEvents.ITEM_ARMOR_EQUIP_GENERIC;
+		}
+
+		@Override
+		public Ingredient getRepairIngredient() {
+			return Ingredient.fromTag(ItemTags.LOGS);
+		}
+
+		@Override
+		public String getName() {
+			return "wood";
+		}
+
+		@Override
+		public float getToughness() {
+			return 0.0F;
+		}
+
+		@Override
+		public float getKnockbackResistance() {
+			return 0.5F;
+		}
+	};
+
+	@Override
+	public void onInitialize() {
+		Registry.register(Registry.ITEM, new Identifier("fabric-item-api-v1-testmod",
+				"wooden_boots"), new ArmorItem(WOOD_ARMOR, EquipmentSlot.FEET, new Item.Settings()));
+	}
+}
diff --git a/fabric-item-api-v1/src/testmod/resources/assets/fabric-item-api-v1-testmod/models/item/wooden_boots.json b/fabric-item-api-v1/src/testmod/resources/assets/fabric-item-api-v1-testmod/models/item/wooden_boots.json
new file mode 100644
index 000000000..3afe800aa
--- /dev/null
+++ b/fabric-item-api-v1/src/testmod/resources/assets/fabric-item-api-v1-testmod/models/item/wooden_boots.json
@@ -0,0 +1,8 @@
+{
+  "parent": "minecraft:item/generated",
+  "textures": {
+    "layer0": "minecraft:block/oak_log",
+    "layer1": "minecraft:item/leather_boots",
+    "layer2": "minecraft:item/leather_boots_overlay"
+  }
+}
diff --git a/fabric-item-api-v1/src/testmod/resources/assets/minecraft/textures/models/armor/wood_layer_1.png b/fabric-item-api-v1/src/testmod/resources/assets/minecraft/textures/models/armor/wood_layer_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..d7c688207cbfe06093f5b53f6ae72871bc7f7165
GIT binary patch
literal 273
zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3-p)I`?e@QjEnx?oJHr&dIz4a#+$GeH|GX
zHuiJ>Nn{1`*#dk*T<d`h28MWHw%b68sU*lR_&>wb?FL>z9%q3^WHAE+-(e7DJf6QI
z1t{3&>EamT;r;fUqfmnak8|LT|4T)Gi3%iH>q*{UwM{Ykl*a?(H~KdgA8__lS~hWV
zN9Gfiq~*`ebJprQmvV+p;`#8ex-ryXABW4myQ~ZE$EK8N?U*v*XpYqLWjWk|1?wb5
z9&I|{TGQR6@k#ic9TfX+U;EfV|HjVC*UTzkEtdPeU=DxmF4o-1ZfYDr7cqFc`njxg
HN@xNA<Tqej

literal 0
HcmV?d00001

diff --git a/fabric-item-api-v1/src/testmod/resources/assets/minecraft/textures/models/armor/wood_layer_2.png b/fabric-item-api-v1/src/testmod/resources/assets/minecraft/textures/models/armor/wood_layer_2.png
new file mode 100644
index 0000000000000000000000000000000000000000..2fbda132c6ace6f76f768af299c24cc8b940ce37
GIT binary patch
literal 204
zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQjEnx?oJHr&dIz4a#+$GeH|GX
zHuiJ>Nn{1`ISV`@iy0XB4ude`@%$AjK*2;$7srqc=eJik@--+3G(UXQEj>R*_>zT$
zn5ntL|9nm6;Nk)%pgIPI!daiUc`xt3Yq(?cq_dLUOmjBg`h0f3>2LXi!Ue|`F{JBo
v6&(Aumu+?E`bf0{KO?`g7&0C`#63ap*HjMK-^<1NL1uWm`njxgN@xNA{MbZM

literal 0
HcmV?d00001

diff --git a/fabric-item-api-v1/src/testmod/resources/fabric.mod.json b/fabric-item-api-v1/src/testmod/resources/fabric.mod.json
index 2750b292a..93e8e9873 100644
--- a/fabric-item-api-v1/src/testmod/resources/fabric.mod.json
+++ b/fabric-item-api-v1/src/testmod/resources/fabric.mod.json
@@ -13,7 +13,8 @@
       "net.fabricmc.fabric.test.item.CustomDamageTest",
       "net.fabricmc.fabric.test.item.FabricItemSettingsTests",
       "net.fabricmc.fabric.test.item.ItemUpdateAnimationTest",
-      "net.fabricmc.fabric.test.item.ModifyItemAttributeModifiersCallbackTest"
+      "net.fabricmc.fabric.test.item.ModifyItemAttributeModifiersCallbackTest",
+      "net.fabricmc.fabric.test.item.ArmorKnockbackResistanceTest"
     ],
     "client": [
       "net.fabricmc.fabric.test.item.client.TooltipTests"