mirror of
https://github.com/FabricMC/fabric.git
synced 2025-03-13 16:53:35 -04:00
Add FabricItemSettings and an API for custom item equipment slots (#956)
* Add FabricItemSettings and an API for custom item equipment slots Closes #952. * Bump module version * Rename duck method to have fabric_ prefix and add Unique to mixin field * Switch to FabricItemInternals + ExtraData like in FabricBlockSettings
This commit is contained in:
parent
db9ee7acda
commit
eb1e5e8520
10 changed files with 348 additions and 1 deletions
|
@ -1,5 +1,5 @@
|
|||
archivesBaseName = "fabric-item-api-v1"
|
||||
version = getSubprojectVersion(project, "1.0.0")
|
||||
version = getSubprojectVersion(project, "1.1.0")
|
||||
|
||||
dependencies {
|
||||
compile project(path: ':fabric-api-base', configuration: 'dev')
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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.api.item.v1;
|
||||
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
/**
|
||||
* A provider for the preferred equipment slot of an item.
|
||||
* This can be used to give non-armor items, such as blocks,
|
||||
* an armor slot that they can go in.
|
||||
*
|
||||
* <p>Equipment slot providers can be set with {@link FabricItemSettings#equipmentSlot(EquipmentSlotProvider)}.
|
||||
*
|
||||
* <p>Note that items extending {@link net.minecraft.item.ArmorItem} don't need to use this
|
||||
* as there's {@link net.minecraft.item.ArmorItem#getSlotType()}.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface EquipmentSlotProvider {
|
||||
/**
|
||||
* Gets the preferred equipment slot for an item stack.
|
||||
*
|
||||
* <p>If there is no preferred armor equipment slot for the stack,
|
||||
* {@link EquipmentSlot#MAINHAND} can be returned.
|
||||
*
|
||||
* @param stack the item stack
|
||||
* @return the preferred equipment slot
|
||||
*/
|
||||
EquipmentSlot getPreferredEquipmentSlot(ItemStack stack);
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* 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.api.item.v1;
|
||||
|
||||
import net.minecraft.item.FoodComponent;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemGroup;
|
||||
import net.minecraft.util.Rarity;
|
||||
|
||||
import net.fabricmc.fabric.impl.item.FabricItemInternals;
|
||||
|
||||
/**
|
||||
* Fabric's version of Item.Settings. Adds additional methods and hooks
|
||||
* not found in the original class.
|
||||
*
|
||||
* <p>To use it, simply replace {@code new Item.Settings()} with
|
||||
* {@code new FabricItemSettings()}.
|
||||
*/
|
||||
public class FabricItemSettings extends Item.Settings {
|
||||
/**
|
||||
* Sets the equipment slot provider of the item.
|
||||
*
|
||||
* @param equipmentSlotProvider the equipment slot provider
|
||||
* @return this builder
|
||||
*/
|
||||
public FabricItemSettings equipmentSlot(EquipmentSlotProvider equipmentSlotProvider) {
|
||||
FabricItemInternals.computeExtraData(this).equipmentSlot(equipmentSlotProvider);
|
||||
return this;
|
||||
}
|
||||
|
||||
// Overrides of vanilla methods
|
||||
|
||||
@Override
|
||||
public FabricItemSettings food(FoodComponent foodComponent) {
|
||||
super.food(foodComponent);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricItemSettings maxCount(int maxCount) {
|
||||
super.maxCount(maxCount);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricItemSettings maxDamageIfAbsent(int maxDamage) {
|
||||
super.maxDamageIfAbsent(maxDamage);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricItemSettings maxDamage(int maxDamage) {
|
||||
super.maxDamage(maxDamage);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricItemSettings recipeRemainder(Item recipeRemainder) {
|
||||
super.recipeRemainder(recipeRemainder);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricItemSettings group(ItemGroup group) {
|
||||
super.group(group);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricItemSettings rarity(Rarity rarity) {
|
||||
super.rarity(rarity);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricItemSettings fireproof() {
|
||||
super.fireproof();
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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.impl.item;
|
||||
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
|
||||
import net.fabricmc.fabric.api.item.v1.EquipmentSlotProvider;
|
||||
|
||||
public final class FabricItemInternals {
|
||||
private static final WeakHashMap<Item.Settings, ExtraData> extraData = new WeakHashMap<>();
|
||||
|
||||
private FabricItemInternals() {
|
||||
}
|
||||
|
||||
public static ExtraData computeExtraData(Item.Settings settings) {
|
||||
return extraData.computeIfAbsent(settings, s -> new ExtraData());
|
||||
}
|
||||
|
||||
public static void onBuild(Item.Settings settings, Item item) {
|
||||
ExtraData data = extraData.get(settings);
|
||||
|
||||
if (data != null) {
|
||||
((ItemExtensions) item).fabric_setEquipmentSlotProvider(data.equipmentSlotProvider);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ExtraData {
|
||||
private /* @Nullable */ EquipmentSlotProvider equipmentSlotProvider;
|
||||
|
||||
public void equipmentSlot(EquipmentSlotProvider equipmentSlotProvider) {
|
||||
this.equipmentSlotProvider = equipmentSlotProvider;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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.impl.item;
|
||||
|
||||
import net.fabricmc.fabric.api.item.v1.EquipmentSlotProvider;
|
||||
|
||||
public interface ItemExtensions {
|
||||
EquipmentSlotProvider fabric_getEquipmentSlotProvider();
|
||||
void fabric_setEquipmentSlotProvider(EquipmentSlotProvider equipmentSlotProvider);
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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 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;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
|
||||
import net.fabricmc.fabric.api.item.v1.EquipmentSlotProvider;
|
||||
import net.fabricmc.fabric.impl.item.FabricItemInternals;
|
||||
import net.fabricmc.fabric.impl.item.ItemExtensions;
|
||||
|
||||
@Mixin(Item.class)
|
||||
abstract class ItemMixin implements ItemExtensions {
|
||||
@Unique
|
||||
private EquipmentSlotProvider equipmentSlotProvider;
|
||||
|
||||
@Inject(method = "<init>", at = @At("RETURN"))
|
||||
private void onConstruct(Item.Settings settings, CallbackInfo info) {
|
||||
FabricItemInternals.onBuild(settings, (Item) (Object) this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EquipmentSlotProvider fabric_getEquipmentSlotProvider() {
|
||||
return equipmentSlotProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fabric_setEquipmentSlotProvider(EquipmentSlotProvider equipmentSlotProvider) {
|
||||
this.equipmentSlotProvider = equipmentSlotProvider;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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 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;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.mob.MobEntity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import net.fabricmc.fabric.api.item.v1.EquipmentSlotProvider;
|
||||
import net.fabricmc.fabric.impl.item.ItemExtensions;
|
||||
|
||||
@Mixin(MobEntity.class)
|
||||
abstract class MobEntityMixin {
|
||||
@Inject(method = "getPreferredEquipmentSlot", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/item/ItemStack;getItem()Lnet/minecraft/item/Item;"), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
private static void onGetPreferredEquipmentSlot(ItemStack stack, CallbackInfoReturnable<EquipmentSlot> info, Item item) {
|
||||
EquipmentSlotProvider equipmentSlotProvider = ((ItemExtensions) item).fabric_getEquipmentSlotProvider();
|
||||
|
||||
if (equipmentSlotProvider != null) {
|
||||
info.setReturnValue(equipmentSlotProvider.getPreferredEquipmentSlot(stack));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,6 +2,10 @@
|
|||
"required": true,
|
||||
"package": "net.fabricmc.fabric.mixin.item",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [
|
||||
"ItemMixin",
|
||||
"MobEntityMixin"
|
||||
],
|
||||
"client": [
|
||||
"client.ItemStackMixin"
|
||||
],
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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.Item;
|
||||
import net.minecraft.item.ItemGroup;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
|
||||
|
||||
public class FabricItemSettingsTests implements ModInitializer {
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
// Registers an item with a custom equipment slot.
|
||||
Item testItem = new Item(new FabricItemSettings().group(ItemGroup.MISC).equipmentSlot(stack -> EquipmentSlot.CHEST));
|
||||
Registry.register(Registry.ITEM, new Identifier("fabric-item-api-v1-testmod", "test_item"), testItem);
|
||||
}
|
||||
}
|
|
@ -9,6 +9,9 @@
|
|||
"fabric-item-api-v1": "*"
|
||||
},
|
||||
"entrypoints": {
|
||||
"main": [
|
||||
"net.fabricmc.fabric.test.item.FabricItemSettingsTests"
|
||||
],
|
||||
"client": [
|
||||
"net.fabricmc.fabric.test.item.client.TooltipTests"
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue