Merge pull request #344 from Kebab11noel/fix/gravity

Fix gravity
This commit is contained in:
TheMode 2021-06-29 00:08:40 +02:00 committed by GitHub
commit fbb8c1a819
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 135 additions and 29 deletions

View File

@ -95,9 +95,18 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
protected Vector velocity = new Vector(); // Movement in block per second protected Vector velocity = new Vector(); // Movement in block per second
protected boolean hasPhysics = true; protected boolean hasPhysics = true;
/**
* The amount of drag applied on the Y axle.
* <p>
* Unit: 1/tick
*/
protected double gravityDragPerTick; protected double gravityDragPerTick;
/**
* Acceleration on the Y axle due to gravity
* <p>
* Unit: blocks/tick
*/
protected double gravityAcceleration; protected double gravityAcceleration;
protected double gravityTerminalVelocity;
protected int gravityTickCount; // Number of tick where gravity tick was applied protected int gravityTickCount; // Number of tick where gravity tick was applied
private boolean autoViewable; private boolean autoViewable;
@ -162,6 +171,8 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
Entity.ENTITY_BY_UUID.put(uuid, this); Entity.ENTITY_BY_UUID.put(uuid, this);
this.eventNode = EventNode.value("entity-" + uuid, EventFilter.ENTITY, this::equals); this.eventNode = EventNode.value("entity-" + uuid, EventFilter.ENTITY, this::equals);
initializeDefaultGravity();
} }
public Entity(@NotNull EntityType entityType) { public Entity(@NotNull EntityType entityType) {
@ -527,13 +538,11 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
Vector newVelocityOut = new Vector(); Vector newVelocityOut = new Vector();
// Gravity force // Gravity force
final double gravityY = !hasNoGravity() ? Math.min( final double gravityY = hasNoGravity() ? 0 : gravityAcceleration;
gravityDragPerTick + (gravityAcceleration * (double) gravityTickCount),
gravityTerminalVelocity) : 0;
final Vector deltaPos = new Vector( final Vector deltaPos = new Vector(
getVelocity().getX() / tps, getVelocity().getX() / tps,
(getVelocity().getY() - gravityY) / tps, getVelocity().getY() / tps - gravityY,
getVelocity().getZ() / tps getVelocity().getZ() / tps
); );
@ -594,6 +603,8 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
this.velocity.setX(velocity.getX() * drag); this.velocity.setX(velocity.getX() * drag);
this.velocity.setZ(velocity.getZ() * drag); this.velocity.setZ(velocity.getZ() * drag);
if (!hasNoGravity())
this.velocity.setY(velocity.getY() * (1-gravityDragPerTick));
if (velocity.equals(new Vector())) { if (velocity.equals(new Vector())) {
this.velocity.zero(); this.velocity.zero();
@ -985,15 +996,6 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
return gravityAcceleration; return gravityAcceleration;
} }
/**
* Gets the maximum gravity velocity.
*
* @return the maximum gravity velocity in block
*/
public double getGravityTerminalVelocity() {
return gravityTerminalVelocity;
}
/** /**
* Gets the number of tick this entity has been applied gravity. * Gets the number of tick this entity has been applied gravity.
* *
@ -1008,13 +1010,11 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
* *
* @param gravityDragPerTick the gravity drag per tick in block * @param gravityDragPerTick the gravity drag per tick in block
* @param gravityAcceleration the gravity acceleration in block * @param gravityAcceleration the gravity acceleration in block
* @param gravityTerminalVelocity the gravity terminal velocity (maximum) in block
* @see <a href="https://minecraft.gamepedia.com/Entity#Motion_of_entities">Entities motion</a> * @see <a href="https://minecraft.gamepedia.com/Entity#Motion_of_entities">Entities motion</a>
*/ */
public void setGravity(double gravityDragPerTick, double gravityAcceleration, double gravityTerminalVelocity) { public void setGravity(double gravityDragPerTick, double gravityAcceleration) {
this.gravityDragPerTick = gravityDragPerTick; this.gravityDragPerTick = gravityDragPerTick;
this.gravityAcceleration = gravityAcceleration; this.gravityAcceleration = gravityAcceleration;
this.gravityTerminalVelocity = gravityTerminalVelocity;
} }
/** /**
@ -1643,6 +1643,107 @@ public class Entity implements Viewable, Tickable, EventHandler<EntityEvent>, Da
tag.write(nbtCompound, value); tag.write(nbtCompound, value);
} }
/**
* Sets the Entity's {@link gravityAcceleration} and {@link gravityDragPerTick} fields to
* the default values according to <a href="https://minecraft.fandom.com/wiki/Entity#Motion_of_entities">Motion of entities</a>
*/
@SuppressWarnings("JavadocReference")
private void initializeDefaultGravity() {
// TODO Add support for these values in the data generator
// Acceleration
switch (entityType) {
// 0
case ITEM_FRAME:
this.gravityAcceleration = 0;
break;
// 0.03
case EGG:
case FISHING_BOBBER:
case EXPERIENCE_BOTTLE:
case ENDER_PEARL:
case POTION:
case SNOWBALL:
this.gravityAcceleration = 0.03;
break;
// 0.04
case BOAT:
case TNT:
case FALLING_BLOCK:
case ITEM:
case MINECART:
this.gravityAcceleration = 0.04;
break;
// 0.05
case ARROW:
case SPECTRAL_ARROW:
case TRIDENT:
this.gravityAcceleration = 0.05;
break;
// 0.06
case LLAMA_SPIT:
this.gravityAcceleration = 0.06;
break;
// 0.1
case FIREBALL:
case WITHER_SKULL:
case DRAGON_FIREBALL:
this.gravityAcceleration = 0.1;
break;
// 0.08
default:
this.gravityAcceleration = 0.08;
break;
}
// Drag
switch (entityType) {
// 0
case BOAT:
this.gravityDragPerTick = 0;
break;
// 0.01
case LLAMA_SPIT:
case ENDER_PEARL:
case POTION:
case SNOWBALL:
case EGG:
case TRIDENT:
case SPECTRAL_ARROW:
case ARROW:
this.gravityDragPerTick = 0.01;
break;
// 0.05
case MINECART:
this.gravityDragPerTick = 0.05;
break;
// 0.08
case FISHING_BOBBER:
this.gravityDragPerTick = 0.08;
break;
// 0.02
default:
this.gravityDragPerTick = 0.02;
break;
}
}
/**
* Applies knockback to the entity
*
* @param strength the strength of the knockback, 0.4 is the vanilla value for a bare hand hit
* @param x knockback on x axle, for default knockback use the following formula <pre>sin(attacker.yaw * (pi/180))</pre>
* @param z knockback on z axle, for default knockback use the following formula <pre>-cos(attacker.yaw * (pi/180))</pre>
*/
public void takeKnockback(final float strength, final double x, final double z) {
if (strength > 0) {
//TODO check possible side effects of unnatural TPS (other than 20TPS)
final Vector velocityModifier = new Vector(x, 0d, z).normalize().multiply(strength * MinecraftServer.TICK_PER_SECOND / 2);
this.velocity.setX(velocity.getX() / 2d - velocityModifier.getX());
this.velocity.setY(onGround ? Math.min(.4d, velocity.getY() / 2d + strength) * MinecraftServer.TICK_PER_SECOND : velocity.getY());
this.velocity.setZ(velocity.getZ() / 2d - velocityModifier.getZ());
}
}
public enum Pose { public enum Pose {
STANDING, STANDING,
FALL_FLYING, FALL_FLYING,

View File

@ -47,7 +47,6 @@ public class EntityProjectile extends Entity {
if (getEntityMeta() instanceof ProjectileMeta) { if (getEntityMeta() instanceof ProjectileMeta) {
((ProjectileMeta) getEntityMeta()).setShooter(this.shooter); ((ProjectileMeta) getEntityMeta()).setShooter(this.shooter);
} }
setGravity(0.02f, 0.04f, 1.96f);
} }
@Nullable @Nullable

View File

@ -17,7 +17,6 @@ public class ExperienceOrb extends Entity {
public ExperienceOrb(short experienceCount, @NotNull Position spawnPosition) { public ExperienceOrb(short experienceCount, @NotNull Position spawnPosition) {
super(EntityType.EXPERIENCE_ORB, spawnPosition); super(EntityType.EXPERIENCE_ORB, spawnPosition);
setGravity(0.02f, 0.04f, 1.96f);
setBoundingBox(0.5f, 0.5f, 0.5f); setBoundingBox(0.5f, 0.5f, 0.5f);
//todo vanilla sets random velocity here? //todo vanilla sets random velocity here?
this.experienceCount = experienceCount; this.experienceCount = experienceCount;

View File

@ -43,7 +43,6 @@ public class ItemEntity extends Entity {
public ItemEntity(@NotNull ItemStack itemStack, @NotNull Position spawnPosition) { public ItemEntity(@NotNull ItemStack itemStack, @NotNull Position spawnPosition) {
super(EntityType.ITEM, spawnPosition); super(EntityType.ITEM, spawnPosition);
setItemStack(itemStack); setItemStack(itemStack);
setGravity(0.02f, 0.04f, 1.96f);
setBoundingBox(0.25f, 0.25f, 0.25f); setBoundingBox(0.25f, 0.25f, 0.25f);
} }

View File

@ -90,7 +90,6 @@ public class LivingEntity extends Entity implements EquipmentHandler {
*/ */
public LivingEntity(@NotNull EntityType entityType, @NotNull UUID uuid) { public LivingEntity(@NotNull EntityType entityType, @NotNull UUID uuid) {
this(entityType, uuid, new Position()); this(entityType, uuid, new Position());
setGravity(0.02f, 0.08f, 3.92f);
initEquipments(); initEquipments();
} }
@ -104,7 +103,6 @@ public class LivingEntity extends Entity implements EquipmentHandler {
@Deprecated @Deprecated
public LivingEntity(@NotNull EntityType entityType, @NotNull UUID uuid, @NotNull Position spawnPosition) { public LivingEntity(@NotNull EntityType entityType, @NotNull UUID uuid, @NotNull Position spawnPosition) {
super(entityType, uuid, spawnPosition); super(entityType, uuid, spawnPosition);
setGravity(0.02f, 0.08f, 3.92f);
initEquipments(); initEquipments();
} }
@ -781,4 +779,18 @@ public class LivingEntity extends Entity implements EquipmentHandler {
return null; return null;
} }
/**
* Applies knockback
* <p>
* Note: The strength is reduced based on knockback resistance
*
* @param strength the strength of the knockback, 0.4 is the vanilla value for a bare hand hit
* @param x knockback on x axle, for default knockback use the following formula <pre>sin(attacker.yaw * (pi/180))</pre>
* @param z knockback on z axle, for default knockback use the following formula <pre>-cos(attacker.yaw * (pi/180))</pre>
*/
@Override
public void takeKnockback(float strength, final double x, final double z) {
strength *= 1 - getAttributeValue(Attribute.KNOCKBACK_RESISTANCE);
super.takeKnockback(strength, x, z);
}
} }

View File

@ -50,16 +50,12 @@ public class PlayerInit {
.addListener(EntityAttackEvent.class, event -> { .addListener(EntityAttackEvent.class, event -> {
final Entity source = event.getEntity(); final Entity source = event.getEntity();
final Entity entity = event.getTarget(); final Entity entity = event.getTarget();
entity.takeKnockback(0.4f, Math.sin(source.getPosition().getYaw() * 0.017453292), -Math.cos(source.getPosition().getYaw() * 0.017453292));
if (entity instanceof Player) { if (entity instanceof Player) {
Player target = (Player) entity; Player target = (Player) entity;
Vector velocity = source.getPosition().clone().getDirection().multiply(4);
velocity.setY(3.5f);
target.setVelocity(velocity);
target.damage(DamageType.fromEntity(source), 5); target.damage(DamageType.fromEntity(source), 5);
} else {
Vector velocity = source.getPosition().clone().getDirection().multiply(3);
velocity.setY(3f);
entity.setVelocity(velocity);
} }
if (source instanceof Player) { if (source instanceof Player) {