Fixed triple chests in <= 1.13.2, started with java-docs

This commit is contained in:
FlorianMichael 2023-06-09 22:13:06 +02:00
parent e1cae0d81d
commit 0080e86fdc
No known key found for this signature in database
GPG Key ID: C2FB87E71C425126
20 changed files with 404 additions and 61 deletions

View File

@ -43,7 +43,6 @@ import java.io.File;
* - TakeItemEntityPacket isEmpty case
* <p>
* TODO | Protocol translation
* - BucketItem#use canPlaceOn in <= 1.13 is missing
* - Cobwebs in <= b1.7.3 are broken
* - Window interactions in <= 1.16.5 are unlegit
* - Entity hitboxes and eye heights has changed

View File

@ -0,0 +1,46 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2023 FlorianMichael/EnZaXD 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 de.florianmichael.viafabricplus.definition;
import net.minecraft.network.PacketByteBuf;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
public class PacketSyncBase {
public final static String PACKET_SYNC_IDENTIFIER = UUID.randomUUID() + ":" + UUID.randomUUID();
private final static Map<String, Consumer<PacketByteBuf>> tasks = new ConcurrentHashMap<>();
public static Consumer<PacketByteBuf> get(final String uuid) {
final var task = tasks.get(uuid);
tasks.remove(uuid);
return task;
}
public static boolean has(final String uuid) {
return tasks.containsKey(uuid);
}
public static String track(final Consumer<PacketByteBuf> task) {
final String uuid = UUID.randomUUID().toString();
tasks.put(uuid, task);
return uuid;
}
}

View File

