Emulate PLAYER_INPUT packet as well

This commit is contained in:
FlorianMichael 2024-10-19 02:28:26 +02:00
parent f274d643a5
commit 4d4f66a1a2
5 changed files with 134 additions and 49 deletions

View File

@ -28,8 +28,7 @@ import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.InventoryState
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.ItemTagStorage;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.PlayerStorage;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.RecipeStorage;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.SneakingStorage;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.task.ClientEndTickPacketTask;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.task.PlayerPacketsTickTask;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
@ -152,7 +151,7 @@ public final class Protocol1_21_2To1_21 extends BackwardsProtocol<ClientboundPac
@Override
public void register(final ViaProviders providers) {
Via.getPlatform().runRepeatingSync(new ClientEndTickPacketTask(), 1L);
Via.getPlatform().runRepeatingSync(new PlayerPacketsTickTask(), 1L);
}
@Override
@ -160,7 +159,6 @@ public final class Protocol1_21_2To1_21 extends BackwardsProtocol<ClientboundPac
addEntityTracker(user, new EntityTrackerBase(user, EntityTypes1_20_5.PLAYER));
user.put(new InventoryStateIdStorage());
user.put(new ItemTagStorage());
user.put(new SneakingStorage());
user.put(new RecipeStorage(this));
user.put(new PlayerStorage());
}

View File

