Fix droppers deleting items when they fail to insert (#1646) (#1647)

This commit is contained in:
Technici4n 2021-08-20 13:01:43 +02:00 committed by GitHub
parent 3fe74aa162
commit a6db925daf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 3 deletions

View file

@ -22,9 +22,9 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import net.minecraft.block.DispenserBlock;
import net.minecraft.block.DropperBlock;
import net.minecraft.block.entity.DispenserBlockEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPointerImpl;
import net.minecraft.util.math.BlockPos;
@ -38,20 +38,26 @@ import net.fabricmc.fabric.api.transfer.v1.storage.StorageUtil;
/**
* Allows droppers to insert into ItemVariant storages.
*
* <p>Maintainer note: it's important that we inject BEFORE the getStack() call,
* as the returned stack can be mutated by the StorageUtil.move() call in the injected callback.
*/
@Mixin(DropperBlock.class)
public class DropperBlockMixin {
@Inject(
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/util/math/BlockPos;offset(Lnet/minecraft/util/math/Direction;)Lnet/minecraft/util/math/BlockPos;"
target = "Lnet/minecraft/block/entity/DispenserBlockEntity;getStack(I)Lnet/minecraft/item/ItemStack;"
),
method = "dispense",
locals = LocalCapture.CAPTURE_FAILHARD,
cancellable = true,
allow = 1
)
public void hookDispense(ServerWorld world, BlockPos pos, CallbackInfo ci, BlockPointerImpl blockPointerImpl, DispenserBlockEntity dispenser, int slot, ItemStack stack, Direction direction) {
public void hookDispense(ServerWorld world, BlockPos pos, CallbackInfo ci, BlockPointerImpl blockPointerImpl, DispenserBlockEntity dispenser, int slot) {
if (dispenser.getStack(slot).isEmpty()) return;
Direction direction = world.getBlockState(pos).get(DispenserBlock.FACING);
Storage<ItemVariant> target = ItemStorage.SIDED.find(world, pos.offset(direction), direction.getOpposite());
if (target != null) {

View file

@ -20,6 +20,7 @@ import static net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants.BUCKET;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.block.Material;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.fluid.Fluids;
@ -34,6 +35,7 @@ import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidStorage;
import net.fabricmc.fabric.api.transfer.v1.item.ItemStorage;
import net.fabricmc.fabric.api.transfer.v1.storage.base.SingleSlotStorage;
import net.fabricmc.fabric.api.transfer.v1.storage.base.SingleVariantStorage;
import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction;
@ -60,6 +62,9 @@ public class FluidTransferTest implements ModInitializer {
FluidStorage.SIDED.registerForBlocks((world, pos, state, be, direction) -> CreativeFluidStorage.WATER, INFINITE_WATER_SOURCE);
FluidStorage.SIDED.registerForBlocks((world, pos, state, be, direction) -> CreativeFluidStorage.LAVA, INFINITE_LAVA_SOURCE);
// Obsidian is now a trash can :-P
ItemStorage.SIDED.registerForBlocks((world, pos, state, be, direction) -> TrashingStorage.ITEM, Blocks.OBSIDIAN);
testFluidStorage();
testTransactionExceptions();
ItemTests.run();

View file

@ -0,0 +1,44 @@
/*
* 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.test.transfer.fluid;
import java.util.Collections;
import java.util.Iterator;
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant;
import net.fabricmc.fabric.api.transfer.v1.storage.StoragePreconditions;
import net.fabricmc.fabric.api.transfer.v1.storage.StorageView;
import net.fabricmc.fabric.api.transfer.v1.storage.TransferVariant;
import net.fabricmc.fabric.api.transfer.v1.storage.base.InsertionOnlyStorage;
import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext;
public class TrashingStorage<T extends TransferVariant<?>> implements InsertionOnlyStorage<T> {
public static final TrashingStorage<ItemVariant> ITEM = new TrashingStorage<>();
@Override
public long insert(T resource, long maxAmount, TransactionContext transaction) {
StoragePreconditions.notBlankNotNegative(resource, maxAmount);
// Insertion always succeeds.
return maxAmount;
}
@Override
public Iterator<StorageView<T>> iterator(TransactionContext transaction) {
return Collections.emptyIterator();
}
}