mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-29 08:27:03 +01:00
Added potion moved dispense behaviour, fixed dispense behaviour output stack not being used resulting in potential dupes
This commit is contained in:
parent
3b516f5022
commit
7784e5b58d
6 changed files with 120 additions and 47 deletions
|
@ -0,0 +1,25 @@
|
||||||
|
package com.simibubi.create.content.contraptions.components.actors.dispenser;
|
||||||
|
|
||||||
|
public class DispenseItemLocation {
|
||||||
|
private final boolean internal;
|
||||||
|
private final int slot;
|
||||||
|
|
||||||
|
public static final DispenseItemLocation NONE = new DispenseItemLocation(false, -1);
|
||||||
|
|
||||||
|
public DispenseItemLocation(boolean internal, int slot) {
|
||||||
|
this.internal = internal;
|
||||||
|
this.slot = slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInternal() {
|
||||||
|
return internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSlot() {
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return slot < 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,13 +31,14 @@ public class DispenserMovementBehaviour extends DropperMovementBehaviour {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void activate(MovementContext context, BlockPos pos) {
|
protected void activate(MovementContext context, BlockPos pos) {
|
||||||
ItemStack itemstack = getDispenseStack(context);
|
DispenseItemLocation location = getDispenseStack(context);
|
||||||
if (itemstack.isEmpty()) {
|
if (location.isEmpty()) {
|
||||||
context.world.playEvent(1001, pos, 0);
|
context.world.playEvent(1001, pos, 0);
|
||||||
} else {
|
} else {
|
||||||
|
ItemStack itemstack = getItemStackAt(location, context);
|
||||||
// Special dispense item behaviour for moving contraptions
|
// Special dispense item behaviour for moving contraptions
|
||||||
if (MOVED_DISPENSE_ITEM_BEHAVIOURS.containsKey(itemstack.getItem())) {
|
if (MOVED_DISPENSE_ITEM_BEHAVIOURS.containsKey(itemstack.getItem())) {
|
||||||
MOVED_DISPENSE_ITEM_BEHAVIOURS.get(itemstack.getItem()).dispense(itemstack, context, pos);
|
setItemStackAt(location, MOVED_DISPENSE_ITEM_BEHAVIOURS.get(itemstack.getItem()).dispense(itemstack, context, pos), context);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,14 +52,14 @@ public class DispenserMovementBehaviour extends DropperMovementBehaviour {
|
||||||
ContraptionBlockSource blockSource = new ContraptionBlockSource(context, pos, clostestFacing);
|
ContraptionBlockSource blockSource = new ContraptionBlockSource(context, pos, clostestFacing);
|
||||||
IDispenseItemBehavior idispenseitembehavior = BEHAVIOUR_LOOKUP.getBehavior(itemstack);
|
IDispenseItemBehavior idispenseitembehavior = BEHAVIOUR_LOOKUP.getBehavior(itemstack);
|
||||||
if (idispenseitembehavior.getClass() != DefaultDispenseItemBehavior.class) { // There is a dispense item behaviour registered for the vanilla dispenser
|
if (idispenseitembehavior.getClass() != DefaultDispenseItemBehavior.class) { // There is a dispense item behaviour registered for the vanilla dispenser
|
||||||
idispenseitembehavior.dispense(blockSource, itemstack);
|
setItemStackAt(location, idispenseitembehavior.dispense(blockSource, itemstack), context);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException ignored) {
|
||||||
itemstack = backup; // Something went wrong with the TE being null in ContraptionBlockSource, reset the stack
|
itemstack = backup;
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultBehaviour.dispense(itemstack, context, pos); // the default: launch the item
|
setItemStackAt(location, defaultBehaviour.dispense(itemstack, context, pos), context); // the default: launch the item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,11 +19,11 @@ public class DropperMovementBehaviour extends MovementBehaviour {
|
||||||
private static final Random RNG = new Random();
|
private static final Random RNG = new Random();
|
||||||
|
|
||||||
protected void activate(MovementContext context, BlockPos pos) {
|
protected void activate(MovementContext context, BlockPos pos) {
|
||||||
ItemStack itemstack = getDispenseStack(context);
|
DispenseItemLocation location = getDispenseStack(context);
|
||||||
if (itemstack.isEmpty()) {
|
if (location.isEmpty()) {
|
||||||
context.world.playEvent(1001, pos, 0);
|
context.world.playEvent(1001, pos, 0);
|
||||||
} else {
|
} else {
|
||||||
defaultBehaviour.dispense(itemstack, context, pos);
|
setItemStackAt(location, defaultBehaviour.dispense(getItemStackAt(location, context), context, pos), context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,27 +40,34 @@ public class DropperMovementBehaviour extends MovementBehaviour {
|
||||||
ItemHelper.extract(context.contraption.inventory, itemStack::isItemEqual, ItemHelper.ExtractionCountMode.UPTO, itemStack.getMaxStackSize() - itemStack.getCount(), false).getCount()));
|
ItemHelper.extract(context.contraption.inventory, itemStack::isItemEqual, ItemHelper.ExtractionCountMode.UPTO, itemStack.getMaxStackSize() - itemStack.getCount(), false).getCount()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
private void updateTemporaryData(MovementContext context) {
|
||||||
private NonNullList<ItemStack> getStacks(MovementContext context) {
|
|
||||||
if (!(context.temporaryData instanceof NonNullList) && context.world instanceof ServerWorld) {
|
if (!(context.temporaryData instanceof NonNullList) && context.world instanceof ServerWorld) {
|
||||||
NonNullList<ItemStack> stacks = NonNullList.withSize(9, ItemStack.EMPTY);
|
NonNullList<ItemStack> stacks = NonNullList.withSize(getInvSize(), ItemStack.EMPTY);
|
||||||
ItemStackHelper.loadAllItems(context.tileData, stacks);
|
ItemStackHelper.loadAllItems(context.tileData, stacks);
|
||||||
context.temporaryData = stacks;
|
context.temporaryData = stacks;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private NonNullList<ItemStack> getStacks(MovementContext context) {
|
||||||
|
updateTemporaryData(context);
|
||||||
return (NonNullList<ItemStack>) context.temporaryData;
|
return (NonNullList<ItemStack>) context.temporaryData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<ItemStack> getUseableStacks(MovementContext context) {
|
private ArrayList<DispenseItemLocation> getUseableLocations(MovementContext context) {
|
||||||
ArrayList<ItemStack> useable = new ArrayList<>();
|
ArrayList<DispenseItemLocation> useable = new ArrayList<>();
|
||||||
for (ItemStack testStack : getStacks(context)) {
|
NonNullList<ItemStack> internalStacks = getStacks(context);
|
||||||
|
for (int slot = 0; slot < getInvSize(); slot++) {
|
||||||
|
DispenseItemLocation location = new DispenseItemLocation(true, slot);
|
||||||
|
ItemStack testStack = getItemStackAt(location, context);
|
||||||
if (testStack == null || testStack.isEmpty())
|
if (testStack == null || testStack.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
if (testStack.getMaxStackSize() == 1) {
|
if (testStack.getMaxStackSize() == 1) {
|
||||||
ItemStack stack = ItemHelper.findFirstMatch(context.contraption.inventory, testStack::isItemEqual);
|
location = new DispenseItemLocation(false, ItemHelper.findFirstMatchingSlotIndex(context.contraption.inventory, testStack::isItemEqual));
|
||||||
if (!stack.isEmpty())
|
if (!getItemStackAt(location, context).isEmpty())
|
||||||
useable.add(stack);
|
useable.add(location);
|
||||||
} else if (testStack.getCount() >= 2)
|
} else if (internalStacks.get(slot).getCount() >= 2)
|
||||||
useable.add(testStack);
|
useable.add(location);
|
||||||
}
|
}
|
||||||
return useable;
|
return useable;
|
||||||
}
|
}
|
||||||
|
@ -79,18 +86,38 @@ public class DropperMovementBehaviour extends MovementBehaviour {
|
||||||
writeExtraData(context);
|
writeExtraData(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ItemStack getDispenseStack(MovementContext context) {
|
protected DispenseItemLocation getDispenseStack(MovementContext context) {
|
||||||
int i = -1;
|
int i = -1;
|
||||||
int j = 1;
|
int j = 1;
|
||||||
List<ItemStack> stacks = getUseableStacks(context);
|
List<DispenseItemLocation> useableLocations = getUseableLocations(context);
|
||||||
for (int k = 0; k < stacks.size(); ++k) {
|
for (int k = 0; k < useableLocations.size(); ++k) {
|
||||||
if (RNG.nextInt(j++) == 0) {
|
if (RNG.nextInt(j++) == 0) {
|
||||||
i = k;
|
i = k;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
return ItemStack.EMPTY;
|
return DispenseItemLocation.NONE;
|
||||||
else
|
else
|
||||||
return stacks.get(i);
|
return useableLocations.get(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ItemStack getItemStackAt(DispenseItemLocation location, MovementContext context) {
|
||||||
|
if (location.isInternal()) {
|
||||||
|
return getStacks(context).get(location.getSlot());
|
||||||
|
} else {
|
||||||
|
return context.contraption.inventory.getStackInSlot(location.getSlot());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setItemStackAt(DispenseItemLocation location, ItemStack stack, MovementContext context) {
|
||||||
|
if (location.isInternal()) {
|
||||||
|
getStacks(context).set(location.getSlot(), stack);
|
||||||
|
} else {
|
||||||
|
context.contraption.inventory.setStackInSlot(location.getSlot(), stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getInvSize() {
|
||||||
|
return 9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import net.minecraft.entity.item.TNTEntity;
|
||||||
import net.minecraft.entity.projectile.*;
|
import net.minecraft.entity.projectile.*;
|
||||||
import net.minecraft.fluid.FlowingFluid;
|
import net.minecraft.fluid.FlowingFluid;
|
||||||
import net.minecraft.fluid.Fluid;
|
import net.minecraft.fluid.Fluid;
|
||||||
|
import net.minecraft.item.BucketItem;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.item.SpawnEggItem;
|
import net.minecraft.item.SpawnEggItem;
|
||||||
|
@ -30,7 +31,6 @@ import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.IWorld;
|
import net.minecraft.world.IWorld;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.items.ItemHandlerHelper;
|
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
@ -100,6 +100,24 @@ public interface IMovedDispenseItemBehaviour {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
MovedProjectileDispenserBehaviour movedPotionDispenseItemBehaviour = new MovedProjectileDispenserBehaviour() {
|
||||||
|
@Override
|
||||||
|
protected IProjectile getProjectileEntity(World world, double x, double y, double z, ItemStack itemStack) {
|
||||||
|
return Util.make(new PotionEntity(world, x, y, z), (p_218411_1_) -> p_218411_1_.setItem(itemStack));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected float getProjectileInaccuracy() {
|
||||||
|
return super.getProjectileInaccuracy() * 0.5F;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected float getProjectileVelocity() {
|
||||||
|
return super.getProjectileVelocity() * .5F;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.SPLASH_POTION, movedPotionDispenseItemBehaviour);
|
||||||
|
DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.LINGERING_POTION, movedPotionDispenseItemBehaviour);
|
||||||
|
|
||||||
|
|
||||||
DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.TNT, new MovedDefaultDispenseItemBehaviour() {
|
DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.TNT, new MovedDefaultDispenseItemBehaviour() {
|
||||||
@Override
|
@Override
|
||||||
protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, Vec3d facing) {
|
protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, Vec3d facing) {
|
||||||
|
@ -175,14 +193,6 @@ public interface IMovedDispenseItemBehaviour {
|
||||||
return super.dispenseStack(itemStack, context, pos, facing);
|
return super.dispenseStack(itemStack, context, pos, facing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ItemStack placeItemInInventory(ItemStack bottles, ItemStack output, MovementContext context, BlockPos pos, Vec3d facing) {
|
|
||||||
bottles.shrink(1);
|
|
||||||
ItemStack remainder = ItemHandlerHelper.insertItem(context.contraption.inventory, output.copy(), false);
|
|
||||||
if (!remainder.isEmpty())
|
|
||||||
super.dispenseStack(output, context, pos, facing);
|
|
||||||
return bottles;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.BUCKET, new MovedDefaultDispenseItemBehaviour() {
|
DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.BUCKET, new MovedDefaultDispenseItemBehaviour() {
|
||||||
|
@ -198,14 +208,6 @@ public interface IMovedDispenseItemBehaviour {
|
||||||
}
|
}
|
||||||
return super.dispenseStack(itemStack, context, pos, facing);
|
return super.dispenseStack(itemStack, context, pos, facing);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ItemStack placeItemInInventory(ItemStack buckets, ItemStack output, MovementContext context, BlockPos pos, Vec3d facing) {
|
|
||||||
buckets.shrink(1);
|
|
||||||
ItemStack remainder = ItemHandlerHelper.insertItem(context.contraption.inventory, output.copy(), false);
|
|
||||||
if (!remainder.isEmpty())
|
|
||||||
super.dispenseStack(output, context, pos, facing);
|
|
||||||
return buckets;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
final IMovedDispenseItemBehaviour spawnEggDispenseBehaviour = new MovedDefaultDispenseItemBehaviour() {
|
final IMovedDispenseItemBehaviour spawnEggDispenseBehaviour = new MovedDefaultDispenseItemBehaviour() {
|
||||||
|
|
|
@ -12,8 +12,10 @@ import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.IWorld;
|
import net.minecraft.world.IWorld;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.items.ItemHandlerHelper;
|
||||||
|
|
||||||
public class MovedDefaultDispenseItemBehaviour implements IMovedDispenseItemBehaviour {
|
public class MovedDefaultDispenseItemBehaviour implements IMovedDispenseItemBehaviour {
|
||||||
|
private static final MovedDefaultDispenseItemBehaviour defaultInstance = new MovedDefaultDispenseItemBehaviour();
|
||||||
|
|
||||||
public static void doDispense(World p_82486_0_, ItemStack p_82486_1_, int p_82486_2_, Vec3d facing, BlockPos p_82486_4_, MovementContext context) {
|
public static void doDispense(World p_82486_0_, ItemStack p_82486_1_, int p_82486_2_, Vec3d facing, BlockPos p_82486_4_, MovementContext context) {
|
||||||
double d0 = p_82486_4_.getX() + facing.x + .5;
|
double d0 = p_82486_4_.getX() + facing.x + .5;
|
||||||
|
@ -80,4 +82,12 @@ public class MovedDefaultDispenseItemBehaviour implements IMovedDispenseItemBeha
|
||||||
protected Direction getClosestFacingDirection(Vec3d exactFacing) {
|
protected Direction getClosestFacingDirection(Vec3d exactFacing) {
|
||||||
return Direction.getFacingFromVector(exactFacing.x, exactFacing.y, exactFacing.z);
|
return Direction.getFacingFromVector(exactFacing.x, exactFacing.y, exactFacing.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected ItemStack placeItemInInventory(ItemStack consumedFrom, ItemStack output, MovementContext context, BlockPos pos, Vec3d facing) {
|
||||||
|
consumedFrom.shrink(1);
|
||||||
|
ItemStack remainder = ItemHandlerHelper.insertItem(context.contraption.inventory, output.copy(), false);
|
||||||
|
if (!remainder.isEmpty())
|
||||||
|
defaultInstance.dispenseStack(output, context, pos, facing);
|
||||||
|
return consumedFrom;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,11 +242,19 @@ public class ItemHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemStack findFirstMatch(IItemHandler inv, Predicate<ItemStack> test) {
|
public static ItemStack findFirstMatch(IItemHandler inv, Predicate<ItemStack> test) {
|
||||||
for (int i = 0; i < inv.getSlots(); i++) {
|
int slot = findFirstMatchingSlotIndex(inv, test);
|
||||||
ItemStack toTest = inv.getStackInSlot(i);
|
if (slot == -1)
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
else
|
||||||
|
return inv.getStackInSlot(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int findFirstMatchingSlotIndex(IItemHandler inv, Predicate<ItemStack> test) {
|
||||||
|
for (int slot = 0; slot < inv.getSlots(); slot++) {
|
||||||
|
ItemStack toTest = inv.getStackInSlot(slot);
|
||||||
if (test.test(toTest))
|
if (test.test(toTest))
|
||||||
return toTest;
|
return slot;
|
||||||
}
|
}
|
||||||
return ItemStack.EMPTY;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue