尝试移植了cgm的延迟补偿,但还有问题
This commit is contained in:
parent
9f68619ea0
commit
1ba75053ad
7 changed files with 280 additions and 20 deletions
|
@ -148,7 +148,7 @@ public class BocekarrowEntity extends AbstractArrow implements ItemSupplier {
|
|||
}
|
||||
super.onHitEntity(result);
|
||||
this.discard();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
|
|
|
@ -142,7 +142,7 @@ public class GunGrenadeEntity extends AbstractArrow implements ItemSupplier {
|
|||
}
|
||||
super.onHitEntity(result);
|
||||
this.discard();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHitBlock(BlockHitResult blockHitResult) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<Entity> PROJECTILE_TARGETS = input -> input != null && input.isPickable() && !input.isSpectator();
|
||||
|
||||
private static final Predicate<BlockState> IGNORE_LEAVES = input -> input != null && input.getBlock() instanceof LeavesBlock;
|
||||
protected LivingEntity shooter;
|
||||
protected int shooterId;
|
||||
private float damage;
|
||||
|
||||
public ProjectileEntity(EntityType<? extends ProjectileEntity> 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<Entity> 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<EntityResult> findEntitiesOnPath(Vec3 startVec, Vec3 endVec)
|
||||
{
|
||||
List<EntityResult> hitEntities = new ArrayList<>();
|
||||
List<Entity> 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<Vec3> 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<BlockState> 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> T performRayTrace(ClipContext context, BiFunction<ClipContext, BlockPos, T> hitFunction, Function<ClipContext, T> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,7 +142,7 @@ public class RpgRocketEntity extends AbstractArrow implements ItemSupplier {
|
|||
}
|
||||
super.onHitEntity(result);
|
||||
this.discard();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHitBlock(BlockHitResult blockHitResult) {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -22,6 +22,6 @@ public class TargetCustomModEntities {
|
|||
|
||||
public static final RegistryObject<EntityType<ProjectileEntity>> PROJECTILE =
|
||||
ENTITY_TYPES.register("projectile",
|
||||
() -> EntityType.Builder.<ProjectileEntity>of(ProjectileEntity::new, MobCategory.MISC).sized(0.5f, 0.5f).build("projectile"));
|
||||
() -> EntityType.Builder.<ProjectileEntity>of(ProjectileEntity::new, MobCategory.MISC).setTrackingRange(0).sized(0.5f, 0.5f).build("projectile"));
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue