Skip to content

Commit

Permalink
Mingrate block breaking modifier methods to hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
KnightMiner committed Jun 12, 2023
1 parent c52d82c commit 0ab41df
Show file tree
Hide file tree
Showing 11 changed files with 198 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -529,20 +529,8 @@ public boolean canPerformAction(IToolStackView tool, int level, ToolAction toolA

/* Harvest hooks */

/**
* Called when break speed is being calculated to affect mining speed conditionally.
* <br>
* Alternatives:
* <ul>
* <li>{@link #addToolStats(ToolRebuildContext, int, ModifierStatsBuilder)}: Limited context, but effect shows in the tooltip.</li>
* </ul>
* @param tool Current tool instance
* @param level Modifier level
* @param event Event instance
* @param sideHit Side of the block that was hit
* @param isEffective If true, the tool is effective against this block type
* @param miningSpeedModifier Calculated modifier from potion effects such as haste and environment such as water, use for additive bonuses to ensure consistency with the mining speed stat
*/
/** @deprecated use {@link slimeknights.tconstruct.library.modifiers.hook.mining.BreakSpeedModifierHook} */
@Deprecated
public void onBreakSpeed(IToolStackView tool, int level, BreakSpeed event, Direction sideHit, boolean isEffective, float miningSpeedModifier) {}

/**
Expand Down Expand Up @@ -576,48 +564,19 @@ public int getLootingValue(IToolStackView tool, int level, LivingEntity holder,
return looting;
}

/**
* Removes the block from the world
* <br>
* Alternatives:
* <ul>
* <li>{@link #afterBlockBreak(IToolStackView, int, ToolHarvestContext)}: Called after the block is successfully removed.</li>
* </ul>
* @param tool Tool used
* @param level Modifier level
* @param context Harvest context
* @return True to override the default block removing logic and stop all later modifiers from running. False to override default without breaking the block. Null to let default logic run
*/
/** @deprecated use {@link slimeknights.tconstruct.library.modifiers.hook.mining.RemoveBlockModifierHook} */
@Nullable
@Deprecated
public Boolean removeBlock(IToolStackView tool, int level, ToolHarvestContext context) {
return null;
}

/**
* Called after a block is broken to apply special effects
* <br>
* Alternatives:
* <ul>
* <li>{@link #removeBlock(IToolStackView, int, ToolHarvestContext)}: Called before the block is set to air.</li>
* <li>{@link #finishBreakingBlocks(IToolStackView, int, ToolHarvestContext)}: Called after all blocks are broken instead of per block.</li>
* </ul>
* @param tool Tool used
* @param level Modifier level
* @param context Harvest context
*/
/** @deprecated use {@link slimeknights.tconstruct.library.modifiers.hook.mining.BlockBreakModifierHook} */
@Deprecated
public void afterBlockBreak(IToolStackView tool, int level, ToolHarvestContext context) {}

/**
* Called after all blocks are broken on the target block
* <br>
* Alternatives:
* <ul>
* <li>{@link #afterBlockBreak(IToolStackView, int, ToolHarvestContext)}: Called after each individual block is broken.</li>
* </ul>
* @param tool Tool used
* @param level Modifier level
* @param context Harvest context
*/
/** @deprecated use {@link slimeknights.tconstruct.library.modifiers.hook.mining.FinishHarvestModifierHook} */
@Deprecated
public void finishBreakingBlocks(IToolStackView tool, int level, ToolHarvestContext context) {}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
import slimeknights.tconstruct.library.modifiers.hook.interaction.BlockInteractionModifierHook;
import slimeknights.tconstruct.library.modifiers.hook.interaction.EntityInteractionModifierHook;
import slimeknights.tconstruct.library.modifiers.hook.interaction.GeneralInteractionModifierHook;
import slimeknights.tconstruct.library.modifiers.hook.mining.BlockBreakModifierHook;
import slimeknights.tconstruct.library.modifiers.hook.mining.BreakSpeedModifierHook;
import slimeknights.tconstruct.library.modifiers.hook.mining.FinishHarvestModifierHook;
import slimeknights.tconstruct.library.modifiers.hook.mining.RemoveBlockModifierHook;
import slimeknights.tconstruct.library.modifiers.hooks.IArmorInteractModifier;
import slimeknights.tconstruct.library.modifiers.hooks.IArmorLootModifier;
import slimeknights.tconstruct.library.modifiers.hooks.IArmorWalkModifier;
Expand Down Expand Up @@ -206,6 +210,25 @@ public void failedMeleeHit(IToolStackView tool, ModifierEntry modifier, ToolAtta
});


/* Harvest */