@ -22,7 +22,6 @@ import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.Protocol1_21_2To1_21;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.PlayerStorage;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.SneakingStorage;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
@ -40,6 +39,7 @@ import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacke
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ServerboundPackets1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.storage.ClientVehicleStorage;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
import java.util.ArrayList;
import java.util.BitSet;
@ -222,10 +222,16 @@ public final class EntityPacketRewriter1_21_2 extends EntityRewriter<Clientbound
protocol.registerServerbound(ServerboundPackets1_20_5.PLAYER_COMMAND, wrapper -> {
wrapper.passthrough(Types.VAR_INT);
final int action = wrapper.passthrough(Types.VAR_INT);
final PlayerStorage storage = wrapper.user().get(PlayerStorage.class);
if (action == 0) {
wrapper.user().get(SneakingStorage.class).setPlayerCommandTrackedSneaking(true);
storage.setPlayerCommandTrackedSneaking(true);
} else if (action == 1) {
wrapper.user().get(SneakingStorage.class).setPlayerCommandTrackedSneaking(false);
storage.setPlayerCommandTrackedSneaking(false);
} else if (action == 3) {
storage.setPlayerCommandTrackedSprinting(true);
} else if (action == 4) {
storage.setPlayerCommandTrackedSprinting(false);
}
});
@ -263,7 +269,7 @@ public final class EntityPacketRewriter1_21_2 extends EntityRewriter<Clientbound
// Player input no longer sets the sneaking state on the server
// Send the change separately if needed (= when in a vehicle and player commands aren't sent by the old client)
final SneakingStorage sneakingStorage = wrapper.user().get(SneakingStorage.class);
final PlayerStorage sneakingStorage = wrapper.user().get(PlayerStorage.class);
if (sneakingStorage.setSneaking(sneaking)) {
final PacketWrapper playerCommandPacket = wrapper.create(ServerboundPackets1_21_2.PLAYER_COMMAND);
playerCommandPacket.write(Types.VAR_INT, tracker(wrapper.user()).clientEntityId());
@ -355,6 +361,36 @@ public final class EntityPacketRewriter1_21_2 extends EntityRewriter<Clientbound
}
}
});
protocol.registerClientbound(ClientboundPackets1_21_2.SET_PASSENGERS, wrapper -> {
final int vehicleId = wrapper.passthrough(Types.VAR_INT);
final int[] passengerIds = wrapper.passthrough(Types.VAR_INT_ARRAY_PRIMITIVE);
final ClientVehicleStorage storage = wrapper.user().get(ClientVehicleStorage.class);
if (storage != null && vehicleId == storage.vehicleId()) {
wrapper.user().remove(ClientVehicleStorage.class);
}
final int clientEntityId = tracker(wrapper.user()).clientEntityId();
for (final int passenger : passengerIds) {
if (passenger == clientEntityId) {
wrapper.user().put(new ClientVehicleStorage(vehicleId));
break;
}
}
});
protocol.appendClientbound(ClientboundPackets1_21_2.REMOVE_ENTITIES, wrapper -> {
final ClientVehicleStorage vehicleStorage = wrapper.user().get(ClientVehicleStorage.class);
if (vehicleStorage == null) {
return;
}
final int[] entityIds = wrapper.get(Types.VAR_INT_ARRAY_PRIMITIVE, 0);
for (final int entityId : entityIds) {
if (entityId == vehicleStorage.vehicleId()) {
wrapper.user().remove(ClientVehicleStorage.class);
break;
}
}
});
}
private void updateRotation(PacketWrapper wrapper) {

View File

@ -18,14 +18,77 @@
package com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage;
import com.viaversion.viabackwards.api.entities.storage.PlayerPositionStorage;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.Protocol1_21_2To1_21;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ServerboundPackets1_21_2;
public final class PlayerStorage extends PlayerPositionStorage {
private static final PlayerInput EMPTY = new PlayerInput(false, false, false, false, false, false, false);
private static final float PLAYER_JUMP_HEIGHT = 0.42F;
private float yaw;
private float pitch;
private boolean playerCommandTrackedSneaking;
private boolean playerCommandTrackedSprinting;
private PlayerInput lastInput = EMPTY;
private double prevX;
private double prevY;
private double prevZ;
public void setPosition(PacketWrapper wrapper) {
setX(wrapper.get(Types.DOUBLE, 0));
setY(wrapper.get(Types.DOUBLE, 1));
setZ(wrapper.get(Types.DOUBLE, 2));
}
public void tick(final UserConnection user) {
final double deltaX = x() - prevX;
final double deltaY = y() - prevY;
final double deltaZ = z() - prevZ;
final double magnitude = Math.sqrt(deltaX * deltaX + deltaZ * deltaZ);
double directionX = magnitude > 0 ? deltaX / magnitude : 0;
double directionZ = magnitude > 0 ? deltaZ / magnitude : 0;
directionX = Math.max(-1, Math.min(1, directionX));
directionZ = Math.max(-1, Math.min(1, directionZ));
final double angle = Math.toRadians(-yaw);
final double newDirectionX = directionX * Math.cos(angle) - directionZ * Math.sin(angle);
final double newDirectionZ = directionX * Math.sin(angle) + directionZ * Math.cos(angle);
final boolean forward = newDirectionZ >= 0.65F;
final boolean backwards = newDirectionZ <= -0.65F;
final boolean left = newDirectionX >= 0.65F;
final boolean right = newDirectionX <= -0.65F;
final boolean jump = Math.abs(deltaY - PLAYER_JUMP_HEIGHT) <= 1E-4F;
final PlayerInput input = new PlayerInput(forward, backwards, left, right, jump, playerCommandTrackedSneaking, playerCommandTrackedSprinting);
if (!lastInput.equals(input)) {
final PacketWrapper playerInputPacket = PacketWrapper.create(ServerboundPackets1_21_2.PLAYER_INPUT, user);
byte flags = 0;
flags = (byte) (flags | (input.forward() ? 1 : 0));
flags = (byte) (flags | (input.backward() ? 2 : 0));
flags = (byte) (flags | (input.left() ? 4 : 0));
flags = (byte) (flags | (input.right() ? 8 : 0));
flags = (byte) (flags | (input.jump() ? 16 : 0));
flags = (byte) (flags | (input.sneak() ? 32 : 0));
flags = (byte) (flags | (input.sprint() ? 64 : 0));
playerInputPacket.write(Types.BYTE, flags);
playerInputPacket.sendToServer(Protocol1_21_2To1_21.class);
lastInput = input;
}
this.prevX = x();
this.prevY = y();
this.prevZ = z();
}
public float yaw() {
return yaw;
}
@ -34,15 +97,27 @@ public final class PlayerStorage extends PlayerPositionStorage {
return pitch;
}
public void setPosition(PacketWrapper wrapper) {
setX(wrapper.get(Types.DOUBLE, 0));
setY(wrapper.get(Types.DOUBLE, 1));
setZ(wrapper.get(Types.DOUBLE, 2));
}
public void setRotation(final PacketWrapper wrapper) {
this.yaw = wrapper.get(Types.FLOAT, 0);
this.pitch = wrapper.get(Types.FLOAT, 1);
}
public void setPlayerCommandTrackedSneaking(final boolean playerCommandTrackedSneaking) {
this.playerCommandTrackedSneaking = playerCommandTrackedSneaking;
}
public void setPlayerCommandTrackedSprinting(final boolean playerCommandTrackedSprinting) {
this.playerCommandTrackedSprinting = playerCommandTrackedSprinting;
}
public boolean setSneaking(final boolean sneaking) {
final boolean changed = this.playerCommandTrackedSneaking != sneaking;
this.playerCommandTrackedSneaking = sneaking;
return changed;
}
public record PlayerInput(boolean forward, boolean backward, boolean left, boolean right, boolean jump,
boolean sneak, boolean sprint) {
}
}

View File

@ -1,34 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-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.viabackwards.protocol.v1_21_2to1_21.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
public final class SneakingStorage implements StorableObject {
private boolean playerCommandTrackedSneaking;
public void setPlayerCommandTrackedSneaking(final boolean playerCommandTrackedSneaking) {
this.playerCommandTrackedSneaking = playerCommandTrackedSneaking;
}
public boolean setSneaking(final boolean sneaking) {
final boolean changed = this.playerCommandTrackedSneaking != sneaking;
this.playerCommandTrackedSneaking = sneaking;
return changed;
}
}

View File

@ -19,15 +19,17 @@ package com.viaversion.viabackwards.protocol.v1_21_2to1_21.task;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.Protocol1_21_2To1_21;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.storage.PlayerStorage;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ServerboundPackets1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.storage.ClientVehicleStorage;
import io.netty.channel.Channel;
import java.util.logging.Level;
public final class ClientEndTickPacketTask implements Runnable {
public final class PlayerPacketsTickTask implements Runnable {
@Override
public void run() {
@ -40,6 +42,14 @@ public final class ClientEndTickPacketTask implements Runnable {
if (!channel.isActive()) {
return;
}
try {
if (!user.has(ClientVehicleStorage.class)) {
final PlayerStorage playerStorage = user.get(PlayerStorage.class);
playerStorage.tick(user);
}
} catch (Throwable t) {
ViaBackwards.getPlatform().getLogger().log(Level.SEVERE, "Error while sending player input packet.", t);
}
try {
final PacketWrapper clientTickEndPacket = PacketWrapper.create(ServerboundPackets1_21_2.CLIENT_TICK_END, user);
clientTickEndPacket.sendToServer(Protocol1_21_2To1_21.class);