Physics rewrite for better gravity manipulation

This commit is contained in:
Sollace 2020-05-10 17:18:45 +02:00
parent 298eddb9c2
commit 5b7f298147
41 changed files with 812 additions and 741 deletions

View file

@ -8,7 +8,6 @@ import javax.annotation.Nullable;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.entity.Updatable;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.network.MsgPlayerAbility;
import com.minelittlepony.unicopia.network.Channel;
@ -16,8 +15,9 @@ import com.minelittlepony.unicopia.util.NbtSerialisable;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.Identifier;
import net.minecraft.util.Tickable;
public class AbilityDispatcher implements Updatable, NbtSerialisable {
public class AbilityDispatcher implements Tickable, NbtSerialisable {
private final Pony player;
@ -88,7 +88,7 @@ public class AbilityDispatcher implements Updatable, NbtSerialisable {
}
@Override
public void onUpdate() {
public void tick() {
getActiveAbility().ifPresent(this::activate);
}

View file

@ -28,8 +28,8 @@ public class CarryAbility implements Ability<Hit> {
}
@Override
public boolean canUse(Race playerSpecies) {
return playerSpecies.canFly();
public boolean canUse(Race race) {
return race.canFly();
}
@Override

View file

@ -74,7 +74,7 @@ public class ChangelingDisguiseAbility extends ChangelingFeedAbility {
return disc;
}).setDisguise(looked);
iplayer.sendCapabilities(true);
iplayer.setDirty();
}
@Override

View file

@ -42,8 +42,8 @@ public class ChangelingFeedAbility implements Ability<Hit> {
}
@Override
public boolean canUse(Race playerSpecies) {
return playerSpecies == Race.CHANGELING;
public boolean canUse(Race race) {
return race == Race.CHANGELING;
}
@Nullable

View file

@ -33,8 +33,8 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
}
@Override
public boolean canUse(Race playerSpecies) {
return playerSpecies == Race.EARTH;
public boolean canUse(Race race) {
return race == Race.EARTH;
}
@Override

View file

@ -64,8 +64,8 @@ public class EarthPonyStompAbility implements Ability<Multi> {
}
@Override
public boolean canUse(Race playerSpecies) {
return playerSpecies.canUseEarth();
public boolean canUse(Race race) {
return race.canUseEarth();
}
@Nullable

View file

@ -25,8 +25,8 @@ public class PegasusCloudInteractionAbility implements Ability<Numeric> {
}
@Override
public boolean canUse(Race playerSpecies) {
return playerSpecies.canInteractWithClouds();
public boolean canUse(Race race) {
return race.canInteractWithClouds();
}
@Override

View file

@ -23,8 +23,8 @@ public class UnicornCastingAbility implements Ability<Hit> {
}
@Override
public boolean canUse(Race playerSpecies) {
return playerSpecies.canCast();
public boolean canUse(Race race) {
return race.canCast();
}
@Override

View file

@ -0,0 +1,67 @@
package com.minelittlepony.unicopia.client.render;
import com.minelittlepony.unicopia.entity.player.Pony;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
public class WorldRenderDelegate {
public static final WorldRenderDelegate INSTANCE = new WorldRenderDelegate();
public void beforeEntityRender(Pony pony, MatrixStack matrices, double x, double y, double z) {
if (pony.getPhysics().isGravityNegative()) {
matrices.push();
Entity entity = pony.getOwner();
matrices.translate(x, y, z);
matrices.translate(0, entity.getHeight(), 0);
matrices.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(180));
matrices.translate(-x, -y, -z);
flipAngles(entity);
}
}
public void afterEntityRender(Pony pony, MatrixStack matrices) {
if (pony.getPhysics().isGravityNegative()) {
matrices.pop();
flipAngles(pony.getOwner());
}
}
private void flipAngles(Entity entity) {
if (MinecraftClient.getInstance().options.perspective > 0) {
entity.prevYaw *= -1;
entity.yaw *= -1;
if (entity instanceof LivingEntity) {
LivingEntity living = (LivingEntity)entity;
living.bodyYaw = -living.bodyYaw;
living.prevBodyYaw = -living.prevBodyYaw;
living.headYaw = -living.headYaw;
living.prevHeadYaw = -living.prevHeadYaw;
}
}
entity.prevPitch *= -1;
entity.pitch *= -1;
}
public void applyWorldTransform(MatrixStack matrices, float tickDelta) {
PlayerEntity player = MinecraftClient.getInstance().player;
if (player != null && MinecraftClient.getInstance().cameraEntity == player) {
float roll = Pony.of(player).getCamera().calculateRoll();
matrices.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(roll));
}
}
}

View file

@ -39,7 +39,7 @@ class GravityCommand {
Pony iplayer = Pony.of(player);
float gravity = iplayer.getGravity().getGravitationConstant();
float gravity = iplayer.getPhysics().getGravityModifier();
if (source.getPlayer() != player) {
translationKey += ".other";
@ -54,8 +54,8 @@ class GravityCommand {
Pony iplayer = Pony.of(player);
iplayer.getGravity().setGraviationConstant(gravity);
iplayer.sendCapabilities(true);
iplayer.getPhysics().setGravityModifier(gravity);
iplayer.setDirty();
if (isSelf) {
player.sendMessage(new TranslatableText(translationKey, gravity));

View file

@ -49,7 +49,7 @@ class SpeciesCommand {
if (race.isPermitted(player)) {
Pony pony = Pony.of(player);
pony.setSpecies(race);
pony.sendCapabilities(false);
pony.setDirty();
Text formattedName = new TranslatableText(race.name().toLowerCase());

View file

@ -1,8 +1,8 @@
package com.minelittlepony.unicopia.ducks;
import com.minelittlepony.unicopia.entity.ItemEntityCapabilities;
import com.minelittlepony.unicopia.entity.ItemImpl;
public interface IItemEntity extends PonyContainer<ItemEntityCapabilities> {
public interface IItemEntity extends PonyContainer<ItemImpl> {
int getAge();

View file

@ -10,9 +10,9 @@ import com.minelittlepony.unicopia.magic.Caster;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
public interface PonyContainer<T extends Ponylike> {
public interface PonyContainer<T extends Ponylike<?>> {
Ponylike create();
Ponylike<?> create();
T get();
@ -28,7 +28,7 @@ public interface PonyContainer<T extends Ponylike> {
}
@SuppressWarnings("unchecked")
static <E extends Entity, T extends Ponylike> Optional<PonyContainer<T>> of(Entity entity) {
static <E extends Entity, T extends Ponylike<?>> Optional<PonyContainer<T>> of(Entity entity) {
if (entity instanceof PonyContainer) {
return Optional.of(((PonyContainer<T>)entity));
}

View file

@ -15,7 +15,7 @@ import net.minecraft.entity.data.TrackedData;
import net.minecraft.entity.data.TrackedDataHandlerRegistry;
import net.minecraft.nbt.CompoundTag;
public class LivingEntityCapabilities implements RaceContainer<LivingEntity>, Caster<LivingEntity> {
public class Creature implements Ponylike<LivingEntity>, Caster<LivingEntity> {
private static final TrackedData<CompoundTag> EFFECT = DataTracker.registerData(LivingEntity.class, TrackedDataHandlerRegistry.TAG_COMPOUND);
@ -23,9 +23,11 @@ public class LivingEntityCapabilities implements RaceContainer<LivingEntity>, Ca
private final EffectSync effectDelegate = new EffectSync(this, EFFECT);
private final Physics physics = new EntityPhysics<>(this);
private final LivingEntity entity;
public LivingEntityCapabilities(LivingEntity entity) {
public Creature(LivingEntity entity) {
this.entity = entity;
entity.getDataTracker().startTracking(EFFECT, new CompoundTag());
@ -36,6 +38,11 @@ public class LivingEntityCapabilities implements RaceContainer<LivingEntity>, Ca
return Race.HUMAN;
}
@Override
public Physics getPhysics() {
return physics;
}
@Override
public void setSpecies(Race race) {
}
@ -56,7 +63,7 @@ public class LivingEntityCapabilities implements RaceContainer<LivingEntity>, Ca
}
@Override
public void onUpdate() {
public void tick() {
if (hasEffect()) {
AttachedMagicEffect effect = getEffect(AttachedMagicEffect.class, true);
@ -72,11 +79,6 @@ public class LivingEntityCapabilities implements RaceContainer<LivingEntity>, Ca
}
}
@Override
public void onDimensionalTravel(int destinationDimension) {
}
@Override
public void setOwner(LivingEntity owner) {
@ -111,6 +113,7 @@ public class LivingEntityCapabilities implements RaceContainer<LivingEntity>, Ca
if (effect != null) {
compound.put("effect", SpellRegistry.instance().serializeEffectToNBT(effect));
}
physics.toNBT(compound);
}
@Override
@ -118,5 +121,6 @@ public class LivingEntityCapabilities implements RaceContainer<LivingEntity>, Ca
if (compound.contains("effect")) {
setEffect(SpellRegistry.instance().createEffectFromNBT(compound.getCompound("effect")));
}
physics.fromNBT(compound);
}
}

View file

@ -40,7 +40,7 @@ import net.minecraft.util.math.Vec3d;
import net.minecraft.world.GameRules;
import net.minecraft.world.World;
public class CuccoonEntity extends LivingEntity implements IMagicals, InAnimate {
public class CuccoonEntity extends LivingEntity implements IMagicals, InAnimate, Trap {
private static final TrackedData<Integer> STRUGGLE_COUNT = DataTracker.registerData(CuccoonEntity.class, TrackedDataHandlerRegistry.INTEGER);
@ -206,6 +206,7 @@ public class CuccoonEntity extends LivingEntity implements IMagicals, InAnimate
return true;
}
@Override
public boolean attemptDismount(Entity captive) {
if (captive.isSneaking() != captiveLastSneakState) {
setStruggleCount(getStruggleCount() + 1);

View file

@ -0,0 +1,101 @@
package com.minelittlepony.unicopia.entity;
import net.minecraft.block.Block;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.block.FenceGateBlock;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.particle.BlockStateParticleEffect;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.tag.BlockTags;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
public class EntityPhysics<T extends Ponylike<?> & Owned<? extends Entity>> implements Physics {
private float gravity = 1;
protected final T pony;
public EntityPhysics(T pony) {
this.pony = pony;
}
@Override
public boolean isFlying() {
return false;
}
@Override
public double calcGravity(double worldConstant) {
return worldConstant * gravity;
}
@Override
public BlockPos getHeadPosition() {
pony.getOwner().onGround = false;
int i = MathHelper.floor(pony.getOwner().getX());
int j = MathHelper.floor(pony.getOwner().getY() + pony.getOwner().getHeight() + 0.20000000298023224D);
int k = MathHelper.floor(pony.getOwner().getZ());
BlockPos blockPos = new BlockPos(i, j, k);
if (pony.getOwner().world.getBlockState(blockPos).isAir()) {
BlockPos blockPos2 = blockPos.down();
BlockState blockState = pony.getOwner().world.getBlockState(blockPos2);
Block block = blockState.getBlock();
if (block.matches(BlockTags.FENCES) || block.matches(BlockTags.WALLS) || block instanceof FenceGateBlock) {
pony.getOwner().onGround = true;
return blockPos2;
}
} else {
pony.getOwner().onGround = true;
}
return blockPos;
}
@Override
public void spawnSprintingParticles() {
Entity entity = pony.getOwner();
BlockState state = entity.world.getBlockState(getHeadPosition());
if (state.getRenderType() != BlockRenderType.INVISIBLE) {
Vec3d vel = entity.getVelocity();
entity.world.addParticle(new BlockStateParticleEffect(ParticleTypes.BLOCK, state),
entity.getX() + (entity.world.random.nextFloat() - 0.5D) * entity.getWidth(),
entity.getY() + entity.getHeight() - 0.1D,
entity.getZ() + (entity.world.random.nextFloat() - 0.5D) * entity.getWidth(),
vel.x * -4, -1.5D, vel.z * -4);
}
}
@Override
public void setGravityModifier(float constant) {
gravity = constant;
}
@Override
public float getGravityModifier() {
return gravity;
}
@Override
public void toNBT(CompoundTag compound) {
if (gravity != 0) {
compound.putFloat("gravity", gravity);
}
}
@Override
public void fromNBT(CompoundTag compound) {
if (compound.contains("gravity")) {
gravity = compound.getFloat("gravity");
} else {
gravity = 0;
}
}
}

View file

@ -11,19 +11,21 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.ActionResult;
public class ItemEntityCapabilities implements RaceContainer<ItemEntity>, Owned<ItemEntity> {
public class ItemImpl implements Ponylike<ItemEntity>, Owned<ItemEntity> {
private static final TrackedData<Integer> ITEM_RACE = DataTracker.registerData(ItemEntity.class, TrackedDataHandlerRegistry.INTEGER);
private final ItemEntity owner;
private Race serverRace;
public ItemEntityCapabilities(ItemEntity owner) {
private final Physics physics = new EntityPhysics<>(this);
public ItemImpl(ItemEntity owner) {
this.owner = owner;
owner.getDataTracker().startTracking(ITEM_RACE, Race.HUMAN.ordinal());
}
@Override
public void onUpdate() {
public void tick() {
}
@Override
@ -47,6 +49,11 @@ public class ItemEntityCapabilities implements RaceContainer<ItemEntity>, Owned<
return false;
}
@Override
public Physics getPhysics() {
return physics;
}
@Override
public Race getSpecies() {
return Race.fromId(getOwner().getDataTracker().get(ITEM_RACE));
@ -60,12 +67,14 @@ public class ItemEntityCapabilities implements RaceContainer<ItemEntity>, Owned<
@Override
public void toNBT(CompoundTag compound) {
compound.putString("owner_species", getSpecies().name());
physics.toNBT(compound);
}
@Override
public void fromNBT(CompoundTag compound) {
setSpecies(Race.fromName(compound.getString("owner_species")));
physics.fromNBT(compound);
}
@Override
@ -73,11 +82,6 @@ public class ItemEntityCapabilities implements RaceContainer<ItemEntity>, Owned<
}
@Override
public void onDimensionalTravel(int destinationDimension) {
}
@Override
public ItemEntity getOwner() {
return owner;

View file

@ -0,0 +1,28 @@
package com.minelittlepony.unicopia.entity;
import com.minelittlepony.unicopia.util.NbtSerialisable;
import net.minecraft.util.math.BlockPos;
public interface Physics extends NbtSerialisable {
double calcGravity(double worldConstant);
float getGravityModifier();
void setGravityModifier(float constant);
boolean isFlying();
BlockPos getHeadPosition();
void spawnSprintingParticles();
default boolean isGravityNegative() {
return getGravityModifier() < 0;
}
default int getGravitySignum() {
return (int)Math.signum(getGravityModifier());
}
}

View file

@ -8,13 +8,14 @@ import com.minelittlepony.unicopia.util.NbtSerialisable;
import net.minecraft.entity.Entity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.util.Tickable;
public interface Ponylike extends NbtSerialisable, Updatable {
public interface Ponylike<T extends Entity> extends NbtSerialisable, Tickable {
Race getSpecies();
void setSpecies(Race race);
Physics getPhysics();
void onDimensionalTravel(int destinationDimension);
void setSpecies(Race race);
/**
* Returns true if this player is fully invisible.
@ -54,7 +55,7 @@ public interface Ponylike extends NbtSerialisable, Updatable {
}
@Nullable
static <T extends Ponylike> T of(Entity entity) {
static <T extends Ponylike<?>> T of(Entity entity) {
return PonyContainer.<Entity, T>of(entity)
.map(PonyContainer::get)
.orElse(null);

View file

@ -1,12 +0,0 @@
package com.minelittlepony.unicopia.entity;
import net.minecraft.entity.Entity;
/**
* Generic container for an entity that has a race.
*
* @param <T> The type of owner
*/
public interface RaceContainer<T extends Entity> extends Ponylike {
}

View file

@ -1,12 +0,0 @@
package com.minelittlepony.unicopia.entity;
/**
* Interface for objects that receive regular updates.
*/
@FunctionalInterface
public interface Updatable {
/**
* Called to update the internal logic.
*/
void onUpdate();
}

View file

@ -0,0 +1,32 @@
package com.minelittlepony.unicopia.entity.player;
public class ManaContainer implements MagicReserves {
private final Pony pony;
public ManaContainer(Pony pony) {
this.pony = pony;
pony.getOwner().getDataTracker().startTracking(Pony.ENERGY, 0F);
pony.getOwner().getDataTracker().startTracking(Pony.EXERTION, 0F);
}
@Override
public float getExertion() {
return pony.getOwner().getDataTracker().get(Pony.EXERTION);
}
@Override
public void setExertion(float exertion) {
pony.getOwner().getDataTracker().set(Pony.EXERTION, Math.max(0, exertion));
}
@Override
public float getEnergy() {
return pony.getOwner().getDataTracker().get(Pony.ENERGY);
}
@Override
public void setEnergy(float energy) {
pony.getOwner().getDataTracker().set(Pony.ENERGY, Math.max(0, energy));
}
}

View file

@ -1,9 +1,9 @@
package com.minelittlepony.unicopia.entity;
package com.minelittlepony.unicopia.entity.player;
/**
* Interface for controlling flight.
*/
public interface FlightControl {
public interface Motion {
/**
* True is we're currently flying.
*/
@ -14,4 +14,6 @@ public interface FlightControl {
float getFlightDuration();
boolean isExperienceCritical();
PlayerDimensions getDimensions();
}

View file

@ -18,19 +18,19 @@ public class PlayerCamera extends MotionCompositor {
double roll = baseRoll;
if (player.getFlight().isFlying()) {
if (player.getMotion().isFlying()) {
Vec3d vel = player.getOwner().getVelocity();
roll -= super.calculateRoll(player.getOwner(), vel.x, vel.y, vel.z);
}
if (player.getGravity().getGravitationConstant() < 0) {
if (player.getPhysics().isGravityNegative()) {
roll = -roll;
roll += 180;
}
if (player.getEntity().age > 10) {
roll = player.getInterpolator().interpolate("roll", (float)roll, 250);
roll = player.getInterpolator().interpolate("roll", (float)roll, 50);
}
return (float)roll;
@ -45,7 +45,7 @@ public class PlayerCamera extends MotionCompositor {
}
public double calculateFieldOfView(double fov) {
fov += player.getMagicalReserves().getExertion() / 5;
fov += player.getMagicalReserves().getExertion() / 5F;
fov += getEnergyAddition();
return fov;

View file

@ -6,7 +6,7 @@ import com.minelittlepony.unicopia.magic.MagicEffect;
import net.minecraft.entity.EntityDimensions;
import net.minecraft.entity.EntityPose;
public final class PlayerDimensionsDelegate {
public final class PlayerDimensions {
private float defaultEyeHeight;
private float defaultBodyHeight;
@ -14,10 +14,13 @@ public final class PlayerDimensionsDelegate {
private float lastTargetEyeHeight;
private float lastTargetBodyHeight;
private final GravityDelegate gravity;
private final PlayerPhysics physics;
public PlayerDimensionsDelegate(GravityDelegate gravity) {
this.gravity = gravity;
private final Pony pony;
public PlayerDimensions(Pony pony, PlayerPhysics gravity) {
this.pony = pony;
this.physics = gravity;
}
public float getActiveEyeHeight(float original) {
@ -46,11 +49,11 @@ public final class PlayerDimensionsDelegate {
private float calculateTargetEyeHeightWithGravity(float targetBodyHeight) {
float height = calculateTargetEyeHeight();
if (gravity.getGravitationConstant() < 0 && gravity.player.getOwner().isSneaking()) {
if (physics.isGravityNegative() && pony.getOwner().isSneaking()) {
height += 0.2F;
}
if (gravity.getGravitationConstant() < 0) {
if (physics.isGravityNegative()) {
height = targetBodyHeight - height;
}
@ -58,17 +61,17 @@ public final class PlayerDimensionsDelegate {
}
private float calculateTargetEyeHeight() {
if (gravity.player.hasEffect()) {
MagicEffect effect = gravity.player.getEffect();
if (pony.hasEffect()) {
MagicEffect effect = pony.getEffect();
if (!effect.isDead() && effect instanceof HeightPredicate) {
float val = ((HeightPredicate)effect).getTargetEyeHeight(gravity.player);
float val = ((HeightPredicate)effect).getTargetEyeHeight(pony);
if (val > 0) {
return val;
}
}
}
if (gravity.isFlying && gravity.isRainboom()) {
if (physics.isFlying && physics.isRainboom()) {
return 0.5F;
}
@ -76,17 +79,17 @@ public final class PlayerDimensionsDelegate {
}
private float calculateTargetBodyHeight() {
if (gravity.player.hasEffect()) {
MagicEffect effect = gravity.player.getEffect();
if (pony.hasEffect()) {
MagicEffect effect = pony.getEffect();
if (!effect.isDead() && effect instanceof HeightPredicate) {
float val = ((HeightPredicate)effect).getTargetBodyHeight(gravity.player);
float val = ((HeightPredicate)effect).getTargetBodyHeight(pony);
if (val > 0) {
return val;
}
}
}
if (gravity.isFlying && gravity.isRainboom()) {
if (physics.isFlying && physics.isRainboom()) {
return defaultBodyHeight / 2;
}

View file

@ -1,443 +0,0 @@
package com.minelittlepony.unicopia.entity.player;
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.ability.AbilityDispatcher;
import com.minelittlepony.unicopia.enchanting.PageOwner;
import com.minelittlepony.unicopia.entity.FlightControl;
import com.minelittlepony.unicopia.entity.Trap;
import com.minelittlepony.unicopia.magic.Affinity;
import com.minelittlepony.unicopia.magic.AttachedMagicEffect;
import com.minelittlepony.unicopia.magic.HeldMagicEffect;
import com.minelittlepony.unicopia.magic.MagicEffect;
import com.minelittlepony.unicopia.magic.MagicalItem;
import com.minelittlepony.unicopia.magic.spell.SpellRegistry;
import com.minelittlepony.unicopia.network.Channel;
import com.minelittlepony.unicopia.network.EffectSync;
import com.minelittlepony.unicopia.network.MsgPlayerCapabilities;
import com.minelittlepony.unicopia.toxin.Toxicity;
import com.minelittlepony.unicopia.toxin.Toxin;
import com.minelittlepony.util.BasicEasingInterpolator;
import com.minelittlepony.util.IInterpolator;
import com.mojang.datafixers.util.Either;
import net.minecraft.client.network.packet.EntityPassengersSetS2CPacket;
import net.minecraft.entity.Entity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.data.DataTracker;
import net.minecraft.entity.data.TrackedData;
import net.minecraft.entity.data.TrackedDataHandlerRegistry;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerEntity.SleepFailureReason;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.Hand;
import net.minecraft.util.Unit;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
public class PlayerImpl implements Pony, MagicReserves {
private static final TrackedData<Integer> PLAYER_RACE = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.INTEGER);
private static final TrackedData<Float> ENERGY = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.FLOAT);
private static final TrackedData<Float> EXERTION = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.FLOAT);
private static final TrackedData<CompoundTag> EFFECT = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.TAG_COMPOUND);
private static final TrackedData<CompoundTag> HELD_EFFECT = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.TAG_COMPOUND);
private final PlayerPageStats pageStates = new PlayerPageStats();
private final AbilityDispatcher powers = new AbilityDispatcher(this);
private final GravityDelegate gravity = new GravityDelegate(this);
private final PlayerAttributes attributes = new PlayerAttributes();
private final PlayerCamera view = new PlayerCamera(this);
private final PlayerInventory inventory = new PlayerInventory(this);
private final EffectSync effectDelegate = new EffectSync(this, EFFECT);
private final EffectSync heldEffectDelegate = new EffectSync(this, HELD_EFFECT);
private final IInterpolator interpolator = new BasicEasingInterpolator();
private float nextStepDistance = 1;
private final PlayerEntity entity;
private boolean dirty = false;
private boolean invisible = false;
public PlayerImpl(PlayerEntity player) {
this.entity = player;
player.getDataTracker().startTracking(PLAYER_RACE, Race.EARTH.ordinal());
player.getDataTracker().startTracking(EXERTION, 0F);
player.getDataTracker().startTracking(ENERGY, 0F);
player.getDataTracker().startTracking(EFFECT, new CompoundTag());
player.getDataTracker().startTracking(HELD_EFFECT, new CompoundTag());
player.getAttributes().register(PlayerAttributes.EXTENDED_REACH_DISTANCE);
}
@Override
public Race getSpecies() {
if (getOwner() == null) {
return Race.HUMAN;
}
return Race.fromId(getOwner().getDataTracker().get(PLAYER_RACE));
}
@Override
public void setSpecies(Race race) {
race = race.validate(entity);
entity.getDataTracker().set(PLAYER_RACE, race.ordinal());
gravity.updateFlightStat(entity, entity.abilities.flying);
entity.sendAbilitiesUpdate();
}
@Override
public MagicReserves getMagicalReserves() {
return this;
}
@Override
public float getExertion() {
return getOwner().getDataTracker().get(EXERTION);
}
@Override
public void setExertion(float exertion) {
entity.getDataTracker().set(EXERTION, Math.max(0, exertion));
}
@Override
public float getEnergy() {
return entity.getDataTracker().get(ENERGY);
}
@Override
public void setEnergy(float energy) {
entity.getDataTracker().set(ENERGY, Math.max(0, energy));
}
@Override
public boolean isInvisible() {
return invisible && hasEffect();
}
@Override
public void setInvisible(boolean invisible) {
this.invisible = invisible;
}
@Nullable
public HeldMagicEffect getHeldEffect(ItemStack stack) {
if (!getSpecies().canCast()) {
heldEffectDelegate.set(null);
return null;
}
HeldMagicEffect heldEffect = heldEffectDelegate.get(HeldMagicEffect.class, true);
if (heldEffect == null || !heldEffect.getName().equals(SpellRegistry.getKeyFromStack(stack))) {
heldEffect = SpellRegistry.instance().getHeldFrom(stack);
heldEffectDelegate.set(heldEffect);
}
return heldEffect;
}
@Override
public Affinity getAffinity() {
return Affinity.NEUTRAL;
}
@Override
public void sendCapabilities(boolean full) {
dirty = false;
if (entity instanceof ServerPlayerEntity) {
System.out.println("Sending capabilities for player");
Channel.BROADCAST_CAPABILITIES.send(new MsgPlayerCapabilities(full, this));
}
}
@Override
public void onDimensionalTravel(int destinationDimension) {
if (!getWorld().isClient()) {
dirty = true;
}
}
@Override
public AbilityDispatcher getAbilities() {
return powers;
}
@Override
public PageOwner getPages() {
return pageStates;
}
@Override
public GravityDelegate getGravity() {
return gravity;
}
@Override
public float getExtendedReach() {
return (float)entity.getAttributeInstance(PlayerAttributes.EXTENDED_REACH_DISTANCE).getValue();
}
@Override
public FlightControl getFlight() {
return gravity;
}
@Override
public PlayerCamera getCamera() {
return view;
}
@Override
public IInterpolator getInterpolator() {
return interpolator;
}
@Override
public boolean beforeUpdate() {
if (entity.world.isClient()) {
if (entity.hasVehicle() && entity.isSneaking()) {
Entity ridee = entity.getVehicle();
if (ridee instanceof Trap) {
if (((Trap)ridee).attemptDismount(entity)) {
entity.stopRiding();
} else {
entity.setSneaking(false);
}
} else {
entity.stopRiding();
if (ridee instanceof ServerPlayerEntity) {
((ServerPlayerEntity)ridee).networkHandler.sendPacket(new EntityPassengersSetS2CPacket(ridee));
}
}
}
}
powers.onUpdate();
inventory.onUpdate();
return false;
}
@Override
public void onUpdate() {
gravity.onUpdate();
if (hasEffect()) {
AttachedMagicEffect effect = getEffect(AttachedMagicEffect.class, true);
if (effect != null) {
if (entity.getEntityWorld().isClient()) {
effect.renderOnPerson(this);
}
if (!effect.updateOnPerson(this)) {
setEffect(null);
}
}
}
ItemStack stack = entity.getStackInHand(Hand.MAIN_HAND);
HeldMagicEffect effect = getHeldEffect(stack);
if (effect != null) {
Affinity affinity = stack.getItem() instanceof MagicalItem ? ((MagicalItem)stack.getItem()).getAffinity(stack) : Affinity.NEUTRAL;
effect.updateInHand(this, affinity);
}
addExertion(-1);
addEnergy(-1);
attributes.applyAttributes(entity, getSpecies());
if (dirty) {
sendCapabilities(true);
}
}
@Override
public float onImpact(float distance) {
if (getSpecies().canFly()) {
distance = Math.max(0, distance - 5);
}
return distance;
}
@Override
public void onJump() {
if (gravity.getGravitationConstant() < 0) {
Vec3d velocity = entity.getVelocity();
entity.setVelocity(velocity.x, velocity.y * -1, velocity.z);
}
}
@Override
public boolean onProjectileImpact(ProjectileEntity projectile) {
if (hasEffect()) {
MagicEffect effect = getEffect();
if (!effect.isDead() && effect.handleProjectileImpact(projectile)) {
return true;
}
}
return false;
}
@Override
public boolean subtractEnergyCost(double foodSubtract) {
if (!entity.abilities.creativeMode) {
int food = (int)(entity.getHungerManager().getFoodLevel() - foodSubtract);
if (food < 0) {
entity.getHungerManager().add(-entity.getHungerManager().getFoodLevel(), 0);
entity.damage(DamageSource.MAGIC, -food/2);
} else {
entity.getHungerManager().add((int)-foodSubtract, 0);
}
}
return entity.getHealth() > 0;
}
@Override
public boolean stepOnCloud() {
if (entity.fallDistance > 1 || entity.distanceTraveled > nextStepDistance) {
nextStepDistance = entity.distanceTraveled + 2;
entity.fallDistance = 0;
return true;
}
return false;
}
@Override
public Either<SleepFailureReason, Unit> trySleep(BlockPos pos) {
if (getInventory().matches(UTags.CURSED_ARTEFACTS)) {
if (!isClient()) {
entity.addChatMessage(new TranslatableText("tile.bed.youAreAMonster"), true);
}
return Either.left(SleepFailureReason.OTHER_PROBLEM);
}
if (findAllSpellsInRange(10).anyMatch(c -> c instanceof Pony && ((Pony)c).getInventory().matches(UTags.CURSED_ARTEFACTS))) {
return Either.left(SleepFailureReason.NOT_SAFE);
}
return Either.right(Unit.INSTANCE);
}
@Override
public PlayerInventory getInventory() {
return inventory;
}
@Override
public void onEat(ItemStack stack) {
if (getSpecies() == Race.CHANGELING) {
Toxin.POISON.afflict(getOwner(), Toxicity.SAFE, stack);
}
}
@Override
public void toNBT(CompoundTag compound) {
compound.putString("playerSpecies", getSpecies().name());
compound.put("powers", powers.toNBT());
compound.put("gravity", gravity.toNBT());
MagicEffect effect = getEffect();
if (effect != null) {
compound.put("effect", SpellRegistry.instance().serializeEffectToNBT(effect));
}
pageStates.toNBT(compound);
}
@Override
public void fromNBT(CompoundTag compound) {
setSpecies(Race.fromName(compound.getString("playerSpecies")));
powers.fromNBT(compound.getCompound("powers"));
gravity.fromNBT(compound.getCompound("gravity"));
if (compound.contains("effect")) {
effectDelegate.set(SpellRegistry.instance().createEffectFromNBT(compound.getCompound("effect")));
}
pageStates.fromNBT(compound);
}
@Override
public void copyFrom(Pony oldPlayer) {
setEffect(oldPlayer.getEffect());
setSpecies(oldPlayer.getSpecies());
sendCapabilities(true);
}
@Override
public void setEffect(@Nullable MagicEffect effect) {
effectDelegate.set(effect);
sendCapabilities(true);
}
@Override
public boolean hasEffect() {
return effectDelegate.has();
}
@Nullable
@Override
public <T extends MagicEffect> T getEffect(@Nullable Class<T> type, boolean update) {
return effectDelegate.get(type, update);
}
@Override
public void setOwner(PlayerEntity owner) {
}
@Override
public PlayerEntity getOwner() {
return entity;
}
@Override
public int getCurrentLevel() {
return 0;
}
@Override
public void setCurrentLevel(int level) {
}
}

View file

@ -4,7 +4,6 @@ import java.util.Iterator;
import java.util.Map;
import com.google.common.collect.Maps;
import com.minelittlepony.unicopia.entity.Updatable;
import com.minelittlepony.unicopia.item.MagicGemItem;
import com.minelittlepony.unicopia.magic.AddictiveMagicalItem;
import com.minelittlepony.unicopia.magic.MagicalItem;
@ -16,9 +15,10 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.tag.Tag;
import net.minecraft.util.Identifier;
import net.minecraft.util.Tickable;
import net.minecraft.util.registry.Registry;
public class PlayerInventory implements Updatable, NbtSerialisable {
public class PlayerInventory implements Tickable, NbtSerialisable {
private final Map<AddictiveMagicalItem, Entry> dependencies = Maps.newHashMap();
private final Pony player;
@ -66,7 +66,7 @@ public class PlayerInventory implements Updatable, NbtSerialisable {
}
@Override
public synchronized void onUpdate() {
public synchronized void tick() {
Iterator<Map.Entry<AddictiveMagicalItem, Entry>> iterator = dependencies.entrySet().iterator();
@ -75,7 +75,7 @@ public class PlayerInventory implements Updatable, NbtSerialisable {
Entry item = entry.getValue();
item.onUpdate();
item.tick();
if (item.needfulness <= 0.001) {
iterator.remove();
@ -132,7 +132,7 @@ public class PlayerInventory implements Updatable, NbtSerialisable {
});
}
class Entry implements Updatable, NbtSerialisable {
class Entry implements Tickable, NbtSerialisable {
int ticksAttached = 0;
float needfulness = 1;
@ -152,7 +152,7 @@ public class PlayerInventory implements Updatable, NbtSerialisable {
}
@Override
public void onUpdate() {
public void tick() {
if (isWearing(item)) {
ticksAttached ++;
needfulness *= 0.9F;

View file

@ -13,6 +13,12 @@ import net.minecraft.util.Identifier;
public class PlayerPageStats implements NbtSerialisable, PageOwner {
private final Map<Identifier, PageState> pageStates = new HashMap<>();
private final Pony pony;
PlayerPageStats(Pony pony) {
this.pony = pony;
}
@Override
public Map<Identifier, PageState> getPageStates() {
return pageStates;
@ -20,7 +26,7 @@ public class PlayerPageStats implements NbtSerialisable, PageOwner {
@Override
public void sendCapabilities(boolean full) {
pony.sendCapabilities(full);
}
@Override

View file

@ -5,8 +5,7 @@ import java.util.Random;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.ability.FlightPredicate;
import com.minelittlepony.unicopia.entity.FlightControl;
import com.minelittlepony.unicopia.entity.Updatable;
import com.minelittlepony.unicopia.entity.EntityPhysics;
import com.minelittlepony.unicopia.magic.MagicEffect;
import com.minelittlepony.unicopia.particles.MagicParticleEffect;
import com.minelittlepony.unicopia.util.NbtSerialisable;
@ -18,13 +17,12 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.Tickable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
public class GravityDelegate implements Updatable, FlightControl, NbtSerialisable, FlightPredicate {
final Pony player;
public class PlayerPhysics extends EntityPhysics<Pony> implements Tickable, Motion, NbtSerialisable {
private static final float MAXIMUM_FLIGHT_EXPERIENCE = 1500;
@ -37,73 +35,63 @@ public class GravityDelegate implements Updatable, FlightControl, NbtSerialisabl
private double lastTickPosX = 0;
private double lastTickPosZ = 0;
private float gravity = 0;
private final PlayerDimensions dimensions;
private final PlayerDimensionsDelegate dimensions;
public GravityDelegate(Pony player) {
this.player = player;
this.dimensions = new PlayerDimensionsDelegate(this);
public PlayerPhysics(Pony pony) {
super(pony);
dimensions = new PlayerDimensions(pony, this);
}
@Override
public boolean checkCanFly(Pony player) {
if (player.getOwner().abilities.creativeMode) {
private boolean checkCanFly() {
if (pony.getOwner().abilities.creativeMode) {
return true;
}
if (player.hasEffect()) {
MagicEffect effect = player.getEffect();
if (pony.hasEffect()) {
MagicEffect effect = pony.getEffect();
if (!effect.isDead() && effect instanceof FlightPredicate) {
return ((FlightPredicate)effect).checkCanFly(player);
return ((FlightPredicate)effect).checkCanFly(pony);
}
}
return player.getSpecies().canFly();
return pony.getSpecies().canFly();
}
protected boolean isRainboom() {
return Math.sqrt(getHorizontalMotion(player.getOwner())) > 0.4F;
return Math.sqrt(getHorizontalMotion(pony.getOwner())) > 0.4F;
}
public PlayerDimensionsDelegate getDimensions() {
@Override
public PlayerDimensions getDimensions() {
return dimensions;
}
public void setGraviationConstant(float constant) {
gravity = constant;
}
public float getGravitationConstant() {
return gravity;
}
@Override
public boolean isExperienceCritical() {
return isRainbooming || flightExperience > MAXIMUM_FLIGHT_EXPERIENCE * 0.8;
}
@Override
public void onUpdate() {
PlayerEntity entity = player.getOwner();
public void tick() {
PlayerEntity entity = pony.getOwner();
MutableVector velocity = new MutableVector(entity.getVelocity());
if (isExperienceCritical() && player.isClient()) {
Random rnd = player.getWorld().random;
if (isExperienceCritical() && pony.isClient()) {
Random rnd = pony.getWorld().random;
for (int i = 0; i < 360 + getHorizontalMotion(entity); i += 10) {
Vec3d pos = player.getOriginVector().add(
Vec3d pos = pony.getOriginVector().add(
rnd.nextGaussian() * entity.getWidth(),
rnd.nextGaussian() * entity.getHeight()/2,
rnd.nextGaussian() * entity.getWidth()
);
player.addParticle(MagicParticleEffect.UNICORN, pos, velocity.toImmutable());
pony.addParticle(MagicParticleEffect.UNICORN, pos, velocity.toImmutable());
}
}
entity.abilities.allowFlying = checkCanFly(player);
entity.abilities.allowFlying = checkCanFly();
if (!entity.abilities.creativeMode) {
entity.abilities.flying |= entity.abilities.allowFlying && isFlying && !entity.onGround && !entity.isTouchingWater();
@ -111,26 +99,6 @@ public class GravityDelegate implements Updatable, FlightControl, NbtSerialisabl
isFlying = entity.abilities.flying && !entity.abilities.creativeMode;
if (gravity != 0) {
if (!entity.abilities.flying) {
velocity.y += 0.038;
velocity.y -= gravity;
}
if (gravity < 0) {
entity.onGround = !entity.world.isAir(new BlockPos(entity.getX(), entity.getY() + entity.getHeight() + 0.5F, entity.getZ()));
if (entity.onGround) {
entity.abilities.flying = false;
isFlying = false;
}
}
}
if (dimensions.update()) {
player.getOwner().calculateDimensions();
}
if (!entity.abilities.creativeMode && !entity.isFallFlying()) {
if (isFlying && !entity.hasVehicle()) {
@ -140,7 +108,7 @@ public class GravityDelegate implements Updatable, FlightControl, NbtSerialisabl
entity.fallDistance = 0;
if (player.getSpecies() != Race.CHANGELING && entity.world.random.nextInt(100) == 0) {
if (pony.getSpecies() != Race.CHANGELING && entity.world.random.nextInt(100) == 0) {
float exhaustion = (0.3F * ticksNextLevel) / 70;
if (entity.isSprinting()) {
exhaustion *= 3.11F;
@ -163,8 +131,8 @@ public class GravityDelegate implements Updatable, FlightControl, NbtSerialisabl
if (isExperienceCritical()) {
if (player.getMagicalReserves().getEnergy() <= 0.25F) {
player.getMagicalReserves().addEnergy(2);
if (pony.getMagicalReserves().getEnergy() <= 0.25F) {
pony.getMagicalReserves().addEnergy(2);
}
if (isRainbooming || (entity.isSneaking() && isRainboom())) {
@ -209,6 +177,15 @@ public class GravityDelegate implements Updatable, FlightControl, NbtSerialisabl
}
}
if (pony.getPhysics().isGravityNegative()) {
entity.onGround = !entity.world.isAir(new BlockPos(entity.getX(), entity.getY() + entity.getHeight() + 0.5F, entity.getZ()));
if (entity.onGround) {
entity.abilities.flying = false;
isFlying = false;
}
}
lastTickPosX = entity.getX();
lastTickPosZ = entity.getZ();
@ -216,21 +193,20 @@ public class GravityDelegate implements Updatable, FlightControl, NbtSerialisabl
}
public SoundEvent getWingSound() {
return player.getSpecies() == Race.CHANGELING ? USounds.CHANGELING_BUZZ : USounds.WING_FLAP;
return pony.getSpecies() == Race.CHANGELING ? USounds.CHANGELING_BUZZ : USounds.WING_FLAP;
}
protected void moveFlying(Entity player, MutableVector velocity) {
float forward = 0.000015F * flightExperience * (float)Math.sqrt(getHorizontalMotion(player));
int factor = gravity < 0 ? -1 : 1;
boolean sneak = !player.isSneaking();
// vertical drop due to gravity
if (sneak) {
velocity.y -= (0.005F - getHorizontalMotion(player) / 100) * factor;
velocity.y -= (0.005F - getHorizontalMotion(player) / 100) * getGravitySignum();
} else {
forward += 0.005F;
velocity.y -= 0.0001F * factor;
velocity.y -= 0.0001F * getGravitySignum();
}
velocity.x += - forward * MathHelper.sin(player.yaw * 0.017453292F);
@ -264,7 +240,6 @@ public class GravityDelegate implements Updatable, FlightControl, NbtSerialisabl
forward = 4;
}
//player.knockBack(player, forward, 1, 1);
velocity.x += - forward * MathHelper.sin((player.yaw + glance) * 0.017453292F);
velocity.z += forward * MathHelper.cos((player.yaw + glance) * 0.017453292F);
}
@ -289,8 +264,10 @@ public class GravityDelegate implements Updatable, FlightControl, NbtSerialisabl
flightExperience = Math.max(0, flightExperience + factor * maximumGain / gainSteps);
}
public void updateFlightStat(PlayerEntity entity, boolean flying) {
entity.abilities.allowFlying = checkCanFly(Pony.of(entity));
public void updateFlightStat(boolean flying) {
PlayerEntity entity = pony.getOwner();
entity.abilities.allowFlying = checkCanFly();
if (entity.abilities.allowFlying) {
entity.abilities.flying |= flying;
@ -308,28 +285,22 @@ public class GravityDelegate implements Updatable, FlightControl, NbtSerialisabl
@Override
public void toNBT(CompoundTag compound) {
super.toNBT(compound);
compound.putInt("flightDuration", ticksNextLevel);
compound.putFloat("flightExperience", flightExperience);
compound.putBoolean("isFlying", isFlying);
compound.putBoolean("isRainbooming", isRainbooming);
if (gravity != 0) {
compound.putFloat("gravity", gravity);
}
}
@Override
public void fromNBT(CompoundTag compound) {
super.fromNBT(compound);
ticksNextLevel = compound.getInt("flightDuration");
flightExperience = compound.getFloat("flightExperience");
isFlying = compound.getBoolean("isFlying");
isRainbooming = compound.getBoolean("isRainbooming");
if (compound.contains("gravity")) {
gravity = compound.getFloat("gravity");
} else {
gravity = 0;
}
pony.getOwner().calculateDimensions();
}
@Override

View file

@ -3,111 +3,422 @@ package com.minelittlepony.unicopia.entity.player;
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.InteractionManager;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.ability.AbilityDispatcher;
import com.minelittlepony.unicopia.ducks.PonyContainer;
import com.minelittlepony.unicopia.enchanting.PageOwner;
import com.minelittlepony.unicopia.entity.FlightControl;
import com.minelittlepony.unicopia.entity.RaceContainer;
import com.minelittlepony.unicopia.entity.Physics;
import com.minelittlepony.unicopia.entity.Ponylike;
import com.minelittlepony.unicopia.entity.Trap;
import com.minelittlepony.unicopia.magic.Affinity;
import com.minelittlepony.unicopia.magic.AttachedMagicEffect;
import com.minelittlepony.unicopia.magic.Caster;
import com.minelittlepony.unicopia.magic.HeldMagicEffect;
import com.minelittlepony.unicopia.magic.MagicEffect;
import com.minelittlepony.unicopia.magic.MagicalItem;
import com.minelittlepony.unicopia.magic.spell.SpellRegistry;
import com.minelittlepony.unicopia.network.Channel;
import com.minelittlepony.unicopia.network.EffectSync;
import com.minelittlepony.unicopia.network.MsgPlayerCapabilities;
import com.minelittlepony.unicopia.network.Transmittable;
import com.minelittlepony.unicopia.toxin.Toxicity;
import com.minelittlepony.unicopia.toxin.Toxin;
import com.minelittlepony.util.BasicEasingInterpolator;
import com.minelittlepony.util.IInterpolator;
import com.mojang.authlib.GameProfile;
import com.mojang.datafixers.util.Either;
import net.minecraft.client.network.packet.EntityPassengersSetS2CPacket;
import net.minecraft.entity.Entity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.data.DataTracker;
import net.minecraft.entity.data.TrackedData;
import net.minecraft.entity.data.TrackedDataHandlerRegistry;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerEntity.SleepFailureReason;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.Hand;
import net.minecraft.util.Unit;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
/**
* The player.
*
* This is the core of unicopia.
*/
public interface Pony extends Caster<PlayerEntity>, RaceContainer<PlayerEntity>, Transmittable {
public class Pony implements Caster<PlayerEntity>, Ponylike<PlayerEntity>, Transmittable {
/**
* Gets the player's magical abilities delegate responsible for all spell casting and persisting/updating.
*/
AbilityDispatcher getAbilities();
private static final TrackedData<Integer> RACE = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.INTEGER);
static final TrackedData<Float> ENERGY = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.FLOAT);
static final TrackedData<Float> EXERTION = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.FLOAT);
private static final TrackedData<CompoundTag> EFFECT = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.TAG_COMPOUND);
private static final TrackedData<CompoundTag> HELD_EFFECT = DataTracker.registerData(PlayerEntity.class, TrackedDataHandlerRegistry.TAG_COMPOUND);
/**
* Gets the gravity delegate responsible for updating flight states
*/
GravityDelegate getGravity();
private final PlayerPageStats pageStates = new PlayerPageStats(this);
private final AbilityDispatcher powers = new AbilityDispatcher(this);
private final PlayerPhysics gravity = new PlayerPhysics(this);
private final PlayerAttributes attributes = new PlayerAttributes();
private final PlayerCamera camera = new PlayerCamera(this);
private final PlayerInventory inventory = new PlayerInventory(this);
private final MagicReserves mana;
/**
* Gets the flight delegate.
*/
FlightControl getFlight();
private final EffectSync effectDelegate = new EffectSync(this, EFFECT);
private final EffectSync heldEffectDelegate = new EffectSync(this, HELD_EFFECT);
/**
* Gets the player's viewport.
*/
PlayerCamera getCamera();
private final IInterpolator interpolator = new BasicEasingInterpolator();
MagicReserves getMagicalReserves();
private float nextStepDistance = 1;
/**
* Gets the inventory delegate for this player.
*/
PlayerInventory getInventory();
private final PlayerEntity entity;
/**
* Gets an animation interpolator.
*/
IInterpolator getInterpolator();
private boolean dirty = false;
PageOwner getPages();
private boolean invisible = false;
/**
*/
float getExtendedReach();
public Pony(PlayerEntity player) {
this.entity = player;
this.mana = new ManaContainer(this);
void copyFrom(Pony oldPlayer);
player.getDataTracker().startTracking(RACE, Race.EARTH.ordinal());
player.getDataTracker().startTracking(EFFECT, new CompoundTag());
player.getDataTracker().startTracking(HELD_EFFECT, new CompoundTag());
/**
* Called when the player steps on clouds.
*/
boolean stepOnCloud();
player.getAttributes().register(PlayerAttributes.EXTENDED_REACH_DISTANCE);
}
/**
* Called when this player falls.
*/
float onImpact(float distance);
@Override
public Race getSpecies() {
if (getOwner() == null) {
return Race.HUMAN;
}
/**
* Called whenever the player eats something.
*/
void onEat(ItemStack food);
return Race.fromId(getOwner().getDataTracker().get(RACE));
}
/**
* Attempts to sleep in a bed.
*
* @param pos The position of the bed
*
* @return The sleep result.
*/
Either<PlayerEntity.SleepFailureReason, Unit> trySleep(BlockPos pos);
@Override
public void setSpecies(Race race) {
race = race.validate(entity);
/**
* Returns true if this player is the use.
*/
default boolean isClientPlayer() {
entity.getDataTracker().set(RACE, race.ordinal());
gravity.updateFlightStat(entity.abilities.flying);
entity.sendAbilitiesUpdate();
}
public MagicReserves getMagicalReserves() {
return mana;
}
@Override
public boolean isInvisible() {
return invisible && hasEffect();
}
@Override
public void setInvisible(boolean invisible) {
this.invisible = invisible;
}
@Nullable
public HeldMagicEffect getHeldEffect(ItemStack stack) {
if (!getSpecies().canCast()) {
heldEffectDelegate.set(null);
return null;
}
HeldMagicEffect heldEffect = heldEffectDelegate.get(HeldMagicEffect.class, true);
if (heldEffect == null || !heldEffect.getName().equals(SpellRegistry.getKeyFromStack(stack))) {
heldEffect = SpellRegistry.instance().getHeldFrom(stack);
heldEffectDelegate.set(heldEffect);
}
return heldEffect;
}
@Override
public Affinity getAffinity() {
return Affinity.NEUTRAL;
}
public void setDirty() {
dirty = true;
}
@Override
public void sendCapabilities(boolean full) {
dirty = false;
if (entity instanceof ServerPlayerEntity) {
System.out.println("Sending capabilities for player");
Channel.BROADCAST_CAPABILITIES.send(new MsgPlayerCapabilities(full, this));
}
}
public AbilityDispatcher getAbilities() {
return powers;
}
public PageOwner getPages() {
return pageStates;
}
@Override
public Physics getPhysics() {
return gravity;
}
public float getExtendedReach() {
return (float)entity.getAttributeInstance(PlayerAttributes.EXTENDED_REACH_DISTANCE).getValue();
}
public Motion getMotion() {
return gravity;
}
public PlayerCamera getCamera() {
return camera;
}
public IInterpolator getInterpolator() {
return interpolator;
}
@Override
public boolean beforeUpdate() {
if (entity.world.isClient()) {
if (entity.hasVehicle() && entity.isSneaking()) {
Entity ridee = entity.getVehicle();
if (ridee instanceof Trap) {
if (((Trap)ridee).attemptDismount(entity)) {
entity.stopRiding();
} else {
entity.setSneaking(false);
}
} else {
entity.stopRiding();
if (ridee instanceof ServerPlayerEntity) {
((ServerPlayerEntity)ridee).networkHandler.sendPacket(new EntityPassengersSetS2CPacket(ridee));
}
}
}
}
powers.tick();
inventory.tick();
return false;
}
@Override
public void tick() {
gravity.tick();
if (hasEffect()) {
AttachedMagicEffect effect = getEffect(AttachedMagicEffect.class, true);
if (effect != null) {
if (entity.getEntityWorld().isClient()) {
effect.renderOnPerson(this);
}
if (!effect.updateOnPerson(this)) {
setEffect(null);
}
}
}
ItemStack stack = entity.getStackInHand(Hand.MAIN_HAND);
HeldMagicEffect effect = getHeldEffect(stack);
if (effect != null) {
Affinity affinity = stack.getItem() instanceof MagicalItem ? ((MagicalItem)stack.getItem()).getAffinity(stack) : Affinity.NEUTRAL;
effect.updateInHand(this, affinity);
}
mana.addExertion(-1);
mana.addEnergy(-1);
attributes.applyAttributes(entity, getSpecies());
if (dirty) {
sendCapabilities(true);
}
}
public float onImpact(float distance) {
if (getSpecies().canFly()) {
distance = Math.max(0, distance - 5);
}
return distance;
}
@Override
public void onJump() {
if (gravity.isGravityNegative()) {
Vec3d velocity = entity.getVelocity();
entity.setVelocity(velocity.x, velocity.y * -1, velocity.z);
}
}
@Override
public boolean onProjectileImpact(ProjectileEntity projectile) {
if (hasEffect()) {
MagicEffect effect = getEffect();
if (!effect.isDead() && effect.handleProjectileImpact(projectile)) {
return true;
}
}
return false;
}
@Override
public boolean subtractEnergyCost(double foodSubtract) {
if (!entity.abilities.creativeMode) {
int food = (int)(entity.getHungerManager().getFoodLevel() - foodSubtract);
if (food < 0) {
entity.getHungerManager().add(-entity.getHungerManager().getFoodLevel(), 0);
entity.damage(DamageSource.MAGIC, -food/2);
} else {
entity.getHungerManager().add((int)-foodSubtract, 0);
}
}
return entity.getHealth() > 0;
}
public boolean stepOnCloud() {
if (entity.fallDistance > 1 || entity.distanceTraveled > nextStepDistance) {
nextStepDistance = entity.distanceTraveled + 2;
entity.fallDistance = 0;
return true;
}
return false;
}
public Either<SleepFailureReason, Unit> trySleep(BlockPos pos) {
if (getInventory().matches(UTags.CURSED_ARTEFACTS)) {
if (!isClient()) {
entity.addChatMessage(new TranslatableText("tile.bed.youAreAMonster"), true);
}
return Either.left(SleepFailureReason.OTHER_PROBLEM);
}
if (findAllSpellsInRange(10).anyMatch(c -> c instanceof Pony && ((Pony)c).getInventory().matches(UTags.CURSED_ARTEFACTS))) {
return Either.left(SleepFailureReason.NOT_SAFE);
}
return Either.right(Unit.INSTANCE);
}
public PlayerInventory getInventory() {
return inventory;
}
public void onEat(ItemStack stack) {
if (getSpecies() == Race.CHANGELING) {
Toxin.POISON.afflict(getOwner(), Toxicity.SAFE, stack);
}
}
@Override
public void toNBT(CompoundTag compound) {
compound.putString("playerSpecies", getSpecies().name());
compound.put("powers", powers.toNBT());
compound.put("gravity", gravity.toNBT());
MagicEffect effect = getEffect();
if (effect != null) {
compound.put("effect", SpellRegistry.instance().serializeEffectToNBT(effect));
}
pageStates.toNBT(compound);
}
@Override
public void fromNBT(CompoundTag compound) {
setSpecies(Race.fromName(compound.getString("playerSpecies")));
powers.fromNBT(compound.getCompound("powers"));
gravity.fromNBT(compound.getCompound("gravity"));
if (compound.contains("effect")) {
effectDelegate.set(SpellRegistry.instance().createEffectFromNBT(compound.getCompound("effect")));
}
pageStates.fromNBT(compound);
}
public void copyFrom(Pony oldPlayer) {
setEffect(oldPlayer.getEffect());
setSpecies(oldPlayer.getSpecies());
setDirty();
}
@Override
public void setEffect(@Nullable MagicEffect effect) {
effectDelegate.set(effect);
setDirty();
}
@Override
public boolean hasEffect() {
return effectDelegate.has();
}
@Nullable
@Override
public <T extends MagicEffect> T getEffect(@Nullable Class<T> type, boolean update) {
return effectDelegate.get(type, update);
}
@Override
public void setOwner(PlayerEntity owner) {
}
@Override
public PlayerEntity getOwner() {
return entity;
}
@Override
public int getCurrentLevel() {
return 0;
}
@Override
public void setCurrentLevel(int level) {
}
public boolean isClientPlayer() {
return InteractionManager.instance().isClientPlayer(getOwner());
}
@SuppressWarnings("unchecked")
@Nullable
static Pony of(@Nullable PlayerEntity player) {
public static Pony of(@Nullable PlayerEntity player) {
return player == null ? null : ((PonyContainer<Pony>)player).get();
}
static boolean equal(GameProfile one, GameProfile two) {
public static boolean equal(GameProfile one, GameProfile two) {
return one == two || (one != null && two != null && one.getId().equals(two.getId()));
}
static boolean equal(PlayerEntity one, PlayerEntity two) {
public static boolean equal(PlayerEntity one, PlayerEntity two) {
return one == two || (one != null && two != null && equal(one.getGameProfile(), two.getGameProfile()));
}
}

View file

@ -8,7 +8,7 @@ import javax.annotation.Nullable;
import com.google.common.collect.Multimap;
import com.minelittlepony.unicopia.AwaitTickQueue;
import com.minelittlepony.unicopia.ducks.IItemEntity;
import com.minelittlepony.unicopia.entity.ItemEntityCapabilities;
import com.minelittlepony.unicopia.entity.ItemImpl;
import com.minelittlepony.unicopia.entity.player.MagicReserves;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.magic.Affinity;
@ -48,7 +48,7 @@ import net.minecraft.world.LocalDifficulty;
import net.minecraft.world.World;
import net.minecraft.world.explosion.Explosion.DestructionType;
public class AlicornAmuletItem extends ArmorItem implements AddictiveMagicalItem, ItemEntityCapabilities.TickableItem {
public class AlicornAmuletItem extends ArmorItem implements AddictiveMagicalItem, ItemImpl.TickableItem {
private static final UUID[] MODIFIERS = new UUID[] {
UUID.fromString("845DB27C-C624-495F-8C9F-6020A9A58B6B"),

View file

@ -4,7 +4,7 @@ import java.util.List;
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.ducks.IItemEntity;
import com.minelittlepony.unicopia.entity.ItemEntityCapabilities;
import com.minelittlepony.unicopia.entity.ItemImpl;
import com.minelittlepony.unicopia.toxin.Toxicity;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.entity.EntityType;
@ -17,7 +17,7 @@ import net.minecraft.util.ActionResult;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
public class AppleItem extends Item implements ItemEntityCapabilities.TickableItem {
public class AppleItem extends Item implements ItemImpl.TickableItem {
public AppleItem(Settings settings) {
super(settings);

View file

@ -19,7 +19,7 @@ public interface Useable {
*
* @param stack The current itemstack
* @param affinity The affinity of the casting artifact
* @param player The player
* @param pony The player
* @param world The player's world
* @param pos The location clicked
* @param side The side of the block clicked

View file

@ -7,7 +7,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.minelittlepony.unicopia.ducks.IItemEntity;
import com.minelittlepony.unicopia.entity.ItemEntityCapabilities;
import com.minelittlepony.unicopia.entity.ItemImpl;
import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity;
@ -16,17 +16,17 @@ import net.minecraft.nbt.CompoundTag;
@Mixin(ItemEntity.class)
abstract class MixinItemEntity extends Entity implements IItemEntity {
private ItemEntityCapabilities caster;
private ItemImpl caster;
private MixinItemEntity() { super(null, null); }
@Override
public ItemEntityCapabilities create() {
return new ItemEntityCapabilities((ItemEntity)(Object)this);
public ItemImpl create() {
return new ItemImpl((ItemEntity)(Object)this);
}
@Override
public ItemEntityCapabilities get() {
public ItemImpl get() {
if (caster == null) {
caster = create();
}
@ -42,7 +42,7 @@ abstract class MixinItemEntity extends Entity implements IItemEntity {
@Inject(method = "tick()V", at = @At("RETURN"))
private void afterTick(CallbackInfo info) {
get().onUpdate();
get().tick();
}
@Inject(method = "writeCustomDataToTag(Lnet/minecraft/nbt/CompoundTag;)V", at = @At("HEAD"))

View file

@ -2,32 +2,35 @@ package com.minelittlepony.unicopia.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Constant;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyConstant;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.minelittlepony.unicopia.ducks.PonyContainer;
import com.minelittlepony.unicopia.entity.Ponylike;
import com.minelittlepony.unicopia.entity.LivingEntityCapabilities;
import com.minelittlepony.unicopia.entity.Creature;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.math.BlockPos;
@Mixin(LivingEntity.class)
abstract class MixinLivingEntity extends Entity implements PonyContainer<Ponylike> {
abstract class MixinLivingEntity extends Entity implements PonyContainer<Ponylike<?>> {
private Ponylike caster;
private Ponylike<?> caster;
private MixinLivingEntity() { super(null, null); }
@Override
public Ponylike create() {
return new LivingEntityCapabilities((LivingEntity)(Object)this);
public Ponylike<?> create() {
return new Creature((LivingEntity)(Object)this);
}
@Override
public Ponylike get() {
public Ponylike<?> get() {
if (caster == null) {
caster = create();
}
@ -55,12 +58,12 @@ abstract class MixinLivingEntity extends Entity implements PonyContainer<Ponylik
@Inject(method = "tick()V", at = @At("RETURN"))
private void afterTick(CallbackInfo info) {
get().onUpdate();
get().tick();
}
@Inject(method = "<clinit>()V", at = @At("RETURN"), remap = false)
private static void clinit(CallbackInfo info) {
LivingEntityCapabilities.boostrap();
Creature.boostrap();
}
@Inject(method = "writeCustomDataToTag(Lnet/minecraft/nbt/CompoundTag;)V", at = @At("HEAD"))
@ -75,6 +78,31 @@ abstract class MixinLivingEntity extends Entity implements PonyContainer<Ponylik
}
}
@ModifyConstant(method = "travel(Lnet/minecraft/util/math/Vec3d;)V", constant = {
@Constant(doubleValue = 0.08D),
@Constant(doubleValue = 0.01D)
})
private double modifyGravity(double initial) {
return get().getPhysics().calcGravity(initial);
}
@Override
protected BlockPos getLandingPos() {
if (get().getPhysics().isGravityNegative()) {
return get().getPhysics().getHeadPosition();
}
return super.getLandingPos();
}
@Override
protected void spawnSprintingParticles() {
if (get().getPhysics().isGravityNegative()) {
get().getPhysics().spawnSprintingParticles();
} else {
super.spawnSprintingParticles();
}
}
// ---------- temporary
@SuppressWarnings("deprecation")
@Inject(method = "isClimbing()Z", at = @At("HEAD"), cancellable = true)

View file

@ -10,7 +10,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.minelittlepony.unicopia.ducks.PonyContainer;
import com.minelittlepony.unicopia.entity.Ponylike;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.entity.player.PlayerImpl;
import com.mojang.datafixers.util.Either;
import net.minecraft.entity.EntityDimensions;
@ -29,8 +28,8 @@ abstract class MixinPlayerEntity extends LivingEntity implements PonyContainer<P
private MixinPlayerEntity() { super(null, null); }
@Override
public Ponylike create() {
return new PlayerImpl((PlayerEntity)(Object)this);
public Ponylike<?> create() {
return new Pony((PlayerEntity)(Object)this);
}
@ModifyVariable(method = "handleFallDamage(FF)Z",
@ -72,20 +71,20 @@ abstract class MixinPlayerEntity extends LivingEntity implements PonyContainer<P
at = @At("RETURN"))
private void onSetGameMode(GameMode mode, CallbackInfo info) {
get().setSpecies(get().getSpecies());
get().sendCapabilities(true);
get().setDirty();
}
@Inject(method = "getActiveEyeHeight(Lnet/minecraft/entity/EntityPose;Lnet/minecraft/entity/EntityDimensions;)F",
at = @At("RETURN"),
cancellable = true)
private void onGetActiveEyeHeight(EntityPose pose, EntityDimensions dimensions, CallbackInfoReturnable<Float> info) {
info.setReturnValue(get().getGravity().getDimensions().getActiveEyeHeight(info.getReturnValue()));
info.setReturnValue(get().getMotion().getDimensions().getActiveEyeHeight(info.getReturnValue()));
}
@Inject(method = "getDimensions(Lnet/minecraft/entity/EntityPose;)Lnet/minecraft/entity/EntityDimensions;",
at = @At("RETURN"),
cancellable = true)
public void onGetDimensions(EntityPose pose, CallbackInfoReturnable<EntityDimensions> info) {
info.setReturnValue(get().getGravity().getDimensions().getDimensions(pose, info.getReturnValue()));
info.setReturnValue(get().getMotion().getDimensions().getDimensions(pose, info.getReturnValue()));
}
}

View file

@ -2,15 +2,11 @@ package com.minelittlepony.unicopia.mixin.client;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.At.Shift;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.minelittlepony.unicopia.entity.player.Pony;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.Camera;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.entity.player.PlayerEntity;
@Mixin(Camera.class)
@ -42,18 +38,4 @@ abstract class MixinCamera {
return pitch;
}
@Inject(method = "setRotation(FF)V",
at = @At(value = "INVOKE",
target = "Lnet/minecraft/util/math/Quaternion;set(FFFF)V",
shift = Shift.AFTER)
)
private void onSetRotation(float yaw, float pitch, CallbackInfo info) {
PlayerEntity player = MinecraftClient.getInstance().player;
if (player != null && MinecraftClient.getInstance().cameraEntity == player) {
float roll = Pony.of(player).getCamera().calculateRoll();
((Camera)(Object)this).getRotation().hamiltonProduct(Vector3f.POSITIVE_Z.getDegreesQuaternion(roll));
}
}
}

View file

@ -5,6 +5,7 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.minelittlepony.unicopia.client.render.WorldRenderDelegate;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.magic.spell.DisguiseSpell;
@ -31,13 +32,7 @@ abstract class MixinEntityRenderDispatcher {
Pony pony = Pony.of((PlayerEntity)entity);
if (pony.getGravity().getGravitationConstant() < 0) {
matrices.push();
matrices.translate(0, entity.getDimensions(entity.getPose()).height, 0);
matrices.scale(1, -1, 1);
entity.prevPitch *= -1;
entity.pitch *= -1;
}
WorldRenderDelegate.INSTANCE.beforeEntityRender(pony, matrices, x, y, z);
DisguiseSpell effect = pony.getEffect(DisguiseSpell.class, true);
@ -64,19 +59,13 @@ abstract class MixinEntityRenderDispatcher {
}
}
@Inject(method = RENDER, at = @At("HEAD"))
@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) {
if (!(entity instanceof PlayerEntity)) {
return;
}
Pony pony = Pony.of((PlayerEntity)entity);
if (pony.getGravity().getGravitationConstant() < 0) {
matrices.pop();
entity.prevPitch *= -1;
entity.pitch *= -1;
}
WorldRenderDelegate.INSTANCE.afterEntityRender(Pony.of((PlayerEntity)entity), matrices);
}
}

View file

@ -3,13 +3,16 @@ package com.minelittlepony.unicopia.mixin.client;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.minelittlepony.unicopia.client.render.WorldRenderDelegate;
import com.minelittlepony.unicopia.entity.player.Pony;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.resource.SynchronousResourceReloadListener;
@Mixin(GameRenderer.class)
@ -22,4 +25,10 @@ abstract class MixinGameRenderer implements AutoCloseable, SynchronousResourceRe
.getCamera()
.calculateFieldOfView(info.getReturnValue()));
}
@Inject(method = "renderWorld(FLLnet/minecraft/client/util/math/MatrixStack;)V",
at = @At("HEAD"))
public void onRenderWorld(float tickDelta, long limitTime, MatrixStack matrices, CallbackInfo info) {
WorldRenderDelegate.INSTANCE.applyWorldTransform(matrices, tickDelta);
}
}

View file

@ -17,7 +17,7 @@ abstract class MixinKeyboardInput extends Input {
private void onTick(boolean strafe, CallbackInfo info) {
Pony player = Pony.of(MinecraftClient.getInstance().player);
if (player.getGravity().getGravitationConstant() < 0) {
if (player.getPhysics().isGravityNegative()) {
boolean tmp = pressingLeft;
pressingLeft = pressingRight;

View file

@ -21,7 +21,7 @@ abstract class MixinMouse {
@Inject(method = "updateMouse()V", at = @At("HEAD"))
private void onUpdateMouse(CallbackInfo info) {
Pony player = Pony.of(MinecraftClient.getInstance().player);
if (player != null&& player.getGravity().getGravitationConstant() < 0) {
if (player != null&& player.getPhysics().isGravityNegative()) {
cursorDeltaX = -cursorDeltaX;
cursorDeltaY = -cursorDeltaY;
}