mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-11-11 13:04:05 +01:00
Added indirect projectile dispense behaviours for compatibility with modded projectiles right out of the box. Removed the direct projectile behaviours from vanilla as they are now covered from the indirect implementation.
This commit is contained in:
parent
3d006e7e87
commit
34f9516d54
@ -8,6 +8,7 @@ import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.DispenserBlock;
|
||||
import net.minecraft.dispenser.DefaultDispenseItemBehavior;
|
||||
import net.minecraft.dispenser.IDispenseItemBehavior;
|
||||
import net.minecraft.dispenser.ProjectileDispenseBehavior;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Direction;
|
||||
@ -45,12 +46,20 @@ public class DispenserMovementBehaviour extends DropperMovementBehaviour {
|
||||
ItemStack backup = itemstack.copy();
|
||||
// If none is there, try vanilla registry
|
||||
try {
|
||||
IDispenseItemBehavior idispenseitembehavior = BEHAVIOUR_LOOKUP.getBehavior(itemstack);
|
||||
if (idispenseitembehavior instanceof ProjectileDispenseBehavior) { // Projectile behaviours can be converted most of the time
|
||||
IMovedDispenseItemBehaviour iMovedDispenseItemBehaviour = MovedProjectileDispenserBehaviour.of((ProjectileDispenseBehavior) idispenseitembehavior);
|
||||
setItemStackAt(location, iMovedDispenseItemBehaviour.dispense(itemstack, context, pos), context);
|
||||
registerMovedDispenseItemBehaviour(itemstack.getItem(), iMovedDispenseItemBehaviour); // buffer conversion if successful
|
||||
return;
|
||||
}
|
||||
|
||||
Vec3d facingVec = new Vec3d(context.state.get(DispenserBlock.FACING).getDirectionVec());
|
||||
facingVec = VecHelper.rotate(facingVec, context.rotation.x, context.rotation.y, context.rotation.z);
|
||||
facingVec.normalize();
|
||||
Direction clostestFacing = Direction.getFacingFromVector(facingVec.x, facingVec.y, facingVec.z);
|
||||
ContraptionBlockSource blockSource = new ContraptionBlockSource(context, pos, clostestFacing);
|
||||
IDispenseItemBehavior idispenseitembehavior = BEHAVIOUR_LOOKUP.getBehavior(itemstack);
|
||||
|
||||
if (idispenseitembehavior.getClass() != DefaultDispenseItemBehavior.class) { // There is a dispense item behaviour registered for the vanilla dispenser
|
||||
setItemStackAt(location, idispenseitembehavior.dispense(blockSource, itemstack), context);
|
||||
return;
|
||||
|
@ -9,13 +9,11 @@ import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.IProjectile;
|
||||
import net.minecraft.entity.SpawnReason;
|
||||
import net.minecraft.entity.item.ExperienceBottleEntity;
|
||||
import net.minecraft.entity.item.FireworkRocketEntity;
|
||||
import net.minecraft.entity.item.TNTEntity;
|
||||
import net.minecraft.entity.projectile.*;
|
||||
import net.minecraft.fluid.FlowingFluid;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.item.BucketItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.item.SpawnEggItem;
|
||||
@ -36,70 +34,6 @@ import java.util.Random;
|
||||
|
||||
public interface IMovedDispenseItemBehaviour {
|
||||
static void init() {
|
||||
DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.ARROW, new MovedProjectileDispenserBehaviour() {
|
||||
@Override
|
||||
protected IProjectile getProjectileEntity(World world, double x, double y, double z, ItemStack itemStack) {
|
||||
ArrowEntity arrowEntity = new ArrowEntity(world, x, y, z);
|
||||
arrowEntity.pickupStatus = AbstractArrowEntity.PickupStatus.ALLOWED;
|
||||
return arrowEntity;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.TIPPED_ARROW, new MovedProjectileDispenserBehaviour() {
|
||||
@Override
|
||||
protected IProjectile getProjectileEntity(World world, double x, double y, double z, ItemStack itemStack) {
|
||||
ArrowEntity arrowEntity = new ArrowEntity(world, x, y, z);
|
||||
arrowEntity.setPotionEffect(itemStack);
|
||||
arrowEntity.pickupStatus = AbstractArrowEntity.PickupStatus.ALLOWED;
|
||||
return arrowEntity;
|
||||
}
|
||||
});
|
||||
|
||||
DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.SPECTRAL_ARROW, new MovedProjectileDispenserBehaviour() {
|
||||
@Override
|
||||
protected IProjectile getProjectileEntity(World world, double x, double y, double z, ItemStack itemStack) {
|
||||
AbstractArrowEntity arrowEntity = new SpectralArrowEntity(world, x, y, z);
|
||||
arrowEntity.pickupStatus = AbstractArrowEntity.PickupStatus.ALLOWED;
|
||||
return arrowEntity;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.EGG, new MovedProjectileDispenserBehaviour() {
|
||||
@Override
|
||||
protected IProjectile getProjectileEntity(World world, double x, double y, double z, ItemStack itemStack) {
|
||||
return Util.make(new EggEntity(world, x, y, z), p_218408_1_ -> p_218408_1_.setItem(itemStack));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.SNOWBALL, new MovedProjectileDispenserBehaviour() {
|
||||
@Override
|
||||
protected IProjectile getProjectileEntity(World world, double x, double y, double z, ItemStack itemStack) {
|
||||
return Util.make(new SnowballEntity(world, x, y, z), p_218409_1_ -> p_218409_1_.setItem(itemStack));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
DispenserMovementBehaviour.registerMovedDispenseItemBehaviour(Items.EXPERIENCE_BOTTLE, new MovedProjectileDispenserBehaviour() {
|
||||
@Override
|
||||
protected IProjectile getProjectileEntity(World world, double x, double y, double z, ItemStack itemStack) {
|
||||
return Util.make(new ExperienceBottleEntity(world, x, y, z), p_218409_1_ -> p_218409_1_.setItem(itemStack));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getProjectileInaccuracy() {
|
||||
return super.getProjectileInaccuracy() * 0.5F;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getProjectileVelocity() {
|
||||
return super.getProjectileVelocity() * 1.25F;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
MovedProjectileDispenserBehaviour movedPotionDispenseItemBehaviour = new MovedProjectileDispenserBehaviour() {
|
||||
@Override
|
||||
protected IProjectile getProjectileEntity(World world, double x, double y, double z, ItemStack itemStack) {
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.simibubi.create.content.contraptions.components.actors.dispenser;
|
||||
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||
import net.minecraft.dispenser.IPosition;
|
||||
import net.minecraft.dispenser.ProjectileDispenseBehavior;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.IProjectile;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@ -9,6 +11,8 @@ import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public abstract class MovedProjectileDispenserBehaviour extends MovedDefaultDispenseItemBehaviour {
|
||||
@Override
|
||||
protected ItemStack dispenseStack(ItemStack itemStack, MovementContext context, BlockPos pos, Vec3d facing) {
|
||||
@ -16,6 +20,8 @@ public abstract class MovedProjectileDispenserBehaviour extends MovedDefaultDisp
|
||||
double y = pos.getY() + facing.y * .7 + .5;
|
||||
double z = pos.getZ() + facing.z * .7 + .5;
|
||||
IProjectile iprojectile = this.getProjectileEntity(context.world, x, y, z, itemStack);
|
||||
if (iprojectile == null)
|
||||
return itemStack;
|
||||
Vec3d effectiveMovementVec = facing.scale(getProjectileVelocity()).add(context.motion);
|
||||
iprojectile.shoot(effectiveMovementVec.x, effectiveMovementVec.y, effectiveMovementVec.z, (float) effectiveMovementVec.length(), this.getProjectileInaccuracy());
|
||||
context.world.addEntity((Entity) iprojectile);
|
||||
@ -37,4 +43,19 @@ public abstract class MovedProjectileDispenserBehaviour extends MovedDefaultDisp
|
||||
protected float getProjectileVelocity() {
|
||||
return 1.1F;
|
||||
}
|
||||
|
||||
public static MovedProjectileDispenserBehaviour of(ProjectileDispenseBehavior vanillaBehaviour) {
|
||||
return new MovedProjectileDispenserBehaviour() {
|
||||
@Override
|
||||
protected IProjectile getProjectileEntity(World world, double x, double y, double z, ItemStack itemStack) {
|
||||
try {
|
||||
Method projectileLookup = ProjectileDispenseBehavior.class.getDeclaredMethod("getProjectileEntity", World.class, IPosition.class, ItemStack.class);
|
||||
projectileLookup.setAccessible(true);
|
||||
return (IProjectile) projectileLookup.invoke(vanillaBehaviour, world, new SimplePos(x, y, z) , itemStack);
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
package com.simibubi.create.content.contraptions.components.actors.dispenser;
|
||||
|
||||
import net.minecraft.dispenser.IPosition;
|
||||
|
||||
public class SimplePos implements IPosition {
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
|
||||
public SimplePos(double x, double y, double z) {
|
||||
this.x = (int) Math.round(x);
|
||||
this.y = (int) Math.round(y);
|
||||
this.z = (int) Math.round(z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getZ() {
|
||||
return z;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user