Improve negative gravity handling on dropped items

This commit is contained in:
Sollace 2021-02-22 15:54:24 +02:00
parent 5821e13728
commit ad74e50e35
9 changed files with 123 additions and 46 deletions

View file

@ -4,6 +4,8 @@ import javax.annotation.Nullable;
import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.DisguiseSpell; import com.minelittlepony.unicopia.ability.magic.spell.DisguiseSpell;
import com.minelittlepony.unicopia.entity.Equine;
import com.minelittlepony.unicopia.entity.ItemImpl;
import com.minelittlepony.unicopia.entity.Living; import com.minelittlepony.unicopia.entity.Living;
import com.minelittlepony.unicopia.entity.behaviour.Disguise; import com.minelittlepony.unicopia.entity.behaviour.Disguise;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
@ -32,7 +34,28 @@ import net.minecraft.util.math.Vec3d;
public class WorldRenderDelegate { public class WorldRenderDelegate {
public static final WorldRenderDelegate INSTANCE = new WorldRenderDelegate(); public static final WorldRenderDelegate INSTANCE = new WorldRenderDelegate();
public boolean onEntityRender(EntityRenderDispatcher dispatcher, Living<?> pony, public boolean onEntityRender(EntityRenderDispatcher dispatcher, Equine<?> pony,
double x, double y, double z, float yaw,
float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light) {
if (pony instanceof ItemImpl) {
matrices.push();
if (pony.getPhysics().isGravityNegative()) {
matrices.translate(0, -((ItemImpl) pony).getMaster().getHeight() * 1.1, 0);
}
return false;
}
if (pony instanceof Living) {
return onLivingRender(dispatcher, (Living<?>)pony, x, y, z, yaw, tickDelta, matrices, vertices, light);
}
return false;
}
private boolean onLivingRender(EntityRenderDispatcher dispatcher, Living<?> pony,
double x, double y, double z, float yaw, double x, double y, double z, float yaw,
float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) { float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) {
@ -84,12 +107,14 @@ public class WorldRenderDelegate {
return false; return false;
} }
public void afterEntityRender(Living<?> pony, MatrixStack matrices) { public void afterEntityRender(Equine<?> pony, MatrixStack matrices) {
if (pony instanceof ItemImpl || pony instanceof Living) {
matrices.pop(); matrices.pop();
if (pony.getPhysics().isGravityNegative()) { if (pony instanceof Living && pony.getPhysics().isGravityNegative()) {
flipAngles(pony.getMaster()); flipAngles(((Living<?>)pony).getMaster());
}
} }
} }

View file

@ -25,12 +25,13 @@ import net.minecraft.nbt.CompoundTag;
public class Creature extends Living<LivingEntity> { public class Creature extends Living<LivingEntity> {
private static final TrackedData<CompoundTag> EFFECT = DataTracker.registerData(LivingEntity.class, TrackedDataHandlerRegistry.TAG_COMPOUND); private static final TrackedData<CompoundTag> EFFECT = DataTracker.registerData(LivingEntity.class, TrackedDataHandlerRegistry.TAG_COMPOUND);
public static final TrackedData<Float> GRAVITY = DataTracker.registerData(LivingEntity.class, TrackedDataHandlerRegistry.FLOAT);
private static final LevelStore LEVELS = Levelled.fixed(0); private static final LevelStore LEVELS = Levelled.fixed(0);
public static void boostrap() {} public static void boostrap() {}
private final Physics physics = new EntityPhysics<>(this); private final Physics physics = new EntityPhysics<>(this, GRAVITY);
public Creature(LivingEntity entity) { public Creature(LivingEntity entity) {
super(entity, EFFECT); super(entity, EFFECT);

View file

@ -10,6 +10,7 @@ import net.minecraft.block.BlockState;
import net.minecraft.block.FenceGateBlock; import net.minecraft.block.FenceGateBlock;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.data.TrackedData;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.particle.BlockStateParticleEffect; import net.minecraft.particle.BlockStateParticleEffect;
import net.minecraft.particle.ParticleTypes; import net.minecraft.particle.ParticleTypes;
@ -20,12 +21,21 @@ import net.minecraft.util.math.Vec3d;
public class EntityPhysics<T extends Owned<? extends Entity>> implements Physics, Copieable<EntityPhysics<T>> { public class EntityPhysics<T extends Owned<? extends Entity>> implements Physics, Copieable<EntityPhysics<T>> {
private float gravity = 1; private final TrackedData<Float> gravity;
protected final T pony; protected final T pony;
public EntityPhysics(T pony) { public EntityPhysics(T pony, TrackedData<Float> gravity) {
this(pony, gravity, true);
}
public EntityPhysics(T pony, TrackedData<Float> gravity, boolean register) {
this.pony = pony; this.pony = pony;
this.gravity = gravity;
if (register) {
this.pony.getMaster().getDataTracker().startTracking(gravity, 1F);
}
} }
@Override @Override
@ -86,7 +96,12 @@ public class EntityPhysics<T extends Owned<? extends Entity>> implements Physics
@Override @Override
public void setBaseGravityModifier(float constant) { public void setBaseGravityModifier(float constant) {
gravity = constant; pony.getMaster().getDataTracker().set(gravity, constant);
}
@Override
public float getBaseGravityModifier() {
return pony.getMaster().getDataTracker().get(gravity);
} }
@Override @Override
@ -97,26 +112,26 @@ public class EntityPhysics<T extends Owned<? extends Entity>> implements Physics
if (((LivingEntity)master).getAttributes() == null) { if (((LivingEntity)master).getAttributes() == null) {
// may be null due to order of execution in the constructor. // may be null due to order of execution in the constructor.
// Will have the default (1) here in any case, so it's safe to ignore the attribute at this point. // Will have the default (1) here in any case, so it's safe to ignore the attribute at this point.
return gravity; return getBaseGravityModifier();
} }
return gravity * (float)((LivingEntity)master).getAttributeValue(PlayerAttributes.ENTITY_GRAVTY_MODIFIER); return getBaseGravityModifier() * (float)((LivingEntity)master).getAttributeValue(PlayerAttributes.ENTITY_GRAVTY_MODIFIER);
} }
return gravity; return getBaseGravityModifier();
} }
@Override @Override
public void copyFrom(EntityPhysics<T> other) { public void copyFrom(EntityPhysics<T> other) {
gravity = other.gravity; setBaseGravityModifier(other.getBaseGravityModifier());
} }
@Override @Override
public void toNBT(CompoundTag compound) { public void toNBT(CompoundTag compound) {
compound.putFloat("gravity", gravity); compound.putFloat("gravity", getBaseGravityModifier());
} }
@Override @Override
public void fromNBT(CompoundTag compound) { public void fromNBT(CompoundTag compound) {
gravity = compound.getFloat("gravity"); setBaseGravityModifier(compound.getFloat("gravity"));
} }
} }

View file

@ -21,26 +21,25 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.particle.ParticleEffect; import net.minecraft.particle.ParticleEffect;
import net.minecraft.particle.ParticleTypes; import net.minecraft.particle.ParticleTypes;
import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResult;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.Tickable;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
public class ItemImpl implements Equine<ItemEntity>, Owned<ItemEntity> { public class ItemImpl implements Equine<ItemEntity>, Owned<ItemEntity> {
private static final TrackedData<Integer> ITEM_RACE = DataTracker.registerData(ItemEntity.class, TrackedDataHandlerRegistry.INTEGER); private static final TrackedData<Integer> ITEM_RACE = DataTracker.registerData(ItemEntity.class, TrackedDataHandlerRegistry.INTEGER);
private static final TrackedData<Float> ITEM_GRAVITY = DataTracker.registerData(ItemEntity.class, TrackedDataHandlerRegistry.FLOAT);
private final ItemEntity owner; private final ItemEntity owner;
private Race serverRace;
private final Physics physics = new EntityPhysics<>(this); private final ItemPhysics physics = new ItemPhysics();
private Race serverRace;
public ItemImpl(ItemEntity owner) { public ItemImpl(ItemEntity owner) {
this.owner = owner; this.owner = owner;
owner.getDataTracker().startTracking(ITEM_GRAVITY, 1F);
owner.getDataTracker().startTracking(ITEM_RACE, Race.HUMAN.ordinal()); owner.getDataTracker().startTracking(ITEM_RACE, Race.HUMAN.ordinal());
} }
@Override
public void tick() {
}
@Override @Override
public boolean beforeUpdate() { public boolean beforeUpdate() {
@ -92,24 +91,15 @@ public class ItemImpl implements Equine<ItemEntity>, Owned<ItemEntity> {
} }
} }
if (physics.isGravityNegative()) {
owner.setNoGravity(true);
owner.setOnGround(owner.verticalCollision);
float g = 0.98f;
if (owner.isOnGround()) {
g *= owner.world.getBlockState(owner.getBlockPos().up()).getBlock().getSlipperiness();
}
owner.setVelocity(owner.getVelocity()
.add(0, physics.calcGravity(-0.04D), 0)
.multiply(g, 1, g));
}
return false; return false;
} }
@Override
public void tick() {
physics.tick();
}
@Override @Override
public Physics getPhysics() { public Physics getPhysics() {
return physics; return physics;
@ -151,6 +141,49 @@ public class ItemImpl implements Equine<ItemEntity>, Owned<ItemEntity> {
ActionResult onGroundTick(IItemEntity entity); ActionResult onGroundTick(IItemEntity entity);
} }
class ItemPhysics extends EntityPhysics<ItemImpl> implements Tickable {
private float serverGravity;
public ItemPhysics() {
super(ItemImpl.this, ITEM_GRAVITY, false);
}
@Override
public void tick() {
if (!owner.world.isClient) {
float gravity = getBaseGravityModifier();
if (gravity != serverGravity) {
serverGravity = gravity;
setBaseGravityModifier(gravity == 0 ? 1 : gravity * 2);
setBaseGravityModifier(gravity);
}
}
if (isGravityNegative() && !owner.getStack().isEmpty()) {
owner.setNoGravity(true);
owner.addVelocity(
0,
0.04
+ calcGravity(-0.04D), // apply our own
0
);
if (!owner.isOnGround()
|| Entity.squaredHorizontalLength(owner.getVelocity()) > 9.999999747378752E-6D) {
float above = 0.98f;
if (owner.verticalCollision) {
above *= owner.world.getBlockState(owner.getBlockPos().up()).getBlock().getSlipperiness();
//above /= 9;
}
owner.setVelocity(owner.getVelocity().multiply(above, 1, above));
}
}
}
}
public interface ClingyItem { public interface ClingyItem {
ClingyItem DEFAULT = stack -> { ClingyItem DEFAULT = stack -> {
return EnchantmentHelper.getLevel(UEnchantments.CLINGY, stack) > 0; return EnchantmentHelper.getLevel(UEnchantments.CLINGY, stack) > 0;

View file

@ -13,6 +13,8 @@ public interface Physics extends NbtSerialisable {
float getGravityModifier(); float getGravityModifier();
float getBaseGravityModifier();
void setBaseGravityModifier(float constant); void setBaseGravityModifier(float constant);
boolean isFlying(); boolean isFlying();

View file

@ -1,5 +1,7 @@
package com.minelittlepony.unicopia.entity.player; package com.minelittlepony.unicopia.entity.player;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.Race;
@ -16,6 +18,8 @@ import net.minecraft.util.registry.Registry;
public class PlayerAttributes implements Tickable { public class PlayerAttributes implements Tickable {
public static final List<EntityAttribute> REGISTRY = new ArrayList<>();
public static final EntityAttribute EXTENDED_REACH_DISTANCE = register("unicopia.pegasus.reach", new ClampedEntityAttribute("player.reachDistance", 0, 0, 10).setTracked(true)); public static final EntityAttribute EXTENDED_REACH_DISTANCE = register("unicopia.pegasus.reach", new ClampedEntityAttribute("player.reachDistance", 0, 0, 10).setTracked(true));
public static final EntityAttribute EXTRA_MINING_SPEED = register("unicopia.earth.mining_speed", new ClampedEntityAttribute("player.miningSpeed", 1, 0, 5).setTracked(true)); public static final EntityAttribute EXTRA_MINING_SPEED = register("unicopia.earth.mining_speed", new ClampedEntityAttribute("player.miningSpeed", 1, 0, 5).setTracked(true));
public static final EntityAttribute ENTITY_GRAVTY_MODIFIER = register("unicopia.player.gravity", (new EntityAttribute("player.gravityModifier", 1) {}).setTracked(true)); public static final EntityAttribute ENTITY_GRAVTY_MODIFIER = register("unicopia.player.gravity", (new EntityAttribute("player.gravityModifier", 1) {}).setTracked(true));
@ -66,6 +70,7 @@ public class PlayerAttributes implements Tickable {
} }
private static EntityAttribute register(String id, EntityAttribute attribute) { private static EntityAttribute register(String id, EntityAttribute attribute) {
REGISTRY.add(attribute);
return Registry.register(Registry.ATTRIBUTE, id, attribute); return Registry.register(Registry.ATTRIBUTE, id, attribute);
} }
} }

View file

@ -4,6 +4,7 @@ import com.minelittlepony.unicopia.FlightType;
import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.ability.magic.Spell; import com.minelittlepony.unicopia.ability.magic.Spell;
import com.minelittlepony.unicopia.entity.Creature;
import com.minelittlepony.unicopia.entity.EntityPhysics; import com.minelittlepony.unicopia.entity.EntityPhysics;
import com.minelittlepony.unicopia.entity.Jumper; import com.minelittlepony.unicopia.entity.Jumper;
import com.minelittlepony.unicopia.entity.player.MagicReserves.Bar; import com.minelittlepony.unicopia.entity.player.MagicReserves.Bar;
@ -47,7 +48,7 @@ public class PlayerPhysics extends EntityPhysics<Pony> implements Tickable, Moti
private final PlayerDimensions dimensions; private final PlayerDimensions dimensions;
public PlayerPhysics(Pony pony) { public PlayerPhysics(Pony pony) {
super(pony); super(pony, Creature.GRAVITY);
dimensions = new PlayerDimensions(pony, this); dimensions = new PlayerDimensions(pony, this);
} }

View file

@ -12,7 +12,6 @@ import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.EntityRenderDispatcher; import net.minecraft.client.render.entity.EntityRenderDispatcher;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
@Mixin(EntityRenderDispatcher.class) @Mixin(EntityRenderDispatcher.class)
abstract class MixinEntityRenderDispatcher { abstract class MixinEntityRenderDispatcher {
@ -21,9 +20,6 @@ abstract class MixinEntityRenderDispatcher {
@Inject(method = RENDER, at = @At("HEAD"), cancellable = true) @Inject(method = RENDER, at = @At("HEAD"), cancellable = true)
private <E extends Entity> void beforeRender(E entity, double x, double y, double z, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo info) { private <E extends Entity> void beforeRender(E entity, double x, double y, double z, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo info) {
if (!(entity instanceof LivingEntity)) {
return;
}
if (WorldRenderDelegate.INSTANCE.onEntityRender((EntityRenderDispatcher)(Object)this, Equine.of(entity), x, y, z, yaw, tickDelta, matrices, vertexConsumers, light)) { if (WorldRenderDelegate.INSTANCE.onEntityRender((EntityRenderDispatcher)(Object)this, Equine.of(entity), x, y, z, yaw, tickDelta, matrices, vertexConsumers, light)) {
info.cancel(); info.cancel();
} }
@ -31,9 +27,6 @@ abstract class MixinEntityRenderDispatcher {
@Inject(method = RENDER, at = @At("RETURN")) @Inject(method = RENDER, at = @At("RETURN"))
private <E extends Entity> void afterRender(E entity, double x, double y, double z, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo info) { private <E extends Entity> void afterRender(E entity, double x, double y, double z, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo info) {
if (!(entity instanceof LivingEntity)) {
return;
}
WorldRenderDelegate.INSTANCE.afterEntityRender(Equine.of(entity), matrices); WorldRenderDelegate.INSTANCE.afterEntityRender(Equine.of(entity), matrices);
} }
} }

View file

@ -46,13 +46,14 @@ import net.minecraft.world.World;
public class MagicProjectileEntity extends ThrownItemEntity implements Magical, Caster<LivingEntity> { public class MagicProjectileEntity extends ThrownItemEntity implements Magical, Caster<LivingEntity> {
private static final TrackedData<Float> DAMAGE = DataTracker.registerData(MagicProjectileEntity.class, TrackedDataHandlerRegistry.FLOAT); private static final TrackedData<Float> DAMAGE = DataTracker.registerData(MagicProjectileEntity.class, TrackedDataHandlerRegistry.FLOAT);
private static final TrackedData<Float> GRAVITY = DataTracker.registerData(MagicProjectileEntity.class, TrackedDataHandlerRegistry.FLOAT);
private static final TrackedData<Boolean> HYDROPHOBIC = DataTracker.registerData(MagicProjectileEntity.class, TrackedDataHandlerRegistry.BOOLEAN); private static final TrackedData<Boolean> HYDROPHOBIC = DataTracker.registerData(MagicProjectileEntity.class, TrackedDataHandlerRegistry.BOOLEAN);
private static final TrackedData<CompoundTag> EFFECT = DataTracker.registerData(MagicProjectileEntity.class, TrackedDataHandlerRegistry.TAG_COMPOUND); private static final TrackedData<CompoundTag> EFFECT = DataTracker.registerData(MagicProjectileEntity.class, TrackedDataHandlerRegistry.TAG_COMPOUND);
private static final LevelStore LEVELS = Levelled.fixed(1); private static final LevelStore LEVELS = Levelled.fixed(1);
private final EffectSync effectDelegate = new EffectSync(this, EFFECT); private final EffectSync effectDelegate = new EffectSync(this, EFFECT);
private final EntityPhysics<MagicProjectileEntity> physics = new EntityPhysics<>(this); private final EntityPhysics<MagicProjectileEntity> physics = new EntityPhysics<>(this, GRAVITY, false);
private BlockPos lastBlockPos; private BlockPos lastBlockPos;
@ -67,7 +68,8 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Magical,
@Override @Override
protected void initDataTracker() { protected void initDataTracker() {
super.initDataTracker(); super.initDataTracker();
getDataTracker().startTracking(DAMAGE, (float)0); getDataTracker().startTracking(GRAVITY, 1F);
getDataTracker().startTracking(DAMAGE, 0F);
getDataTracker().startTracking(EFFECT, new CompoundTag()); getDataTracker().startTracking(EFFECT, new CompoundTag());
getDataTracker().startTracking(HYDROPHOBIC, false); getDataTracker().startTracking(HYDROPHOBIC, false);
} }