mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-23 21:38:00 +01:00
Fix fall damage, ladders, hitbox calculations, clipping, camera offset, and unicorn's teleportation when in inverted gravity
This commit is contained in:
parent
b4a847e4b5
commit
692db5a070
17 changed files with 203 additions and 158 deletions
|
@ -27,6 +27,7 @@ import net.minecraft.sound.SoundCategory;
|
|||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.world.World;
|
||||
|
@ -89,8 +90,10 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
|||
return trace.getBlockOrEntityPos().map(pos -> {
|
||||
final BlockPos originalPos = pos;
|
||||
|
||||
Direction globalUp = player.getPhysics().isGravityNegative() ? Direction.DOWN : Direction.UP;
|
||||
|
||||
boolean originalPosHasSupport = exception(w, pos, player.asEntity());
|
||||
boolean originalPosValid = enterable(w, pos.up()) && enterable(w, pos.up(2));
|
||||
boolean originalPosValid = enterable(w, pos.offset(globalUp)) && enterable(w, pos.offset(globalUp, 2));
|
||||
|
||||
if (w.getBlockState(pos).isOf(Blocks.POWDER_SNOW) && !PowderSnowBlock.canWalkOnPowderSnow(player.asEntity())) {
|
||||
return null;
|
||||
|
@ -111,11 +114,11 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
|||
if (pos.getX() != originalPos.getX() || pos.getZ() != originalPos.getZ()) {
|
||||
// check support
|
||||
int steps = 0;
|
||||
while (enterable(w, pos.down())) {
|
||||
pos = pos.down();
|
||||
while (enterable(w, pos.offset(globalUp.getOpposite()))) {
|
||||
pos = pos.offset(globalUp.getOpposite());
|
||||
if (++steps > 2) {
|
||||
if (originalPosValid) {
|
||||
pos = originalPos.up();
|
||||
pos = originalPos.offset(globalUp);
|
||||
break;
|
||||
} else {
|
||||
return null;
|
||||
|
@ -125,7 +128,7 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
|||
}
|
||||
|
||||
if ((!enterable(w, pos) && exception(w, pos, player.asEntity()))
|
||||
|| (!enterable(w, pos.up()) && exception(w, pos.up(), player.asEntity()))) {
|
||||
|| (!enterable(w, pos.offset(globalUp)) && exception(w, pos.offset(globalUp), player.asEntity()))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -175,43 +175,39 @@ public class WorldRenderDelegate {
|
|||
|
||||
boolean negative = pony.getPhysics().isGravityNegative();
|
||||
|
||||
float roll = negative ? 180 : 0;
|
||||
|
||||
roll = pony instanceof Pony ? ((Pony)pony).getInterpolator().interpolate("g_roll", roll, 15) : roll;
|
||||
|
||||
matrices.translate(x, y + owner.getHeight() / 2, z);
|
||||
|
||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(roll));
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(roll));
|
||||
|
||||
if (pony instanceof Pony p) {
|
||||
roll = p.getCamera().calculateRoll();
|
||||
if (negative) {
|
||||
roll -= 180;
|
||||
}
|
||||
float sidewaysRoll = p.getCamera().calculateRoll();
|
||||
|
||||
if (p.getAcrobatics().isFloppy()) {
|
||||
matrices.translate(0, -0.5, 0);
|
||||
p.asEntity().setBodyYaw(0);
|
||||
p.asEntity().setYaw(0);
|
||||
matrices.multiply(RotationAxis.NEGATIVE_X.rotationDegrees(90));
|
||||
sidewaysRoll += 90;
|
||||
}
|
||||
|
||||
matrices.multiply(RotationAxis.NEGATIVE_Y.rotationDegrees(yaw));
|
||||
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(roll));
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(90));
|
||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(sidewaysRoll));
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-90));
|
||||
|
||||
float diveAngle = p.getInterpolator().interpolate("g_kdive", p.getMotion().isDiving() ? 80 : 0, 15);
|
||||
float forwardPitch = p.getInterpolator().interpolate("g_kdive", p.getMotion().isDiving() ? 80 : 0, 15);
|
||||
|
||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(diveAngle));
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(yaw));
|
||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(forwardPitch));
|
||||
|
||||
if (p.getCompositeRace().includes(Race.SEAPONY)
|
||||
&& pony.asEntity().isSubmergedInWater()
|
||||
&& MineLPDelegate.getInstance().getPlayerPonyRace(p.asEntity()) != Race.SEAPONY) {
|
||||
ModelPartHooks.startCollecting();
|
||||
}
|
||||
} else if (pony instanceof Creature creature && smittenEyesRenderer.isSmitten(creature)) {
|
||||
ModelPartHooks.startCollecting();
|
||||
} else {
|
||||
float roll = negative ? 180 : 0;
|
||||
|
||||
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(roll));
|
||||
|
||||
if (pony instanceof Creature creature && smittenEyesRenderer.isSmitten(creature)) {
|
||||
ModelPartHooks.startCollecting();
|
||||
}
|
||||
}
|
||||
|
||||
matrices.translate(-x, -y - owner.getHeight() / 2, -z);
|
||||
|
@ -224,7 +220,7 @@ public class WorldRenderDelegate {
|
|||
}
|
||||
|
||||
private void flipAngles(Entity entity) {
|
||||
if (entity instanceof PlayerEntity) {
|
||||
if (entity instanceof PlayerEntity player) {
|
||||
entity.prevYaw *= -1;
|
||||
entity.setYaw(entity.getYaw() * -1);
|
||||
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
package com.minelittlepony.unicopia.command;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.google.common.collect.Streams;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import com.minelittlepony.unicopia.entity.Living;
|
||||
import com.mojang.brigadier.arguments.FloatArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
|
||||
import net.minecraft.command.argument.EntityArgumentType;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.command.CommandManager;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
|
@ -22,45 +22,48 @@ class GravityCommand {
|
|||
return CommandManager.literal("gravity").requires(s -> s.hasPermissionLevel(2))
|
||||
.then(CommandManager.literal("get")
|
||||
.executes(context -> get(context.getSource(), context.getSource().getPlayer(), true))
|
||||
.then(CommandManager.argument("target", EntityArgumentType.player())
|
||||
.executes(context -> get(context.getSource(), EntityArgumentType.getPlayer(context, "target"), false))
|
||||
.then(CommandManager.argument("target", EntityArgumentType.entity())
|
||||
.executes(context -> get(context.getSource(), EntityArgumentType.getEntity(context, "target"), false))
|
||||
))
|
||||
.then(CommandManager.literal("set")
|
||||
.then(CommandManager.argument("gravity", FloatArgumentType.floatArg(-99, 99))
|
||||
.executes(context -> set(context.getSource(), context.getSource().getPlayer(), FloatArgumentType.getFloat(context, "gravity"), true))
|
||||
.then(CommandManager.argument("target", EntityArgumentType.player())
|
||||
.executes(context -> set(context.getSource(), EntityArgumentType.getPlayer(context, "target"), FloatArgumentType.getFloat(context, "gravity"), false))
|
||||
.executes(context -> set(context.getSource(), List.of(context.getSource().getPlayer()), FloatArgumentType.getFloat(context, "gravity"), true))
|
||||
.then(CommandManager.argument("target", EntityArgumentType.entities())
|
||||
.executes(context -> set(context.getSource(), EntityArgumentType.getEntities(context, "target"), FloatArgumentType.getFloat(context, "gravity"), false))
|
||||
)));
|
||||
}
|
||||
|
||||
static int get(ServerCommandSource source, PlayerEntity player, boolean isSelf) throws CommandSyntaxException {
|
||||
sendFeedback(source, player, "get", false, Pony.of(player).getPhysics().getGravityModifier());
|
||||
return 0;
|
||||
}
|
||||
static int get(ServerCommandSource source, Entity target, boolean isSelf) throws CommandSyntaxException {
|
||||
Living<?> l = Living.living(target);
|
||||
|
||||
static int set(ServerCommandSource source, PlayerEntity player, float gravity, boolean isSelf) {
|
||||
|
||||
Pony iplayer = Pony.of(player);
|
||||
|
||||
iplayer.getPhysics().setBaseGravityModifier(gravity);
|
||||
iplayer.setDirty();
|
||||
|
||||
sendFeedback(source, player, "set", true, gravity);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void sendFeedback(ServerCommandSource source, PlayerEntity player, String key, boolean notifyTarget, Object...arguments) {
|
||||
String translationKey = "commands.gravity." + key;
|
||||
|
||||
if (source.getEntity() == player) {
|
||||
source.sendFeedback(() -> Text.translatable(translationKey + ".self", arguments), true);
|
||||
float gravity = l == null ? 1 : l.getPhysics().getGravityModifier();
|
||||
if (source.getEntity() == target) {
|
||||
source.sendFeedback(() -> Text.translatable("commands.gravity.get.self", gravity), true);
|
||||
} else {
|
||||
if (notifyTarget && source.getWorld().getGameRules().getBoolean(GameRules.SEND_COMMAND_FEEDBACK)) {
|
||||
player.sendMessage(Text.translatable(translationKey, arguments));
|
||||
}
|
||||
|
||||
source.sendFeedback(() -> Text.translatable(translationKey + ".other", Streams.concat(Stream.of(player.getDisplayName()), Arrays.stream(arguments)).toArray()), true);
|
||||
source.sendFeedback(() -> Text.translatable("commands.gravity.get.other", target.getDisplayName(), gravity), true);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set(ServerCommandSource source, Collection<? extends Entity> targets, float gravity, boolean isSelf) {
|
||||
List<Entity> affected = targets.stream().map(Living::living).filter(Objects::nonNull).map(l -> {
|
||||
l.getPhysics().setBaseGravityModifier(gravity);
|
||||
l.setDirty();
|
||||
if (l.asEntity() instanceof PlayerEntity player) {
|
||||
if (source.getEntity() == player) {
|
||||
player.sendMessage(Text.translatable("commands.gravity.set.self", gravity));
|
||||
} else if (source.getWorld().getGameRules().getBoolean(GameRules.SEND_COMMAND_FEEDBACK)) {
|
||||
player.sendMessage(Text.translatable("commands.gravity.set.other", l.asEntity().getDisplayName(), gravity));
|
||||
}
|
||||
}
|
||||
return (Entity)l.asEntity();
|
||||
}).toList();
|
||||
|
||||
if (affected.size() == 1) {
|
||||
source.sendFeedback(() -> Text.translatable("commands.gravity.set.other", affected.get(0).getDisplayName()), true);
|
||||
} else {
|
||||
source.sendFeedback(() -> Text.translatable("commands.gravity.set.multiple", affected.size()), true);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,18 +4,13 @@ import com.minelittlepony.unicopia.entity.mob.UEntityAttributes;
|
|||
import com.minelittlepony.unicopia.util.Copyable;
|
||||
import com.minelittlepony.unicopia.util.Tickable;
|
||||
|
||||
import net.minecraft.block.BlockRenderType;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.FenceGateBlock;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityPose;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.MovementType;
|
||||
import net.minecraft.entity.data.TrackedData;
|
||||
import net.minecraft.entity.mob.MobEntity;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.particle.BlockStateParticleEffect;
|
||||
import net.minecraft.particle.ParticleTypes;
|
||||
import net.minecraft.registry.tag.BlockTags;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
@ -37,22 +32,12 @@ public class EntityPhysics<T extends Entity> implements Physics, Copyable<Entity
|
|||
@Override
|
||||
public void tick() {
|
||||
if (isGravityNegative()) {
|
||||
if (isGravityNegative() && !entity.isSneaking() && entity.isInSneakingPose()) {
|
||||
float currentHeight = entity.getDimensions(entity.getPose()).height;
|
||||
float sneakingHeight = entity.getDimensions(EntityPose.STANDING).height;
|
||||
|
||||
entity.move(MovementType.SELF, new Vec3d(0, -(currentHeight - sneakingHeight), 0));
|
||||
entity.setPose(EntityPose.STANDING);
|
||||
}
|
||||
|
||||
if (entity.getY() > entity.getWorld().getHeight() + 64) {
|
||||
entity.damage(entity.getDamageSources().outOfWorld(), 4.0F);
|
||||
}
|
||||
|
||||
entity.setOnGround(entity.verticalCollision && entity.getVelocity().getY() > 0);
|
||||
}
|
||||
|
||||
float gravity = this.getGravityModifier();
|
||||
float gravity = getGravityModifier();
|
||||
if (gravity != lastGravity) {
|
||||
lastGravity = gravity;
|
||||
|
||||
|
@ -87,8 +72,6 @@ public class EntityPhysics<T extends Entity> implements Physics, Copyable<Entity
|
|||
@Override
|
||||
public BlockPos getHeadPosition() {
|
||||
|
||||
entity.setOnGround(false);
|
||||
|
||||
BlockPos pos = new BlockPos(
|
||||
MathHelper.floor(entity.getX()),
|
||||
MathHelper.floor(entity.getY() + entity.getHeight() + 0.20000000298023224D),
|
||||
|
@ -99,29 +82,13 @@ public class EntityPhysics<T extends Entity> implements Physics, Copyable<Entity
|
|||
BlockPos below = pos.down();
|
||||
BlockState block = entity.getWorld().getBlockState(below);
|
||||
if (block.isIn(BlockTags.FENCES) || block.isIn(BlockTags.WALLS) || block.getBlock() instanceof FenceGateBlock) {
|
||||
entity.setOnGround(true);
|
||||
return below;
|
||||
}
|
||||
} else {
|
||||
entity.setOnGround(true);
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnSprintingParticles() {
|
||||
BlockState state = entity.getWorld().getBlockState(getHeadPosition());
|
||||
if (state.getRenderType() != BlockRenderType.INVISIBLE) {
|
||||
Vec3d vel = entity.getVelocity();
|
||||
entity.getWorld().addParticle(new BlockStateParticleEffect(ParticleTypes.BLOCK, state),
|
||||
entity.getX() + (entity.getWorld().random.nextFloat() - 0.5D) * entity.getWidth(),
|
||||
entity.getY() + entity.getHeight() - 0.1D,
|
||||
entity.getZ() + (entity.getWorld().random.nextFloat() - 0.5D) * entity.getWidth(),
|
||||
vel.x * -4, -1.5D, vel.z * -4);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBaseGravityModifier(float constant) {
|
||||
entity.getDataTracker().set(gravity, constant);
|
||||
|
|
|
@ -476,12 +476,6 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
|||
return false;
|
||||
}
|
||||
|
||||
public void onJump() {
|
||||
if (getPhysics().isGravityNegative()) {
|
||||
entity.setVelocity(entity.getVelocity().multiply(1, -1, 1));
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public final Caster<?> getAttacker() {
|
||||
return attacker;
|
||||
|
|
|
@ -21,8 +21,6 @@ public interface Physics extends NbtSerialisable {
|
|||
|
||||
BlockPos getHeadPosition();
|
||||
|
||||
void spawnSprintingParticles();
|
||||
|
||||
default boolean isGravityNegative() {
|
||||
return getGravityModifier() < 0;
|
||||
}
|
||||
|
|
|
@ -25,11 +25,7 @@ public final class PlayerDimensions {
|
|||
.or(() -> physics.isFlyingSurvival ? FLYING_EYE_HEIGHT : physics.isGravityNegative() ? Optional.of(dimensions.height) : Optional.empty())
|
||||
.map(h -> {
|
||||
if (physics.isGravityNegative()) {
|
||||
if (pony.asEntity().isSneaking()) {
|
||||
h += 0.2F;
|
||||
}
|
||||
|
||||
return dimensions.height - h;
|
||||
return dimensions.height - h + 0.1F;
|
||||
}
|
||||
return h;
|
||||
});
|
||||
|
|
|
@ -301,10 +301,6 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
|
|||
if (entity.isOnGround() || (!creative && entity.horizontalCollision)) {
|
||||
cancelFlight(false);
|
||||
}
|
||||
|
||||
if (entity.isClimbing() && (entity.horizontalCollision || ((LivingEntityDuck)entity).isJumping())) {
|
||||
velocity.y = -0.2F;
|
||||
}
|
||||
}
|
||||
|
||||
isFlyingSurvival = entity.getAbilities().flying && !creative;
|
||||
|
|
|
@ -631,7 +631,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
|
|||
float max = 0.6F;
|
||||
return Optional.of(new Vec3d(
|
||||
MathHelper.clamp(speed.x * factor, -max, max),
|
||||
speed.y * ((speed.y * getPhysics().getGravitySignum()) > 0 ? 1.2 : 1.101),
|
||||
speed.y * (speed.y > 0 ? 1.2 : 1.101),
|
||||
MathHelper.clamp(speed.z * factor, -max, max)
|
||||
));
|
||||
}
|
||||
|
@ -715,11 +715,8 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
|
|||
}
|
||||
|
||||
public Optional<Float> onImpact(float distance, float damageMultiplier, DamageSource cause) {
|
||||
|
||||
float originalDistance = distance;
|
||||
|
||||
distance *= gravity.getGravityModifier();
|
||||
|
||||
boolean extraProtection = getSpellSlot().get(SpellType.SHIELD, false).isPresent();
|
||||
|
||||
if (!entity.isCreative() && !entity.isSpectator()) {
|
||||
|
|
|
@ -128,11 +128,6 @@ abstract class MixinLivingEntity extends Entity implements LivingEntityDuck, Equ
|
|||
get().adjustMovementSpeedInWater(info.getReturnValue()).ifPresent(info::setReturnValue);
|
||||
}
|
||||
|
||||
@Inject(method = "jump()V", at = @At("RETURN"))
|
||||
private void onJump(CallbackInfo info) {
|
||||
get().onJump();
|
||||
}
|
||||
|
||||
@Inject(method = "tick()V", at = @At("HEAD"), cancellable = true)
|
||||
private void beforeTick(CallbackInfo info) {
|
||||
if (get().beforeUpdate()) {
|
||||
|
@ -186,21 +181,4 @@ abstract class MixinLivingEntity extends Entity implements LivingEntityDuck, Equ
|
|||
setLivingFlag(2, hand == Hand.OFF_HAND);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getBlockPos() {
|
||||
if (get().getPhysics().isGravityNegative()) {
|
||||
return get().getPhysics().getHeadPosition();
|
||||
}
|
||||
return super.getBlockPos();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void spawnSprintingParticles() {
|
||||
if (get().getPhysics().isGravityNegative()) {
|
||||
get().getPhysics().spawnSprintingParticles();
|
||||
} else {
|
||||
super.spawnSprintingParticles();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,12 +27,6 @@ abstract class MixinKeyboardInput extends Input {
|
|||
pressingRight = tmp;
|
||||
|
||||
movementSideways = -movementSideways;
|
||||
|
||||
/*if (player.asEntity().getAbilities().flying && !player.getPhysics().isFlying()) {
|
||||
tmp = jumping;
|
||||
jumping = sneaking;
|
||||
sneaking = tmp;
|
||||
}*/
|
||||
}
|
||||
|
||||
if (EffectUtils.getAmplifier(MinecraftClient.getInstance().player, UEffects.PARALYSIS) > 1) {
|
||||
|
|
|
@ -5,6 +5,7 @@ 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.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
@ -12,7 +13,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
|||
import com.minelittlepony.unicopia.entity.Equine;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityPose;
|
||||
import net.minecraft.entity.MovementType;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
@Mixin(value = Entity.class, priority = 29000)
|
||||
|
@ -21,7 +24,7 @@ abstract class MixinEntity {
|
|||
// we invert y when moving
|
||||
@ModifyVariable(method = "move", at = @At("HEAD"), argsOnly = true)
|
||||
private Vec3d modifyMovement(Vec3d movement) {
|
||||
if (this instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) {
|
||||
if (unicopiaIsGravityInverted()) {
|
||||
return movement.multiply(1, -1, 1);
|
||||
}
|
||||
return movement;
|
||||
|
@ -35,14 +38,6 @@ abstract class MixinEntity {
|
|||
}
|
||||
}
|
||||
|
||||
// invert jumping velocity so we can jump
|
||||
@Inject(method = "getJumpVelocityMultiplier", at = @At("RETURN"), cancellable = true)
|
||||
private void onGetJumpVelocityMultiplier(CallbackInfoReturnable<Float> info) {
|
||||
if (this instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) {
|
||||
info.setReturnValue(-info.getReturnValue());
|
||||
}
|
||||
}
|
||||
|
||||
// invert offsets so it can properly find the block we're walking on
|
||||
@ModifyVariable(method = "getPosWithYOffset", at = @At("HEAD"), argsOnly = true)
|
||||
private float onGetPosWithYOffset(float offset) {
|
||||
|
@ -53,12 +48,27 @@ abstract class MixinEntity {
|
|||
}
|
||||
|
||||
// fix sprinting particles
|
||||
@Inject(method = "spawnSprintingParticles", at = @At("HEAD"), cancellable = true)
|
||||
protected void spawnSprintingParticles(CallbackInfo info) {
|
||||
@ModifyArg(method = "spawnSprintingParticles",
|
||||
at = @At(value = "INVOKE",
|
||||
target = "net/minecraft/world/World.addParticle(Lnet/minecraft/particle/ParticleEffect;DDDDDD)V"),
|
||||
index = 2)
|
||||
private double modifyParticleY(double y) {
|
||||
if (this instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) {
|
||||
eq.get().getPhysics().spawnSprintingParticles();
|
||||
info.cancel();
|
||||
Entity self = eq.get().asEntity();
|
||||
return self.getHeight() - y + (self.getY() * 2);
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
// fix fall damage
|
||||
@ModifyArg(
|
||||
method = "move",
|
||||
at = @At(value = "INVOKE", target = "net/minecraft/entity/Entity.fall(DZLnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;)V"))
|
||||
private double modifyFallDistance(double heightDifference) {
|
||||
if (unicopiaIsGravityInverted()) {
|
||||
return -heightDifference;
|
||||
}
|
||||
return heightDifference;
|
||||
}
|
||||
|
||||
// invert check for walking up a step
|
||||
|
@ -68,9 +78,43 @@ abstract class MixinEntity {
|
|||
argsOnly = true)
|
||||
|
||||
private static Vec3d modifyMovementForStepheight(Vec3d movement, @Nullable Entity entity) {
|
||||
if (entity != null && movement.getY() == entity.getStepHeight()) {
|
||||
if (entity instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative() && movement.getY() == entity.getStepHeight()) {
|
||||
return movement.multiply(1, -1, 1);
|
||||
}
|
||||
return movement;
|
||||
}
|
||||
|
||||
@Inject(method = {"calculateBoundsForPose"}, at = @At("RETURN"), cancellable = true)
|
||||
private void adjustPoseBoxForGravity(EntityPose pos, CallbackInfoReturnable<Box> info) {
|
||||
unicopiaReAnchorBoundingBox(info);
|
||||
}
|
||||
|
||||
@Inject(method = {"calculateBoundingBox"}, at = @At("RETURN"), cancellable = true)
|
||||
private void adjustPoseBoxForGravity(CallbackInfoReturnable<Box> info) {
|
||||
if (unicopiaReAnchorBoundingBox(info)) {
|
||||
Entity self = (Entity)(Object)this;
|
||||
self.setPos(self.getX(), info.getReturnValue().minY, self.getZ());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean unicopiaReAnchorBoundingBox(CallbackInfoReturnable<Box> info) {
|
||||
if (this instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) {
|
||||
Entity self = eq.get().asEntity();
|
||||
Box box = info.getReturnValue();
|
||||
Box oldBox = self.getBoundingBox();
|
||||
double newHeight = box.getYLength();
|
||||
if (newHeight > oldBox.getYLength()) {
|
||||
double targetMaxY = oldBox.maxY;
|
||||
Vec3d min = new Vec3d(box.minX, targetMaxY - newHeight, box.minZ);
|
||||
Vec3d max = new Vec3d(box.maxX, targetMaxY, box.maxZ);
|
||||
info.setReturnValue(new Box(min, max));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean unicopiaIsGravityInverted() {
|
||||
return this instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
package com.minelittlepony.unicopia.mixin.gravity;
|
||||
|
||||
import org.spongepowered.asm.mixin.*;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Constant;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyConstant;
|
||||
import com.minelittlepony.unicopia.entity.*;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
@Mixin(LivingEntity.class)
|
||||
abstract class MixinLivingEntity extends Entity implements Equine.Container<Living<?>> {
|
||||
|
@ -19,4 +23,23 @@ abstract class MixinLivingEntity extends Entity implements Equine.Container<Livi
|
|||
private double modifyGravity(double initial) {
|
||||
return Math.abs(get().getPhysics().calcGravity(initial));
|
||||
}
|
||||
|
||||
@ModifyArg(method = "fall",
|
||||
at = @At(value = "INVOKE",
|
||||
target = "net/minecraft/server/world/ServerWorld.spawnParticles(Lnet/minecraft/particle/ParticleEffect;DDDIDDDD)I"),
|
||||
index = 2)
|
||||
private double modifyParticleY(double y) {
|
||||
if (get().getPhysics().isGravityNegative()) {
|
||||
return y + getHeight();
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getBlockPos() {
|
||||
if (get().getPhysics().isGravityNegative()) {
|
||||
return get().getPhysics().getHeadPosition();
|
||||
}
|
||||
return super.getBlockPos();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package com.minelittlepony.unicopia.mixin.gravity;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
|
||||
import net.minecraft.network.listener.ServerPlayPacketListener;
|
||||
import net.minecraft.network.listener.TickablePacketListener;
|
||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.EntityTrackingListener;
|
||||
|
||||
@Mixin(ServerPlayNetworkHandler.class)
|
||||
abstract class MixinServerPlayNetworkHandler
|
||||
implements EntityTrackingListener,
|
||||
TickablePacketListener,
|
||||
ServerPlayPacketListener {
|
||||
@Shadow public ServerPlayerEntity player;
|
||||
|
||||
@ModifyVariable(method = "onPlayerMove", at = @At("STORE"), ordinal = 0)
|
||||
private boolean flipLandingFlag(boolean value) {
|
||||
if (Pony.of(this.player).getPhysics().isGravityNegative()) {
|
||||
return !value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.minelittlepony.unicopia.mixin.gravity;
|
||||
|
||||
import org.spongepowered.asm.mixin.*;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
|
||||
import com.minelittlepony.unicopia.entity.Equine;
|
||||
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
@Mixin(ServerPlayerEntity.class)
|
||||
abstract class MixinServerPlayerEntity {
|
||||
@ModifyVariable(
|
||||
method = "handleFall(DDDZ)V",
|
||||
at = @At("HEAD"),
|
||||
ordinal = 1,
|
||||
argsOnly = true)
|
||||
private double modifyFallDistance(double value) {
|
||||
if (this instanceof Equine.Container eq && eq.get().getPhysics().isGravityNegative()) {
|
||||
return -value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -1383,6 +1383,7 @@
|
|||
"commands.gravity.set": "Your gravity has been updated to %f",
|
||||
"commands.gravity.set.self": "Set own gravity to %f",
|
||||
"commands.gravity.set.other": "Set %s's gravity to %f",
|
||||
"commands.gravity.set.multiple": "Updated %s entities",
|
||||
|
||||
"unicopia.options.title": "Unicopia Options",
|
||||
"unicopia.options.ignore_mine_lp": "Ignore Mine Little Pony",
|
||||
|
|
|
@ -59,6 +59,8 @@
|
|||
"gravity.MixinMobEntity",
|
||||
"gravity.MixinWorld",
|
||||
"gravity.MixinServerWorld",
|
||||
"gravity.MixinServerPlayerEntity",
|
||||
"gravity.MixinServerPlayNetworkHandler",
|
||||
"gravity.MixinWorldChunk",
|
||||
"trinkets.MixinTrinketSurvivalSlot",
|
||||
"trinkets.MixinTrinketItem",
|
||||
|
|
Loading…
Reference in a new issue