mirror of
https://github.com/FabricMC/fabric.git
synced 2024-11-30 03:26:07 -05:00
fabric-mining-levels-v0 -> fabric-tool-attribute-api-v1 (1.15 edition) (#460)
Moves the ToolManager and tool tags declared in fabric-mining-levels-v0 to a new fabric-tool-attributes-v1, along with adding new interfaces to be implemented on tools so that mining speed, mining level, and entity attribute modifiers can be decided by the itemstack.
This commit is contained in:
parent
6c0e72dfcd
commit
b764ce9905
29 changed files with 573 additions and 127 deletions
|
@ -4,4 +4,5 @@ version = getSubprojectVersion(project, "0.1.2")
|
|||
dependencies {
|
||||
compile project(path: ':fabric-api-base', configuration: 'dev')
|
||||
compile project(path: ':fabric-tag-extensions-v0', configuration: 'dev')
|
||||
compile project(path: ':fabric-tool-attribute-api-v1', configuration: 'dev')
|
||||
}
|
||||
|
|
|
@ -20,12 +20,12 @@ import net.minecraft.item.Item;
|
|||
import net.minecraft.tag.Tag;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import net.fabricmc.fabric.api.tools.FabricToolTags;
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
|
||||
|
||||
/**
|
||||
* Item tags provided by Fabric.
|
||||
*
|
||||
* @deprecated Use dedicated classes, such as {@link net.fabricmc.fabric.api.tools.FabricToolTags}
|
||||
* @deprecated Use dedicated classes, such as {@link FabricToolTags}
|
||||
*/
|
||||
@Deprecated
|
||||
public class FabricItemTags {
|
||||
|
|
|
@ -18,23 +18,19 @@ package net.fabricmc.fabric.api.tools;
|
|||
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.tag.Tag;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import net.fabricmc.fabric.api.tag.TagRegistry;
|
||||
|
||||
/**
|
||||
* Tool item tags provided by Fabric.
|
||||
*
|
||||
* @deprecated Use the moved {@link net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags} class instead
|
||||
*/
|
||||
@Deprecated
|
||||
public class FabricToolTags {
|
||||
public static final Tag<Item> AXES = register("axes");
|
||||
public static final Tag<Item> HOES = register("hoes");
|
||||
public static final Tag<Item> PICKAXES = register("pickaxes");
|
||||
public static final Tag<Item> SHOVELS = register("shovels");
|
||||
public static final Tag<Item> SWORDS = register("swords");
|
||||
public static final Tag<Item> AXES = net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags.AXES;
|
||||
public static final Tag<Item> HOES = net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags.HOES;
|
||||
public static final Tag<Item> PICKAXES = net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags.PICKAXES;
|
||||
public static final Tag<Item> SHOVELS = net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags.SHOVELS;
|
||||
public static final Tag<Item> SWORDS = net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags.SWORDS;
|
||||
|
||||
private FabricToolTags() { }
|
||||
|
||||
private static Tag<Item> register(String id) {
|
||||
return TagRegistry.item(new Identifier("fabric", id));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* 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.mining.level;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
import net.minecraft.item.MiningToolItem;
|
||||
|
||||
@Mixin(MiningToolItem.class)
|
||||
public interface MiningToolItemAccessor {
|
||||
@Accessor
|
||||
float getMiningSpeed();
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* 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.mining.level;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import net.fabricmc.fabric.api.util.TriState;
|
||||
import net.fabricmc.fabric.impl.mining.level.ToolManager;
|
||||
|
||||
@Mixin(ItemStack.class)
|
||||
public abstract class MixinItemStack {
|
||||
@Shadow
|
||||
public abstract Item getItem();
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "isEffectiveOn", cancellable = true)
|
||||
public void isEffectiveOn(BlockState state, CallbackInfoReturnable<Boolean> info) {
|
||||
TriState triState = ToolManager.handleIsEffectiveOn((ItemStack) (Object) this, state);
|
||||
|
||||
if (triState != TriState.DEFAULT) {
|
||||
info.setReturnValue(triState.get());
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "getMiningSpeedMultiplier", cancellable = true)
|
||||
public void getBlockBreakingSpeed(BlockState state, CallbackInfoReturnable<Float> info) {
|
||||
if (this.getItem() instanceof MiningToolItemAccessor) {
|
||||
TriState triState = ToolManager.handleIsEffectiveOn((ItemStack) (Object) this, state);
|
||||
|
||||
if (triState != TriState.DEFAULT) {
|
||||
info.setReturnValue(triState.get() ? ((MiningToolItemAccessor) this.getItem()).getMiningSpeed() : 1.0F);
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"required": true,
|
||||
"package": "net.fabricmc.fabric.mixin.mining.level",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [
|
||||
"MiningToolItemAccessor",
|
||||
"MixinItemStack"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
|
@ -18,10 +18,8 @@
|
|||
"depends": {
|
||||
"fabricloader": ">=0.4.0",
|
||||
"fabric-api-base": "*",
|
||||
"fabric-tag-extensions-v0": "*"
|
||||
"fabric-tag-extensions-v0": "*",
|
||||
"fabric-tool-attribute-api-v1": "*"
|
||||
},
|
||||
"description": "Block mining level tags for tools.",
|
||||
"mixins": [
|
||||
"fabric-mining-levels-v0.mixins.json"
|
||||
]
|
||||
"description": "Block mining level tags for tools. Deprecated and replaced by fabric-tool-attribute-v1."
|
||||
}
|
||||
|
|
|
@ -3,5 +3,5 @@ version = getSubprojectVersion(project, "0.2.5")
|
|||
|
||||
dependencies {
|
||||
compile project(path: ':fabric-api-base', configuration: 'dev')
|
||||
compile project(path: ':fabric-mining-levels-v0', configuration: 'dev')
|
||||
compile project(path: ':fabric-tool-attribute-api-v1', configuration: 'dev')
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ import net.minecraft.util.DyeColor;
|
|||
import net.minecraft.util.Identifier;
|
||||
|
||||
import net.fabricmc.fabric.api.event.registry.BlockConstructedCallback;
|
||||
import net.fabricmc.fabric.impl.mining.level.ToolManager;
|
||||
import net.fabricmc.fabric.impl.tool.attribute.ToolManager;
|
||||
|
||||
/**
|
||||
* Fabric's version of Block.Settings. Adds additional methods and hooks
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
"depends": {
|
||||
"fabricloader": ">=0.4.0",
|
||||
"fabric-api-base": "*",
|
||||
"fabric-mining-levels-v0": "*"
|
||||
"fabric-tool-attribute-api-v1": "*"
|
||||
},
|
||||
"description": "Builders for objects vanilla has locked down.",
|
||||
"mixins": [
|
||||
|
|
7
fabric-tool-attribute-api-v1/build.gradle
Normal file
7
fabric-tool-attribute-api-v1/build.gradle
Normal file
|
@ -0,0 +1,7 @@
|
|||
archivesBaseName = "fabric-tool-attribute-api-v1"
|
||||
version = getSubprojectVersion(project, "1.0.1")
|
||||
|
||||
dependencies {
|
||||
compile project(path: ':fabric-api-base', configuration: 'dev')
|
||||
compile project(path: ':fabric-tag-extensions-v0', configuration: 'dev')
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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.tool.attribute.v1;
|
||||
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.attribute.EntityAttribute;
|
||||
import net.minecraft.entity.attribute.EntityAttributeModifier;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
/**
|
||||
* Interface for adding various tool attributes to items.
|
||||
*/
|
||||
public interface DynamicAttributeTool {
|
||||
Multimap<EntityAttribute, EntityAttributeModifier> EMPTY = ImmutableSetMultimap.of();
|
||||
|
||||
/**
|
||||
* Determines the mining level of the passed stack, which is used for calculating what blocks this tool is allowed to break.
|
||||
*
|
||||
* @param stack The stack to check on.
|
||||
* @param user The current user of the tool, or null if there isn't any.
|
||||
* @return The mining level of the item. 3 is equal to a diamond pick.
|
||||
*/
|
||||
//TODO: nullable on user once we have an official @Nullable annotation in
|
||||
int getMiningLevel(ItemStack stack, LivingEntity user);
|
||||
|
||||
/**
|
||||
* Determines the mining speed multiplier of the passed stack, which is one factor in overall mining speed.
|
||||
*
|
||||
* @param stack The stack to check on.
|
||||
* @param user The current user of the tool, or null if there isn't any.
|
||||
* @return The mining speed multiplier of the item. 8.0 is equal to a diamond pick.
|
||||
*/
|
||||
//TODO: nullable on user once we have an official @Nullable annotation in
|
||||
float getMiningSpeedMultiplier(ItemStack stack, LivingEntity user);
|
||||
|
||||
/**
|
||||
* Add modifiers for any {@link net.minecraft.entity.attribute.EntityAttributes} your item should give when equipped, based on the stack.
|
||||
*
|
||||
* <p>Appends to either attribute modifier NBT or the result from {@link net.minecraft.item.Item#getModifiers(EquipmentSlot)}.</p>
|
||||
*
|
||||
* @param slot The equipment slot this item is equipped in.
|
||||
* @param stack The stack that's equipped.
|
||||
* @param user The current user of the tool, or none if there isn't any
|
||||
* @return The dynamic modifiers to add on top of other modifiers on this stack. If none, return {@link #EMPTY}.
|
||||
*/
|
||||
//TODO: nullable on user once we have an official @Nullable annotation in
|
||||
default Multimap<EntityAttribute, EntityAttributeModifier> getDynamicModifiers(EquipmentSlot slot, ItemStack stack, LivingEntity user) {
|
||||
return EMPTY;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.tool.attribute.v1;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.tag.Tag;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import net.fabricmc.fabric.api.tag.TagRegistry;
|
||||
|
||||
/**
|
||||
* Tool item tags provided by Fabric.
|
||||
*/
|
||||
public class FabricToolTags {
|
||||
public static final Tag<Item> AXES = register("axes");
|
||||
public static final Tag<Item> HOES = register("hoes");
|
||||
public static final Tag<Item> PICKAXES = register("pickaxes");
|
||||
public static final Tag<Item> SHOVELS = register("shovels");
|
||||
public static final Tag<Item> SWORDS = register("swords");
|
||||
public static final Tag<Item> SHEARS = register("shears");
|
||||
|
||||
private FabricToolTags() { }
|
||||
|
||||
private static Tag<Item> register(String id) {
|
||||
return TagRegistry.item(new Identifier("fabric", id));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* 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.tool.attribute;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import net.minecraft.entity.attribute.EntityAttribute;
|
||||
import net.minecraft.entity.attribute.EntityAttributeModifier;
|
||||
|
||||
public final class AttributeManager {
|
||||
private AttributeManager() { }
|
||||
|
||||
/**
|
||||
* Merge two multimaps of EntityAttributeModifiers, combining their modifiers to prevent duplicate entries in a tooltip.
|
||||
*
|
||||
* @param left The first of the two multimaps to merge.
|
||||
* @param right The second of the two multimaps to merge.
|
||||
* @return The merged form of the two.
|
||||
*/
|
||||
public static Multimap<EntityAttribute, EntityAttributeModifier> mergeAttributes(Multimap<EntityAttribute, EntityAttributeModifier> left, Multimap<EntityAttribute, EntityAttributeModifier> right) {
|
||||
if (left.isEmpty()) return right;
|
||||
if (right.isEmpty()) return left;
|
||||
Multimap<EntityAttribute, EntityAttributeModifier> ret = HashMultimap.create();
|
||||
Set<EntityAttribute> allKeys = new HashSet<>();
|
||||
allKeys.addAll(left.keySet());
|
||||
allKeys.addAll(right.keySet());
|
||||
|
||||
for (EntityAttribute key : allKeys) {
|
||||
Collection<EntityAttributeModifier> leftModifiers = left.get(key);
|
||||
Collection<EntityAttributeModifier> rightModifiers = right.get(key);
|
||||
|
||||
if (leftModifiers.isEmpty()) {
|
||||
ret.putAll(key, rightModifiers);
|
||||
} else if (rightModifiers.isEmpty()) {
|
||||
ret.putAll(key, leftModifiers);
|
||||
} else {
|
||||
Collection<EntityAttributeModifier> modifiers = new ArrayList<>(leftModifiers.size() + rightModifiers.size());
|
||||
modifiers.addAll(leftModifiers);
|
||||
modifiers.addAll(rightModifiers);
|
||||
|
||||
EntityAttributeModifier lastAddMod = null;
|
||||
EntityAttributeModifier lastMultBaseMod = null;
|
||||
EntityAttributeModifier lastMultTotalMod = null;
|
||||
int addCount = 0;
|
||||
int multBaseCount = 0;
|
||||
int multTotalCount = 0;
|
||||
double add = 0;
|
||||
double multBase = 1;
|
||||
double multTotal = 1;
|
||||
|
||||
for (EntityAttributeModifier mod : modifiers) {
|
||||
double amount = mod.getAmount();
|
||||
if (amount == 0) continue;
|
||||
|
||||
switch (mod.getOperation()) {
|
||||
case ADDITION:
|
||||
lastAddMod = mod;
|
||||
addCount++;
|
||||
add += amount;
|
||||
break;
|
||||
case MULTIPLY_BASE:
|
||||
lastMultBaseMod = mod;
|
||||
multBaseCount++;
|
||||
multBase += amount;
|
||||
break;
|
||||
case MULTIPLY_TOTAL:
|
||||
lastMultTotalMod = mod;
|
||||
multTotalCount++;
|
||||
multTotal *= 1 + amount;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (addCount == 1) {
|
||||
ret.put(key, lastAddMod);
|
||||
} else if (addCount > 0) {
|
||||
ret.put(key, new EntityAttributeModifier("merged add", add, EntityAttributeModifier.Operation.ADDITION));
|
||||
}
|
||||
|
||||
if (multBaseCount == 1) {
|
||||
ret.put(key, lastMultBaseMod);
|
||||
} else if (multBaseCount > 0) {
|
||||
ret.put(key, new EntityAttributeModifier("merged multiply-base", multBase, EntityAttributeModifier.Operation.MULTIPLY_BASE));
|
||||
}
|
||||
|
||||
if (multTotalCount == 1) {
|
||||
ret.put(key, lastMultTotalMod);
|
||||
} else if (multTotalCount > 0) {
|
||||
ret.put(key, new EntityAttributeModifier("merged multiply-total", multTotal, EntityAttributeModifier.Operation.MULTIPLY_TOTAL));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -14,18 +14,19 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.impl.mining.level;
|
||||
package net.fabricmc.fabric.impl.tool.attribute;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ToolItem;
|
||||
import net.minecraft.tag.Tag;
|
||||
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.DynamicAttributeTool;
|
||||
import net.fabricmc.fabric.api.util.TriState;
|
||||
|
||||
public final class ToolManager {
|
||||
|
@ -85,9 +86,10 @@ public final class ToolManager {
|
|||
entry(block).putBreakByTool(tag, miningLevel);
|
||||
}
|
||||
|
||||
private static int getMiningLevel(ItemStack stack) {
|
||||
if (stack.getItem() instanceof ToolItem) {
|
||||
return ((ToolItem) stack.getItem()).getMaterial().getMiningLevel();
|
||||
//TODO: nullable on user once we have an official @Nullable annotation in
|
||||
private static int getMiningLevel(ItemStack stack, LivingEntity user) {
|
||||
if (stack.getItem() instanceof DynamicAttributeTool) {
|
||||
return ((DynamicAttributeTool) stack.getItem()).getMiningLevel(stack, user);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
@ -96,7 +98,8 @@ public final class ToolManager {
|
|||
/**
|
||||
* Hook for ItemStack.isEffectiveOn and similar methods.
|
||||
*/
|
||||
public static TriState handleIsEffectiveOn(ItemStack stack, BlockState state) {
|
||||
//TODO: nullable on user once we have an official @Nullable annotation in
|
||||
public static TriState handleIsEffectiveOn(ItemStack stack, BlockState state, LivingEntity user) {
|
||||
EntryImpl entry = entries.get(state.getBlock());
|
||||
|
||||
if (entry != null) {
|
||||
|
@ -104,7 +107,7 @@ public final class ToolManager {
|
|||
|
||||
for (int i = 0; i < entry.tags.length; i++) {
|
||||
if (item.isIn(entry.tags[i])) {
|
||||
return TriState.of(getMiningLevel(stack) >= entry.tagLevels[i]);
|
||||
return TriState.of(getMiningLevel(stack, user) >= entry.tagLevels[i]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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.tool.attribute;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.attribute.EntityAttribute;
|
||||
import net.minecraft.entity.attribute.EntityAttributeModifier;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.DynamicAttributeTool;
|
||||
import net.fabricmc.fabric.api.util.TriState;
|
||||
import net.fabricmc.fabric.impl.tool.attribute.AttributeManager;
|
||||
import net.fabricmc.fabric.impl.tool.attribute.ToolManager;
|
||||
|
||||
@Mixin(ItemStack.class)
|
||||
public abstract class MixinItemStack {
|
||||
@Shadow
|
||||
public abstract Item getItem();
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "isEffectiveOn", cancellable = true)
|
||||
public void isEffectiveOn(BlockState state, CallbackInfoReturnable<Boolean> info) {
|
||||
TriState triState = ToolManager.handleIsEffectiveOn((ItemStack) (Object) this, state, null);
|
||||
|
||||
if (triState != TriState.DEFAULT) {
|
||||
info.setReturnValue(triState.get());
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "getMiningSpeedMultiplier", cancellable = true)
|
||||
public void getMiningSpeedMultiplier(BlockState state, CallbackInfoReturnable<Float> info) {
|
||||
TriState triState = ToolManager.handleIsEffectiveOn((ItemStack) (Object) this, state, null);
|
||||
|
||||
if (triState != TriState.DEFAULT) {
|
||||
Item item = this.getItem();
|
||||
float miningSpeed;
|
||||
|
||||
if (item instanceof DynamicAttributeTool) {
|
||||
miningSpeed = ((DynamicAttributeTool) this.getItem()).getMiningSpeedMultiplier((ItemStack) (Object) this, null);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
info.setReturnValue(triState.get() ? miningSpeed : 1.0F);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(at = @At("RETURN"), method = "getAttributeModifiers", cancellable = true, locals = LocalCapture.CAPTURE_FAILEXCEPTION)
|
||||
public void getAttributeModifiers(EquipmentSlot slot, CallbackInfoReturnable<Multimap<EntityAttribute, EntityAttributeModifier>> info, Multimap<EntityAttribute, EntityAttributeModifier> multimap) {
|
||||
ItemStack stack = (ItemStack) (Object) this;
|
||||
|
||||
if (stack.getItem() instanceof DynamicAttributeTool) {
|
||||
DynamicAttributeTool holder = (DynamicAttributeTool) stack.getItem();
|
||||
Multimap<EntityAttribute, EntityAttributeModifier> ret = AttributeManager.mergeAttributes(multimap, (holder).getDynamicModifiers(slot, stack, null));
|
||||
info.setReturnValue(ret);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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.tool.attribute;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.attribute.EntityAttribute;
|
||||
import net.minecraft.entity.attribute.EntityAttributeModifier;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.DynamicAttributeTool;
|
||||
import net.fabricmc.fabric.impl.tool.attribute.AttributeManager;
|
||||
|
||||
@Mixin(LivingEntity.class)
|
||||
public abstract class MixinLivingEntity extends Entity {
|
||||
public MixinLivingEntity(EntityType<?> type, World world) {
|
||||
super(type, world);
|
||||
}
|
||||
|
||||
/**
|
||||
* @author B0undarybreaker
|
||||
* @reason get entity attribute modifiers for dynamic tools
|
||||
*/
|
||||
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getAttributeModifiers(Lnet/minecraft/entity/EquipmentSlot;)Lcom/google/common/collect/Multimap;"))
|
||||
public Multimap<EntityAttribute, EntityAttributeModifier> actTickModifiers(ItemStack stack, EquipmentSlot slot) {
|
||||
return actModifiers(stack, slot, (LivingEntity) (Object) this);
|
||||
}
|
||||
|
||||
private static Multimap<EntityAttribute, EntityAttributeModifier> actModifiers(ItemStack stack, EquipmentSlot slot, LivingEntity user) {
|
||||
Multimap<EntityAttribute, EntityAttributeModifier> original = stack.getAttributeModifiers(slot);
|
||||
|
||||
if (stack.getItem() instanceof DynamicAttributeTool) {
|
||||
DynamicAttributeTool tool = (DynamicAttributeTool) stack.getItem();
|
||||
return (AttributeManager.mergeAttributes(original, tool.getDynamicModifiers(slot, stack, user)));
|
||||
}
|
||||
|
||||
return original;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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.tool.attribute;
|
||||
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.DynamicAttributeTool;
|
||||
import net.fabricmc.fabric.api.util.TriState;
|
||||
import net.fabricmc.fabric.impl.tool.attribute.ToolManager;
|
||||
|
||||
@Mixin(PlayerInventory.class)
|
||||
public abstract class MixinPlayerInventory {
|
||||
@Shadow
|
||||
@Final
|
||||
public DefaultedList<ItemStack> main;
|
||||
|
||||
@Shadow
|
||||
public int selectedSlot;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
public PlayerEntity player;
|
||||
|
||||
@Shadow
|
||||
public abstract ItemStack getStack(int int_1);
|
||||
|
||||
@Inject(method = "isUsingEffectiveTool", at = @At("HEAD"), cancellable = true)
|
||||
public void actMiningLevel(BlockState state, CallbackInfoReturnable<Boolean> info) {
|
||||
ItemStack stack = this.getStack(this.selectedSlot);
|
||||
|
||||
if (stack.getItem() instanceof DynamicAttributeTool) {
|
||||
TriState ret = ToolManager.handleIsEffectiveOn(stack, state, player);
|
||||
|
||||
if (ret != TriState.DEFAULT) {
|
||||
info.setReturnValue(ret.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "getBlockBreakingSpeed", at = @At("HEAD"), cancellable = true)
|
||||
public void actMiningSleed(BlockState state, CallbackInfoReturnable<Float> info) {
|
||||
ItemStack stack = this.main.get(this.selectedSlot);
|
||||
|
||||
if (stack.getItem() instanceof DynamicAttributeTool) {
|
||||
info.setReturnValue(((DynamicAttributeTool) stack.getItem()).getMiningSpeedMultiplier(stack, player));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.tool.attribute;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ToolItem;
|
||||
import net.minecraft.item.ToolMaterial;
|
||||
|
||||
import net.fabricmc.fabric.api.tool.attribute.v1.DynamicAttributeTool;
|
||||
|
||||
@Mixin(ToolItem.class)
|
||||
public abstract class MixinToolItem extends Item implements DynamicAttributeTool {
|
||||
@Shadow
|
||||
public abstract ToolMaterial getMaterial();
|
||||
|
||||
public MixinToolItem(Settings settings) {
|
||||
super(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMiningLevel(ItemStack stack, LivingEntity user) {
|
||||
return this.getMaterial().getMiningLevel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMiningSpeedMultiplier(ItemStack stack, LivingEntity user) {
|
||||
return this.getMaterial().getMiningSpeedMultiplier();
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
"minecraft:shears"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"required": true,
|
||||
"package": "net.fabricmc.fabric.mixin.tool.attribute",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [
|
||||
"MixinItemStack",
|
||||
"MixinLivingEntity",
|
||||
"MixinPlayerInventory",
|
||||
"MixinToolItem"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "fabric-tool-attribute-api-v1",
|
||||
"name": "Fabric Tool Attribute API (v1)",
|
||||
"version": "${version}",
|
||||
"environment": "*",
|
||||
"license": "Apache-2.0",
|
||||
"icon": "assets/fabric-tool-attribute0api-v1/icon.png",
|
||||
"contact": {
|
||||
"homepage": "https://fabricmc.net",
|
||||
"irc": "irc://irc.esper.net:6667/fabric",
|
||||
"issues": "https://github.com/FabricMC/fabric/issues",
|
||||
"sources": "https://github.com/FabricMC/fabric"
|
||||
},
|
||||
"authors": [
|
||||
"FabricMC"
|
||||
],
|
||||
"depends": {
|
||||
"fabricloader": ">=0.4.0",
|
||||
"fabric-api-base": "*",
|
||||
"fabric-tag-extensions-v0": "*"
|
||||
},
|
||||
"description": "Dynamic atttributes for tools.",
|
||||
"mixins": [
|
||||
"fabric-tool-attribute-api-v1.mixins.json"
|
||||
]
|
||||
}
|
|
@ -43,3 +43,4 @@ include 'fabric-resource-loader-v0'
|
|||
include 'fabric-tag-extensions-v0'
|
||||
include 'fabric-textures-v0'
|
||||
include 'fabric-dimensions-v1'
|
||||
include 'fabric-tool-attribute-api-v1'
|
||||
|
|
Loading…
Reference in a new issue