More work on movement

This commit is contained in:
FlorianMichael 2024-12-29 13:42:44 +01:00
parent 1bc66814e9
commit c6287d9ddc
No known key found for this signature in database
GPG Key ID: C2FB87E71C425126
32 changed files with 1197 additions and 531 deletions

View File

@ -4,7 +4,7 @@ org.gradle.parallel=true
# Project Details
maven_group=com.viaversion
maven_version=4.0.0
maven_version=4.0.0-SNAPSHOT
maven_description=Fabric mod to connect to EVERY Minecraft server version (Release, Beta, Alpha, Classic, Snapshots, Bedrock) with QoL fixes to the gameplay
# Minecraft/Fabric

View File

@ -0,0 +1,65 @@
/*
* This file is part of ViaFabricPlus - https://github.com/ViaVersion/ViaFabricPlus
* Copyright (C) 2021-2024 the original authors
* - FlorianMichael/EnZaXD <florian.michael07@gmail.com>
* - RK_01/RaphiMC
* Copyright (C) 2023-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.entity.pose;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import net.minecraft.entity.EntityPose;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.World;
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;
@Mixin(PlayerEntity.class)
public abstract class MixinPlayerEntity extends LivingEntity {
protected MixinPlayerEntity(EntityType<? extends LivingEntity> entityType, World world) {
super(entityType, world);
}
@Inject(method = "updatePose", at = @At("HEAD"), cancellable = true)
private void onUpdatePose(CallbackInfo ci) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_13_2)) {
final EntityPose pose;
if (this.isGliding()) {
pose = EntityPose.GLIDING;
} else if (this.isSleeping()) {
pose = EntityPose.SLEEPING;
} else if (this.isSwimming()) {
pose = EntityPose.SWIMMING;
} else if (this.isUsingRiptide()) {
pose = EntityPose.SPIN_ATTACK;
} else if (this.isSneaking()) {
pose = EntityPose.CROUCHING;
} else {
pose = EntityPose.STANDING;
}
this.setPose(pose);
ci.cancel();
}
}
}

View File

@ -0,0 +1,59 @@
/*
* This file is part of ViaFabricPlus - https://github.com/ViaVersion/ViaFabricPlus
* Copyright (C) 2021-2024 the original authors
* - FlorianMichael/EnZaXD <florian.michael07@gmail.com>
* - RK_01/RaphiMC
* Copyright (C) 2023-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.entity.riding_offsets;
import com.viaversion.viafabricplus.features.entity.riding_offsets.EntityRidingOffsetsPre1_20_2;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityDimensions;
import net.minecraft.util.math.Vec3d;
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.Redirect;
@Mixin(Entity.class)
public abstract class MixinEntity {
@Shadow
protected abstract Vec3d getPassengerAttachmentPos(Entity passenger, EntityDimensions dimensions, float scaleFactor);
@Redirect(method = "updatePassengerPosition(Lnet/minecraft/entity/Entity;Lnet/minecraft/entity/Entity$PositionUpdater;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getVehicleAttachmentPos(Lnet/minecraft/entity/Entity;)Lnet/minecraft/util/math/Vec3d;"))
private Vec3d use1_20_1RidingOffset(Entity instance, Entity vehicle) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_20)) {
return new Vec3d(0, -EntityRidingOffsetsPre1_20_2.getHeightOffset(instance), 0);
} else {
return instance.getVehicleAttachmentPos(vehicle);
}
}
@Redirect(method = "getPassengerRidingPos", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getPassengerAttachmentPos(Lnet/minecraft/entity/Entity;Lnet/minecraft/entity/EntityDimensions;F)Lnet/minecraft/util/math/Vec3d;"))
private Vec3d getPassengerRidingPos1_20_1(Entity instance, Entity passenger, EntityDimensions dimensions, float scaleFactor) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_20)) {
return EntityRidingOffsetsPre1_20_2.getMountedHeightOffset(instance, passenger).rotateY(-instance.getYaw() * (float) (Math.PI / 180));
} else {
return getPassengerAttachmentPos(passenger, dimensions, scaleFactor);
}
}
}

View File

@ -0,0 +1,53 @@
/*
* This file is part of ViaFabricPlus - https://github.com/ViaVersion/ViaFabricPlus
* Copyright (C) 2021-2024 the original authors
* - FlorianMichael/EnZaXD <florian.michael07@gmail.com>
* - RK_01/RaphiMC
* Copyright (C) 2023-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.entity.riding_offsets;
import com.viaversion.viafabricplus.features.entity.riding_offsets.EntityRidingOffsetsPre1_20_2;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityDimensions;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(LivingEntity.class)
public abstract class MixinLivingEntity extends Entity {
public MixinLivingEntity(EntityType<?> type, World world) {
super(type, world);
}
@Redirect(method = "getPassengerRidingPos", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;getPassengerAttachmentPos(Lnet/minecraft/entity/Entity;Lnet/minecraft/entity/EntityDimensions;F)Lnet/minecraft/util/math/Vec3d;"))
private Vec3d getPassengerRidingPos1_20_1(LivingEntity instance, Entity entity, EntityDimensions entityDimensions, float v) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_20)) {
return EntityRidingOffsetsPre1_20_2.getMountedHeightOffset(instance, entity).rotateY(-instance.getYaw() * (float) (Math.PI / 180));
} else {
return getPassengerAttachmentPos(entity, entityDimensions, v);
}
}
}

View File

@ -0,0 +1,96 @@
/*
* This file is part of ViaFabricPlus - https://github.com/ViaVersion/ViaFabricPlus
* Copyright (C) 2021-2024 the original authors
* - FlorianMichael/EnZaXD <florian.michael07@gmail.com>
* - RK_01/RaphiMC
* Copyright (C) 2023-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement;
import com.mojang.authlib.GameProfile;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.input.Input;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.math.MathHelper;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import org.spongepowered.asm.mixin.Final;
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.Redirect;
@Mixin(value = ClientPlayerEntity.class, priority = 2000)
public abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity {
@Shadow
public Input input;
@Shadow
@Final
protected MinecraftClient client;
@Shadow
private boolean lastOnGround;
@Shadow
private int ticksSinceLastPositionPacketSent;
public MixinClientPlayerEntity(ClientWorld world, GameProfile profile) {
super(world, profile);
}
@Redirect(method = "sendMovementPackets", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;square(D)D"))
private double changeMagnitude(double n) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_18)) {
return 9.0E-4D;
} else {
return MathHelper.square(n);
}
}
@Redirect(method = "sendMovementPackets", at = @At(value = "FIELD", target = "Lnet/minecraft/client/network/ClientPlayerEntity;ticksSinceLastPositionPacketSent:I", ordinal = 0))
private int moveLastPosPacketIncrement(ClientPlayerEntity instance) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_8)) {
return this.ticksSinceLastPositionPacketSent - 1; // Reverting original operation
} else {
return this.ticksSinceLastPositionPacketSent;
}
}
@Redirect(method = "sendMovementPackets", at = @At(value = "FIELD", target = "Lnet/minecraft/client/network/ClientPlayerEntity;ticksSinceLastPositionPacketSent:I", ordinal = 2))
private int moveLastPosPacketIncrement2(ClientPlayerEntity instance) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_8)) {
return this.ticksSinceLastPositionPacketSent++; // Return previous value, then increment
} else {
return this.ticksSinceLastPositionPacketSent;
}
}
@Redirect(method = "sendMovementPackets", at = @At(value = "FIELD", target = "Lnet/minecraft/client/network/ClientPlayerEntity;lastOnGround:Z", ordinal = 0))
private boolean sendIdlePacket(ClientPlayerEntity instance) {
if (ProtocolTranslator.getTargetVersion().betweenInclusive(LegacyProtocolVersion.r1_4_2, ProtocolVersion.v1_8) || ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(LegacyProtocolVersion.r1_2_4tor1_2_5)) {
return !isOnGround();
} else {
return this.lastOnGround;
}
}
}

View File

@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.levitation_value;
package com.viaversion.viafabricplus.injection.mixin.features.movement.allow_negative_amplifier;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;

View File

@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.block;
package com.viaversion.viafabricplus.injection.mixin.features.movement.change_honey_slowness;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;

View File

@ -0,0 +1,52 @@
/*
* This file is part of ViaFabricPlus - https://github.com/ViaVersion/ViaFabricPlus
* Copyright (C) 2021-2024 the original authors
* - FlorianMichael/EnZaXD <florian.michael07@gmail.com>
* - RK_01/RaphiMC
* Copyright (C) 2023-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.elytra_movement;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.mojang.authlib.GameProfile;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(value = ClientPlayerEntity.class, priority = 2000)
public abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity {
public MixinClientPlayerEntity(ClientWorld world, GameProfile profile) {
super(world, profile);
}
@Redirect(method = "canStartSprinting", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isGliding()Z"))
private boolean removeGlidingCheck(ClientPlayerEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_19_3) && instance.isGliding();
}
@ModifyExpressionValue(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isClimbing()Z"))
private boolean allowElytraWhenClimbing(boolean original) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_15_1) && original;
}
}

View File

@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.elytra;
package com.viaversion.viafabricplus.injection.mixin.features.movement.elytra_movement;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;

View File

@ -0,0 +1,64 @@
/*
* This file is part of ViaFabricPlus - https://github.com/ViaVersion/ViaFabricPlus
* Copyright (C) 2021-2024 the original authors
* - FlorianMichael/EnZaXD <florian.michael07@gmail.com>
* - RK_01/RaphiMC
* Copyright (C) 2023-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.elytra_movement;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.effect.StatusEffect;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(LivingEntity.class)
public abstract class MixinLivingEntity extends Entity {
public MixinLivingEntity(EntityType<?> type, World world) {
super(type, world);
}
@Redirect(method = "calcGlidingVelocity", at = @At(value = "INVOKE", target = "Ljava/lang/Math;cos(D)D", remap = false))
private double fixCosTable(double a) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_18)) {
return MathHelper.cos((float) a);
} else {
return Math.cos(a);
}
}
@Redirect(method = "canGlide", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;hasStatusEffect(Lnet/minecraft/registry/entry/RegistryEntry;)Z"))
private boolean allowElytraWhenLevitating(LivingEntity instance, RegistryEntry<StatusEffect> effect) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_15_2) && instance.hasStatusEffect(effect);
}
@Redirect(method = "canGlide", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;hasVehicle()Z"))
private boolean allowElytraInVehicle(LivingEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_14_4) && instance.hasVehicle();
}
}

View File

@ -0,0 +1,59 @@
/*
* This file is part of ViaFabricPlus - https://github.com/ViaVersion/ViaFabricPlus
* Copyright (C) 2021-2024 the original authors
* - FlorianMichael/EnZaXD <florian.michael07@gmail.com>
* - RK_01/RaphiMC
* Copyright (C) 2023-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.elytra_movement;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.world.World;
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.CallbackInfoReturnable;
@Mixin(PlayerEntity.class)
public abstract class MixinPlayerEntity extends LivingEntity {
protected MixinPlayerEntity(EntityType<? extends LivingEntity> entityType, World world) {
super(entityType, world);
}
@Inject(method = "checkGliding", at = @At("HEAD"), cancellable = true)
private void replaceGlidingCondition(CallbackInfoReturnable<Boolean> cir) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_14_4)) {
if (!this.isOnGround() && this.getVelocity().y < 0D && !this.isGliding()) {
final ItemStack itemStack = this.getEquippedStack(EquipmentSlot.CHEST);
if (itemStack.isOf(Items.ELYTRA) && canGlideWith(itemStack, EquipmentSlot.CHEST)) {
cir.setReturnValue(true);
return;
}
}
cir.setReturnValue(false);
}
}
}

View File

@ -1,290 +0,0 @@
/*
* This file is part of ViaFabricPlus - https://github.com/ViaVersion/ViaFabricPlus
* Copyright (C) 2021-2024 the original authors
* - FlorianMichael/EnZaXD <florian.michael07@gmail.com>
* - RK_01/RaphiMC
* Copyright (C) 2023-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.entity;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import com.mojang.authlib.GameProfile;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viafabricplus.injection.access.base.IClientConnection;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.input.Input;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.minecraft.entity.vehicle.BoatEntity;
import net.minecraft.network.packet.Packet;
import net.minecraft.util.math.MathHelper;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.vialegacy.protocol.release.r1_5_2tor1_6_1.Protocolr1_5_2Tor1_6_1;
import net.raphimc.vialegacy.protocol.release.r1_5_2tor1_6_1.packet.ServerboundPackets1_5_2;
import org.spongepowered.asm.mixin.Final;
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.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.Slice;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(value = ClientPlayerEntity.class, priority = 2000)
public abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity {
@Shadow
public Input input;
@Shadow
@Final
protected MinecraftClient client;
@Shadow
private boolean lastOnGround;
@Shadow
private int ticksSinceLastPositionPacketSent;
@Shadow
@Final
public ClientPlayNetworkHandler networkHandler;
@Shadow
public abstract void setClientPermissionLevel(int clientPermissionLevel);
@Shadow
private boolean inSneakingPose;
@Shadow
protected abstract void sendSneakingPacket();
@Shadow
protected abstract boolean shouldStopSprinting();
public MixinClientPlayerEntity(ClientWorld world, GameProfile profile) {
super(world, profile);
}
@Redirect(method = "canStartSprinting", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;shouldSlowDown()Z"))
private boolean removeSlowdownCondition(ClientPlayerEntity instance) {
return instance.shouldSlowDown() && ProtocolTranslator.getTargetVersion().newerThanOrEqualTo(ProtocolVersion.v1_21_4);
}
@Redirect(method = "canStartSprinting", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isSubmergedInWater()Z"))
private boolean removeSlowdownCondition2(ClientPlayerEntity instance) {
return instance.isSubmergedInWater() && ProtocolTranslator.getTargetVersion().newerThanOrEqualTo(ProtocolVersion.v1_21_4);
}
@Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;shouldStopSprinting()Z"))
private boolean dontUnsprint(ClientPlayerEntity instance) {
return shouldStopSprinting() && ProtocolTranslator.getTargetVersion().newerThanOrEqualTo(ProtocolVersion.v1_21_4);
}
@WrapWithCondition(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;sendSneakingPacket()V"))
private boolean sendSneakingAfterSprinting(ClientPlayerEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThanOrEqualTo(ProtocolVersion.v1_21_2);
}
@Inject(method = "sendMovementPackets", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;sendSprintingPacket()V", shift = At.Shift.AFTER))
private void sendSneakingAfterSprinting(CallbackInfo ci) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_21)) {
this.sendSneakingPacket();
}
}
@WrapWithCondition(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;jump()V"))
private boolean dontJumpBeforeFlying(ClientPlayerEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThanOrEqualTo(ProtocolVersion.v1_20_5);
}
@Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;hasVehicle()Z", ordinal = 0))
private boolean removeVehicleRequirement(ClientPlayerEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_20) && instance.hasVehicle();
}
@WrapWithCondition(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;sendSprintingPacket()V"))
private boolean removeSprintingPacket(ClientPlayerEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThanOrEqualTo(ProtocolVersion.v1_19_3);
}
@Redirect(method = "autoJump", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;inverseSqrt(F)F"))
private float useFastInverseSqrt(float x) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_19_3)) {
x = Float.intBitsToFloat(1597463007 - (Float.floatToIntBits(x) >> 1));
return x * (1.5F - (0.5F * x) * x * x);
} else {
return MathHelper.inverseSqrt(x);
}
}
@Redirect(method = "canStartSprinting", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;hasVehicle()Z"))
private boolean removeVehicleCheck(ClientPlayerEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_19_3) && instance.hasVehicle();
}
@Redirect(method = "canStartSprinting", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isGliding()Z"))
private boolean removeGlidingCheck(ClientPlayerEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_19_3) && instance.isGliding();
}
@Redirect(method = "canSprint", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;hasVehicle()Z"))
private boolean dontAllowSprintingAsPassenger(ClientPlayerEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_19_1) && instance.hasVehicle();
}
@Redirect(method = "sendMovementPackets", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;square(D)D"))
private double changeMagnitude(double n) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_18)) {
return 9.0E-4D;
} else {
return MathHelper.square(n);
}
}
@Inject(method = "startRiding", at = @At("RETURN"))
private void setRotationsWhenInBoat(Entity entity, boolean force, CallbackInfoReturnable<Boolean> cir) {
if (cir.getReturnValueZ() && entity instanceof BoatEntity && ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_18)) {
this.prevYaw = entity.getYaw();
this.setYaw(entity.getYaw());
this.setHeadYaw(entity.getYaw());
}
}
@ModifyExpressionValue(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isClimbing()Z"))
private boolean allowElytraWhenClimbing(boolean original) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_15_1) && original;
}
@Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;shouldSlowDown()Z"))
private boolean changeSneakSlowdownCondition(ClientPlayerEntity instance) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_13_2)) {
return instance.input.playerInput.sneak();
} else if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_14_4)) {
return !MinecraftClient.getInstance().player.isSpectator() && (instance.input.playerInput.sneak() || instance.shouldSlowDown());
} else {
return instance.shouldSlowDown();
}
}
@Inject(method = "tickMovement()V",
slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isCamera()Z")),
at = @At(value = "INVOKE", target = "Lnet/minecraft/util/PlayerInput;sneak()Z", ordinal = 0))
private void undoSneakSlowdownForFly(CallbackInfo ci) {
if (ProtocolTranslator.getTargetVersion().betweenInclusive(ProtocolVersion.v1_9, ProtocolVersion.v1_14_4)) {
if (this.input.playerInput.sneak()) {
this.input.movementSideways = (float) ((double) this.input.movementSideways / 0.3D);
this.input.movementForward = (float) ((double) this.input.movementForward / 0.3D);
}
}
}
@Inject(method = "isWalking", at = @At("HEAD"), cancellable = true)
private void easierUnderwaterSprinting(CallbackInfoReturnable<Boolean> cir) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_14_1)) {
cir.setReturnValue(((ClientPlayerEntity) (Object) this).input.movementForward >= 0.8);
}
}
@Redirect(method = "tickMovement()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/input/Input;hasForwardMovement()Z", ordinal = 0))
private boolean disableSprintSneak(Input input) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_14_1)) {
return input.movementForward >= 0.8F;
} else {
return input.hasForwardMovement();
}
}
@Redirect(method = "tickMovement",
slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isWalking()Z")),
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isSwimming()Z", ordinal = 0))
private boolean dontAllowSneakingWhileSwimming(ClientPlayerEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_14_1) && instance.isSwimming();
}
@Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;getAttributeValue(Lnet/minecraft/registry/entry/RegistryEntry;)D"))
private void removeSneakingConditions(CallbackInfo ci) { // Allows sneaking while flying, inside blocks and vehicles
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_13_2)) {
this.inSneakingPose = this.isSneaking() && !this.isSleeping();
}
}
@Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isTouchingWater()Z"))
private boolean disableWaterRelatedMovement(ClientPlayerEntity self) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_12_2) && self.isTouchingWater();
}
@Inject(method = "init", at = @At("RETURN"))
private void setOpLevel4(CallbackInfo ci) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_8)) {
this.setClientPermissionLevel(4);
}
}
@Redirect(method = "sendMovementPackets", at = @At(value = "FIELD", target = "Lnet/minecraft/client/network/ClientPlayerEntity;ticksSinceLastPositionPacketSent:I", ordinal = 0))
private int moveLastPosPacketIncrement(ClientPlayerEntity instance) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_8)) {
return this.ticksSinceLastPositionPacketSent - 1; // Reverting original operation
} else {
return this.ticksSinceLastPositionPacketSent;
}
}
@Redirect(method = "sendMovementPackets", at = @At(value = "FIELD", target = "Lnet/minecraft/client/network/ClientPlayerEntity;ticksSinceLastPositionPacketSent:I", ordinal = 2))
private int moveLastPosPacketIncrement2(ClientPlayerEntity instance) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_8)) {
return this.ticksSinceLastPositionPacketSent++; // Return previous value, then increment
} else {
return this.ticksSinceLastPositionPacketSent;
}
}
@Redirect(method = "sendMovementPackets", at = @At(value = "FIELD", target = "Lnet/minecraft/client/network/ClientPlayerEntity;lastOnGround:Z", ordinal = 0))
private boolean sendIdlePacket(ClientPlayerEntity instance) {
if (ProtocolTranslator.getTargetVersion().betweenInclusive(LegacyProtocolVersion.r1_4_2, ProtocolVersion.v1_8) || ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(LegacyProtocolVersion.r1_2_4tor1_2_5)) {
return !isOnGround();
} else {
return this.lastOnGround;
}
}
@Redirect(method = "tick", slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;hasVehicle()Z")), at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/packet/Packet;)V", ordinal = 0))
private void modifyPositionPacket(ClientPlayNetworkHandler instance, Packet<?> packet) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(LegacyProtocolVersion.r1_5_2)) {
final PacketWrapper movePlayerPosRot = PacketWrapper.create(ServerboundPackets1_5_2.MOVE_PLAYER_POS_ROT, ((IClientConnection) this.networkHandler.getConnection()).viaFabricPlus$getUserConnection());
movePlayerPosRot.write(Types.DOUBLE, this.getVelocity().x); // x
movePlayerPosRot.write(Types.DOUBLE, -999.0D); // y
movePlayerPosRot.write(Types.DOUBLE, -999.0D); // stance
movePlayerPosRot.write(Types.DOUBLE, this.getVelocity().z); // z
movePlayerPosRot.write(Types.FLOAT, this.getYaw()); // yaw
movePlayerPosRot.write(Types.FLOAT, this.getPitch()); // pitch
movePlayerPosRot.write(Types.BOOLEAN, this.isOnGround()); // onGround
movePlayerPosRot.scheduleSendToServer(Protocolr1_5_2Tor1_6_1.class);
return;
}
instance.sendPacket(packet);
}
}

View File

@ -55,24 +55,12 @@ public abstract class MixinEntity {
@Shadow
private World world;
@Shadow
protected Object2DoubleMap<TagKey<Fluid>> fluidHeight;
@Shadow
private Vec3d pos;
@Shadow
public abstract Box getBoundingBox();
@Shadow
public abstract Vec3d getVelocity();
@Shadow
public abstract void setVelocity(Vec3d velocity);
@Shadow
protected abstract Vec3d getPassengerAttachmentPos(Entity passenger, EntityDimensions dimensions, float scaleFactor);
@Shadow
public abstract World getWorld();
@ -132,33 +120,6 @@ public abstract class MixinEntity {
}
}
@Redirect(method = "updateSubmergedInWaterState", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getEyeY()D"))
private double addMagicOffset(Entity instance) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_20_3)) {
return instance.getEyeY() - 0.11111111F;
} else {
return instance.getEyeY();
}
}
@Redirect(method = "updatePassengerPosition(Lnet/minecraft/entity/Entity;Lnet/minecraft/entity/Entity$PositionUpdater;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getVehicleAttachmentPos(Lnet/minecraft/entity/Entity;)Lnet/minecraft/util/math/Vec3d;"))
private Vec3d use1_20_1RidingOffset(Entity instance, Entity vehicle) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_20)) {
return new Vec3d(0, -EntityRidingOffsetsPre1_20_2.getHeightOffset(instance), 0);
} else {
return instance.getVehicleAttachmentPos(vehicle);
}
}
@Redirect(method = "getPassengerRidingPos", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getPassengerAttachmentPos(Lnet/minecraft/entity/Entity;Lnet/minecraft/entity/EntityDimensions;F)Lnet/minecraft/util/math/Vec3d;"))
private Vec3d getPassengerRidingPos1_20_1(Entity instance, Entity passenger, EntityDimensions dimensions, float scaleFactor) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_20)) {
return EntityRidingOffsetsPre1_20_2.getMountedHeightOffset(instance, passenger).rotateY(-instance.getYaw() * (float) (Math.PI / 180));
} else {
return getPassengerAttachmentPos(passenger, dimensions, scaleFactor);
}
}
@Inject(method = "getPosWithYOffset", at = @At("HEAD"), cancellable = true)
private void modifyPosWithYOffset(float offset, CallbackInfoReturnable<BlockPos> cir) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_19_4)) {
@ -229,65 +190,6 @@ public abstract class MixinEntity {
}
}
@Inject(method = "setSwimming", at = @At("HEAD"), cancellable = true)
private void cancelSwimming(boolean swimming, CallbackInfo ci) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_12_2) && swimming) {
ci.cancel();
}
}
@Inject(method = "updateMovementInFluid", at = @At("HEAD"), cancellable = true)
private void modifyFluidMovementBoundingBox(TagKey<Fluid> fluidTag, double d, CallbackInfoReturnable<Boolean> cir) {
if (ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_12_2)) {
return;
}
Box box = this.getBoundingBox().expand(0, -0.4, 0).contract(0.001);
int minX = MathHelper.floor(box.minX);
int maxX = MathHelper.ceil(box.maxX);
int minY = MathHelper.floor(box.minY);
int maxY = MathHelper.ceil(box.maxY);
int minZ = MathHelper.floor(box.minZ);
int maxZ = MathHelper.ceil(box.maxZ);
if (!this.world.isRegionLoaded(minX, minY, minZ, maxX, maxY, maxZ)) {
cir.setReturnValue(false);
return;
}
double waterHeight = 0;
boolean foundFluid = false;
Vec3d pushVec = Vec3d.ZERO;
BlockPos.Mutable mutable = new BlockPos.Mutable();
for (int x = minX; x < maxX; x++) {
for (int y = minY - 1; y < maxY; y++) {
for (int z = minZ; z < maxZ; z++) {
mutable.set(x, y, z);
FluidState state = this.world.getFluidState(mutable);
if (state.isIn(fluidTag)) {
double height = y + state.getHeight(this.world, mutable);
if (height >= box.minY - 0.4)
waterHeight = Math.max(height - box.minY + 0.4, waterHeight);
if (y >= minY && maxY >= height) {
foundFluid = true;
pushVec = pushVec.add(state.getVelocity(this.world, mutable));
}
}
}
}
}
if (pushVec.length() > 0) {
pushVec = pushVec.normalize().multiply(0.014);
this.setVelocity(this.getVelocity().add(pushVec));
}
this.fluidHeight.put(fluidTag, waterHeight);
cir.setReturnValue(foundFluid);
}
@Inject(method = "getTargetingMargin", at = @At("HEAD"), cancellable = true)
private void expandHitBox(CallbackInfoReturnable<Float> cir) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_8)) {

View File

@ -56,9 +56,6 @@ public abstract class MixinLivingEntity extends Entity {
@Shadow
protected boolean jumping;
@Shadow
protected abstract float getBaseWaterMovementSpeedMultiplier();
@Shadow
private Optional<BlockPos> climbingPos;
@ -84,15 +81,6 @@ public abstract class MixinLivingEntity extends Entity {
}
}
@Redirect(method = "getPassengerRidingPos", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;getPassengerAttachmentPos(Lnet/minecraft/entity/Entity;Lnet/minecraft/entity/EntityDimensions;F)Lnet/minecraft/util/math/Vec3d;"))
private Vec3d getPassengerRidingPos1_20_1(LivingEntity instance, Entity entity, EntityDimensions entityDimensions, float v) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_20)) {
return EntityRidingOffsetsPre1_20_2.getMountedHeightOffset(instance, entity).rotateY(-instance.getYaw() * (float) (Math.PI / 180));
} else {
return getPassengerAttachmentPos(entity, entityDimensions, v);
}
}
@Inject(method = "tickCramming", at = @At("HEAD"), cancellable = true)
private void preventEntityPush(CallbackInfo ci) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_8)) {
@ -100,34 +88,6 @@ public abstract class MixinLivingEntity extends Entity {
}
}
@Redirect(method = "calcGlidingVelocity", at = @At(value = "INVOKE", target = "Ljava/lang/Math;cos(D)D", remap = false))
private double fixCosTable(double a) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_18)) {
return MathHelper.cos((float) a);
} else {
return Math.cos(a);
}
}
@Redirect(method = "travelInFluid", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;getFluidHeight(Lnet/minecraft/registry/tag/TagKey;)D"))
private double dontApplyLavaMovement(LivingEntity instance, TagKey<Fluid> tagKey) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_15_2)) {
return Double.MAX_VALUE;
} else {
return instance.getFluidHeight(tagKey);
}
}
@Redirect(method = "canGlide", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;hasStatusEffect(Lnet/minecraft/registry/entry/RegistryEntry;)Z"))
private boolean allowElytraWhenLevitating(LivingEntity instance, RegistryEntry<StatusEffect> effect) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_15_2) && instance.hasStatusEffect(effect);
}
@Redirect(method = "canGlide", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;hasVehicle()Z"))
private boolean allowElytraInVehicle(LivingEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_14_4) && instance.hasVehicle();
}
@Redirect(method = "tickActiveItemStack", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;areItemsEqual(Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ItemStack;)Z"))
private boolean replaceItemStackEqualsCheck(ItemStack left, ItemStack right) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_14_3)) {
@ -151,18 +111,6 @@ public abstract class MixinLivingEntity extends Entity {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_13_2) && jumping;
}
@Redirect(method = "travelInFluid",
slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/entity/effect/StatusEffects;DOLPHINS_GRACE:Lnet/minecraft/registry/entry/RegistryEntry;")),
at = @At(value = "FIELD", target = "Lnet/minecraft/entity/LivingEntity;horizontalCollision:Z", ordinal = 0))
private boolean disableClimbing(LivingEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_13_2) && instance.horizontalCollision;
}
@ModifyVariable(method = "applyFluidMovingSpeed", ordinal = 0, at = @At("HEAD"), argsOnly = true)
private boolean modifyMovingDown(boolean movingDown) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_13_2) && movingDown;
}
@Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;onLanding()V"))
private void dontResetLevitationFallDistance(LivingEntity instance) {
if (this.hasStatusEffect(StatusEffects.SLOW_FALLING) || ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_12_2)) {
@ -170,35 +118,6 @@ public abstract class MixinLivingEntity extends Entity {
}
}
@Redirect(method = "travelInFluid", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;isSprinting()Z", ordinal = 0))
private boolean modifySwimSprintSpeed(LivingEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_12_2) && instance.isSprinting();
}
@Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;getFluidHeight(Lnet/minecraft/registry/tag/TagKey;)D"))
private double redirectFluidHeight(LivingEntity instance, TagKey<Fluid> tagKey) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_12_2) && tagKey == FluidTags.WATER) {
if (instance.getFluidHeight(tagKey) > 0) return 1;
}
return instance.getFluidHeight(tagKey);
}
@Inject(method = "applyFluidMovingSpeed", at = @At("HEAD"), cancellable = true)
private void modifySwimSprintFallSpeed(double gravity, boolean movingDown, Vec3d velocity, CallbackInfoReturnable<Vec3d> ci) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_12_2) && !this.hasNoGravity()) {
ci.setReturnValue(new Vec3d(velocity.x, velocity.y - 0.02, velocity.z));
}
}
@ModifyConstant(method = "travelInFluid", constant = @Constant(floatValue = 0.9F))
private float modifySwimFriction(float constant) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_12_2)) {
return this.getBaseWaterMovementSpeedMultiplier();
} else {
return constant;
}
}
@Inject(method = "getPreferredEquipmentSlot", at = @At("HEAD"), cancellable = true)
private void removeShieldSlotPreference(ItemStack stack, CallbackInfoReturnable<EquipmentSlot> cir) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_9_3) && stack.isOf(Items.SHIELD)) {

View File

@ -131,42 +131,6 @@ public abstract class MixinPlayerEntity extends LivingEntity {
}
}
@Inject(method = "checkGliding", at = @At("HEAD"), cancellable = true)
private void replaceGlidingCondition(CallbackInfoReturnable<Boolean> cir) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_14_4)) {
if (!this.isOnGround() && this.getVelocity().y < 0D && !this.isGliding()) {
final ItemStack itemStack = this.getEquippedStack(EquipmentSlot.CHEST);
if (itemStack.isOf(Items.ELYTRA) && canGlideWith(itemStack, EquipmentSlot.CHEST)) {
cir.setReturnValue(true);
return;
}
}
cir.setReturnValue(false);
}
}
@Inject(method = "updatePose", at = @At("HEAD"), cancellable = true)
private void onUpdatePose(CallbackInfo ci) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_13_2)) {
final EntityPose pose;
if (this.isGliding()) {
pose = EntityPose.GLIDING;
} else if (this.isSleeping()) {
pose = EntityPose.SLEEPING;
} else if (this.isSwimming()) {
pose = EntityPose.SWIMMING;
} else if (this.isUsingRiptide()) {
pose = EntityPose.SPIN_ATTACK;
} else if (this.isSneaking()) {
pose = EntityPose.CROUCHING;
} else {
pose = EntityPose.STANDING;
}
this.setPose(pose);
ci.cancel();
}
}
@Inject(method = "getBaseDimensions", at = @At("HEAD"), cancellable = true)
private void modifyDimensions(EntityPose pose, CallbackInfoReturnable<EntityDimensions> cir) {
if (pose == EntityPose.CROUCHING) {

View File

@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.block;
package com.viaversion.viafabricplus.injection.mixin.features.movement.handle_slowness_on_collision;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;

View File

@ -0,0 +1,58 @@
/*
* This file is part of ViaFabricPlus - https://github.com/ViaVersion/ViaFabricPlus
* Copyright (C) 2021-2024 the original authors
* - FlorianMichael/EnZaXD <florian.michael07@gmail.com>
* - RK_01/RaphiMC
* Copyright (C) 2023-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.jump;
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import com.mojang.authlib.GameProfile;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.math.MathHelper;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(ClientPlayerEntity.class)
public abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity {
public MixinClientPlayerEntity(ClientWorld world, GameProfile profile) {
super(world, profile);
}
@WrapWithCondition(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;jump()V"))
private boolean dontJumpBeforeFlying(ClientPlayerEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThanOrEqualTo(ProtocolVersion.v1_20_5);
}
@Redirect(method = "autoJump", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;inverseSqrt(F)F"))
private float useFastInverseSqrt(float x) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_19_3)) {
x = Float.intBitsToFloat(1597463007 - (Float.floatToIntBits(x) >> 1));
return x * (1.5F - (0.5F * x) * x * x);
} else {
return MathHelper.inverseSqrt(x);
}
}
}

View File

@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.block;
package com.viaversion.viafabricplus.injection.mixin.features.movement.remove_bed_bounce;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;

View File

@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.entity;
package com.viaversion.viafabricplus.injection.mixin.features.movement.replace_boat_movement;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;

View File

@ -0,0 +1,64 @@
/*
* This file is part of ViaFabricPlus - https://github.com/ViaVersion/ViaFabricPlus
* Copyright (C) 2021-2024 the original authors
* - FlorianMichael/EnZaXD <florian.michael07@gmail.com>
* - RK_01/RaphiMC
* Copyright (C) 2023-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.replace_boat_movement;
import com.mojang.authlib.GameProfile;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.minecraft.entity.vehicle.BoatEntity;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(value = ClientPlayerEntity.class, priority = 2000)
public abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity {
public MixinClientPlayerEntity(ClientWorld world, GameProfile profile) {
super(world, profile);
}
@Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;hasVehicle()Z", ordinal = 0))
private boolean removeVehicleRequirement(ClientPlayerEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_20) && instance.hasVehicle();
}
@Redirect(method = "canStartSprinting", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;hasVehicle()Z"))
private boolean removeVehicleCheck(ClientPlayerEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_19_3) && instance.hasVehicle();
}
@Inject(method = "startRiding", at = @At("RETURN"))
private void setRotationsWhenInBoat(Entity entity, boolean force, CallbackInfoReturnable<Boolean> cir) {
if (cir.getReturnValueZ() && entity instanceof BoatEntity && ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_18)) {
this.prevYaw = entity.getYaw();
this.setYaw(entity.getYaw());
this.setHeadYaw(entity.getYaw());
}
}
}

View File

@ -0,0 +1,82 @@
/*
* This file is part of ViaFabricPlus - https://github.com/ViaVersion/ViaFabricPlus
* Copyright (C) 2021-2024 the original authors
* - FlorianMichael/EnZaXD <florian.michael07@gmail.com>
* - RK_01/RaphiMC
* Copyright (C) 2023-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.slowdown_calculation_changes;
import com.mojang.authlib.GameProfile;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.input.Input;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
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.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.Slice;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(value = ClientPlayerEntity.class, priority = 2000)
public abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity {
@Shadow public Input input;
public MixinClientPlayerEntity(ClientWorld world, GameProfile profile) {
super(world, profile);
}
@Redirect(method = "canStartSprinting", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;shouldSlowDown()Z"))
private boolean removeSlowdownCondition(ClientPlayerEntity instance) {
return instance.shouldSlowDown() && ProtocolTranslator.getTargetVersion().newerThanOrEqualTo(ProtocolVersion.v1_21_4);
}
@Redirect(method = "canStartSprinting", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isSubmergedInWater()Z"))
private boolean removeSlowdownCondition2(ClientPlayerEntity instance) {
return instance.isSubmergedInWater() && ProtocolTranslator.getTargetVersion().newerThanOrEqualTo(ProtocolVersion.v1_21_4);
}
@Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;shouldSlowDown()Z"))
private boolean changeSneakSlowdownCondition(ClientPlayerEntity instance) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_13_2)) {
return instance.input.playerInput.sneak();
} else if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_14_4)) {
return !MinecraftClient.getInstance().player.isSpectator() && (instance.input.playerInput.sneak() || instance.shouldSlowDown());
} else {
return instance.shouldSlowDown();
}
}
@Inject(method = "tickMovement()V",
slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isCamera()Z")),
at = @At(value = "INVOKE", target = "Lnet/minecraft/util/PlayerInput;sneak()Z", ordinal = 0))
private void undoSneakSlowdownForFly(CallbackInfo ci) {
if (ProtocolTranslator.getTargetVersion().betweenInclusive(ProtocolVersion.v1_9, ProtocolVersion.v1_14_4)) {
if (this.input.playerInput.sneak()) {
this.input.movementSideways = (float) ((double) this.input.movementSideways / 0.3D);
this.input.movementForward = (float) ((double) this.input.movementForward / 0.3D);
}
}
}
}

View File

@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.item;
package com.viaversion.viafabricplus.injection.mixin.features.movement.slowdown_calculation_changes;
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;

View File

@ -0,0 +1,95 @@
/*
* This file is part of ViaFabricPlus - https://github.com/ViaVersion/ViaFabricPlus
* Copyright (C) 2021-2024 the original authors
* - FlorianMichael/EnZaXD <florian.michael07@gmail.com>
* - RK_01/RaphiMC
* Copyright (C) 2023-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.sprinting_sneaking_condition_changes;
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import com.mojang.authlib.GameProfile;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import net.minecraft.client.input.Input;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
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.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(value = ClientPlayerEntity.class, priority = 2000)
public abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity {
@Shadow protected abstract boolean shouldStopSprinting();
@Shadow protected abstract void sendSneakingPacket();
@Shadow private boolean inSneakingPose;
public MixinClientPlayerEntity(ClientWorld world, GameProfile profile) {
super(world, profile);
}
@Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;shouldStopSprinting()Z"))
private boolean dontUnsprint(ClientPlayerEntity instance) {
return shouldStopSprinting() && ProtocolTranslator.getTargetVersion().newerThanOrEqualTo(ProtocolVersion.v1_21_4);
}
@WrapWithCondition(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;sendSneakingPacket()V"))
private boolean sendSneakingAfterSprinting(ClientPlayerEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThanOrEqualTo(ProtocolVersion.v1_21_2);
}
@Inject(method = "sendMovementPackets", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;sendSprintingPacket()V", shift = At.Shift.AFTER))
private void sendSneakingAfterSprinting(CallbackInfo ci) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_21)) {
this.sendSneakingPacket();
}
}
@WrapWithCondition(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;sendSprintingPacket()V"))
private boolean removeSprintingPacket(ClientPlayerEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThanOrEqualTo(ProtocolVersion.v1_19_3);
}
@Redirect(method = "canSprint", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;hasVehicle()Z"))
private boolean dontAllowSprintingAsPassenger(ClientPlayerEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_19_1) && instance.hasVehicle();
}
@Redirect(method = "tickMovement()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/input/Input;hasForwardMovement()Z", ordinal = 0))
private boolean disableSprintSneak(Input input) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_14_1)) {
return input.movementForward >= 0.8F;
} else {
return input.hasForwardMovement();
}
}
@Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;getAttributeValue(Lnet/minecraft/registry/entry/RegistryEntry;)D"))
private void removeSneakingConditions(CallbackInfo ci) { // Allows sneaking while flying, inside blocks and vehicles
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_13_2)) {
this.inSneakingPose = this.isSneaking() && !this.isSleeping();
}
}
}

View File

@ -0,0 +1,72 @@
/*
* This file is part of ViaFabricPlus - https://github.com/ViaVersion/ViaFabricPlus
* Copyright (C) 2021-2024 the original authors
* - FlorianMichael/EnZaXD <florian.michael07@gmail.com>
* - RK_01/RaphiMC
* Copyright (C) 2023-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.v1_5_2_vehicle_movement;
import com.mojang.authlib.GameProfile;
import com.viaversion.viafabricplus.injection.access.base.IClientConnection;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.network.packet.Packet;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.vialegacy.protocol.release.r1_5_2tor1_6_1.Protocolr1_5_2Tor1_6_1;
import net.raphimc.vialegacy.protocol.release.r1_5_2tor1_6_1.packet.ServerboundPackets1_5_2;
import org.spongepowered.asm.mixin.Final;
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.Redirect;
import org.spongepowered.asm.mixin.injection.Slice;
@Mixin(ClientPlayerEntity.class)
public abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity {
@Shadow
@Final
public ClientPlayNetworkHandler networkHandler;
public MixinClientPlayerEntity(ClientWorld world, GameProfile profile) {
super(world, profile);
}
@Redirect(method = "tick", slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;hasVehicle()Z")), at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/packet/Packet;)V", ordinal = 0))
private void modifyPositionPacket(ClientPlayNetworkHandler instance, Packet<?> packet) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(LegacyProtocolVersion.r1_5_2)) {
final PacketWrapper movePlayerPosRot = PacketWrapper.create(ServerboundPackets1_5_2.MOVE_PLAYER_POS_ROT, ((IClientConnection) this.networkHandler.getConnection()).viaFabricPlus$getUserConnection());
movePlayerPosRot.write(Types.DOUBLE, this.getVelocity().x); // x
movePlayerPosRot.write(Types.DOUBLE, -999.0D); // y
movePlayerPosRot.write(Types.DOUBLE, -999.0D); // stance
movePlayerPosRot.write(Types.DOUBLE, this.getVelocity().z); // z
movePlayerPosRot.write(Types.FLOAT, this.getYaw()); // yaw
movePlayerPosRot.write(Types.FLOAT, this.getPitch()); // pitch
movePlayerPosRot.write(Types.BOOLEAN, this.isOnGround()); // onGround
movePlayerPosRot.scheduleSendToServer(Protocolr1_5_2Tor1_6_1.class);
return;
}
instance.sendPacket(packet);
}
}

View File

@ -0,0 +1,63 @@
/*
* This file is part of ViaFabricPlus - https://github.com/ViaVersion/ViaFabricPlus
* Copyright (C) 2021-2024 the original authors
* - FlorianMichael/EnZaXD <florian.michael07@gmail.com>
* - RK_01/RaphiMC
* Copyright (C) 2023-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.water_movement;
import com.mojang.authlib.GameProfile;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
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.Redirect;
import org.spongepowered.asm.mixin.injection.Slice;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(value = ClientPlayerEntity.class, priority = 2000)
public abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity {
public MixinClientPlayerEntity(ClientWorld world, GameProfile profile) {
super(world, profile);
}
@Inject(method = "isWalking", at = @At("HEAD"), cancellable = true)
private void easierUnderwaterSprinting(CallbackInfoReturnable<Boolean> cir) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_14_1)) {
cir.setReturnValue(((ClientPlayerEntity) (Object) this).input.movementForward >= 0.8);
}
}
@Redirect(method = "tickMovement",
slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isWalking()Z")),
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isSwimming()Z", ordinal = 0))
private boolean dontAllowSneakingWhileSwimming(ClientPlayerEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_14_1) && instance.isSwimming();
}
@Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isTouchingWater()Z"))
private boolean disableWaterRelatedMovement(ClientPlayerEntity self) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_12_2) && self.isTouchingWater();
}
}

View File

@ -0,0 +1,129 @@
/*
* This file is part of ViaFabricPlus - https://github.com/ViaVersion/ViaFabricPlus
* Copyright (C) 2021-2024 the original authors
* - FlorianMichael/EnZaXD <florian.michael07@gmail.com>
* - RK_01/RaphiMC
* Copyright (C) 2023-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.water_movement;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import it.unimi.dsi.fastutil.objects.Object2DoubleMap;
import net.minecraft.entity.Entity;
import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.FluidState;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
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.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(Entity.class)
public abstract class MixinEntity {
@Shadow
protected Object2DoubleMap<TagKey<Fluid>> fluidHeight;
@Shadow
private World world;
@Shadow
public abstract Box getBoundingBox();
@Shadow
public abstract Vec3d getVelocity();
@Shadow
public abstract void setVelocity(Vec3d velocity);
@Redirect(method = "updateSubmergedInWaterState", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getEyeY()D"))
private double addMagicOffset(Entity instance) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_20_3)) {
return instance.getEyeY() - 0.11111111F;
} else {
return instance.getEyeY();
}
}
@Inject(method = "setSwimming", at = @At("HEAD"), cancellable = true)
private void cancelSwimming(boolean swimming, CallbackInfo ci) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_12_2) && swimming) {
ci.cancel();
}
}
@Inject(method = "updateMovementInFluid", at = @At("HEAD"), cancellable = true)
private void modifyFluidMovementBoundingBox(TagKey<Fluid> fluidTag, double d, CallbackInfoReturnable<Boolean> cir) {
if (ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_12_2)) {
return;
}
Box box = this.getBoundingBox().expand(0, -0.4, 0).contract(0.001);
int minX = MathHelper.floor(box.minX);
int maxX = MathHelper.ceil(box.maxX);
int minY = MathHelper.floor(box.minY);
int maxY = MathHelper.ceil(box.maxY);
int minZ = MathHelper.floor(box.minZ);
int maxZ = MathHelper.ceil(box.maxZ);
if (!this.world.isRegionLoaded(minX, minY, minZ, maxX, maxY, maxZ)) {
cir.setReturnValue(false);
return;
}
double waterHeight = 0;
boolean foundFluid = false;
Vec3d pushVec = Vec3d.ZERO;
BlockPos.Mutable mutable = new BlockPos.Mutable();
for (int x = minX; x < maxX; x++) {
for (int y = minY - 1; y < maxY; y++) {
for (int z = minZ; z < maxZ; z++) {
mutable.set(x, y, z);
FluidState state = this.world.getFluidState(mutable);
if (state.isIn(fluidTag)) {
double height = y + state.getHeight(this.world, mutable);
if (height >= box.minY - 0.4)
waterHeight = Math.max(height - box.minY + 0.4, waterHeight);
if (y >= minY && maxY >= height) {
foundFluid = true;
pushVec = pushVec.add(state.getVelocity(this.world, mutable));
}
}
}
}
}
if (pushVec.length() > 0) {
pushVec = pushVec.normalize().multiply(0.014);
this.setVelocity(this.getVelocity().add(pushVec));
}
this.fluidHeight.put(fluidTag, waterHeight);
cir.setReturnValue(foundFluid);
}
}

View File

@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.block;
package com.viaversion.viafabricplus.injection.mixin.features.movement.water_movement;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;

View File

@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.item;
package com.viaversion.viafabricplus.injection.mixin.features.movement.water_movement;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;

View File

@ -0,0 +1,99 @@
/*
* This file is part of ViaFabricPlus - https://github.com/ViaVersion/ViaFabricPlus
* Copyright (C) 2021-2024 the original authors
* - FlorianMichael/EnZaXD <florian.michael07@gmail.com>
* - RK_01/RaphiMC
* Copyright (C) 2023-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.water_movement;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.fluid.Fluid;
import net.minecraft.registry.tag.FluidTags;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.*;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(LivingEntity.class)
public abstract class MixinLivingEntity extends Entity {
public MixinLivingEntity(EntityType<?> type, World world) {
super(type, world);
}
@Shadow
protected abstract float getBaseWaterMovementSpeedMultiplier();
@Redirect(method = "travelInFluid", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;getFluidHeight(Lnet/minecraft/registry/tag/TagKey;)D"))
private double dontApplyLavaMovement(LivingEntity instance, TagKey<Fluid> tagKey) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_15_2)) {
return Double.MAX_VALUE;
} else {
return instance.getFluidHeight(tagKey);
}
}
@Redirect(method = "travelInFluid",
slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/entity/effect/StatusEffects;DOLPHINS_GRACE:Lnet/minecraft/registry/entry/RegistryEntry;")),
at = @At(value = "FIELD", target = "Lnet/minecraft/entity/LivingEntity;horizontalCollision:Z", ordinal = 0))
private boolean disableClimbing(LivingEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_13_2) && instance.horizontalCollision;
}
@ModifyVariable(method = "applyFluidMovingSpeed", ordinal = 0, at = @At("HEAD"), argsOnly = true)
private boolean modifyMovingDown(boolean movingDown) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_13_2) && movingDown;
}
@Redirect(method = "travelInFluid", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;isSprinting()Z", ordinal = 0))
private boolean modifySwimSprintSpeed(LivingEntity instance) {
return ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_12_2) && instance.isSprinting();
}
@Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;getFluidHeight(Lnet/minecraft/registry/tag/TagKey;)D"))
private double redirectFluidHeight(LivingEntity instance, TagKey<Fluid> tagKey) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_12_2) && tagKey == FluidTags.WATER) {
if (instance.getFluidHeight(tagKey) > 0) return 1;
}
return instance.getFluidHeight(tagKey);
}
@Inject(method = "applyFluidMovingSpeed", at = @At("HEAD"), cancellable = true)
private void modifySwimSprintFallSpeed(double gravity, boolean movingDown, Vec3d velocity, CallbackInfoReturnable<Vec3d> ci) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_12_2) && !this.hasNoGravity()) {
ci.setReturnValue(new Vec3d(velocity.x, velocity.y - 0.02, velocity.z));
}
}
@ModifyConstant(method = "travelInFluid", constant = @Constant(floatValue = 0.9F))
private float modifySwimFriction(float constant) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_12_2)) {
return this.getBaseWaterMovementSpeedMultiplier();
} else {
return constant;
}
}
}

View File

@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.movement.entity;
package com.viaversion.viafabricplus.injection.mixin.features.movement.water_movement;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;

View File

@ -0,0 +1,46 @@
/*
* This file is part of ViaFabricPlus - https://github.com/ViaVersion/ViaFabricPlus
* Copyright (C) 2021-2024 the original authors
* - FlorianMichael/EnZaXD <florian.michael07@gmail.com>
* - RK_01/RaphiMC
* Copyright (C) 2023-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viafabricplus.injection.mixin.features.networking.always_set_highest_op_level;
import com.viaversion.viafabricplus.protocoltranslator.ProtocolTranslator;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import net.minecraft.client.network.ClientPlayerEntity;
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.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ClientPlayerEntity.class)
public abstract class MixinClientPlayerEntity {
@Shadow
public abstract void setClientPermissionLevel(int clientPermissionLevel);
@Inject(method = "init", at = @At("RETURN"))
private void setOpLevel4(CallbackInfo ci) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_8)) {
this.setClientPermissionLevel(4);
}
}
}

View File

@ -87,6 +87,7 @@
"features.cpe_extensions.MixinWeatherRendering",
"features.entity.allow_duplicated_uuids.MixinEntityIndex",
"features.entity.enchantment_attributes.MixinLivingEntity",
"features.entity.interactions.MixinAbstractBoatEntity",
"features.entity.interactions.MixinAbstractClientPlayerEntity",
"features.entity.interactions.MixinAbstractHorseEntity",
"features.entity.interactions.MixinAnimalEntity",
@ -106,7 +107,11 @@
"features.entity.metadata_handling.MixinEntityPacketRewriter1_9",
"features.entity.metadata_handling.MixinEntityTracker1_9",
"features.entity.pose.MixinOtherClientPlayerEntity",
"features.entity.pose.MixinPlayerEntity",
"features.entity.riding_offsets.MixinAbstractBoatEntity",
"features.entity.riding_offsets.MixinCamelEntity",
"features.entity.riding_offsets.MixinEntity",
"features.entity.riding_offsets.MixinLivingEntity",
"features.entity.v1_8_boat.MixinEntityModels",
"features.entity.v1_8_boat.MixinEntityRenderDispatcher",
"features.execute_inputs_sync.MixinKeyboard",
@ -122,20 +127,20 @@
"features.interaction.container_clicking.MixinCraftingScreenHandler",
"features.interaction.container_clicking.MixinItemPacketRewriter1_17",
"features.interaction.container_clicking.MixinScreenHandler",
"features.interaction.replace_block_item_use_logic.item_and_block_use_at_same_time.MixinMinecraftClient",
"features.interaction.merchant_emulation.MixinMerchantScreenHandler",
"features.interaction.remove_fuel_slot.MixinBrewingStandScreenHandler_FuelSlot",
"features.interaction.remove_offhand_slot.MixinPlayerScreenHandler",
"features.interaction.replace_block_item_use_logic.MixinClientPlayerInteractionManager",
"features.interaction.replace_block_item_use_logic.MixinItemPlacementContext",
"features.interaction.replace_block_item_use_logic.item_and_block_use_at_same_time.MixinMinecraftClient",
"features.interaction.v1_18_2_block_ack_emulation.MixinClientPlayerInteractionManager",
"features.interaction.v1_18_2_block_ack_emulation.MixinWorldPacketRewriter1_19",
"features.movement.item.MixinItemEntity",
"features.item.attack_damage_changes.MixinItemPacketRewriter1_9",
"features.item.attack_damage_changes.MixinItemStack",
"features.item.cooldown.MixinItemCooldownManager",
"features.item.filter_creative_tabs.MixinItemGroup_EntriesImpl",
"features.item.filter_creative_tabs.MixinItemGroups",
"features.item.gracefully_handle_enchantment_tooltips.MixinItemStack",
"features.item.interactions.MixinAxeItem",
"features.item.interactions.MixinBlockItem",
"features.item.interactions.MixinBowItem",
@ -163,20 +168,31 @@
"features.max_chat_length.MixinStringHelper",
"features.mouse_sensitivity.MixinMouse",
"features.mouse_sensitivity.MixinMouseOptionsScreen",
"features.movement.block.MixinBedBlock",
"features.movement.block.MixinFlowableFluid",
"features.movement.block.MixinHoneyBlock",
"features.movement.block.MixinSoulSandBlock",
"features.movement.elytra.MixinFireworkRocketItem",
"features.movement.entity.MixinAbstractBoatEntity",
"features.movement.entity.MixinClientPlayerEntity",
"features.movement.MixinClientPlayerEntity",
"features.movement.allow_negative_amplifier.MixinStatusEffectInstance",
"features.movement.change_honey_slowness.MixinHoneyBlock",
"features.movement.elytra_movement.MixinClientPlayerEntity",
"features.movement.elytra_movement.MixinFireworkRocketItem",
"features.movement.entity.MixinEntity",
"features.movement.entity.MixinLivingEntity",
"features.movement.entity.MixinPlayerEntity",
"features.movement.entity.MixinPlayerEntityRenderer",
"features.movement.entity.MixinSkeletonHorseEntity",
"features.movement.item.MixinEnderEyeItem",
"features.movement.levitation_value.MixinStatusEffectInstance",
"features.movement.handle_slowness_on_collision.MixinSoulSandBlock",
"features.movement.jump.MixinClientPlayerEntity",
"features.movement.remove_bed_bounce.MixinBedBlock",
"features.movement.replace_boat_movement.MixinAbstractBoatEntity",
"features.movement.replace_boat_movement.MixinClientPlayerEntity",
"features.movement.slowdown_calculation_changes.MixinClientPlayerEntity",
"features.movement.slowdown_calculation_changes.MixinEnderEyeItem",
"features.movement.sprinting_sneaking_condition_changes.MixinClientPlayerEntity",
"features.movement.v1_5_2_vehicle_movement.MixinClientPlayerEntity",
"features.movement.water_movement.MixinClientPlayerEntity",
"features.movement.water_movement.MixinEntity",
"features.movement.water_movement.MixinFlowableFluid",
"features.movement.water_movement.MixinItemEntity",
"features.movement.water_movement.MixinLivingEntity",
"features.movement.water_movement.MixinSkeletonHorseEntity",
"features.networking.always_set_highest_op_level.MixinClientPlayerEntity",
"features.networking.config_state_fixes.MixinClientConfigurationNetworkHandler",
"features.networking.config_state_fixes.MixinClientPlayNetworkHandler",
"features.networking.config_state_fixes.MixinNetworkStateTransitionHandler",
@ -226,9 +242,8 @@
"features.world.remove_server_view_distance.MixinGameOptions",
"integration.viabedrock.MixinJoinPackets",
"integration.vialegacy.MixinViaLegacyConfig",
"features.entity.interactions.MixinAbstractBoatEntity",
"features.entity.riding_offsets.MixinAbstractBoatEntity",
"features.item.gracefully_handle_enchantment_tooltips.MixinItemStack"
"features.movement.elytra_movement.MixinLivingEntity",
"features.movement.elytra_movement.MixinPlayerEntity"
],
"injectors": {
"defaultRequire": 1