From 34f9516d542aadbb0434546994c31b301a0aea48 Mon Sep 17 00:00:00 2001 From: grimmauld Date: Thu, 10 Sep 2020 16:28:55 +0200 Subject: [PATCH] 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. --- .../dispenser/DispenserMovementBehaviour.java | 11 +++- .../IMovedDispenseItemBehaviour.java | 66 ------------------- .../MovedProjectileDispenserBehaviour.java | 21 ++++++ .../actors/dispenser/SimplePos.java | 30 +++++++++ 4 files changed, 61 insertions(+), 67 deletions(-) create mode 100644 src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/SimplePos.java diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DispenserMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DispenserMovementBehaviour.java index 1af570dc3..48ddd8cab 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DispenserMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DispenserMovementBehaviour.java @@ -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; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/IMovedDispenseItemBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/IMovedDispenseItemBehaviour.java index 7ef9d1748..fba60a901 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/IMovedDispenseItemBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/IMovedDispenseItemBehaviour.java @@ -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) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedProjectileDispenserBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedProjectileDispenserBehaviour.java index 924cefff0..a40a1ce32 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedProjectileDispenserBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedProjectileDispenserBehaviour.java @@ -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; + } + }; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/SimplePos.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/SimplePos.java new file mode 100644 index 000000000..14d9f9d7d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/SimplePos.java @@ -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; + } +}