/** Hook for conditionally modifying the break speed of a block */
public static final ModifierHook<BreakSpeedModifierHook> BREAK_SPEED = register("break_speed", BreakSpeedModifierHook.class, BreakSpeedModifierHook.AllMerger::new, (tool, modifier, event, sideHit, isEffective, miningSpeedModifier)
-> modifier.getModifier().onBreakSpeed(tool, modifier.getLevel(), event, sideHit, isEffective, miningSpeedModifier));

/** Called when a block is broken by a tool to allow the modifier to take over the block removing logic */
public static final ModifierHook<RemoveBlockModifierHook> REMOVE_BLOCK = register("remove_block", RemoveBlockModifierHook.class, RemoveBlockModifierHook.FirstMerger::new, (tool, modifier, context)
-> modifier.getModifier().removeBlock(tool, modifier.getLevel(), context));

/** Called after a block is broken by a tool for every block in the AOE */
public static final ModifierHook<BlockBreakModifierHook> BLOCK_BREAK = register("block_break", BlockBreakModifierHook.class, BlockBreakModifierHook.AllMerger::new, (tool, modifier, context)
-> modifier.getModifier().afterBlockBreak(tool, modifier.getLevel(), context));

/** Called after all blocks in the AOE are broken */
public static final ModifierHook<FinishHarvestModifierHook> FINISH_HARVEST = register("finish_harvest", FinishHarvestModifierHook.class, FinishHarvestModifierHook.AllMerger::new, (tool, modifier, context)
-> modifier.getModifier().finishBreakingBlocks(tool, modifier.getLevel(), context));


/* Ranged */

/** Hook for firing arrows or other projectiles to modify the entity post firing */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
import java.util.function.BiConsumer;
import java.util.function.Function;

/** Modifier hook implementing bonus enchantments from a tool, applied directly before block break. Can implement separately for leggings and tools if desired via the different hooks */
/**
* Modifier hook implementing bonus enchantments from a tool, applied directly before block break. Can implement separately for leggings and tools if desired via the different hooks
* TODO 1.19: move into {@link slimeknights.tconstruct.library.modifiers.hook.mining}
*/
public interface HarvestEnchantmentsModifierHook {
HarvestEnchantmentsModifierHook EMPTY = (tool, modifier, context, consumer) -> {};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package slimeknights.tconstruct.library.modifiers.hook.mining;

import slimeknights.tconstruct.library.modifiers.ModifierEntry;
import slimeknights.tconstruct.library.tools.context.ToolHarvestContext;
import slimeknights.tconstruct.library.tools.nbt.IToolStackView;

import java.util.Collection;

/** Hook called after a block is broken by a modifier. Called for every block broken by an AOE tool. */
public interface BlockBreakModifierHook {
/**
* Called after a block is broken to apply special effects
* <br>
* Alternatives:
* <ul>
* <li>{@link RemoveBlockModifierHook}: Called before the block is set to air.</li>
* <li>{@link FinishHarvestModifierHook}: Called after all blocks are broken instead of per block.</li>
* </ul>
* @param tool Tool used
* @param modifier Modifier level
* @param context Harvest context
*/
void afterBlockBreak(IToolStackView tool, ModifierEntry modifier, ToolHarvestContext context);

/** Merger that runs all nested hooks */
record AllMerger(Collection<BlockBreakModifierHook> modules) implements BlockBreakModifierHook {
@Override
public void afterBlockBreak(IToolStackView tool, ModifierEntry modifier, ToolHarvestContext context) {
for (BlockBreakModifierHook module : modules) {
module.afterBlockBreak(tool, modifier, context);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package slimeknights.tconstruct.library.modifiers.hook.mining;

import net.minecraft.core.Direction;
import net.minecraftforge.event.entity.player.PlayerEvent.BreakSpeed;
import slimeknights.tconstruct.library.modifiers.ModifierEntry;
import slimeknights.tconstruct.library.tools.nbt.IToolStackView;

import java.util.Collection;

/** Hook used to increase mining speed of a block conditioned on the environment or the player */
public interface BreakSpeedModifierHook {
/**
* Called when break speed is being calculated to affect mining speed conditionally.
* <br>
* Alternatives:
* <ul>
* <li>{@link slimeknights.tconstruct.library.modifiers.hook.build.ToolStatsModifierHook}: Limited context, but effect shows in the tooltip automatically.</li>
* <li>{@link slimeknights.tconstruct.library.modifiers.hook.TooltipModifierHook}: Allows adding bonus effects to the tooltip.</li>
* </ul>
* @param tool Current tool instance
* @param modifier Modifier level
* @param event Event instance
* @param sideHit Side of the block that was hit
* @param isEffective If true, the tool is effective against this block type
* @param miningSpeedModifier Calculated modifier from potion effects such as haste and environment such as water, use for additive bonuses to ensure consistency with the mining speed stat
*/
void onBreakSpeed(IToolStackView tool, ModifierEntry modifier, BreakSpeed event, Direction sideHit, boolean isEffective, float miningSpeedModifier);

/** Merger that runs each hook in succession */
record AllMerger(Collection<BreakSpeedModifierHook> modules) implements BreakSpeedModifierHook {
@Override
public void onBreakSpeed(IToolStackView tool, ModifierEntry modifier, BreakSpeed event, Direction sideHit, boolean isEffective, float miningSpeedModifier) {
for (BreakSpeedModifierHook module : modules) {
module.onBreakSpeed(tool, modifier, event, sideHit, isEffective, miningSpeedModifier);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package slimeknights.tconstruct.library.modifiers.hook.mining;

import slimeknights.tconstruct.library.modifiers.ModifierEntry;
import slimeknights.tconstruct.library.tools.context.ToolHarvestContext;
import slimeknights.tconstruct.library.tools.nbt.IToolStackView;

import java.util.Collection;

/** Hook called after a tool completes breaking all blocks in its AOE */
public interface FinishHarvestModifierHook {
/**
* Called after all blocks are broken on the target block
* <br>
* Alternatives:
* <ul>
* <li>{@link BlockBreakModifierHook}: Called after each individual block is broken.</li>
* </ul>
* @param tool Tool used
* @param modifier Modifier level
* @param context Harvest context
*/
void finishHarvest(IToolStackView tool, ModifierEntry modifier, ToolHarvestContext context);

/** Merger that runs all submodules */
record AllMerger(Collection<FinishHarvestModifierHook> modules) implements FinishHarvestModifierHook {
@Override
public void finishHarvest(IToolStackView tool, ModifierEntry modifier, ToolHarvestContext context) {
for (FinishHarvestModifierHook module : modules) {
module.finishHarvest(tool, modifier, context);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package slimeknights.tconstruct.library.modifiers.hook.mining;

import slimeknights.tconstruct.library.modifiers.ModifierEntry;
import slimeknights.tconstruct.library.tools.context.ToolHarvestContext;
import slimeknights.tconstruct.library.tools.nbt.IToolStackView;

import javax.annotation.Nullable;
import java.util.Collection;

/** Hook called when a block is removed to allow the modifier to control the details of the block's removal. */
public interface RemoveBlockModifierHook {
/**
* Removes the block from the world
* <br>
* Alternatives:
* <ul>
* <li>{@link BlockBreakModifierHook}: Called after the block is successfully removed.</li>
* </ul>
* @param tool Tool used
* @param modifier Modifier level
* @param context Harvest context
* @return True to override the default block removing logic and stop all later modifiers from running. False to override default without breaking the block. Null to let default logic run
*/
@Nullable
Boolean removeBlock(IToolStackView tool, ModifierEntry modifier, ToolHarvestContext context);

/** Merger that returns when the first hook finishes the action */
record FirstMerger(Collection<RemoveBlockModifierHook> modules) implements RemoveBlockModifierHook {
@Nullable
@Override
public Boolean removeBlock(IToolStackView tool, ModifierEntry modifier, ToolHarvestContext context) {
for (RemoveBlockModifierHook module : modules) {
Boolean handled = module.removeBlock(tool, modifier, context);
if (handled != null) {
return handled;
}
}
return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
package slimeknights.tconstruct.library.modifiers.hook.mining;

import net.minecraft.MethodsReturnNonnullByDefault;

import javax.annotation.ParametersAreNonnullByDefault;
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import slimeknights.tconstruct.common.TinkerTags;
import slimeknights.tconstruct.common.network.TinkerNetwork;
import slimeknights.tconstruct.library.modifiers.ModifierEntry;
import slimeknights.tconstruct.library.modifiers.TinkerHooks;
import slimeknights.tconstruct.library.tools.context.ToolHarvestContext;
import slimeknights.tconstruct.library.tools.definition.aoe.IAreaOfEffectIterator;
import slimeknights.tconstruct.library.tools.nbt.IToolStackView;
Expand Down Expand Up @@ -91,7 +92,7 @@ private static boolean removeBlock(IToolStackView tool, ToolHarvestContext conte
Boolean removed = null;
if (!tool.isBroken()) {
for (ModifierEntry entry : tool.getModifierList()) {
removed = entry.getModifier().removeBlock(tool, entry.getLevel(), context);
removed = entry.getHook(TinkerHooks.REMOVE_BLOCK).removeBlock(tool, entry, context);
if (removed != null) {
break;
}
Expand Down Expand Up @@ -163,7 +164,7 @@ protected static boolean breakBlock(ToolStack tool, ItemStack stack, ToolHarvest
// broken means we are using "empty hand"
if (!tool.isBroken() && removed) {
for (ModifierEntry entry : tool.getModifierList()) {
entry.getModifier().afterBlockBreak(tool, entry.getLevel(), context);
entry.getHook(TinkerHooks.BLOCK_BREAK).afterBlockBreak(tool, entry, context);
}
ToolDamageUtil.damageAnimated(tool, damage, player);
}
Expand Down Expand Up @@ -261,7 +262,7 @@ public static boolean handleBlockBreak(ItemStack stack, BlockPos pos, Player pla
}
}
for (ModifierEntry entry : tool.getModifierList()) {
entry.getModifier().finishBreakingBlocks(tool, entry.getLevel(), context);
entry.getHook(TinkerHooks.FINISH_HARVEST).finishHarvest(tool, entry, context);
}
}

Expand All @@ -285,7 +286,7 @@ public static boolean mineBlock(ItemStack stack, Level worldIn, BlockState state
boolean isEffective = ToolHarvestLogic.isEffective(tool, state);
ToolHarvestContext context = new ToolHarvestContext((ServerLevel) worldIn, entityLiving, state, pos, Direction.UP, true, isEffective);
for (ModifierEntry entry : tool.getModifierList()) {
entry.getModifier().afterBlockBreak(tool, entry.getLevel(), context);
entry.getHook(TinkerHooks.BLOCK_BREAK).afterBlockBreak(tool, entry, context);
}
ToolDamageUtil.damageAnimated(tool, ToolHarvestLogic.getDamage(tool, worldIn, pos, state), entityLiving);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import slimeknights.tconstruct.TConstruct;
import slimeknights.tconstruct.library.events.ToolEquipmentChangeEvent;
import slimeknights.tconstruct.library.modifiers.ModifierEntry;
import slimeknights.tconstruct.library.modifiers.TinkerHooks;
import slimeknights.tconstruct.library.tools.context.EquipmentChangeContext;
import slimeknights.tconstruct.library.tools.helper.ModifierUtil;
import slimeknights.tconstruct.library.tools.nbt.IToolStackView;
Expand Down Expand Up @@ -97,7 +98,7 @@ private static void runModifierHooks(LivingEntity entity, EquipmentSlot changedS
IToolStackView tool = context.getOriginalTool();
if (tool != null) {
for (ModifierEntry entry : tool.getModifierList()) {
entry.getModifier().onUnequip(tool, entry.getLevel(), context);
entry.getHook(TinkerHooks.EQUIPMENT_CHANGE).onUnequip(tool, entry, context);
}
// only path that should bring you here that did not already call the modifier method is when your shield breaks. ideally we will switch to a forge onStoppedUsing method instead
// TODO 1.19: consider simplier check, such as the tool having the active modifier tag set. Will need to do a bit of work for bows which don't set modifiers though
Expand All @@ -110,7 +111,7 @@ private static void runModifierHooks(LivingEntity entity, EquipmentSlot changedS
tool = context.getReplacementTool();
if (tool != null) {
for (ModifierEntry entry : tool.getModifierList()) {
entry.getModifier().onEquip(tool, entry.getLevel(), context);
entry.getHook(TinkerHooks.EQUIPMENT_CHANGE).onEquip(tool, entry, context);
}
}

Expand All @@ -120,7 +121,7 @@ private static void runModifierHooks(LivingEntity entity, EquipmentSlot changedS
tool = context.getToolInSlot(otherSlot);
if (tool != null) {
for (ModifierEntry entry : tool.getModifierList()) {
entry.getModifier().onEquipmentChange(tool, entry.getLevel(), context, otherSlot);
entry.getHook(TinkerHooks.EQUIPMENT_CHANGE).onEquipmentChange(tool, entry, context, otherSlot);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ static void onBreakSpeed(PlayerEvent.BreakSpeed event) {
boolean isEffective = stack.isCorrectToolForDrops(event.getState());
Direction direction = BlockSideHitListener.getSideHit(player);
for (ModifierEntry entry : tool.getModifierList()) {
entry.getModifier().onBreakSpeed(tool, entry.getLevel(), event, direction, isEffective, miningSpeedModifier);
entry.getHook(TinkerHooks.BREAK_SPEED).onBreakSpeed(tool, entry, event, direction, isEffective, miningSpeedModifier);
// if any modifier cancels mining, stop right here
if (event.isCanceled()) {
return;
Expand Down

0 comments on commit 0ab41df

Please sign in to comment.