Skip to content

Commit

Permalink
Partial implementation for BlockToolModificationEvent
Browse files Browse the repository at this point in the history
  • Loading branch information
AlphaMode committed Jul 26, 2024
1 parent 2f5e0e3 commit 5e32232
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 3 deletions.
1 change: 1 addition & 0 deletions modules/base/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
portingLib.addModuleDependencies([
"lazy_registration",
"tool_actions",
"extensions",
"gui_utils",
"transfer",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import io.github.fabricators_of_create.porting_lib.block.CustomExpBlock;
import io.github.fabricators_of_create.porting_lib.core.event.BaseEvent;
import io.github.fabricators_of_create.porting_lib.tool.ToolAction;
import io.github.fabricators_of_create.porting_lib.tool.ToolActions;
import io.github.fabricators_of_create.porting_lib.util.PortingHooks;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
Expand All @@ -10,6 +12,7 @@
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
Expand All @@ -18,6 +21,7 @@
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.state.BlockState;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.EnumSet;
Expand All @@ -28,11 +32,17 @@ public abstract class BlockEvents extends BaseEvent {
for (BlockBreak e : callbacks)
e.onBlockBreak(event);
});

public static final Event<NotifyNeighbors> NEIGHBORS_NOTIFY = EventFactory.createArrayBacked(NotifyNeighbors.class, callbacks -> event -> {
for (NotifyNeighbors e : callbacks)
e.onNotifyNeighbors(event);
});

public static final Event<BlockModification> BLOCK_MODIFICATION = EventFactory.createArrayBacked(BlockModification.class, callbacks -> event -> {
for (BlockModification e : callbacks)
e.onBlockModification(event);
});

@FunctionalInterface
public interface BlockBreak {
void onBlockBreak(BreakEvent event);
Expand All @@ -43,6 +53,11 @@ public interface NotifyNeighbors {
void onNotifyNeighbors(NeighborNotifyEvent event);
}

@FunctionalInterface
public interface BlockModification {
void onBlockModification(BlockToolModificationEvent event);
}

/**
* Invoked before a block is placed from the head of {@link BlockItem#useOn(UseOnContext)}. Called on both client and server.
* Return null to fall back to further processing. Any non-null value will result in placement being cancelled.
Expand Down Expand Up @@ -203,4 +218,100 @@ public void sendEvent() {
NEIGHBORS_NOTIFY.invoker().onNotifyNeighbors(this);
}
}

/**
* Note for this event isn't fully implemented on 1.20.1
* Fired when a block is right-clicked by a tool to change its state.
* For example: Used to determine if {@link ToolActions#AXE_STRIP an axe can strip},
* {@link ToolActions#SHOVEL_FLATTEN a shovel can path}, or {@link ToolActions#HOE_TILL a hoe can till}.
* <p>
* Care must be taken to ensure level-modifying events are only performed if {@link #isSimulated()} returns {@code false}.
* <p>
* This event is cancelable. If canceled, this will prevent the tool
* from changing the block's state.
*/
public static class BlockToolModificationEvent extends BlockEvents {
private final UseOnContext context;
private final ToolAction toolAction;
private final boolean simulate;
private BlockState state;

public BlockToolModificationEvent(BlockState originalState, @NotNull UseOnContext context, ToolAction toolAction, boolean simulate) {
super(context.getLevel(), context.getClickedPos(), originalState);
this.context = context;
this.state = originalState;
this.toolAction = toolAction;
this.simulate = simulate;
}

/**
* @return the player using the tool.
* May be null based on what was provided by {@link #getContext() the use on context}.
*/
@Nullable
public Player getPlayer() {
return this.context.getPlayer();
}

/**
* @return the tool being used
*/
public ItemStack getHeldItemStack() {
return this.context.getItemInHand();
}

/**
* @return the action being performed
*/
public ToolAction getToolAction() {
return this.toolAction;
}

/**
* Returns {@code true} if this event should not perform any actions that modify the level.
* If {@code false}, then level-modifying actions can be performed.
*
* @return {@code true} if this event should not perform any actions that modify the level.
* If {@code false}, then level-modifying actions can be performed.
*/
public boolean isSimulated() {
return this.simulate;
}

/**
* Returns the nonnull use on context that this event was performed in.
*
* @return the nonnull use on context that this event was performed in
*/
@NotNull
public UseOnContext getContext() {
return context;
}

/**
* Sets the state to transform the block into after tool use.
*
* @param finalState the state to transform the block into after tool use
* @see #getFinalState()
*/
public void setFinalState(@Nullable BlockState finalState) {
this.state = finalState;
}

/**
* Returns the state to transform the block into after tool use.
* If {@link #setFinalState(BlockState)} is not called, this will return the original state.
* If {@link #isCanceled()} is {@code true}, this value will be ignored and the tool action will be canceled.
*
* @return the state to transform the block into after tool use
*/
public BlockState getFinalState() {
return state;
}

@Override
public void sendEvent() {
BLOCK_MODIFICATION.invoker().onBlockModification(this);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.github.fabricators_of_create.porting_lib.mixin.common;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;

import io.github.fabricators_of_create.porting_lib.tool.ToolActions;
import io.github.fabricators_of_create.porting_lib.util.PortingHooks;
import net.minecraft.world.item.AxeItem;

import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.block.state.BlockState;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

import java.util.Optional;

// This really should be in the tool actions modules fix this TODO: fix this on 1.21
@Mixin(AxeItem.class)
public class AxeItemMixin {
@WrapOperation(method = "useOn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/AxeItem;getStripped(Lnet/minecraft/world/level/block/state/BlockState;)Ljava/util/Optional;"))
private Optional<BlockState> onStripToolAction(AxeItem instance, BlockState blockState, Operation<Optional<BlockState>> original, UseOnContext context) {
BlockState eventState = PortingHooks.onToolUse(blockState, context, ToolActions.AXE_STRIP, false);
return eventState != blockState ? Optional.ofNullable(eventState) : original.call(instance, blockState);
}

@WrapOperation(method = "useOn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/WeatheringCopper;getPrevious(Lnet/minecraft/world/level/block/state/BlockState;)Ljava/util/Optional;"))
private Optional<BlockState> onScrapeToolAction(BlockState blockState, Operation<Optional<BlockState>> original, UseOnContext context) {
BlockState eventState = PortingHooks.onToolUse(blockState, context, ToolActions.AXE_SCRAPE, false);
return eventState != blockState ? Optional.ofNullable(eventState) : original.call(blockState);
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package io.github.fabricators_of_create.porting_lib.util;

import javax.annotation.Nullable;

import io.github.fabricators_of_create.porting_lib.entity.events.EntityEvents;

import io.github.fabricators_of_create.porting_lib.tool.ToolAction;
import net.fabricmc.api.EnvType;
import net.minecraft.server.TickTask;
import net.minecraft.world.entity.item.ItemEntity;

import net.minecraft.world.item.context.UseOnContext;

import org.jetbrains.annotations.NotNull;

import io.github.fabricators_of_create.porting_lib.event.common.BlockEvents;
Expand All @@ -34,6 +35,8 @@
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.pattern.BlockInWorld;

import org.jetbrains.annotations.Nullable;

@SuppressWarnings({"removal", "UnstableApiUsage"})
public class PortingHooks {
public static boolean isCorrectToolForDrops(@NotNull BlockState state, @NotNull Player player) {
Expand Down Expand Up @@ -92,7 +95,7 @@ public static int onBlockBreakEvent(Level world, GameType gameType, ServerPlayer
public static void init() {
EntityEvents.ON_JOIN_WORLD.register((entity, world, loadedFromDisk) -> {
if (entity.getClass().equals(ItemEntity.class)) {
ItemStack stack = ((ItemEntity)entity).getItem();
ItemStack stack = ((ItemEntity) entity).getItem();
Item item = stack.getItem();
if (item.hasCustomEntity(stack)) {
Entity newEntity = item.createEntity(world, entity, stack);
Expand Down Expand Up @@ -127,4 +130,10 @@ public static int onGrindstoneChange(@NotNull ItemStack top, @NotNull ItemStack
outputSlot.setItem(0, e.getOutput());
return e.getXp();
}

@Nullable
public static BlockState onToolUse(BlockState originalState, UseOnContext context, ToolAction toolAction, boolean simulate) {
BlockEvents.BlockToolModificationEvent event = new BlockEvents.BlockToolModificationEvent(originalState, context, toolAction, simulate);
return event.post() ? null : event.getFinalState();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"client.CreateWorldScreenMixin",
"common.AbstractMinecartMixin",
"common.AnvilMenuMixin",
"common.AxeItemMixin",
"common.BambooStalkBlockMixin",
"common.BaseRailBlockMixin",
"common.BeaconBlockEntityMixin",
Expand Down

0 comments on commit 5e32232

Please sign in to comment.