Add Shears ToolActions (#7997)

Make shear interactions extend to subclasses
Add Shears actions for beehive harvesting, pumpkin carving and trip wire disarming
This commit is contained in:
cech12 authored and GitHub committed 2021-08-30 13:42:37 -07:00
1 parent c5a1c90366
commit a336e443f7
31 files changed
+231 -161

No files matched your search

@@ -36,6 +36,7 @@ import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.common.data.ForgeFluidTagsProvider;
import net.minecraftforge.common.loot.CanToolPerformAction;
import net.minecraftforge.common.loot.GlobalLootModifierSerializer;
import net.minecraftforge.common.loot.LootTableIdCondition;
import net.minecraftforge.eventbus.api.IEventBus;
@@ -314,5 +315,6 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
{
// Ignore the event itself: this is done only not to statically initialize our custom LootConditionType
Registry.register(Registry.LOOT_CONDITION_TYPE, new ResourceLocation("forge:loot_table_id"), LootTableIdCondition.LOOT_TABLE_ID);
Registry.register(Registry.LOOT_CONDITION_TYPE, new ResourceLocation("forge:can_tool_perform_action"), CanToolPerformAction.LOOT_CONDITION_TYPE);
}
}
@@ -54,6 +54,11 @@ public class ToolActions
*/
public static final ToolAction SWORD_DIG = ToolAction.get("sword_dig");
/**
* Exposed by shears to allow querying tool behaviours
*/
public static final ToolAction SHEARS_DIG = ToolAction.get("shears_dig");
/**
* Passed onto {@link IForgeBlock#getToolModifiedState} when an axe wants to strip a log
*/
@@ -80,7 +85,25 @@ public class ToolActions
* @see {@link IForgeItem#getSweepHitBox}
*/
public static final ToolAction SWORD_SWEEP = ToolAction.get("sword_sweep");
/**
* This action is exposed by shears and corresponds to a harvest action that is triggered with a right click on a block that supports such behaviour.
* Example: Right click with shears on a beehive with honey level 5 to harvest it
*/
public static final ToolAction SHEARS_HARVEST = ToolAction.get("shears_harvest");
/**
* This action is exposed by shears and corresponds to a carve action that is triggered with a right click on a block that supports such behaviour.
* Example: Right click with shears o a pumpkin to carve it
*/
public static final ToolAction SHEARS_CARVE = ToolAction.get("shears_carve");
/**
* This action is exposed by shears and corresponds to a disarm action that is triggered by breaking a block that supports such behaviour.
* Example: Breaking a trip wire with shears to disarm it.
*/
public static final ToolAction SHEARS_DISARM = ToolAction.get("shears_disarm");
///**
// * Passed onto {@link IForgeBlock#getToolModifiedState} when a hoe wants to turn dirt into soil
// */
@@ -88,9 +111,14 @@ public class ToolActions
// Default actions supported by each tool type
public static final Set<ToolAction> DEFAULT_AXE_ACTIONS = Stream.of(AXE_DIG, AXE_STRIP, AXE_SCRAPE, AXE_WAX_OFF).collect(Collectors.toCollection(Sets::newIdentityHashSet));
public static final Set<ToolAction> DEFAULT_HOE_ACTIONS = Stream.of(HOE_DIG /* TODO: , HOE_TILL */).collect(Collectors.toCollection(Sets::newIdentityHashSet));
public static final Set<ToolAction> DEFAULT_SHOVEL_ACTIONS = Stream.of(SHOVEL_DIG, SHOVEL_FLATTEN).collect(Collectors.toCollection(Sets::newIdentityHashSet));
public static final Set<ToolAction> DEFAULT_PICKAXE_ACTIONS = Stream.of(PICKAXE_DIG).collect(Collectors.toCollection(Sets::newIdentityHashSet));
public static final Set<ToolAction> DEFAULT_SWORD_ACTIONS = Stream.of(SWORD_DIG, SWORD_SWEEP).collect(Collectors.toCollection(Sets::newIdentityHashSet));
public static final Set<ToolAction> DEFAULT_AXE_ACTIONS = of(AXE_DIG, AXE_STRIP, AXE_SCRAPE, AXE_WAX_OFF);
public static final Set<ToolAction> DEFAULT_HOE_ACTIONS = of(HOE_DIG /* TODO: , HOE_TILL */);
public static final Set<ToolAction> DEFAULT_SHOVEL_ACTIONS = of(SHOVEL_DIG, SHOVEL_FLATTEN);
public static final Set<ToolAction> DEFAULT_PICKAXE_ACTIONS = of(PICKAXE_DIG);
public static final Set<ToolAction> DEFAULT_SWORD_ACTIONS = of(SWORD_DIG, SWORD_SWEEP);
public static final Set<ToolAction> DEFAULT_SHEARS_ACTIONS = of(SHEARS_DIG, SHEARS_HARVEST, SHEARS_CARVE, SHEARS_DISARM);
private static Set<ToolAction> of(ToolAction... actions) {
return Stream.of(actions).collect(Collectors.toCollection(Sets::newIdentityHashSet));
}
}
@@ -25,13 +25,14 @@ import net.minecraft.data.DataGenerator;
import net.minecraft.data.loot.LootTableProvider;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Items;
import net.minecraft.tags.Tag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.storage.loot.predicates.AlternativeLootItemCondition;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
import net.minecraft.world.level.storage.loot.predicates.InvertedLootItemCondition;
import net.minecraft.world.level.storage.loot.predicates.MatchTool;
import net.minecraftforge.common.Tags;
import net.minecraftforge.common.ToolAction;
import net.minecraftforge.common.ToolActions;
import net.minecraftforge.common.loot.CanToolPerformAction;
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
import java.util.List;
@@ -50,7 +51,7 @@ import net.minecraft.world.level.storage.loot.entries.LootPoolEntryContainer;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSet;
/**
* Currently used only for replacing shears item to shears tag
* Currently used only for replacing shears item to shears_dig tool action
*/
public final class ForgeLootTableProvider extends LootTableProvider {
@@ -73,13 +74,13 @@ public final class ForgeLootTableProvider extends LootTableProvider {
private Consumer<BiConsumer<ResourceLocation, LootTable.Builder>> replaceAndFilterChangesOnly(Consumer<BiConsumer<ResourceLocation, LootTable.Builder>> consumer) {
return (newConsumer) -> consumer.accept((resourceLocation, builder) -> {
if (findAndReplaceInLootTableBuilder(builder, Items.SHEARS, Tags.Items.SHEARS)) {
if (findAndReplaceInLootTableBuilder(builder, Items.SHEARS, ToolActions.SHEARS_DIG)) {
newConsumer.accept(resourceLocation, builder);
}
});
}
private boolean findAndReplaceInLootTableBuilder(LootTable.Builder builder, Item from, Tag.Named<Item> to) {
private boolean findAndReplaceInLootTableBuilder(LootTable.Builder builder, Item from, ToolAction toolAction) {
List<LootPool> lootPools = ObfuscationReflectionHelper.getPrivateValue(LootTable.Builder.class, builder, "f_7915" + "6_");
boolean found = false;
@@ -88,7 +89,7 @@ public final class ForgeLootTableProvider extends LootTableProvider {
}
for (LootPool lootPool : lootPools) {
if (findAndReplaceInLootPool(lootPool, from, to)) {
if (findAndReplaceInLootPool(lootPool, from, toolAction)) {
found = true;
}
}
@@ -96,7 +97,7 @@ public final class ForgeLootTableProvider extends LootTableProvider {
return found;
}
private boolean findAndReplaceInLootPool(LootPool lootPool, Item from, Tag.Named<Item> to) {
private boolean findAndReplaceInLootPool(LootPool lootPool, Item from, ToolAction toolAction) {
List<LootPoolEntryContainer> lootEntries = ObfuscationReflectionHelper.getPrivateValue(LootPool.class, lootPool, "f_7902" +"3_");
List<LootItemCondition> lootConditions = ObfuscationReflectionHelper.getPrivateValue(LootPool.class, lootPool, "f_7902" + "4_");
boolean found = false;
@@ -107,7 +108,7 @@ public final class ForgeLootTableProvider extends LootTableProvider {
for (LootPoolEntryContainer lootEntry : lootEntries) {
if (lootEntry instanceof CompositeEntryBase) {
if (findAndReplaceInParentedLootEntry((CompositeEntryBase) lootEntry, from, to)) {
if (findAndReplaceInParentedLootEntry((CompositeEntryBase) lootEntry, from, toolAction)) {
found = true;
}
}
@@ -120,15 +121,15 @@ public final class ForgeLootTableProvider extends LootTableProvider {
for (int i = 0; i < lootConditions.size(); i++) {
LootItemCondition lootCondition = lootConditions.get(i);
if (lootCondition instanceof MatchTool && checkMatchTool((MatchTool) lootCondition, from)) {
lootConditions.set(i, MatchTool.toolMatches(ItemPredicate.Builder.item().of(to)).build());
lootConditions.set(i, CanToolPerformAction.canToolPerformAction(toolAction).build());
found = true;
} else if (lootCondition instanceof InvertedLootItemCondition) {
LootItemCondition invLootCondition = ObfuscationReflectionHelper.getPrivateValue(InvertedLootItemCondition.class, (InvertedLootItemCondition) lootCondition, "f_8168" + "1_");
if (invLootCondition instanceof MatchTool && checkMatchTool((MatchTool) invLootCondition, from)) {
lootConditions.set(i, InvertedLootItemCondition.invert(MatchTool.toolMatches(ItemPredicate.Builder.item().of(to))).build());
lootConditions.set(i, InvertedLootItemCondition.invert(CanToolPerformAction.canToolPerformAction(toolAction)).build());
found = true;
} else if (invLootCondition instanceof AlternativeLootItemCondition && findAndReplaceInAlternative((AlternativeLootItemCondition) invLootCondition, from, to)) {
} else if (invLootCondition instanceof AlternativeLootItemCondition && findAndReplaceInAlternative((AlternativeLootItemCondition) invLootCondition, from, toolAction)) {
found = true;
}
}
@@ -137,7 +138,7 @@ public final class ForgeLootTableProvider extends LootTableProvider {
return found;
}
private boolean findAndReplaceInParentedLootEntry(CompositeEntryBase entry, Item from, Tag.Named<Item> to) {
private boolean findAndReplaceInParentedLootEntry(CompositeEntryBase entry, Item from, ToolAction toolAction) {
LootPoolEntryContainer[] lootEntries = ObfuscationReflectionHelper.getPrivateValue(CompositeEntryBase.class, entry, "f_7942" + "8_");
boolean found = false;
@@ -146,7 +147,7 @@ public final class ForgeLootTableProvider extends LootTableProvider {
}
for (LootPoolEntryContainer lootEntry : lootEntries) {
if (findAndReplaceInLootEntry(lootEntry, from, to)) {
if (findAndReplaceInLootEntry(lootEntry, from, toolAction)) {
found = true;
}
}
@@ -154,7 +155,7 @@ public final class ForgeLootTableProvider extends LootTableProvider {
return found;
}
private boolean findAndReplaceInLootEntry(LootPoolEntryContainer entry, Item from, Tag.Named<Item> to) {
private boolean findAndReplaceInLootEntry(LootPoolEntryContainer entry, Item from, ToolAction toolAction) {
LootItemCondition[] lootConditions = ObfuscationReflectionHelper.getPrivateValue(LootPoolEntryContainer.class, entry, "f_7963" + "6_");
boolean found = false;
@@ -163,10 +164,10 @@ public final class ForgeLootTableProvider extends LootTableProvider {
}
for (int i = 0; i < lootConditions.length; i++) {
if (lootConditions[i] instanceof AlternativeLootItemCondition && findAndReplaceInAlternative((AlternativeLootItemCondition) lootConditions[i], from, to)) {
if (lootConditions[i] instanceof AlternativeLootItemCondition && findAndReplaceInAlternative((AlternativeLootItemCondition) lootConditions[i], from, toolAction)) {
found = true;
} else if (lootConditions[i] instanceof MatchTool && checkMatchTool((MatchTool) lootConditions[i], from)) {
lootConditions[i] = MatchTool.toolMatches(ItemPredicate.Builder.item().of(to)).build();
lootConditions[i] = CanToolPerformAction.canToolPerformAction(toolAction).build();
found = true;
}
}
@@ -174,7 +175,7 @@ public final class ForgeLootTableProvider extends LootTableProvider {
return found;
}
private boolean findAndReplaceInAlternative(AlternativeLootItemCondition alternative, Item from, Tag.Named<Item> to) {
private boolean findAndReplaceInAlternative(AlternativeLootItemCondition alternative, Item from, ToolAction toolAction) {
LootItemCondition[] lootConditions = ObfuscationReflectionHelper.getPrivateValue(AlternativeLootItemCondition.class, alternative, "f_8146" + "8_");
boolean found = false;
@@ -184,7 +185,7 @@ public final class ForgeLootTableProvider extends LootTableProvider {
for (int i = 0; i < lootConditions.length; i++) {
if (lootConditions[i] instanceof MatchTool && checkMatchTool((MatchTool) lootConditions[i], from)) {
lootConditions[i] = MatchTool.toolMatches(ItemPredicate.Builder.item().of(to)).build();
lootConditions[i] = CanToolPerformAction.canToolPerformAction(toolAction).build();
found = true;
}
}
@@ -0,0 +1,61 @@
package net.minecraftforge.common.loot;
import com.google.common.collect.ImmutableSet;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParam;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType;
import net.minecraftforge.common.ToolAction;
import javax.annotation.Nonnull;
import java.util.Set;
/**
* This LootItemCondition "forge:can_tool_perform_action" can be used to check if a tool can perform a given ToolAction.
*/
public class CanToolPerformAction implements LootItemCondition {
public static final LootItemConditionType LOOT_CONDITION_TYPE = new LootItemConditionType(new CanToolPerformAction.Serializer());
final ToolAction action;
public CanToolPerformAction(ToolAction action) {
this.action = action;
}
@Nonnull
public LootItemConditionType getType() {
return LOOT_CONDITION_TYPE;
}
@Nonnull
public Set<LootContextParam<?>> getReferencedContextParams() {
return ImmutableSet.of(LootContextParams.TOOL);
}
public boolean test(LootContext lootContext) {
ItemStack itemstack = lootContext.getParamOrNull(LootContextParams.TOOL);
return itemstack != null && itemstack.canPerformAction(this.action);
}
public static LootItemCondition.Builder canToolPerformAction(ToolAction action) {
return () -> new CanToolPerformAction(action);
}
public static class Serializer implements net.minecraft.world.level.storage.loot.Serializer<CanToolPerformAction> {
public void serialize(JsonObject json, CanToolPerformAction itemCondition, @Nonnull JsonSerializationContext context) {
json.addProperty("action", itemCondition.action.name());
}
@Nonnull
public CanToolPerformAction deserialize(JsonObject json, @Nonnull JsonDeserializationContext context) {
return new CanToolPerformAction(ToolAction.get(json.get("action").getAsString()));
}
}
}