Reworked using opencode
build / build (push) Successful in 1m10s

This commit is contained in:
2026-07-19 10:16:39 +02:00
parent 7e3dff14db
commit 3e0613f297
10 changed files with 630 additions and 363 deletions
@@ -1,15 +1,8 @@
package com.dynamitos.mixin.client;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.Minecraft;
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.CallbackInfo;
@Mixin(MinecraftClient.class)
@Mixin(Minecraft.class)
public class ExampleClientMixin {
@Inject(at = @At("HEAD"), method = "run")
private void init(CallbackInfo info) {
// This code is injected into the start of MinecraftClient.run()V
}
}
}
@@ -0,0 +1,71 @@
package com.dynamitos;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Items;
public class CopperFarmingRegistry {
private static final List<CropType> CROP_TYPES = new ArrayList<>();
public record CropType(ItemStack seedStack, Predicate<BlockState> predicate) {
public String name() {
return BuiltInRegistries.ITEM.getKey(seedStack.getItem()).toString();
}
}
public static void registerCrop(CropType cropType) {
CROP_TYPES.add(cropType);
Copperfarmers.LOGGER.info("Registered crop type: " + cropType.name());
}
public static List<CropType> getCropTypes() {
return List.copyOf(CROP_TYPES);
}
public static Predicate<BlockState> getFarmlandPredicate() {
return state -> state.is(Blocks.FARMLAND);
}
public static Predicate<BlockState> getDestinationPredicate() {
return state -> state.is(Blocks.FARMLAND);
}
public static Predicate<BlockState> getSourcePredicate() {
return state -> state.is(Blocks.FARMLAND);
}
public static boolean isCropsReadyToHarvest(BlockState state) {
if (!state.is(Blocks.FARMLAND)) {
return false;
}
return true;
}
static {
CropType wheatCrop = new CropType(new ItemStack(Items.WHEAT_SEEDS), s -> true);
CropType potatoCrop = new CropType(new ItemStack(Items.POTATO), s -> true);
CropType carrotCrop = new CropType(new ItemStack(Items.CARROT), s -> true);
registerCrop(wheatCrop);
registerCrop(potatoCrop);
registerCrop(carrotCrop);
}
public static boolean isRegisteredCrop(Item item) {
return CROP_TYPES.stream().anyMatch(c -> c.seedStack.getItem() == item);
}
public static List<ItemStack> getCropSeedStacks() {
return CROP_TYPES.stream()
.map(c -> c.seedStack.copy())
.toList();
}
}
@@ -0,0 +1,59 @@
package com.dynamitos.mixin;
import java.util.function.BiConsumer;
import org.spongepowered.asm.mixin.Mixin;
import com.dynamitos.Copperfarmers;
import com.dynamitos.CopperFarmingRegistry;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.Container;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.animal.golem.CopperGolem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
@Mixin(targets = "net/minecraft/world/entity/animal/golem/CopperGolemAi")
public abstract class CopperGolemBehaviorHookMixin {
public static void copperfarmers$handleFarmlandPlanting(
CopperGolem golem, ServerLevel world, BlockPos pos, BlockState state) {
BlockPos plantedAt = pos.above();
if (state.is(Blocks.FARMLAND) && canPlantHere(world, plantedAt)) {
ItemStack antennaStack = golem.getItemBySlot(CopperGolem.EQUIPMENT_SLOT_ANTENNA);
if (!antennaStack.isEmpty() && antennaStack.is(Items.WHEAT_SEEDS)) {
world.setBlock(pos, Blocks.FARMLAND.defaultBlockState(), 3);
antennaStack.shrink(1);
Copperfarmers.LOGGER.debug("Planted wheat at " + pos.above());
}
}
}
public static void copperfarmers$handleFarmlandHarvesting(
CopperGolem golem, ServerLevel world, BlockPos pos, BlockState state) {
BlockPos plantedAt = pos.above();
BlockState above = world.getBlockState(plantedAt);
if (above.is(Blocks.CARROTS)) {
world.destroyBlock(plantedAt, true);
ItemStack harvested = new ItemStack(Items.CARROT);
ItemStack antennaSlot = golem.getItemBySlot(CopperGolem.EQUIPMENT_SLOT_ANTENNA);
if (antennaSlot.isEmpty()) {
golem.setItemSlot(CopperGolem.EQUIPMENT_SLOT_ANTENNA, harvested.copy());
} else if (antennaSlot.is(harvested.getItem())) {
antennaSlot.grow(harvested.getCount());
}
Copperfarmers.LOGGER.debug("Harvested crops at " + pos);
}
}
public static boolean canPlantHere(ServerLevel world, BlockPos plantedAt) {
BlockState above = world.getBlockState(plantedAt);
return above.isAir() || true;
}
}
@@ -1,65 +0,0 @@
package com.dynamitos.mixin;
import java.util.function.Predicate;
import org.jetbrains.annotations.Nullable;
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 com.dynamitos.Copperfarmers;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.ChestBlockEntity;
import net.minecraft.entity.ai.brain.task.MoveItemsTask;
import net.minecraft.entity.passive.CopperGolemBrain;
import net.minecraft.entity.passive.CopperGolemEntity;
import net.minecraft.entity.passive.CopperGolemState;
import net.minecraft.inventory.Inventory;
import net.minecraft.sound.SoundEvent;
@Mixin(CopperGolemBrain.class)
public abstract class CopperGolemBrainMixin {
@Inject(method = "createInteractionCallback", at = @At("HEAD"), cancellable = true)
private static void createInteractionCallback(CopperGolemState state, @Nullable SoundEvent soundEvent,
CallbackInfoReturnable<MoveItemsTask.InteractionCallback> callbackInfo) {
callbackInfo.setReturnValue((pathAwareEntity, storage, interactionTicks) -> {
if (pathAwareEntity instanceof CopperGolemEntity copperGolemEntity) {
Inventory inventory = storage.inventory();
if (interactionTicks == 1) {
if (!storage.state().isOf(Blocks.FARMLAND)) {
inventory.onOpen(copperGolemEntity);
}
copperGolemEntity.setTargetContainerPos(storage.pos());
copperGolemEntity.setState(state);
}
if (interactionTicks == 9 && soundEvent != null) {
copperGolemEntity.playSoundIfNotSilent(soundEvent);
}
if (interactionTicks == 60) {
if (!storage.state().isOf(Blocks.FARMLAND)) {
if (inventory.getViewingUsers().contains(pathAwareEntity)) {
inventory.onClose(copperGolemEntity);
}
}
copperGolemEntity.resetTargetContainerPos();
}
}
});
}
@Inject(method = "createStoragePredicate", at = @At("HEAD"), cancellable = true)
private static void createStoragePredicate(CallbackInfoReturnable<Predicate<MoveItemsTask.Storage>> callbackInfo) {
callbackInfo.setReturnValue(storage -> {
if (storage.state().isOf(Blocks.FARMLAND)) {
Copperfarmers.LOGGER.debug("Storage predicate returning false for farmland at " + storage.pos());
return false;
}
return storage.blockEntity() instanceof ChestBlockEntity chestBlockEntity ? !chestBlockEntity.getViewingUsers().isEmpty() : false;
});
}
}
@@ -0,0 +1,32 @@
package com.dynamitos.mixin;
import java.util.function.Predicate;
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 com.dynamitos.CopperFarmingRegistry;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
@Mixin(targets = "net/minecraft/world/entity/animal/golem/CopperGolemActivitySourcePredicate")
public abstract class FarmlandPredicateMixin {
@Inject(method = "createStorageSourcePred", at = @At("HEAD"), cancellable = true)
private static void copperfarmers$modifyStorageSourcePred(
CallbackInfoReturnable<Predicate<BlockState>> callbackInfo) {
Predicate<BlockState> original = callbackInfo.getReturnValue();
Predicate<BlockState> farmlandAware = state ->
state.is(Blocks.FARMLAND) || (original != null && original.test(state));
callbackInfo.setReturnValue(farmlandAware);
}
public static Predicate<BlockState> copperfarmers$createFarmlandPredicate() {
return state ->
state.is(Blocks.FARMLAND) ||
CopperFarmingRegistry.getDestinationPredicate().test(state);
}
}
@@ -1,78 +0,0 @@
package com.dynamitos.mixin;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
import net.minecraft.block.BlockState;
import net.minecraft.entity.ai.brain.task.MoveItemsTask;
import net.minecraft.entity.mob.PathAwareEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
@Mixin(MoveItemsTask.class)
public interface MoveItemsTaskAccessor {
@Accessor("interactionState")
void copperfarmers$setInteractionState(MoveItemsTask.InteractionState state);
@Accessor("interactionTicks")
int copperfarmers$getInteractionTicks();
@Accessor("interactionTicks")
void copperfarmers$setInteractionTicks(int ticks);
@Invoker("getSearchBoundingBox")
Box copperfarmers$getSearchBoundingBox(PathAwareEntity entity);
@Invoker("atCenterY")
Vec3d copperfarmers$atCenterY(PathAwareEntity entity);
@Invoker("isWithinRange")
boolean copperfarmers$isWithinRange(double range, MoveItemsTask.Storage storage, World world, PathAwareEntity entity, Vec3d pos);
@Invoker("transitionToTravelling")
void copperfarmers$transitionToTravelling(PathAwareEntity entity);
@Invoker("setLookTarget")
void copperfarmers$setLookTarget(MoveItemsTask.Storage storage, PathAwareEntity entity);
@Invoker("extractStack")
static ItemStack copperfarmers$extractStack(Inventory inventory) {
return null;
}
@Invoker("resetVisitedPositions")
void copperfarmers$resetVisitedPositions(PathAwareEntity entity);
@Invoker("insertStack")
static ItemStack copperfarmers$insertStack(PathAwareEntity entity, Inventory inventory) {
return null;
}
@Invoker("invalidateTargetStorage")
void copperfarmers$invalidateTargetStorage(PathAwareEntity entity);
@Invoker("canPickUpItem")
static boolean copperfarmers$canPickUpItem(PathAwareEntity entity) {
return false;
}
@Invoker("hasItem")
static boolean copperfarmers$hasItem(Inventory inventory) {
return false;
}
@Invoker("canInsert")
static boolean copperfarmers$canInsert(PathAwareEntity entity, Inventory inventory) {
return false;
}
@Invoker("setNavigationState")
void copperfarmers$setNavigationState(MoveItemsTask.NavigationState state);
}
@@ -1,206 +0,0 @@
package com.dynamitos.mixin;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Predicate;
import org.spongepowered.asm.mixin.Debug;
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.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.dynamitos.Copperfarmers;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.ai.brain.MemoryModuleState;
import net.minecraft.entity.ai.brain.MemoryModuleType;
import net.minecraft.entity.ai.brain.task.MoveItemsTask;
import net.minecraft.entity.ai.brain.task.MultiTickTask;
import net.minecraft.entity.mob.PathAwareEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.world.World;
@Mixin(MoveItemsTask.class)
public abstract class MoveItemsTaskMixin extends MultiTickTask<PathAwareEntity> {
private MoveItemsTaskAccessor thisAccessor = (MoveItemsTaskAccessor) this;
public MoveItemsTaskMixin(Map<MemoryModuleType<?>, MemoryModuleState> requiredMemoryState) {
super(requiredMemoryState);
// TODO Auto-generated constructor stub
}
@Inject(method = "findStorage", at = @At("HEAD"), cancellable = true)
private void findStorage(ServerWorld world, PathAwareEntity entity,
CallbackInfoReturnable<Optional<MoveItemsTask.Storage>> callbackInfo) {
Copperfarmers.LOGGER.debug("Wrapped findStorage called");
Box box = ((MoveItemsTaskAccessor) this).copperfarmers$getSearchBoundingBox(entity);
if (!entity.getEquippedStack(EquipmentSlot.MAINHAND).isOf(Items.WHEAT_SEEDS)) {
return;
}
for (int z = (int) box.minZ; z <= box.maxZ; z++) {
for (int y = (int) box.minY; y <= box.maxY; y++) {
for (int x = (int) box.minX; x <= box.maxX; x++) {
var pos = new BlockPos(x, y, z);
var blockState = world.getBlockState(pos);
// if block is farmland
if (blockState.isOf(Blocks.FARMLAND) && world.isAir(pos.up())) {
Copperfarmers.LOGGER.debug("Found farmland at " + pos);
if (Math.random() < 0.5) {
callbackInfo
.setReturnValue(
Optional.of(new MoveItemsTask.Storage(pos, null, null, blockState)));
return;
}
}
}
}
}
}
@Inject(method = "testContainer", at = @At("HEAD"), cancellable = true)
private void testContainer(PathAwareEntity entity, BlockState state, CallbackInfoReturnable<Boolean> callbackInfo) {
Copperfarmers.LOGGER.debug("Wrapped testContainer called");
if (!MoveItemsTaskAccessor.copperfarmers$canPickUpItem(entity) && state.isOf(Blocks.FARMLAND)) {
Copperfarmers.LOGGER.debug("testContainer returning true for farmland");
callbackInfo.setReturnValue(true);
}
}
@Inject(method = "tickInteracting", at = @At("HEAD"), cancellable = true)
private void tickInteracting(MoveItemsTask.Storage storage, World world, PathAwareEntity entity,
CallbackInfo callbackInfo) {
Copperfarmers.LOGGER.debug("Wrapped tickInteracting called");
if (!thisAccessor.copperfarmers$isWithinRange(2.0, storage, world, entity,
thisAccessor.copperfarmers$atCenterY(entity))) {
thisAccessor.copperfarmers$transitionToTravelling(entity);
} else {
thisAccessor.copperfarmers$setInteractionTicks(thisAccessor.copperfarmers$getInteractionTicks() + 1);
thisAccessor.copperfarmers$setLookTarget(storage, entity);
Copperfarmers.LOGGER.debug("Interaction ticks: " + thisAccessor.copperfarmers$getInteractionTicks());
if (thisAccessor.copperfarmers$getInteractionTicks() >= 60) {
Copperfarmers.LOGGER.debug("Interacting with storage at " + storage.pos());
this.selectInteractionState2(
entity,
storage,
this::takeStack2,
(entityxx, inventory) -> thisAccessor.copperfarmers$invalidateTargetStorage(entity),
this::placeStack2,
(entityxx, inventory) -> thisAccessor.copperfarmers$invalidateTargetStorage(entity));
thisAccessor.copperfarmers$transitionToTravelling(entity);
}
}
callbackInfo.cancel();
}
@Inject(method = "transitionToInteracting", at = @At("HEAD"), cancellable = true)
private void transitionToInteracting(MoveItemsTask.Storage storage, PathAwareEntity entity,
CallbackInfo callbackInfo) {
Copperfarmers.LOGGER.debug("Wrapped transitionToInteracting called");
this.selectInteractionState2(
entity,
storage,
this.createSetInteractionStateCallback2(MoveItemsTask.InteractionState.PICKUP_ITEM),
this.createSetInteractionStateCallback2(MoveItemsTask.InteractionState.PICKUP_NO_ITEM),
this.createSetInteractionStateCallback2(MoveItemsTask.InteractionState.PLACE_ITEM),
this.createSetInteractionStateCallback2(MoveItemsTask.InteractionState.PLACE_NO_ITEM));
thisAccessor.copperfarmers$setNavigationState(MoveItemsTask.NavigationState.INTERACTING);
callbackInfo.cancel();
}
@Inject(method = "isUnchanged", at = @At("HEAD"), cancellable = true)
private void isUnchanged(World world, MoveItemsTask.Storage storage, CallbackInfoReturnable<Boolean> callbackInfo) {
Copperfarmers.LOGGER.debug("Wrapped isUnchanged called");
if (storage.state().isOf(Blocks.FARMLAND) && world.isAir(storage.pos().up())) {
Copperfarmers.LOGGER.debug("isUnchanged returning true for farmland at " + storage.pos());
callbackInfo.setReturnValue(true);
return;
}
Copperfarmers.LOGGER.debug("Storage state: " + storage.state() + " isAir: " + world.isAir(storage.pos().up()));
if (storage.blockEntity() == null) {
Copperfarmers.LOGGER.debug("No blockentity " + storage.pos());
callbackInfo.setReturnValue(false);
return;
}
}
private void placeStack2(PathAwareEntity entity, MoveItemsTask.Storage storage) {
Copperfarmers.LOGGER.debug("Wrapped placeStack called");
BlockPos pos = storage.pos();
ServerWorld world = (ServerWorld) entity.getEntityWorld();
if (world.getBlockState(pos).isOf(Blocks.FARMLAND) && world.isAir(pos.up())
&& entity.getEquippedStack(EquipmentSlot.MAINHAND).isOf(Items.WHEAT_SEEDS)) {
world.setBlockState(pos.up(), Blocks.WHEAT.getDefaultState());
entity.getEquippedStack(EquipmentSlot.MAINHAND).decrement(1);
if (entity.getEquippedStack(EquipmentSlot.MAINHAND).isEmpty()) {
thisAccessor.copperfarmers$resetVisitedPositions(entity);
} else {
thisAccessor.copperfarmers$invalidateTargetStorage(entity);
}
Copperfarmers.LOGGER.debug("Placed wheat seeds at " + pos.up());
return;
}
if (storage.inventory() == null) {
Copperfarmers.LOGGER.debug("No inventory to place items into at " + pos);
return;
}
ItemStack itemStack = MoveItemsTaskAccessor.copperfarmers$insertStack(entity, storage.inventory());
storage.inventory().markDirty();
entity.equipStack(EquipmentSlot.MAINHAND, itemStack);
if (itemStack.isEmpty()) {
thisAccessor.copperfarmers$resetVisitedPositions(entity);
} else {
thisAccessor.copperfarmers$invalidateTargetStorage(entity);
}
}
private void takeStack2(PathAwareEntity entity, MoveItemsTask.Storage storage) {
entity.equipStack(EquipmentSlot.MAINHAND,
MoveItemsTaskAccessor.copperfarmers$extractStack(storage.inventory()));
entity.setDropGuaranteed(EquipmentSlot.MAINHAND);
storage.inventory().markDirty();
thisAccessor.copperfarmers$resetVisitedPositions(entity);
}
private void selectInteractionState2(
PathAwareEntity entity,
MoveItemsTask.Storage storage,
BiConsumer<PathAwareEntity, MoveItemsTask.Storage> pickupItemCallback,
BiConsumer<PathAwareEntity, MoveItemsTask.Storage> pickupNoItemCallback,
BiConsumer<PathAwareEntity, MoveItemsTask.Storage> placeItemCallback,
BiConsumer<PathAwareEntity, MoveItemsTask.Storage> placeNoItemCallback) {
Copperfarmers.LOGGER.debug("Wrapped selectInteractionState called");
if (storage == null && entity.getEquippedStack(EquipmentSlot.MAINHAND).isOf(Items.WHEAT_SEEDS)) {
placeItemCallback.accept(entity, storage);
}
if (MoveItemsTaskAccessor.copperfarmers$canPickUpItem(entity)) {
if (MoveItemsTaskAccessor.copperfarmers$hasItem(storage.inventory())) {
pickupItemCallback.accept(entity, storage);
} else {
pickupNoItemCallback.accept(entity, storage);
}
} else if (storage.state().isOf(Blocks.FARMLAND)
|| MoveItemsTaskAccessor.copperfarmers$canInsert(entity, storage.inventory())) {
placeItemCallback.accept(entity, storage);
} else {
placeNoItemCallback.accept(entity, storage);
}
}
private BiConsumer<PathAwareEntity, MoveItemsTask.Storage> createSetInteractionStateCallback2(
MoveItemsTask.InteractionState state) {
return (entity, inventory) -> thisAccessor.copperfarmers$setInteractionState(state);
}
}
@@ -0,0 +1,105 @@
package com.dynamitos.mixin;
import java.util.Optional;
import java.util.Map;
import java.util.function.Predicate;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
import net.minecraft.world.Container;
import net.minecraft.world.entity.PathfinderMob;
import net.minecraft.world.entity.ai.behavior.TransportItemsBetweenContainers;
import net.minecraft.world.item.ItemStack;
import net.minecraft.core.BlockPos;
import net.minecraft.core.GlobalPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.phys.AABB;
@Mixin(TransportItemsBetweenContainers.class)
public interface TransportItemsBasedOnResearchAccessor {
/** Access instance field via private setter */
@Invoker("setInteractionState")
void copperfarmers$setInteractionState(TransportItemsBetweenContainers.ContainerInteractionState state);
@Invoker("setTransportingState")
void copperfarmers$setTransportingState(TransportItemsBetweenContainers.TransportItemState state);
/** Access the target search area via private method */
@Invoker("getTargetSearchArea")
AABB copperfarmers$getTargetSearchArea(PathfinderMob entity);
/** Access the center Y position via private method */
@Invoker("atCenterY")
net.minecraft.world.phys.Vec3 copperfarmers$atCenterY(PathfinderMob entity);
/** Check if target is within distance via private method */
@Invoker("isWithinTargetDistance")
boolean copperfarmers$isWithinTargetDistance(double distance,
TransportItemsBetweenContainers.TransportItemTarget target,
net.minecraft.world.level.Level world, PathfinderMob entity, net.minecraft.world.phys.Vec3 pos);
/** Execute travel to target callback (protected method) */
@Invoker("onTravelToTarget")
void copperfarmers$onTravelToTarget(TransportItemsBetweenContainers.TransportItemTarget target,
net.minecraft.world.level.Level world, PathfinderMob entity);
/** Get center position for walking via private method */
@Invoker("getCenterPos")
net.minecraft.world.phys.Vec3 copperfarmers$getCenterPos(PathfinderMob entity);
/** Pick up items from container (private method) */
@Invoker("pickUpItems")
void copperfarmers$pickUpItems(PathfinderMob entity, Container container);
/** Put down item into container (private method) */
@Invoker("putDownItem")
void copperfarmers$putDownItem(PathfinderMob entity, Container container);
/** Static helper invoker for extracting items from containers */
@Invoker("pickupItemFromContainer")
static ItemStack copperfarmers$extractStack(Container inventory) {
return ItemStack.EMPTY;
}
@Invoker("getVisitedPositions")
void copperfarmers$resetVisitedPositions(PathfinderMob entity);
/** Static helper invoker for inserting items */
@Invoker("addItemsToContainer")
static ItemStack copperfarmers$insertStack(PathfinderMob entity, Container container) {
return ItemStack.EMPTY;
}
@Invoker("invalidateTargetStorage")
void copperfarmers$invalidateTargetStorage(PathfinderMob entity);
/** Check if the entity can pick up items (static method) */
@Invoker("isPickingUpItems")
static boolean copperfarmers$canPickUpItem(PathfinderMob entity) {
return false;
}
@Invoker("hasItem")
static boolean copperfarmers$hasItem(Container inventory) {
return false;
}
/** Check if target matches the golem's hand item requirement */
@Invoker("matchesLeavingItemsRequirement")
static boolean copperfarmers$canInsert(PathfinderMob entity, Container container) {
return false;
}
@Invoker("hasItemMatchingHandItem")
static boolean copperfarmers$hasItemMatchingHandItem(PathfinderMob entity, Container container) {
return false;
}
/** Get the transport target via private getTransportTarget method */
@Invoker("getTransportTarget")
Optional<TransportItemsBetweenContainers.TransportItemTarget> copperfarmers$getTransportTarget(
ServerLevel world, PathfinderMob entity);
}
@@ -3,12 +3,12 @@
"package": "com.dynamitos.mixin",
"compatibilityLevel": "JAVA_25",
"mixins": [
"CopperGolemBrainMixin",
"MoveItemsTaskMixin",
"MoveItemsTaskAccessor"
"CopperGolemBehaviorHookMixin",
"FarmlandPredicateMixin",
"TransportItemsBasedOnResearchAccessor"
],
"injectors": {
"defaultRequire": 1
"defaultRequire": true
},
"overwrites": {
"requireAnnotations": true