尝试移植了cgm的延迟补偿,但还有问题

This commit is contained in:
Atsuihsio 2024-05-05 01:19:33 +08:00
parent 9f68619ea0
commit ab27c132ee
8 changed files with 303 additions and 20 deletions

View file

@ -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)
@ -80,13 +166,16 @@ public class ProjectileEntity extends ThrowableItemProjectile {
hitPos = headshotHitPos.get();
headshot = true;
}
if(headshot){
ProjectileHeadshotEntity.execute(this.level(), pResult.getEntity(), this, this.getOwner());
}
}
}
if(hitPos == null)
{
return null;
}
ProjectileHitEntity.execute(this.level(), pResult.getEntity(), this, this.getOwner());
return new EntityResult(entity, hitPos, headshot);
}
@Override
@ -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;
}
}
}

View file

@ -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"));
}

View file

@ -0,0 +1,23 @@
package net.mcreator.target.util.math;
import net.mcreator.target.entity.ProjectileEntity;
import net.minecraft.world.phys.EntityHitResult;
/**
* Author: MrCrayFish
*/
public class ExtendedEntityRayTraceResult extends EntityHitResult
{
private final boolean headshot;
public ExtendedEntityRayTraceResult(ProjectileEntity.EntityResult result)
{
super(result.getEntity(), result.getHitPos());
this.headshot = result.isHeadshot();
}
public boolean isHeadshot()
{
return this.headshot;
}
}