diff --git a/src/main/java/net/mcreator/target/entity/BocekarrowEntity.java b/src/main/java/net/mcreator/target/entity/BocekarrowEntity.java index 7d9aa078a..e159ce3f3 100644 --- a/src/main/java/net/mcreator/target/entity/BocekarrowEntity.java +++ b/src/main/java/net/mcreator/target/entity/BocekarrowEntity.java @@ -148,7 +148,7 @@ public class BocekarrowEntity extends AbstractArrow implements ItemSupplier { } super.onHitEntity(result); this.discard(); - } + } @Override public void tick() { diff --git a/src/main/java/net/mcreator/target/entity/GunGrenadeEntity.java b/src/main/java/net/mcreator/target/entity/GunGrenadeEntity.java index 767455e2d..d8c7f002b 100644 --- a/src/main/java/net/mcreator/target/entity/GunGrenadeEntity.java +++ b/src/main/java/net/mcreator/target/entity/GunGrenadeEntity.java @@ -142,7 +142,7 @@ public class GunGrenadeEntity extends AbstractArrow implements ItemSupplier { } super.onHitEntity(result); this.discard(); - } + } @Override public void onHitBlock(BlockHitResult blockHitResult) { diff --git a/src/main/java/net/mcreator/target/entity/MortarShellEntity.java b/src/main/java/net/mcreator/target/entity/MortarShellEntity.java index afb6e1866..ce707dd00 100644 --- a/src/main/java/net/mcreator/target/entity/MortarShellEntity.java +++ b/src/main/java/net/mcreator/target/entity/MortarShellEntity.java @@ -72,7 +72,7 @@ public class MortarShellEntity extends AbstractArrow implements ItemSupplier { public void onHitEntity(EntityHitResult entityHitResult) { super.onHitEntity(entityHitResult); MortarShellDanSheWuJiZhongShiTiShiProcedure.execute(this.level(), this); - } + } @Override public void onHitBlock(BlockHitResult blockHitResult) { diff --git a/src/main/java/net/mcreator/target/entity/ProjectileEntity.java b/src/main/java/net/mcreator/target/entity/ProjectileEntity.java index 080adfce9..7a15182ac 100644 --- a/src/main/java/net/mcreator/target/entity/ProjectileEntity.java +++ b/src/main/java/net/mcreator/target/entity/ProjectileEntity.java @@ -1,9 +1,18 @@ package net.mcreator.target.entity; +import net.minecraft.advancements.CriteriaTriggers; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.stats.Stats; +import net.minecraft.util.Mth; +import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.level.ClipContext; +import net.minecraft.world.level.block.*; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.FluidState; import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.level.Level; import net.minecraft.world.entity.EntityType; @@ -15,6 +24,8 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSource; import net.minecraft.server.level.ServerLevel; import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; import net.mcreator.target.headshot.BoundingBoxManager; import net.mcreator.target.headshot.IHeadshotBox; @@ -22,11 +33,25 @@ import net.mcreator.target.init.TargetCustomModEntities; import net.mcreator.target.init.TargetModItems; import net.mcreator.target.procedures.ProjectileHitEntity; import net.mcreator.target.procedures.ProjectileHeadshotEntity; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraftforge.common.MinecraftForge; +import net.mcreator.target.util.math.ExtendedEntityRayTraceResult; +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Predicate; public class ProjectileEntity extends ThrowableItemProjectile { + private static final Predicate PROJECTILE_TARGETS = input -> input != null && input.isPickable() && !input.isSpectator(); + + private static final Predicate IGNORE_LEAVES = input -> input != null && input.getBlock() instanceof LeavesBlock; + protected LivingEntity shooter; + protected int shooterId; private float damage; public ProjectileEntity(EntityType p_i50159_1_, Level p_i50159_2_) { @@ -46,18 +71,79 @@ public class ProjectileEntity extends ThrowableItemProjectile { public ProjectileEntity(Level p_i1775_1_, double p_i1775_2_, double p_i1775_4_, double p_i1775_6_) { super(TargetCustomModEntities.PROJECTILE.get(), p_i1775_2_, p_i1775_4_, p_i1775_6_, p_i1775_1_); } - @Override - protected void onHitEntity(EntityHitResult pResult) { - final Vec3 position = this.position(); - Entity entity = pResult.getEntity(); - if (entity instanceof LivingEntity livingEntity) { - entity.invulnerableTime = 0; + @Nullable + protected EntityResult findEntityOnPath(Vec3 startVec, Vec3 endVec) + { + Vec3 hitVec = null; + Entity hitEntity = null; + boolean headshot = false; + List entities = this.level().getEntities(this, this.getBoundingBox().expandTowards(this.getDeltaMovement()).inflate(1.0), PROJECTILE_TARGETS); + double closestDistance = Double.MAX_VALUE; + for(Entity entity : entities) + { + if(!entity.equals(this.shooter)) + { + EntityResult result = this.getHitResult(entity, startVec, endVec); + if(result == null) + continue; + Vec3 hitPos = result.getHitPos(); + double distanceToHit = startVec.distanceTo(hitPos); + if(distanceToHit < closestDistance) + { + hitVec = hitPos; + hitEntity = entity; + closestDistance = distanceToHit; + headshot = result.isHeadshot(); + } + } } + return hitEntity != null ? new EntityResult(hitEntity, hitVec, headshot) : null; + } + + @Nullable + protected List findEntitiesOnPath(Vec3 startVec, Vec3 endVec) + { + List hitEntities = new ArrayList<>(); + List entities = this.level().getEntities(this, this.getBoundingBox().expandTowards(this.getDeltaMovement()).inflate(1.0), PROJECTILE_TARGETS); + for(Entity entity : entities) + { + if(!entity.equals(this.shooter)) + { + EntityResult result = this.getHitResult(entity, startVec, endVec); + if(result == null) + continue; + hitEntities.add(result); + } + } + return hitEntities; + } + + @Nullable + @SuppressWarnings("unchecked") + private EntityResult getHitResult(Entity entity, Vec3 startVec, Vec3 endVec) + { + double expandHeight = entity instanceof Player && !entity.isCrouching() ? 0.0625 : 0.0; AABB boundingBox = entity.getBoundingBox(); - Vec3 startVec = this.position(); - Vec3 endVec = startVec.add(this.getDeltaMovement()); + if(entity instanceof ServerPlayer && this.shooter != null) + { + int ping = (int) Math.floor((((ServerPlayer) this.shooter).latency / 1000.0) * 20.0 + 3.5); + boundingBox = BoundingBoxManager.getBoundingBox((Player) entity, ping); + } + boundingBox = boundingBox.expandTowards(0, expandHeight, 0); + Vec3 hitPos = boundingBox.clip(startVec, endVec).orElse(null); + Vec3 grownHitPos = boundingBox.inflate(0.2, 0, 0.2).clip(startVec, endVec).orElse(null); + if(hitPos == null && grownHitPos != null) + { + HitResult raytraceresult = rayTraceBlocks(this.level(), new ClipContext(startVec, grownHitPos, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this), IGNORE_LEAVES); + if(raytraceresult.getType() == HitResult.Type.BLOCK) + { + return null; + } + hitPos = grownHitPos; + } + /* Check for headshot */ boolean headshot = false; if(entity instanceof LivingEntity) @@ -72,7 +158,7 @@ public class ProjectileEntity extends ThrowableItemProjectile { Optional headshotHitPos = box.clip(startVec, endVec); if(!headshotHitPos.isPresent()) { - box = box.inflate( 0.2, 0.2, 0.2); + box = box.inflate(0.2, 0.2, 0.2); headshotHitPos = box.clip(startVec, endVec); } if(headshotHitPos.isPresent() && (hitPos == null || headshotHitPos.get().distanceTo(hitPos) < 0.55)) @@ -80,15 +166,18 @@ public class ProjectileEntity extends ThrowableItemProjectile { hitPos = headshotHitPos.get(); headshot = true; } - if(headshot){ - ProjectileHeadshotEntity.execute(this.level(), pResult.getEntity(), this, this.getOwner()); - } } } } - ProjectileHitEntity.execute(this.level(), pResult.getEntity(), this, this.getOwner()); - } + if(hitPos == null) + { + return null; + } + + return new EntityResult(entity, hitPos, headshot); + } + @Override public void tick() { super.tick(); @@ -115,6 +204,42 @@ public class ProjectileEntity extends ThrowableItemProjectile { this.discard(); } + private void onHit(HitResult result, Vec3 startVec, Vec3 endVec) + { + + if(result instanceof ExtendedEntityRayTraceResult entityHitResult) + { + Entity entity = entityHitResult.getEntity(); + if(entity.getId() == this.shooterId) + { + return; + } + + if(this.shooter instanceof Player player) + { + if(entity.hasIndirectPassenger(player)) + { + return; + } + } + + + this.onHitEntity(entity, result.getLocation(), startVec, endVec, entityHitResult.isHeadshot()); + entity.invulnerableTime = 0; + } + } + + protected void onHitEntity(Entity entity, Vec3 hitVec, Vec3 startVec, Vec3 endVec, boolean headshot) + { + + if(headshot){ + + ProjectileHeadshotEntity.execute(this.level(), entity, this, this.getOwner()); + + } + ProjectileHitEntity.execute(this.level(), entity, this, this.getOwner()); + } + @Override protected Item getDefaultItem() { return TargetModItems.RIFLE_AMMO.get().asItem(); @@ -127,4 +252,139 @@ public class ProjectileEntity extends ThrowableItemProjectile { public float getDamage() { return this.damage; } + + private static BlockHitResult rayTraceBlocks(Level world, ClipContext context, Predicate ignorePredicate) + { + return performRayTrace(context, (rayTraceContext, blockPos) -> { + BlockState blockState = world.getBlockState(blockPos); + if(ignorePredicate.test(blockState)) return null; + FluidState fluidState = world.getFluidState(blockPos); + Vec3 startVec = rayTraceContext.getFrom(); + Vec3 endVec = rayTraceContext.getTo(); + VoxelShape blockShape = rayTraceContext.getBlockShape(blockState, world, blockPos); + BlockHitResult blockResult = world.clipWithInteractionOverride(startVec, endVec, blockPos, blockShape, blockState); + VoxelShape fluidShape = rayTraceContext.getFluidShape(fluidState, world, blockPos); + BlockHitResult fluidResult = fluidShape.clip(startVec, endVec, blockPos); + double blockDistance = blockResult == null ? Double.MAX_VALUE : rayTraceContext.getFrom().distanceToSqr(blockResult.getLocation()); + double fluidDistance = fluidResult == null ? Double.MAX_VALUE : rayTraceContext.getFrom().distanceToSqr(fluidResult.getLocation()); + return blockDistance <= fluidDistance ? blockResult : fluidResult; + }, (rayTraceContext) -> { + Vec3 Vector3d = rayTraceContext.getFrom().subtract(rayTraceContext.getTo()); + return BlockHitResult.miss(rayTraceContext.getTo(), Direction.getNearest(Vector3d.x, Vector3d.y, Vector3d.z), BlockPos.containing(rayTraceContext.getTo())); + }); + } + + private static T performRayTrace(ClipContext context, BiFunction hitFunction, Function p_217300_2_) + { + Vec3 startVec = context.getFrom(); + Vec3 endVec = context.getTo(); + if(startVec.equals(endVec)) + { + return p_217300_2_.apply(context); + } + else + { + double startX = Mth.lerp(-0.0000001, endVec.x, startVec.x); + double startY = Mth.lerp(-0.0000001, endVec.y, startVec.y); + double startZ = Mth.lerp(-0.0000001, endVec.z, startVec.z); + double endX = Mth.lerp(-0.0000001, startVec.x, endVec.x); + double endY = Mth.lerp(-0.0000001, startVec.y, endVec.y); + double endZ = Mth.lerp(-0.0000001, startVec.z, endVec.z); + int blockX = Mth.floor(endX); + int blockY = Mth.floor(endY); + int blockZ = Mth.floor(endZ); + BlockPos.MutableBlockPos mutablePos = new BlockPos.MutableBlockPos(blockX, blockY, blockZ); + T t = hitFunction.apply(context, mutablePos); + if(t != null) + { + return t; + } + + double deltaX = startX - endX; + double deltaY = startY - endY; + double deltaZ = startZ - endZ; + int signX = Mth.sign(deltaX); + int signY = Mth.sign(deltaY); + int signZ = Mth.sign(deltaZ); + double d9 = signX == 0 ? Double.MAX_VALUE : (double) signX / deltaX; + double d10 = signY == 0 ? Double.MAX_VALUE : (double) signY / deltaY; + double d11 = signZ == 0 ? Double.MAX_VALUE : (double) signZ / deltaZ; + double d12 = d9 * (signX > 0 ? 1.0D - Mth.frac(endX) : Mth.frac(endX)); + double d13 = d10 * (signY > 0 ? 1.0D - Mth.frac(endY) : Mth.frac(endY)); + double d14 = d11 * (signZ > 0 ? 1.0D - Mth.frac(endZ) : Mth.frac(endZ)); + + while(d12 <= 1.0D || d13 <= 1.0D || d14 <= 1.0D) + { + if(d12 < d13) + { + if(d12 < d14) + { + blockX += signX; + d12 += d9; + } + else + { + blockZ += signZ; + d14 += d11; + } + } + else if(d13 < d14) + { + blockY += signY; + d13 += d10; + } + else + { + blockZ += signZ; + d14 += d11; + } + + T t1 = hitFunction.apply(context, mutablePos.set(blockX, blockY, blockZ)); + if(t1 != null) + { + return t1; + } + } + + return p_217300_2_.apply(context); + } + } + + public static class EntityResult + { + private Entity entity; + private Vec3 hitVec; + private boolean headshot; + + public EntityResult(Entity entity, Vec3 hitVec, boolean headshot) + { + this.entity = entity; + this.hitVec = hitVec; + this.headshot = headshot; + } + + /** + * Gets the entity that was hit by the projectile + */ + public Entity getEntity() + { + return this.entity; + } + + /** + * Gets the position the projectile hit + */ + public Vec3 getHitPos() + { + return this.hitVec; + } + + /** + * Gets if this was a headshot + */ + public boolean isHeadshot() + { + return this.headshot; + } + } } diff --git a/src/main/java/net/mcreator/target/entity/RpgRocketEntity.java b/src/main/java/net/mcreator/target/entity/RpgRocketEntity.java index b1c6f4ac6..1dcb6f2e5 100644 --- a/src/main/java/net/mcreator/target/entity/RpgRocketEntity.java +++ b/src/main/java/net/mcreator/target/entity/RpgRocketEntity.java @@ -142,7 +142,7 @@ public class RpgRocketEntity extends AbstractArrow implements ItemSupplier { } super.onHitEntity(result); this.discard(); - } + } @Override public void onHitBlock(BlockHitResult blockHitResult) { diff --git a/src/main/java/net/mcreator/target/entity/TaserBulletProjectileEntity.java b/src/main/java/net/mcreator/target/entity/TaserBulletProjectileEntity.java index 9125a0bb0..8ccad1afa 100644 --- a/src/main/java/net/mcreator/target/entity/TaserBulletProjectileEntity.java +++ b/src/main/java/net/mcreator/target/entity/TaserBulletProjectileEntity.java @@ -143,7 +143,7 @@ public class TaserBulletProjectileEntity extends AbstractArrow implements ItemSu super.onHitEntity(result); TaserBulletDangTouZhiWuJiZhongShiTiShiProcedure.execute(result.getEntity(), this, this.getOwner()); this.discard(); - } + } @Override public void tick() { diff --git a/src/main/java/net/mcreator/target/init/TargetCustomModEntities.java b/src/main/java/net/mcreator/target/init/TargetCustomModEntities.java index 3a937039b..7425b6bc2 100644 --- a/src/main/java/net/mcreator/target/init/TargetCustomModEntities.java +++ b/src/main/java/net/mcreator/target/init/TargetCustomModEntities.java @@ -22,6 +22,6 @@ public class TargetCustomModEntities { public static final RegistryObject> PROJECTILE = ENTITY_TYPES.register("projectile", - () -> EntityType.Builder.of(ProjectileEntity::new, MobCategory.MISC).sized(0.5f, 0.5f).build("projectile")); + () -> EntityType.Builder.of(ProjectileEntity::new, MobCategory.MISC).setTrackingRange(0).sized(0.5f, 0.5f).build("projectile")); }