@ -28,7 +28,7 @@ public class ClassicProgressRenderer {
public static void renderProgress(final DrawContext context) {
if (MinecraftClient.getInstance().getNetworkHandler() == null) return;
final UserConnection connection = MinecraftClient.getInstance().getNetworkHandler().getConnection().channel.attr(ProtocolHack.LOCAL_VIA_CONNECTION).get();
final UserConnection connection = ProtocolHack.getMainUserConnection();
if (connection == null) return;
final ClassicProgressStorage classicProgressStorage = connection.get(ClassicProgressStorage.class);
if (classicProgressStorage == null) return;

View File

@ -20,11 +20,10 @@ package de.florianmichael.viafabricplus.definition.c0_30.command;
import com.viaversion.viaversion.api.command.ViaSubCommand;
import com.viaversion.viaversion.api.connection.UserConnection;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import net.minecraft.client.MinecraftClient;
public abstract class ClassicViaSubCommand extends ViaSubCommand {
public UserConnection getUser() {
return MinecraftClient.getInstance().getNetworkHandler().getConnection().channel.attr(ProtocolHack.LOCAL_VIA_CONNECTION).get();
return ProtocolHack.getMainUserConnection();
}
}

View File

@ -0,0 +1,66 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2023 FlorianMichael/EnZaXD 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 de.florianmichael.viafabricplus.definition.v1_13_2;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonElement;
import de.florianmichael.viafabricplus.ViaFabricPlus;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ingame.HandledScreens;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.resource.featuretoggle.FeatureFlags;
import net.minecraft.screen.GenericContainerScreenHandler;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.text.Text;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Consumer;
public class ScreenHandlerEmulator1_13_2 {
public final static Consumer<PacketByteBuf> OLD_PACKET_HANDLER = data -> {
final var byteBuf = data.asByteBuf();
try {
ScreenHandlerEmulator1_13_2.handle(Type.SHORT.readPrimitive(byteBuf), Type.COMPONENT.read(byteBuf), Type.SHORT.readPrimitive(byteBuf));
} catch (Exception e) {
ViaFabricPlus.LOGGER.error("Failed to open custom ScreenHandler with dimension 9xN", e);
}
};
private final static Map<Integer, ScreenHandlerType<GenericContainerScreenHandler>> fakeHandlers = new LinkedHashMap<>();
static {
for (int i = 0; i < 1000; i++) {
int finalI = i;
fakeHandlers.put(i, new ScreenHandlerType<>((syncId, playerInventory) -> new GenericContainerScreenHandler(fakeHandlers.get(finalI), syncId, playerInventory, finalI), FeatureFlags.VANILLA_FEATURES));
}
}
public static void handle(final short windowID, final JsonElement title, final short slots) {
int n = slots / 9;
final int modulo = slots % 9;
if (modulo > 0) n++;
HandledScreens.open(ScreenHandlerEmulator1_13_2.fakeHandlers.get(n), MinecraftClient.getInstance(), windowID, Text.Serializer.fromJson(title.toString()));
}
public static boolean isFakeHandler(final ScreenHandlerType<?> screenHandlerType) {
return fakeHandlers.containsValue(screenHandlerType);
}
}

View File

@ -19,20 +19,37 @@ package de.florianmichael.viafabricplus.definition.v1_18_2;
import de.florianmichael.viafabricplus.ViaFabricPlus;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import de.florianmichael.viafabricplus.protocolhack.util.BlockStateTranslator;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
import net.minecraft.util.Pair;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec2f;
import net.raphimc.vialoader.util.VersionEnum;
public class ClientPlayerInteractionManager1_18_2 {
private final static Object2ObjectLinkedOpenHashMap<Pair<BlockPos, PlayerActionC2SPacket.Action>, PositionAndRotation> unAckedActions = new Object2ObjectLinkedOpenHashMap<>();
import java.util.function.Consumer;
public final static String ACK_TRANSFORMER_IDENTIFIER = "viafabricplus:acknowledge_player_digging";
public class ClientPlayerInteractionManager1_18_2 {
public final static Consumer<PacketByteBuf> OLD_PACKET_HANDLER = data -> {
try {
final var pos = data.readBlockPos();
final var blockState = Block.STATE_IDS.get(BlockStateTranslator.translateBlockState1_18(data.readVarInt()));
final var action = data.readEnumConstant(PlayerActionC2SPacket.Action.class);
final var allGood = data.readBoolean();
//noinspection DataFlowIssue
ClientPlayerInteractionManager1_18_2.handleBlockBreakAck(MinecraftClient.getInstance().getNetworkHandler().getWorld(), pos, blockState, action, allGood);
} catch (Exception e) {
ViaFabricPlus.LOGGER.error("Failed to read BlockBreakAck packet data", e);
}
};
private final static Object2ObjectLinkedOpenHashMap<Pair<BlockPos, PlayerActionC2SPacket.Action>, PositionAndRotation> UN_ACKED_ACTIONS = new Object2ObjectLinkedOpenHashMap<>();
public static void trackBlockAction(final PlayerActionC2SPacket.Action action, final BlockPos blockPos) {
final var player = MinecraftClient.getInstance().player;
@ -42,14 +59,14 @@ public class ClientPlayerInteractionManager1_18_2 {
if (ProtocolHack.getTargetVersion().isNewerThan(VersionEnum.r1_16_2)) {
rotation = null;
}
unAckedActions.put(new Pair<>(blockPos, action), new PositionAndRotation(player.getPos().x, player.getPos().y, player.getPos().z, rotation));
UN_ACKED_ACTIONS.put(new Pair<>(blockPos, action), new PositionAndRotation(player.getPos().x, player.getPos().y, player.getPos().z, rotation));
}
public static void handleBlockBreakAck(final ClientWorld world, final BlockPos blockPos, final BlockState blockState, final PlayerActionC2SPacket.Action action, final boolean allGood) {
final var player = MinecraftClient.getInstance().player;
if (player == null) return;
final var next = unAckedActions.remove(new Pair<>(blockPos, action));
final var next = UN_ACKED_ACTIONS.remove(new Pair<>(blockPos, action));
final var blockStateFromPos = world.getBlockState(blockPos);
if ((next == null || !allGood || action != PlayerActionC2SPacket.Action.START_DESTROY_BLOCK && blockStateFromPos != blockState) && blockStateFromPos != blockState) {
@ -63,9 +80,9 @@ public class ClientPlayerInteractionManager1_18_2 {
}
}
while (unAckedActions.size() >= 50) {
ViaFabricPlus.LOGGER.error("Too many unacked block actions, dropping {}", unAckedActions.firstKey());
unAckedActions.removeFirst();
while (UN_ACKED_ACTIONS.size() >= 50) {
ViaFabricPlus.LOGGER.error("Too many unacked block actions, dropping {}", UN_ACKED_ACTIONS.firstKey());
UN_ACKED_ACTIONS.removeFirst();
}
}

View File

@ -42,7 +42,7 @@ public class MixinDebugHud {
final List<String> information = new ArrayList<>();
if (MinecraftClient.getInstance().getNetworkHandler() != null) {
final UserConnection userConnection = MinecraftClient.getInstance().getNetworkHandler().getConnection().channel.attr(ProtocolHack.LOCAL_VIA_CONNECTION).get();
final UserConnection userConnection = ProtocolHack.getMainUserConnection();
information.add("");
information.add(Formatting.GOLD + "[ViaFabricPlus] " + Formatting.WHITE);

View File

@ -19,14 +19,9 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft;
import com.llamalad7.mixinextras.injector.WrapWithCondition;
import com.mojang.authlib.GameProfile;
import de.florianmichael.viafabricplus.definition.v1_18_2.ClientPlayerInteractionManager1_18_2;
import de.florianmichael.viafabricplus.protocolhack.usage.BlockStateTranslator;
import net.minecraft.block.Block;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
import net.raphimc.vialoader.util.VersionEnum;
import de.florianmichael.viafabricplus.ViaFabricPlus;
import de.florianmichael.viafabricplus.base.settings.groups.VisualSettings;
import de.florianmichael.viafabricplus.definition.PacketSyncBase;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.DownloadingTerrainScreen;
@ -36,14 +31,19 @@ import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.network.PlayerListEntry;
import net.minecraft.client.network.ServerInfo;
import net.minecraft.client.util.telemetry.WorldSession;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.vehicle.BoatEntity;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.listener.ServerPlayPacketListener;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.s2c.play.*;
import net.minecraft.screen.ScreenHandler;
import net.raphimc.vialoader.util.VersionEnum;
import org.slf4j.Logger;
import org.spongepowered.asm.mixin.*;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.*;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@ -64,17 +64,25 @@ public abstract class MixinClientPlayNetworkHandler {
public abstract void onEntityStatus(EntityStatusS2CPacket packet);
@Mutable
@Shadow @Final private Set<PlayerListEntry> listedPlayerListEntries;
@Shadow
@Final
private Set<PlayerListEntry> listedPlayerListEntries;
@Shadow public abstract void onSimulationDistance(SimulationDistanceS2CPacket packet);
@Shadow
public abstract void onSimulationDistance(SimulationDistanceS2CPacket packet);
@Shadow protected abstract void sendPacket(Packet<ServerPlayPacketListener> packet, BooleanSupplier sendCondition, Duration expirationTime);
@Shadow
protected abstract void sendPacket(Packet<ServerPlayPacketListener> packet, BooleanSupplier sendCondition, Duration expirationTime);
@Shadow public abstract void sendPacket(Packet<?> packet);
@Shadow
public abstract void sendPacket(Packet<?> packet);
@Shadow @Final private ClientConnection connection;
@Shadow
@Final
private ClientConnection connection;
@Shadow private ClientWorld world;
@Shadow
private ClientWorld world;
@Inject(method = "<init>", at = @At("RETURN"))
public void fixPlayerListOrdering(MinecraftClient client, Screen screen, ClientConnection connection, ServerInfo serverInfo, GameProfile profile, WorldSession worldSession, CallbackInfo ci) {
@ -107,7 +115,7 @@ public abstract class MixinClientPlayNetworkHandler {
}
}
@Inject(method = { "onGameJoin", "onPlayerRespawn" }, at = @At("TAIL"))
@Inject(method = {"onGameJoin", "onPlayerRespawn"}, at = @At("TAIL"))
private void injectOnOnGameJoinOrRespawn(CallbackInfo ci) {
if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) {
ClientPlayerEntity player = MinecraftClient.getInstance().player;
@ -169,15 +177,13 @@ public abstract class MixinClientPlayNetworkHandler {
final var channel = packet.getChannel().toString();
final var data = packet.getData();
if (channel.equals(ClientPlayerInteractionManager1_18_2.ACK_TRANSFORMER_IDENTIFIER)) {
final var pos = data.readBlockPos();
final var blockState = Block.STATE_IDS.get(BlockStateTranslator.translateBlockState1_18(data.readVarInt()));
final var action = data.readEnumConstant(PlayerActionC2SPacket.Action.class);
final var allGood = data.readBoolean();
if (channel.equals(PacketSyncBase.PACKET_SYNC_IDENTIFIER)) {
final var uuid = data.readString();
ClientPlayerInteractionManager1_18_2.handleBlockBreakAck(world, pos, blockState, action, allGood);
ci.cancel();
if (PacketSyncBase.has(uuid)) {
PacketSyncBase.get(uuid).accept(data);
ci.cancel();
}
}
}
}

View File

@ -33,7 +33,7 @@ import de.florianmichael.viafabricplus.injection.access.IClientPlayerEntity;
import de.florianmichael.viafabricplus.injection.access.IScreenHandler;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import de.florianmichael.viafabricplus.protocolhack.provider.viaversion.ViaFabricPlusHandItemProvider;
import de.florianmichael.viafabricplus.protocolhack.usage.ItemTranslator;
import de.florianmichael.viafabricplus.protocolhack.util.ItemTranslator;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity;
@ -129,7 +129,7 @@ public abstract class MixinClientPlayerInteractionManager {
else
slotItemBeforeModification = viafabricplus_oldItems.get(clickSlot.getSlot());
final UserConnection viaConnection = networkHandler.getConnection().channel.attr(ProtocolHack.LOCAL_VIA_CONNECTION).get();
final UserConnection userConnection = networkHandler.getConnection().channel.attr(ProtocolHack.LOCAL_VIA_CONNECTION).get();
final short syncId = (short) clickSlot.getSyncId();
final short slot = (short) clickSlot.getSlot();
final byte button = (byte) clickSlot.getButton();
@ -137,8 +137,8 @@ public abstract class MixinClientPlayerInteractionManager {
final int actionType = clickSlot.getActionType().ordinal();
final Item item = ItemTranslator.minecraftToViaVersion(slotItemBeforeModification, VersionEnum.r1_16.getVersion());
viaConnection.getChannel().eventLoop().submit(() -> {
final PacketWrapper clickSlotPacket = PacketWrapper.create(ServerboundPackets1_16_2.CLICK_WINDOW, viaConnection);
userConnection.getChannel().eventLoop().submit(() -> {
final PacketWrapper clickSlotPacket = PacketWrapper.create(ServerboundPackets1_16_2.CLICK_WINDOW, userConnection);
clickSlotPacket.write(Type.UNSIGNED_BYTE, syncId);
clickSlotPacket.write(Type.SHORT, slot);

View File

@ -0,0 +1,43 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2023 FlorianMichael/EnZaXD 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 de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft;
import de.florianmichael.viafabricplus.definition.v1_13_2.ScreenHandlerEmulator1_13_2;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
import net.minecraft.client.gui.screen.ingame.HandledScreens;
import net.minecraft.screen.GenericContainerScreenHandler;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.screen.ScreenHandlerType;
import net.raphimc.vialoader.util.VersionEnum;
import org.jetbrains.annotations.Nullable;
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(HandledScreens.class)
public class MixinHandledScreens {
@Inject(method = "getProvider", at = @At("HEAD"), cancellable = true)
private static <T extends ScreenHandler> void returnFakeProvider(ScreenHandlerType<T> type, CallbackInfoReturnable<HandledScreens.@Nullable Provider> cir) {
if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_13_2) && ScreenHandlerEmulator1_13_2.isFakeHandler(type)) {
cir.setReturnValue((handler, playerInventory, title) -> new GenericContainerScreen((GenericContainerScreenHandler) handler, playerInventory, title));
}
}
}

View File

@ -124,11 +124,11 @@ public abstract class MixinMinecraftClient implements IMinecraftClient {
@Inject(method = "handleInputEvents", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;hasRidingInventory()Z"))
private void onInventoryKeyPressed(CallbackInfo ci) {
if (getNetworkHandler() != null && DebugSettings.INSTANCE.sendOpenInventoryPacket.getValue()) {
final UserConnection viaConnection = MinecraftClient.getInstance().getNetworkHandler().getConnection().channel.attr(ProtocolHack.LOCAL_VIA_CONNECTION).get();
final UserConnection userConnection = ProtocolHack.getMainUserConnection();
if (viaConnection != null && viaConnection.getProtocolInfo().getPipeline().contains(Protocol1_12To1_11_1.class)) {
viaConnection.getChannel().eventLoop().submit(() -> {
final PacketWrapper clientStatus = PacketWrapper.create(ServerboundPackets1_9_3.CLIENT_STATUS, viaConnection);
if (userConnection != null && userConnection.getProtocolInfo().getPipeline().contains(Protocol1_12To1_11_1.class)) {
userConnection.getChannel().eventLoop().submit(() -> {
final PacketWrapper clientStatus = PacketWrapper.create(ServerboundPackets1_9_3.CLIENT_STATUS, userConnection);
clientStatus.write(Type.VAR_INT, 2); // Open Inventory Achievement
try {

View File

@ -19,11 +19,8 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.entity;
import com.viaversion.viaversion.api.connection.UserConnection;
import net.raphimc.vialoader.util.VersionEnum;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.definition.v1_14_4.Meta18Storage;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.passive.WolfEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@ -37,7 +34,7 @@ public class MixinWolfEntity {
public float rewriteHealth(WolfEntity instance) {
float health = instance.getHealth();
if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_14_4)) {
final UserConnection userConnection = MinecraftClient.getInstance().getNetworkHandler().getConnection().channel.attr(ProtocolHack.LOCAL_VIA_CONNECTION).get();
final UserConnection userConnection = ProtocolHack.getMainUserConnection();
if (!userConnection.has(Meta18Storage.class)) userConnection.put(new Meta18Storage(userConnection));
return userConnection.get(Meta18Storage.class).getHealthDataMap().getOrDefault(instance.getId(), health);
}

View File

@ -0,0 +1,82 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2023 FlorianMichael/EnZaXD 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 de.florianmichael.viafabricplus.injection.mixin.fixes.viaversion.protocol1_14to1_13_2;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.ProtocolPathEntry;
import com.viaversion.viaversion.api.protocol.packet.Direction;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.connection.UserConnectionImpl;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.ClientboundPackets1_14;
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.packets.InventoryPackets;
import com.viaversion.viaversion.protocols.protocol1_16to1_15_2.storage.InventoryTracker1_16;
import de.florianmichael.viafabricplus.definition.PacketSyncBase;
import de.florianmichael.viafabricplus.definition.v1_13_2.ScreenHandlerEmulator1_13_2;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import io.netty.buffer.Unpooled;
import net.minecraft.SharedConstants;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.List;
import java.util.stream.Collectors;
@Mixin(value = InventoryPackets.class, remap = false)
public class MixinInventoryPackets {
@Inject(method = "lambda$registerPackets$0", at = @At(value = "INVOKE", target = "Ljava/util/logging/Logger;warning(Ljava/lang/String;)V"), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true)
private static void supportCustomSlots(PacketWrapper wrapper, CallbackInfo ci, Short windowId, String type, JsonElement title, Short slots, int typeId) {
if (typeId == -1) {
wrapper.clearPacket();
wrapper.setPacketType(ClientboundPackets1_14.PLUGIN_MESSAGE);
wrapper.write(Type.STRING, PacketSyncBase.PACKET_SYNC_IDENTIFIER);
final List<ProtocolPathEntry> protocolPath = Via.getManager().getProtocolManager().getProtocolPath(SharedConstants.getProtocolVersion(), ProtocolVersion.v1_13_2.getVersion());
final var userConnection = ProtocolHack.createFakerUserConnection();
try {
var fakeOpenWindow = PacketWrapper.create(ClientboundPackets1_14.OPEN_WINDOW, Unpooled.buffer(), userConnection);
fakeOpenWindow.write(Type.VAR_INT, windowId.intValue());
fakeOpenWindow.write(Type.VAR_INT, typeId);
fakeOpenWindow.write(Type.COMPONENT, title);
fakeOpenWindow.apply(Direction.CLIENTBOUND, State.PLAY, 0, protocolPath.stream().map(ProtocolPathEntry::protocol).collect(Collectors.toList()), true);
fakeOpenWindow.read(Type.VAR_INT);
fakeOpenWindow.read(Type.VAR_INT);
final String uuid = PacketSyncBase.track(ScreenHandlerEmulator1_13_2.OLD_PACKET_HANDLER);
wrapper.write(Type.STRING, uuid);
wrapper.write(Type.SHORT, windowId);
wrapper.write(Type.COMPONENT, fakeOpenWindow.read(Type.COMPONENT));
wrapper.write(Type.SHORT, slots);
} catch (Exception e) {
e.printStackTrace();
}
ci.cancel();
}
}
}

View File

@ -24,6 +24,7 @@ import com.viaversion.viaversion.protocols.protocol1_18to1_17_1.ClientboundPacke
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.ClientboundPackets1_19;
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.Protocol1_19To1_18_2;
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.packets.WorldPackets;
import de.florianmichael.viafabricplus.definition.PacketSyncBase;
import de.florianmichael.viafabricplus.definition.v1_18_2.ClientPlayerInteractionManager1_18_2;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@ -41,7 +42,10 @@ public class MixinWorldPackets {
}
wrapper.resetReader();
wrapper.write(Type.STRING, ClientPlayerInteractionManager1_18_2.ACK_TRANSFORMER_IDENTIFIER);
final String uuid = PacketSyncBase.track(ClientPlayerInteractionManager1_18_2.OLD_PACKET_HANDLER);
wrapper.write(Type.STRING, PacketSyncBase.PACKET_SYNC_IDENTIFIER);
wrapper.write(Type.STRING, uuid);
});
}
}

View File

@ -24,6 +24,7 @@ import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.connection.UserConnectionImpl;
import com.viaversion.viaversion.protocol.ProtocolPipelineImpl;
import com.viaversion.viaversion.protocols.protocol1_16to1_15_2.storage.InventoryTracker1_16;
import de.florianmichael.viafabricplus.ViaFabricPlus;
import de.florianmichael.viafabricplus.base.event.ChangeProtocolVersionCallback;
import de.florianmichael.viafabricplus.base.event.FinishViaVersionStartupCallback;
@ -49,14 +50,36 @@ import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
/**
* This class represents the whole Protocol Translator, here all important variables are stored
*/
public class ProtocolHack {
public final static AttributeKey<UserConnection> LOCAL_VIA_CONNECTION = AttributeKey.newInstance("viafabricplus-via-connection");
/**
* These attribute keys are used to track the main connections of Minecraft and ViaVersion, so that they can be used later during the connection to send packets.
*/
public final static AttributeKey<ClientConnection> LOCAL_MINECRAFT_CONNECTION = AttributeKey.newInstance("viafabricplus-minecraft-connection");
public final static AttributeKey<UserConnection> LOCAL_VIA_CONNECTION = AttributeKey.newInstance("viafabricplus-via-connection");
/**
* This list is temporary and is used during the connection to the server to create the FORCED_VERSION attribute.
*/
private final static Map<InetSocketAddress, VersionEnum> forcedVersions = new HashMap<>();
/**
* This attribute stores the forced version for the current connection (if you set a specific version in the Edit Server screen)
*/
public final static AttributeKey<VersionEnum> FORCED_VERSION = AttributeKey.newInstance("viafabricplus-forced-version");
private final static Map<InetSocketAddress, VersionEnum> forcedVersions = new HashMap<>();
/**
* This field stores the target version that you set in the GUI
*/
public static VersionEnum targetVersion = VersionEnum.r1_20;
/**
* This method is used when you need the target version after connecting to the server.
*
* @return the target version
*/
public static VersionEnum getTargetVersion() {
if (MinecraftClient.getInstance() == null || MinecraftClient.getInstance().getNetworkHandler() == null) {
return getTargetVersion((Channel) null);
@ -65,6 +88,12 @@ public class ProtocolHack {
return getTargetVersion(MinecraftClient.getInstance().getNetworkHandler().getConnection().channel);
}
/**
* This method is used when you need the target version while connecting to the server before Netty is started
*
* @param socketAddress the target address
* @return the target version
*/
public static VersionEnum getTargetVersion(final InetSocketAddress socketAddress) {
if (forcedVersions.containsKey(socketAddress)) {
return forcedVersions.get(socketAddress);
@ -72,6 +101,12 @@ public class ProtocolHack {
return getTargetVersion();
}
/**
* This method is used when you need the target version while connecting to the server after Netty is started and before ViaVersion is finished loading.
*
* @param channel channel of the current connection
* @return the target version
*/
public static VersionEnum getTargetVersion(final Channel channel) {
if (channel != null && channel.hasAttr(FORCED_VERSION)) {
return channel.attr(FORCED_VERSION).get();
@ -86,6 +121,13 @@ public class ProtocolHack {
return forcedVersions;
}
/**
* Injects the ViaFabricPlus pipeline with all ViaVersion elements into a Minecraft pipeline
*
* @param connection the Minecraft connection
* @param channel the current channel
* @param address the target address
*/
public static void injectVLBPipeline(final ClientConnection connection, final Channel channel, final InetSocketAddress address) {
if (ProtocolHack.getForcedVersions().containsKey(address)) {
channel.attr(ProtocolHack.FORCED_VERSION).set(ProtocolHack.getForcedVersions().get(address));
@ -100,8 +142,10 @@ public class ProtocolHack {
channel.pipeline().addLast(new ViaFabricPlusVLLegacyPipeline(user, ProtocolHack.getTargetVersion(channel), address));
}
/**
* Adding ViaVersion's command system into Fabric
*/
private static void initCommands() {
// Adding ViaVersion commands
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> {
final ViaFabricPlusVLCommandHandler commandHandler = (ViaFabricPlusVLCommandHandler) Via.getManager().getCommandHandler();
@ -113,11 +157,44 @@ public class ProtocolHack {
});
}
/**
* Sets the target version of the GUI
*
* @param targetVersion the target version
*/
public static void setTargetVersion(VersionEnum targetVersion) {
ProtocolHack.targetVersion = targetVersion;
ChangeProtocolVersionCallback.EVENT.invoker().onChangeProtocolVersion(targetVersion);
}
/**
* @return Creates a Fake UserConnection class with a valid protocol pipeline to emulate packets
*/
public static UserConnection createFakerUserConnection() {
final var current = getMainUserConnection();
final var userConnection = new UserConnectionImpl(current.getChannel(), true);
userConnection.getProtocolInfo().setPipeline(new ProtocolPipelineImpl(userConnection));
userConnection.put(new InventoryTracker1_16());
return userConnection;
}
/**
* @return Returns the current ViaVersion UserConnection via the LOCAL_VIA_CONNECTION channel attribute
*/
public static UserConnection getMainUserConnection() {
final MinecraftClient client = MinecraftClient.getInstance();
if (client.getNetworkHandler() == null) return null;
final var channel = client.getNetworkHandler().getConnection().channel;
if (!channel.hasAttr(LOCAL_VIA_CONNECTION)) return null;
return channel.attr(LOCAL_VIA_CONNECTION).get();
}
/**
* Starts ViaVersion
*/
public static void init() {
ViaLoader.init(new ViaFabricPlusViaVersionPlatformImpl(ViaFabricPlus.RUN_DIRECTORY), new ViaFabricPlusVLLoader(), new ViaFabricPlusVLInjector(), new ViaFabricPlusVLCommandHandler(), ViaBackwardsPlatformImpl::new, ViaFabricPlusViaLegacyPlatformImpl::new, ViaAprilFoolsPlatformImpl::new, ViaBedrockPlatformImpl::new);
initCommands();

View File

@ -21,7 +21,7 @@ import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.Item;
import net.raphimc.vialoader.util.VersionEnum;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.HandItemProvider;
import de.florianmichael.viafabricplus.protocolhack.usage.ItemTranslator;
import de.florianmichael.viafabricplus.protocolhack.util.ItemTranslator;
import net.minecraft.item.ItemStack;
public class ViaFabricPlusHandItemProvider extends HandItemProvider {

View File

@ -15,9 +15,10 @@
* 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 de.florianmichael.viafabricplus.protocolhack.usage;
package de.florianmichael.viafabricplus.protocolhack.util;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.ProtocolPathEntry;
import com.viaversion.viaversion.api.protocol.packet.Direction;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
@ -35,6 +36,7 @@ import java.util.List;
import java.util.stream.Collectors;
public class BlockStateTranslator {
private final static UserConnection DUMMY_USER_CONNECTION = new UserConnectionImpl(null, false);
public static int translateBlockState1_18(int oldId) {
final List<ProtocolPathEntry> protocolPath = Via.getManager().getProtocolManager().getProtocolPath(SharedConstants.getProtocolVersion(), ProtocolVersion.v1_18_2.getVersion());
@ -45,7 +47,7 @@ public class BlockStateTranslator {
inputData.writeVarInt(oldId);
try {
var wrapper = PacketWrapper.create(ClientboundPackets1_18.BLOCK_CHANGE, inputData.asByteBuf(), new UserConnectionImpl(null, true));
var wrapper = PacketWrapper.create(ClientboundPackets1_18.BLOCK_CHANGE, inputData.asByteBuf(), DUMMY_USER_CONNECTION);
wrapper.apply(Direction.CLIENTBOUND, State.PLAY, 0, protocolPath.stream().map(ProtocolPathEntry::protocol).collect(Collectors.toList()), true);
wrapper.read(Type.POSITION1_14);

View File

@ -15,7 +15,7 @@
* 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 de.florianmichael.viafabricplus.protocolhack.usage;
package de.florianmichael.viafabricplus.protocolhack.util;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
@ -39,6 +39,7 @@ import java.util.List;
import java.util.stream.Collectors;
public class ItemTranslator {
private final static UserConnection DUMMY_USER_CONNECTION = new UserConnectionImpl(null, false);
public static Item minecraftToViaVersion(final ItemStack stack, final int targetVersion) {
final List<ProtocolPathEntry> protocolPath = Via.getManager().getProtocolManager().getProtocolPath(SharedConstants.getProtocolVersion(), targetVersion);
@ -51,7 +52,7 @@ public class ItemTranslator {
final int id = NetworkState.PLAY.getPacketId(NetworkSide.SERVERBOUND, dummyPacket);
try {
final PacketWrapper wrapper = new PacketWrapperImpl(id, emptyBuf, new UserConnectionImpl(null, true));
final PacketWrapper wrapper = new PacketWrapperImpl(id, emptyBuf, DUMMY_USER_CONNECTION);
wrapper.apply(Direction.SERVERBOUND, State.PLAY, 0, protocolPath.stream().map(ProtocolPathEntry::protocol).collect(Collectors.toList()));
wrapper.read(Type.SHORT);

View File

@ -11,4 +11,6 @@ accessible field net/minecraft/client/font/FontManager fontStorages Ljava/util/M
accessible field net/minecraft/network/ClientConnection EPOLL_CLIENT_IO_GROUP Lnet/minecraft/util/Lazy;
accessible field net/minecraft/network/ClientConnection LOCAL_CLIENT_IO_GROUP Lnet/minecraft/util/Lazy;
accessible method net/minecraft/screen/GenericContainerScreenHandler <init> (Lnet/minecraft/screen/ScreenHandlerType;ILnet/minecraft/entity/player/PlayerInventory;I)V
accessible class net/minecraft/client/gui/screen/GameModeSelectionScreen$GameModeSelection

View File

@ -28,6 +28,7 @@
"fixes.minecraft.MixinClientPlayerInteractionManager",
"fixes.minecraft.MixinClientPlayNetworkHandler",
"fixes.minecraft.MixinDrawContext",
"fixes.minecraft.MixinHandledScreens",
"fixes.minecraft.MixinInGameHud",
"fixes.minecraft.MixinItemRenderer",
"fixes.minecraft.MixinMinecraftClient",
@ -41,6 +42,7 @@
"fixes.minecraft.MixinTextRenderer",
"fixes.minecraft.block.MixinAbstractBlock",
"fixes.minecraft.block.MixinAbstractBlock_AbstractBlockState",
"fixes.minecraft.block.MixinAbstractSignBlock",
"fixes.minecraft.block.MixinAnvilBlock",
"fixes.minecraft.block.MixinBambooBlock",
"fixes.minecraft.block.MixinBedBlock",
@ -68,6 +70,8 @@
"fixes.minecraft.entity.MixinAbstractDonkeyEntity",
"fixes.minecraft.entity.MixinAllayEntity",
"fixes.minecraft.entity.MixinAnimalEntity",
"fixes.minecraft.entity.MixinBoatEntity",
"fixes.minecraft.entity.MixinCamelEntity",
"fixes.minecraft.entity.MixinClientPlayerEntity",
"fixes.minecraft.entity.MixinCowEntity",
"fixes.minecraft.entity.MixinCreeperEntity",
@ -91,6 +95,7 @@
"fixes.minecraft.item.MixinArmorItem",
"fixes.minecraft.item.MixinAxeItem",
"fixes.minecraft.item.MixinBlockItem",
"fixes.minecraft.item.MixinBrushItem",
"fixes.minecraft.item.MixinElytraItem",
"fixes.minecraft.item.MixinEnderPearlItem",
"fixes.minecraft.item.MixinFireworkRocketItem",
@ -152,6 +157,7 @@
"fixes.viaversion.protocol1_18_2to1_18.MixinProtocol1_18_2To1_18",
"fixes.viaversion.protocol1_19_1to1_19.MixinProtocol1_19_1To1_19",
"fixes.viaversion.protocol1_19_3to1_19_1.MixinProtocol1_19_3To1_19_1",
"fixes.viaversion.protocol1_19to1_18_2.MixinWorldPackets",
"fixes.viaversion.protocol1_9_1to1_9.MixinProtocol1_9_1To1_9",
"fixes.viaversion.protocol1_9to1_8.MixinChunk1_8Type",
"fixes.viaversion.protocol1_9to1_8.MixinCommandBlockProvider",
@ -163,11 +169,7 @@
"jsonwebtoken.MixinClasses",
"jsonwebtoken.MixinDefaultCompressionCodecResolver",
"jsonwebtoken.MixinDefaultJwtParserBuilder",
"fixes.minecraft.block.MixinAbstractSignBlock",
"fixes.minecraft.entity.MixinBoatEntity",
"fixes.minecraft.entity.MixinCamelEntity",
"fixes.minecraft.item.MixinBrushItem",
"fixes.viaversion.protocol1_19to1_18_2.MixinWorldPackets"
"fixes.viaversion.protocol1_14to1_13_2.MixinInventoryPackets"
],
"injectors": {
"defaultRequire": 1