From f1323d72717fb8be1fb5353e4c8b4bb4d612ec4c Mon Sep 17 00:00:00 2001 From: i509VCB Date: Fri, 3 Jul 2020 23:48:16 -0500 Subject: [PATCH] Implement Attributes API --- .../entity/monster/ZombieEntityAccessor.java | 40 ++++++ .../horse/AbstractHorseEntityAccessor.java | 40 ++++++ .../resources/mixins.common.accessors.json | 2 + .../common/data/type/SpongeEquipmentType.java | 5 +- .../SpongeAttributeModifierBuilder.java | 83 +++++++++++++ .../common/item/SpongeItemStackBuilder.java | 48 +++++++- .../registry/SpongeBuilderRegistry.java | 3 + .../registry/SpongeCatalogRegistry.java | 9 ++ .../vanilla/AttributeTypeStreamGenerator.java | 60 +++++++++ .../vanilla/EquipmentTypeStreamGenerator.java | 51 ++++++++ .../spongepowered/common/util/Constants.java | 3 + .../api/mcp/entity/LivingEntityMixin_API.java | 13 ++ .../ai/attributes/AttributeMixin_API.java | 54 +++++++++ .../AttributeModifierMixin_API.java | 65 ++++++++++ .../AttributeModifier_OperationMixin_API.java | 50 ++++++++ .../IAttributeInstanceMixin_API.java | 114 ++++++++++++++++++ .../ai/attributes/IAttributeMixin_API.java | 59 +++++++++ .../attributes/RangedAttributeMixin_API.java | 47 ++++++++ .../api/mcp/item/ItemStackMixin_API.java | 44 ++++++- src/mixins/resources/mixins.common.api.json | 6 + 20 files changed, 792 insertions(+), 4 deletions(-) create mode 100644 src/accessors/java/org/spongepowered/common/accessor/entity/monster/ZombieEntityAccessor.java create mode 100644 src/accessors/java/org/spongepowered/common/accessor/entity/passive/horse/AbstractHorseEntityAccessor.java create mode 100644 src/main/java/org/spongepowered/common/entity/attribute/SpongeAttributeModifierBuilder.java create mode 100644 src/main/java/org/spongepowered/common/registry/builtin/vanilla/AttributeTypeStreamGenerator.java create mode 100644 src/main/java/org/spongepowered/common/registry/builtin/vanilla/EquipmentTypeStreamGenerator.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/AttributeMixin_API.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/AttributeModifierMixin_API.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/AttributeModifier_OperationMixin_API.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/IAttributeInstanceMixin_API.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/IAttributeMixin_API.java create mode 100644 src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/RangedAttributeMixin_API.java diff --git a/src/accessors/java/org/spongepowered/common/accessor/entity/monster/ZombieEntityAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/entity/monster/ZombieEntityAccessor.java new file mode 100644 index 00000000000..a97578898bb --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/entity/monster/ZombieEntityAccessor.java @@ -0,0 +1,40 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.accessor.entity.monster; + +import net.minecraft.entity.ai.attributes.IAttribute; +import net.minecraft.entity.monster.ZombieEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(ZombieEntity.class) +public interface ZombieEntityAccessor { + + @Accessor("SPAWN_REINFORCEMENTS_CHANCE") + static IAttribute accessor$getSpawnReinforcementsChance() { + throw new IllegalStateException("Untransformed Accessor!"); + } + +} diff --git a/src/accessors/java/org/spongepowered/common/accessor/entity/passive/horse/AbstractHorseEntityAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/entity/passive/horse/AbstractHorseEntityAccessor.java new file mode 100644 index 00000000000..a9733935949 --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/entity/passive/horse/AbstractHorseEntityAccessor.java @@ -0,0 +1,40 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.accessor.entity.passive.horse; + +import net.minecraft.entity.ai.attributes.IAttribute; +import net.minecraft.entity.passive.horse.AbstractHorseEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(AbstractHorseEntity.class) +public interface AbstractHorseEntityAccessor { + + @Accessor("JUMP_STRENGTH") + static IAttribute accessor$getJumpStrength() { + throw new IllegalStateException("Untransformed Accessor!"); + } + +} diff --git a/src/accessors/resources/mixins.common.accessors.json b/src/accessors/resources/mixins.common.accessors.json index 65d59d05f65..bcb8c4ed0db 100644 --- a/src/accessors/resources/mixins.common.accessors.json +++ b/src/accessors/resources/mixins.common.accessors.json @@ -53,6 +53,7 @@ "entity.monster.SpellcastingIllagerEntityAccessor", "entity.monster.VexEntityAccessor", "entity.monster.VindicatorEntityAccessor", + "entity.monster.ZombieEntityAccessor", "entity.monster.ZombiePigmanEntityAccessor", "entity.passive.AbstractChestedHorseEntityAccessor", "entity.passive.AnimalEntityAccessor", @@ -64,6 +65,7 @@ "entity.passive.TurtleEntityAccessor", "entity.passive.WolfEntityAccessor", "entity.passive.fish.PufferfishEntityAccessor", + "entity.passive.horse.AbstractHorseEntityAccessor", "entity.passive.horse.LlamaEntityAccessor", "entity.passive.horse.TraderLlamaEntityAccessor", "entity.player.PlayerAbilitiesAccessor", diff --git a/src/main/java/org/spongepowered/common/data/type/SpongeEquipmentType.java b/src/main/java/org/spongepowered/common/data/type/SpongeEquipmentType.java index e41f6b94dd7..b46992e9c9a 100644 --- a/src/main/java/org/spongepowered/common/data/type/SpongeEquipmentType.java +++ b/src/main/java/org/spongepowered/common/data/type/SpongeEquipmentType.java @@ -28,6 +28,9 @@ import org.spongepowered.api.ResourceKey; import org.spongepowered.api.item.inventory.equipment.EquipmentType; import org.spongepowered.common.SpongeCatalogType; +import org.spongepowered.common.util.MissingImplementationException; + +import java.util.Arrays; public class SpongeEquipmentType extends SpongeCatalogType implements EquipmentType { @@ -44,6 +47,6 @@ public EquipmentSlotType[] getSlots() { @Override public boolean includes(EquipmentType other) { - return false; + throw new MissingImplementationException("SpongeEquipmentType", "includes"); } } diff --git a/src/main/java/org/spongepowered/common/entity/attribute/SpongeAttributeModifierBuilder.java b/src/main/java/org/spongepowered/common/entity/attribute/SpongeAttributeModifierBuilder.java new file mode 100644 index 00000000000..1d1668be63d --- /dev/null +++ b/src/main/java/org/spongepowered/common/entity/attribute/SpongeAttributeModifierBuilder.java @@ -0,0 +1,83 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.entity.attribute; + +import com.google.common.base.Preconditions; +import org.spongepowered.api.entity.attribute.AttributeModifier; +import org.spongepowered.api.entity.attribute.AttributeOperation; + +import java.util.UUID; + +public final class SpongeAttributeModifierBuilder implements AttributeModifier.Builder { + // Use a random id + private UUID id = UUID.randomUUID(); + private String name; + private AttributeOperation operation; + private double amount; + + public SpongeAttributeModifierBuilder() { + } + + @Override + public AttributeModifier.Builder id(final UUID id) { + this.id = Preconditions.checkNotNull(id, "Modifier id cannot be null"); + return this; + } + + @Override + public AttributeModifier.Builder name(final String name) { + this.name = Preconditions.checkNotNull(name, "Name cannot be null"); + return this; + } + + @Override + public AttributeModifier.Builder operation(final AttributeOperation operation) { + this.operation = Preconditions.checkNotNull(operation, "Operation cannot be null"); + return this; + } + + @Override + public AttributeModifier.Builder amount(final double amount) { + this.amount = amount; + return this; + } + + @Override + public AttributeModifier build() { + Preconditions.checkNotNull(this.name, "Name must be set"); + Preconditions.checkNotNull(this.operation, "Operation must be set"); + return (AttributeModifier) new net.minecraft.entity.ai.attributes.AttributeModifier(this.id, this.name, this.amount, (net.minecraft.entity.ai.attributes.AttributeModifier.Operation) (Object) this.operation); + } + + @Override + public AttributeModifier.Builder reset() { + // Randomize id when reset + this.id = UUID.randomUUID(); + this.name = null; + this.amount = 0.0D; + this.operation = null; + return this; + } +} diff --git a/src/main/java/org/spongepowered/common/item/SpongeItemStackBuilder.java b/src/main/java/org/spongepowered/common/item/SpongeItemStackBuilder.java index cdcfbc767d6..8fae18bb754 100644 --- a/src/main/java/org/spongepowered/common/item/SpongeItemStackBuilder.java +++ b/src/main/java/org/spongepowered/common/item/SpongeItemStackBuilder.java @@ -28,7 +28,10 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; +import com.google.common.base.Preconditions; import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.item.Item; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; @@ -48,9 +51,12 @@ import org.spongepowered.api.item.inventory.ItemStack; import org.spongepowered.api.item.inventory.ItemStackSnapshot; import org.spongepowered.api.item.inventory.equipment.EquipmentType; +import org.spongepowered.api.item.inventory.equipment.EquipmentTypes; +import org.spongepowered.api.item.inventory.equipment.WornEquipmentType; import org.spongepowered.common.SpongeImplHooks; import org.spongepowered.common.block.SpongeBlockSnapshot; import org.spongepowered.common.data.persistence.NbtTranslator; +import org.spongepowered.common.data.type.SpongeEquipmentType; import org.spongepowered.common.util.Constants; import org.spongepowered.common.util.MissingImplementationException; import org.spongepowered.common.util.PrettyPrinter; @@ -124,8 +130,46 @@ public ItemStack.Builder fromItemStack(final ItemStack itemStack) { } @Override - public ItemStack.Builder attributeModifier(AttributeType attributeType, AttributeModifier modifier, EquipmentType equipmentType) { - throw new MissingImplementationException("SpongeItemStackBuilder", "attributeModifier"); + public ItemStack.Builder attributeModifier(final AttributeType attributeType, final AttributeModifier modifier, final EquipmentType equipmentType) { + Preconditions.checkNotNull(attributeType, "AttributeType cannot be null"); + Preconditions.checkNotNull(modifier, "AttributeModifier cannot be null"); + Preconditions.checkNotNull(equipmentType, "EquipmentType cannot be null"); + + // Create the compound if needed + if (this.compound == null) { + this.compound = new CompoundNBT(); + } + + final CompoundNBT compound = this.compound; + + if (!compound.contains(Constants.ItemStack.ATTRIBUTE_MODIFIERS, Constants.NBT.TAG_LIST)) { + compound.put(Constants.ItemStack.ATTRIBUTE_MODIFIERS, new ListNBT()); + } + + final ListNBT attributeModifiers = compound.getList(Constants.ItemStack.ATTRIBUTE_MODIFIERS, Constants.NBT.TAG_COMPOUND); + + // The modifier will apply in any slot, equipable or not. Pass null for the slot + if (equipmentType.equals(EquipmentTypes.ANY.get()) || equipmentType.equals(EquipmentTypes.EQUIPPED.get())) { + this.writeAttributeModifier(attributeModifiers, (net.minecraft.entity.ai.attributes.AttributeModifier) modifier, null); + } else { + // Write modifier to every applicable slot. + for (EquipmentSlotType slot : ((SpongeEquipmentType) equipmentType).getSlots()) { + this.writeAttributeModifier(attributeModifiers, (net.minecraft.entity.ai.attributes.AttributeModifier) modifier, slot); + } + } + + return this; + } + + private void writeAttributeModifier(final ListNBT attributeModifiers, final net.minecraft.entity.ai.attributes.AttributeModifier attributeModifier, final EquipmentSlotType slot) { + final CompoundNBT modifierNbt = SharedMonsterAttributes.writeAttributeModifier(attributeModifier); + modifierNbt.putString(Constants.ItemStack.ATTRIBUTE_NAME, attributeModifier.getName()); + + if (slot != null) { + modifierNbt.putString(Constants.ItemStack.ATTRIBUTE_SLOT, slot.getName()); + } + + attributeModifiers.add(modifierNbt); } @Override diff --git a/src/main/java/org/spongepowered/common/registry/SpongeBuilderRegistry.java b/src/main/java/org/spongepowered/common/registry/SpongeBuilderRegistry.java index 92c4b96a2b2..7ce0e17b7de 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeBuilderRegistry.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeBuilderRegistry.java @@ -33,6 +33,7 @@ import org.spongepowered.api.command.CommandResult; import org.spongepowered.api.command.parameter.Parameter; import org.spongepowered.api.command.parameter.managed.standard.VariableValueParameters; +import org.spongepowered.api.entity.attribute.AttributeModifier; import org.spongepowered.api.registry.BuilderRegistry; import org.spongepowered.api.registry.DuplicateRegistrationException; import org.spongepowered.api.registry.UnknownTypeException; @@ -43,6 +44,7 @@ import org.spongepowered.common.command.parameter.multi.SpongeSequenceParameterBuilder; import org.spongepowered.common.command.parameter.subcommand.SpongeSubcommandParameterBuilder; import org.spongepowered.common.command.result.SpongeCommandResultBuilder; +import org.spongepowered.common.entity.attribute.SpongeAttributeModifierBuilder; import java.util.Map; import java.util.function.Supplier; @@ -148,6 +150,7 @@ public void registerDefaultBuilders() { // .register(FilteredTrigger.Builder.class, SpongeFilteredTriggerBuilder::new) // .register(Trigger.Builder.class, SpongeTriggerBuilder::new) // .register(ResourceKey.Builder.class, SpongeCatalogKeyBuilder::new) + .register(AttributeModifier.Builder.class, SpongeAttributeModifierBuilder::new) .register(Command.Builder.class, SpongeParameterizedCommandBuilder::new) .register(Parameter.FirstOfBuilder.class, SpongeFirstOfParameterBuilder::new) .register(Parameter.SequenceBuilder.class, SpongeSequenceParameterBuilder::new) diff --git a/src/main/java/org/spongepowered/common/registry/SpongeCatalogRegistry.java b/src/main/java/org/spongepowered/common/registry/SpongeCatalogRegistry.java index 8b8c68baaef..2093f1942e3 100644 --- a/src/main/java/org/spongepowered/common/registry/SpongeCatalogRegistry.java +++ b/src/main/java/org/spongepowered/common/registry/SpongeCatalogRegistry.java @@ -29,6 +29,7 @@ import com.google.inject.Singleton; import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.entity.monster.PhantomEntity; import net.minecraft.entity.monster.SpellcastingIllagerEntity; import net.minecraft.entity.passive.FoxEntity; @@ -101,6 +102,8 @@ import org.spongepowered.api.effect.sound.music.MusicDisc; import org.spongepowered.api.entity.ai.goal.GoalExecutorType; import org.spongepowered.api.entity.ai.goal.GoalType; +import org.spongepowered.api.entity.attribute.AttributeOperation; +import org.spongepowered.api.entity.attribute.type.AttributeType; import org.spongepowered.api.entity.living.monster.boss.dragon.phase.DragonPhaseType; import org.spongepowered.api.entity.living.player.gamemode.GameMode; import org.spongepowered.api.event.cause.EventContextKey; @@ -108,6 +111,7 @@ import org.spongepowered.api.event.cause.entity.dismount.DismountType; import org.spongepowered.api.event.cause.entity.spawn.SpawnType; import org.spongepowered.api.item.FireworkShape; +import org.spongepowered.api.item.inventory.equipment.EquipmentType; import org.spongepowered.api.item.inventory.query.QueryType; import org.spongepowered.api.registry.CatalogRegistry; import org.spongepowered.api.registry.DuplicateRegistrationException; @@ -148,6 +152,7 @@ import org.spongepowered.common.registry.builtin.sponge.RabbitTypeStreamGenerator; import org.spongepowered.common.registry.builtin.sponge.SpawnTypeStreamGenerator; import org.spongepowered.common.registry.builtin.sponge.WoodTypeStreamGenerator; +import org.spongepowered.common.registry.builtin.vanilla.AttributeTypeStreamGenerator; import org.spongepowered.common.registry.builtin.vanilla.BiomeSupplier; import org.spongepowered.common.registry.builtin.vanilla.BlockSupplier; import org.spongepowered.common.registry.builtin.vanilla.ContainerTypeSupplier; @@ -157,6 +162,7 @@ import org.spongepowered.common.registry.builtin.vanilla.EffectSupplier; import org.spongepowered.common.registry.builtin.vanilla.EnchantmentSupplier; import org.spongepowered.common.registry.builtin.vanilla.EntityTypeSupplier; +import org.spongepowered.common.registry.builtin.vanilla.EquipmentTypeStreamGenerator; import org.spongepowered.common.registry.builtin.vanilla.FireworkShapeStreamGenerator; import org.spongepowered.common.registry.builtin.vanilla.FluidSupplier; import org.spongepowered.common.registry.builtin.vanilla.ItemSupplier; @@ -412,6 +418,8 @@ public void registerDefaultRegistries() { .registerRegistry(AdvancementTree.class, ResourceKey.minecraft("advancement_tree")) // .generateRegistry(AdvancementType.class, ResourceKey.minecraft("advancement_type"), Arrays.stream(FrameType.values()), true) .generateRegistry(ArmorMaterial.class, ResourceKey.minecraft("armor_material"), Arrays.stream(net.minecraft.item.ArmorMaterial.values()), true) + .generateRegistry(AttributeOperation.class, ResourceKey.minecraft("attribute_operation"), Arrays.stream(AttributeModifier.Operation.values()), true) + .generateRegistry(AttributeType.class, ResourceKey.minecraft("attribute_type"), AttributeTypeStreamGenerator.stream(), true) .generateRegistry(BanType.class, ResourceKey.minecraft("ban_type"), BanTypeStreamGenerator.stream(), true) .generateRegistry(BannerPatternShape.class, ResourceKey.minecraft("banner_pattern_shape"), Arrays.stream(BannerPattern.values()), true) // .generateRegistry(BossBarOverlay.class, ResourceKey.minecraft("boss_bar_overlay"), Arrays.stream(BossInfo.Overlay.values()), true) @@ -431,6 +439,7 @@ public void registerDefaultRegistries() { .generateRegistry(DyeColor.class, ResourceKey.minecraft("dye_color"), Arrays.stream(net.minecraft.item.DyeColor.values()), true) .generateRegistry(CatalogedValueParameter.class, ResourceKey.sponge("value_parameter"), CatalogedValueParameterStreamGenerator.stream(), true) .generateRegistry(CommandRegistrar.class, ResourceKey.sponge("command_registrar"), CommandRegistrarStreamGenerator.stream(), true) + .generateRegistry(EquipmentType.class, ResourceKey.minecraft("equipment_type"), EquipmentTypeStreamGenerator.stream(), true) .generateRegistry(EventContextKey.class, ResourceKey.sponge("event_context_key"), EventContextKeyStreamGenerator.stream(), true) .generateRegistry(FoxType.class, ResourceKey.minecraft("fox_type"), Arrays.stream(FoxEntity.Type.values()), true) .generateRegistry(GameMode.class, ResourceKey.minecraft("game_mode"), Arrays.stream(GameType.values()), true) diff --git a/src/main/java/org/spongepowered/common/registry/builtin/vanilla/AttributeTypeStreamGenerator.java b/src/main/java/org/spongepowered/common/registry/builtin/vanilla/AttributeTypeStreamGenerator.java new file mode 100644 index 00000000000..ac34ee8d601 --- /dev/null +++ b/src/main/java/org/spongepowered/common/registry/builtin/vanilla/AttributeTypeStreamGenerator.java @@ -0,0 +1,60 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.registry.builtin.vanilla; + +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.Attribute; +import net.minecraft.entity.monster.ZombieEntity; +import org.spongepowered.api.entity.attribute.type.AttributeType; +import org.spongepowered.common.accessor.entity.monster.ZombieEntityAccessor; +import org.spongepowered.common.accessor.entity.monster.ZombiePigmanEntityAccessor; +import org.spongepowered.common.accessor.entity.passive.horse.AbstractHorseEntityAccessor; + +import java.util.stream.Stream; + +public final class AttributeTypeStreamGenerator { + + private AttributeTypeStreamGenerator() { + } + + public static Stream stream() { + return Stream.of( + (AttributeType) SharedMonsterAttributes.ARMOR, + (AttributeType) SharedMonsterAttributes.ARMOR_TOUGHNESS, + (AttributeType) SharedMonsterAttributes.ATTACK_DAMAGE, + (AttributeType) SharedMonsterAttributes.ATTACK_KNOCKBACK, + (AttributeType) SharedMonsterAttributes.ATTACK_SPEED, + (AttributeType) SharedMonsterAttributes.FLYING_SPEED, + (AttributeType) SharedMonsterAttributes.FOLLOW_RANGE, + (AttributeType) SharedMonsterAttributes.KNOCKBACK_RESISTANCE, + (AttributeType) SharedMonsterAttributes.LUCK, + (AttributeType) SharedMonsterAttributes.MAX_HEALTH, + (AttributeType) SharedMonsterAttributes.MOVEMENT_SPEED, + // Entity specific attributes + ((AttributeType) AbstractHorseEntityAccessor.accessor$getJumpStrength()), + ((AttributeType) ZombieEntityAccessor.accessor$getSpawnReinforcementsChance()) + ); + } +} diff --git a/src/main/java/org/spongepowered/common/registry/builtin/vanilla/EquipmentTypeStreamGenerator.java b/src/main/java/org/spongepowered/common/registry/builtin/vanilla/EquipmentTypeStreamGenerator.java new file mode 100644 index 00000000000..32612fa106a --- /dev/null +++ b/src/main/java/org/spongepowered/common/registry/builtin/vanilla/EquipmentTypeStreamGenerator.java @@ -0,0 +1,51 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.registry.builtin.vanilla; + +import net.minecraft.inventory.EquipmentSlotType; +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.item.inventory.equipment.EquipmentType; +import org.spongepowered.common.data.type.SpongeEquipmentType; +import org.spongepowered.common.data.type.SpongeHeldEquipmentType; +import org.spongepowered.common.data.type.SpongeWornEquipmentType; + +import java.util.stream.Stream; + +public final class EquipmentTypeStreamGenerator { + public static Stream stream() { + return Stream.of( + new SpongeEquipmentType(ResourceKey.minecraft("any"), EquipmentSlotType.values()), + new SpongeEquipmentType(ResourceKey.minecraft("equipped"), EquipmentSlotType.values()), + new SpongeHeldEquipmentType(ResourceKey.minecraft("held"), EquipmentSlotType.MAINHAND, EquipmentSlotType.OFFHAND), + new SpongeHeldEquipmentType(ResourceKey.minecraft("main_hand"), EquipmentSlotType.MAINHAND), + new SpongeHeldEquipmentType(ResourceKey.minecraft("off_hand"), EquipmentSlotType.OFFHAND), + new SpongeWornEquipmentType(ResourceKey.minecraft("worn"), EquipmentSlotType.HEAD, EquipmentSlotType.CHEST, EquipmentSlotType.LEGS, EquipmentSlotType.FEET), + new SpongeWornEquipmentType(ResourceKey.minecraft("boots"), EquipmentSlotType.FEET), + new SpongeWornEquipmentType(ResourceKey.minecraft("leggings"), EquipmentSlotType.LEGS), + new SpongeWornEquipmentType(ResourceKey.minecraft("chestplate"), EquipmentSlotType.CHEST), + new SpongeWornEquipmentType(ResourceKey.minecraft("headwear"), EquipmentSlotType.HEAD) + ); + } +} diff --git a/src/main/java/org/spongepowered/common/util/Constants.java b/src/main/java/org/spongepowered/common/util/Constants.java index 6b5bf6b1c0a..535267a4808 100644 --- a/src/main/java/org/spongepowered/common/util/Constants.java +++ b/src/main/java/org/spongepowered/common/util/Constants.java @@ -1241,6 +1241,9 @@ public static final class ItemStack { public static final DataQuery COUNT = of("Count"); public static final DataQuery TYPE = of("ItemType"); public static final DataQuery DAMAGE_VALUE = of("UnsafeDamage"); + public static final String ATTRIBUTE_MODIFIERS = "AttributeModifiers"; + public static final String ATTRIBUTE_NAME = "AttributeName"; + public static final String ATTRIBUTE_SLOT = "Slot"; } public static final class Particles { diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/LivingEntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/LivingEntityMixin_API.java index 80f70b16b70..e5af8daceb2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/LivingEntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/LivingEntityMixin_API.java @@ -24,15 +24,21 @@ */ package org.spongepowered.common.mixin.api.mcp.entity; +import com.google.common.base.Preconditions; import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.attributes.IAttribute; +import net.minecraft.entity.ai.attributes.IAttributeInstance; import net.minecraft.item.ItemStack; import net.minecraft.util.Hand; import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.entity.attribute.Attribute; +import org.spongepowered.api.entity.attribute.type.AttributeType; import org.spongepowered.api.entity.living.Living; import org.spongepowered.api.text.Text; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import java.util.Optional; import java.util.Set; @Mixin(value = LivingEntity.class, priority = 999) @@ -40,12 +46,19 @@ public abstract class LivingEntityMixin_API extends EntityMixin_API implements L @Shadow public abstract ItemStack shadow$getHeldItem(Hand hand); @Shadow public abstract float shadow$getHealth(); + @Shadow public abstract IAttributeInstance shadow$getAttribute(IAttribute attribute); @Override public Text getTeamRepresentation() { return Text.of(this.shadow$getUniqueID().toString()); } + @Override + public Optional getAttribute(final AttributeType type) { + Preconditions.checkNotNull(type, "AttributeType cannot be null"); + return Optional.ofNullable((Attribute) this.shadow$getAttribute((IAttribute) type)); + } + @Override protected Set> api$getVanillaValues() { final Set> values = super.api$getVanillaValues(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/AttributeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/AttributeMixin_API.java new file mode 100644 index 00000000000..c76fb34411c --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/AttributeMixin_API.java @@ -0,0 +1,54 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.mcp.entity.ai.attributes; + +import com.google.common.base.CaseFormat; +import net.minecraft.entity.ai.attributes.Attribute; +import net.minecraft.entity.ai.attributes.IAttribute; +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.entity.attribute.type.AttributeType; +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.CallbackInfo; +import org.spongepowered.common.SpongeCommon; + +@Mixin(Attribute.class) +public abstract class AttributeMixin_API implements AttributeType { + + @Inject(method = "", at = @At("TAIL")) + private void api$setKey(IAttribute parentIn, String unlocalizedNameIn, double defaultValueIn, CallbackInfo ci) { + // Thankfully in 1.16, mojang does not use camelCase in attributes. + this.api$key = ResourceKey.of(SpongeCommon.getActivePlugin(), CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, unlocalizedNameIn)); + } + + // This is gonna break if someone extends IAttribute + private ResourceKey api$key; + + @Override + public ResourceKey getKey() { + return this.api$key; + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/AttributeModifierMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/AttributeModifierMixin_API.java new file mode 100644 index 00000000000..5011d345030 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/AttributeModifierMixin_API.java @@ -0,0 +1,65 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.mcp.entity.ai.attributes; + +import org.spongepowered.api.entity.attribute.AttributeModifier; +import org.spongepowered.api.entity.attribute.AttributeOperation; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.UUID; + +@Mixin(net.minecraft.entity.ai.attributes.AttributeModifier.class) +@Implements(@Interface(iface = AttributeModifier.class, prefix = "api$")) +public abstract class AttributeModifierMixin_API implements AttributeModifier { + @Shadow public abstract String shadow$getName(); + @Shadow public abstract double shadow$getAmount(); + @Shadow public abstract net.minecraft.entity.ai.attributes.AttributeModifier.Operation shadow$getOperation(); + @Shadow public abstract UUID shadow$getID(); + + @Intrinsic + public String api$getName() { + return this.shadow$getName(); + } + + @Override + public AttributeOperation getOperation() { + return (AttributeOperation) (Object) this.shadow$getOperation(); + } + + @Intrinsic + public double api$getAmount() { + return this.shadow$getAmount(); + } + + @Override + public UUID getUniqueId() { + return this.shadow$getID(); + } + +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/AttributeModifier_OperationMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/AttributeModifier_OperationMixin_API.java new file mode 100644 index 00000000000..66ac247a6a4 --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/AttributeModifier_OperationMixin_API.java @@ -0,0 +1,50 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.mcp.entity.ai.attributes; + +import net.minecraft.entity.ai.attributes.AttributeModifier; +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.entity.attribute.AttributeOperation; +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.CallbackInfo; +import org.spongepowered.common.SpongeCommon; + +@Mixin(AttributeModifier.Operation.class) +public abstract class AttributeModifier_OperationMixin_API implements AttributeOperation { + + @Inject(method = "", at = @At("TAIL")) + private void api$setKey(String enumName, int ordinal, int id, CallbackInfo ci) { + this.api$key = ResourceKey.of(SpongeCommon.getActivePlugin(), enumName.toLowerCase()); + } + + private ResourceKey api$key; + + @Override + public ResourceKey getKey() { + return this.api$key; + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/IAttributeInstanceMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/IAttributeInstanceMixin_API.java new file mode 100644 index 00000000000..1c48c5f936c --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/IAttributeInstanceMixin_API.java @@ -0,0 +1,114 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.mcp.entity.ai.attributes; + +import net.minecraft.entity.ai.attributes.IAttribute; +import net.minecraft.entity.ai.attributes.IAttributeInstance; +import org.spongepowered.api.entity.attribute.Attribute; +import org.spongepowered.api.entity.attribute.AttributeModifier; +import org.spongepowered.api.entity.attribute.AttributeOperation; +import org.spongepowered.api.entity.attribute.type.AttributeType; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Collection; +import java.util.Optional; +import java.util.UUID; + +@Mixin(IAttributeInstance.class) +@Implements(@Interface(iface = Attribute.class, prefix = "api$")) +public interface IAttributeInstanceMixin_API extends Attribute { + + @Shadow IAttribute shadow$getAttribute(); + @Shadow double shadow$getBaseValue(); + @Shadow void shadow$setBaseValue(double baseValue); + @Shadow double shadow$getValue(); + @Shadow Collection shadow$getModifiers(); + @Shadow Collection shadow$func_220368_a(net.minecraft.entity.ai.attributes.AttributeModifier.Operation p_220368_1_); + @Shadow net.minecraft.entity.ai.attributes.AttributeModifier shadow$getModifier(UUID uuid); + @Shadow boolean shadow$hasModifier(net.minecraft.entity.ai.attributes.AttributeModifier modifier); + @Shadow void shadow$applyModifier(net.minecraft.entity.ai.attributes.AttributeModifier modifier); + @Shadow void shadow$removeModifier(net.minecraft.entity.ai.attributes.AttributeModifier modifier); + @Shadow void shadow$removeModifier(UUID uuid); + + @Override + default AttributeType getType() { + return (AttributeType) this.shadow$getAttribute(); + } + + @Intrinsic + default double api$getBaseValue() { + return this.shadow$getBaseValue(); + } + + @Intrinsic + default double api$getValue() { + return this.shadow$getValue(); + } + + @Intrinsic + default void api$setBaseValue(final double baseValue) { + this.shadow$setBaseValue(baseValue); + } + + @Override + default Collection getModifiers() { + return (Collection) this.shadow$getModifiers(); + } + + @Override + default Collection getModifiers(final AttributeOperation operation) { + return (Collection) this.shadow$func_220368_a((net.minecraft.entity.ai.attributes.AttributeModifier.Operation) (Object) operation); + } + + @Override + default boolean hasModifier(final AttributeModifier modifier) { + return this.shadow$hasModifier((net.minecraft.entity.ai.attributes.AttributeModifier) modifier); + } + + @Override + default Optional getModifier(final UUID uniqueId) { + return Optional.ofNullable((AttributeModifier) this.shadow$getModifier(uniqueId)); + } + + @Override + default void addModifier(final AttributeModifier modifier) { + this.shadow$applyModifier((net.minecraft.entity.ai.attributes.AttributeModifier) modifier); + } + + @Override + default void removeModifier(final AttributeModifier modifier) { + this.shadow$removeModifier((net.minecraft.entity.ai.attributes.AttributeModifier) modifier); + } + + @Override + default void removeModifier(final UUID uniqueId) { + this.shadow$removeModifier(uniqueId); + } + +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/IAttributeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/IAttributeMixin_API.java new file mode 100644 index 00000000000..2e672aedcef --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/IAttributeMixin_API.java @@ -0,0 +1,59 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.mcp.entity.ai.attributes; + +import net.minecraft.entity.ai.attributes.IAttribute; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.entity.attribute.type.AttributeType; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Optional; + +@Mixin(IAttribute.class) +@Implements(@Interface(iface = AttributeType.class, prefix = "api$")) +public interface IAttributeMixin_API extends AttributeType { + @Shadow @Nullable IAttribute shadow$getParent(); + @Shadow double shadow$getDefaultValue(); + @Shadow double shadow$clampValue(double value); + + @Override + default Optional getParent() { + return Optional.ofNullable((AttributeType) this.shadow$getParent()); + } + + @Intrinsic + default double api$getDefaultValue() { + return this.shadow$getDefaultValue(); + } + + @Intrinsic + default double api$clampValue(final double value) { + return this.shadow$clampValue(value); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/RangedAttributeMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/RangedAttributeMixin_API.java new file mode 100644 index 00000000000..69f6f10bd0e --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/mcp/entity/ai/attributes/RangedAttributeMixin_API.java @@ -0,0 +1,47 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.mcp.entity.ai.attributes; + +import net.minecraft.entity.ai.attributes.RangedAttribute; +import org.spongepowered.api.entity.attribute.type.RangedAttributeType; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(RangedAttribute.class) +public abstract class RangedAttributeMixin_API implements RangedAttributeType { + @Shadow @Final private double minimumValue; + @Shadow @Final private double maximumValue; + + @Override + public double getMinimumValue() { + return this.minimumValue; + } + + @Override + public double getMaximumValue() { + return this.maximumValue; + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/mcp/item/ItemStackMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/mcp/item/ItemStackMixin_API.java index fc563f214e6..3dd0c3d8e34 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/mcp/item/ItemStackMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/mcp/item/ItemStackMixin_API.java @@ -25,16 +25,24 @@ package org.spongepowered.common.mixin.api.mcp.item; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Multimap; +import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.item.Item; import net.minecraft.nbt.CompoundNBT; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.api.data.SerializableDataHolder; import org.spongepowered.api.data.persistence.DataContainer; import org.spongepowered.api.data.persistence.DataView; import org.spongepowered.api.data.persistence.InvalidDataException; import org.spongepowered.api.data.persistence.Queries; +import org.spongepowered.api.entity.attribute.AttributeModifier; +import org.spongepowered.api.entity.attribute.type.AttributeType; import org.spongepowered.api.item.ItemType; import org.spongepowered.api.item.inventory.ItemStack; import org.spongepowered.api.item.inventory.ItemStackSnapshot; +import org.spongepowered.api.item.inventory.equipment.EquipmentType; +import org.spongepowered.api.item.inventory.equipment.EquipmentTypes; import org.spongepowered.api.text.translation.Translation; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; @@ -43,11 +51,12 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.common.SpongeImplHooks; import org.spongepowered.common.data.persistence.NbtTranslator; +import org.spongepowered.common.data.type.SpongeEquipmentType; import org.spongepowered.common.item.SpongeItemStackSnapshot; import org.spongepowered.common.text.translation.SpongeTranslation; import org.spongepowered.common.util.Constants; -import javax.annotation.Nullable; +import java.util.Collection; @Mixin(net.minecraft.item.ItemStack.class) @Implements(@Interface(iface = ItemStack.class, prefix = "itemStack$")) // We need to soft implement this interface due to a synthetic bridge method @@ -64,6 +73,8 @@ public abstract class ItemStackMixin_API implements SerializableDataHolder.Mutab @Shadow public abstract CompoundNBT shadow$getTag(); @Shadow public abstract net.minecraft.item.ItemStack shadow$copy(); @Shadow public abstract Item shadow$getItem(); + @Shadow public abstract Multimap shadow$getAttributeModifiers(EquipmentSlotType equipmentSlot); + @Shadow public abstract void shadow$addAttributeModifier(String attributeName, net.minecraft.entity.ai.attributes.AttributeModifier modifier, @Nullable EquipmentSlotType equipmentSlot); public int itemStack$getQuantity() { return this.shadow$getCount(); @@ -117,6 +128,37 @@ public SerializableDataHolder.Mutable copy() { return (ItemStack) (Object) this.shadow$copy(); } + public Collection itemStack$getAttributeModifiers(final AttributeType attributeType, final EquipmentType equipmentType) { + Preconditions.checkNotNull(attributeType, "Attribute type cannot be null"); + Preconditions.checkNotNull(equipmentType, "Equipment type cannot be null"); + + final ImmutableList.Builder builder = ImmutableList.builder(); + + for (EquipmentSlotType equipmentSlotType : ((SpongeEquipmentType) equipmentType).getSlots()) { + final Multimap modifierMultimap = this.shadow$getAttributeModifiers(equipmentSlotType); + builder.addAll((Iterable) modifierMultimap.get(attributeType.getKey().getValue())); + } + + return builder.build(); + } + + public void itemStack$addAttributeModifier(final AttributeType attributeType, final AttributeModifier modifier, final EquipmentType equipmentType) { + Preconditions.checkNotNull(attributeType, "Attribute type cannot be null"); + Preconditions.checkNotNull(modifier, "Attribute modifier cannot be null"); + Preconditions.checkNotNull(equipmentType, "Equipment type cannot be null"); + + if (equipmentType.equals(EquipmentTypes.ANY.get()) || equipmentType.equals(EquipmentTypes.EQUIPPED.get())) { + // Any equipment slot = null + this.shadow$addAttributeModifier(modifier.getName(), (net.minecraft.entity.ai.attributes.AttributeModifier) modifier, null); + return; + } + + // Get all slots this modifier applies to, and apply + for (EquipmentSlotType equipmentSlotType : ((SpongeEquipmentType) equipmentType).getSlots()) { + this.shadow$addAttributeModifier(modifier.getName(), (net.minecraft.entity.ai.attributes.AttributeModifier) modifier, equipmentSlotType); + } + } + @Override public int getContentVersion() { return 1; diff --git a/src/mixins/resources/mixins.common.api.json b/src/mixins/resources/mixins.common.api.json index f43d3a3ceb8..e80ad8a1647 100644 --- a/src/mixins/resources/mixins.common.api.json +++ b/src/mixins/resources/mixins.common.api.json @@ -36,6 +36,12 @@ "mcp.entity.IRangedAttackMobMixin_API", "mcp.entity.LivingEntityMixin_API", "mcp.entity.MobEntityMixin_API", + "mcp.entity.ai.attributes.AttributeMixin_API", + "mcp.entity.ai.attributes.AttributeModifier_OperationMixin_API", + "mcp.entity.ai.attributes.AttributeModifierMixin_API", + "mcp.entity.ai.attributes.IAttributeInstanceMixin_API", + "mcp.entity.ai.attributes.IAttributeMixin_API", + "mcp.entity.ai.attributes.RangedAttributeMixin_API", "mcp.entity.ai.goal.AvoidLivingGoalMixin_API", "mcp.entity.ai.goal.GoalMixin_API", "mcp.entity.ai.goal.GoalSelectorMixin_API",