Skip to content

Commit 5f22e1e

Browse files
authored
Implement item attributes (#4231)
1 parent b3b9ab9 commit 5f22e1e

File tree

13 files changed

+345
-2
lines changed

13 files changed

+345
-2
lines changed

generator/src/main/java/org/spongepowered/vanilla/generator/world/entities/EntityRegistries.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import net.minecraft.resources.ResourceLocation;
2929
import net.minecraft.world.entity.Display;
3030
import net.minecraft.world.entity.EquipmentSlot;
31+
import net.minecraft.world.entity.EquipmentSlotGroup;
3132
import net.minecraft.world.entity.MobCategory;
3233
import net.minecraft.world.entity.animal.Fox;
3334
import net.minecraft.world.entity.animal.MushroomCow;
@@ -159,6 +160,13 @@ public static List<Generator> enumEntries(final Context context) {
159160
"getSerializedName",
160161
"sponge"
161162
),
163+
new EnumEntriesValidator<>(
164+
"item.inventory.equipment",
165+
"EquipmentConditions",
166+
EquipmentSlotGroup.class,
167+
"getSerializedName",
168+
"sponge"
169+
),
162170
new EnumEntriesValidator<>(
163171
"item.inventory.equipment",
164172
"EquipmentGroups",

src/main/java/org/spongepowered/common/data/provider/item/stack/ItemStackData.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import net.minecraft.world.item.component.CustomModelData;
4444
import net.minecraft.world.item.component.DamageResistant;
4545
import net.minecraft.world.item.component.DeathProtection;
46+
import net.minecraft.world.item.component.ItemAttributeModifiers;
4647
import net.minecraft.world.item.component.ItemContainerContents;
4748
import net.minecraft.world.item.component.ItemLore;
4849
import net.minecraft.world.item.component.Unbreakable;
@@ -56,6 +57,7 @@
5657
import org.spongepowered.api.data.Keys;
5758
import org.spongepowered.api.data.type.ItemAction;
5859
import org.spongepowered.api.data.value.Value;
60+
import org.spongepowered.api.entity.attribute.ItemAttribute;
5961
import org.spongepowered.api.item.ItemRarity;
6062
import org.spongepowered.api.item.ItemType;
6163
import org.spongepowered.api.item.inventory.Inventory;
@@ -82,7 +84,6 @@ private ItemStackData() {
8284
// @formatter:off
8385
public static void register(final DataProviderRegistrator registrator) {
8486
// TODO DataComponents.SUSPICIOUS_STEW_EFFECTS
85-
// TODO maybe DataComponents.ATTRIBUTE_MODIFIERS as keys?
8687
// TODO DataComponents.BUNDLE_CONTENTS also check for Shulker Boxes? - removing the component prevents using the bundle
8788
// TODO DataComponents.CONTAINER_LOOT for containers with loottable data, also for blockentity?
8889
// TODO DataComponents.BLOCK_ENTITY_DATA maybe expose as raw DataContainer? (id MUST have block entity type)
@@ -367,6 +368,16 @@ public static void register(final DataProviderRegistrator registrator) {
367368
return builder.build();
368369
})
369370
.deleteAndGet(ItemStackData::deleteAndTransactUseCooldown)
371+
.create(Keys.ITEM_ATTRIBUTES)
372+
.get(stack -> {
373+
final var attributes = stack.getOrDefault(DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY).modifiers();
374+
return attributes.isEmpty() ? null : (List<ItemAttribute>) (Object) List.copyOf(attributes);
375+
})
376+
.set((stack, v) -> {
377+
final var attributes = (List<ItemAttributeModifiers.Entry>) (Object) List.copyOf(v);
378+
stack.update(DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY, p -> new ItemAttributeModifiers(attributes, p.showInTooltip()));
379+
})
380+
.resetOnDelete(List.of())
370381
;
371382
}
372383
// @formatter:on
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* This file is part of Sponge, licensed under the MIT License (MIT).
3+
*
4+
* Copyright (c) SpongePowered <https://www.spongepowered.org>
5+
* Copyright (c) contributors
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package org.spongepowered.common.entity.attribute;
26+
27+
import net.minecraft.core.registries.Registries;
28+
import net.minecraft.world.entity.EquipmentSlotGroup;
29+
import net.minecraft.world.entity.ai.attributes.Attribute;
30+
import net.minecraft.world.item.component.ItemAttributeModifiers;
31+
import org.spongepowered.api.entity.attribute.AttributeModifier;
32+
import org.spongepowered.api.entity.attribute.ItemAttribute;
33+
import org.spongepowered.api.entity.attribute.type.AttributeType;
34+
import org.spongepowered.api.item.inventory.equipment.EquipmentCondition;
35+
import org.spongepowered.common.SpongeCommon;
36+
37+
import java.util.Objects;
38+
39+
public final class SpongeItemAttributeFactory implements ItemAttribute.Factory {
40+
41+
@Override
42+
public ItemAttribute of(final AttributeType type, final AttributeModifier modifier, final EquipmentCondition condition) {
43+
Objects.requireNonNull(type, "type");
44+
Objects.requireNonNull(modifier, "modifier");
45+
Objects.requireNonNull(condition, "condition");
46+
return (ItemAttribute) (Object) new ItemAttributeModifiers.Entry(
47+
SpongeCommon.vanillaRegistry(Registries.ATTRIBUTE).wrapAsHolder((Attribute) type),
48+
(net.minecraft.world.entity.ai.attributes.AttributeModifier) (Object) modifier,
49+
(EquipmentSlotGroup) (Object) condition
50+
);
51+
}
52+
}

src/main/java/org/spongepowered/common/registry/SpongeFactoryProvider.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import org.spongepowered.api.data.value.Value;
4747
import org.spongepowered.api.effect.ForwardingViewer;
4848
import org.spongepowered.api.effect.VanishState;
49+
import org.spongepowered.api.entity.attribute.ItemAttribute;
4950
import org.spongepowered.api.event.EventListenerRegistration;
5051
import org.spongepowered.api.event.cause.entity.damage.DamageStepType;
5152
import org.spongepowered.api.event.cause.entity.damage.source.DamageSource;
@@ -123,6 +124,7 @@
123124
import org.spongepowered.common.data.manipulator.MutableDataManipulatorFactory;
124125
import org.spongepowered.common.data.value.SpongeValueFactory;
125126
import org.spongepowered.common.effect.SpongeCustomForwardingViewer;
127+
import org.spongepowered.common.entity.attribute.SpongeItemAttributeFactory;
126128
import org.spongepowered.common.entity.effect.SpongeVanishState;
127129
import org.spongepowered.common.event.SpongeEventListenerRegistration;
128130
import org.spongepowered.common.event.cause.entity.damage.SpongeDamageStepType;
@@ -287,6 +289,7 @@ public void registerDefaultFactories() {
287289
.registerFactory(NaturalSpawner.Factory.class, new SpongeNaturalSpawnerFactory())
288290
.registerFactory(ScoreFormat.Factory.class, new SpongeScoreFormatFactory())
289291
.registerFactory(ToolRule.Factory.class, new SpongeToolRuleFactory())
292+
.registerFactory(ItemAttribute.Factory.class, new SpongeItemAttributeFactory())
290293
.registerFactory(ItemAction.Factory.class, new SpongeItemActionFactory())
291294
.registerFactory(PortalLogic.Factory.class, new SpongePortalLogicFactory())
292295
.registerFactory(RecipeInput.Factory.class, new SpongeRecipeInputFactory())

src/main/java/org/spongepowered/common/registry/loader/VanillaRegistryLoader.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import net.minecraft.world.damagesource.DamageScaling;
3737
import net.minecraft.world.entity.Display;
3838
import net.minecraft.world.entity.EquipmentSlot;
39+
import net.minecraft.world.entity.EquipmentSlotGroup;
3940
import net.minecraft.world.entity.HumanoidArm;
4041
import net.minecraft.world.entity.MobCategory;
4142
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
@@ -183,6 +184,7 @@ private void loadEnumRegistries() {
183184
this.automaticName(RegistryTypes.DYE_COLOR, DyeColor.values());
184185
this.automaticName(RegistryTypes.DOOR_HINGE, DoorHingeSide.values());
185186
this.automaticName(RegistryTypes.DRIPSTONE_SEGMENT, DripstoneThickness.values());
187+
this.automaticName(RegistryTypes.EQUIPMENT_CONDITION, EquipmentSlotGroup.values());
186188
this.automaticName(RegistryTypes.EQUIPMENT_GROUP, EquipmentSlot.Type.values());
187189
this.automaticName(RegistryTypes.EQUIPMENT_TYPE, EquipmentSlot.values());
188190
this.automaticName(RegistryTypes.FOX_TYPE, Fox.Variant.values());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* This file is part of Sponge, licensed under the MIT License (MIT).
3+
*
4+
* Copyright (c) SpongePowered <https://www.spongepowered.org>
5+
* Copyright (c) contributors
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package org.spongepowered.common.mixin.api.minecraft.world.item.component;
26+
27+
import net.minecraft.core.Holder;
28+
import net.minecraft.world.entity.EquipmentSlotGroup;
29+
import net.minecraft.world.entity.ai.attributes.Attribute;
30+
import net.minecraft.world.item.component.ItemAttributeModifiers;
31+
import org.spongepowered.api.entity.attribute.AttributeModifier;
32+
import org.spongepowered.api.entity.attribute.ItemAttribute;
33+
import org.spongepowered.api.entity.attribute.type.AttributeType;
34+
import org.spongepowered.api.item.inventory.equipment.EquipmentCondition;
35+
import org.spongepowered.asm.mixin.Final;
36+
import org.spongepowered.asm.mixin.Implements;
37+
import org.spongepowered.asm.mixin.Interface;
38+
import org.spongepowered.asm.mixin.Intrinsic;
39+
import org.spongepowered.asm.mixin.Mixin;
40+
import org.spongepowered.asm.mixin.Shadow;
41+
42+
@Mixin(ItemAttributeModifiers.Entry.class)
43+
@Implements(@Interface(iface = ItemAttribute.class, prefix = "attribute$"))
44+
public abstract class ItemAttributeModifiers_EntryMixin_API implements ItemAttribute {
45+
46+
@Shadow @Final private Holder<Attribute> attribute;
47+
@Shadow @Final private net.minecraft.world.entity.ai.attributes.AttributeModifier modifier;
48+
@Shadow @Final private EquipmentSlotGroup slot;
49+
50+
@Override
51+
public AttributeType type() {
52+
return (AttributeType) this.attribute.value();
53+
}
54+
55+
@Intrinsic
56+
public AttributeModifier attribute$modifier() {
57+
return (AttributeModifier) (Object) this.modifier;
58+
}
59+
60+
@Override
61+
public EquipmentCondition condition() {
62+
return (EquipmentCondition) (Object) this.slot;
63+
}
64+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* This file is part of Sponge, licensed under the MIT License (MIT).
3+
*
4+
* Copyright (c) SpongePowered <https://www.spongepowered.org>
5+
* Copyright (c) contributors
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package org.spongepowered.common.mixin.inventory.api.world.entity;
26+
27+
import net.kyori.adventure.text.Component;
28+
import net.minecraft.world.entity.EquipmentSlot;
29+
import net.minecraft.world.entity.EquipmentSlotGroup;
30+
import org.spongepowered.api.item.inventory.equipment.EquipmentCondition;
31+
import org.spongepowered.api.item.inventory.equipment.EquipmentType;
32+
import org.spongepowered.asm.mixin.Final;
33+
import org.spongepowered.asm.mixin.Mixin;
34+
import org.spongepowered.asm.mixin.Shadow;
35+
import org.spongepowered.asm.mixin.injection.At;
36+
import org.spongepowered.asm.mixin.injection.Inject;
37+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
38+
39+
import java.util.Objects;
40+
41+
@Mixin(EquipmentSlotGroup.class)
42+
public abstract class EquipmentSlotGroupMixin_Inventory_API implements EquipmentCondition {
43+
44+
@Shadow public abstract boolean shadow$test(EquipmentSlot slot);
45+
46+
@Shadow @Final private String key;
47+
48+
private Component api$component;
49+
50+
@Inject(method = "<init>(Ljava/lang/String;IILjava/lang/String;Ljava/util/function/Predicate;)V", at = @At("RETURN"))
51+
private void api$setComponent(final CallbackInfo ci) {
52+
this.api$component = Component.translatable("item.modifiers." + this.key);
53+
}
54+
55+
@Override
56+
public Component asComponent() {
57+
return this.api$component;
58+
}
59+
60+
@Override
61+
public boolean test(final EquipmentType type) {
62+
return this.shadow$test((EquipmentSlot) (Object) Objects.requireNonNull(type, "type"));
63+
}
64+
}

src/mixins/java/org/spongepowered/common/mixin/inventory/api/world/entity/EquipmentSlotMixin_Inventory_API.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
package org.spongepowered.common.mixin.inventory.api.world.entity;
2626

2727
import net.minecraft.world.entity.EquipmentSlot;
28+
import net.minecraft.world.entity.EquipmentSlotGroup;
29+
import org.spongepowered.api.item.inventory.equipment.EquipmentCondition;
2830
import org.spongepowered.api.item.inventory.equipment.EquipmentGroup;
2931
import org.spongepowered.api.item.inventory.equipment.EquipmentType;
3032
import org.spongepowered.asm.mixin.Final;
@@ -40,4 +42,9 @@ public abstract class EquipmentSlotMixin_Inventory_API implements EquipmentType
4042
public EquipmentGroup group() {
4143
return (EquipmentGroup) (Object) this.type;
4244
}
45+
46+
@Override
47+
public EquipmentCondition condition() {
48+
return (EquipmentCondition) (Object) EquipmentSlotGroup.bySlot((EquipmentSlot) (Object) this);
49+
}
4350
}

src/mixins/resources/mixins.sponge.api.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@
332332
"minecraft.world.item.ToolMaterialMixin_API",
333333
"minecraft.world.item.alchemy.PotionMixin_API",
334334
"minecraft.world.item.component.FireworkExplosionMixin_API",
335+
"minecraft.world.item.component.ItemAttributeModifiers_EntryMixin_API",
335336
"minecraft.world.item.component.Tool_RuleMixin_API",
336337
"minecraft.world.item.consume_effects.ApplyStatusEffectsConsumeEffectMixin_API",
337338
"minecraft.world.item.consume_effects.ClearAllStatusEffectsConsumeEffectMixin_API",

0 commit comments

Comments
 (0)