From b8e53adf40fc363fff341ea1b04614c5a97b564b Mon Sep 17 00:00:00 2001 From: yueh Date: Thu, 10 Sep 2020 17:54:02 +0200 Subject: [PATCH] Fixes #4719: Take the entity size into account when spawning item entities (#4720) --- .../parts/automation/FormationPlanePart.java | 70 +++++++++++-------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/src/main/java/appeng/parts/automation/FormationPlanePart.java b/src/main/java/appeng/parts/automation/FormationPlanePart.java index e26fc885f..8a4e89a75 100644 --- a/src/main/java/appeng/parts/automation/FormationPlanePart.java +++ b/src/main/java/appeng/parts/automation/FormationPlanePart.java @@ -26,7 +26,6 @@ import java.util.Random; import javax.annotation.Nonnull; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.container.ContainerType; @@ -277,51 +276,62 @@ public class FormationPlanePart extends AbstractFormationPlanePart } private static boolean spawnItemEntity(World w, TileEntity te, AEPartLocation side, ItemStack is) { - // the item offset based on the entity height plus some offset - final double itemOffset = .55 + EntityType.ITEM.getHeight(); - // The center of the block the plane is located in final double centerX = te.getPos().getX() + .5; - final double centerY = te.getPos().getY() + .5; + final double centerY = te.getPos().getY(); final double centerZ = te.getPos().getZ() + .5; - // When spawning downwards, we have to take the item height of 0.25 into account - // Otherwise it will get stuck and be spit out in a random direction as - // minecraft spawns it at its feet position and not center - final double additionalYOffset = side.yOffset == -1 ? -.3 : 0; + // Create an ItemEntity already at the position of the plane. + // We don't know the final position, but need it for its size. + Entity entity = new ItemEntity(w, centerX, centerY, centerZ, is.copy()); + + // Replace it if there is a custom entity + if (is.getItem().hasCustomEntity(is)) { + Entity result = is.getItem().createEntity(w, entity, is); + // Destroy the old one, in case it's spawned somehow and replace with the new + // one. + if (result != null) { + entity.remove(); + entity = result; + } + } + + // When spawning downwards, we have to take into account that it spawns it at + // their "feet" and not center like x or z. So we move it up to be flush with + // the plane + final double additionalYOffset = side.yOffset == -1 ? 1 - entity.getHeight() : 0; + + // Calculate the maximum spawn area so an entity hitbox will always be inside + // the block. + final double spawnAreaHeight = Math.max(0, 1 - entity.getHeight()); + final double spawnAreaWidth = Math.max(0, 1 - entity.getWidth()); // Calculate the offsets to spawn it into the adjacent block, taking the sign // into account. // Spawn it 0.8 blocks away from the center pos when facing in this direction // Every other direction will select a position in a .5 block area around the // block center. - final double offsetX = (side.xOffset == 0) ? ((RANDOM_OFFSET.nextFloat() / 2) - .25) - : (side.xOffset * itemOffset); - final double offsetY = (side.yOffset == 0) ? ((RANDOM_OFFSET.nextFloat() / 2) - .25) - : ((side.yOffset * itemOffset) + additionalYOffset); - final double offsetZ = (side.zOffset == 0) ? ((RANDOM_OFFSET.nextFloat() / 2) - .25) - : (side.zOffset * itemOffset); + final double offsetX = (side.xOffset == 0) // + ? ((RANDOM_OFFSET.nextFloat() * spawnAreaWidth) - spawnAreaWidth / 2) + : (side.xOffset * (.525 + entity.getWidth() / 2)); + final double offsetY = (side.yOffset == 0) // + ? (RANDOM_OFFSET.nextFloat() * spawnAreaHeight) + : ((side.yOffset) + additionalYOffset); + final double offsetZ = (side.zOffset == 0) // + ? ((RANDOM_OFFSET.nextFloat() * spawnAreaWidth) - spawnAreaWidth / 2) + : (side.zOffset * (.525 + entity.getWidth() / 2)); final double absoluteX = centerX + offsetX; final double absoluteY = centerY + offsetY; final double absoluteZ = centerZ + offsetZ; - final ItemEntity ei = new ItemEntity(w, absoluteX, absoluteY, absoluteZ, is.copy()); - Entity result = ei; + // Set to correct position and slow the motion down a bit + entity.setPosition(absoluteX, absoluteY, absoluteZ); + entity.setMotion(side.xOffset * .1, side.yOffset * 0.1, side.zOffset * 0.1); - ei.setMotion(side.xOffset * .1, side.yOffset * 0.1, side.zOffset * 0.1); - - if (is.getItem().hasCustomEntity(is)) { - result = is.getItem().createEntity(w, ei, is); - if (result != null) { - ei.remove(); - } else { - result = ei; - } - } - - if (!w.addEntity(result)) { - result.remove(); + // Try to spawn it and destroy it in case it's not possible + if (!w.addEntity(entity)) { + entity.remove(); return false; } return true;