diff --git a/build.gradle b/build.gradle index 687d216a2..574031e92 100644 --- a/build.gradle +++ b/build.gradle @@ -80,6 +80,9 @@ dependencies { // Lenni0451 Libraries jij "net.lenni0451:Reflect:${project.reflect_version}" + jij("net.lenni0451:MCPing:${project.mcping_version}") { + exclude group: "com.google.code.gson", module: "gson" + } // Misc Libraries jij("org.cloudburstmc.netty:netty-transport-raknet:${project.raknet_transport_version}") { diff --git a/gradle.properties b/gradle.properties index a91bbb4be..b9a99d4f3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -27,6 +27,7 @@ raknet_transport_version=1.0.0.CR1-SNAPSHOT # Lenni0451 Libraries reflect_version=1.3.0 +mcping_version=1.3.0 # Misc Libraries mod_menu_version=8.0.0 diff --git a/src/main/java/de/florianmichael/viafabricplus/ViaFabricPlus.java b/src/main/java/de/florianmichael/viafabricplus/ViaFabricPlus.java index 21634897f..ebf6f1fe8 100644 --- a/src/main/java/de/florianmichael/viafabricplus/ViaFabricPlus.java +++ b/src/main/java/de/florianmichael/viafabricplus/ViaFabricPlus.java @@ -20,12 +20,11 @@ package de.florianmichael.viafabricplus; import de.florianmichael.viafabricplus.event.PostGameLoadCallback; -import de.florianmichael.viafabricplus.event.LoadCallback; import de.florianmichael.viafabricplus.fixes.ClientsideFixes; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; -import de.florianmichael.viafabricplus.util.ClassLoaderPriorityUtil; import de.florianmichael.viafabricplus.save.SaveManager; import de.florianmichael.viafabricplus.settings.SettingsManager; +import de.florianmichael.viafabricplus.util.ClassLoaderPriorityUtil; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -38,7 +37,7 @@ * - Window interactions in <= 1.16.5 has changed and can be detected by the server * - Most CTS protocol features aren't supported (see https://github.com/ViaVersion/ViaFabricPlus/issues/181) * - Most CPE features aren't implemented correctly (see https://github.com/ViaVersion/ViaFabricPlus/issues/152) - * - Bedrock scaffolding should be added as soon as ViaBedrock supports block placement (see https://github.com/ViaVersion/ViaFabricPlus/issues/204) + * - Check if MixinPlayerScreenHandler.injectTransferSlot is needed? Check git log * * TODO | Movement * - X/Z Face based jump movement in <= 1.13.2 is broken (https://github.com/ViaVersion/ViaFabricPlus/issues/189) @@ -46,13 +45,16 @@ * - Blit-jump is not supported in <= 1.8.9 (https://github.com/ViaVersion/ViaFabricPlus/issues/225) * * TODO | Migration v3 - * - Rename all methods * - Use ViaProxy config patch for some clientside fixes options (Remove ViaFabricPlusVLViaConfig and MixinViaLegacyConfig) - * - Fix auto detect to not be a huge mess + * - Add setting for VFP AlphaInventoryProvider * - Fix MixinAbstractDonkeyEntity - * - Boats are probably broken. Check entity height offset fix * - Check TO DO in MixinEntity - * - Diff ItemRegistryDiff from projects and add missing items + * - Fix MixinMultiplayerServerListWidget_ServerEntry + * - Test villagers + * - Test offhand + * - Check if attack cooldown is there or not + * - Test very large 1.8 chests + * - Test block ack */ public class ViaFabricPlus { private static final ViaFabricPlus instance = new ViaFabricPlus(); diff --git a/src/main/java/de/florianmichael/viafabricplus/fixes/ActionResultException.java b/src/main/java/de/florianmichael/viafabricplus/fixes/ActionResultException.java new file mode 100644 index 000000000..c24a9e74d --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/fixes/ActionResultException.java @@ -0,0 +1,41 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.fixes; + +import net.minecraft.util.ActionResult; + +public class ActionResultException extends RuntimeException { + + private final ActionResult actionResult; + + public ActionResultException(final ActionResult actionResult) { + this.actionResult = actionResult; + } + + public ActionResult getActionResult() { + return this.actionResult; + } + + @Override + public synchronized Throwable fillInStackTrace() { + return this; + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/fixes/ArmorUpdateListener.java b/src/main/java/de/florianmichael/viafabricplus/fixes/ArmorUpdateListener.java new file mode 100644 index 000000000..731c42bcf --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/fixes/ArmorUpdateListener.java @@ -0,0 +1,67 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.fixes; + +import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; +import com.viaversion.viaversion.api.type.Type; +import com.viaversion.viaversion.protocols.protocol1_9to1_8.ArmorType; +import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9; +import com.viaversion.viaversion.protocols.protocol1_9to1_8.Protocol1_9To1_8; +import de.florianmichael.viafabricplus.ViaFabricPlus; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.minecraft.client.MinecraftClient; +import net.minecraft.item.ItemStack; +import net.minecraft.registry.Registries; + +public class ArmorUpdateListener { + + public static void init() { + ClientTickEvents.START_WORLD_TICK.register(world -> { + if (MinecraftClient.getInstance().player != null) { + try { + sendArmorUpdate(); + } catch (Throwable t) { + ViaFabricPlus.global().getLogger().error("Error sending armor update", t); + } + } + }); + } + + public static void sendArmorUpdate() throws Exception { + int armor = 0; + for (final ItemStack stack : MinecraftClient.getInstance().player.getInventory().armor) { + armor += ArmorType.findByType(Registries.ITEM.getId(stack.getItem()).toString()).getArmorPoints(); + } + if (armor == this.oldArmor) return; + + this.oldArmor = armor; + final PacketWrapper properties = PacketWrapper.create(ClientboundPackets1_9.ENTITY_PROPERTIES, MinecraftClient.getInstance().getNetworkHandler().getConnection().getUserConnection()); + properties.write(Type.VAR_INT, MinecraftClient.getInstance().player.getId()); + properties.write(Type.INT, 1); + properties.write(Type.STRING, "generic.armor"); + properties.write(Type.DOUBLE, 0D); + properties.write(Type.VAR_INT, 1); + properties.write(Type.UUID, ARMOR_POINTS_UUID); + properties.write(Type.DOUBLE, (double) armor); + properties.write(Type.BYTE, (byte) 0); + properties.scheduleSend(Protocol1_9To1_8.class); + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/fixes/ChestHandler1_13_2.java b/src/main/java/de/florianmichael/viafabricplus/fixes/ChestHandler1_13_2.java new file mode 100644 index 000000000..674eed543 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/fixes/ChestHandler1_13_2.java @@ -0,0 +1,50 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.fixes; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.ingame.GenericContainerScreen; +import net.minecraft.inventory.SimpleInventory; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.screen.GenericContainerScreenHandler; +import net.minecraft.text.Text; +import net.minecraft.util.math.MathHelper; + +import java.util.function.Consumer; + +public class ChestHandler1_13_2 { + + public static final Consumer OLD_PACKET_HANDLER = data -> { + final MinecraftClient mc = MinecraftClient.getInstance(); + + try { + final int windowId = data.readUnsignedByte(); + final int slots = data.readUnsignedByte(); + final Text title = data.readText(); + + final GenericContainerScreenHandler screenHandler = new GenericContainerScreenHandler(null, windowId, mc.player.getInventory(), new SimpleInventory(slots), MathHelper.ceil(slots / 9F)); + mc.player.currentScreenHandler = screenHandler; + mc.setScreen(new GenericContainerScreen(screenHandler, mc.player.getInventory(), title)); + } catch (Throwable t) { + throw new RuntimeException("Failed to handle OpenWindow packet data", t); + } + }; + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/fixes/ClientPlayerInteractionManager1_18_2.java b/src/main/java/de/florianmichael/viafabricplus/fixes/ClientPlayerInteractionManager1_18_2.java index c1d38df3d..7cdb3d893 100644 --- a/src/main/java/de/florianmichael/viafabricplus/fixes/ClientPlayerInteractionManager1_18_2.java +++ b/src/main/java/de/florianmichael/viafabricplus/fixes/ClientPlayerInteractionManager1_18_2.java @@ -21,7 +21,7 @@ import de.florianmichael.viafabricplus.ViaFabricPlus; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; -import de.florianmichael.viafabricplus.protocolhack.util.BlockStateTranslator; +import de.florianmichael.viafabricplus.protocolhack.translator.BlockStateTranslator; import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -33,62 +33,62 @@ import net.minecraft.util.math.Vec2f; import net.raphimc.vialoader.util.VersionEnum; -import java.util.Objects; import java.util.function.Consumer; public class ClientPlayerInteractionManager1_18_2 { + public static final Consumer OLD_PACKET_HANDLER = data -> { try { final var pos = data.readBlockPos(); - final var blockState = Block.STATE_IDS.get(BlockStateTranslator.translateBlockState1_18(data.readVarInt())); + final var blockState = BlockStateTranslator.via1_18_2toMc(data.readVarInt()); final var action = data.readEnumConstant(PlayerActionC2SPacket.Action.class); final var allGood = data.readBoolean(); ClientPlayerInteractionManager1_18_2.handleBlockBreakAck(pos, blockState, action, allGood); - } catch (Exception e) { - ViaFabricPlus.global().getLogger().error("Failed to read BlockBreakAck packet data", e); + } catch (Throwable t) { + throw new RuntimeException("Failed to handle BlockBreakAck packet data", t); } }; - private static final Object2ObjectLinkedOpenHashMap, PositionAndRotation> UN_ACKED_ACTIONS = new Object2ObjectLinkedOpenHashMap<>(); + private static final Object2ObjectLinkedOpenHashMap, PositionAndRotation> UNACKED_ACTIONS = new Object2ObjectLinkedOpenHashMap<>(); - public static void trackBlockAction(final PlayerActionC2SPacket.Action action, final BlockPos blockPos) { + public static void trackPlayerAction(final PlayerActionC2SPacket.Action action, final BlockPos blockPos) { final var player = MinecraftClient.getInstance().player; if (player == null) return; var rotation = new Vec2f(player.getYaw(), player.getPitch()); - if (ProtocolHack.getTargetVersion().isNewerThan(VersionEnum.r1_16_2)) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_16_1)) { rotation = null; } - UN_ACKED_ACTIONS.put(new Pair<>(blockPos, action), new PositionAndRotation(player.getPos().x, player.getPos().y, player.getPos().z, rotation)); + UNACKED_ACTIONS.put(new Pair<>(blockPos, action), new PositionAndRotation(player.getPos().x, player.getPos().y, player.getPos().z, rotation)); } - public static void handleBlockBreakAck(final BlockPos blockPos, final BlockState blockState, final PlayerActionC2SPacket.Action action, final boolean allGood) { + public static void handleBlockBreakAck(final BlockPos blockPos, final BlockState expectedState, final PlayerActionC2SPacket.Action action, final boolean allGood) { final var player = MinecraftClient.getInstance().player; if (player == null) return; + final var world = MinecraftClient.getInstance().getNetworkHandler().getWorld(); - final var world = Objects.requireNonNull(MinecraftClient.getInstance().getNetworkHandler()).getWorld(); - - final var next = UN_ACKED_ACTIONS.remove(new Pair<>(blockPos, action)); - final var blockStateFromPos = world.getBlockState(blockPos); + final var oldPlayerState = UNACKED_ACTIONS.remove(new Pair<>(blockPos, action)); + final var actualState = world.getBlockState(blockPos); - if ((next == null || !allGood || action != PlayerActionC2SPacket.Action.START_DESTROY_BLOCK && blockStateFromPos != blockState) && blockStateFromPos != blockState) { - world.setBlockState(blockPos, blockState); - if (next != null && world == player.getWorld() && player.collidesWithStateAtPos(blockPos, blockState)) { - if (next.rotation != null) { - player.updatePositionAndAngles(next.x, next.y, next.z, next.rotation.x, next.rotation.y); + if ((oldPlayerState == null || !allGood || action != PlayerActionC2SPacket.Action.START_DESTROY_BLOCK && actualState != expectedState) && (actualState != expectedState || ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_15_2))) { + world.setBlockState(blockPos, expectedState, Block.NOTIFY_ALL | Block.FORCE_STATE); + if (oldPlayerState != null && ((ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_16_1) || (world == player.getWorld() && player.collidesWithStateAtPos(blockPos, expectedState))))) { + if (oldPlayerState.rotation != null) { + player.updatePositionAndAngles(oldPlayerState.x, oldPlayerState.y, oldPlayerState.z, oldPlayerState.rotation.x, oldPlayerState.rotation.y); } else { - player.updatePosition(next.x, next.y, next.z); + player.updatePosition(oldPlayerState.x, oldPlayerState.y, oldPlayerState.z); } } } - while (UN_ACKED_ACTIONS.size() >= 50) { - ViaFabricPlus.global().getLogger().error("Too many unacked block actions, dropping {}", UN_ACKED_ACTIONS.firstKey()); - UN_ACKED_ACTIONS.removeFirst(); + while (UNACKED_ACTIONS.size() >= 50) { + ViaFabricPlus.global().getLogger().warn("Too many unacked block actions, dropping {}", UNACKED_ACTIONS.firstKey()); + UNACKED_ACTIONS.removeFirst(); } } public record PositionAndRotation(double x, double y, double z, Vec2f rotation) { } + } diff --git a/src/main/java/de/florianmichael/viafabricplus/fixes/ClientsideFixes.java b/src/main/java/de/florianmichael/viafabricplus/fixes/ClientsideFixes.java index a231ba88b..cd51339ee 100644 --- a/src/main/java/de/florianmichael/viafabricplus/fixes/ClientsideFixes.java +++ b/src/main/java/de/florianmichael/viafabricplus/fixes/ClientsideFixes.java @@ -19,28 +19,22 @@ package de.florianmichael.viafabricplus.fixes; -import com.viaversion.viaversion.protocols.protocol1_9to1_8.ArmorType; import de.florianmichael.viafabricplus.event.ChangeProtocolVersionCallback; -import de.florianmichael.viafabricplus.event.PostGameLoadCallback; import de.florianmichael.viafabricplus.event.LoadClassicProtocolExtensionCallback; import de.florianmichael.viafabricplus.fixes.classic.CustomClassicProtocolExtensions; import de.florianmichael.viafabricplus.fixes.classic.screen.ClassicItemSelectionScreen; import de.florianmichael.viafabricplus.injection.ViaFabricPlusMixinPlugin; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; +import net.minecraft.block.*; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.FontStorage; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; import net.minecraft.network.PacketByteBuf; import net.minecraft.registry.Registries; import net.raphimc.vialegacy.protocols.classic.protocolc0_28_30toc0_28_30cpe.data.ClassicProtocolExtension; import net.raphimc.vialoader.util.VersionEnum; -import net.raphimc.vialoader.util.VersionRange; -import java.util.*; +import java.util.List; +import java.util.Map; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; @@ -54,16 +48,6 @@ public class ClientsideFixes { */ private static List RELOADABLE_BLOCKS; - /** - * Legacy versions do not support SRV records, so we need to resolve them manually - */ - public static final VersionRange LEGACY_SRV_RESOLVE = VersionRange.andOlder(VersionEnum.r1_2_4tor1_2_5).add(VersionRange.single(VersionEnum.bedrockLatest)); - - /** - * Contains the armor points of all armor items in legacy versions (<= 1.8.x) - */ - private static final Map LEGACY_ARMOR_POINTS = new HashMap<>(); - /** * Contains all tasks that are waiting for a packet to be received, this system can be used to sync ViaVersion tasks with the correct thread */ @@ -74,63 +58,59 @@ public class ClientsideFixes { */ public static final String PACKET_SYNC_IDENTIFIER = UUID.randomUUID() + ":" + UUID.randomUUID(); + private static final float DEFAULT_SOUL_SAND_VELOCITY_MULTIPLIER = Blocks.SOUL_SAND.getVelocityMultiplier(); + private static final float _1_14_4_SOUL_SAND_VELOCITY_MULTIPLIER = 1F; + /** * The current chat limit */ - private static int currentChatLimit = 256; + private static int currentChatLength = 256; public static void init() { CustomClassicProtocolExtensions.create(); - - PostGameLoadCallback.EVENT.register(() -> { - // Loads the armor points of all armor items in legacy versions (<= 1.8.x) - for (Item armorItem : Arrays.asList(Items.LEATHER_HELMET, Items.LEATHER_CHESTPLATE, Items.LEATHER_BOOTS, - Items.CHAINMAIL_HELMET, Items.CHAINMAIL_CHESTPLATE, Items.CHAINMAIL_LEGGINGS, Items.CHAINMAIL_BOOTS, - Items.IRON_HELMET, Items.IRON_CHESTPLATE, Items.IRON_LEGGINGS, Items.IRON_BOOTS, Items.DIAMOND_HELMET, - Items.DIAMOND_CHESTPLATE, Items.DIAMOND_LEGGINGS, Items.DIAMOND_BOOTS, Items.GOLDEN_HELMET, - Items.GOLDEN_CHESTPLATE, Items.GOLDEN_LEGGINGS, Items.GOLDEN_BOOTS)) { - LEGACY_ARMOR_POINTS.put(armorItem, ArmorType.findByType(Registries.ITEM.getId(armorItem).toString()).getArmorPoints()); - } - - RELOADABLE_BLOCKS = Arrays.asList(Blocks.ANVIL, Blocks.WHITE_BED, Blocks.ORANGE_BED, - Blocks.MAGENTA_BED, Blocks.LIGHT_BLUE_BED, Blocks.YELLOW_BED, Blocks.LIME_BED, Blocks.PINK_BED, Blocks.GRAY_BED, - Blocks.LIGHT_GRAY_BED, Blocks.CYAN_BED, Blocks.PURPLE_BED, Blocks.BLUE_BED, Blocks.BROWN_BED, Blocks.GREEN_BED, - Blocks.RED_BED, Blocks.BLACK_BED, Blocks.BREWING_STAND, Blocks.CAULDRON, Blocks.CHEST, Blocks.PITCHER_CROP, - Blocks.END_PORTAL, Blocks.END_PORTAL_FRAME, Blocks.FARMLAND, Blocks.OAK_FENCE, Blocks.HOPPER, Blocks.LADDER, - Blocks.LILY_PAD, Blocks.GLASS_PANE, Blocks.WHITE_STAINED_GLASS_PANE, Blocks.ORANGE_STAINED_GLASS_PANE, - Blocks.MAGENTA_STAINED_GLASS_PANE, Blocks.LIGHT_BLUE_STAINED_GLASS_PANE, Blocks.YELLOW_STAINED_GLASS_PANE, - Blocks.LIME_STAINED_GLASS_PANE, Blocks.PINK_STAINED_GLASS_PANE, Blocks.GRAY_STAINED_GLASS_PANE, - Blocks.LIGHT_GRAY_STAINED_GLASS_PANE, Blocks.CYAN_STAINED_GLASS_PANE, Blocks.PURPLE_STAINED_GLASS_PANE, - Blocks.BLUE_STAINED_GLASS_PANE, Blocks.BROWN_STAINED_GLASS_PANE, Blocks.GREEN_STAINED_GLASS_PANE, - Blocks.RED_STAINED_GLASS_PANE, Blocks.BLACK_STAINED_GLASS_PANE, Blocks.PISTON, Blocks.PISTON_HEAD, - Blocks.SNOW, Blocks.COBBLESTONE_WALL, Blocks.MOSSY_COBBLESTONE_WALL - ); - }); + EntityHitboxUpdateListener.init(); + ArmorUpdateListener.init(); // Reloads some clientside stuff when the protocol version changes ChangeProtocolVersionCallback.EVENT.register((oldVersion, newVersion) -> MinecraftClient.getInstance().execute(() -> { - if (MinecraftClient.getInstance() == null) return; + // Soul sand velocity multiplier + if (isNewerThan(oldVersion, newVersion, VersionEnum.r1_14_4)) { + Blocks.SOUL_SAND.velocityMultiplier = DEFAULT_SOUL_SAND_VELOCITY_MULTIPLIER; + } + if (isOlderThanOrEqualTo(oldVersion, newVersion, VersionEnum.r1_14_4)) { + Blocks.SOUL_SAND.velocityMultiplier = _1_14_4_SOUL_SAND_VELOCITY_MULTIPLIER; + } // Reloads all bounding boxes - for (Block block : RELOADABLE_BLOCKS) { - for (BlockState state : block.getStateManager().getStates()) { - state.initShapeCache(); + for (Block block : Registries.BLOCK) { + if (block instanceof AnvilBlock || block instanceof BedBlock || block instanceof BrewingStandBlock + || block instanceof CarpetBlock || block instanceof CauldronBlock || block instanceof ChestBlock + || block instanceof EnderChestBlock || block instanceof EndPortalBlock || block instanceof EndPortalFrameBlock + || block instanceof FarmlandBlock || block instanceof FenceBlock || block instanceof FenceGateBlock + || block instanceof HopperBlock || block instanceof LadderBlock || block instanceof LeavesBlock + || block instanceof LilyPadBlock || block instanceof PaneBlock || block instanceof PistonBlock + || block instanceof PistonHeadBlock || block instanceof SnowBlock || block instanceof WallBlock + || block instanceof CropBlock || block instanceof FlowerbedBlock + ) { + for (BlockState state : block.getStateManager().getStates()) { + state.initShapeCache(); + } } } - // Calculates the current chat limit, since it changes depending on the protocol version + // Calculates the current chat length limit if (newVersion.isOlderThanOrEqualTo(VersionEnum.c0_28toc0_30)) { - currentChatLimit = 64 - (MinecraftClient.getInstance().getSession().getUsername().length() + 2); + currentChatLength = 64 - (MinecraftClient.getInstance().getSession().getUsername().length() + 2); } else if (newVersion.equals(VersionEnum.bedrockLatest)) { - currentChatLimit = 512; + currentChatLength = 512; } else if (newVersion.isOlderThanOrEqualTo(VersionEnum.r1_9_3tor1_9_4)) { - currentChatLimit = 100; + currentChatLength = 100; } else { - currentChatLimit = 256; + currentChatLength = 256; } + // Text Renderer invisible character fix if (!ViaFabricPlusMixinPlugin.DASH_LOADER_PRESENT) { - // Reloads all font storages to fix the font renderer for (FontStorage storage : MinecraftClient.getInstance().fontManager.fontStorages.values()) { storage.glyphRendererCache.clear(); storage.glyphCache.clear(); @@ -145,7 +125,7 @@ public static void init() { // Calculates the current chat limit, since it changes depending on the protocol version LoadClassicProtocolExtensionCallback.EVENT.register(classicProtocolExtension -> { if (classicProtocolExtension == ClassicProtocolExtension.LONGER_MESSAGES) { - currentChatLimit = Short.MAX_VALUE * 2; + currentChatLength = Short.MAX_VALUE * 2; } }); } @@ -163,33 +143,30 @@ public static String executeSyncTask(final Consumer task) { } public static void handleSyncTask(final PacketByteBuf buf) { - buf.resetReaderIndex(); - final var uuid = buf.readString(); if (PENDING_EXECUTION_TASKS.containsKey(uuid)) { MinecraftClient.getInstance().execute(() -> { // Execute the task on the main thread - final var task = PENDING_EXECUTION_TASKS.get(uuid); - PENDING_EXECUTION_TASKS.remove(uuid); - + final var task = PENDING_EXECUTION_TASKS.remove(uuid); task.accept(buf); }); } } - /** - * Returns the armor points of an armor item in legacy versions (<= 1.8.x) - * - * @param itemStack The item stack to get the armor points from - * @return The armor points of the item stack - */ - public static int getLegacyArmorPoints(final ItemStack itemStack) { - if (!LEGACY_ARMOR_POINTS.containsKey(itemStack.getItem())) return 0; // Just in case + public static int getCurrentChatLength() { + return currentChatLength; + } - return LEGACY_ARMOR_POINTS.get(itemStack.getItem()); + private static boolean isOlderThanOrEqualTo(final VersionEnum oldVersion, final VersionEnum newVersion, final VersionEnum toCheck) { + return oldVersion.isNewerThan(toCheck) && newVersion.isOlderThanOrEqualTo(toCheck); } - public static int getCurrentChatLimit() { - return currentChatLimit; + private static boolean isNewerThan(final VersionEnum oldVersion, final VersionEnum newVersion, final VersionEnum toCheck) { + return newVersion.isNewerThan(toCheck) && oldVersion.isOlderThanOrEqualTo(toCheck); } + + private static boolean didCrossBoundary(final VersionEnum oldVersion, final VersionEnum newVersion, final VersionEnum toCheck) { + return isNewerThan(oldVersion, newVersion, toCheck) || isOlderThanOrEqualTo(oldVersion, newVersion, toCheck); + } + } diff --git a/src/main/java/de/florianmichael/viafabricplus/fixes/EntityHeightOffsetsPre1_20_2.java b/src/main/java/de/florianmichael/viafabricplus/fixes/EntityHeightOffsetsPre1_20_2.java index 4c98ecde3..ea1e9950c 100644 --- a/src/main/java/de/florianmichael/viafabricplus/fixes/EntityHeightOffsetsPre1_20_2.java +++ b/src/main/java/de/florianmichael/viafabricplus/fixes/EntityHeightOffsetsPre1_20_2.java @@ -39,144 +39,141 @@ public class EntityHeightOffsetsPre1_20_2 { public static Vector3f getMountedHeightOffset(final Entity entity, final Entity passenger) { - double yOffset = entity.getHeight() * 0.75; + float yOffset = entity.getHeight() * 0.75F; - if (entity instanceof LlamaEntity llamaEntity) { - yOffset = entity.getHeight() * 0.6; + if (entity instanceof BoatEntity boatEntity) { + if (!boatEntity.hasPassenger(passenger)) return new Vector3f(); - final float xOffset = MathHelper.sin(llamaEntity.bodyYaw * 0.017453292F); - final float zOffset = MathHelper.cos(llamaEntity.bodyYaw * 0.017453292F); + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) { + yOffset = -0.3F; + final float xOffset = MathHelper.cos(boatEntity.getYaw() * MathHelper.PI / 180F); + final float zOffset = MathHelper.sin(boatEntity.getYaw() * MathHelper.PI / 180F); - return new Vector3f(0.3F * xOffset, (float) yOffset, -(0.3F * zOffset)); - } else if (entity instanceof CamelEntity camelEntity) { - yOffset = entity.getDimensions(camelEntity.isSitting() ? EntityPose.SITTING : EntityPose.STANDING).height - (camelEntity.isBaby() ? 0.35F : 0.6F); - - final int passengerIndex = camelEntity.getPassengerList().indexOf(passenger); - final boolean firstIndex = passengerIndex == 0; - if (passengerIndex >= 0) { - float zOffset = 0.5f; - if (camelEntity.isRemoved()) { - yOffset = 0.01f; + return new Vector3f(0.4F * xOffset, yOffset, 0.4F * zOffset); + } else { + if (boatEntity.isRemoved()) { + yOffset = 0.01F; } else { - final var fakeDimension = EntityDimensions.fixed(0F, (0.375F * camelEntity.getScaleFactor()) + (float) yOffset); // Reverts original calculation to set yOffset to our field - yOffset = camelEntity.getPassengerAttachmentY(firstIndex, 0.0f, fakeDimension, camelEntity.getScaleFactor()); + yOffset = boatEntity.getVariant() == BoatEntity.Type.BAMBOO ? 0.25F : -0.1F; } - if (camelEntity.getPassengerList().size() > 1) { - if (!firstIndex) zOffset = -0.7f; - if (passenger instanceof AnimalEntity) zOffset += 0.2f; + float xOffset = boatEntity instanceof ChestBoatEntity ? 0.15F : 0F; + if (boatEntity.getPassengerList().size() > 1) { + final int idx = boatEntity.getPassengerList().indexOf(passenger); + if (idx == 0) { + xOffset = 0.2F; + } else { + xOffset = -0.6F; + } + + if (passenger instanceof AnimalEntity) xOffset += 0.2F; } - return new Vector3f(0, (float) yOffset, zOffset); - } else { - return new Vector3f(); + return new Vector3f(xOffset, yOffset, 0F); } - } else if (entity instanceof SnifferEntity) { - yOffset = 1.8; - } else if (entity instanceof EnderDragonEntity enderDragonEntity) { - yOffset = enderDragonEntity.body.getHeight(); - } else if (entity instanceof PiglinEntity) { - yOffset = entity.getHeight() * 0.92; - } else if (entity instanceof HoglinEntity hoglinEntity) { - yOffset = entity.getHeight() - (hoglinEntity.isBaby() ? 0.2 : 0.15); - } else if (entity instanceof SkeletonHorseEntity) { - yOffset -= 0.1875; - } else if (entity instanceof PhantomEntity) { - yOffset = entity.getEyeHeight(entity.getPose()); - } else if (entity instanceof RavagerEntity) { - yOffset = 2.1; - } else if (entity instanceof ZoglinEntity zoglinEntity) { - yOffset = (double) entity.getHeight() - (zoglinEntity.isBaby() ? 0.2 : 0.15); - } else if (entity instanceof BoatEntity boatEntity) { - final var version = ProtocolHack.getTargetVersion(); - if (version.isOlderThanOrEqualTo(VersionEnum.r1_8)) { - yOffset = -0.3; + } else if (entity instanceof CamelEntity camelEntity) { + if (!camelEntity.hasPassenger(passenger)) return new Vector3f(); + + final boolean firstPassenger = camelEntity.getPassengerList().indexOf(passenger) == 0; + yOffset = camelEntity.getDimensions(camelEntity.isSitting() ? EntityPose.SITTING : EntityPose.STANDING).height - (camelEntity.isBaby() ? 0.35F : 0.6F); + if (camelEntity.isRemoved()) { + yOffset = 0.01F; } else { - yOffset = boatEntity.getVariant() == BoatEntity.Type.BAMBOO ? 0.25 : -0.1; + yOffset = (float) camelEntity.getPassengerAttachmentY(firstPassenger, 0F, EntityDimensions.fixed(0F, (0.375F * camelEntity.getScaleFactor()) + yOffset), camelEntity.getScaleFactor()); } - if (boatEntity.hasPassenger(passenger)) { - float xOffset = (boatEntity instanceof ChestBoatEntity) ? 0.15F : 0.0F; - yOffset = (boatEntity.isRemoved() ? (double) 0.01f : yOffset); + float zOffset = 0.5F; + if (camelEntity.getPassengerList().size() > 1) { + if (!firstPassenger) zOffset = -0.7F; + if (passenger instanceof AnimalEntity) zOffset += 0.2F; + } - if (boatEntity.getPassengerList().size() > 1) { - int i = boatEntity.getPassengerList().indexOf(passenger); - xOffset = i == 0 ? 0.2f : -0.6f; - if (passenger instanceof AnimalEntity) { - xOffset += 0.2f; - } - } + return new Vector3f(0, yOffset, zOffset); + } else if (entity instanceof ChickenEntity chickenEntity) { + final float xOffset = MathHelper.sin(chickenEntity.bodyYaw * MathHelper.PI / 180F); + final float zOffset = MathHelper.cos(chickenEntity.bodyYaw * MathHelper.PI / 180F); - return new Vector3f(xOffset, (float) yOffset, 0.0F); - } else { - return new Vector3f(); - } - } else if (entity instanceof StriderEntity striderEntity) { - final var var1 = Math.min(0.25F, striderEntity.limbAnimator.getSpeed()); - final var var2 = striderEntity.limbAnimator.getPos(); + return new Vector3f(0.1F * xOffset, (float) (chickenEntity.getBodyY(0.5D) - chickenEntity.getY()), -0.1F * zOffset); + } else if (entity instanceof EnderDragonEntity enderDragonEntity) { + yOffset = enderDragonEntity.body.getHeight(); + } else if (entity instanceof HoglinEntity hoglinEntity) { + yOffset = hoglinEntity.getHeight() - (hoglinEntity.isBaby() ? 0.2F : 0.15F); + } else if (entity instanceof LlamaEntity llamaEntity) { + yOffset = entity.getHeight() * 0.6F; + final float xOffset = MathHelper.sin(llamaEntity.bodyYaw * MathHelper.PI / 180F); + final float zOffset = MathHelper.cos(llamaEntity.bodyYaw * MathHelper.PI / 180F); - yOffset = (double) striderEntity.getHeight() - 0.19 + (double) (0.12F * MathHelper.cos(var2 * 1.5F) * 2.0F * var1); + return new Vector3f(0.3F * xOffset, yOffset, 0.3F * zOffset); + } else if (entity instanceof PhantomEntity) { + yOffset = entity.getStandingEyeHeight(); + } else if (entity instanceof PiglinEntity) { + yOffset = entity.getHeight() * 0.92F; + } else if (entity instanceof RavagerEntity) { + yOffset = 2.1F; + } else if (entity instanceof SkeletonHorseEntity) { + yOffset -= 0.1875F; + } else if (entity instanceof SnifferEntity) { + yOffset = 1.8F; } else if (entity instanceof SpiderEntity) { yOffset = entity.getHeight() * 0.5F; - } else if (entity instanceof ChickenEntity chickenEntity) { - final var xOffset = MathHelper.sin(chickenEntity.bodyYaw * (MathHelper.PI / 180)); - final var zOffset = MathHelper.cos(chickenEntity.bodyYaw * (MathHelper.PI / 180)); - - return new Vector3f(0.1f * xOffset, (float) (chickenEntity.getBodyY(0.5) - chickenEntity.getY()), -(0.1f * zOffset)); + } else if (entity instanceof StriderEntity striderEntity) { + final float f = Math.min(0.25F, striderEntity.limbAnimator.getSpeed()); + final float g = striderEntity.limbAnimator.getPos(); + yOffset = striderEntity.getHeight() - 0.19F + (0.12F * MathHelper.cos(g * 1.5F) * 2F * f); + } else if (entity instanceof ZoglinEntity zoglinEntity) { + yOffset = zoglinEntity.getHeight() - (zoglinEntity.isBaby() ? 0.2F : 0.15F); + } else if (entity instanceof AbstractDonkeyEntity) { + yOffset -= 0.25F; + } else if (entity instanceof AbstractMinecartEntity) { + yOffset = 0F; } - if (entity instanceof AbstractDonkeyEntity) { - yOffset -= 0.25; - } else if (entity instanceof AbstractMinecartEntity) { - yOffset = 0.0; - } else if (entity instanceof AbstractHorseEntity abstractHorseEntity) { + if (entity instanceof AbstractHorseEntity abstractHorseEntity) { if (abstractHorseEntity.lastAngryAnimationProgress > 0.0f) { - final float xOffset = MathHelper.sin(abstractHorseEntity.bodyYaw * ((float) Math.PI / 180)); - final float zOffset = MathHelper.cos(abstractHorseEntity.bodyYaw * ((float) Math.PI / 180)); - + final float xOffset = MathHelper.sin(abstractHorseEntity.bodyYaw * MathHelper.PI / 180F); + final float zOffset = MathHelper.cos(abstractHorseEntity.bodyYaw * MathHelper.PI / 180F); final float xzFactor = 0.7F * abstractHorseEntity.lastAngryAnimationProgress; - return new Vector3f(xzFactor * xOffset, (float) (yOffset + 0.15F * abstractHorseEntity.lastAngryAnimationProgress), xzFactor * zOffset); + return new Vector3f(xzFactor * xOffset, yOffset + 0.15F * abstractHorseEntity.lastAngryAnimationProgress, xzFactor * zOffset); } } - return new Vector3f(0.0F, (float) yOffset, 0.0F); + return new Vector3f(0, yOffset, 0); } public static double getHeightOffset(final Entity entity) { - if (entity instanceof ArmorStandEntity armorStandEntity && !armorStandEntity.isMarker()) { - return 0.1; - } else if (entity instanceof EndermiteEntity) { - return 0.1; - } else if (entity instanceof ShulkerEntity shulkerEntity) { - final var vehicleType = shulkerEntity.getVehicle().getType(); - - return !(shulkerEntity.getVehicle() instanceof BoatEntity) && vehicleType != EntityType.MINECART ? 0 : 0.1875 - getMountedHeightOffset(shulkerEntity.getVehicle(), null).y; - } else if (entity instanceof SilverfishEntity) { - return 0.1; - } else if (entity instanceof AllayEntity || entity instanceof VexEntity) { + if (entity instanceof AllayEntity || entity instanceof VexEntity) { if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_19_1tor1_19_2)) { return 0D; } - return 0.4; + return 0.4D; + } else if (entity instanceof ArmorStandEntity armorStandEntity) { + return armorStandEntity.isMarker() ? 0D : 0.1D; + } else if (entity instanceof EndermiteEntity) { + return 0.1D; + } else if (entity instanceof ShulkerEntity shulkerEntity) { + final EntityType vehicleType = shulkerEntity.getVehicle().getType(); + return !(shulkerEntity.getVehicle() instanceof BoatEntity) && vehicleType != EntityType.MINECART ? 0D : 0.1875D - getMountedHeightOffset(shulkerEntity.getVehicle(), null).y; + } else if (entity instanceof SilverfishEntity) { + return 0.1D; } else if (entity instanceof ZombifiedPiglinEntity zombifiedPiglinEntity) { - return zombifiedPiglinEntity.isBaby() ? -0.05 : -0.45; + return zombifiedPiglinEntity.isBaby() ? -0.05D : -0.45D; } else if (entity instanceof ZombieEntity zombieEntity) { - return zombieEntity.isBaby() ? 0.0 : -0.45; - } - - if (entity instanceof PlayerEntity) { - return -0.35; + return zombieEntity.isBaby() ? 0D : -0.45D; + } else if (entity instanceof AnimalEntity) { + return 0.14D; } else if (entity instanceof PatrolEntity) { - return -0.45; + return -0.45D; + } else if (entity instanceof PlayerEntity) { + return -0.35D; } else if (entity instanceof AbstractPiglinEntity abstractPiglinEntity) { - return abstractPiglinEntity.isBaby() ? -0.05 : -0.45; + return abstractPiglinEntity.isBaby() ? -0.05D : -0.45D; } else if (entity instanceof AbstractSkeletonEntity) { - return -0.6; - } else if (entity instanceof AnimalEntity) { - return 0.14; + return -0.6D; } - return 0; + + return 0D; } + } diff --git a/src/main/java/de/florianmichael/viafabricplus/fixes/EntityHitboxUpdateListener.java b/src/main/java/de/florianmichael/viafabricplus/fixes/EntityHitboxUpdateListener.java new file mode 100644 index 000000000..9f38f66b0 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/fixes/EntityHitboxUpdateListener.java @@ -0,0 +1,162 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.fixes; + +import de.florianmichael.viafabricplus.event.ChangeProtocolVersionCallback; +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.EntityDimensions; +import net.minecraft.entity.EntityType; +import net.raphimc.vialoader.util.VersionEnum; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class EntityHitboxUpdateListener { + + private static final Map, Map> ENTITY_DIMENSIONS = linkedHashMap( + EntityType.WITHER, linkedHashMap( + VersionEnum.r1_7_6tor1_7_10, EntityDimensions.changing(0.9F, 4.0F), + VersionEnum.r1_8, EntityType.WITHER.getDimensions() + ), + EntityType.SILVERFISH, linkedHashMap( + VersionEnum.r1_7_6tor1_7_10, EntityDimensions.changing(0.3F, 0.7F), + VersionEnum.r1_8, EntityType.SILVERFISH.getDimensions() + ), + EntityType.SNOW_GOLEM, linkedHashMap( + VersionEnum.r1_7_6tor1_7_10, EntityDimensions.changing(0.4F, 1.8F), + VersionEnum.r1_8, EntityType.SNOW_GOLEM.getDimensions() + ), + EntityType.ZOMBIE, linkedHashMap( + VersionEnum.r1_7_6tor1_7_10, EntityDimensions.changing(0.6F, 1.8F), + VersionEnum.r1_8, EntityDimensions.fixed(EntityType.ZOMBIE.getDimensions().width, EntityType.ZOMBIE.getDimensions().height), + VersionEnum.r1_9, EntityType.ZOMBIE.getDimensions() + ), + EntityType.CHICKEN, linkedHashMap( + VersionEnum.b1_7tob1_7_3, EntityDimensions.changing(0.3F, 0.4F), + VersionEnum.r1_7_6tor1_7_10, EntityDimensions.changing(0.3F, 0.7F), + VersionEnum.r1_8, EntityType.CHICKEN.getDimensions() + ), + EntityType.SHEEP, linkedHashMap( + VersionEnum.c0_28toc0_30, EntityDimensions.changing(1.4F, 1.72F), + VersionEnum.a1_0_15, EntityType.SHEEP.getDimensions() + ), + EntityType.OCELOT, linkedHashMap( + VersionEnum.r1_7_6tor1_7_10, EntityDimensions.changing(0.6F, 0.8F), + VersionEnum.r1_8, EntityType.OCELOT.getDimensions() + ), + EntityType.BOAT, linkedHashMap( + VersionEnum.r1_8, EntityDimensions.changing(1.5F, 0.6F), + VersionEnum.r1_9, EntityType.BOAT.getDimensions() + ), + EntityType.CREEPER, linkedHashMap( + VersionEnum.r1_8, EntityDimensions.changing(0.6F, 1.8F), + VersionEnum.r1_9, EntityType.CREEPER.getDimensions() + ), + EntityType.IRON_GOLEM, linkedHashMap( + VersionEnum.r1_8, EntityDimensions.changing(1.4F, 2.9F), + VersionEnum.r1_9, EntityType.IRON_GOLEM.getDimensions() + ), + EntityType.SKELETON, linkedHashMap( + VersionEnum.r1_7_6tor1_7_10, EntityDimensions.changing(0.6F, 1.8F), + VersionEnum.r1_8, EntityDimensions.changing(0.6F, 1.95F), + VersionEnum.r1_9, EntityType.SKELETON.getDimensions() + ), + EntityType.WITHER_SKELETON, linkedHashMap( + VersionEnum.r1_4_6tor1_4_7, EntityDimensions.changing(0.72F, 2.16F), + VersionEnum.r1_7_6tor1_7_10, EntityDimensions.changing(0.72F, 2.34F), + VersionEnum.r1_8, EntityDimensions.changing(0.72F, 2.535F), + VersionEnum.r1_9, EntityType.WITHER_SKELETON.getDimensions() + ), + EntityType.COW, linkedHashMap( + VersionEnum.r1_8, EntityDimensions.changing(0.9F, 1.3F), + VersionEnum.r1_9, EntityType.COW.getDimensions() + ), + EntityType.HORSE, linkedHashMap( + VersionEnum.r1_8, EntityDimensions.changing(1.4F, 1.6F), + VersionEnum.r1_9, EntityType.HORSE.getDimensions() + ), + EntityType.MOOSHROOM, linkedHashMap( + VersionEnum.r1_8, EntityDimensions.changing(0.9F, 1.3F), + VersionEnum.r1_9, EntityType.MOOSHROOM.getDimensions() + ), + EntityType.RABBIT, linkedHashMap( + VersionEnum.r1_8, EntityDimensions.changing(0.6F, 0.7F), + VersionEnum.r1_9, EntityType.RABBIT.getDimensions() + ), + EntityType.SQUID, linkedHashMap( + VersionEnum.r1_8, EntityDimensions.changing(0.95F, 0.95F), + VersionEnum.r1_9, EntityType.SQUID.getDimensions() + ), + EntityType.VILLAGER, linkedHashMap( + VersionEnum.r1_8, EntityDimensions.changing(0.6F, 1.8F), + VersionEnum.r1_9, EntityType.VILLAGER.getDimensions() + ), + EntityType.WOLF, linkedHashMap( + VersionEnum.r1_1, EntityDimensions.changing(0.8F, 0.8F), + VersionEnum.r1_8, EntityDimensions.changing(0.6F, 0.8F), + VersionEnum.r1_9, EntityType.WOLF.getDimensions() + ), + EntityType.DRAGON_FIREBALL, linkedHashMap( + VersionEnum.r1_10, EntityDimensions.changing(0.3125F, 0.3125F), + VersionEnum.r1_11, EntityType.DRAGON_FIREBALL.getDimensions() + ), + EntityType.LEASH_KNOT, linkedHashMap( + VersionEnum.r1_16_4tor1_16_5, EntityDimensions.changing(0.5F, 0.5F), + VersionEnum.r1_17, EntityType.LEASH_KNOT.getDimensions() + ), + EntityType.SLIME, linkedHashMap( + VersionEnum.r1_13_2, EntityDimensions.changing(2F, 2F), + VersionEnum.r1_14, EntityType.SLIME.getDimensions() + ), + EntityType.MAGMA_CUBE, linkedHashMap( + VersionEnum.r1_13_2, EntityDimensions.changing(2F, 2F), + VersionEnum.r1_14, EntityType.MAGMA_CUBE.getDimensions() + ), + EntityType.ARROW, linkedHashMap( + VersionEnum.c0_28toc0_30, EntityDimensions.changing(0.3F, 0.5F), + VersionEnum.a1_0_15, EntityType.ARROW.getDimensions() + ) + ); + + public static void init() { + ChangeProtocolVersionCallback.EVENT.register((oldVersion, newVersion) -> MinecraftClient.getInstance().execute(() -> ENTITY_DIMENSIONS.forEach((entityType, dimensionMap) -> { + for (Map.Entry entry : dimensionMap.entrySet()) { + final VersionEnum version = entry.getKey(); + final EntityDimensions dimensions = entry.getValue(); + if (oldVersion.isNewerThan(version) && newVersion.isOlderThanOrEqualTo(version)) { + entityType.dimensions = dimensions; + break; + } + if (newVersion.isNewerThanOrEqualTo(version) && oldVersion.isOlderThanOrEqualTo(version)) { + entityType.dimensions = dimensions; + } + } + }))); + } + + private static Map linkedHashMap(final Object... objects) { + if (objects.length % 2 != 0) throw new IllegalArgumentException("Uneven object count"); + + final Map map = new LinkedHashMap<>(); + for (int i = 0; i < objects.length; i += 2) map.put((K) objects[i], (V) objects[i + 1]); + return map; + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/fixes/PendingUpdateManager1_18_2.java b/src/main/java/de/florianmichael/viafabricplus/fixes/PendingUpdateManager1_18_2.java new file mode 100644 index 000000000..585e571ef --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/fixes/PendingUpdateManager1_18_2.java @@ -0,0 +1,62 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.fixes; + +import net.minecraft.block.BlockState; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.network.PendingUpdateManager; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.util.math.BlockPos; + +public class PendingUpdateManager1_18_2 extends PendingUpdateManager { + + @Override + public void addPendingUpdate(BlockPos pos, BlockState state, ClientPlayerEntity player) { + } + + @Override + public boolean hasPendingUpdate(BlockPos pos, BlockState state) { + return false; + } + + @Override + public void processPendingUpdates(int maxProcessableSequence, ClientWorld world) { + } + + @Override + public PendingUpdateManager incrementSequence() { + return this; + } + + @Override + public void close() { + } + + @Override + public int getSequence() { + return 0; + } + + @Override + public boolean hasPendingSequence() { + return false; + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/fixes/TripleChestHandler1_13_2.java b/src/main/java/de/florianmichael/viafabricplus/fixes/TripleChestHandler1_13_2.java deleted file mode 100644 index 70fa681ea..000000000 --- a/src/main/java/de/florianmichael/viafabricplus/fixes/TripleChestHandler1_13_2.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus - * Copyright (C) 2021-2023 FlorianMichael/EnZaXD - * Copyright (C) 2023 RK_01/RaphiMC 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 . - */ - -package de.florianmichael.viafabricplus.fixes; - -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.resource.featuretoggle.FeatureSet; -import net.minecraft.screen.GenericContainerScreenHandler; -import net.minecraft.screen.ScreenHandlerType; -import net.minecraft.text.Text; - -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; - -public class TripleChestHandler1_13_2 { - public static final Consumer TRIPLE_CHEST_HANDLER = data -> { - final var byteBuf = data.asByteBuf(); - - try { - TripleChestHandler1_13_2.handleTripleChestHandler(Type.SHORT.readPrimitive(byteBuf), Type.COMPONENT.read(byteBuf), Type.SHORT.readPrimitive(byteBuf)); - } catch (Exception e) { - ViaFabricPlus.global().getLogger().error("Failed to open custom ScreenHandler with dimension 9xN", e); - } - }; - - public static void handleTripleChestHandler(final short windowID, final JsonElement title, final short slots) { - int n = slots / 9; - final int modulo = slots % 9; - if (modulo > 0) n++; - - final var screenHandler = new AtomicReference>(); - int finalN = n; - screenHandler.set(new TripleChestScreenHandlerType((syncId, playerInventory) -> new GenericContainerScreenHandler(screenHandler.get(), syncId, playerInventory, finalN), FeatureFlags.VANILLA_FEATURES)); - - HandledScreens.open(screenHandler.get(), MinecraftClient.getInstance(), windowID, Text.Serializer.fromJson(title.toString())); - } - - public static class TripleChestScreenHandlerType extends ScreenHandlerType { - - public TripleChestScreenHandlerType(Factory factory, FeatureSet requiredFeatures) { - super(factory, requiredFeatures); - } - } -} diff --git a/src/main/java/de/florianmichael/viafabricplus/fixes/classic/screen/ClassicItemSelectionScreen.java b/src/main/java/de/florianmichael/viafabricplus/fixes/classic/screen/ClassicItemSelectionScreen.java index c564dbdfe..1fb929b12 100644 --- a/src/main/java/de/florianmichael/viafabricplus/fixes/classic/screen/ClassicItemSelectionScreen.java +++ b/src/main/java/de/florianmichael/viafabricplus/fixes/classic/screen/ClassicItemSelectionScreen.java @@ -33,7 +33,7 @@ @SuppressWarnings("DataFlowIssue") public class ClassicItemSelectionScreen extends VFPScreen { - public static ClassicItemSelectionScreen INSTANCE = new ClassicItemSelectionScreen(); + public static final ClassicItemSelectionScreen INSTANCE = new ClassicItemSelectionScreen(); private static final int MAX_ROW_DIVIDER = 9; private static final int ITEM_XY_BOX_DIMENSION_CLASSIC = 25; diff --git a/src/main/java/de/florianmichael/viafabricplus/fixes/diff/ItemRegistryDiff.java b/src/main/java/de/florianmichael/viafabricplus/fixes/diff/ItemRegistryDiff.java new file mode 100644 index 000000000..45e8bff9a --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/fixes/diff/ItemRegistryDiff.java @@ -0,0 +1,1373 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.fixes.diff; + +import de.florianmichael.viafabricplus.injection.access.IClientConnection; +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.item.Item; +import net.raphimc.vialegacy.protocols.classic.protocolc0_28_30toc0_28_30cpe.data.ClassicProtocolExtension; +import net.raphimc.vialegacy.protocols.classic.protocolc0_28_30toc0_28_30cpe.storage.ExtensionProtocolMetadataStorage; +import net.raphimc.vialoader.util.VersionRange; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static net.minecraft.item.Items.*; +import static net.raphimc.vialoader.util.VersionEnum.*; +import static net.raphimc.vialoader.util.VersionRange.*; + +public class ItemRegistryDiff { + + private static final Map ITEM_DIFF = new HashMap<>(); + private static final List EXTENDED_CLASSIC_ITEMS = new ArrayList<>(); + + static { + ITEM_DIFF.put(CHERRY_LOG, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CHERRY_WOOD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(STRIPPED_CHERRY_LOG, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(STRIPPED_CHERRY_WOOD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CHERRY_PLANKS, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CHERRY_STAIRS, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CHERRY_SLAB, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CHERRY_FENCE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CHERRY_FENCE_GATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CHERRY_DOOR, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CHERRY_TRAPDOOR, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CHERRY_PRESSURE_PLATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CHERRY_BUTTON, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BAMBOO_BLOCK, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(STRIPPED_BAMBOO_BLOCK, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BAMBOO_PLANKS, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BAMBOO_STAIRS, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BAMBOO_SLAB, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BAMBOO_FENCE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BAMBOO_FENCE_GATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BAMBOO_DOOR, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BAMBOO_TRAPDOOR, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BAMBOO_PRESSURE_PLATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BAMBOO_BUTTON, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BAMBOO_MOSAIC, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BAMBOO_MOSAIC_STAIRS, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BAMBOO_MOSAIC_SLAB, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CHERRY_BOAT, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CHERRY_CHEST_BOAT, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BAMBOO_RAFT, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BAMBOO_CHEST_RAFT, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(MUSIC_DISC_RELIC, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(SNIFFER_SPAWN_EGG, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CAMEL_SPAWN_EGG, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CALIBRATED_SCULK_SENSOR, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CHISELED_BOOKSHELF, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(DECORATED_POT, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(SUSPICIOUS_SAND, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(SUSPICIOUS_GRAVEL, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(PIGLIN_HEAD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(OAK_HANGING_SIGN, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(SPRUCE_HANGING_SIGN, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BIRCH_HANGING_SIGN, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(JUNGLE_HANGING_SIGN, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(ACACIA_HANGING_SIGN, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CHERRY_HANGING_SIGN, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(DARK_OAK_HANGING_SIGN, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(MANGROVE_HANGING_SIGN, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BAMBOO_HANGING_SIGN, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CRIMSON_HANGING_SIGN, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(WARPED_HANGING_SIGN, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CHERRY_LEAVES, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CHERRY_SAPLING, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(CHERRY_SIGN, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BAMBOO_SIGN, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(TORCHFLOWER, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(TORCHFLOWER_SEEDS, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(PINK_PETALS, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(PITCHER_PLANT, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(PITCHER_POD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(SNIFFER_EGG, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BRUSH, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(ANGLER_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(ARCHER_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(ARMS_UP_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BLADE_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BREWER_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(BURN_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(DANGER_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(EXPLORER_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(FRIEND_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(HEART_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(HEARTBREAK_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(HOWL_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(MINER_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(MOURNER_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(PLENTY_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(PRIZE_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(SHEAF_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(SHELTER_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(SKULL_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(SNORT_POTTERY_SHERD, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(NETHERITE_UPGRADE_SMITHING_TEMPLATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(DUNE_ARMOR_TRIM_SMITHING_TEMPLATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(COAST_ARMOR_TRIM_SMITHING_TEMPLATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(WILD_ARMOR_TRIM_SMITHING_TEMPLATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(WARD_ARMOR_TRIM_SMITHING_TEMPLATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(EYE_ARMOR_TRIM_SMITHING_TEMPLATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(VEX_ARMOR_TRIM_SMITHING_TEMPLATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(TIDE_ARMOR_TRIM_SMITHING_TEMPLATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(RIB_ARMOR_TRIM_SMITHING_TEMPLATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(RAISER_ARMOR_TRIM_SMITHING_TEMPLATE, andNewer(r1_20tor1_20_1)); + ITEM_DIFF.put(HOST_ARMOR_TRIM_SMITHING_TEMPLATE, andNewer(r1_20tor1_20_1)); + + ITEM_DIFF.put(IRON_GOLEM_SPAWN_EGG, andNewer(r1_19_3)); + ITEM_DIFF.put(SNOW_GOLEM_SPAWN_EGG, andNewer(r1_19_3)); + ITEM_DIFF.put(WITHER_SPAWN_EGG, andNewer(r1_19_3)); + ITEM_DIFF.put(ENDER_DRAGON_SPAWN_EGG, andNewer(r1_19_3)); + ITEM_DIFF.put(SPAWNER, andNewer(r1_19_3)); + + ITEM_DIFF.put(OCHRE_FROGLIGHT, andNewer(r1_19)); + ITEM_DIFF.put(PEARLESCENT_FROGLIGHT, andNewer(r1_19)); + ITEM_DIFF.put(VERDANT_FROGLIGHT, andNewer(r1_19)); + ITEM_DIFF.put(FROGSPAWN, andNewer(r1_19)); + ITEM_DIFF.put(MANGROVE_LEAVES, andNewer(r1_19)); + ITEM_DIFF.put(MANGROVE_LOG, andNewer(r1_19)); + ITEM_DIFF.put(STRIPPED_MANGROVE_LOG, andNewer(r1_19)); + ITEM_DIFF.put(MANGROVE_PLANKS, andNewer(r1_19)); + ITEM_DIFF.put(MANGROVE_PROPAGULE, andNewer(r1_19)); + ITEM_DIFF.put(MANGROVE_ROOTS, andNewer(r1_19)); + ITEM_DIFF.put(MUDDY_MANGROVE_ROOTS, andNewer(r1_19)); + ITEM_DIFF.put(MANGROVE_WOOD, andNewer(r1_19)); + ITEM_DIFF.put(STRIPPED_MANGROVE_WOOD, andNewer(r1_19)); + ITEM_DIFF.put(MANGROVE_BOAT, andNewer(r1_19)); + ITEM_DIFF.put(MANGROVE_CHEST_BOAT, andNewer(r1_19)); + ITEM_DIFF.put(MANGROVE_PRESSURE_PLATE, andNewer(r1_19)); + ITEM_DIFF.put(MANGROVE_TRAPDOOR, andNewer(r1_19)); + ITEM_DIFF.put(MANGROVE_FENCE_GATE, andNewer(r1_19)); + ITEM_DIFF.put(MANGROVE_DOOR, andNewer(r1_19)); + ITEM_DIFF.put(MANGROVE_FENCE, andNewer(r1_19)); + ITEM_DIFF.put(MANGROVE_SIGN, andNewer(r1_19)); + ITEM_DIFF.put(MANGROVE_SLAB, andNewer(r1_19)); + ITEM_DIFF.put(MANGROVE_STAIRS, andNewer(r1_19)); + ITEM_DIFF.put(MANGROVE_BUTTON, andNewer(r1_19)); + ITEM_DIFF.put(MUD, andNewer(r1_19)); + ITEM_DIFF.put(MUD_BRICKS, andNewer(r1_19)); + ITEM_DIFF.put(MUD_BRICK_WALL, andNewer(r1_19)); + ITEM_DIFF.put(MUD_BRICK_SLAB, andNewer(r1_19)); + ITEM_DIFF.put(MUD_BRICK_STAIRS, andNewer(r1_19)); + ITEM_DIFF.put(PACKED_MUD, andNewer(r1_19)); + ITEM_DIFF.put(REINFORCED_DEEPSLATE, andNewer(r1_19)); + ITEM_DIFF.put(SCULK, andNewer(r1_19)); + ITEM_DIFF.put(SCULK_CATALYST, andNewer(r1_19)); + ITEM_DIFF.put(SCULK_SHRIEKER, andNewer(r1_19)); + ITEM_DIFF.put(SCULK_VEIN, andNewer(r1_19)); + ITEM_DIFF.put(TADPOLE_BUCKET, andNewer(r1_19)); + ITEM_DIFF.put(DISC_FRAGMENT_5, andNewer(r1_19)); + ITEM_DIFF.put(ECHO_SHARD, andNewer(r1_19)); + ITEM_DIFF.put(GOAT_HORN, andNewer(r1_19)); + ITEM_DIFF.put(MUSIC_DISC_5, andNewer(r1_19)); + ITEM_DIFF.put(RECOVERY_COMPASS, andNewer(r1_19)); + ITEM_DIFF.put(OAK_CHEST_BOAT, andNewer(r1_19)); + ITEM_DIFF.put(SPRUCE_CHEST_BOAT, andNewer(r1_19)); + ITEM_DIFF.put(BIRCH_CHEST_BOAT, andNewer(r1_19)); + ITEM_DIFF.put(JUNGLE_CHEST_BOAT, andNewer(r1_19)); + ITEM_DIFF.put(ACACIA_CHEST_BOAT, andNewer(r1_19)); + ITEM_DIFF.put(DARK_OAK_CHEST_BOAT, andNewer(r1_19)); + ITEM_DIFF.put(ALLAY_SPAWN_EGG, andNewer(r1_19)); + ITEM_DIFF.put(FROG_SPAWN_EGG, andNewer(r1_19)); + ITEM_DIFF.put(TADPOLE_SPAWN_EGG, andNewer(r1_19)); + ITEM_DIFF.put(WARDEN_SPAWN_EGG, andNewer(r1_19)); + + ITEM_DIFF.put(MUSIC_DISC_OTHERSIDE, andNewer(r1_18tor1_18_1)); + + ITEM_DIFF.put(CANDLE, andNewer(r1_17)); + ITEM_DIFF.put(WHITE_CANDLE, andNewer(r1_17)); + ITEM_DIFF.put(ORANGE_CANDLE, andNewer(r1_17)); + ITEM_DIFF.put(MAGENTA_CANDLE, andNewer(r1_17)); + ITEM_DIFF.put(LIGHT_BLUE_CANDLE, andNewer(r1_17)); + ITEM_DIFF.put(YELLOW_CANDLE, andNewer(r1_17)); + ITEM_DIFF.put(LIME_CANDLE, andNewer(r1_17)); + ITEM_DIFF.put(PINK_CANDLE, andNewer(r1_17)); + ITEM_DIFF.put(GRAY_CANDLE, andNewer(r1_17)); + ITEM_DIFF.put(LIGHT_GRAY_CANDLE, andNewer(r1_17)); + ITEM_DIFF.put(CYAN_CANDLE, andNewer(r1_17)); + ITEM_DIFF.put(PURPLE_CANDLE, andNewer(r1_17)); + ITEM_DIFF.put(BLUE_CANDLE, andNewer(r1_17)); + ITEM_DIFF.put(BROWN_CANDLE, andNewer(r1_17)); + ITEM_DIFF.put(GREEN_CANDLE, andNewer(r1_17)); + ITEM_DIFF.put(RED_CANDLE, andNewer(r1_17)); + ITEM_DIFF.put(BLACK_CANDLE, andNewer(r1_17)); + ITEM_DIFF.put(AMETHYST_BLOCK, andNewer(r1_17)); + ITEM_DIFF.put(BUDDING_AMETHYST, andNewer(r1_17)); + ITEM_DIFF.put(AMETHYST_CLUSTER, andNewer(r1_17)); + ITEM_DIFF.put(LARGE_AMETHYST_BUD, andNewer(r1_17)); + ITEM_DIFF.put(MEDIUM_AMETHYST_BUD, andNewer(r1_17)); + ITEM_DIFF.put(SMALL_AMETHYST_BUD, andNewer(r1_17)); + ITEM_DIFF.put(TUFF, andNewer(r1_17)); + ITEM_DIFF.put(CALCITE, andNewer(r1_17)); + ITEM_DIFF.put(TINTED_GLASS, andNewer(r1_17)); + ITEM_DIFF.put(SCULK_SENSOR, andNewer(r1_17)); + ITEM_DIFF.put(WEATHERED_COPPER, andNewer(r1_17)); + ITEM_DIFF.put(OXIDIZED_COPPER, andNewer(r1_17)); + ITEM_DIFF.put(EXPOSED_COPPER, andNewer(r1_17)); + ITEM_DIFF.put(COPPER_BLOCK, andNewer(r1_17)); + ITEM_DIFF.put(COPPER_ORE, andNewer(r1_17)); + ITEM_DIFF.put(WEATHERED_CUT_COPPER, andNewer(r1_17)); + ITEM_DIFF.put(OXIDIZED_CUT_COPPER, andNewer(r1_17)); + ITEM_DIFF.put(EXPOSED_CUT_COPPER, andNewer(r1_17)); + ITEM_DIFF.put(CUT_COPPER, andNewer(r1_17)); + ITEM_DIFF.put(WEATHERED_CUT_COPPER_STAIRS, andNewer(r1_17)); + ITEM_DIFF.put(OXIDIZED_CUT_COPPER_STAIRS, andNewer(r1_17)); + ITEM_DIFF.put(EXPOSED_CUT_COPPER_STAIRS, andNewer(r1_17)); + ITEM_DIFF.put(CUT_COPPER_STAIRS, andNewer(r1_17)); + ITEM_DIFF.put(WEATHERED_CUT_COPPER_SLAB, andNewer(r1_17)); + ITEM_DIFF.put(OXIDIZED_CUT_COPPER_SLAB, andNewer(r1_17)); + ITEM_DIFF.put(EXPOSED_CUT_COPPER_SLAB, andNewer(r1_17)); + ITEM_DIFF.put(CUT_COPPER_SLAB, andNewer(r1_17)); + ITEM_DIFF.put(WAXED_COPPER_BLOCK, andNewer(r1_17)); + ITEM_DIFF.put(WAXED_WEATHERED_COPPER, andNewer(r1_17)); + ITEM_DIFF.put(WAXED_EXPOSED_COPPER, andNewer(r1_17)); + ITEM_DIFF.put(WAXED_CUT_COPPER, andNewer(r1_17)); + ITEM_DIFF.put(WAXED_WEATHERED_CUT_COPPER, andNewer(r1_17)); + ITEM_DIFF.put(WAXED_EXPOSED_CUT_COPPER, andNewer(r1_17)); + ITEM_DIFF.put(WAXED_CUT_COPPER_STAIRS, andNewer(r1_17)); + ITEM_DIFF.put(WAXED_WEATHERED_CUT_COPPER_STAIRS, andNewer(r1_17)); + ITEM_DIFF.put(WAXED_EXPOSED_CUT_COPPER_STAIRS, andNewer(r1_17)); + ITEM_DIFF.put(WAXED_CUT_COPPER_SLAB, andNewer(r1_17)); + ITEM_DIFF.put(WAXED_WEATHERED_CUT_COPPER_SLAB, andNewer(r1_17)); + ITEM_DIFF.put(WAXED_EXPOSED_CUT_COPPER_SLAB, andNewer(r1_17)); + ITEM_DIFF.put(LIGHTNING_ROD, andNewer(r1_17)); + ITEM_DIFF.put(POINTED_DRIPSTONE, andNewer(r1_17)); + ITEM_DIFF.put(DRIPSTONE_BLOCK, andNewer(r1_17)); + ITEM_DIFF.put(GLOW_LICHEN, andNewer(r1_17)); + ITEM_DIFF.put(AZALEA_LEAVES, andNewer(r1_17)); + ITEM_DIFF.put(SPORE_BLOSSOM, andNewer(r1_17)); + ITEM_DIFF.put(AZALEA, andNewer(r1_17)); + ITEM_DIFF.put(FLOWERING_AZALEA, andNewer(r1_17)); + ITEM_DIFF.put(FLOWERING_AZALEA_LEAVES, andNewer(r1_17)); + ITEM_DIFF.put(MOSS_CARPET, andNewer(r1_17)); + ITEM_DIFF.put(MOSS_BLOCK, andNewer(r1_17)); + ITEM_DIFF.put(BIG_DRIPLEAF, andNewer(r1_17)); + ITEM_DIFF.put(SMALL_DRIPLEAF, andNewer(r1_17)); + ITEM_DIFF.put(ROOTED_DIRT, andNewer(r1_17)); + ITEM_DIFF.put(HANGING_ROOTS, andNewer(r1_17)); + ITEM_DIFF.put(DEEPSLATE_GOLD_ORE, andNewer(r1_17)); + ITEM_DIFF.put(DEEPSLATE_IRON_ORE, andNewer(r1_17)); + ITEM_DIFF.put(DEEPSLATE_LAPIS_ORE, andNewer(r1_17)); + ITEM_DIFF.put(DEEPSLATE_DIAMOND_ORE, andNewer(r1_17)); + ITEM_DIFF.put(DEEPSLATE_REDSTONE_ORE, andNewer(r1_17)); + ITEM_DIFF.put(CHISELED_DEEPSLATE, andNewer(r1_17)); + ITEM_DIFF.put(DEEPSLATE, andNewer(r1_17)); + ITEM_DIFF.put(COBBLED_DEEPSLATE, andNewer(r1_17)); + ITEM_DIFF.put(COBBLED_DEEPSLATE_STAIRS, andNewer(r1_17)); + ITEM_DIFF.put(COBBLED_DEEPSLATE_SLAB, andNewer(r1_17)); + ITEM_DIFF.put(COBBLED_DEEPSLATE_WALL, andNewer(r1_17)); + ITEM_DIFF.put(DEEPSLATE_BRICK_SLAB, andNewer(r1_17)); + ITEM_DIFF.put(DEEPSLATE_BRICK_STAIRS, andNewer(r1_17)); + ITEM_DIFF.put(DEEPSLATE_BRICK_WALL, andNewer(r1_17)); + ITEM_DIFF.put(DEEPSLATE_BRICKS, andNewer(r1_17)); + ITEM_DIFF.put(DEEPSLATE_TILE_SLAB, andNewer(r1_17)); + ITEM_DIFF.put(DEEPSLATE_TILE_STAIRS, andNewer(r1_17)); + ITEM_DIFF.put(DEEPSLATE_TILE_WALL, andNewer(r1_17)); + ITEM_DIFF.put(DEEPSLATE_TILES, andNewer(r1_17)); + ITEM_DIFF.put(POLISHED_DEEPSLATE, andNewer(r1_17)); + ITEM_DIFF.put(POLISHED_DEEPSLATE_SLAB, andNewer(r1_17)); + ITEM_DIFF.put(POLISHED_DEEPSLATE_STAIRS, andNewer(r1_17)); + ITEM_DIFF.put(POLISHED_DEEPSLATE_WALL, andNewer(r1_17)); + ITEM_DIFF.put(SMOOTH_BASALT, andNewer(r1_17)); + ITEM_DIFF.put(CRACKED_DEEPSLATE_BRICKS, andNewer(r1_17)); + ITEM_DIFF.put(CRACKED_DEEPSLATE_TILES, andNewer(r1_17)); + ITEM_DIFF.put(DEEPSLATE_COAL_ORE, andNewer(r1_17)); + ITEM_DIFF.put(DEEPSLATE_COPPER_ORE, andNewer(r1_17)); + ITEM_DIFF.put(DEEPSLATE_EMERALD_ORE, andNewer(r1_17)); + ITEM_DIFF.put(INFESTED_DEEPSLATE, andNewer(r1_17)); + ITEM_DIFF.put(LIGHT, andNewer(r1_17)); + ITEM_DIFF.put(WAXED_OXIDIZED_COPPER, andNewer(r1_17)); + ITEM_DIFF.put(WAXED_OXIDIZED_CUT_COPPER, andNewer(r1_17)); + ITEM_DIFF.put(WAXED_OXIDIZED_CUT_COPPER_SLAB, andNewer(r1_17)); + ITEM_DIFF.put(WAXED_OXIDIZED_CUT_COPPER_STAIRS, andNewer(r1_17)); + ITEM_DIFF.put(RAW_COPPER_BLOCK, andNewer(r1_17)); + ITEM_DIFF.put(RAW_GOLD_BLOCK, andNewer(r1_17)); + ITEM_DIFF.put(RAW_IRON_BLOCK, andNewer(r1_17)); + ITEM_DIFF.put(COPPER_INGOT, andNewer(r1_17)); + ITEM_DIFF.put(BUNDLE, andNewer(r1_17)); + ITEM_DIFF.put(AMETHYST_SHARD, andNewer(r1_17)); + ITEM_DIFF.put(SPYGLASS, andNewer(r1_17)); + ITEM_DIFF.put(POWDER_SNOW_BUCKET, andNewer(r1_17)); + ITEM_DIFF.put(AXOLOTL_BUCKET, andNewer(r1_17)); + ITEM_DIFF.put(GLOW_ITEM_FRAME, andNewer(r1_17)); + ITEM_DIFF.put(GLOW_INK_SAC, andNewer(r1_17)); + ITEM_DIFF.put(GLOW_BERRIES, andNewer(r1_17)); + ITEM_DIFF.put(RAW_IRON, andNewer(r1_17)); + ITEM_DIFF.put(RAW_GOLD, andNewer(r1_17)); + ITEM_DIFF.put(RAW_COPPER, andNewer(r1_17)); + ITEM_DIFF.put(AXOLOTL_SPAWN_EGG, andNewer(r1_17)); + ITEM_DIFF.put(GLOW_SQUID_SPAWN_EGG, andNewer(r1_17)); + ITEM_DIFF.put(GOAT_SPAWN_EGG, andNewer(r1_17)); + + ITEM_DIFF.put(ANCIENT_DEBRIS, andNewer(r1_16)); + ITEM_DIFF.put(BASALT, andNewer(r1_16)); + ITEM_DIFF.put(CRIMSON_BUTTON, andNewer(r1_16)); + ITEM_DIFF.put(WARPED_BUTTON, andNewer(r1_16)); + ITEM_DIFF.put(CRIMSON_DOOR, andNewer(r1_16)); + ITEM_DIFF.put(WARPED_DOOR, andNewer(r1_16)); + ITEM_DIFF.put(CRIMSON_FENCE, andNewer(r1_16)); + ITEM_DIFF.put(WARPED_FENCE, andNewer(r1_16)); + ITEM_DIFF.put(CRIMSON_FENCE_GATE, andNewer(r1_16)); + ITEM_DIFF.put(WARPED_FENCE_GATE, andNewer(r1_16)); + ITEM_DIFF.put(CRIMSON_FUNGUS, andNewer(r1_16)); + ITEM_DIFF.put(WARPED_FUNGUS, andNewer(r1_16)); + ITEM_DIFF.put(NETHER_SPROUTS, andNewer(r1_16)); + ITEM_DIFF.put(CRIMSON_NYLIUM, andNewer(r1_16)); + ITEM_DIFF.put(WARPED_NYLIUM, andNewer(r1_16)); + ITEM_DIFF.put(CRIMSON_PLANKS, andNewer(r1_16)); + ITEM_DIFF.put(WARPED_PLANKS, andNewer(r1_16)); + ITEM_DIFF.put(CRIMSON_PRESSURE_PLATE, andNewer(r1_16)); + ITEM_DIFF.put(WARPED_PRESSURE_PLATE, andNewer(r1_16)); + ITEM_DIFF.put(CRIMSON_ROOTS, andNewer(r1_16)); + ITEM_DIFF.put(WARPED_ROOTS, andNewer(r1_16)); + ITEM_DIFF.put(CRIMSON_SIGN, andNewer(r1_16)); + ITEM_DIFF.put(WARPED_SIGN, andNewer(r1_16)); + ITEM_DIFF.put(CRIMSON_SLAB, andNewer(r1_16)); + ITEM_DIFF.put(WARPED_SLAB, andNewer(r1_16)); + ITEM_DIFF.put(CRIMSON_STAIRS, andNewer(r1_16)); + ITEM_DIFF.put(WARPED_STAIRS, andNewer(r1_16)); + ITEM_DIFF.put(CRIMSON_STEM, andNewer(r1_16)); + ITEM_DIFF.put(WARPED_STEM, andNewer(r1_16)); + ITEM_DIFF.put(STRIPPED_CRIMSON_STEM, andNewer(r1_16)); + ITEM_DIFF.put(STRIPPED_WARPED_STEM, andNewer(r1_16)); + ITEM_DIFF.put(CRIMSON_TRAPDOOR, andNewer(r1_16)); + ITEM_DIFF.put(WARPED_TRAPDOOR, andNewer(r1_16)); + ITEM_DIFF.put(NETHERITE_BLOCK, andNewer(r1_16)); + ITEM_DIFF.put(SHROOMLIGHT, andNewer(r1_16)); + ITEM_DIFF.put(SOUL_LANTERN, andNewer(r1_16)); + ITEM_DIFF.put(SOUL_TORCH, andNewer(r1_16)); + ITEM_DIFF.put(SOUL_SOIL, andNewer(r1_16)); + ITEM_DIFF.put(WARPED_WART_BLOCK, andNewer(r1_16)); + ITEM_DIFF.put(WEEPING_VINES, andNewer(r1_16)); + ITEM_DIFF.put(TARGET, andNewer(r1_16)); + ITEM_DIFF.put(CRYING_OBSIDIAN, andNewer(r1_16)); + ITEM_DIFF.put(WARPED_HYPHAE, andNewer(r1_16)); + ITEM_DIFF.put(STRIPPED_WARPED_HYPHAE, andNewer(r1_16)); + ITEM_DIFF.put(CRIMSON_HYPHAE, andNewer(r1_16)); + ITEM_DIFF.put(STRIPPED_CRIMSON_HYPHAE, andNewer(r1_16)); + ITEM_DIFF.put(NETHER_GOLD_ORE, andNewer(r1_16)); + ITEM_DIFF.put(TWISTING_VINES, andNewer(r1_16)); + ITEM_DIFF.put(POLISHED_BASALT, andNewer(r1_16)); + ITEM_DIFF.put(RESPAWN_ANCHOR, andNewer(r1_16)); + ITEM_DIFF.put(LODESTONE, andNewer(r1_16)); + ITEM_DIFF.put(CHAIN, andNewer(r1_16)); + ITEM_DIFF.put(SOUL_CAMPFIRE, andNewer(r1_16)); + ITEM_DIFF.put(BLACKSTONE, andNewer(r1_16)); + ITEM_DIFF.put(BLACKSTONE_STAIRS, andNewer(r1_16)); + ITEM_DIFF.put(BLACKSTONE_WALL, andNewer(r1_16)); + ITEM_DIFF.put(BLACKSTONE_SLAB, andNewer(r1_16)); + ITEM_DIFF.put(POLISHED_BLACKSTONE, andNewer(r1_16)); + ITEM_DIFF.put(POLISHED_BLACKSTONE_BRICKS, andNewer(r1_16)); + ITEM_DIFF.put(CRACKED_POLISHED_BLACKSTONE_BRICKS, andNewer(r1_16)); + ITEM_DIFF.put(CHISELED_POLISHED_BLACKSTONE, andNewer(r1_16)); + ITEM_DIFF.put(POLISHED_BLACKSTONE_BRICK_SLAB, andNewer(r1_16)); + ITEM_DIFF.put(POLISHED_BLACKSTONE_BRICK_STAIRS, andNewer(r1_16)); + ITEM_DIFF.put(POLISHED_BLACKSTONE_BRICK_WALL, andNewer(r1_16)); + ITEM_DIFF.put(GILDED_BLACKSTONE, andNewer(r1_16)); + ITEM_DIFF.put(POLISHED_BLACKSTONE_STAIRS, andNewer(r1_16)); + ITEM_DIFF.put(POLISHED_BLACKSTONE_SLAB, andNewer(r1_16)); + ITEM_DIFF.put(POLISHED_BLACKSTONE_PRESSURE_PLATE, andNewer(r1_16)); + ITEM_DIFF.put(POLISHED_BLACKSTONE_BUTTON, andNewer(r1_16)); + ITEM_DIFF.put(POLISHED_BLACKSTONE_WALL, andNewer(r1_16)); + ITEM_DIFF.put(CHISELED_NETHER_BRICKS, andNewer(r1_16)); + ITEM_DIFF.put(CRACKED_NETHER_BRICKS, andNewer(r1_16)); + ITEM_DIFF.put(QUARTZ_BRICKS, andNewer(r1_16)); + ITEM_DIFF.put(NETHERITE_SCRAP, andNewer(r1_16)); + ITEM_DIFF.put(NETHERITE_INGOT, andNewer(r1_16)); + ITEM_DIFF.put(NETHERITE_HELMET, andNewer(r1_16)); + ITEM_DIFF.put(NETHERITE_CHESTPLATE, andNewer(r1_16)); + ITEM_DIFF.put(NETHERITE_LEGGINGS, andNewer(r1_16)); + ITEM_DIFF.put(NETHERITE_BOOTS, andNewer(r1_16)); + ITEM_DIFF.put(NETHERITE_SWORD, andNewer(r1_16)); + ITEM_DIFF.put(NETHERITE_SHOVEL, andNewer(r1_16)); + ITEM_DIFF.put(NETHERITE_AXE, andNewer(r1_16)); + ITEM_DIFF.put(NETHERITE_PICKAXE, andNewer(r1_16)); + ITEM_DIFF.put(NETHERITE_HOE, andNewer(r1_16)); + ITEM_DIFF.put(WARPED_FUNGUS_ON_A_STICK, andNewer(r1_16)); + ITEM_DIFF.put(MUSIC_DISC_PIGSTEP, andNewer(r1_16)); + ITEM_DIFF.put(PIGLIN_BANNER_PATTERN, andNewer(r1_16)); + ITEM_DIFF.put(HOGLIN_SPAWN_EGG, andNewer(r1_16)); + ITEM_DIFF.put(PIGLIN_SPAWN_EGG, andNewer(r1_16)); + ITEM_DIFF.put(PIGLIN_BRUTE_SPAWN_EGG, andNewer(r1_16)); + ITEM_DIFF.put(STRIDER_SPAWN_EGG, andNewer(r1_16)); + ITEM_DIFF.put(ZOGLIN_SPAWN_EGG, andNewer(r1_16)); + + ITEM_DIFF.put(BEE_NEST, andNewer(r1_15)); + ITEM_DIFF.put(BEEHIVE, andNewer(r1_15)); + ITEM_DIFF.put(HONEY_BLOCK, andNewer(r1_15)); + ITEM_DIFF.put(HONEYCOMB_BLOCK, andNewer(r1_15)); + ITEM_DIFF.put(HONEYCOMB, andNewer(r1_15)); + ITEM_DIFF.put(HONEY_BOTTLE, andNewer(r1_15)); + ITEM_DIFF.put(BEE_SPAWN_EGG, andNewer(r1_15)); + + ITEM_DIFF.put(CORNFLOWER, andNewer(r1_14)); + ITEM_DIFF.put(LILY_OF_THE_VALLEY, andNewer(r1_14)); + ITEM_DIFF.put(WITHER_ROSE, andNewer(r1_14)); + ITEM_DIFF.put(STONE_SLAB, andNewer(r1_14)); + ITEM_DIFF.put(CUT_SANDSTONE_SLAB, andNewer(r1_14)); + ITEM_DIFF.put(CUT_RED_SANDSTONE_SLAB, andNewer(r1_14)); + ITEM_DIFF.put(BRICK_WALL, andNewer(r1_14)); + ITEM_DIFF.put(PRISMARINE_WALL, andNewer(r1_14)); + ITEM_DIFF.put(RED_SANDSTONE_WALL, andNewer(r1_14)); + ITEM_DIFF.put(MOSSY_STONE_BRICK_WALL, andNewer(r1_14)); + ITEM_DIFF.put(GRANITE_WALL, andNewer(r1_14)); + ITEM_DIFF.put(STONE_BRICK_WALL, andNewer(r1_14)); + ITEM_DIFF.put(NETHER_BRICK_WALL, andNewer(r1_14)); + ITEM_DIFF.put(ANDESITE_WALL, andNewer(r1_14)); + ITEM_DIFF.put(RED_NETHER_BRICK_WALL, andNewer(r1_14)); + ITEM_DIFF.put(SANDSTONE_WALL, andNewer(r1_14)); + ITEM_DIFF.put(END_STONE_BRICK_WALL, andNewer(r1_14)); + ITEM_DIFF.put(DIORITE_WALL, andNewer(r1_14)); + ITEM_DIFF.put(POLISHED_GRANITE_STAIRS, andNewer(r1_14)); + ITEM_DIFF.put(SMOOTH_RED_SANDSTONE_STAIRS, andNewer(r1_14)); + ITEM_DIFF.put(MOSSY_STONE_BRICK_STAIRS, andNewer(r1_14)); + ITEM_DIFF.put(POLISHED_DIORITE_STAIRS, andNewer(r1_14)); + ITEM_DIFF.put(MOSSY_COBBLESTONE_STAIRS, andNewer(r1_14)); + ITEM_DIFF.put(END_STONE_BRICK_STAIRS, andNewer(r1_14)); + ITEM_DIFF.put(STONE_STAIRS, andNewer(r1_14)); + ITEM_DIFF.put(SMOOTH_SANDSTONE_STAIRS, andNewer(r1_14)); + ITEM_DIFF.put(SMOOTH_QUARTZ_STAIRS, andNewer(r1_14)); + ITEM_DIFF.put(GRANITE_STAIRS, andNewer(r1_14)); + ITEM_DIFF.put(ANDESITE_STAIRS, andNewer(r1_14)); + ITEM_DIFF.put(RED_NETHER_BRICK_STAIRS, andNewer(r1_14)); + ITEM_DIFF.put(POLISHED_ANDESITE_STAIRS, andNewer(r1_14)); + ITEM_DIFF.put(DIORITE_STAIRS, andNewer(r1_14)); + ITEM_DIFF.put(POLISHED_GRANITE_SLAB, andNewer(r1_14)); + ITEM_DIFF.put(SMOOTH_RED_SANDSTONE_SLAB, andNewer(r1_14)); + ITEM_DIFF.put(MOSSY_STONE_BRICK_SLAB, andNewer(r1_14)); + ITEM_DIFF.put(POLISHED_DIORITE_SLAB, andNewer(r1_14)); + ITEM_DIFF.put(MOSSY_COBBLESTONE_SLAB, andNewer(r1_14)); + ITEM_DIFF.put(END_STONE_BRICK_SLAB, andNewer(r1_14)); + ITEM_DIFF.put(SMOOTH_SANDSTONE_SLAB, andNewer(r1_14)); + ITEM_DIFF.put(SMOOTH_QUARTZ_SLAB, andNewer(r1_14)); + ITEM_DIFF.put(GRANITE_SLAB, andNewer(r1_14)); + ITEM_DIFF.put(ANDESITE_SLAB, andNewer(r1_14)); + ITEM_DIFF.put(RED_NETHER_BRICK_SLAB, andNewer(r1_14)); + ITEM_DIFF.put(POLISHED_ANDESITE_SLAB, andNewer(r1_14)); + ITEM_DIFF.put(DIORITE_SLAB, andNewer(r1_14)); + ITEM_DIFF.put(SCAFFOLDING, andNewer(r1_14)); + ITEM_DIFF.put(JIGSAW, andNewer(r1_14)); + ITEM_DIFF.put(COMPOSTER, andNewer(r1_14)); + ITEM_DIFF.put(SPRUCE_SIGN, andNewer(r1_14)); + ITEM_DIFF.put(BIRCH_SIGN, andNewer(r1_14)); + ITEM_DIFF.put(JUNGLE_SIGN, andNewer(r1_14)); + ITEM_DIFF.put(ACACIA_SIGN, andNewer(r1_14)); + ITEM_DIFF.put(DARK_OAK_SIGN, andNewer(r1_14)); + ITEM_DIFF.put(BAMBOO, andNewer(r1_14)); + ITEM_DIFF.put(BLUE_DYE, andNewer(r1_14)); + ITEM_DIFF.put(BROWN_DYE, andNewer(r1_14)); + ITEM_DIFF.put(BLACK_DYE, andNewer(r1_14)); + ITEM_DIFF.put(WHITE_DYE, andNewer(r1_14)); + ITEM_DIFF.put(CAT_SPAWN_EGG, andNewer(r1_14)); + ITEM_DIFF.put(FOX_SPAWN_EGG, andNewer(r1_14)); + ITEM_DIFF.put(PANDA_SPAWN_EGG, andNewer(r1_14)); + ITEM_DIFF.put(PILLAGER_SPAWN_EGG, andNewer(r1_14)); + ITEM_DIFF.put(RAVAGER_SPAWN_EGG, andNewer(r1_14)); + ITEM_DIFF.put(TRADER_LLAMA_SPAWN_EGG, andNewer(r1_14)); + ITEM_DIFF.put(WANDERING_TRADER_SPAWN_EGG, andNewer(r1_14)); + ITEM_DIFF.put(LEATHER_HORSE_ARMOR, andNewer(r1_14)); + ITEM_DIFF.put(CROSSBOW, andNewer(r1_14)); + ITEM_DIFF.put(SUSPICIOUS_STEW, andNewer(r1_14)); + ITEM_DIFF.put(LOOM, andNewer(r1_14)); + ITEM_DIFF.put(FLOWER_BANNER_PATTERN, andNewer(r1_14)); + ITEM_DIFF.put(CREEPER_BANNER_PATTERN, andNewer(r1_14)); + ITEM_DIFF.put(SKULL_BANNER_PATTERN, andNewer(r1_14)); + ITEM_DIFF.put(MOJANG_BANNER_PATTERN, andNewer(r1_14)); + ITEM_DIFF.put(GLOBE_BANNER_PATTERN, andNewer(r1_14)); + ITEM_DIFF.put(BARREL, andNewer(r1_14)); + ITEM_DIFF.put(SMOKER, andNewer(r1_14)); + ITEM_DIFF.put(BLAST_FURNACE, andNewer(r1_14)); + ITEM_DIFF.put(CARTOGRAPHY_TABLE, andNewer(r1_14)); + ITEM_DIFF.put(FLETCHING_TABLE, andNewer(r1_14)); + ITEM_DIFF.put(GRINDSTONE, andNewer(r1_14)); + ITEM_DIFF.put(LECTERN, andNewer(r1_14)); + ITEM_DIFF.put(SMITHING_TABLE, andNewer(r1_14)); + ITEM_DIFF.put(STONECUTTER, andNewer(r1_14)); + ITEM_DIFF.put(BELL, andNewer(r1_14)); + ITEM_DIFF.put(LANTERN, andNewer(r1_14)); + ITEM_DIFF.put(SWEET_BERRIES, andNewer(r1_14)); + ITEM_DIFF.put(CAMPFIRE, andNewer(r1_14)); + + ITEM_DIFF.put(DEAD_BRAIN_CORAL, andNewer(r1_13_1)); + ITEM_DIFF.put(DEAD_BUBBLE_CORAL, andNewer(r1_13_1)); + ITEM_DIFF.put(DEAD_FIRE_CORAL, andNewer(r1_13_1)); + ITEM_DIFF.put(DEAD_HORN_CORAL, andNewer(r1_13_1)); + ITEM_DIFF.put(DEAD_TUBE_CORAL, andNewer(r1_13_1)); + + ITEM_DIFF.put(STRIPPED_OAK_LOG, andNewer(r1_13)); + ITEM_DIFF.put(STRIPPED_SPRUCE_LOG, andNewer(r1_13)); + ITEM_DIFF.put(STRIPPED_BIRCH_LOG, andNewer(r1_13)); + ITEM_DIFF.put(STRIPPED_JUNGLE_LOG, andNewer(r1_13)); + ITEM_DIFF.put(STRIPPED_ACACIA_LOG, andNewer(r1_13)); + ITEM_DIFF.put(STRIPPED_DARK_OAK_LOG, andNewer(r1_13)); + ITEM_DIFF.put(STRIPPED_OAK_WOOD, andNewer(r1_13)); + ITEM_DIFF.put(STRIPPED_SPRUCE_WOOD, andNewer(r1_13)); + ITEM_DIFF.put(STRIPPED_BIRCH_WOOD, andNewer(r1_13)); + ITEM_DIFF.put(STRIPPED_JUNGLE_WOOD, andNewer(r1_13)); + ITEM_DIFF.put(STRIPPED_ACACIA_WOOD, andNewer(r1_13)); + ITEM_DIFF.put(STRIPPED_DARK_OAK_WOOD, andNewer(r1_13)); + ITEM_DIFF.put(OAK_WOOD, andNewer(r1_13)); + ITEM_DIFF.put(SPRUCE_WOOD, andNewer(r1_13)); + ITEM_DIFF.put(BIRCH_WOOD, andNewer(r1_13)); + ITEM_DIFF.put(JUNGLE_WOOD, andNewer(r1_13)); + ITEM_DIFF.put(ACACIA_WOOD, andNewer(r1_13)); + ITEM_DIFF.put(DARK_OAK_WOOD, andNewer(r1_13)); + ITEM_DIFF.put(SEAGRASS, andNewer(r1_13)); + ITEM_DIFF.put(SEA_PICKLE, andNewer(r1_13)); + ITEM_DIFF.put(PRISMARINE_SLAB, andNewer(r1_13)); + ITEM_DIFF.put(PRISMARINE_BRICK_SLAB, andNewer(r1_13)); + ITEM_DIFF.put(DARK_PRISMARINE_SLAB, andNewer(r1_13)); + ITEM_DIFF.put(SMOOTH_QUARTZ, andNewer(r1_13)); + ITEM_DIFF.put(SMOOTH_RED_SANDSTONE, andNewer(r1_13)); + ITEM_DIFF.put(SMOOTH_SANDSTONE, andNewer(r1_13)); + ITEM_DIFF.put(SMOOTH_STONE, andNewer(r1_13)); + ITEM_DIFF.put(SPRUCE_PRESSURE_PLATE, andNewer(r1_13)); + ITEM_DIFF.put(BIRCH_PRESSURE_PLATE, andNewer(r1_13)); + ITEM_DIFF.put(JUNGLE_PRESSURE_PLATE, andNewer(r1_13)); + ITEM_DIFF.put(ACACIA_PRESSURE_PLATE, andNewer(r1_13)); + ITEM_DIFF.put(DARK_OAK_PRESSURE_PLATE, andNewer(r1_13)); + ITEM_DIFF.put(PUMPKIN, andNewer(r1_13)); + ITEM_DIFF.put(SPRUCE_TRAPDOOR, andNewer(r1_13)); + ITEM_DIFF.put(BIRCH_TRAPDOOR, andNewer(r1_13)); + ITEM_DIFF.put(JUNGLE_TRAPDOOR, andNewer(r1_13)); + ITEM_DIFF.put(ACACIA_TRAPDOOR, andNewer(r1_13)); + ITEM_DIFF.put(DARK_OAK_TRAPDOOR, andNewer(r1_13)); + ITEM_DIFF.put(SPRUCE_BUTTON, andNewer(r1_13)); + ITEM_DIFF.put(BIRCH_BUTTON, andNewer(r1_13)); + ITEM_DIFF.put(JUNGLE_BUTTON, andNewer(r1_13)); + ITEM_DIFF.put(ACACIA_BUTTON, andNewer(r1_13)); + ITEM_DIFF.put(DARK_OAK_BUTTON, andNewer(r1_13)); + ITEM_DIFF.put(PRISMARINE_STAIRS, andNewer(r1_13)); + ITEM_DIFF.put(PRISMARINE_BRICK_STAIRS, andNewer(r1_13)); + ITEM_DIFF.put(DARK_PRISMARINE_STAIRS, andNewer(r1_13)); + ITEM_DIFF.put(SHULKER_BOX, andNewer(r1_13)); + ITEM_DIFF.put(TURTLE_EGG, andNewer(r1_13)); + ITEM_DIFF.put(DEAD_TUBE_CORAL_BLOCK, andNewer(r1_13)); + ITEM_DIFF.put(DEAD_BRAIN_CORAL_BLOCK, andNewer(r1_13)); + ITEM_DIFF.put(DEAD_BUBBLE_CORAL_BLOCK, andNewer(r1_13)); + ITEM_DIFF.put(DEAD_FIRE_CORAL_BLOCK, andNewer(r1_13)); + ITEM_DIFF.put(DEAD_HORN_CORAL_BLOCK, andNewer(r1_13)); + ITEM_DIFF.put(TUBE_CORAL_BLOCK, andNewer(r1_13)); + ITEM_DIFF.put(BRAIN_CORAL_BLOCK, andNewer(r1_13)); + ITEM_DIFF.put(BUBBLE_CORAL_BLOCK, andNewer(r1_13)); + ITEM_DIFF.put(FIRE_CORAL_BLOCK, andNewer(r1_13)); + ITEM_DIFF.put(HORN_CORAL_BLOCK, andNewer(r1_13)); + ITEM_DIFF.put(TUBE_CORAL, andNewer(r1_13)); + ITEM_DIFF.put(BRAIN_CORAL, andNewer(r1_13)); + ITEM_DIFF.put(BUBBLE_CORAL, andNewer(r1_13)); + ITEM_DIFF.put(FIRE_CORAL, andNewer(r1_13)); + ITEM_DIFF.put(HORN_CORAL, andNewer(r1_13)); + ITEM_DIFF.put(TUBE_CORAL_FAN, andNewer(r1_13)); + ITEM_DIFF.put(BRAIN_CORAL_FAN, andNewer(r1_13)); + ITEM_DIFF.put(BUBBLE_CORAL_FAN, andNewer(r1_13)); + ITEM_DIFF.put(FIRE_CORAL_FAN, andNewer(r1_13)); + ITEM_DIFF.put(HORN_CORAL_FAN, andNewer(r1_13)); + ITEM_DIFF.put(DEAD_TUBE_CORAL_FAN, andNewer(r1_13)); + ITEM_DIFF.put(DEAD_BRAIN_CORAL_FAN, andNewer(r1_13)); + ITEM_DIFF.put(DEAD_BUBBLE_CORAL_FAN, andNewer(r1_13)); + ITEM_DIFF.put(DEAD_FIRE_CORAL_FAN, andNewer(r1_13)); + ITEM_DIFF.put(DEAD_HORN_CORAL_FAN, andNewer(r1_13)); + ITEM_DIFF.put(BLUE_ICE, andNewer(r1_13)); + ITEM_DIFF.put(CONDUIT, andNewer(r1_13)); + ITEM_DIFF.put(TURTLE_HELMET, andNewer(r1_13)); + ITEM_DIFF.put(SCUTE, andNewer(r1_13)); + ITEM_DIFF.put(PUFFERFISH_BUCKET, andNewer(r1_13)); + ITEM_DIFF.put(SALMON_BUCKET, andNewer(r1_13)); + ITEM_DIFF.put(COD_BUCKET, andNewer(r1_13)); + ITEM_DIFF.put(TROPICAL_FISH_BUCKET, andNewer(r1_13)); + ITEM_DIFF.put(KELP, andNewer(r1_13)); + ITEM_DIFF.put(DRIED_KELP_BLOCK, andNewer(r1_13)); + ITEM_DIFF.put(DRIED_KELP, andNewer(r1_13)); + ITEM_DIFF.put(COD_SPAWN_EGG, andNewer(r1_13)); + ITEM_DIFF.put(DOLPHIN_SPAWN_EGG, andNewer(r1_13)); + ITEM_DIFF.put(DROWNED_SPAWN_EGG, andNewer(r1_13)); + ITEM_DIFF.put(PHANTOM_SPAWN_EGG, andNewer(r1_13)); + ITEM_DIFF.put(PUFFERFISH_SPAWN_EGG, andNewer(r1_13)); + ITEM_DIFF.put(SALMON_SPAWN_EGG, andNewer(r1_13)); + ITEM_DIFF.put(TROPICAL_FISH_SPAWN_EGG, andNewer(r1_13)); + ITEM_DIFF.put(TURTLE_SPAWN_EGG, andNewer(r1_13)); + ITEM_DIFF.put(DEBUG_STICK, andNewer(r1_13)); + ITEM_DIFF.put(TRIDENT, andNewer(r1_13)); + ITEM_DIFF.put(PHANTOM_MEMBRANE, andNewer(r1_13)); + ITEM_DIFF.put(NAUTILUS_SHELL, andNewer(r1_13)); + ITEM_DIFF.put(HEART_OF_THE_SEA, andNewer(r1_13)); + + ITEM_DIFF.put(KNOWLEDGE_BOOK, andNewer(r1_12)); + ITEM_DIFF.put(WHITE_GLAZED_TERRACOTTA, andNewer(r1_12)); + ITEM_DIFF.put(ORANGE_GLAZED_TERRACOTTA, andNewer(r1_12)); + ITEM_DIFF.put(MAGENTA_GLAZED_TERRACOTTA, andNewer(r1_12)); + ITEM_DIFF.put(LIGHT_BLUE_GLAZED_TERRACOTTA, andNewer(r1_12)); + ITEM_DIFF.put(YELLOW_GLAZED_TERRACOTTA, andNewer(r1_12)); + ITEM_DIFF.put(LIME_GLAZED_TERRACOTTA, andNewer(r1_12)); + ITEM_DIFF.put(PINK_GLAZED_TERRACOTTA, andNewer(r1_12)); + ITEM_DIFF.put(GRAY_GLAZED_TERRACOTTA, andNewer(r1_12)); + ITEM_DIFF.put(LIGHT_GRAY_GLAZED_TERRACOTTA, andNewer(r1_12)); + ITEM_DIFF.put(CYAN_GLAZED_TERRACOTTA, andNewer(r1_12)); + ITEM_DIFF.put(PURPLE_GLAZED_TERRACOTTA, andNewer(r1_12)); + ITEM_DIFF.put(BLUE_GLAZED_TERRACOTTA, andNewer(r1_12)); + ITEM_DIFF.put(BROWN_GLAZED_TERRACOTTA, andNewer(r1_12)); + ITEM_DIFF.put(GREEN_GLAZED_TERRACOTTA, andNewer(r1_12)); + ITEM_DIFF.put(RED_GLAZED_TERRACOTTA, andNewer(r1_12)); + ITEM_DIFF.put(BLACK_GLAZED_TERRACOTTA, andNewer(r1_12)); + ITEM_DIFF.put(WHITE_CONCRETE, andNewer(r1_12)); + ITEM_DIFF.put(ORANGE_CONCRETE, andNewer(r1_12)); + ITEM_DIFF.put(MAGENTA_CONCRETE, andNewer(r1_12)); + ITEM_DIFF.put(LIGHT_BLUE_CONCRETE, andNewer(r1_12)); + ITEM_DIFF.put(YELLOW_CONCRETE, andNewer(r1_12)); + ITEM_DIFF.put(LIME_CONCRETE, andNewer(r1_12)); + ITEM_DIFF.put(PINK_CONCRETE, andNewer(r1_12)); + ITEM_DIFF.put(GRAY_CONCRETE, andNewer(r1_12)); + ITEM_DIFF.put(LIGHT_GRAY_CONCRETE, andNewer(r1_12)); + ITEM_DIFF.put(CYAN_CONCRETE, andNewer(r1_12)); + ITEM_DIFF.put(PURPLE_CONCRETE, andNewer(r1_12)); + ITEM_DIFF.put(BLUE_CONCRETE, andNewer(r1_12)); + ITEM_DIFF.put(BROWN_CONCRETE, andNewer(r1_12)); + ITEM_DIFF.put(GREEN_CONCRETE, andNewer(r1_12)); + ITEM_DIFF.put(RED_CONCRETE, andNewer(r1_12)); + ITEM_DIFF.put(BLACK_CONCRETE, andNewer(r1_12)); + ITEM_DIFF.put(WHITE_CONCRETE_POWDER, andNewer(r1_12)); + ITEM_DIFF.put(ORANGE_CONCRETE_POWDER, andNewer(r1_12)); + ITEM_DIFF.put(MAGENTA_CONCRETE_POWDER, andNewer(r1_12)); + ITEM_DIFF.put(LIGHT_BLUE_CONCRETE_POWDER, andNewer(r1_12)); + ITEM_DIFF.put(YELLOW_CONCRETE_POWDER, andNewer(r1_12)); + ITEM_DIFF.put(LIME_CONCRETE_POWDER, andNewer(r1_12)); + ITEM_DIFF.put(PINK_CONCRETE_POWDER, andNewer(r1_12)); + ITEM_DIFF.put(GRAY_CONCRETE_POWDER, andNewer(r1_12)); + ITEM_DIFF.put(LIGHT_GRAY_CONCRETE_POWDER, andNewer(r1_12)); + ITEM_DIFF.put(CYAN_CONCRETE_POWDER, andNewer(r1_12)); + ITEM_DIFF.put(PURPLE_CONCRETE_POWDER, andNewer(r1_12)); + ITEM_DIFF.put(BLUE_CONCRETE_POWDER, andNewer(r1_12)); + ITEM_DIFF.put(BROWN_CONCRETE_POWDER, andNewer(r1_12)); + ITEM_DIFF.put(GREEN_CONCRETE_POWDER, andNewer(r1_12)); + ITEM_DIFF.put(RED_CONCRETE_POWDER, andNewer(r1_12)); + ITEM_DIFF.put(BLACK_CONCRETE_POWDER, andNewer(r1_12)); + ITEM_DIFF.put(WHITE_BED, andNewer(r1_12)); + ITEM_DIFF.put(ORANGE_BED, andNewer(r1_12)); + ITEM_DIFF.put(MAGENTA_BED, andNewer(r1_12)); + ITEM_DIFF.put(LIGHT_BLUE_BED, andNewer(r1_12)); + ITEM_DIFF.put(YELLOW_BED, andNewer(r1_12)); + ITEM_DIFF.put(LIME_BED, andNewer(r1_12)); + ITEM_DIFF.put(PINK_BED, andNewer(r1_12)); + ITEM_DIFF.put(GRAY_BED, andNewer(r1_12)); + ITEM_DIFF.put(LIGHT_GRAY_BED, andNewer(r1_12)); + ITEM_DIFF.put(CYAN_BED, andNewer(r1_12)); + ITEM_DIFF.put(PURPLE_BED, andNewer(r1_12)); + ITEM_DIFF.put(BLUE_BED, andNewer(r1_12)); + ITEM_DIFF.put(BROWN_BED, andNewer(r1_12)); + ITEM_DIFF.put(GREEN_BED, andNewer(r1_12)); + ITEM_DIFF.put(BLACK_BED, andNewer(r1_12)); + ITEM_DIFF.put(PARROT_SPAWN_EGG, andNewer(r1_12)); + + ITEM_DIFF.put(IRON_NUGGET, andNewer(r1_11_1to1_11_2)); + + ITEM_DIFF.put(OBSERVER, andNewer(r1_11)); + ITEM_DIFF.put(WHITE_SHULKER_BOX, andNewer(r1_11)); + ITEM_DIFF.put(ORANGE_SHULKER_BOX, andNewer(r1_11)); + ITEM_DIFF.put(MAGENTA_SHULKER_BOX, andNewer(r1_11)); + ITEM_DIFF.put(LIGHT_BLUE_SHULKER_BOX, andNewer(r1_11)); + ITEM_DIFF.put(YELLOW_SHULKER_BOX, andNewer(r1_11)); + ITEM_DIFF.put(LIME_SHULKER_BOX, andNewer(r1_11)); + ITEM_DIFF.put(PINK_SHULKER_BOX, andNewer(r1_11)); + ITEM_DIFF.put(GRAY_SHULKER_BOX, andNewer(r1_11)); + ITEM_DIFF.put(LIGHT_GRAY_SHULKER_BOX, andNewer(r1_11)); + ITEM_DIFF.put(CYAN_SHULKER_BOX, andNewer(r1_11)); + ITEM_DIFF.put(PURPLE_SHULKER_BOX, andNewer(r1_11)); + ITEM_DIFF.put(BLUE_SHULKER_BOX, andNewer(r1_11)); + ITEM_DIFF.put(BROWN_SHULKER_BOX, andNewer(r1_11)); + ITEM_DIFF.put(GREEN_SHULKER_BOX, andNewer(r1_11)); + ITEM_DIFF.put(RED_SHULKER_BOX, andNewer(r1_11)); + ITEM_DIFF.put(BLACK_SHULKER_BOX, andNewer(r1_11)); + ITEM_DIFF.put(TOTEM_OF_UNDYING, andNewer(r1_11)); + ITEM_DIFF.put(SHULKER_SHELL, andNewer(r1_11)); + ITEM_DIFF.put(VEX_SPAWN_EGG, andNewer(r1_11)); + ITEM_DIFF.put(POLAR_BEAR_SPAWN_EGG, andNewer(r1_11)); + ITEM_DIFF.put(STRAY_SPAWN_EGG, andNewer(r1_11)); + ITEM_DIFF.put(HUSK_SPAWN_EGG, andNewer(r1_11)); + ITEM_DIFF.put(ELDER_GUARDIAN_SPAWN_EGG, andNewer(r1_11)); + ITEM_DIFF.put(WITHER_SKELETON_SPAWN_EGG, andNewer(r1_11)); + ITEM_DIFF.put(DONKEY_SPAWN_EGG, andNewer(r1_11)); + ITEM_DIFF.put(MULE_SPAWN_EGG, andNewer(r1_11)); + ITEM_DIFF.put(SKELETON_HORSE_SPAWN_EGG, andNewer(r1_11)); + ITEM_DIFF.put(ZOMBIE_HORSE_SPAWN_EGG, andNewer(r1_11)); + ITEM_DIFF.put(ZOMBIE_VILLAGER_SPAWN_EGG, andNewer(r1_11)); + ITEM_DIFF.put(EVOKER_SPAWN_EGG, andNewer(r1_11)); + ITEM_DIFF.put(LLAMA_SPAWN_EGG, andNewer(r1_11)); + ITEM_DIFF.put(VINDICATOR_SPAWN_EGG, andNewer(r1_11)); + + ITEM_DIFF.put(MAGMA_BLOCK, andNewer(r1_10)); + ITEM_DIFF.put(NETHER_WART_BLOCK, andNewer(r1_10)); + ITEM_DIFF.put(RED_NETHER_BRICKS, andNewer(r1_10)); + ITEM_DIFF.put(BONE_BLOCK, andNewer(r1_10)); + ITEM_DIFF.put(STRUCTURE_VOID, andNewer(r1_10)); + ITEM_DIFF.put(STRUCTURE_BLOCK, andNewer(r1_10)); + + ITEM_DIFF.put(END_ROD, andNewer(r1_9)); + ITEM_DIFF.put(CHORUS_PLANT, andNewer(r1_9)); + ITEM_DIFF.put(CHORUS_FLOWER, andNewer(r1_9)); + ITEM_DIFF.put(PURPUR_BLOCK, andNewer(r1_9)); + ITEM_DIFF.put(PURPUR_PILLAR, andNewer(r1_9)); + ITEM_DIFF.put(PURPUR_STAIRS, andNewer(r1_9)); + ITEM_DIFF.put(PURPUR_SLAB, andNewer(r1_9)); + ITEM_DIFF.put(END_STONE_BRICKS, andNewer(r1_9)); + ITEM_DIFF.put(DIRT_PATH, andNewer(r1_9)); + ITEM_DIFF.put(REPEATING_COMMAND_BLOCK, andNewer(r1_9)); + ITEM_DIFF.put(CHAIN_COMMAND_BLOCK, andNewer(r1_9)); + ITEM_DIFF.put(END_CRYSTAL, andNewer(r1_9)); + ITEM_DIFF.put(CHORUS_FRUIT, andNewer(r1_9)); + ITEM_DIFF.put(POPPED_CHORUS_FRUIT, andNewer(r1_9)); + ITEM_DIFF.put(BEETROOT, andNewer(r1_9)); + ITEM_DIFF.put(BEETROOT_SEEDS, andNewer(r1_9)); + ITEM_DIFF.put(BEETROOT_SOUP, andNewer(r1_9)); + ITEM_DIFF.put(DRAGON_HEAD, andNewer(r1_9)); + ITEM_DIFF.put(DRAGON_BREATH, andNewer(r1_9)); + ITEM_DIFF.put(SPECTRAL_ARROW, andNewer(r1_9)); + ITEM_DIFF.put(TIPPED_ARROW, andNewer(r1_9)); + ITEM_DIFF.put(SPRUCE_BOAT, andNewer(r1_9)); + ITEM_DIFF.put(BIRCH_BOAT, andNewer(r1_9)); + ITEM_DIFF.put(JUNGLE_BOAT, andNewer(r1_9)); + ITEM_DIFF.put(ACACIA_BOAT, andNewer(r1_9)); + ITEM_DIFF.put(DARK_OAK_BOAT, andNewer(r1_9)); + ITEM_DIFF.put(LINGERING_POTION, andNewer(r1_9)); + ITEM_DIFF.put(SHIELD, andNewer(r1_9)); + ITEM_DIFF.put(ELYTRA, andNewer(r1_9)); + ITEM_DIFF.put(SHULKER_SPAWN_EGG, andNewer(r1_9)); + + ITEM_DIFF.put(ACACIA_DOOR, andNewer(r1_8)); + ITEM_DIFF.put(ACACIA_FENCE, andNewer(r1_8)); + ITEM_DIFF.put(ACACIA_FENCE_GATE, andNewer(r1_8)); + ITEM_DIFF.put(ARMOR_STAND, andNewer(r1_8)); + ITEM_DIFF.put(WHITE_BANNER, andNewer(r1_8)); + ITEM_DIFF.put(ORANGE_BANNER, andNewer(r1_8)); + ITEM_DIFF.put(MAGENTA_BANNER, andNewer(r1_8)); + ITEM_DIFF.put(LIGHT_BLUE_BANNER, andNewer(r1_8)); + ITEM_DIFF.put(YELLOW_BANNER, andNewer(r1_8)); + ITEM_DIFF.put(LIME_BANNER, andNewer(r1_8)); + ITEM_DIFF.put(PINK_BANNER, andNewer(r1_8)); + ITEM_DIFF.put(GRAY_BANNER, andNewer(r1_8)); + ITEM_DIFF.put(LIGHT_GRAY_BANNER, andNewer(r1_8)); + ITEM_DIFF.put(CYAN_BANNER, andNewer(r1_8)); + ITEM_DIFF.put(PURPLE_BANNER, andNewer(r1_8)); + ITEM_DIFF.put(BLUE_BANNER, andNewer(r1_8)); + ITEM_DIFF.put(BROWN_BANNER, andNewer(r1_8)); + ITEM_DIFF.put(GREEN_BANNER, andNewer(r1_8)); + ITEM_DIFF.put(RED_BANNER, andNewer(r1_8)); + ITEM_DIFF.put(BLACK_BANNER, andNewer(r1_8)); + ITEM_DIFF.put(BARRIER, andNewer(r1_8)); + ITEM_DIFF.put(BIRCH_DOOR, andNewer(r1_8)); + ITEM_DIFF.put(BIRCH_FENCE, andNewer(r1_8)); + ITEM_DIFF.put(BIRCH_FENCE_GATE, andNewer(r1_8)); + ITEM_DIFF.put(COOKED_MUTTON, andNewer(r1_8)); + ITEM_DIFF.put(COOKED_RABBIT, andNewer(r1_8)); + ITEM_DIFF.put(DARK_OAK_DOOR, andNewer(r1_8)); + ITEM_DIFF.put(DARK_OAK_FENCE, andNewer(r1_8)); + ITEM_DIFF.put(DARK_OAK_FENCE_GATE, andNewer(r1_8)); + ITEM_DIFF.put(IRON_TRAPDOOR, andNewer(r1_8)); + ITEM_DIFF.put(JUNGLE_DOOR, andNewer(r1_8)); + ITEM_DIFF.put(JUNGLE_FENCE, andNewer(r1_8)); + ITEM_DIFF.put(JUNGLE_FENCE_GATE, andNewer(r1_8)); + ITEM_DIFF.put(MUTTON, andNewer(r1_8)); + ITEM_DIFF.put(PRISMARINE, andNewer(r1_8)); + ITEM_DIFF.put(PRISMARINE_CRYSTALS, andNewer(r1_8)); + ITEM_DIFF.put(PRISMARINE_SHARD, andNewer(r1_8)); + ITEM_DIFF.put(RABBIT, andNewer(r1_8)); + ITEM_DIFF.put(RABBIT_FOOT, andNewer(r1_8)); + ITEM_DIFF.put(RABBIT_HIDE, andNewer(r1_8)); + ITEM_DIFF.put(RABBIT_STEW, andNewer(r1_8)); + ITEM_DIFF.put(RED_SANDSTONE, andNewer(r1_8)); + ITEM_DIFF.put(RED_SANDSTONE_STAIRS, andNewer(r1_8)); + ITEM_DIFF.put(CUT_RED_SANDSTONE, andNewer(r1_8)); + ITEM_DIFF.put(CHISELED_RED_SANDSTONE, andNewer(r1_8)); + ITEM_DIFF.put(RED_SANDSTONE_SLAB, andNewer(r1_8)); + ITEM_DIFF.put(SEA_LANTERN, andNewer(r1_8)); + ITEM_DIFF.put(SLIME_BLOCK, andNewer(r1_8)); + ITEM_DIFF.put(SPRUCE_DOOR, andNewer(r1_8)); + ITEM_DIFF.put(SPRUCE_FENCE, andNewer(r1_8)); + ITEM_DIFF.put(SPRUCE_FENCE_GATE, andNewer(r1_8)); + ITEM_DIFF.put(DIORITE, andNewer(r1_8)); + ITEM_DIFF.put(POLISHED_DIORITE, andNewer(r1_8)); + ITEM_DIFF.put(ANDESITE, andNewer(r1_8)); + ITEM_DIFF.put(POLISHED_ANDESITE, andNewer(r1_8)); + ITEM_DIFF.put(GRANITE, andNewer(r1_8)); + ITEM_DIFF.put(POLISHED_GRANITE, andNewer(r1_8)); + ITEM_DIFF.put(DARK_PRISMARINE, andNewer(r1_8)); + ITEM_DIFF.put(PRISMARINE_BRICKS, andNewer(r1_8)); + ITEM_DIFF.put(WET_SPONGE, andNewer(r1_8)); + ITEM_DIFF.put(COARSE_DIRT, andNewer(r1_8)); + ITEM_DIFF.put(RABBIT_SPAWN_EGG, andNewer(r1_8)); + ITEM_DIFF.put(GUARDIAN_SPAWN_EGG, andNewer(r1_8)); + ITEM_DIFF.put(ENDERMITE_SPAWN_EGG, andNewer(r1_8)); + + ITEM_DIFF.put(WHITE_STAINED_GLASS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(ORANGE_STAINED_GLASS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(MAGENTA_STAINED_GLASS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(LIGHT_BLUE_STAINED_GLASS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(YELLOW_STAINED_GLASS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(LIME_STAINED_GLASS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(PINK_STAINED_GLASS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(GRAY_STAINED_GLASS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(LIGHT_GRAY_STAINED_GLASS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(CYAN_STAINED_GLASS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(PURPLE_STAINED_GLASS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(BLUE_STAINED_GLASS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(BROWN_STAINED_GLASS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(GREEN_STAINED_GLASS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(RED_STAINED_GLASS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(BLACK_STAINED_GLASS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(WHITE_STAINED_GLASS_PANE, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(ORANGE_STAINED_GLASS_PANE, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(MAGENTA_STAINED_GLASS_PANE, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(LIGHT_BLUE_STAINED_GLASS_PANE, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(YELLOW_STAINED_GLASS_PANE, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(LIME_STAINED_GLASS_PANE, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(PINK_STAINED_GLASS_PANE, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(GRAY_STAINED_GLASS_PANE, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(LIGHT_GRAY_STAINED_GLASS_PANE, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(CYAN_STAINED_GLASS_PANE, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(PURPLE_STAINED_GLASS_PANE, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(BLUE_STAINED_GLASS_PANE, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(BROWN_STAINED_GLASS_PANE, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(GREEN_STAINED_GLASS_PANE, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(RED_STAINED_GLASS_PANE, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(BLACK_STAINED_GLASS_PANE, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(ACACIA_LOG, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(DARK_OAK_LOG, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(ACACIA_PLANKS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(DARK_OAK_PLANKS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(ACACIA_SLAB, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(DARK_OAK_SLAB, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(ACACIA_STAIRS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(DARK_OAK_STAIRS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(ACACIA_SAPLING, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(DARK_OAK_SAPLING, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(ACACIA_LEAVES, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(DARK_OAK_LEAVES, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(PACKED_ICE, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(PODZOL, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(RED_SAND, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(RED_TULIP, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(ORANGE_TULIP, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(WHITE_TULIP, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(PINK_TULIP, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(BLUE_ORCHID, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(ALLIUM, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(AZURE_BLUET, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(OXEYE_DAISY, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(SUNFLOWER, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(PEONY, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(ROSE_BUSH, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(LILAC, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(TALL_GRASS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(LARGE_FERN, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(INFESTED_MOSSY_STONE_BRICKS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(INFESTED_CRACKED_STONE_BRICKS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(INFESTED_CHISELED_STONE_BRICKS, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(PUFFERFISH, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(SALMON, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(COOKED_SALMON, andNewer(r1_7_2tor1_7_5)); + ITEM_DIFF.put(TROPICAL_FISH, andNewer(r1_7_2tor1_7_5)); + + ITEM_DIFF.put(HAY_BLOCK, andNewer(r1_6_1)); + ITEM_DIFF.put(WHITE_CARPET, andNewer(r1_6_1)); + ITEM_DIFF.put(ORANGE_CARPET, andNewer(r1_6_1)); + ITEM_DIFF.put(MAGENTA_CARPET, andNewer(r1_6_1)); + ITEM_DIFF.put(LIGHT_BLUE_CARPET, andNewer(r1_6_1)); + ITEM_DIFF.put(YELLOW_CARPET, andNewer(r1_6_1)); + ITEM_DIFF.put(LIME_CARPET, andNewer(r1_6_1)); + ITEM_DIFF.put(PINK_CARPET, andNewer(r1_6_1)); + ITEM_DIFF.put(GRAY_CARPET, andNewer(r1_6_1)); + ITEM_DIFF.put(LIGHT_GRAY_CARPET, andNewer(r1_6_1)); + ITEM_DIFF.put(CYAN_CARPET, andNewer(r1_6_1)); + ITEM_DIFF.put(PURPLE_CARPET, andNewer(r1_6_1)); + ITEM_DIFF.put(BLUE_CARPET, andNewer(r1_6_1)); + ITEM_DIFF.put(BROWN_CARPET, andNewer(r1_6_1)); + ITEM_DIFF.put(GREEN_CARPET, andNewer(r1_6_1)); + ITEM_DIFF.put(RED_CARPET, andNewer(r1_6_1)); + ITEM_DIFF.put(BLACK_CARPET, andNewer(r1_6_1)); + ITEM_DIFF.put(TERRACOTTA, andNewer(r1_6_1)); + ITEM_DIFF.put(WHITE_TERRACOTTA, andNewer(r1_6_1)); + ITEM_DIFF.put(ORANGE_TERRACOTTA, andNewer(r1_6_1)); + ITEM_DIFF.put(MAGENTA_TERRACOTTA, andNewer(r1_6_1)); + ITEM_DIFF.put(LIGHT_BLUE_TERRACOTTA, andNewer(r1_6_1)); + ITEM_DIFF.put(YELLOW_TERRACOTTA, andNewer(r1_6_1)); + ITEM_DIFF.put(LIME_TERRACOTTA, andNewer(r1_6_1)); + ITEM_DIFF.put(PINK_TERRACOTTA, andNewer(r1_6_1)); + ITEM_DIFF.put(GRAY_TERRACOTTA, andNewer(r1_6_1)); + ITEM_DIFF.put(LIGHT_GRAY_TERRACOTTA, andNewer(r1_6_1)); + ITEM_DIFF.put(CYAN_TERRACOTTA, andNewer(r1_6_1)); + ITEM_DIFF.put(PURPLE_TERRACOTTA, andNewer(r1_6_1)); + ITEM_DIFF.put(BLUE_TERRACOTTA, andNewer(r1_6_1)); + ITEM_DIFF.put(BROWN_TERRACOTTA, andNewer(r1_6_1)); + ITEM_DIFF.put(GREEN_TERRACOTTA, andNewer(r1_6_1)); + ITEM_DIFF.put(RED_TERRACOTTA, andNewer(r1_6_1)); + ITEM_DIFF.put(BLACK_TERRACOTTA, andNewer(r1_6_1)); + ITEM_DIFF.put(COAL_BLOCK, andNewer(r1_6_1)); + ITEM_DIFF.put(IRON_HORSE_ARMOR, andNewer(r1_6_1)); + ITEM_DIFF.put(GOLDEN_HORSE_ARMOR, andNewer(r1_6_1)); + ITEM_DIFF.put(DIAMOND_HORSE_ARMOR, andNewer(r1_6_1)); + ITEM_DIFF.put(HORSE_SPAWN_EGG, andNewer(r1_6_1)); + ITEM_DIFF.put(LEAD, andNewer(r1_6_1)); + ITEM_DIFF.put(NAME_TAG, andNewer(r1_6_1)); + + ITEM_DIFF.put(ACTIVATOR_RAIL, andNewer(r1_5tor1_5_1)); + ITEM_DIFF.put(REDSTONE_BLOCK, andNewer(r1_5tor1_5_1)); + ITEM_DIFF.put(DAYLIGHT_DETECTOR, andNewer(r1_5tor1_5_1)); + ITEM_DIFF.put(DROPPER, andNewer(r1_5tor1_5_1)); + ITEM_DIFF.put(HOPPER, andNewer(r1_5tor1_5_1)); + ITEM_DIFF.put(COMPARATOR, andNewer(r1_5tor1_5_1)); + ITEM_DIFF.put(TRAPPED_CHEST, andNewer(r1_5tor1_5_1)); + ITEM_DIFF.put(LIGHT_WEIGHTED_PRESSURE_PLATE, andNewer(r1_5tor1_5_1)); + ITEM_DIFF.put(HEAVY_WEIGHTED_PRESSURE_PLATE, andNewer(r1_5tor1_5_1)); + ITEM_DIFF.put(NETHER_QUARTZ_ORE, andNewer(r1_5tor1_5_1)); + ITEM_DIFF.put(QUARTZ_BLOCK, andNewer(r1_5tor1_5_1)); + ITEM_DIFF.put(QUARTZ_SLAB, andNewer(r1_5tor1_5_1)); + ITEM_DIFF.put(QUARTZ_STAIRS, andNewer(r1_5tor1_5_1)); + ITEM_DIFF.put(CHISELED_QUARTZ_BLOCK, andNewer(r1_5tor1_5_1)); + ITEM_DIFF.put(QUARTZ_PILLAR, andNewer(r1_5tor1_5_1)); + ITEM_DIFF.put(NETHER_BRICK, andNewer(r1_5tor1_5_1)); + ITEM_DIFF.put(QUARTZ, andNewer(r1_5tor1_5_1)); + ITEM_DIFF.put(TNT_MINECART, andNewer(r1_5tor1_5_1)); + ITEM_DIFF.put(HOPPER_MINECART, andNewer(r1_5tor1_5_1)); + + ITEM_DIFF.put(NETHER_BRICK_SLAB, andNewer(r1_4_6tor1_4_7)); + ITEM_DIFF.put(ENCHANTED_BOOK, andNewer(r1_4_6tor1_4_7)); + ITEM_DIFF.put(FIREWORK_STAR, andNewer(r1_4_6tor1_4_7)); + ITEM_DIFF.put(FIREWORK_ROCKET, andNewer(r1_4_6tor1_4_7)); + + ITEM_DIFF.put(MUSIC_DISC_WAIT, andNewer(r1_4_4tor1_4_5)); + + ITEM_DIFF.put(COMMAND_BLOCK, andNewer(r1_4_2)); + ITEM_DIFF.put(COMMAND_BLOCK_MINECART, andNewer(r1_4_2)); + ITEM_DIFF.put(BEACON, andNewer(r1_4_2)); + ITEM_DIFF.put(ANVIL, andNewer(r1_4_2)); + ITEM_DIFF.put(CHIPPED_ANVIL, andNewer(r1_4_2)); + ITEM_DIFF.put(DAMAGED_ANVIL, andNewer(r1_4_2)); + ITEM_DIFF.put(FLOWER_POT, andNewer(r1_4_2)); + ITEM_DIFF.put(COBBLESTONE_WALL, andNewer(r1_4_2)); + ITEM_DIFF.put(MOSSY_COBBLESTONE_WALL, andNewer(r1_4_2)); + ITEM_DIFF.put(CREEPER_HEAD, andNewer(r1_4_2)); + ITEM_DIFF.put(ZOMBIE_HEAD, andNewer(r1_4_2)); + ITEM_DIFF.put(SKELETON_SKULL, andNewer(r1_4_2)); + ITEM_DIFF.put(WITHER_SKELETON_SKULL, andNewer(r1_4_2)); + ITEM_DIFF.put(PLAYER_HEAD, andNewer(r1_4_2)); + ITEM_DIFF.put(OAK_BUTTON, andNewer(r1_4_2)); + ITEM_DIFF.put(POTATO, andNewer(r1_4_2)); + ITEM_DIFF.put(POISONOUS_POTATO, andNewer(r1_4_2)); + ITEM_DIFF.put(BAKED_POTATO, andNewer(r1_4_2)); + ITEM_DIFF.put(CARROT, andNewer(r1_4_2)); + ITEM_DIFF.put(GOLDEN_CARROT, andNewer(r1_4_2)); + ITEM_DIFF.put(CARROT_ON_A_STICK, andNewer(r1_4_2)); + ITEM_DIFF.put(PUMPKIN_PIE, andNewer(r1_4_2)); + ITEM_DIFF.put(NETHER_STAR, andNewer(r1_4_2)); + ITEM_DIFF.put(BAT_SPAWN_EGG, andNewer(r1_4_2)); + ITEM_DIFF.put(WITCH_SPAWN_EGG, andNewer(r1_4_2)); + ITEM_DIFF.put(ITEM_FRAME, andNewer(r1_4_2)); + + ITEM_DIFF.put(EMERALD_ORE, andNewer(r1_3_1tor1_3_2)); + ITEM_DIFF.put(EMERALD_BLOCK, andNewer(r1_3_1tor1_3_2)); + ITEM_DIFF.put(EMERALD, andNewer(r1_3_1tor1_3_2)); + ITEM_DIFF.put(ENDER_CHEST, andNewer(r1_3_1tor1_3_2)); + ITEM_DIFF.put(TRIPWIRE_HOOK, andNewer(r1_3_1tor1_3_2)); + ITEM_DIFF.put(SANDSTONE_STAIRS, andNewer(r1_3_1tor1_3_2)); + ITEM_DIFF.put(WRITABLE_BOOK, andNewer(r1_3_1tor1_3_2)); + ITEM_DIFF.put(WRITTEN_BOOK, andNewer(r1_3_1tor1_3_2)); + ITEM_DIFF.put(ENCHANTED_GOLDEN_APPLE, andNewer(r1_3_1tor1_3_2)); + ITEM_DIFF.put(OAK_SLAB, andNewer(r1_3_1tor1_3_2)); + ITEM_DIFF.put(SPRUCE_SLAB, andNewer(r1_3_1tor1_3_2)); + ITEM_DIFF.put(BIRCH_SLAB, andNewer(r1_3_1tor1_3_2)); + ITEM_DIFF.put(JUNGLE_SLAB, andNewer(r1_3_1tor1_3_2)); + ITEM_DIFF.put(SPRUCE_STAIRS, andNewer(r1_3_1tor1_3_2)); + ITEM_DIFF.put(BIRCH_STAIRS, andNewer(r1_3_1tor1_3_2)); + ITEM_DIFF.put(JUNGLE_STAIRS, andNewer(r1_3_1tor1_3_2)); + + ITEM_DIFF.put(BIRCH_PLANKS, andNewer(r1_2_4tor1_2_5)); + ITEM_DIFF.put(SPRUCE_PLANKS, andNewer(r1_2_4tor1_2_5)); + ITEM_DIFF.put(JUNGLE_PLANKS, andNewer(r1_2_4tor1_2_5)); + ITEM_DIFF.put(CHISELED_SANDSTONE, andNewer(r1_2_4tor1_2_5)); + ITEM_DIFF.put(CUT_SANDSTONE, andNewer(r1_2_4tor1_2_5)); + + ITEM_DIFF.put(CHISELED_STONE_BRICKS, andNewer(r1_2_1tor1_2_3)); + ITEM_DIFF.put(REDSTONE_LAMP, andNewer(r1_2_1tor1_2_3)); + ITEM_DIFF.put(JUNGLE_LOG, andNewer(r1_2_1tor1_2_3)); + ITEM_DIFF.put(JUNGLE_LEAVES, andNewer(r1_2_1tor1_2_3)); + ITEM_DIFF.put(JUNGLE_SAPLING, andNewer(r1_2_1tor1_2_3)); + ITEM_DIFF.put(EXPERIENCE_BOTTLE, andNewer(r1_2_1tor1_2_3)); + ITEM_DIFF.put(FIRE_CHARGE, andNewer(r1_2_1tor1_2_3)); + ITEM_DIFF.put(OCELOT_SPAWN_EGG, andNewer(r1_2_1tor1_2_3)); + + ITEM_DIFF.put(BLAZE_SPAWN_EGG, andNewer(r1_1)); + ITEM_DIFF.put(CAVE_SPIDER_SPAWN_EGG, andNewer(r1_1)); + ITEM_DIFF.put(CHICKEN_SPAWN_EGG, andNewer(r1_1)); + ITEM_DIFF.put(COW_SPAWN_EGG, andNewer(r1_1)); + ITEM_DIFF.put(CREEPER_SPAWN_EGG, andNewer(r1_1)); + ITEM_DIFF.put(ENDERMAN_SPAWN_EGG, andNewer(r1_1)); + ITEM_DIFF.put(GHAST_SPAWN_EGG, andNewer(r1_1)); + ITEM_DIFF.put(MAGMA_CUBE_SPAWN_EGG, andNewer(r1_1)); + ITEM_DIFF.put(MOOSHROOM_SPAWN_EGG, andNewer(r1_1)); + ITEM_DIFF.put(PIG_SPAWN_EGG, andNewer(r1_1)); + ITEM_DIFF.put(SHEEP_SPAWN_EGG, andNewer(r1_1)); + ITEM_DIFF.put(SILVERFISH_SPAWN_EGG, andNewer(r1_1)); + ITEM_DIFF.put(SKELETON_SPAWN_EGG, andNewer(r1_1)); + ITEM_DIFF.put(SLIME_SPAWN_EGG, andNewer(r1_1)); + ITEM_DIFF.put(SPIDER_SPAWN_EGG, andNewer(r1_1)); + ITEM_DIFF.put(SQUID_SPAWN_EGG, andNewer(r1_1)); + ITEM_DIFF.put(VILLAGER_SPAWN_EGG, andNewer(r1_1)); + ITEM_DIFF.put(WOLF_SPAWN_EGG, andNewer(r1_1)); + ITEM_DIFF.put(ZOMBIE_SPAWN_EGG, andNewer(r1_1)); + ITEM_DIFF.put(ZOMBIFIED_PIGLIN_SPAWN_EGG, andNewer(r1_1)); + + ITEM_DIFF.put(BREWING_STAND, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(CAULDRON, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(DRAGON_EGG, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(ENCHANTING_TABLE, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(END_PORTAL_FRAME, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(END_STONE, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(LILY_PAD, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(MYCELIUM, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(NETHER_BRICKS, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(NETHER_BRICK_FENCE, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(NETHER_BRICK_STAIRS, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(NETHER_WART, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(BLAZE_POWDER, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(BLAZE_ROD, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(ENDER_EYE, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(SPIDER_EYE, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(FERMENTED_SPIDER_EYE, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(GHAST_TEAR, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(GLASS_BOTTLE, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(GLISTERING_MELON_SLICE, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(GOLD_NUGGET, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(MAGMA_CREAM, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(MUSIC_DISC_13, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(MUSIC_DISC_CAT, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(MUSIC_DISC_BLOCKS, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(MUSIC_DISC_CHIRP, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(MUSIC_DISC_FAR, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(MUSIC_DISC_MALL, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(MUSIC_DISC_MELLOHI, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(MUSIC_DISC_STAL, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(MUSIC_DISC_STRAD, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(MUSIC_DISC_WARD, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(MUSIC_DISC_11, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(POTION, andNewer(r1_0_0tor1_0_1)); + ITEM_DIFF.put(SPLASH_POTION, andNewer(r1_0_0tor1_0_1)); + + ITEM_DIFF.put(STONE_BRICKS, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(MOSSY_STONE_BRICKS, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(CRACKED_STONE_BRICKS, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(INFESTED_STONE, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(INFESTED_STONE_BRICKS, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(INFESTED_COBBLESTONE, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(BRICK_SLAB, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(STONE_BRICK_SLAB, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(MUSHROOM_STEM, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(BROWN_MUSHROOM_BLOCK, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(RED_MUSHROOM_BLOCK, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(MELON, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(VINE, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(IRON_BARS, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(GLASS_PANE, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(OAK_FENCE_GATE, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(BRICK_STAIRS, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(STONE_BRICK_STAIRS, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(CHICKEN, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(COOKED_CHICKEN, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(BEEF, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(COOKED_BEEF, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(ENDER_PEARL, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(MELON_SEEDS, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(MELON_SLICE, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(PUMPKIN_SEEDS, andNewer(b1_8tob1_8_1)); + ITEM_DIFF.put(ROTTEN_FLESH, andNewer(b1_8tob1_8_1)); + + ITEM_DIFF.put(PISTON, andNewer(b1_7tob1_7_3)); + ITEM_DIFF.put(STICKY_PISTON, andNewer(b1_7tob1_7_3)); + ITEM_DIFF.put(SHEARS, andNewer(b1_7tob1_7_3)); + + ITEM_DIFF.put(DEAD_BUSH, andNewer(b1_6tob1_6_6)); + ITEM_DIFF.put(GRASS, andNewer(b1_6tob1_6_6)); + ITEM_DIFF.put(FERN, andNewer(b1_6tob1_6_6)); + ITEM_DIFF.put(OAK_TRAPDOOR, andNewer(b1_6tob1_6_6)); + ITEM_DIFF.put(MAP, andNewer(b1_6tob1_6_6)); + ITEM_DIFF.put(FILLED_MAP, andNewer(b1_6tob1_6_6)); + + ITEM_DIFF.put(BIRCH_SAPLING, andNewer(b1_5tob1_5_2)); + ITEM_DIFF.put(COBWEB, andNewer(b1_5tob1_5_2)); + ITEM_DIFF.put(DETECTOR_RAIL, andNewer(b1_5tob1_5_2)); + ITEM_DIFF.put(POWERED_RAIL, andNewer(b1_5tob1_5_2)); + ITEM_DIFF.put(SPRUCE_SAPLING, andNewer(b1_5tob1_5_2)); + + ITEM_DIFF.put(COOKIE, andNewer(b1_4tob1_4_1)); + + ITEM_DIFF.put(RED_BED, andNewer(b1_3tob1_3_1)); + ITEM_DIFF.put(REPEATER, andNewer(b1_3tob1_3_1)); + ITEM_DIFF.put(COBBLESTONE_SLAB, andNewer(b1_3tob1_3_1)); + ITEM_DIFF.put(PETRIFIED_OAK_SLAB, andNewer(b1_3tob1_3_1)); + ITEM_DIFF.put(SANDSTONE_SLAB, andNewer(b1_3tob1_3_1)); + ITEM_DIFF.put(PAINTING, andNewer(b1_3tob1_3_1)); + + ITEM_DIFF.put(CAKE, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(DISPENSER, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(LAPIS_LAZULI, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(LAPIS_ORE, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(LAPIS_BLOCK, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(NOTE_BLOCK, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(SANDSTONE, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(SPRUCE_LOG, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(BIRCH_LOG, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(SPRUCE_LEAVES, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(BIRCH_LEAVES, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(BONE, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(BONE_MEAL, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(COCOA_BEANS, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(INK_SAC, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(CHARCOAL, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(SUGAR, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(PURPLE_DYE, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(CYAN_DYE, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(LIGHT_GRAY_DYE, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(GRAY_DYE, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(PINK_DYE, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(LIME_DYE, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(YELLOW_DYE, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(LIGHT_BLUE_DYE, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(MAGENTA_DYE, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(ORANGE_DYE, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(RED_DYE, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(GREEN_DYE, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(ORANGE_WOOL, andNewer(b1_2_0tob1_2_2).add(of(c0_0_20ac0_27, c0_28toc0_30))); + ITEM_DIFF.put(MAGENTA_WOOL, andNewer(b1_2_0tob1_2_2).add(of(c0_0_20ac0_27, c0_28toc0_30))); + ITEM_DIFF.put(LIGHT_BLUE_WOOL, andNewer(b1_2_0tob1_2_2).add(of(c0_0_20ac0_27, c0_28toc0_30))); + ITEM_DIFF.put(YELLOW_WOOL, andNewer(b1_2_0tob1_2_2).add(of(c0_0_20ac0_27, c0_28toc0_30))); + ITEM_DIFF.put(LIME_WOOL, andNewer(b1_2_0tob1_2_2).add(of(c0_0_20ac0_27, c0_28toc0_30))); + ITEM_DIFF.put(PINK_WOOL, andNewer(b1_2_0tob1_2_2).add(of(c0_0_20ac0_27, c0_28toc0_30))); + ITEM_DIFF.put(GRAY_WOOL, andNewer(b1_2_0tob1_2_2).add(of(c0_0_20ac0_27, c0_28toc0_30))); + ITEM_DIFF.put(LIGHT_GRAY_WOOL, andNewer(b1_2_0tob1_2_2).add(of(c0_0_20ac0_27, c0_28toc0_30))); + ITEM_DIFF.put(CYAN_WOOL, andNewer(b1_2_0tob1_2_2).add(of(c0_0_20ac0_27, c0_28toc0_30))); + ITEM_DIFF.put(PURPLE_WOOL, andNewer(b1_2_0tob1_2_2).add(of(c0_0_20ac0_27, c0_28toc0_30))); + ITEM_DIFF.put(BLUE_WOOL, andNewer(b1_2_0tob1_2_2).add(of(c0_0_20ac0_27, c0_28toc0_30))); + ITEM_DIFF.put(BROWN_WOOL, andNewer(b1_2_0tob1_2_2)); + ITEM_DIFF.put(GREEN_WOOL, andNewer(b1_2_0tob1_2_2).add(of(c0_0_20ac0_27, c0_28toc0_30))); + ITEM_DIFF.put(RED_WOOL, andNewer(b1_2_0tob1_2_2).add(of(c0_0_20ac0_27, c0_28toc0_30))); + ITEM_DIFF.put(BLACK_WOOL, andNewer(b1_2_0tob1_2_2)); + + ITEM_DIFF.put(JACK_O_LANTERN, andNewer(a1_2_0toa1_2_1_1)); + ITEM_DIFF.put(GLOWSTONE, andNewer(a1_2_0toa1_2_1_1)); + ITEM_DIFF.put(CLOCK, andNewer(a1_2_0toa1_2_1_1)); + ITEM_DIFF.put(NETHERRACK, andNewer(a1_2_0toa1_2_1_1)); + ITEM_DIFF.put(COD, andNewer(a1_2_0toa1_2_1_1)); + ITEM_DIFF.put(COOKED_COD, andNewer(a1_2_0toa1_2_1_1)); + ITEM_DIFF.put(SOUL_SAND, andNewer(a1_2_0toa1_2_1_1)); + ITEM_DIFF.put(CARVED_PUMPKIN, andNewer(a1_2_0toa1_2_1_1)); + ITEM_DIFF.put(GLOWSTONE_DUST, andNewer(a1_2_0toa1_2_1_1)); + + ITEM_DIFF.put(FISHING_ROD, andNewer(a1_1_0toa1_1_2_1)); + ITEM_DIFF.put(COMPASS, andNewer(a1_1_0toa1_1_2_1)); + + ITEM_DIFF.put(GRASS_BLOCK, andNewer(a1_0_15).add(single(c0_30cpe))); + ITEM_DIFF.put(BEDROCK, andNewer(a1_0_15).add(single(c0_30cpe))); + ITEM_DIFF.put(WATER_BUCKET, andNewer(a1_0_15).add(single(c0_30cpe))); + ITEM_DIFF.put(LAVA_BUCKET, andNewer(a1_0_15).add(single(c0_30cpe))); + + ITEM_DIFF.put(WOODEN_AXE, andNewer(a1_0_15)); + ITEM_DIFF.put(WOODEN_HOE, andNewer(a1_0_15)); + ITEM_DIFF.put(WOODEN_PICKAXE, andNewer(a1_0_15)); + ITEM_DIFF.put(WOODEN_SHOVEL, andNewer(a1_0_15)); + ITEM_DIFF.put(WOODEN_SWORD, andNewer(a1_0_15)); + ITEM_DIFF.put(STONE_AXE, andNewer(a1_0_15)); + ITEM_DIFF.put(STONE_HOE, andNewer(a1_0_15)); + ITEM_DIFF.put(STONE_PICKAXE, andNewer(a1_0_15)); + ITEM_DIFF.put(STONE_SHOVEL, andNewer(a1_0_15)); + ITEM_DIFF.put(STONE_SWORD, andNewer(a1_0_15)); + ITEM_DIFF.put(IRON_AXE, andNewer(a1_0_15)); + ITEM_DIFF.put(IRON_HOE, andNewer(a1_0_15)); + ITEM_DIFF.put(IRON_PICKAXE, andNewer(a1_0_15)); + ITEM_DIFF.put(IRON_SHOVEL, andNewer(a1_0_15)); + ITEM_DIFF.put(IRON_SWORD, andNewer(a1_0_15)); + ITEM_DIFF.put(GOLDEN_AXE, andNewer(a1_0_15)); + ITEM_DIFF.put(GOLDEN_HOE, andNewer(a1_0_15)); + ITEM_DIFF.put(GOLDEN_PICKAXE, andNewer(a1_0_15)); + ITEM_DIFF.put(GOLDEN_SHOVEL, andNewer(a1_0_15)); + ITEM_DIFF.put(GOLDEN_SWORD, andNewer(a1_0_15)); + ITEM_DIFF.put(DIAMOND_AXE, andNewer(a1_0_15)); + ITEM_DIFF.put(DIAMOND_HOE, andNewer(a1_0_15)); + ITEM_DIFF.put(DIAMOND_PICKAXE, andNewer(a1_0_15)); + ITEM_DIFF.put(DIAMOND_SHOVEL, andNewer(a1_0_15)); + ITEM_DIFF.put(DIAMOND_SWORD, andNewer(a1_0_15)); + ITEM_DIFF.put(LEATHER_HELMET, andNewer(a1_0_15)); + ITEM_DIFF.put(LEATHER_CHESTPLATE, andNewer(a1_0_15)); + ITEM_DIFF.put(LEATHER_LEGGINGS, andNewer(a1_0_15)); + ITEM_DIFF.put(LEATHER_BOOTS, andNewer(a1_0_15)); + ITEM_DIFF.put(CHAINMAIL_HELMET, andNewer(a1_0_15)); + ITEM_DIFF.put(CHAINMAIL_CHESTPLATE, andNewer(a1_0_15)); + ITEM_DIFF.put(CHAINMAIL_LEGGINGS, andNewer(a1_0_15)); + ITEM_DIFF.put(CHAINMAIL_BOOTS, andNewer(a1_0_15)); + ITEM_DIFF.put(IRON_HELMET, andNewer(a1_0_15)); + ITEM_DIFF.put(IRON_CHESTPLATE, andNewer(a1_0_15)); + ITEM_DIFF.put(IRON_LEGGINGS, andNewer(a1_0_15)); + ITEM_DIFF.put(IRON_BOOTS, andNewer(a1_0_15)); + ITEM_DIFF.put(GOLDEN_HELMET, andNewer(a1_0_15)); + ITEM_DIFF.put(GOLDEN_CHESTPLATE, andNewer(a1_0_15)); + ITEM_DIFF.put(GOLDEN_LEGGINGS, andNewer(a1_0_15)); + ITEM_DIFF.put(GOLDEN_BOOTS, andNewer(a1_0_15)); + ITEM_DIFF.put(DIAMOND_HELMET, andNewer(a1_0_15)); + ITEM_DIFF.put(DIAMOND_CHESTPLATE, andNewer(a1_0_15)); + ITEM_DIFF.put(DIAMOND_LEGGINGS, andNewer(a1_0_15)); + ITEM_DIFF.put(DIAMOND_BOOTS, andNewer(a1_0_15)); + ITEM_DIFF.put(BUCKET, andNewer(a1_0_15)); + ITEM_DIFF.put(MILK_BUCKET, andNewer(a1_0_15)); + ITEM_DIFF.put(FLINT_AND_STEEL, andNewer(a1_0_15)); + ITEM_DIFF.put(SADDLE, andNewer(a1_0_15)); + ITEM_DIFF.put(OAK_BOAT, andNewer(a1_0_15)); + ITEM_DIFF.put(RAIL, andNewer(a1_0_15)); + ITEM_DIFF.put(MINECART, andNewer(a1_0_15)); + ITEM_DIFF.put(CHEST_MINECART, andNewer(a1_0_15)); + ITEM_DIFF.put(FURNACE_MINECART, andNewer(a1_0_15)); + ITEM_DIFF.put(SNOWBALL, andNewer(a1_0_15)); + ITEM_DIFF.put(EGG, andNewer(a1_0_15)); + ITEM_DIFF.put(BOW, andNewer(a1_0_15)); + ITEM_DIFF.put(ARROW, andNewer(a1_0_15)); + ITEM_DIFF.put(APPLE, andNewer(a1_0_15)); + ITEM_DIFF.put(GOLDEN_APPLE, andNewer(a1_0_15)); + ITEM_DIFF.put(PORKCHOP, andNewer(a1_0_15)); + ITEM_DIFF.put(COOKED_PORKCHOP, andNewer(a1_0_15)); + ITEM_DIFF.put(BREAD, andNewer(a1_0_15)); + ITEM_DIFF.put(MUSHROOM_STEW, andNewer(a1_0_15)); + ITEM_DIFF.put(COAL, andNewer(a1_0_15)); + ITEM_DIFF.put(IRON_INGOT, andNewer(a1_0_15)); + ITEM_DIFF.put(GOLD_INGOT, andNewer(a1_0_15)); + ITEM_DIFF.put(DIAMOND, andNewer(a1_0_15)); + ITEM_DIFF.put(STICK, andNewer(a1_0_15)); + ITEM_DIFF.put(FLINT, andNewer(a1_0_15)); + ITEM_DIFF.put(WHEAT, andNewer(a1_0_15)); + ITEM_DIFF.put(STRING, andNewer(a1_0_15)); + ITEM_DIFF.put(FEATHER, andNewer(a1_0_15)); + ITEM_DIFF.put(LEATHER, andNewer(a1_0_15)); + ITEM_DIFF.put(SLIME_BALL, andNewer(a1_0_15)); + ITEM_DIFF.put(CLAY, andNewer(a1_0_15)); + ITEM_DIFF.put(CLAY_BALL, andNewer(a1_0_15)); + ITEM_DIFF.put(BOWL, andNewer(a1_0_15)); + ITEM_DIFF.put(BRICK, andNewer(a1_0_15)); + ITEM_DIFF.put(PAPER, andNewer(a1_0_15)); + ITEM_DIFF.put(BOOK, andNewer(a1_0_15)); + ITEM_DIFF.put(REDSTONE, andNewer(a1_0_15)); + ITEM_DIFF.put(GUNPOWDER, andNewer(a1_0_15)); + ITEM_DIFF.put(REDSTONE_TORCH, andNewer(a1_0_15)); + ITEM_DIFF.put(LEVER, andNewer(a1_0_15)); + ITEM_DIFF.put(STONE_BUTTON, andNewer(a1_0_15)); + ITEM_DIFF.put(OAK_PRESSURE_PLATE, andNewer(a1_0_15)); + ITEM_DIFF.put(STONE_PRESSURE_PLATE, andNewer(a1_0_15)); + ITEM_DIFF.put(CHEST, andNewer(a1_0_15)); + ITEM_DIFF.put(FURNACE, andNewer(a1_0_15)); + ITEM_DIFF.put(REDSTONE_ORE, andNewer(a1_0_15)); + ITEM_DIFF.put(JUKEBOX, andNewer(a1_0_15)); + ITEM_DIFF.put(OAK_DOOR, andNewer(a1_0_15)); + ITEM_DIFF.put(IRON_DOOR, andNewer(a1_0_15)); + ITEM_DIFF.put(OAK_SIGN, andNewer(a1_0_15)); + ITEM_DIFF.put(LADDER, andNewer(a1_0_15)); + ITEM_DIFF.put(TORCH, andNewer(a1_0_15)); + ITEM_DIFF.put(CRAFTING_TABLE, andNewer(a1_0_15)); + ITEM_DIFF.put(CACTUS, andNewer(a1_0_15)); + ITEM_DIFF.put(SUGAR_CANE, andNewer(a1_0_15)); + ITEM_DIFF.put(WHEAT_SEEDS, andNewer(a1_0_15)); + ITEM_DIFF.put(FARMLAND, andNewer(a1_0_15)); + ITEM_DIFF.put(SNOW, andNewer(a1_0_15)); + ITEM_DIFF.put(SNOW_BLOCK, andNewer(a1_0_15)); + ITEM_DIFF.put(ICE, andNewer(a1_0_15)); + ITEM_DIFF.put(DIAMOND_ORE, andNewer(a1_0_15)); + ITEM_DIFF.put(DIAMOND_BLOCK, andNewer(a1_0_15)); + ITEM_DIFF.put(OAK_FENCE, andNewer(a1_0_15)); + ITEM_DIFF.put(OAK_STAIRS, andNewer(a1_0_15)); + ITEM_DIFF.put(COBBLESTONE_STAIRS, andNewer(a1_0_15)); + + ITEM_DIFF.put(OBSIDIAN, andNewer(c0_30cpe)); + ITEM_DIFF.put(TNT, andNewer(c0_30cpe)); + ITEM_DIFF.put(BOOKSHELF, andNewer(c0_30cpe)); + ITEM_DIFF.put(IRON_BLOCK, andNewer(c0_30cpe)); + ITEM_DIFF.put(BRICKS, andNewer(c0_30cpe)); + ITEM_DIFF.put(COAL_ORE, andNewer(c0_30cpe)); + ITEM_DIFF.put(GOLD_ORE, andNewer(c0_30cpe)); + ITEM_DIFF.put(IRON_ORE, andNewer(c0_30cpe)); + ITEM_DIFF.put(MOSSY_COBBLESTONE, andNewer(c0_30cpe)); + ITEM_DIFF.put(SMOOTH_STONE_SLAB, andNewer(c0_30cpe)); + + ITEM_DIFF.put(DANDELION, andNewer(c0_0_20ac0_27)); + ITEM_DIFF.put(POPPY, andNewer(c0_0_20ac0_27)); + ITEM_DIFF.put(BROWN_MUSHROOM, andNewer(c0_0_20ac0_27)); + ITEM_DIFF.put(RED_MUSHROOM, andNewer(c0_0_20ac0_27)); + ITEM_DIFF.put(GOLD_BLOCK, andNewer(c0_0_20ac0_27)); + ITEM_DIFF.put(WHITE_WOOL, andNewer(c0_0_20ac0_27)); + + ITEM_DIFF.put(SPONGE, andNewer(c0_0_19a_06)); + ITEM_DIFF.put(GLASS, andNewer(c0_0_19a_06)); + + ITEM_DIFF.put(STONE, andNewer(c0_0_15a_1)); + ITEM_DIFF.put(DIRT, andNewer(c0_0_15a_1)); + ITEM_DIFF.put(COBBLESTONE, andNewer(c0_0_15a_1)); + ITEM_DIFF.put(OAK_PLANKS, andNewer(c0_0_15a_1)); + ITEM_DIFF.put(OAK_SAPLING, andNewer(c0_0_15a_1)); + ITEM_DIFF.put(OAK_LOG, andNewer(c0_0_15a_1)); + ITEM_DIFF.put(OAK_LEAVES, andNewer(c0_0_15a_1)); + ITEM_DIFF.put(SAND, andNewer(c0_0_15a_1)); + ITEM_DIFF.put(GRAVEL, andNewer(c0_0_15a_1)); + + EXTENDED_CLASSIC_ITEMS.add(COBBLESTONE_SLAB); + EXTENDED_CLASSIC_ITEMS.add(DEAD_BUSH); + EXTENDED_CLASSIC_ITEMS.add(SANDSTONE); + EXTENDED_CLASSIC_ITEMS.add(SNOW); + EXTENDED_CLASSIC_ITEMS.add(TORCH); + EXTENDED_CLASSIC_ITEMS.add(BROWN_WOOL); + EXTENDED_CLASSIC_ITEMS.add(ICE); + EXTENDED_CLASSIC_ITEMS.add(CHISELED_QUARTZ_BLOCK); + EXTENDED_CLASSIC_ITEMS.add(NETHER_QUARTZ_ORE); + EXTENDED_CLASSIC_ITEMS.add(QUARTZ_PILLAR); + EXTENDED_CLASSIC_ITEMS.add(JUKEBOX); + EXTENDED_CLASSIC_ITEMS.add(STONE_BRICKS); + + // https://minecraft.gamepedia.com/Java_Edition_version_history + } + + public static boolean keepItem(final Item item) { + if (ProtocolHack.getTargetVersion().equals(c0_30cpe)) { + final ClientPlayNetworkHandler handler = MinecraftClient.getInstance().getNetworkHandler(); + if (handler == null) return true; + final ExtensionProtocolMetadataStorage extensionProtocol = ((IClientConnection)handler.getConnection()).viaFabricPlus$getUserConnection().get(ExtensionProtocolMetadataStorage.class); + if (extensionProtocol == null) return false; + if (extensionProtocol.hasServerExtension(ClassicProtocolExtension.CUSTOM_BLOCKS, 1) && EXTENDED_CLASSIC_ITEMS.contains(item)) { + return true; + } + } + + return !ITEM_DIFF.containsKey(item) || ITEM_DIFF.get(item).contains(ProtocolHack.getTargetVersion() /*ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(ITEM_DIFF.get(item)*/); + } + + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/fixes/diff/RecipesPre1_12.java b/src/main/java/de/florianmichael/viafabricplus/fixes/diff/RecipesPre1_12.java deleted file mode 100644 index 0e138598c..000000000 --- a/src/main/java/de/florianmichael/viafabricplus/fixes/diff/RecipesPre1_12.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus - * Copyright (C) 2021-2023 FlorianMichael/EnZaXD - * Copyright (C) 2023 RK_01/RaphiMC 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 . - */ - -package de.florianmichael.viafabricplus.fixes.diff; - -import net.minecraft.block.ConcretePowderBlock; -import net.minecraft.block.GlazedTerracottaBlock; -import net.minecraft.block.ShulkerBoxBlock; -import net.minecraft.client.MinecraftClient; -import net.minecraft.inventory.RecipeInputInventory; -import net.minecraft.item.BlockItem; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket; -import net.minecraft.recipe.*; -import net.minecraft.screen.ScreenHandler; -import net.raphimc.vialoader.util.VersionEnum; - -import java.util.List; - -/** - * Handles all recipe related stuff for versions older than 1.12. - */ -public class RecipesPre1_12 { - - /** - * Removes recipes that are not supported in 1.11 and older versions. - * - * @param recipes List of recipes - * @param version Version of the client - */ - public static void editRecipes(final List> recipes, final VersionEnum version) { - final var registryManager = MinecraftClient.getInstance().world.getRegistryManager(); - - recipes.removeIf(recipe -> { - if (recipe.getResult(registryManager).getItem() instanceof BlockItem block) { - return block.getBlock() instanceof ConcretePowderBlock || block.getBlock() instanceof GlazedTerracottaBlock; - } - return false; - }); - - if (version.isOlderThanOrEqualTo(VersionEnum.r1_11)) { - recipes.removeIf(recipe -> recipe.getResult(registryManager).getItem() == Items.IRON_NUGGET); - - if (version.isOlderThanOrEqualTo(VersionEnum.r1_10)) { - recipes.removeIf(recipe -> { - Item item = recipe.getResult(registryManager).getItem(); - if (item instanceof BlockItem blockItem) { - return blockItem.getBlock() instanceof ShulkerBoxBlock; - } else if (item == Items.OBSERVER || item == Items.IRON_NUGGET) { - return true; - } else if (item == Items.GOLD_NUGGET) { - return recipe.getSerializer() == RecipeSerializer.SMELTING; - } else { - return false; - } - }); - } - - if (version.isOlderThanOrEqualTo(VersionEnum.r1_9_3tor1_9_4)) { - recipes.removeIf(recipe -> recipe.getResult(registryManager).getItem() == Items.BONE_BLOCK); - } - } - } - - /** - * Sets the result slot of a crafting screen handler to the correct item stack. In MC <= 1.11.2 the result slot - * is not updated when the input slots change, so we need to update it manually, Spigot and Paper re-syncs the slot, - * so we don't notice this bug on servers that use Spigot or Paper - * - * @param syncId The sync id of the screen handler - * @param screenHandler The screen handler - * @param inventory The inventory of the screen handler - */ - public static void setCraftingResultSlot(final int syncId, final ScreenHandler screenHandler, final RecipeInputInventory inventory) { - final var network = MinecraftClient.getInstance().getNetworkHandler(); - if (network == null) return; - - final var world = MinecraftClient.getInstance().world; - - final var result = network.getRecipeManager(). - getFirstMatch(RecipeType.CRAFTING, inventory, world). // Get the first matching recipe - map(recipe -> recipe.value().craft(inventory, world.getRegistryManager())). // Craft the recipe to get the result - orElse(ItemStack.EMPTY); // If there is no recipe, set the result to air - - // Update the result slot - network.onScreenHandlerSlotUpdate(new ScreenHandlerSlotUpdateS2CPacket(syncId, screenHandler.getRevision(), 0, result)); - } -} diff --git a/src/main/java/de/florianmichael/viafabricplus/fixes/diff/RenderableGlyphDiff.java b/src/main/java/de/florianmichael/viafabricplus/fixes/diff/RenderableGlyphDiff.java new file mode 100644 index 000000000..f6cdd3e84 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/fixes/diff/RenderableGlyphDiff.java @@ -0,0 +1,982 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.fixes.diff; + +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.ints.IntConsumer; +import net.raphimc.vialoader.util.VersionEnum; + +import static java.util.stream.IntStream.rangeClosed; +import static net.raphimc.vialoader.util.VersionEnum.*; + +public class RenderableGlyphDiff { + + private static final Int2ObjectMap RENDERABLE_GLYPH_DIFF_LEGACY = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap RENDERABLE_GLYPH_DIFF = new Int2ObjectOpenHashMap<>(); + + static { + rangeClosed(0, 887).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(890, 894).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(900, 906).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(908, c0_0_15a_1); + rangeClosed(910, 929).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(931, 1315).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(1329, 1366).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(1369, 1418).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(1423, c0_0_15a_1); + rangeClosed(1425, 1479).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(1488, 1514).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(1520, 1524).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(1536, 1539).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(1542, 1563).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(1566, 1567).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(1569, 1630).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(1632, 1805).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(1807, 1866).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(1869, 1969).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(1984, 2042).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2305, 2361).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2364, 2381).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2384, 2388).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2392, 2418).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2427, 2431).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2433, 2435).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2437, 2444).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2447, 2448).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2451, 2472).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2474, 2480).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(2482, c0_0_15a_1); + rangeClosed(2486, 2489).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2492, 2500).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2503, 2504).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2507, 2510).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(2519, c0_0_15a_1); + rangeClosed(2524, 2525).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2527, 2531).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2534, 2554).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2561, 2563).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2565, 2570).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2575, 2576).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2579, 2600).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2602, 2608).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2610, 2611).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2613, 2614).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2616, 2617).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(2620, c0_0_15a_1); + rangeClosed(2622, 2626).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2631, 2632).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2635, 2637).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(2641, c0_0_15a_1); + rangeClosed(2649, 2652).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(2654, c0_0_15a_1); + rangeClosed(2662, 2677).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2689, 2691).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2693, 2701).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2703, 2705).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2707, 2728).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2730, 2736).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2738, 2739).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2741, 2745).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2748, 2757).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2759, 2761).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2763, 2765).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(2768, c0_0_15a_1); + rangeClosed(2784, 2787).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2790, 2799).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(2801, c0_0_15a_1); + rangeClosed(2817, 2819).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2821, 2828).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2831, 2832).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2835, 2856).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2858, 2864).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2866, 2867).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2869, 2873).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2876, 2884).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2887, 2888).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2891, 2893).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2902, 2903).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2908, 2909).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2911, 2915).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2918, 2929).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2946, 2947).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2949, 2954).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2958, 2960).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2962, 2965).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2969, 2970).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(2972, c0_0_15a_1); + rangeClosed(2974, 2975).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2979, 2980).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2984, 2986).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(2990, 3001).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3006, 3010).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3014, 3016).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3018, 3021).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(3024, c0_0_15a_1); + RENDERABLE_GLYPH_DIFF_LEGACY.put(3031, c0_0_15a_1); + rangeClosed(3046, 3066).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3073, 3075).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3077, 3084).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3086, 3088).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3090, 3112).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3114, 3123).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3125, 3129).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3133, 3140).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3142, 3144).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3146, 3149).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3157, 3158).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3160, 3161).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3168, 3171).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3174, 3183).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3192, 3199).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3202, 3203).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3205, 3212).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3214, 3216).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3218, 3240).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3242, 3251).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3253, 3257).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3260, 3268).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3270, 3272).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3274, 3277).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3285, 3286).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(3294, c0_0_15a_1); + rangeClosed(3296, 3299).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3302, 3311).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3313, 3314).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3330, 3331).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3333, 3340).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3342, 3344).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3346, 3368).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3370, 3385).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3389, 3396).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3398, 3400).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3402, 3405).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(3415, c0_0_15a_1); + rangeClosed(3424, 3427).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3430, 3445).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3449, 3455).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3458, 3459).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3461, 3478).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3482, 3505).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3507, 3515).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(3517, c0_0_15a_1); + rangeClosed(3520, 3526).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(3530, c0_0_15a_1); + rangeClosed(3535, 3540).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(3542, c0_0_15a_1); + rangeClosed(3544, 3551).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3570, 3572).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3585, 3642).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3647, 3675).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3713, 3714).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(3716, c0_0_15a_1); + rangeClosed(3719, 3720).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(3722, c0_0_15a_1); + RENDERABLE_GLYPH_DIFF_LEGACY.put(3725, c0_0_15a_1); + rangeClosed(3732, 3735).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3737, 3743).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3745, 3747).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(3749, c0_0_15a_1); + RENDERABLE_GLYPH_DIFF_LEGACY.put(3751, c0_0_15a_1); + rangeClosed(3754, 3755).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3757, 3769).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3771, 3773).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3776, 3780).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(3782, c0_0_15a_1); + rangeClosed(3784, 3789).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3792, 3801).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3804, 3805).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3840, 3911).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3913, 3948).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3953, 3979).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3984, 3991).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(3993, 4028).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4030, 4044).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4046, 4052).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4096, 4249).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4254, 4293).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4304, 4348).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4352, 4441).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4447, 4514).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4520, 4601).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4608, 4680).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4682, 4685).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4688, 4694).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(4696, c0_0_15a_1); + rangeClosed(4698, 4701).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4704, 4744).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4746, 4749).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4752, 4784).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4786, 4789).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4792, 4798).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(4800, c0_0_15a_1); + rangeClosed(4802, 4805).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4808, 4822).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4824, 4880).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4882, 4885).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4888, 4954).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4959, 4988).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(4992, 5017).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(5024, 5108).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(5121, 5750).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(5760, 5788).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(5792, 5880).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(5888, 5900).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(5902, 5908).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(5920, 5942).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(5952, 5971).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(5984, 5996).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(5998, 6000).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(6002, 6003).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(6016, 6109).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(6112, 6121).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(6128, 6137).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(6144, 6158).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(6160, 6169).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(6176, 6263).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(6272, 6314).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(6400, 6428).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(6432, 6443).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(6448, 6459).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(6464, c0_0_15a_1); + rangeClosed(6468, 6509).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(6512, 6516).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(6528, 6569).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(6576, 6601).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(6608, 6617).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(6622, 6683).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(6686, 6687).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(6912, 6987).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(6992, 7036).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(7040, 7082).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(7086, 7097).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(7168, 7223).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(7227, 7241).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(7245, 7295).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(7424, 7654).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(7678, 7957).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(7960, 7965).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(7968, 8005).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(8008, 8013).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(8016, 8023).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(8025, c0_0_15a_1); + RENDERABLE_GLYPH_DIFF_LEGACY.put(8027, c0_0_15a_1); + RENDERABLE_GLYPH_DIFF_LEGACY.put(8029, c0_0_15a_1); + rangeClosed(8031, 8061).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(8064, 8116).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(8118, 8132).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(8134, 8147).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(8150, 8155).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(8157, 8175).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(8178, 8180).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(8182, 8190).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(8192, 8292).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(8298, 8305).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(8308, 8334).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(8336, 8340).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(8352, 8373).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(8381, c0_0_15a_1); + rangeClosed(8400, 8432).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(8448, 8527).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(8531, 8584).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(8592, 9143).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(9145, 9191).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(9193, 9194).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(9197, 9199).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(9204, 9213).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(9216, 9254).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(9280, 9290).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(9312, 9885).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(9888, 9916).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(9920, 9923).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(9935, c0_0_15a_1); + RENDERABLE_GLYPH_DIFF_LEGACY.put(9960, c0_0_15a_1); + rangeClosed(9985, 9988).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(9990, 9993).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(9996, 10023).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(10025, 10061).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(10063, 10066).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(10070, c0_0_15a_1); + rangeClosed(10072, 10078).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(10081, 10132).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(10136, 10159).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(10161, 10174).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(10176, 10186).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(10188, c0_0_15a_1); + rangeClosed(10192, 11084).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(11088, 11092).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(11096, c0_0_15a_1); + rangeClosed(11264, 11310).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(11312, 11358).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(11360, 11375).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(11377, 11389).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(11392, 11498).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(11513, 11557).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(11568, 11621).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(11631, c0_0_15a_1); + rangeClosed(11648, 11670).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(11680, 11686).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(11688, 11694).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(11696, 11702).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(11704, 11710).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(11712, 11718).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(11720, 11726).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(11728, 11734).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(11736, 11742).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(11744, 11824).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(11829, c0_0_15a_1); + RENDERABLE_GLYPH_DIFF_LEGACY.put(11832, c0_0_15a_1); + RENDERABLE_GLYPH_DIFF_LEGACY.put(11841, c0_0_15a_1); + RENDERABLE_GLYPH_DIFF_LEGACY.put(11851, c0_0_15a_1); + rangeClosed(11904, 11929).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(11931, 12019).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(12032, 12245).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(12272, 12283).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(12288, 12351).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(12353, 12438).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(12441, 12543).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(12549, 12589).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(12593, 12686).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(12688, 12727).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(12736, 12771).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(12784, 12830).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(12832, 12867).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(12880, 13054).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(13056, 19893).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(19904, 40899).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(40960, 42124).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(42128, 42182).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(42240, 42539).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(42560, 42591).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(42594, 42611).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(42620, 42647).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(42752, 42892).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(42928, c0_0_15a_1); + rangeClosed(43003, 43051).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(43072, 43127).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(43136, 43204).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(43214, 43225).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(43264, 43347).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(43359, c0_0_15a_1); + rangeClosed(43520, 43574).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(43584, 43597).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(43600, 43609).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(43612, 43615).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(44032, 55203).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(63744, 64045).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(64048, 64106).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(64112, 64217).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(64256, 64262).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(64275, 64279).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(64285, 64310).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(64312, 64316).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(64318, c0_0_15a_1); + rangeClosed(64320, 64321).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(64323, 64324).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(64326, 64433).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(64467, 64831).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(64848, 64911).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(64914, 64967).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(64976, 65021).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(65024, 65049).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(65056, 65062).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(65072, 65106).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(65108, 65126).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(65128, 65131).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(65136, 65140).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(65142, 65276).forEach(putLegacy(c0_0_15a_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(65279, c0_0_15a_1); + rangeClosed(65281, 65470).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(65474, 65479).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(65482, 65487).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(65490, 65495).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(65498, 65500).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(65504, 65510).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(65512, 65518).forEach(putLegacy(c0_0_15a_1)); + rangeClosed(65529, 65535).forEach(putLegacy(c0_0_15a_1)); + + rangeClosed(1316, 1327).forEach(putLegacy(r1_16)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(4295, r1_16); + RENDERABLE_GLYPH_DIFF_LEGACY.put(4301, r1_16); + rangeClosed(4349, 4351).forEach(putLegacy(r1_16)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(8382, r1_16); + RENDERABLE_GLYPH_DIFF_LEGACY.put(9924, r1_16); + RENDERABLE_GLYPH_DIFF_LEGACY.put(9928, r1_16); + rangeClosed(11390, 11391).forEach(putLegacy(r1_16)); + rangeClosed(42900, 42901).forEach(putLegacy(r1_16)); + rangeClosed(42920, 42921).forEach(putLegacy(r1_16)); + rangeClosed(42927, 42927).forEach(putLegacy(r1_16)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(42948, r1_16); + RENDERABLE_GLYPH_DIFF_LEGACY.put(42950, r1_16); + rangeClosed(43856, 43857).forEach(putLegacy(r1_16)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(43875, r1_16); + rangeClosed(66352, 66378).forEach(putLegacy(r1_16)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(127754, r1_16); + RENDERABLE_GLYPH_DIFF_LEGACY.put(127783, r1_16); + RENDERABLE_GLYPH_DIFF_LEGACY.put(128293, r1_16); + + rangeClosed(8528, 8530).forEach(putLegacy(r1_16_2)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(8585, r1_16_2); + rangeClosed(11242, 11243).forEach(putLegacy(r1_16_2)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(127907, r1_16_2); + RENDERABLE_GLYPH_DIFF_LEGACY.put(127993, r1_16_2); + RENDERABLE_GLYPH_DIFF_LEGACY.put(128305, r1_16_2); + RENDERABLE_GLYPH_DIFF_LEGACY.put(128481, r1_16_2); + RENDERABLE_GLYPH_DIFF_LEGACY.put(128737, r1_16_2); + RENDERABLE_GLYPH_DIFF_LEGACY.put(129514, r1_16_2); + RENDERABLE_GLYPH_DIFF_LEGACY.put(129683, r1_16_2); + + rangeClosed(8374, 8380).forEach(putLegacy(r1_17_1)); + RENDERABLE_GLYPH_DIFF_LEGACY.put(8383, r1_17_1); + RENDERABLE_GLYPH_DIFF_LEGACY.put(9203, r1_17_1); + RENDERABLE_GLYPH_DIFF_LEGACY.put(127830, r1_17_1); + RENDERABLE_GLYPH_DIFF_LEGACY.put(128276, r1_17_1); + RENDERABLE_GLYPH_DIFF_LEGACY.put(129699, r1_17_1); + + // 1.20 switch to using Unihex as a main font + + rangeClosed(0, 2559).forEach(put(r1_20tor1_20_1)); + rangeClosed(2561, 55295).forEach(put(r1_20tor1_20_1)); + rangeClosed(61425, 61426).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(61429, r1_20tor1_20_1); + rangeClosed(63744, 65533).forEach(put(r1_20tor1_20_1)); + rangeClosed(65536, 72543).forEach(put(r1_20tor1_20_1)); + rangeClosed(72704, 73727).forEach(put(r1_20tor1_20_1)); + rangeClosed(74650, 74751).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(74863, r1_20tor1_20_1); + rangeClosed(74869, 74879).forEach(put(r1_20tor1_20_1)); + rangeClosed(75076, 77823).forEach(put(r1_20tor1_20_1)); + rangeClosed(78895, 82943).forEach(put(r1_20tor1_20_1)); + rangeClosed(83527, 92159).forEach(put(r1_20tor1_20_1)); + rangeClosed(92729, 94207).forEach(put(r1_20tor1_20_1)); + rangeClosed(100344, 100351).forEach(put(r1_20tor1_20_1)); + rangeClosed(101120, 101631).forEach(put(r1_20tor1_20_1)); + rangeClosed(101641, 128124).forEach(put(r1_20tor1_20_1)); + rangeClosed(128126, 131069).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(131083, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(131207, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(131209, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(131234, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(131236, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(131276, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(131428, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(131490, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(131603, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(131883, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(131953, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(131969, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(132089, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(132170, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(132361, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(132566, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(132648, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(132726, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(132943, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(133127, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(133178, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(133305, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(133500, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(133533, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(133843, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(133917, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(134047, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(134352, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(134469, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(134625, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(134756, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(134765, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(134805, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(135007, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(135359, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(135681, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(135741, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(135765, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(135796, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(135803, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(135895, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(135908, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(135933, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(135963, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(135990, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(136004, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(136090, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(136132, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(136211, r1_20tor1_20_1); + rangeClosed(136301, 136302).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(136663, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(136775, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(136884, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(136966, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(137026, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(137405, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(137667, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(138326, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(138541, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(138565, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(138594, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(138616, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(138642, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(138652, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(138657, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(138679, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(138720, r1_20tor1_20_1); + rangeClosed(138803, 138804).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(139038, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(139126, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(139258, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(139643, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(139800, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(140062, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(140205, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(141043, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(141403, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(141483, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(141711, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(142008, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(142150, r1_20tor1_20_1); + rangeClosed(142159, 142160).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(142246, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(142365, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(142372, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(142817, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(143798, r1_20tor1_20_1); + rangeClosed(143811, 143812).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(143861, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(144242, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(144336, r1_20tor1_20_1); + rangeClosed(144338, 144339).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(144341, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(144346, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(144351, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(144356, r1_20tor1_20_1); + rangeClosed(144458, 144459).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(144465, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(144485, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(144612, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(144730, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(144788, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(144836, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(144843, r1_20tor1_20_1); + rangeClosed(144952, 144954).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(144967, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(145164, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(145180, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(145215, r1_20tor1_20_1); + rangeClosed(145251, 145252).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(145383, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(145407, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(145444, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(145469, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(146072, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(146559, r1_20tor1_20_1); + rangeClosed(146583, 146584).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(146686, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(146688, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(146702, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(146752, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(146899, r1_20tor1_20_1); + rangeClosed(146937, 146938).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(146979, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(147326, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(147606, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(147715, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(147910, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(147966, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(147982, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(148412, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(149033, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(149157, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(149489, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(149654, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(149737, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(149979, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(150017, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(150093, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(150141, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(150217, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(150358, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(150383, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(150550, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(150804, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(151054, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(151095, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(151146, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(151179, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(151626, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(151637, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(151842, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(151977, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(152013, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(152037, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(152094, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(152140, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(152622, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(152718, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(152793, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(152846, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(152882, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(152930, r1_20tor1_20_1); + rangeClosed(152999, 153000).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(153457, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(153513, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(153524, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(154052, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(154068, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(154327, r1_20tor1_20_1); + rangeClosed(154339, 154340).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(154353, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(154546, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(154699, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(154724, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(155041, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(155182, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(155209, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(155222, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(155234, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(155237, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(155330, r1_20tor1_20_1); + rangeClosed(155351, 155352).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(155368, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(155427, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(155484, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(155604, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(155616, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(155643, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(155660, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(155671, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(155744, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(155885, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(156193, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(156272, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(156294, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(156492, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(156674, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(156813, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(157302, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(157310, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(157360, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(157469, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(157564, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(157917, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(157930, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(158033, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(158063, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(158173, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(158238, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(158296, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(158348, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(158391, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(158463, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(158556, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(158753, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(158761, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(158835, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(158941, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(159296, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(159333, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(159636, r1_20tor1_20_1); + rangeClosed(159734, 159736).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(159988, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(160013, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(160057, r1_20tor1_20_1); + rangeClosed(160730, 160731).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(160766, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(160784, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(160841, r1_20tor1_20_1); + rangeClosed(161300, 161301).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(161329, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(161412, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(161427, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(161550, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(161571, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(161618, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(161970, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(162181, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(162436, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(162739, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(162750, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(162759, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(163000, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(163232, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(163344, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(163503, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(163767, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(163833, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(163978, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(164027, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(164471, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(164482, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(164595, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(164813, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(164872, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(164876, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(164949, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(165227, r1_20tor1_20_1); + rangeClosed(165320, 165321).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(165496, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(165525, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(165591, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(165626, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(165856, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166214, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166217, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166251, r1_20tor1_20_1); + rangeClosed(166279, 166280).forEach(put(r1_20tor1_20_1)); + rangeClosed(166330, 166331).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(166336, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166415, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166430, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166441, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166467, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166513, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166553, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166605, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166621, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166628, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166726, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166729, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166734, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166849, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166895, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166983, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166991, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166993, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(166996, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(167184, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(167281, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(167419, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(167439, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(167455, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(167478, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(167561, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(167577, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(167659, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(167730, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(167928, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(168608, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(168625, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(169104, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(169423, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(169599, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(169712, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(169753, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(169808, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(170000, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(170182, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(170610, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(171477, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(171483, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(171541, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(171581, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(171593, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(171658, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(171716, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(171739, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(171753, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(171902, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(171907, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(171916, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(171982, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(172058, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(172079, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(172162, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(172281, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(172432, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(172940, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(173111, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(173553, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(173570, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(173594, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(173746, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(174045, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(174141, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(174331, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(174359, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(174640, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(174646, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(174680, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(176034, r1_20tor1_20_1); + rangeClosed(176423, 176424).forEach(put(r1_20tor1_20_1)); + rangeClosed(176439, 176440).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(176621, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(176896, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(176995, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(177007, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(177010, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(177021, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(177156, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(177168, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(177171, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(177249, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(177383, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(177391, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(177398, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(177401, r1_20tor1_20_1); + rangeClosed(177421, 177422).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(177462, r1_20tor1_20_1); + rangeClosed(177582, 177583).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(177587, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(177639, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(177652, r1_20tor1_20_1); + rangeClosed(177692, 177693).forEach(put(r1_20tor1_20_1)); + rangeClosed(177702, 177704).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(177706, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(177708, r1_20tor1_20_1); + rangeClosed(177813, 177814).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(177837, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(177901, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(178089, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(178117, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(178150, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(178167, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(178169, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(178172, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(178182, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(178186, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(178204, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(178360, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(178840, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(178887, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(179039, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(179042, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(179068, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(179075, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(179227, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(179575, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(179591, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(179703, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(179753, r1_20tor1_20_1); + rangeClosed(180265, 180266).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(180393, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(180426, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(180693, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(180697, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(180729, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(180860, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(180872, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(180900, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(181015, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(181083, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(181089, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(181092, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(181384, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(181396, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(181399, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(181570, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(181643, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(181779, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(181784, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(181793, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(181801, r1_20tor1_20_1); + rangeClosed(181803, 181805).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(181807, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(181826, r1_20tor1_20_1); + rangeClosed(181834, 181835).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(182060, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(182063, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(182175, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(182209, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(182252, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(182269, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(182489, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(182494, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(182497, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(182515, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(182535, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(182538, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(182557, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(182786, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(182798, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(182909, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(182953, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(182994, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183081, r1_20tor1_20_1); + rangeClosed(183085, 183086).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(183089, r1_20tor1_20_1); + rangeClosed(183096, 183097).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(183099, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183103, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183105, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183114, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183118, r1_20tor1_20_1); + rangeClosed(183130, 183131).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(183140, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183145, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183148, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183151, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183155, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183158, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183160, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183164, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183217, r1_20tor1_20_1); + rangeClosed(183231, 183232).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(183246, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183382, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183391, r1_20tor1_20_1); + rangeClosed(183541, 183542).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(183549, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183551, r1_20tor1_20_1); + rangeClosed(183554, 183555).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(183562, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183688, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183691, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183693, r1_20tor1_20_1); + rangeClosed(183695, 183696).forEach(put(r1_20tor1_20_1)); + rangeClosed(183711, 183712).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(183720, r1_20tor1_20_1); + rangeClosed(183725, 183726).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(183765, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183832, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183834, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183843, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183846, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183850, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183932, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183944, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(183955, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(185218, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(185668, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(194692, r1_20tor1_20_1); + RENDERABLE_GLYPH_DIFF.put(194742, r1_20tor1_20_1); + rangeClosed(200413, 200414).forEach(put(r1_20tor1_20_1)); + RENDERABLE_GLYPH_DIFF.put(200812, r1_20tor1_20_1); + rangeClosed(917504, 917631).forEach(put(r1_20tor1_20_1)); + rangeClosed(917760, 917999).forEach(put(r1_20tor1_20_1)); + rangeClosed(1048574, 1048575).forEach(put(r1_20tor1_20_1)); + } + + public static boolean isGlyphRenderable(final int codePoint) { + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(r1_20tor1_20_1)) { + return RENDERABLE_GLYPH_DIFF.containsKey(codePoint) && ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(RENDERABLE_GLYPH_DIFF.get(codePoint)); + } + + return RENDERABLE_GLYPH_DIFF_LEGACY.containsKey(codePoint) && ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(RENDERABLE_GLYPH_DIFF_LEGACY.get(codePoint)); + } + + private static IntConsumer putLegacy(final VersionEnum version) { + return i -> RENDERABLE_GLYPH_DIFF_LEGACY.put(i, version); + } + + private static IntConsumer put(final VersionEnum version) { + return i -> RENDERABLE_GLYPH_DIFF.put(i, version); + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/fixes/recipe/AddBannerPatternRecipe.java b/src/main/java/de/florianmichael/viafabricplus/fixes/recipe/AddBannerPatternRecipe.java new file mode 100644 index 000000000..af592b52a --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/fixes/recipe/AddBannerPatternRecipe.java @@ -0,0 +1,183 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.fixes.recipe; + +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.minecraft.block.entity.BannerBlockEntity; +import net.minecraft.inventory.RecipeInputInventory; +import net.minecraft.item.BannerItem; +import net.minecraft.item.DyeItem; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtList; +import net.minecraft.recipe.RecipeSerializer; +import net.minecraft.recipe.SpecialCraftingRecipe; +import net.minecraft.recipe.SpecialRecipeSerializer; +import net.minecraft.recipe.book.CraftingRecipeCategory; +import net.minecraft.registry.DynamicRegistryManager; +import net.minecraft.util.DyeColor; +import net.minecraft.world.World; +import net.raphimc.vialoader.util.VersionEnum; + +public class AddBannerPatternRecipe extends SpecialCraftingRecipe { + + public static final RecipeSerializer SERIALIZER = new SpecialRecipeSerializer<>(AddBannerPatternRecipe::new); + + public AddBannerPatternRecipe(CraftingRecipeCategory craftingRecipeCategory) { + super(craftingRecipeCategory); + } + + @Override + public boolean matches(RecipeInputInventory inv, World world) { + boolean foundBanner = false; + for (int i = 0; i < inv.size(); i++) { + ItemStack stack = inv.getStack(i); + if (stack.getItem() instanceof BannerItem) { + if (foundBanner) + return false; + if (BannerBlockEntity.getPatternCount(stack) >= 6) + return false; + foundBanner = true; + } + } + return foundBanner && getBannerPattern(inv) != null; + } + + @Override + public ItemStack craft(RecipeInputInventory inv, DynamicRegistryManager registryManager) { + ItemStack result = ItemStack.EMPTY; + + for (int i = 0; i < inv.size(); i++) { + ItemStack stack = inv.getStack(i); + if (!stack.isEmpty() && stack.getItem() instanceof BannerItem) { + result = stack.copy(); + result.setCount(1); + break; + } + } + + BannerPattern_1_13_2 pattern = getBannerPattern(inv); + if (pattern != null) { + DyeColor color = ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_12_2) ? DyeColor.BLACK : DyeColor.WHITE; + for (int i = 0; i < inv.size(); i++) { + Item item = inv.getStack(i).getItem(); + if (item instanceof DyeItem dyeItem) { + color = dyeItem.getColor(); + } + } + + NbtCompound tileEntityNbt = result.getOrCreateSubNbt("BlockEntityTag"); + NbtList patterns; + if (tileEntityNbt.contains("Patterns", 9)) { + patterns = tileEntityNbt.getList("Patterns", 10); + } else { + patterns = new NbtList(); + tileEntityNbt.put("Patterns", patterns); + } + NbtCompound patternNbt = new NbtCompound(); + patternNbt.putString("Pattern", pattern.getId()); + patternNbt.putInt("Color", color.getId()); + patterns.add(patternNbt); + } + + return result; + } + + @Override + public boolean fits(int width, int height) { + return width >= 3 && height >= 3; + } + + @Override + public RecipeSerializer getSerializer() { + return SERIALIZER; + } + + private static BannerPattern_1_13_2 getBannerPattern(RecipeInputInventory inv) { + for (BannerPattern_1_13_2 pattern : BannerPattern_1_13_2.values()) { + if (!pattern.isCraftable()) + continue; + + boolean matches = true; + if (pattern.hasBaseStack()) { + boolean foundBaseItem = false; + boolean foundDye = false; + for (int i = 0; i < inv.size(); i++) { + ItemStack stack = inv.getStack(i); + if (!stack.isEmpty() && !(stack.getItem() instanceof BannerItem)) { + if (stack.getItem() instanceof DyeItem) { + if (foundDye) { + matches = false; + break; + } + foundDye = true; + } else { + if (foundBaseItem || !(!stack.isEmpty() && ItemStack.areItemsEqual(stack, pattern.getBaseStack()))) { + matches = false; + break; + } + foundBaseItem = true; + } + } + } + if (!foundBaseItem || (!foundDye && ProtocolHack.getTargetVersion().isNewerThan(VersionEnum.r1_10))) matches = false; + } else if (inv.size() == pattern.getRecipePattern().length * pattern.getRecipePattern()[0].length()) { + DyeColor patternColor = null; + for (int i = 0; i < inv.size(); i++) { + int row = i / 3; + int col = i % 3; + ItemStack stack = inv.getStack(i); + Item item = stack.getItem(); + if (!stack.isEmpty() && !(item instanceof BannerItem)) { + if (!(item instanceof DyeItem)) { + matches = false; + break; + } + + DyeColor color = ((DyeItem) item).getColor(); + if (patternColor != null && color != patternColor) { + matches = false; + break; + } + + if (pattern.getRecipePattern()[row].charAt(col) == ' ') { + matches = false; + break; + } + + patternColor = color; + } else if (pattern.getRecipePattern()[row].charAt(col) != ' ') { + matches = false; + break; + } + } + } else { + matches = false; + } + + if (matches) + return pattern; + } + + return null; + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/fixes/recipe/BannerPattern_1_13_2.java b/src/main/java/de/florianmichael/viafabricplus/fixes/recipe/BannerPattern_1_13_2.java new file mode 100644 index 000000000..4c50734b8 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/fixes/recipe/BannerPattern_1_13_2.java @@ -0,0 +1,112 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.fixes.recipe; + +import net.minecraft.block.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; + +// safe from vanilla modification + removal of recipes +public enum BannerPattern_1_13_2 { + + BASE("b"), + SQUARE_BOTTOM_LEFT("bl", " ", " ", "# "), + SQUARE_BOTTOM_RIGHT("br", " ", " ", " #"), + SQUARE_TOP_LEFT("tl", "# ", " ", " "), + SQUARE_TOP_RIGHT("tr", " #", " ", " "), + STRIPE_BOTTOM("bs", " ", " ", "###"), + STRIPE_TOP("ts", "###", " ", " "), + STRIPE_LEFT("ls", "# ", "# ", "# "), + STRIPE_RIGHT("rs", " #", " #", " #"), + STRIPE_CENTER("cs", " # ", " # ", " # "), + STRIPE_MIDDLE("ms", " ", "###", " "), + STRIPE_DOWNRIGHT("drs", "# ", " # ", " #"), + STRIPE_DOWNLEFT("dls", " #", " # ", "# "), + STRIPE_SMALL("ss", "# #", "# #", " "), + CROSS("cr", "# #", " # ", "# #"), + STRAIGHT_CROSS("sc", " # ", "###", " # "), + TRIANGLE_BOTTOM("bt", " ", " # ", "# #"), + TRIANGLE_TOP("tt", "# #", " # ", " "), + TRIANGLES_BOTTOM("bts", " ", "# #", " # "), + TRIANGLES_TOP("tts", " # ", "# #", " "), + DIAGONAL_LEFT("ld", "## ", "# ", " "), + DIAGONAL_RIGHT("rd", " ", " #", " ##"), + DIAGONAL_LEFT_MIRROR("lud", " ", "# ", "## "), + DIAGONAL_RIGHT_MIRROR("rud", " ##", " #", " "), + CIRCLE_MIDDLE("mc", " ", " # ", " "), + RHOMBUS_MIDDLE("mr", " # ", "# #", " # "), + HALF_VERTICAL("vh", "## ", "## ", "## "), + HALF_HORIZONTAL("hh", "###", "###", " "), + HALF_VERTICAL_MIRROR("vhr", " ##", " ##", " ##"), + HALF_HORIZONTAL_MIRROR("hhb", " ", "###", "###"), + BORDER("bo", "###", "# #", "###"), + CURLY_BORDER("cbo", new ItemStack(Blocks.VINE)), + GRADIENT("gra", "# #", " # ", " # "), + GRADIENT_UP("gru", " # ", " # ", "# #"), + BRICKS("bri", new ItemStack(Blocks.BRICKS)), + GLOBE("glb"), + CREEPER("cre", new ItemStack(Items.CREEPER_HEAD)), + SKULL("sku", new ItemStack(Items.WITHER_SKELETON_SKULL)), + FLOWER("flo", new ItemStack(Blocks.OXEYE_DAISY)), + MOJANG("moj", new ItemStack(Items.ENCHANTED_GOLDEN_APPLE)); + + private final String id; + private final String[] recipePattern; + private ItemStack baseStack; + + BannerPattern_1_13_2(String id) { + this.recipePattern = new String[3]; + this.baseStack = ItemStack.EMPTY; + this.id = id; + } + + BannerPattern_1_13_2(String id, ItemStack baseStack) { + this(id); + this.baseStack = baseStack; + } + + BannerPattern_1_13_2(String id, String recipe1, String recipe2, String recipe3) { + this(id); + this.recipePattern[0] = recipe1; + this.recipePattern[1] = recipe2; + this.recipePattern[2] = recipe3; + } + + public String getId() { + return this.id; + } + + public boolean isCraftable() { + return !this.baseStack.isEmpty() || this.recipePattern[0] != null; + } + + public boolean hasBaseStack() { + return !this.baseStack.isEmpty(); + } + + public ItemStack getBaseStack() { + return this.baseStack; + } + + public String[] getRecipePattern() { + return this.recipePattern; + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/fixes/recipe/RecipeInfo.java b/src/main/java/de/florianmichael/viafabricplus/fixes/recipe/RecipeInfo.java new file mode 100644 index 000000000..7b868e6ec --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/fixes/recipe/RecipeInfo.java @@ -0,0 +1,217 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.fixes.recipe; + +import net.minecraft.item.ItemConvertible; +import net.minecraft.item.ItemStack; +import net.minecraft.recipe.*; +import net.minecraft.recipe.book.CookingRecipeCategory; +import net.minecraft.recipe.book.CraftingRecipeCategory; +import net.minecraft.util.Identifier; +import net.minecraft.util.collection.DefaultedList; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.function.Supplier; + +public final class RecipeInfo> { + + private final Supplier> creator; + private final RecipeSerializer recipeType; + private final ItemStack output; + private String distinguisher = ""; + + private RecipeInfo(Supplier> creator, RecipeSerializer recipeType, ItemStack output) { + this.creator = creator; + this.recipeType = recipeType; + this.output = output; + } + + public static > RecipeInfo of(Supplier> creator, RecipeSerializer recipeType, ItemStack output) { + return new RecipeInfo<>(creator, recipeType, output); + } + + public static > RecipeInfo of(Supplier> creator, RecipeSerializer recipeType, ItemConvertible output) { + return of(creator, recipeType, new ItemStack(output)); + } + + public static > RecipeInfo of(Supplier> creator, RecipeSerializer recipeType, ItemConvertible output, int count) { + return of(creator, recipeType, new ItemStack(output, count)); + } + + public static RecipeInfo shaped(ItemStack output, Object... args) { + return shaped("", output, args); + } + + public static RecipeInfo shaped(ItemConvertible output, Object... args) { + return shaped("", output, args); + } + + public static RecipeInfo shaped(int count, ItemConvertible output, Object... args) { + return shaped("", count, output, args); + } + + public static RecipeInfo shaped(String group, ItemStack output, Object... args) { + int i; + int width = 0; + List shape = new ArrayList<>(); + for (i = 0; i < args.length && args[i] instanceof String str; i++) { + if (i == 0) + width = str.length(); + else if (str.length() != width) + throw new IllegalArgumentException("Rows do not have consistent width"); + shape.add(str); + } + var legend = new HashMap(); + while (i < args.length && args[i] instanceof Character key) { + i++; + List items = new ArrayList<>(); + for (; i < args.length && args[i] instanceof ItemConvertible; i++) { + items.add((ItemConvertible) args[i]); + } + legend.put(key, Ingredient.ofItems(items.toArray(new ItemConvertible[0]))); + } + if (i != args.length) + throw new IllegalArgumentException("Unexpected argument at index " + i + ": " + args[i]); + + int height = shape.size(); + DefaultedList ingredients = DefaultedList.of(); + for (String row : shape) { + for (int x = 0; x < width; x++) { + char key = row.charAt(x); + Ingredient ingredient = legend.get(key); + if (ingredient == null) { + if (key == ' ') + ingredient = Ingredient.EMPTY; + else + throw new IllegalArgumentException("Unknown character in shape: " + key); + } + ingredients.add(ingredient); + } + } + + final int width_f = width; + return new RecipeInfo<>(() -> new ShapedRecipe(group, CraftingRecipeCategory.MISC, width_f, height, ingredients, output), RecipeSerializer.SHAPED, output); + } + + public static RecipeInfo shaped(String group, ItemConvertible output, Object... args) { + return shaped(group, new ItemStack(output), args); + } + + public static RecipeInfo shaped(String group, int count, ItemConvertible output, Object... args) { + return shaped(group, new ItemStack(output, count), args); + } + + public static RecipeInfo shapeless(String group, ItemStack output, ItemConvertible... inputs) { + ItemConvertible[][] newInputs = new ItemConvertible[inputs.length][1]; + for (int i = 0; i < inputs.length; i++) + newInputs[i] = new ItemConvertible[]{inputs[i]}; + return shapeless(group, output, newInputs); + } + + public static RecipeInfo shapeless(String group, ItemConvertible output, ItemConvertible... inputs) { + return shapeless(group, new ItemStack(output), inputs); + } + + public static RecipeInfo shapeless(String group, int count, ItemConvertible output, ItemConvertible... inputs) { + return shapeless(group, new ItemStack(output, count), inputs); + } + + public static RecipeInfo shapeless(String group, ItemStack output, ItemConvertible[]... inputs) { + DefaultedList ingredients = DefaultedList.of(); + for (ItemConvertible[] input : inputs) { + ingredients.add(Ingredient.ofItems(input)); + } + return new RecipeInfo<>(() -> new ShapelessRecipe(group, CraftingRecipeCategory.MISC, output, ingredients), RecipeSerializer.SHAPELESS, output); + } + + public static RecipeInfo shapeless(String group, ItemConvertible output, ItemConvertible[]... inputs) { + return shapeless(group, new ItemStack(output), inputs); + } + + public static RecipeInfo shapeless(String group, int count, ItemConvertible output, ItemConvertible[]... inputs) { + return shapeless(group, new ItemStack(output, count), inputs); + } + + public static RecipeInfo shapeless(ItemStack output, ItemConvertible... inputs) { + return shapeless("", output, inputs); + } + + public static RecipeInfo shapeless(ItemConvertible output, ItemConvertible... inputs) { + return shapeless("", output, inputs); + } + + public static RecipeInfo shapeless(int count, ItemConvertible output, ItemConvertible... inputs) { + return shapeless("", count, output, inputs); + } + + public static RecipeInfo shapeless(ItemStack output, ItemConvertible[]... inputs) { + return shapeless("", output, inputs); + } + + public static RecipeInfo shapeless(ItemConvertible output, ItemConvertible[]... inputs) { + return shapeless("", output, inputs); + } + + public static RecipeInfo shapeless(int count, ItemConvertible output, ItemConvertible[]... inputs) { + return shapeless("", count, output, inputs); + } + + public static RecipeInfo smelting(ItemConvertible output, ItemConvertible input, float experience) { + return smelting(output, input, experience, 200); + } + + public static RecipeInfo smelting(ItemConvertible output, Ingredient input, float experience) { + return smelting(output, input, experience, 200); + } + + public static RecipeInfo smelting(ItemConvertible output, ItemConvertible input, float experience, int cookTime) { + return smelting(output, Ingredient.ofItems(input), experience, cookTime); + } + + public static RecipeInfo smelting(ItemConvertible output, Ingredient input, float experience, int cookTime) { + ItemStack outputStack = new ItemStack(output); + return new RecipeInfo<>(() -> new SmeltingRecipe("", CookingRecipeCategory.MISC, input, outputStack, experience, cookTime), RecipeSerializer.SMELTING, outputStack); + } + + public RecipeInfo distinguisher(String distinguisher) { + this.distinguisher = distinguisher; + return this; + } + + + public RecipeEntry create(Identifier id) { + return new RecipeEntry>(id, this.creator.get()); + } + + public RecipeSerializer getRecipeType() { + return this.recipeType; + } + + public ItemStack getOutput() { + return this.output; + } + + public String getDistinguisher() { + return this.distinguisher; + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/fixes/recipe/Recipes1_11_2.java b/src/main/java/de/florianmichael/viafabricplus/fixes/recipe/Recipes1_11_2.java new file mode 100644 index 000000000..5740ec295 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/fixes/recipe/Recipes1_11_2.java @@ -0,0 +1,713 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.fixes.recipe; + +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.minecraft.block.Blocks; +import net.minecraft.client.MinecraftClient; +import net.minecraft.inventory.RecipeInputInventory; +import net.minecraft.item.ItemConvertible; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket; +import net.minecraft.recipe.*; +import net.minecraft.recipe.book.CraftingRecipeCategory; +import net.minecraft.registry.tag.ItemTags; +import net.minecraft.screen.ScreenHandler; +import net.raphimc.vialoader.util.VersionEnum; + +import java.util.ArrayList; +import java.util.List; + +public class Recipes1_11_2 { + + public static List> getRecipes() { + final List> recipes = new ArrayList<>(); + + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_4_2)) { + recipes.add(RecipeInfo.of(() -> new ArmorDyeRecipe(CraftingRecipeCategory.MISC), RecipeSerializer.ARMOR_DYE, Items.LEATHER_HELMET)); + recipes.add(RecipeInfo.of(() -> new MapCloningRecipe(CraftingRecipeCategory.MISC), RecipeSerializer.MAP_CLONING, Items.FILLED_MAP, 2)); + recipes.add(RecipeInfo.of(() -> new MapExtendingRecipe(CraftingRecipeCategory.MISC), RecipeSerializer.MAP_EXTENDING, Items.FILLED_MAP)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_4_6tor1_4_7)) { + recipes.add(RecipeInfo.of(() -> new FireworkRocketRecipe(CraftingRecipeCategory.MISC), RecipeSerializer.FIREWORK_ROCKET, Items.FIREWORK_ROCKET)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_11)) { + recipes.add(RecipeInfo.of(() -> new ShulkerBoxColoringRecipe(CraftingRecipeCategory.MISC), RecipeSerializer.SHULKER_BOX, Items.WHITE_SHULKER_BOX)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_9)) { + recipes.add(RecipeInfo.of(() -> new TippedArrowRecipe(CraftingRecipeCategory.MISC), RecipeSerializer.TIPPED_ARROW, Items.TIPPED_ARROW)); + recipes.add(RecipeInfo.of(() -> new ShieldDecorationRecipe(CraftingRecipeCategory.MISC), RecipeSerializer.SHIELD_DECORATION, Items.SHIELD)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_8)) { + recipes.add(RecipeInfo.of(() -> new RepairItemRecipe(CraftingRecipeCategory.MISC), RecipeSerializer.REPAIR_ITEM, Items.WOODEN_SWORD)); + recipes.add(RecipeInfo.of(() -> new BannerDuplicateRecipe(CraftingRecipeCategory.MISC), RecipeSerializer.BANNER_DUPLICATE, Items.WHITE_BANNER, 2)); + recipes.add(RecipeInfo.of(() -> new AddBannerPatternRecipe(CraftingRecipeCategory.MISC), AddBannerPatternRecipe.SERIALIZER, Items.WHITE_BANNER)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_7_2tor1_7_5)) { + recipes.add(RecipeInfo.of(() -> new BookCloningRecipe(CraftingRecipeCategory.MISC), RecipeSerializer.BOOK_CLONING, Items.WRITABLE_BOOK, 2)); + } + + recipes.add(RecipeInfo.shaped(Items.WOODEN_SWORD, "X", "X", "#", '#', Items.STICK, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped(Items.WOODEN_SHOVEL, "X", "#", "#", '#', Items.STICK, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped(Items.WOODEN_PICKAXE, "XXX", " # ", " # ", '#', Items.STICK, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped(Items.WOODEN_HOE, "XX", " #", " #", '#', Items.STICK, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped(Items.WOODEN_AXE, "XX", "X#", " #", '#', Items.STICK, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped(Items.STONE_SWORD, "X", "X", "#", '#', Items.STICK, 'X', Blocks.COBBLESTONE)); + recipes.add(RecipeInfo.shaped(4, Blocks.COBBLESTONE_STAIRS, "# ", "## ", "###", '#', Blocks.COBBLESTONE)); + recipes.add(RecipeInfo.shaped(Items.STONE_SHOVEL, "X", "#", "#", '#', Items.STICK, 'X', Blocks.COBBLESTONE)); + recipes.add(RecipeInfo.shaped(Items.STONE_PICKAXE, "XXX", " # ", " # ", '#', Items.STICK, 'X', Blocks.COBBLESTONE)); + recipes.add(RecipeInfo.shaped(Items.STONE_HOE, "XX", " #", " #", '#', Items.STICK, 'X', Blocks.COBBLESTONE)); + recipes.add(RecipeInfo.shaped(Blocks.STONE_BUTTON, "#", '#', Blocks.STONE)); + recipes.add(RecipeInfo.shaped(Items.STONE_AXE, "XX", "X#", " #", '#', Items.STICK, 'X', Blocks.COBBLESTONE)); + recipes.add(RecipeInfo.shaped(4, Items.STICK, "#", "#", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped(Blocks.SNOW_BLOCK, "##", "##", '#', Items.SNOWBALL)); + recipes.add(RecipeInfo.shaped(Blocks.REDSTONE_TORCH, "X", "#", '#', Items.STICK, 'X', Blocks.REDSTONE_WIRE)); + recipes.add(RecipeInfo.shaped(16, Blocks.RAIL, "X X", "X#X", "X X", '#', Items.STICK, 'X', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(3, Items.PAPER, "###", '#', Blocks.SUGAR_CANE)); + recipes.add(RecipeInfo.shaped(Items.PAINTING, "###", "#X#", "###", '#', Items.STICK, 'X', Blocks.WHITE_WOOL, Blocks.ORANGE_WOOL, Blocks.MAGENTA_WOOL, Blocks.LIGHT_BLUE_WOOL, Blocks.YELLOW_WOOL, Blocks.LIME_WOOL, Blocks.PINK_WOOL, Blocks.GRAY_WOOL, Blocks.LIGHT_GRAY_WOOL, Blocks.CYAN_WOOL, Blocks.PURPLE_WOOL, Blocks.BLUE_WOOL, Blocks.BROWN_WOOL, Blocks.GREEN_WOOL, Blocks.RED_WOOL, Blocks.BLACK_WOOL)); + recipes.add(RecipeInfo.shaped("wooden_stairs", 4, Blocks.OAK_STAIRS, "# ", "## ", "###", '#', Blocks.OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("planks", 4, Blocks.OAK_PLANKS, "#", '#', Blocks.OAK_LOG)); + recipes.add(RecipeInfo.shaped(Items.MINECART, "# #", "###", '#', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(Blocks.LEVER, "X", "#", '#', Blocks.COBBLESTONE, 'X', Items.STICK)); + recipes.add(RecipeInfo.shaped(Items.LEATHER_LEGGINGS, "XXX", "X X", "X X", 'X', Items.LEATHER)); + recipes.add(RecipeInfo.shaped(Items.LEATHER_HELMET, "XXX", "X X", 'X', Items.LEATHER)); + recipes.add(RecipeInfo.shaped(Items.LEATHER_CHESTPLATE, "X X", "XXX", "XXX", 'X', Items.LEATHER)); + recipes.add(RecipeInfo.shaped(Items.LEATHER_BOOTS, "X X", "X X", 'X', Items.LEATHER)); + recipes.add(RecipeInfo.shaped(Blocks.JUKEBOX, "###", "#X#", "###", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS, 'X', Items.DIAMOND)); + recipes.add(RecipeInfo.shaped(Items.IRON_SWORD, "X", "X", "#", '#', Items.STICK, 'X', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(Items.IRON_SHOVEL, "X", "#", "#", '#', Items.STICK, 'X', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(Items.IRON_PICKAXE, "XXX", " # ", " # ", '#', Items.STICK, 'X', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(Items.IRON_LEGGINGS, "XXX", "X X", "X X", 'X', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped("iron_ingot", 9, Items.IRON_INGOT, "#", '#', Blocks.IRON_BLOCK)); + recipes.add(RecipeInfo.shaped(Items.IRON_HOE, "XX", " #", " #", '#', Items.STICK, 'X', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(Items.IRON_HELMET, "XXX", "X X", 'X', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(Items.IRON_CHESTPLATE, "X X", "XXX", "XXX", 'X', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(Items.IRON_BOOTS, "X X", "X X", 'X', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(Blocks.IRON_BLOCK, "###", "###", "###", '#', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(Items.IRON_AXE, "XX", "X#", " #", '#', Items.STICK, 'X', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(Items.GOLDEN_SWORD, "X", "X", "#", '#', Items.STICK, 'X', Items.GOLD_INGOT)); + recipes.add(RecipeInfo.shaped(Items.GOLDEN_SHOVEL, "X", "#", "#", '#', Items.STICK, 'X', Items.GOLD_INGOT)); + recipes.add(RecipeInfo.shaped(Items.GOLDEN_PICKAXE, "XXX", " # ", " # ", '#', Items.STICK, 'X', Items.GOLD_INGOT)); + recipes.add(RecipeInfo.shaped(Items.GOLDEN_LEGGINGS, "XXX", "X X", "X X", 'X', Items.GOLD_INGOT)); + recipes.add(RecipeInfo.shaped(Items.GOLDEN_HOE, "XX", " #", " #", '#', Items.STICK, 'X', Items.GOLD_INGOT)); + recipes.add(RecipeInfo.shaped(Items.GOLDEN_HELMET, "XXX", "X X", 'X', Items.GOLD_INGOT)); + recipes.add(RecipeInfo.shaped(Items.GOLDEN_CHESTPLATE, "X X", "XXX", "XXX", 'X', Items.GOLD_INGOT)); + recipes.add(RecipeInfo.shaped(Items.GOLDEN_BOOTS, "X X", "X X", 'X', Items.GOLD_INGOT)); + recipes.add(RecipeInfo.shaped(Items.GOLDEN_AXE, "XX", "X#", " #", '#', Items.STICK, 'X', Items.GOLD_INGOT)); + recipes.add(RecipeInfo.shaped("gold_ingot", 9, Items.GOLD_INGOT, "#", '#', Blocks.GOLD_BLOCK)); + recipes.add(RecipeInfo.shaped(Blocks.GOLD_BLOCK, "###", "###", "###", '#', Items.GOLD_INGOT)); + recipes.add(RecipeInfo.shaped(Items.FURNACE_MINECART, "A", "B", 'A', Blocks.FURNACE, 'B', Items.MINECART)); + recipes.add(RecipeInfo.shaped(Blocks.FURNACE, "###", "# #", "###", '#', Blocks.COBBLESTONE)); + recipes.add(RecipeInfo.shaped(Items.DIAMOND_SWORD, "X", "X", "#", '#', Items.STICK, 'X', Items.DIAMOND)); + recipes.add(RecipeInfo.shaped(Items.DIAMOND_SHOVEL, "X", "#", "#", '#', Items.STICK, 'X', Items.DIAMOND)); + recipes.add(RecipeInfo.shaped(Items.DIAMOND_PICKAXE, "XXX", " # ", " # ", '#', Items.STICK, 'X', Items.DIAMOND)); + recipes.add(RecipeInfo.shaped(Items.DIAMOND_LEGGINGS, "XXX", "X X", "X X", 'X', Items.DIAMOND)); + recipes.add(RecipeInfo.shaped(Items.DIAMOND_HOE, "XX", " #", " #", '#', Items.STICK, 'X', Items.DIAMOND)); + recipes.add(RecipeInfo.shaped(Items.DIAMOND_HELMET, "XXX", "X X", 'X', Items.DIAMOND)); + recipes.add(RecipeInfo.shaped(Items.DIAMOND_CHESTPLATE, "X X", "XXX", "XXX", 'X', Items.DIAMOND)); + recipes.add(RecipeInfo.shaped(Items.DIAMOND_BOOTS, "X X", "X X", 'X', Items.DIAMOND)); + recipes.add(RecipeInfo.shaped(Blocks.DIAMOND_BLOCK, "###", "###", "###", '#', Items.DIAMOND)); + recipes.add(RecipeInfo.shaped(Items.DIAMOND_AXE, "XX", "X#", " #", '#', Items.STICK, 'X', Items.DIAMOND)); + recipes.add(RecipeInfo.shaped(9, Items.DIAMOND, "#", '#', Blocks.DIAMOND_BLOCK)); + recipes.add(RecipeInfo.shaped(Blocks.CRAFTING_TABLE, "##", "##", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped(Blocks.CLAY, "##", "##", '#', Items.CLAY_BALL)); + recipes.add(RecipeInfo.shaped(Items.CHEST_MINECART, "A", "B", 'A', Blocks.CHEST, 'B', Items.MINECART)); + recipes.add(RecipeInfo.shaped(Blocks.CHEST, "###", "# #", "###", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped(Items.BUCKET, "# #", " # ", '#', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(Blocks.BRICKS, "##", "##", '#', Items.BRICK)); + recipes.add(RecipeInfo.shaped(Items.BREAD, "###", '#', Items.WHEAT)); + recipes.add(RecipeInfo.shaped(4, Items.BOWL, "# #", " # ", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped(Items.BOW, " #X", "# X", " #X", '#', Items.STICK, 'X', Blocks.TRIPWIRE)); + recipes.add(RecipeInfo.shaped(Blocks.BOOKSHELF, "###", "XXX", "###", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS, 'X', Items.BOOK)); + recipes.add(RecipeInfo.shaped(4, Items.ARROW, "X", "#", "Y", '#', Items.STICK, 'X', Items.FLINT, 'Y', Items.FEATHER)); + + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_12)) { + recipes.add(RecipeInfo.shapeless("concrete_powder", 8, Blocks.YELLOW_CONCRETE_POWDER, Items.YELLOW_DYE, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL)); + recipes.add(RecipeInfo.shapeless("concrete_powder", 8, Blocks.WHITE_CONCRETE_POWDER, Items.BONE_MEAL, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL)); + recipes.add(RecipeInfo.shapeless("concrete_powder", 8, Blocks.RED_CONCRETE_POWDER, Items.RED_DYE, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL)); + recipes.add(RecipeInfo.shapeless("concrete_powder", 8, Blocks.PURPLE_CONCRETE_POWDER, Items.PURPLE_DYE, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL)); + recipes.add(RecipeInfo.shapeless("concrete_powder", 8, Blocks.PINK_CONCRETE_POWDER, Items.PINK_DYE, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL)); + recipes.add(RecipeInfo.shapeless("concrete_powder", 8, Blocks.ORANGE_CONCRETE_POWDER, Items.ORANGE_DYE, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL)); + recipes.add(RecipeInfo.shapeless("concrete_powder", 8, Blocks.MAGENTA_CONCRETE_POWDER, Items.MAGENTA_DYE, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL)); + recipes.add(RecipeInfo.shapeless("concrete_powder", 8, Blocks.LIME_CONCRETE_POWDER, Items.LIME_DYE, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL)); + recipes.add(RecipeInfo.shapeless("concrete_powder", 8, Blocks.LIGHT_GRAY_CONCRETE_POWDER, Items.LIGHT_GRAY_DYE, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL)); + recipes.add(RecipeInfo.shapeless("concrete_powder", 8, Blocks.LIGHT_BLUE_CONCRETE_POWDER, Items.LIGHT_BLUE_DYE, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL)); + recipes.add(RecipeInfo.shapeless("concrete_powder", 8, Blocks.GREEN_CONCRETE_POWDER, Items.GREEN_DYE, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL)); + recipes.add(RecipeInfo.shapeless("concrete_powder", 8, Blocks.GRAY_CONCRETE_POWDER, Items.GRAY_DYE, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL)); + recipes.add(RecipeInfo.shapeless("concrete_powder", 8, Blocks.CYAN_CONCRETE_POWDER, Items.CYAN_DYE, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL)); + recipes.add(RecipeInfo.shapeless("concrete_powder", 8, Blocks.BROWN_CONCRETE_POWDER, Blocks.COCOA, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL)); + recipes.add(RecipeInfo.shapeless("concrete_powder", 8, Blocks.BLUE_CONCRETE_POWDER, Items.LAPIS_LAZULI, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL)); + recipes.add(RecipeInfo.shapeless("concrete_powder", 8, Blocks.BLACK_CONCRETE_POWDER, Items.INK_SAC, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL)); + recipes.add(RecipeInfo.shapeless("dyed_bed", Blocks.YELLOW_BED, Blocks.WHITE_BED, Items.YELLOW_DYE)); + recipes.add(RecipeInfo.shapeless("dyed_bed", Blocks.RED_BED, Blocks.WHITE_BED, Items.RED_DYE)); + recipes.add(RecipeInfo.shapeless("dyed_bed", Blocks.PURPLE_BED, Blocks.WHITE_BED, Items.PURPLE_DYE)); + recipes.add(RecipeInfo.shapeless("dyed_bed", Blocks.PINK_BED, Blocks.WHITE_BED, Items.PINK_DYE)); + recipes.add(RecipeInfo.shapeless("dyed_bed", Blocks.ORANGE_BED, Blocks.WHITE_BED, Items.ORANGE_DYE)); + recipes.add(RecipeInfo.shapeless("dyed_bed", Blocks.MAGENTA_BED, Blocks.WHITE_BED, Items.MAGENTA_DYE)); + recipes.add(RecipeInfo.shapeless("dyed_bed", Blocks.LIME_BED, Blocks.WHITE_BED, Items.LIME_DYE)); + recipes.add(RecipeInfo.shapeless("dyed_bed", Blocks.LIGHT_GRAY_BED, Blocks.WHITE_BED, Items.LIGHT_GRAY_DYE)); + recipes.add(RecipeInfo.shapeless("dyed_bed", Blocks.LIGHT_BLUE_BED, Blocks.WHITE_BED, Items.LIGHT_BLUE_DYE)); + recipes.add(RecipeInfo.shapeless("dyed_bed", Blocks.GREEN_BED, Blocks.WHITE_BED, Items.GREEN_DYE)); + recipes.add(RecipeInfo.shapeless("dyed_bed", Blocks.GRAY_BED, Blocks.WHITE_BED, Items.GRAY_DYE)); + recipes.add(RecipeInfo.shapeless("dyed_bed", Blocks.CYAN_BED, Blocks.WHITE_BED, Items.CYAN_DYE)); + recipes.add(RecipeInfo.shapeless("dyed_bed", Blocks.BROWN_BED, Blocks.WHITE_BED, Blocks.COCOA)); + recipes.add(RecipeInfo.shapeless("dyed_bed", Blocks.BLUE_BED, Blocks.WHITE_BED, Items.LAPIS_LAZULI)); + recipes.add(RecipeInfo.shapeless("dyed_bed", Blocks.BLACK_BED, Blocks.WHITE_BED, Items.INK_SAC)); + recipes.add(RecipeInfo.shaped("bed", Blocks.YELLOW_BED, "###", "XXX", '#', Blocks.YELLOW_WOOL, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("bed", Blocks.WHITE_BED, "###", "XXX", '#', Blocks.WHITE_WOOL, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("bed", Blocks.RED_BED, "###", "XXX", '#', Blocks.RED_WOOL, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("bed", Blocks.PURPLE_BED, "###", "XXX", '#', Blocks.PURPLE_WOOL, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("bed", Blocks.PINK_BED, "###", "XXX", '#', Blocks.PINK_WOOL, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("bed", Blocks.ORANGE_BED, "###", "XXX", '#', Blocks.ORANGE_WOOL, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("bed", Blocks.MAGENTA_BED, "###", "XXX", '#', Blocks.MAGENTA_WOOL, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("bed", Blocks.LIME_BED, "###", "XXX", '#', Blocks.LIME_WOOL, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("bed", Blocks.LIGHT_GRAY_BED, "###", "XXX", '#', Blocks.LIGHT_GRAY_WOOL, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("bed", Blocks.LIGHT_BLUE_BED, "###", "XXX", '#', Blocks.LIGHT_BLUE_WOOL, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("bed", Blocks.GREEN_BED, "###", "XXX", '#', Blocks.GREEN_WOOL, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("bed", Blocks.GRAY_BED, "###", "XXX", '#', Blocks.GRAY_WOOL, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("bed", Blocks.CYAN_BED, "###", "XXX", '#', Blocks.CYAN_WOOL, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("bed", Blocks.BROWN_BED, "###", "XXX", '#', Blocks.BROWN_WOOL, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("bed", Blocks.BLUE_BED, "###", "XXX", '#', Blocks.BLUE_WOOL, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("bed", Blocks.BLACK_BED, "###", "XXX", '#', Blocks.BLACK_WOOL, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + } else { + recipes.add(RecipeInfo.shapeless(Blocks.WHITE_WOOL, Blocks.WHITE_WOOL, Items.BONE_MEAL)); + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.b1_3tob1_3_1)) { + recipes.add(RecipeInfo.shaped("bed", Blocks.RED_BED, "###", "XXX", '#', Blocks.YELLOW_WOOL, Blocks.BLACK_WOOL, Blocks.BLUE_WOOL, Blocks.BROWN_WOOL, Blocks.CYAN_WOOL, Blocks.GRAY_WOOL, Blocks.GREEN_WOOL, Blocks.LIGHT_BLUE_WOOL, Blocks.LIGHT_GRAY_WOOL, Blocks.WHITE_WOOL, Blocks.RED_WOOL, Blocks.PURPLE_WOOL, Blocks.PINK_WOOL, Blocks.ORANGE_WOOL, Blocks.LIME_WOOL, Blocks.MAGENTA_WOOL, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + } + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_11_1to1_11_2)) { + recipes.add(RecipeInfo.shaped(9, Items.IRON_NUGGET, "#", '#', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped("iron_ingot", Items.IRON_INGOT, "###", "###", "###", '#', Items.IRON_NUGGET).distinguisher("iron_nugget_to_ingot")); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_11)) { + recipes.add(RecipeInfo.shaped(Blocks.OBSERVER, "###", "RRQ", "###", 'Q', Items.QUARTZ, 'R', Blocks.REDSTONE_WIRE, '#', Blocks.COBBLESTONE)); + recipes.add(RecipeInfo.shaped(Blocks.PURPLE_SHULKER_BOX, "-", "#", "-", '#', Blocks.CHEST, '-', Items.SHULKER_SHELL)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_10)) { + recipes.add(RecipeInfo.shapeless("bonemeal", 9, Items.BONE_MEAL, Blocks.BONE_BLOCK)); + recipes.add(RecipeInfo.shaped(Blocks.BONE_BLOCK, "XXX", "XXX", "XXX", 'X', Items.BONE_MEAL)); + recipes.add(RecipeInfo.shaped(Blocks.MAGMA_BLOCK, "##", "##", '#', Items.MAGMA_CREAM)); + recipes.add(RecipeInfo.shaped(Blocks.NETHER_WART_BLOCK, "###", "###", "###", '#', Blocks.NETHER_WART)); + recipes.add(RecipeInfo.shaped(Blocks.RED_NETHER_BRICKS, "NW", "WN", 'W', Blocks.NETHER_WART, 'N', Items.NETHER_BRICK)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_9)) { + recipes.add(RecipeInfo.shapeless(Blocks.TRAPPED_CHEST, Blocks.CHEST, Blocks.TRIPWIRE_HOOK)); + recipes.add(RecipeInfo.shaped(Items.SHIELD, "WoW", "WWW", " W ", 'W', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS, 'o', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(4, Blocks.PURPUR_BLOCK, "FF", "FF", 'F', Items.POPPED_CHORUS_FRUIT)); + recipes.add(RecipeInfo.shaped(6, Blocks.PURPUR_SLAB, "###", '#', Blocks.PURPUR_BLOCK)); + recipes.add(RecipeInfo.shaped(4, Blocks.PURPUR_STAIRS, "# ", "## ", "###", '#', Blocks.PURPUR_BLOCK)); + recipes.add(RecipeInfo.shaped(Blocks.PURPUR_PILLAR, "#", "#", '#', Blocks.PURPUR_SLAB)); + recipes.add(RecipeInfo.shaped(4, Blocks.END_STONE_BRICKS, "##", "##", '#', Blocks.END_STONE)); + recipes.add(RecipeInfo.shaped("boat", Items.SPRUCE_BOAT, "# #", "###", '#', Blocks.SPRUCE_PLANKS)); + recipes.add(RecipeInfo.shaped("boat", Items.JUNGLE_BOAT, "# #", "###", '#', Blocks.JUNGLE_PLANKS)); + recipes.add(RecipeInfo.shaped("boat", Items.OAK_BOAT, "# #", "###", '#', Blocks.OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("boat", Items.DARK_OAK_BOAT, "# #", "###", '#', Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("boat", Items.BIRCH_BOAT, "# #", "###", '#', Blocks.BIRCH_PLANKS)); + recipes.add(RecipeInfo.shaped("boat", Items.ACACIA_BOAT, "# #", "###", '#', Blocks.ACACIA_PLANKS)); + recipes.add(RecipeInfo.shaped(4, Blocks.END_ROD, "/", "#", '#', Items.POPPED_CHORUS_FRUIT, '/', Items.BLAZE_ROD)); + recipes.add(RecipeInfo.shaped(Items.END_CRYSTAL, "GGG", "GEG", "GTG", 'T', Items.GHAST_TEAR, 'E', Items.ENDER_EYE, 'G', Blocks.GLASS)); + recipes.add(RecipeInfo.shaped(2, Items.SPECTRAL_ARROW, " # ", "#X#", " # ", '#', Items.GLOWSTONE_DUST, 'X', Items.ARROW)); + recipes.add(RecipeInfo.shapeless("red_dye", Items.RED_DYE, Items.BEETROOT)); + recipes.add(RecipeInfo.shaped(Items.BEETROOT_SOUP, "OOO", "OOO", " B ", 'B', Items.BOWL, 'O', Items.BEETROOT)); + } else { + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_5tor1_5_1)) { + recipes.add(RecipeInfo.shaped(Blocks.TRAPPED_CHEST, "#-", '#', Blocks.CHEST, '-', Blocks.TRIPWIRE_HOOK)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_3_1tor1_3_2)) { + recipes.add(RecipeInfo.shaped(Items.ENCHANTED_GOLDEN_APPLE, "###", "#X#", "###", '#', Items.GOLD_BLOCK, 'X', Items.APPLE)); + } + recipes.add(RecipeInfo.shaped("boat", Items.OAK_BOAT, "# #", "###", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.DARK_OAK_PLANKS, Blocks.BIRCH_PLANKS, Blocks.ACACIA_PLANKS)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_8)) { + recipes.add(RecipeInfo.shapeless(Blocks.MOSSY_COBBLESTONE, Blocks.COBBLESTONE, Blocks.VINE)); + recipes.add(RecipeInfo.shapeless(Blocks.MOSSY_STONE_BRICKS, Blocks.STONE_BRICKS, Blocks.VINE)); + recipes.add(RecipeInfo.shaped(Blocks.CHISELED_STONE_BRICKS, "#", "#", '#', Blocks.STONE_BRICK_SLAB)); + recipes.add(RecipeInfo.shaped(4, Blocks.COARSE_DIRT, "DG", "GD", 'D', Blocks.DIRT, 'G', Blocks.GRAVEL)); + recipes.add(RecipeInfo.shaped("wooden_fence", 3, Blocks.SPRUCE_FENCE, "W#W", "W#W", '#', Items.STICK, 'W', Blocks.SPRUCE_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_fence", 3, Blocks.JUNGLE_FENCE, "W#W", "W#W", '#', Items.STICK, 'W', Blocks.JUNGLE_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_fence", 3, Blocks.OAK_FENCE, "W#W", "W#W", '#', Items.STICK, 'W', Blocks.OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_fence", 3, Blocks.DARK_OAK_FENCE, "W#W", "W#W", '#', Items.STICK, 'W', Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_fence", 3, Blocks.BIRCH_FENCE, "W#W", "W#W", '#', Items.STICK, 'W', Blocks.BIRCH_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_fence", 3, Blocks.ACACIA_FENCE, "W#W", "W#W", '#', Items.STICK, 'W', Blocks.ACACIA_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_fence_gate", Blocks.SPRUCE_FENCE_GATE, "#W#", "#W#", '#', Items.STICK, 'W', Blocks.SPRUCE_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_fence_gate", Blocks.JUNGLE_FENCE_GATE, "#W#", "#W#", '#', Items.STICK, 'W', Blocks.JUNGLE_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_fence_gate", Blocks.OAK_FENCE_GATE, "#W#", "#W#", '#', Items.STICK, 'W', Blocks.OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_fence_gate", Blocks.DARK_OAK_FENCE_GATE, "#W#", "#W#", '#', Items.STICK, 'W', Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_fence_gate", Blocks.BIRCH_FENCE_GATE, "#W#", "#W#", '#', Items.STICK, 'W', Blocks.BIRCH_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_fence_gate", Blocks.ACACIA_FENCE_GATE, "#W#", "#W#", '#', Items.STICK, 'W', Blocks.ACACIA_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_door", 3, Blocks.OAK_DOOR, "##", "##", "##", '#', Blocks.OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_door", 3, Blocks.SPRUCE_DOOR, "##", "##", "##", '#', Blocks.SPRUCE_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_door", 3, Blocks.JUNGLE_DOOR, "##", "##", "##", '#', Blocks.JUNGLE_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_door", 3, Blocks.DARK_OAK_DOOR, "##", "##", "##", '#', Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_door", 3, Blocks.BIRCH_DOOR, "##", "##", "##", '#', Blocks.BIRCH_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_door", 3, Blocks.ACACIA_DOOR, "##", "##", "##", '#', Blocks.ACACIA_PLANKS)); + recipes.add(RecipeInfo.shaped("banner", Blocks.YELLOW_BANNER, "###", "###", " | ", '#', Blocks.YELLOW_WOOL, '|', Items.STICK)); + recipes.add(RecipeInfo.shaped("banner", Blocks.RED_BANNER, "###", "###", " | ", '#', Blocks.RED_WOOL, '|', Items.STICK)); + recipes.add(RecipeInfo.shaped("banner", Blocks.PURPLE_BANNER, "###", "###", " | ", '#', Blocks.PURPLE_WOOL, '|', Items.STICK)); + recipes.add(RecipeInfo.shaped("banner", Blocks.PINK_BANNER, "###", "###", " | ", '#', Blocks.PINK_WOOL, '|', Items.STICK)); + recipes.add(RecipeInfo.shaped("banner", Blocks.ORANGE_BANNER, "###", "###", " | ", '#', Blocks.ORANGE_WOOL, '|', Items.STICK)); + recipes.add(RecipeInfo.shaped("banner", Blocks.MAGENTA_BANNER, "###", "###", " | ", '#', Blocks.MAGENTA_WOOL, '|', Items.STICK)); + recipes.add(RecipeInfo.shaped("banner", Blocks.LIME_BANNER, "###", "###", " | ", '#', Blocks.LIME_WOOL, '|', Items.STICK)); + recipes.add(RecipeInfo.shaped("banner", Blocks.LIGHT_GRAY_BANNER, "###", "###", " | ", '#', Blocks.LIGHT_GRAY_WOOL, '|', Items.STICK)); + recipes.add(RecipeInfo.shaped("banner", Blocks.LIGHT_BLUE_BANNER, "###", "###", " | ", '#', Blocks.LIGHT_BLUE_WOOL, '|', Items.STICK)); + recipes.add(RecipeInfo.shaped("banner", Blocks.GREEN_BANNER, "###", "###", " | ", '#', Blocks.GREEN_WOOL, '|', Items.STICK)); + recipes.add(RecipeInfo.shaped("banner", Blocks.GRAY_BANNER, "###", "###", " | ", '#', Blocks.GRAY_WOOL, '|', Items.STICK)); + recipes.add(RecipeInfo.shaped("banner", Blocks.CYAN_BANNER, "###", "###", " | ", '#', Blocks.CYAN_WOOL, '|', Items.STICK)); + recipes.add(RecipeInfo.shaped("banner", Blocks.BROWN_BANNER, "###", "###", " | ", '#', Blocks.BROWN_WOOL, '|', Items.STICK)); + recipes.add(RecipeInfo.shaped("banner", Blocks.BLUE_BANNER, "###", "###", " | ", '#', Blocks.BLUE_WOOL, '|', Items.STICK)); + recipes.add(RecipeInfo.shaped("banner", Blocks.BLACK_BANNER, "###", "###", " | ", '#', Blocks.BLACK_WOOL, '|', Items.STICK)); + recipes.add(RecipeInfo.shaped("banner", Blocks.WHITE_BANNER, "###", "###", " | ", '#', Blocks.WHITE_WOOL, '|', Items.STICK)); + recipes.add(RecipeInfo.shaped("rabbit_stew", Items.RABBIT_STEW, " R ", "CPD", " B ", 'P', Items.BAKED_POTATO, 'R', Items.COOKED_RABBIT, 'B', Items.BOWL, 'C', Blocks.CARROTS, 'D', Blocks.RED_MUSHROOM)); + recipes.add(RecipeInfo.shaped("rabbit_stew", Items.RABBIT_STEW, " R ", "CPM", " B ", 'P', Items.BAKED_POTATO, 'R', Items.COOKED_RABBIT, 'B', Items.BOWL, 'C', Blocks.CARROTS, 'M', Blocks.BROWN_MUSHROOM)); + recipes.add(RecipeInfo.shaped(3, Blocks.IRON_DOOR, "##", "##", "##", '#', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(Blocks.IRON_TRAPDOOR, "##", "##", '#', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(Blocks.RED_SANDSTONE, "##", "##", '#', Blocks.RED_SAND)); + recipes.add(RecipeInfo.shaped(4, Blocks.CUT_RED_SANDSTONE, "##", "##", '#', Blocks.RED_SANDSTONE)); + recipes.add(RecipeInfo.shaped(6, Blocks.RED_SANDSTONE_SLAB, "###", '#', Blocks.RED_SANDSTONE, Blocks.CHISELED_RED_SANDSTONE, Blocks.CUT_RED_SANDSTONE)); + recipes.add(RecipeInfo.shaped(4, Blocks.RED_SANDSTONE_STAIRS, "# ", "## ", "###", '#', Blocks.RED_SANDSTONE, Blocks.CHISELED_RED_SANDSTONE, Blocks.CUT_RED_SANDSTONE)); + recipes.add(RecipeInfo.shaped(Blocks.CHISELED_RED_SANDSTONE, "#", "#", '#', Blocks.RED_SANDSTONE_SLAB)); + recipes.add(RecipeInfo.shaped(Items.LEATHER, "##", "##", '#', Items.RABBIT_HIDE)); + recipes.add(RecipeInfo.shaped(Items.ARMOR_STAND, "///", " / ", "/_/", '/', Items.STICK, '_', Blocks.SMOOTH_STONE_SLAB)); + recipes.add(RecipeInfo.shaped(Blocks.SEA_LANTERN, "SCS", "CCC", "SCS", 'S', Items.PRISMARINE_SHARD, 'C', Items.PRISMARINE_CRYSTALS)); + recipes.add(RecipeInfo.shaped(Blocks.PRISMARINE_BRICKS, "SSS", "SSS", "SSS", 'S', Items.PRISMARINE_SHARD)); + recipes.add(RecipeInfo.shaped(Blocks.PRISMARINE, "SS", "SS", 'S', Items.PRISMARINE_SHARD)); + recipes.add(RecipeInfo.shaped(Blocks.DARK_PRISMARINE, "SSS", "SIS", "SSS", 'S', Items.PRISMARINE_SHARD, 'I', Items.INK_SAC)); + recipes.add(RecipeInfo.shaped(9, Items.SLIME_BALL, "#", '#', Blocks.SLIME_BLOCK)); + recipes.add(RecipeInfo.shaped(Blocks.SLIME_BLOCK, "###", "###", "###", '#', Items.SLIME_BALL)); + recipes.add(RecipeInfo.shaped(2, Blocks.DIORITE, "CQ", "QC", 'Q', Items.QUARTZ, 'C', Blocks.COBBLESTONE)); + recipes.add(RecipeInfo.shapeless(2, Blocks.ANDESITE, Blocks.DIORITE, Blocks.COBBLESTONE)); + recipes.add(RecipeInfo.shapeless(Blocks.GRANITE, Blocks.DIORITE, Items.QUARTZ)); + recipes.add(RecipeInfo.shaped(4, Blocks.POLISHED_GRANITE, "SS", "SS", 'S', Blocks.GRANITE)); + recipes.add(RecipeInfo.shaped(4, Blocks.POLISHED_DIORITE, "SS", "SS", 'S', Blocks.DIORITE)); + recipes.add(RecipeInfo.shaped(4, Blocks.POLISHED_ANDESITE, "SS", "SS", 'S', Blocks.ANDESITE)); + } else { + recipes.add(RecipeInfo.shaped("wooden_fence", 2, Blocks.OAK_FENCE, "###", "###", '#', Items.STICK)); + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.b1_8tob1_8_1)) { + recipes.add(RecipeInfo.shaped("wooden_fence_gate", Blocks.OAK_FENCE_GATE, "#W#", "#W#", '#', Items.STICK, 'W', Blocks.OAK_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.DARK_OAK_PLANKS, Blocks.BIRCH_PLANKS, Blocks.ACACIA_PLANKS)); + } + recipes.add(RecipeInfo.shaped(Blocks.IRON_DOOR, "##", "##", "##", '#', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped("wooden_door", Blocks.OAK_DOOR, "##", "##", "##", '#', Blocks.OAK_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.DARK_OAK_PLANKS, Blocks.BIRCH_PLANKS, Blocks.ACACIA_PLANKS)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_7_2tor1_7_5)) { + recipes.add(RecipeInfo.shaped("stained_glass", 8, Blocks.YELLOW_STAINED_GLASS, "###", "#X#", "###", '#', Blocks.GLASS, 'X', Items.YELLOW_DYE)); + recipes.add(RecipeInfo.shaped("stained_glass", 8, Blocks.WHITE_STAINED_GLASS, "###", "#X#", "###", '#', Blocks.GLASS, 'X', Items.BONE_MEAL)); + recipes.add(RecipeInfo.shaped("stained_glass", 8, Blocks.RED_STAINED_GLASS, "###", "#X#", "###", '#', Blocks.GLASS, 'X', Items.RED_DYE)); + recipes.add(RecipeInfo.shaped("stained_glass", 8, Blocks.PURPLE_STAINED_GLASS, "###", "#X#", "###", '#', Blocks.GLASS, 'X', Items.PURPLE_DYE)); + recipes.add(RecipeInfo.shaped("stained_glass", 8, Blocks.PINK_STAINED_GLASS, "###", "#X#", "###", '#', Blocks.GLASS, 'X', Items.PINK_DYE)); + recipes.add(RecipeInfo.shaped("stained_glass", 8, Blocks.ORANGE_STAINED_GLASS, "###", "#X#", "###", '#', Blocks.GLASS, 'X', Items.ORANGE_DYE)); + recipes.add(RecipeInfo.shaped("stained_glass", 8, Blocks.MAGENTA_STAINED_GLASS, "###", "#X#", "###", '#', Blocks.GLASS, 'X', Items.MAGENTA_DYE)); + recipes.add(RecipeInfo.shaped("stained_glass", 8, Blocks.LIME_STAINED_GLASS, "###", "#X#", "###", '#', Blocks.GLASS, 'X', Items.LIME_DYE)); + recipes.add(RecipeInfo.shaped("stained_glass", 8, Blocks.LIGHT_GRAY_STAINED_GLASS, "###", "#X#", "###", '#', Blocks.GLASS, 'X', Items.LIGHT_GRAY_DYE)); + recipes.add(RecipeInfo.shaped("stained_glass", 8, Blocks.LIGHT_BLUE_STAINED_GLASS, "###", "#X#", "###", '#', Blocks.GLASS, 'X', Items.LIGHT_BLUE_DYE)); + recipes.add(RecipeInfo.shaped("stained_glass", 8, Blocks.GREEN_STAINED_GLASS, "###", "#X#", "###", '#', Blocks.GLASS, 'X', Items.GREEN_DYE)); + recipes.add(RecipeInfo.shaped("stained_glass", 8, Blocks.GRAY_STAINED_GLASS, "###", "#X#", "###", '#', Blocks.GLASS, 'X', Items.GRAY_DYE)); + recipes.add(RecipeInfo.shaped("stained_glass", 8, Blocks.CYAN_STAINED_GLASS, "###", "#X#", "###", '#', Blocks.GLASS, 'X', Items.CYAN_DYE)); + recipes.add(RecipeInfo.shaped("stained_glass", 8, Blocks.BROWN_STAINED_GLASS, "###", "#X#", "###", '#', Blocks.GLASS, 'X', Blocks.COCOA)); + recipes.add(RecipeInfo.shaped("stained_glass", 8, Blocks.BLUE_STAINED_GLASS, "###", "#X#", "###", '#', Blocks.GLASS, 'X', Items.LAPIS_LAZULI)); + recipes.add(RecipeInfo.shaped("stained_glass", 8, Blocks.BLACK_STAINED_GLASS, "###", "#X#", "###", '#', Blocks.GLASS, 'X', Items.INK_SAC)); + recipes.add(RecipeInfo.shaped("stained_glass_pane", 16, Blocks.YELLOW_STAINED_GLASS_PANE, "###", "###", '#', Blocks.YELLOW_STAINED_GLASS)); + recipes.add(RecipeInfo.shaped("stained_glass_pane", 16, Blocks.WHITE_STAINED_GLASS_PANE, "###", "###", '#', Blocks.WHITE_STAINED_GLASS)); + recipes.add(RecipeInfo.shaped("stained_glass_pane", 16, Blocks.RED_STAINED_GLASS_PANE, "###", "###", '#', Blocks.RED_STAINED_GLASS)); + recipes.add(RecipeInfo.shaped("stained_glass_pane", 16, Blocks.PURPLE_STAINED_GLASS_PANE, "###", "###", '#', Blocks.PURPLE_STAINED_GLASS)); + recipes.add(RecipeInfo.shaped("stained_glass_pane", 16, Blocks.PINK_STAINED_GLASS_PANE, "###", "###", '#', Blocks.PINK_STAINED_GLASS)); + recipes.add(RecipeInfo.shaped("stained_glass_pane", 16, Blocks.ORANGE_STAINED_GLASS_PANE, "###", "###", '#', Blocks.ORANGE_STAINED_GLASS)); + recipes.add(RecipeInfo.shaped("stained_glass_pane", 16, Blocks.MAGENTA_STAINED_GLASS_PANE, "###", "###", '#', Blocks.MAGENTA_STAINED_GLASS)); + recipes.add(RecipeInfo.shaped("stained_glass_pane", 16, Blocks.LIME_STAINED_GLASS_PANE, "###", "###", '#', Blocks.LIME_STAINED_GLASS)); + recipes.add(RecipeInfo.shaped("stained_glass_pane", 16, Blocks.LIGHT_GRAY_STAINED_GLASS_PANE, "###", "###", '#', Blocks.LIGHT_GRAY_STAINED_GLASS)); + recipes.add(RecipeInfo.shaped("stained_glass_pane", 16, Blocks.LIGHT_BLUE_STAINED_GLASS_PANE, "###", "###", '#', Blocks.LIGHT_BLUE_STAINED_GLASS)); + recipes.add(RecipeInfo.shaped("stained_glass_pane", 16, Blocks.GREEN_STAINED_GLASS_PANE, "###", "###", '#', Blocks.GREEN_STAINED_GLASS)); + recipes.add(RecipeInfo.shaped("stained_glass_pane", 16, Blocks.GRAY_STAINED_GLASS_PANE, "###", "###", '#', Blocks.GRAY_STAINED_GLASS)); + recipes.add(RecipeInfo.shaped("stained_glass_pane", 16, Blocks.CYAN_STAINED_GLASS_PANE, "###", "###", '#', Blocks.CYAN_STAINED_GLASS)); + recipes.add(RecipeInfo.shaped("stained_glass_pane", 16, Blocks.BROWN_STAINED_GLASS_PANE, "###", "###", '#', Blocks.BROWN_STAINED_GLASS)); + recipes.add(RecipeInfo.shaped("stained_glass_pane", 16, Blocks.BLUE_STAINED_GLASS_PANE, "###", "###", '#', Blocks.BLUE_STAINED_GLASS)); + recipes.add(RecipeInfo.shaped("stained_glass_pane", 16, Blocks.BLACK_STAINED_GLASS_PANE, "###", "###", '#', Blocks.BLACK_STAINED_GLASS)); + recipes.add(RecipeInfo.shaped("planks", 4, Blocks.ACACIA_PLANKS, "#", '#', Blocks.ACACIA_LOG)); + recipes.add(RecipeInfo.shaped("planks", 4, Blocks.DARK_OAK_PLANKS, "#", '#', Blocks.DARK_OAK_LOG)); + recipes.add(RecipeInfo.shaped("wooden_slab", 6, Blocks.ACACIA_SLAB, "###", '#', Blocks.ACACIA_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_stairs", 4, Blocks.ACACIA_STAIRS, "# ", "## ", "###", '#', Blocks.ACACIA_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_slab", 6, Blocks.DARK_OAK_SLAB, "###", '#', Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_stairs", 4, Blocks.DARK_OAK_STAIRS, "# ", "## ", "###", '#', Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped(Blocks.TNT, "X#X", "#X#", "X#X", '#', Blocks.SAND, Blocks.RED_SAND, 'X', Items.GUNPOWDER)); + recipes.add(RecipeInfo.shapeless("red_dye", Items.RED_DYE, Blocks.RED_TULIP)); + recipes.add(RecipeInfo.shapeless("orange_dye", Items.ORANGE_DYE, Blocks.ORANGE_TULIP)); + recipes.add(RecipeInfo.shapeless("light_gray_dye", Items.LIGHT_GRAY_DYE, Blocks.WHITE_TULIP)); + recipes.add(RecipeInfo.shapeless("pink_dye", Items.PINK_DYE, Blocks.PINK_TULIP)); + recipes.add(RecipeInfo.shapeless("light_blue_dye", Items.LIGHT_BLUE_DYE, Blocks.BLUE_ORCHID)); + recipes.add(RecipeInfo.shapeless("magenta_dye", Items.MAGENTA_DYE, Blocks.ALLIUM)); + recipes.add(RecipeInfo.shapeless("light_gray_dye", Items.LIGHT_GRAY_DYE, Blocks.AZURE_BLUET)); + recipes.add(RecipeInfo.shapeless("light_gray_dye", Items.LIGHT_GRAY_DYE, Blocks.OXEYE_DAISY)); + recipes.add(RecipeInfo.shapeless("yellow_dye", 2, Items.YELLOW_DYE, Blocks.SUNFLOWER)); + recipes.add(RecipeInfo.shapeless("pink_dye", 2, Items.PINK_DYE, Blocks.PEONY)); + recipes.add(RecipeInfo.shapeless("red_dye", 2, Items.RED_DYE, Blocks.ROSE_BUSH)); + recipes.add(RecipeInfo.shapeless("magenta_dye", 2, Items.MAGENTA_DYE, Blocks.LILAC)); + recipes.add(RecipeInfo.shapeless(Items.FLINT_AND_STEEL, Items.IRON_INGOT, Items.FLINT)); + } else { + recipes.add(RecipeInfo.shaped(Items.FLINT_AND_STEEL, "A ", " B", 'A', Items.IRON_INGOT, 'B', Items.FLINT)); + recipes.add(RecipeInfo.shaped(Blocks.TNT, "X#X", "#X#", "X#X", '#', Blocks.SAND, 'X', Items.GUNPOWDER)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_6_1)) { + recipes.add(RecipeInfo.shaped(Items.GOLDEN_APPLE, "###", "#X#", "###", '#', Items.GOLD_INGOT, 'X', Items.APPLE)); + recipes.add(RecipeInfo.shaped(Items.GLISTERING_MELON_SLICE, "###", "#X#", "###", '#', Items.GOLD_NUGGET, 'X', Items.MELON_SLICE)); + recipes.add(RecipeInfo.shaped("carpet", 3, Blocks.YELLOW_CARPET, "##", '#', Blocks.YELLOW_WOOL)); + recipes.add(RecipeInfo.shaped("carpet", 3, Blocks.WHITE_CARPET, "##", '#', Blocks.WHITE_WOOL)); + recipes.add(RecipeInfo.shaped("carpet", 3, Blocks.RED_CARPET, "##", '#', Blocks.RED_WOOL)); + recipes.add(RecipeInfo.shaped("carpet", 3, Blocks.PURPLE_CARPET, "##", '#', Blocks.PURPLE_WOOL)); + recipes.add(RecipeInfo.shaped("carpet", 3, Blocks.PINK_CARPET, "##", '#', Blocks.PINK_WOOL)); + recipes.add(RecipeInfo.shaped("carpet", 3, Blocks.ORANGE_CARPET, "##", '#', Blocks.ORANGE_WOOL)); + recipes.add(RecipeInfo.shaped("carpet", 3, Blocks.MAGENTA_CARPET, "##", '#', Blocks.MAGENTA_WOOL)); + recipes.add(RecipeInfo.shaped("carpet", 3, Blocks.LIME_CARPET, "##", '#', Blocks.LIME_WOOL)); + recipes.add(RecipeInfo.shaped("carpet", 3, Blocks.LIGHT_GRAY_CARPET, "##", '#', Blocks.LIGHT_GRAY_WOOL)); + recipes.add(RecipeInfo.shaped("carpet", 3, Blocks.LIGHT_BLUE_CARPET, "##", '#', Blocks.LIGHT_BLUE_WOOL)); + recipes.add(RecipeInfo.shaped("carpet", 3, Blocks.GREEN_CARPET, "##", '#', Blocks.GREEN_WOOL)); + recipes.add(RecipeInfo.shaped("carpet", 3, Blocks.GRAY_CARPET, "##", '#', Blocks.GRAY_WOOL)); + recipes.add(RecipeInfo.shaped("carpet", 3, Blocks.CYAN_CARPET, "##", '#', Blocks.CYAN_WOOL)); + recipes.add(RecipeInfo.shaped("carpet", 3, Blocks.BROWN_CARPET, "##", '#', Blocks.BROWN_WOOL)); + recipes.add(RecipeInfo.shaped("carpet", 3, Blocks.BLUE_CARPET, "##", '#', Blocks.BLUE_WOOL)); + recipes.add(RecipeInfo.shaped("carpet", 3, Blocks.BLACK_CARPET, "##", '#', Blocks.BLACK_WOOL)); + recipes.add(RecipeInfo.shaped("stained_hardened_clay", 8, Blocks.YELLOW_TERRACOTTA, "###", "#X#", "###", '#', Blocks.TERRACOTTA, 'X', Items.YELLOW_DYE)); + recipes.add(RecipeInfo.shaped("stained_hardened_clay", 8, Blocks.WHITE_TERRACOTTA, "###", "#X#", "###", '#', Blocks.TERRACOTTA, 'X', Items.BONE_MEAL)); + recipes.add(RecipeInfo.shaped("stained_hardened_clay", 8, Blocks.RED_TERRACOTTA, "###", "#X#", "###", '#', Blocks.TERRACOTTA, 'X', Items.RED_DYE)); + recipes.add(RecipeInfo.shaped("stained_hardened_clay", 8, Blocks.PURPLE_TERRACOTTA, "###", "#X#", "###", '#', Blocks.TERRACOTTA, 'X', Items.PURPLE_DYE)); + recipes.add(RecipeInfo.shaped("stained_hardened_clay", 8, Blocks.PINK_TERRACOTTA, "###", "#X#", "###", '#', Blocks.TERRACOTTA, 'X', Items.PINK_DYE)); + recipes.add(RecipeInfo.shaped("stained_hardened_clay", 8, Blocks.ORANGE_TERRACOTTA, "###", "#X#", "###", '#', Blocks.TERRACOTTA, 'X', Items.ORANGE_DYE)); + recipes.add(RecipeInfo.shaped("stained_hardened_clay", 8, Blocks.MAGENTA_TERRACOTTA, "###", "#X#", "###", '#', Blocks.TERRACOTTA, 'X', Items.MAGENTA_DYE)); + recipes.add(RecipeInfo.shaped("stained_hardened_clay", 8, Blocks.LIME_TERRACOTTA, "###", "#X#", "###", '#', Blocks.TERRACOTTA, 'X', Items.LIME_DYE)); + recipes.add(RecipeInfo.shaped("stained_hardened_clay", 8, Blocks.LIGHT_GRAY_TERRACOTTA, "###", "#X#", "###", '#', Blocks.TERRACOTTA, 'X', Items.LIGHT_GRAY_DYE)); + recipes.add(RecipeInfo.shaped("stained_hardened_clay", 8, Blocks.LIGHT_BLUE_TERRACOTTA, "###", "#X#", "###", '#', Blocks.TERRACOTTA, 'X', Items.LIGHT_BLUE_DYE)); + recipes.add(RecipeInfo.shaped("stained_hardened_clay", 8, Blocks.GREEN_TERRACOTTA, "###", "#X#", "###", '#', Blocks.TERRACOTTA, 'X', Items.GREEN_DYE)); + recipes.add(RecipeInfo.shaped("stained_hardened_clay", 8, Blocks.GRAY_TERRACOTTA, "###", "#X#", "###", '#', Blocks.TERRACOTTA, 'X', Items.GRAY_DYE)); + recipes.add(RecipeInfo.shaped("stained_hardened_clay", 8, Blocks.CYAN_TERRACOTTA, "###", "#X#", "###", '#', Blocks.TERRACOTTA, 'X', Items.CYAN_DYE)); + recipes.add(RecipeInfo.shaped("stained_hardened_clay", 8, Blocks.BROWN_TERRACOTTA, "###", "#X#", "###", '#', Blocks.TERRACOTTA, 'X', Blocks.COCOA)); + recipes.add(RecipeInfo.shaped("stained_hardened_clay", 8, Blocks.BLUE_TERRACOTTA, "###", "#X#", "###", '#', Blocks.TERRACOTTA, 'X', Items.LAPIS_LAZULI)); + recipes.add(RecipeInfo.shaped("stained_hardened_clay", 8, Blocks.BLACK_TERRACOTTA, "###", "#X#", "###", '#', Blocks.TERRACOTTA, 'X', Items.INK_SAC)); + recipes.add(RecipeInfo.shaped(2, Items.LEAD, "~~ ", "~O ", " ~", '~', Blocks.TRIPWIRE, 'O', Items.SLIME_BALL)); + recipes.add(RecipeInfo.shaped(Blocks.HAY_BLOCK, "###", "###", "###", '#', Items.WHEAT)); + recipes.add(RecipeInfo.shaped(9, Items.WHEAT, "#", '#', Blocks.HAY_BLOCK)); + recipes.add(RecipeInfo.shaped(Blocks.COAL_BLOCK, "###", "###", "###", '#', Items.COAL)); + recipes.add(RecipeInfo.shaped(9, Items.COAL, "#", '#', Blocks.COAL_BLOCK)); + } else { + recipes.add(RecipeInfo.shaped(Items.GOLDEN_APPLE, "###", "#X#", "###", '#', Items.GOLD_NUGGET, 'X', Items.APPLE)); + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_0_0tor1_0_1)) { + recipes.add(RecipeInfo.shapeless(Items.GLISTERING_MELON_SLICE, Items.GOLD_NUGGET, Items.MELON_SLICE)); + } + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_5tor1_5_1)) { + recipes.add(RecipeInfo.shaped(6, Blocks.SNOW, "###", '#', Blocks.SNOW_BLOCK)); + recipes.add(RecipeInfo.shaped(Blocks.QUARTZ_BLOCK, "##", "##", '#', Items.QUARTZ)); + recipes.add(RecipeInfo.shaped(2, Blocks.QUARTZ_PILLAR, "#", "#", '#', Blocks.QUARTZ_BLOCK)); + recipes.add(RecipeInfo.shaped(Blocks.CHISELED_QUARTZ_BLOCK, "#", "#", '#', Blocks.QUARTZ_SLAB)); + recipes.add(RecipeInfo.shaped(6, Blocks.QUARTZ_SLAB, "###", '#', Blocks.QUARTZ_BLOCK, Blocks.CHISELED_QUARTZ_BLOCK, Blocks.QUARTZ_PILLAR)); + recipes.add(RecipeInfo.shaped(6, Blocks.ACTIVATOR_RAIL, "XSX", "X#X", "XSX", '#', Blocks.REDSTONE_TORCH, 'S', Items.STICK, 'X', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(Items.TNT_MINECART, "A", "B", 'A', Blocks.TNT, 'B', Items.MINECART)); + recipes.add(RecipeInfo.shaped(Items.HOPPER_MINECART, "A", "B", 'A', Blocks.HOPPER, 'B', Items.MINECART)); + recipes.add(RecipeInfo.shaped(4, Blocks.QUARTZ_STAIRS, "# ", "## ", "###", '#', Blocks.QUARTZ_BLOCK, Blocks.CHISELED_QUARTZ_BLOCK, Blocks.QUARTZ_PILLAR)); + recipes.add(RecipeInfo.shaped(Blocks.COMPARATOR, " # ", "#X#", "III", '#', Blocks.REDSTONE_TORCH, 'X', Items.QUARTZ, 'I', Blocks.STONE)); + recipes.add(RecipeInfo.shaped(Blocks.LIGHT_WEIGHTED_PRESSURE_PLATE, "##", '#', Items.GOLD_INGOT)); + recipes.add(RecipeInfo.shaped(Blocks.HEAVY_WEIGHTED_PRESSURE_PLATE, "##", '#', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(Blocks.DROPPER, "###", "# #", "#R#", 'R', Blocks.REDSTONE_WIRE, '#', Blocks.COBBLESTONE)); + recipes.add(RecipeInfo.shaped(Blocks.HOPPER, "I I", "ICI", " I ", 'C', Blocks.CHEST, 'I', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(Blocks.NETHER_BRICKS, "NN", "NN", 'N', Items.NETHER_BRICK)); + recipes.add(RecipeInfo.shaped(Blocks.DAYLIGHT_DETECTOR, "GGG", "QQQ", "WWW", 'Q', Items.QUARTZ, 'G', Blocks.GLASS, 'W', Blocks.OAK_SLAB, Blocks.SPRUCE_SLAB, Blocks.BIRCH_SLAB, Blocks.JUNGLE_SLAB, Blocks.ACACIA_SLAB, Blocks.DARK_OAK_SLAB)); + recipes.add(RecipeInfo.shaped(Blocks.REDSTONE_BLOCK, "###", "###", "###", '#', Blocks.REDSTONE_WIRE)); + recipes.add(RecipeInfo.shaped(9, Blocks.REDSTONE_WIRE, "#", '#', Blocks.REDSTONE_BLOCK)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_4_6tor1_4_7)) { + recipes.add(RecipeInfo.shaped(6, Blocks.NETHER_BRICK_SLAB, "###", '#', Blocks.NETHER_BRICKS)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_4_2)) { + recipes.add(RecipeInfo.shaped(6, Blocks.COBBLESTONE_WALL, "###", "###", '#', Blocks.COBBLESTONE)); + recipes.add(RecipeInfo.shaped(6, Blocks.MOSSY_COBBLESTONE_WALL, "###", "###", '#', Blocks.MOSSY_COBBLESTONE)); + recipes.add(RecipeInfo.shaped(Blocks.FLOWER_POT, "# #", " # ", '#', Items.BRICK)); + recipes.add(RecipeInfo.shaped(Items.CARROT_ON_A_STICK, "# ", " X", '#', Items.FISHING_ROD, 'X', Blocks.CARROTS)); + recipes.add(RecipeInfo.shaped(Items.ITEM_FRAME, "###", "#X#", "###", '#', Items.STICK, 'X', Items.LEATHER)); + recipes.add(RecipeInfo.shaped(Items.GOLDEN_CARROT, "###", "#X#", "###", '#', Items.GOLD_NUGGET, 'X', Blocks.CARROTS)); + recipes.add(RecipeInfo.shaped(Blocks.OAK_BUTTON, "#", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped(Blocks.ANVIL, "III", " i ", "iii", 'I', Blocks.IRON_BLOCK, 'i', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(Blocks.BEACON, "GGG", "GSG", "OOO", 'S', Items.NETHER_STAR, 'G', Blocks.GLASS, 'O', Blocks.OBSIDIAN)); + recipes.add(RecipeInfo.shapeless(Items.PUMPKIN_PIE, Blocks.CARVED_PUMPKIN, Items.SUGAR, Items.EGG)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_3_1tor1_3_2)) { + recipes.add(RecipeInfo.shapeless(Items.WRITABLE_BOOK, Items.BOOK, Items.INK_SAC, Items.FEATHER)); + recipes.add(RecipeInfo.shapeless(Items.BOOK, Items.PAPER, Items.PAPER, Items.PAPER, Items.LEATHER)); + recipes.add(RecipeInfo.shaped(3, Blocks.OAK_SIGN, "###", "###", " X ", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS, 'X', Items.STICK)); + recipes.add(RecipeInfo.shaped("wooden_slab", 6, Blocks.SPRUCE_SLAB, "###", '#', Blocks.SPRUCE_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_slab", 6, Blocks.BIRCH_SLAB, "###", '#', Blocks.BIRCH_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_slab", 6, Blocks.JUNGLE_SLAB, "###", '#', Blocks.JUNGLE_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_slab", 6, Blocks.OAK_SLAB, "###", '#', Blocks.OAK_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_stairs", 4, Blocks.SPRUCE_STAIRS, "# ", "## ", "###", '#', Blocks.SPRUCE_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_stairs", 4, Blocks.BIRCH_STAIRS, "# ", "## ", "###", '#', Blocks.BIRCH_PLANKS)); + recipes.add(RecipeInfo.shaped("wooden_stairs", 4, Blocks.JUNGLE_STAIRS, "# ", "## ", "###", '#', Blocks.JUNGLE_PLANKS)); + recipes.add(RecipeInfo.shaped(4, Blocks.SANDSTONE_STAIRS, "# ", "## ", "###", '#', Blocks.SANDSTONE, Blocks.CHISELED_SANDSTONE, Blocks.CUT_SANDSTONE)); + recipes.add(RecipeInfo.shaped(2, Blocks.TRIPWIRE_HOOK, "I", "S", "#", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS, 'S', Items.STICK, 'I', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(Blocks.ENDER_CHEST, "###", "#E#", "###", '#', Blocks.OBSIDIAN, 'E', Items.ENDER_EYE)); + recipes.add(RecipeInfo.shaped(Blocks.EMERALD_BLOCK, "###", "###", "###", '#', Items.EMERALD)); + recipes.add(RecipeInfo.shaped(9, Items.EMERALD, "#", '#', Blocks.EMERALD_BLOCK)); + } else { + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_2_1tor1_2_3)) { + recipes.add(RecipeInfo.shaped("wooden_slab", 6, Blocks.OAK_SLAB, "###", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + } else { + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.b1_3tob1_3_1)) { + recipes.add(RecipeInfo.shaped("wooden_slab", 3, Blocks.OAK_SLAB, "###", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + } + } + recipes.add(RecipeInfo.shaped(Items.BOOK, "#", "#", "#", '#', Items.PAPER)); + recipes.add(RecipeInfo.shaped(Blocks.OAK_SIGN, "###", "###", " X ", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS, 'X', Items.STICK)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_2_4tor1_2_5)) { + recipes.add(RecipeInfo.shaped("planks", 4, Blocks.BIRCH_PLANKS, "#", '#', Blocks.BIRCH_LOG)); + recipes.add(RecipeInfo.shaped("planks", 4, Blocks.SPRUCE_PLANKS, "#", '#', Blocks.SPRUCE_LOG)); + recipes.add(RecipeInfo.shaped("planks", 4, Blocks.JUNGLE_PLANKS, "#", '#', Blocks.JUNGLE_LOG)); + recipes.add(RecipeInfo.shaped(Blocks.CHISELED_SANDSTONE, "#", "#", '#', Blocks.SANDSTONE_SLAB)); + recipes.add(RecipeInfo.shaped(4, Blocks.CUT_SANDSTONE, "##", "##", '#', Blocks.SANDSTONE)); + } else { + recipes.add(RecipeInfo.shaped("planks", 4, Blocks.OAK_PLANKS, "#", '#', Blocks.BIRCH_LOG, Blocks.SPRUCE_LOG, Blocks.JUNGLE_LOG)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_2_1tor1_2_3)) { + recipes.add(RecipeInfo.shaped(3, Blocks.LADDER, "# #", "###", "# #", '#', Items.STICK)); + recipes.add(RecipeInfo.shaped(6, Blocks.SMOOTH_STONE_SLAB, "###", '#', Blocks.STONE)); + recipes.add(RecipeInfo.shaped(6, Blocks.SANDSTONE_SLAB, "###", '#', Blocks.SANDSTONE, Blocks.CHISELED_SANDSTONE, Blocks.CUT_SANDSTONE)); + recipes.add(RecipeInfo.shaped(6, Blocks.COBBLESTONE_SLAB, "###", '#', Blocks.COBBLESTONE)); + recipes.add(RecipeInfo.shaped(6, Blocks.BRICK_SLAB, "###", '#', Blocks.BRICKS)); + recipes.add(RecipeInfo.shaped(6, Blocks.STONE_BRICK_SLAB, "###", '#', Blocks.STONE_BRICKS, Blocks.MOSSY_STONE_BRICKS, Blocks.CRACKED_STONE_BRICKS, Blocks.CHISELED_STONE_BRICKS)); + recipes.add(RecipeInfo.shaped(Blocks.REDSTONE_LAMP, " R ", "RGR", " R ", 'R', Blocks.REDSTONE_WIRE, 'G', Blocks.GLOWSTONE)); + recipes.add(RecipeInfo.shapeless(3, Items.FIRE_CHARGE, new ItemConvertible[]{Items.GUNPOWDER}, new ItemConvertible[]{Items.BLAZE_POWDER}, new ItemConvertible[]{Items.COAL, Items.CHARCOAL})); + } else { + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.b1_5tob1_5_2)) { + recipes.add(RecipeInfo.shaped(2, Blocks.LADDER, "# #", "###", "# #", '#', Items.STICK)); + } else { + recipes.add(RecipeInfo.shaped(1, Blocks.LADDER, "# #", "###", "# #", '#', Items.STICK)); + } + recipes.add(RecipeInfo.shaped(3, Blocks.SMOOTH_STONE_SLAB, "###", '#', Blocks.STONE)); + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.b1_3tob1_3_1)) { + recipes.add(RecipeInfo.shaped(3, Blocks.SANDSTONE_SLAB, "###", '#', Blocks.SANDSTONE, Blocks.CHISELED_SANDSTONE, Blocks.CUT_SANDSTONE)); + recipes.add(RecipeInfo.shaped(3, Blocks.COBBLESTONE_SLAB, "###", '#', Blocks.COBBLESTONE)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.b1_8tob1_8_1)) { + recipes.add(RecipeInfo.shaped(3, Blocks.BRICK_SLAB, "###", '#', Blocks.BRICKS)); + recipes.add(RecipeInfo.shaped(3, Blocks.STONE_BRICK_SLAB, "###", '#', Blocks.STONE_BRICKS, Blocks.MOSSY_STONE_BRICKS, Blocks.CRACKED_STONE_BRICKS, Blocks.CHISELED_STONE_BRICKS)); + } + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_0_0tor1_0_1)) { + recipes.add(RecipeInfo.shapeless(Items.MUSHROOM_STEW, Blocks.BROWN_MUSHROOM, Blocks.RED_MUSHROOM, Items.BOWL)); + recipes.add(RecipeInfo.shaped(4, Blocks.NETHER_BRICK_STAIRS, "# ", "## ", "###", '#', Blocks.NETHER_BRICKS)); + recipes.add(RecipeInfo.shaped(6, Blocks.NETHER_BRICK_FENCE, "###", "###", '#', Blocks.NETHER_BRICKS)); + recipes.add(RecipeInfo.shaped(3, Items.GLASS_BOTTLE, "# #", " # ", '#', Blocks.GLASS)); + recipes.add(RecipeInfo.shaped(Blocks.BREWING_STAND, " B ", "###", 'B', Items.BLAZE_ROD, '#', Blocks.COBBLESTONE)); + recipes.add(RecipeInfo.shaped(Blocks.CAULDRON, "# #", "# #", "###", '#', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shapeless(Items.ENDER_EYE, Items.ENDER_PEARL, Items.BLAZE_POWDER)); + recipes.add(RecipeInfo.shaped(Blocks.ENCHANTING_TABLE, " B ", "D#D", "###", 'B', Items.BOOK, '#', Blocks.OBSIDIAN, 'D', Items.DIAMOND)); + recipes.add(RecipeInfo.shaped(4, Blocks.PUMPKIN_STEM, "M", 'M', Blocks.CARVED_PUMPKIN)); + recipes.add(RecipeInfo.shapeless(Items.FERMENTED_SPIDER_EYE, Items.SPIDER_EYE, Blocks.BROWN_MUSHROOM, Items.SUGAR)); + recipes.add(RecipeInfo.shapeless(2, Items.BLAZE_POWDER, Items.BLAZE_ROD)); + recipes.add(RecipeInfo.shapeless(Items.MAGMA_CREAM, Items.BLAZE_POWDER, Items.SLIME_BALL)); + recipes.add(RecipeInfo.shaped(9, Items.GOLD_NUGGET, "#", '#', Items.GOLD_INGOT)); + recipes.add(RecipeInfo.shaped("gold_ingot", Items.GOLD_INGOT, "###", "###", "###", '#', Items.GOLD_NUGGET)); + } else { + recipes.add(RecipeInfo.shaped(Items.MUSHROOM_STEW, "Y", "X", "#", 'X', Blocks.BROWN_MUSHROOM, 'Y', Blocks.RED_MUSHROOM, '#', Items.BOWL)); + recipes.add(RecipeInfo.shaped(Items.MUSHROOM_STEW, "Y", "X", "#", 'X', Blocks.RED_MUSHROOM, 'Y', Blocks.BROWN_MUSHROOM, '#', Items.BOWL)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.b1_8tob1_8_1)) { + recipes.add(RecipeInfo.shaped(4, Blocks.BRICK_STAIRS, "# ", "## ", "###", '#', Blocks.BRICKS)); + recipes.add(RecipeInfo.shaped(4, Blocks.STONE_BRICK_STAIRS, "# ", "## ", "###", '#', Blocks.STONE_BRICKS, Blocks.MOSSY_STONE_BRICKS, Blocks.CRACKED_STONE_BRICKS, Blocks.CHISELED_STONE_BRICKS)); + recipes.add(RecipeInfo.shaped(4, Blocks.STONE_BRICKS, "##", "##", '#', Blocks.STONE)); + recipes.add(RecipeInfo.shaped(16, Blocks.IRON_BARS, "###", "###", '#', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(16, Blocks.GLASS_PANE, "###", "###", '#', Blocks.GLASS)); + recipes.add(RecipeInfo.shaped(Blocks.MELON, "MMM", "MMM", "MMM", 'M', Items.MELON_SLICE)); + recipes.add(RecipeInfo.shaped(Blocks.MELON_STEM, "M", 'M', Items.MELON_SLICE)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.b1_7tob1_7_3)) { + recipes.add(RecipeInfo.shaped(Blocks.STICKY_PISTON, "S", "P", 'P', Blocks.PISTON, 'S', Items.SLIME_BALL)); + recipes.add(RecipeInfo.shaped(Blocks.PISTON, "TTT", "#X#", "#R#", 'R', Blocks.REDSTONE_WIRE, '#', Blocks.COBBLESTONE, 'T', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS, 'X', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(Items.SHEARS, " #", "# ", '#', Items.IRON_INGOT)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.b1_6tob1_6_6)) { + recipes.add(RecipeInfo.shaped(Blocks.GLOWSTONE, "##", "##", '#', Items.GLOWSTONE_DUST)); + recipes.add(RecipeInfo.shaped(Blocks.WHITE_WOOL, "##", "##", '#', Blocks.TRIPWIRE)); + recipes.add(RecipeInfo.shaped(2, Blocks.OAK_TRAPDOOR, "###", "###", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped(Items.MAP, "###", "#X#", "###", '#', Items.PAPER, 'X', Items.COMPASS)); + } else { + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.a1_2_0toa1_2_1_1)) { + recipes.add(RecipeInfo.shaped(Blocks.GLOWSTONE, "###", "###", "###", '#', Items.GLOWSTONE_DUST)); + } + recipes.add(RecipeInfo.shaped(Blocks.WHITE_WOOL, "###", "###", "###", '#', Blocks.TRIPWIRE)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.b1_5tob1_5_2)) { + recipes.add(RecipeInfo.shaped(6, Blocks.DETECTOR_RAIL, "X X", "X#X", "XRX", 'R', Blocks.REDSTONE_WIRE, '#', Blocks.STONE_PRESSURE_PLATE, 'X', Items.IRON_INGOT)); + recipes.add(RecipeInfo.shaped(6, Blocks.POWERED_RAIL, "X X", "X#X", "XRX", 'R', Blocks.REDSTONE_WIRE, '#', Items.STICK, 'X', Items.GOLD_INGOT)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.b1_4tob1_4_1)) { + recipes.add(RecipeInfo.shaped(8, Items.COOKIE, "#X#", '#', Items.WHEAT, 'X', Blocks.COCOA)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.b1_3tob1_3_1)) { + recipes.add(RecipeInfo.shaped(Blocks.REPEATER, "#X#", "III", '#', Blocks.REDSTONE_TORCH, 'X', Blocks.REDSTONE_WIRE, 'I', Blocks.STONE)); + recipes.add(RecipeInfo.shaped(Blocks.OAK_PRESSURE_PLATE, "##", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped(Blocks.STONE_PRESSURE_PLATE, "##", '#', Blocks.STONE)); + } else { + recipes.add(RecipeInfo.shaped(Blocks.OAK_PRESSURE_PLATE, "###", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS)); + recipes.add(RecipeInfo.shaped(Blocks.STONE_PRESSURE_PLATE, "###", '#', Blocks.STONE)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.b1_2_0tob1_2_2)) { + recipes.add(RecipeInfo.shaped(Blocks.NOTE_BLOCK, "###", "#X#", "###", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS, 'X', Blocks.REDSTONE_WIRE)); + recipes.add(RecipeInfo.shaped(Blocks.CAKE, "AAA", "BEB", "CCC", 'A', Items.MILK_BUCKET, 'B', Items.SUGAR, 'C', Items.WHEAT, 'E', Items.EGG)); + recipes.add(RecipeInfo.shaped(Items.SUGAR, "#", '#', Blocks.SUGAR_CANE)); + recipes.add(RecipeInfo.shaped(4, Blocks.TORCH, "X", "#", '#', Items.STICK, 'X', Items.COAL, Items.CHARCOAL)); + recipes.add(RecipeInfo.shaped(Blocks.DISPENSER, "###", "#X#", "#R#", 'R', Blocks.REDSTONE_WIRE, '#', Blocks.COBBLESTONE, 'X', Items.BOW)); + recipes.add(RecipeInfo.shaped(Blocks.SANDSTONE, "##", "##", '#', Blocks.SAND)); + recipes.add(RecipeInfo.shapeless("wool", Blocks.YELLOW_WOOL, Items.YELLOW_DYE, Blocks.WHITE_WOOL)); + recipes.add(RecipeInfo.shapeless("yellow_dye", Items.YELLOW_DYE, Blocks.DANDELION)); + recipes.add(RecipeInfo.shapeless("wool", Blocks.RED_WOOL, Items.RED_DYE, Blocks.WHITE_WOOL)); + recipes.add(RecipeInfo.shapeless("red_dye", Items.RED_DYE, Blocks.POPPY)); + recipes.add(RecipeInfo.shapeless("wool", Blocks.PURPLE_WOOL, Items.PURPLE_DYE, Blocks.WHITE_WOOL)); + recipes.add(RecipeInfo.shapeless(2, Items.PURPLE_DYE, Items.LAPIS_LAZULI, Items.RED_DYE)); + recipes.add(RecipeInfo.shapeless("wool", Blocks.PINK_WOOL, Items.PINK_DYE, Blocks.WHITE_WOOL)); + recipes.add(RecipeInfo.shapeless("pink_dye", 2, Items.PINK_DYE, Items.RED_DYE, Items.BONE_MEAL)); + recipes.add(RecipeInfo.shapeless("wool", Blocks.ORANGE_WOOL, Items.ORANGE_DYE, Blocks.WHITE_WOOL)); + recipes.add(RecipeInfo.shapeless("orange_dye", 2, Items.ORANGE_DYE, Items.RED_DYE, Items.YELLOW_DYE)); + recipes.add(RecipeInfo.shapeless("wool", Blocks.MAGENTA_WOOL, Items.MAGENTA_DYE, Blocks.WHITE_WOOL)); + recipes.add(RecipeInfo.shapeless("magenta_dye", 2, Items.MAGENTA_DYE, Items.PURPLE_DYE, Items.PINK_DYE)); + recipes.add(RecipeInfo.shapeless("magenta_dye", 3, Items.MAGENTA_DYE, Items.LAPIS_LAZULI, Items.RED_DYE, Items.PINK_DYE)); + recipes.add(RecipeInfo.shapeless("magenta_dye", 4, Items.MAGENTA_DYE, Items.LAPIS_LAZULI, Items.RED_DYE, Items.RED_DYE, Items.BONE_MEAL)); + recipes.add(RecipeInfo.shapeless("wool", Blocks.LIME_WOOL, Items.LIME_DYE, Blocks.WHITE_WOOL)); + recipes.add(RecipeInfo.shapeless(2, Items.LIME_DYE, Items.GREEN_DYE, Items.BONE_MEAL)); + recipes.add(RecipeInfo.shapeless("wool", Blocks.LIGHT_GRAY_WOOL, Items.LIGHT_GRAY_DYE, Blocks.WHITE_WOOL)); + recipes.add(RecipeInfo.shapeless("light_gray_dye", 3, Items.LIGHT_GRAY_DYE, Items.INK_SAC, Items.BONE_MEAL, Items.BONE_MEAL)); + recipes.add(RecipeInfo.shapeless("light_gray_dye", 2, Items.LIGHT_GRAY_DYE, Items.GRAY_DYE, Items.BONE_MEAL)); + recipes.add(RecipeInfo.shapeless("wool", Blocks.LIGHT_BLUE_WOOL, Items.LIGHT_BLUE_DYE, Blocks.WHITE_WOOL)); + recipes.add(RecipeInfo.shapeless("light_blue_dye", 2, Items.LIGHT_BLUE_DYE, Items.LAPIS_LAZULI, Items.BONE_MEAL)); + recipes.add(RecipeInfo.shapeless("wool", Blocks.GREEN_WOOL, Items.GREEN_DYE, Blocks.WHITE_WOOL)); + recipes.add(RecipeInfo.shapeless("wool", Blocks.GRAY_WOOL, Items.GRAY_DYE, Blocks.WHITE_WOOL)); + recipes.add(RecipeInfo.shapeless(2, Items.GRAY_DYE, Items.INK_SAC, Items.BONE_MEAL)); + recipes.add(RecipeInfo.shapeless("wool", Blocks.CYAN_WOOL, Items.CYAN_DYE, Blocks.WHITE_WOOL)); + recipes.add(RecipeInfo.shapeless(2, Items.CYAN_DYE, Items.LAPIS_LAZULI, Items.GREEN_DYE)); + recipes.add(RecipeInfo.shapeless("wool", Blocks.BLUE_WOOL, Items.LAPIS_LAZULI, Blocks.WHITE_WOOL)); + recipes.add(RecipeInfo.shapeless("wool", Blocks.BLACK_WOOL, Items.INK_SAC, Blocks.WHITE_WOOL)); + recipes.add(RecipeInfo.shapeless("wool", Blocks.BROWN_WOOL, Blocks.COCOA, Blocks.WHITE_WOOL)); + recipes.add(RecipeInfo.shapeless("bonemeal", 3, Items.BONE_MEAL, Items.BONE)); + recipes.add(RecipeInfo.shaped(9, Items.LAPIS_LAZULI, "#", '#', Blocks.LAPIS_BLOCK)); + recipes.add(RecipeInfo.shaped(Blocks.LAPIS_BLOCK, "###", "###", "###", '#', Items.LAPIS_LAZULI)); + } else { + recipes.add(RecipeInfo.shaped(4, Blocks.TORCH, "X", "#", '#', Items.STICK, 'X', Items.COAL)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.a1_2_0toa1_2_1_1)) { + recipes.add(RecipeInfo.shaped(Blocks.JACK_O_LANTERN, "A", "B", 'A', Blocks.CARVED_PUMPKIN, 'B', Blocks.TORCH)); + recipes.add(RecipeInfo.shaped(Items.CLOCK, " # ", "#X#", " # ", '#', Items.GOLD_INGOT, 'X', Blocks.REDSTONE_WIRE)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.a1_1_0toa1_1_2_1)) { + recipes.add(RecipeInfo.shaped(Items.FISHING_ROD, " #", " #X", "# X", '#', Items.STICK, 'X', Blocks.TRIPWIRE)); + recipes.add(RecipeInfo.shaped(Items.COMPASS, " # ", "#X#", " # ", '#', Items.IRON_INGOT, 'X', Blocks.REDSTONE_WIRE)); + } + + recipes.add(RecipeInfo.smelting(Items.IRON_INGOT, Items.IRON_ORE, 0.7F)); + recipes.add(RecipeInfo.smelting(Items.GOLD_INGOT, Items.GOLD_ORE, 1.0F)); + recipes.add(RecipeInfo.smelting(Items.DIAMOND, Items.DIAMOND_ORE, 1.0F)); + recipes.add(RecipeInfo.smelting(Items.GLASS, Ingredient.fromTag(ItemTags.SAND), 0.1F)); + recipes.add(RecipeInfo.smelting(Items.COOKED_PORKCHOP, Items.PORKCHOP, 0.35F)); + recipes.add(RecipeInfo.smelting(Items.STONE, Items.COBBLESTONE, 0.1F)); + recipes.add(RecipeInfo.smelting(Items.BRICK, Items.CLAY_BALL, 0.3F)); + + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_12)) { + recipes.add(RecipeInfo.smelting(Items.WHITE_GLAZED_TERRACOTTA, Items.WHITE_TERRACOTTA, 0.1F)); + recipes.add(RecipeInfo.smelting(Items.ORANGE_GLAZED_TERRACOTTA, Items.ORANGE_TERRACOTTA, 0.1F)); + recipes.add(RecipeInfo.smelting(Items.MAGENTA_GLAZED_TERRACOTTA, Items.MAGENTA_TERRACOTTA, 0.1F)); + recipes.add(RecipeInfo.smelting(Items.LIGHT_BLUE_GLAZED_TERRACOTTA, Items.LIGHT_BLUE_TERRACOTTA, 0.1F)); + recipes.add(RecipeInfo.smelting(Items.YELLOW_GLAZED_TERRACOTTA, Items.YELLOW_TERRACOTTA, 0.1F)); + recipes.add(RecipeInfo.smelting(Items.LIME_GLAZED_TERRACOTTA, Items.LIME_TERRACOTTA, 0.1F)); + recipes.add(RecipeInfo.smelting(Items.PINK_GLAZED_TERRACOTTA, Items.PINK_TERRACOTTA, 0.1F)); + recipes.add(RecipeInfo.smelting(Items.GRAY_GLAZED_TERRACOTTA, Items.GRAY_TERRACOTTA, 0.1F)); + recipes.add(RecipeInfo.smelting(Items.LIGHT_GRAY_GLAZED_TERRACOTTA, Items.LIGHT_GRAY_TERRACOTTA, 0.1F)); + recipes.add(RecipeInfo.smelting(Items.CYAN_GLAZED_TERRACOTTA, Items.CYAN_TERRACOTTA, 0.1F)); + recipes.add(RecipeInfo.smelting(Items.PURPLE_GLAZED_TERRACOTTA, Items.PURPLE_TERRACOTTA, 0.1F)); + recipes.add(RecipeInfo.smelting(Items.BLUE_GLAZED_TERRACOTTA, Items.BLUE_TERRACOTTA, 0.1F)); + recipes.add(RecipeInfo.smelting(Items.BROWN_GLAZED_TERRACOTTA, Items.BROWN_TERRACOTTA, 0.1F)); + recipes.add(RecipeInfo.smelting(Items.GREEN_GLAZED_TERRACOTTA, Items.GREEN_TERRACOTTA, 0.1F)); + recipes.add(RecipeInfo.smelting(Items.RED_GLAZED_TERRACOTTA, Items.RED_TERRACOTTA, 0.1F)); + recipes.add(RecipeInfo.smelting(Items.BLACK_GLAZED_TERRACOTTA, Items.BLACK_TERRACOTTA, 0.1F)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_11_1to1_11_2)) { + recipes.add(RecipeInfo.smelting(Items.IRON_NUGGET, Ingredient.ofItems(Items.CHAINMAIL_HELMET, Items.CHAINMAIL_CHESTPLATE, Items.CHAINMAIL_LEGGINGS, Items.CHAINMAIL_BOOTS, Items.IRON_PICKAXE, Items.IRON_SHOVEL, Items.IRON_AXE, Items.IRON_HOE, Items.IRON_SWORD, Items.IRON_HELMET, Items.IRON_CHESTPLATE, Items.IRON_LEGGINGS, Items.IRON_BOOTS, Items.IRON_HORSE_ARMOR), 0.1F)); + recipes.add(RecipeInfo.smelting(Items.GOLD_NUGGET, Ingredient.ofItems(Items.GOLDEN_PICKAXE, Items.GOLDEN_SHOVEL, Items.GOLDEN_AXE, Items.GOLDEN_HOE, Items.GOLDEN_SWORD, Items.GOLDEN_HELMET, Items.GOLDEN_CHESTPLATE, Items.GOLDEN_LEGGINGS, Items.GOLDEN_BOOTS, Items.GOLDEN_HORSE_ARMOR), 0.1F)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_9)) { + recipes.add(RecipeInfo.smelting(Items.POPPED_CHORUS_FRUIT, Items.CHORUS_FRUIT, 0.1F)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_7_2tor1_7_5)) { + recipes.add(RecipeInfo.smelting(Items.COOKED_RABBIT, Items.RABBIT, 0.35F)); + recipes.add(RecipeInfo.smelting(Items.COOKED_MUTTON, Items.MUTTON, 0.35F)); + recipes.add(RecipeInfo.smelting(Items.CRACKED_STONE_BRICKS, Items.STONE_BRICKS, 0.1F)); + recipes.add(RecipeInfo.smelting(Items.SPONGE, Items.WET_SPONGE, 0.15F)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_6_1)) { + recipes.add(RecipeInfo.smelting(Items.TERRACOTTA, Items.CLAY, 0.35F)); + recipes.add(RecipeInfo.smelting(Items.COOKED_SALMON, Items.SALMON, 0.35F)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_5tor1_5_1)) { + recipes.add(RecipeInfo.smelting(Items.NETHER_BRICK, Items.NETHERRACK, 0.1F)); + recipes.add(RecipeInfo.smelting(Items.QUARTZ, Items.NETHER_QUARTZ_ORE, 0.2F)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_4_2)) { + recipes.add(RecipeInfo.smelting(Items.BAKED_POTATO, Items.POTATO, 0.35F)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_3_1tor1_3_2)) { + recipes.add(RecipeInfo.smelting(Items.EMERALD, Items.EMERALD_ORE, 1.0F)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_0_0tor1_0_1)) { + recipes.add(RecipeInfo.smelting(Items.COAL, Items.COAL_ORE, 0.1F)); + recipes.add(RecipeInfo.smelting(Items.REDSTONE, Items.REDSTONE_ORE, 0.7F)); + recipes.add(RecipeInfo.smelting(Items.LAPIS_LAZULI, Items.LAPIS_ORE, 0.2F)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.b1_8tob1_8_1)) { + recipes.add(RecipeInfo.smelting(Items.COOKED_CHICKEN, Items.CHICKEN, 0.35F)); + recipes.add(RecipeInfo.smelting(Items.COOKED_BEEF, Items.BEEF, 0.35F)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.b1_2_0tob1_2_2)) { + recipes.add(RecipeInfo.smelting(Items.CHARCOAL, Ingredient.fromTag(ItemTags.LOGS), 0.15F)); + recipes.add(RecipeInfo.smelting(Items.GREEN_DYE, Items.CACTUS, 0.2F)); + } + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.a1_2_0toa1_2_1_1)) { + recipes.add(RecipeInfo.smelting(Items.COOKED_COD, Items.COD, 0.35F)); + } + + return recipes; + } + + /** + * Sets the result slot of a crafting screen handler to the correct item stack. In MC <= 1.11.2 the result slot + * is not updated when the input slots change, so we need to update it manually, Spigot and Paper re-syncs the slot, + * so we don't notice this bug on servers that use Spigot or Paper + * + * @param syncId The sync id of the screen handler + * @param screenHandler The screen handler + * @param inventory The inventory of the screen handler + */ + public static void setCraftingResultSlot(final int syncId, final ScreenHandler screenHandler, final RecipeInputInventory inventory) { + final var network = MinecraftClient.getInstance().getNetworkHandler(); + final var world = MinecraftClient.getInstance().world; + + final var result = network.getRecipeManager() + .getFirstMatch(RecipeType.CRAFTING, inventory, world) // Get the first matching recipe + .map(recipe -> recipe.value().craft(inventory, network.getRegistryManager())) // Craft the recipe to get the result + .orElse(ItemStack.EMPTY); // If there is no recipe, set the result to air + + // Update the result slot + network.onScreenHandlerSlotUpdate(new ScreenHandlerSlotUpdateS2CPacket(syncId, screenHandler.getRevision(), 0, result)); + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/access/IChunkTracker.java b/src/main/java/de/florianmichael/viafabricplus/injection/access/IChunkTracker.java new file mode 100644 index 000000000..b25600dfb --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/access/IChunkTracker.java @@ -0,0 +1,30 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.access; + +public interface IChunkTracker { + + int viaFabricPlus$getSubChunkRequests(); + + int viaFabricPlus$getPendingSubChunks(); + + int viaFabricPlus$getChunks(); + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/access/IItemStack.java b/src/main/java/de/florianmichael/viafabricplus/injection/access/IItemStack.java index d1d4a5e22..840bb0daf 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/access/IItemStack.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/access/IItemStack.java @@ -21,7 +21,7 @@ public interface IItemStack { - boolean viaFabricPlus$has1_10ProtocolHackTag(); + boolean viaFabricPlus$has1_10ViaFabricPlusTag(); int viaFabricPlus$get1_10Count(); diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/access/IMouseKeyboard.java b/src/main/java/de/florianmichael/viafabricplus/injection/access/IMouseKeyboard.java new file mode 100644 index 000000000..73af73370 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/access/IMouseKeyboard.java @@ -0,0 +1,28 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.access; + +import java.util.Queue; + +public interface IMouseKeyboard { + + Queue viaFabricPlus$getPendingScreenEvents(); + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/access/IRakSessionCodec.java b/src/main/java/de/florianmichael/viafabricplus/injection/access/IRakSessionCodec.java new file mode 100644 index 000000000..013ceab06 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/access/IRakSessionCodec.java @@ -0,0 +1,28 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.access; + +public interface IRakSessionCodec { + + int viaFabricPlus$getOutgoingPackets(); + + int viaFabricPlus$SentDatagrams(); + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/access/IScreenHandler.java b/src/main/java/de/florianmichael/viafabricplus/injection/access/IScreenHandler.java index dc59f8216..1f8e8ed5c 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/access/IScreenHandler.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/access/IScreenHandler.java @@ -21,5 +21,8 @@ public interface IScreenHandler { - short viaFabricPlus$getAndIncrementLastActionId(); + short viaFabricPlus$getActionId(); + + short viaFabricPlus$incrementAndGetActionId(); + } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinChunkTracker.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinChunkTracker.java new file mode 100644 index 000000000..96e146580 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinChunkTracker.java @@ -0,0 +1,62 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.base.integration; + +import de.florianmichael.viafabricplus.injection.access.IChunkTracker; +import net.raphimc.viabedrock.api.chunk.BedrockChunk; +import net.raphimc.viabedrock.protocol.storage.ChunkTracker; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Map; +import java.util.Set; + +@Mixin(value = ChunkTracker.class, remap = false) +public abstract class MixinChunkTracker implements IChunkTracker { + + @Shadow + @Final + private Set subChunkRequests; + + @Shadow + @Final + private Set pendingSubChunks; + + @Shadow + @Final + private Map chunks; + + @Override + public int viaFabricPlus$getSubChunkRequests() { + return this.subChunkRequests.size(); + } + + @Override + public int viaFabricPlus$getPendingSubChunks() { + return this.pendingSubChunks.size(); + } + + @Override + public int viaFabricPlus$getChunks() { + return this.chunks.size(); + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinConnectScreen_1.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinConnectScreen_1.java index 44a1fd494..62dc0687e 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinConnectScreen_1.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinConnectScreen_1.java @@ -19,30 +19,71 @@ package de.florianmichael.viafabricplus.injection.mixin.base.integration; +import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; import de.florianmichael.viafabricplus.ViaFabricPlus; -import de.florianmichael.viafabricplus.protocolhack.provider.vialegacy.ViaFabricPlusClassicMPPassProvider; -import de.florianmichael.viafabricplus.settings.impl.AuthenticationSettings; -import net.minecraft.client.MinecraftClient; -import net.minecraft.network.ClientConnection; -import net.minecraft.network.packet.Packet; -import net.minecraft.network.packet.c2s.login.LoginHelloC2SPacket; +import de.florianmichael.viafabricplus.injection.access.IServerInfo; +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import de.florianmichael.viafabricplus.settings.impl.GeneralSettings; +import net.lenni0451.mcping.MCPing; +import net.minecraft.client.gui.screen.ConnectScreen; +import net.minecraft.client.network.ServerInfo; +import net.minecraft.client.session.Session; +import net.minecraft.text.Text; +import net.raphimc.vialoader.util.VersionEnum; +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.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import java.net.InetSocketAddress; @Mixin(targets = "net.minecraft.client.gui.screen.ConnectScreen$1") public abstract class MixinConnectScreen_1 { - @Redirect(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;send(Lnet/minecraft/network/packet/Packet;)V")) - private void spoofUserName(ClientConnection instance, Packet packet) { - if (AuthenticationSettings.global().setSessionNameToClassiCubeNameInServerList.getValue() && ViaFabricPlusClassicMPPassProvider.classiCubeMPPass != null) { - final var account = ViaFabricPlus.global().getSaveManager().getAccountsSave().getClassicubeAccount(); - if (account != null) { - instance.send(new LoginHelloC2SPacket(account.username(), MinecraftClient.getInstance().getSession().getUuidOrNull())); - return; - } + @Shadow + @Final + ServerInfo field_40415; + + @Shadow + @Final + ConnectScreen field_2416; + + @Redirect(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/session/Session;getUsername()Ljava/lang/String;")) + private String useClassiCubeUsername(Session instance) { + final var account = ViaFabricPlus.global().getSaveManager().getAccountsSave().getClassicubeAccount(); + if (account != null) { + return account.username(); } - instance.send(packet); + return instance.getUsername(); } -} \ No newline at end of file + + @SuppressWarnings("InvalidInjectorMethodSignature") + @Inject(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;connect(Ljava/net/InetSocketAddress;ZLnet/minecraft/network/ClientConnection;)Lio/netty/channel/ChannelFuture;", shift = At.Shift.BEFORE), locals = LocalCapture.CAPTURE_FAILHARD) + private void setServerInfo(CallbackInfo ci, InetSocketAddress inetSocketAddress) { + final VersionEnum serverVersion = ((IServerInfo) this.field_40415).viaFabricPlus$forcedVersion(); + if (serverVersion != null) { + ProtocolHack.setTargetVersion(serverVersion); + } else if (GeneralSettings.global().autoDetectVersion.getValue()) { + this.field_2416.setStatus(Text.translatable("base.viafabricplus.detecting_server_version")); + MCPing + .pingModern(-1) + .address(inetSocketAddress.getHostString(), inetSocketAddress.getPort()) + .noResolve() + .timeout(1000, 1000) + .exceptionHandler(t -> { + }) + .responseHandler(r -> { + if (ProtocolVersion.isRegistered(r.version.protocol)) { + ProtocolHack.setTargetVersion(VersionEnum.fromProtocolId(r.version.protocol)); + } + }) + .getSync(); + } + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinDebugHud.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinDebugHud.java index 400bd170b..4ac62ab8e 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinDebugHud.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinDebugHud.java @@ -26,21 +26,26 @@ import de.florianmichael.viafabricplus.fixes.tracker.JoinGameTracker; import de.florianmichael.viafabricplus.injection.ViaFabricPlusMixinPlugin; import de.florianmichael.viafabricplus.injection.access.IBlobCache; +import de.florianmichael.viafabricplus.injection.access.IChunkTracker; +import de.florianmichael.viafabricplus.injection.access.IRakSessionCodec; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; import de.florianmichael.viafabricplus.protocolhack.provider.viabedrock.ViaFabricPlusBlobCacheProvider; import de.florianmichael.viafabricplus.settings.impl.GeneralSettings; import de.florianmichael.viafabricplus.util.ChatUtil; import de.florianmichael.viafabricplus.util.StringUtil; -import net.lenni0451.reflect.stream.RStream; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.hud.DebugHud; +import net.minecraft.util.Formatting; import net.raphimc.viabedrock.protocol.data.enums.bedrock.ServerMovementModes; import net.raphimc.viabedrock.protocol.providers.BlobCacheProvider; import net.raphimc.viabedrock.protocol.storage.BlobCache; +import net.raphimc.viabedrock.protocol.storage.ChunkTracker; import net.raphimc.viabedrock.protocol.storage.GameSessionStorage; import net.raphimc.vialegacy.protocols.classic.protocolc0_28_30toc0_28_30cpe.storage.ExtensionProtocolMetadataStorage; import net.raphimc.vialegacy.protocols.release.protocol1_2_1_3to1_1.storage.SeedStorage; import net.raphimc.vialegacy.protocols.release.protocol1_8to1_7_6_10.storage.EntityTracker; +import org.cloudburstmc.netty.channel.raknet.RakClientChannel; +import org.cloudburstmc.netty.handler.codec.raknet.common.RakSessionCodec; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -48,8 +53,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; @SuppressWarnings("DataFlowIssue") @Mixin(DebugHud.class) @@ -69,19 +72,39 @@ public void addViaFabricPlusInformation(CallbackInfoReturnable> cir information.add(""); // Title - information.add(ChatUtil.PREFIX + " " + ViaFabricPlusMixinPlugin.VFP_VERSION); + information.add(ChatUtil.PREFIX + Formatting.GRAY + " " + ViaFabricPlusMixinPlugin.VFP_VERSION); // common final ProtocolInfo info = userConnection.getProtocolInfo(); information.add( - "P: " + info.getPipeline().pipes().size() + - " / C: " + ProtocolVersion.getProtocol(info.getProtocolVersion()) + - " / S: " + ProtocolVersion.getProtocol(info.getServerProtocolVersion()) + "P: " + info.getPipeline().pipes().size() + + " C: " + ProtocolVersion.getProtocol(info.getProtocolVersion()) + + " S: " + ProtocolVersion.getProtocol(info.getServerProtocolVersion()) ); + // r1_7_10 + final EntityTracker entityTracker1_7_10 = userConnection.get(EntityTracker.class); + if (entityTracker1_7_10 != null) { + information.add( + "1.7 Entities: " + entityTracker1_7_10.getTrackedEntities().size() + + ", Virtual holograms: " + entityTracker1_7_10.getVirtualHolograms().size() + ); + } + + // r1_1 + final SeedStorage seedStorage = userConnection.get(SeedStorage.class); + if (seedStorage != null) { + information.add("World Seed: " + seedStorage.seed); + } + + // c0.30cpe + final ExtensionProtocolMetadataStorage extensionProtocolMetadataStorage = userConnection.get(ExtensionProtocolMetadataStorage.class); + if (extensionProtocolMetadataStorage != null) { + information.add("CPE extensions: " + extensionProtocolMetadataStorage.getExtensionCount()); + } + // bedrock final JoinGameTracker joinGameTracker = userConnection.get(JoinGameTracker.class); - if (joinGameTracker != null) { final int movementMode = userConnection.get(GameSessionStorage.class).getMovementMode(); String movement = "Server with rewind"; @@ -91,7 +114,10 @@ public void addViaFabricPlusInformation(CallbackInfoReturnable> cir movement = "Server"; } - information.add("Bedrock Level: " + joinGameTracker.getLevelId() + " / Enchantment Seed: " + joinGameTracker.getEnchantmentSeed() + " / Movement: " + movement); + information.add("Bedrock Level: " + joinGameTracker.getLevelId() + ", Enchantment Seed: " + joinGameTracker.getEnchantmentSeed() + ", Movement: " + movement); + } + if (joinGameTracker != null) { + information.add("World Seed: " + joinGameTracker.getSeed()); } final BlobCache blobCache = userConnection.get(BlobCache.class); if (blobCache != null) { @@ -101,32 +127,22 @@ public void addViaFabricPlusInformation(CallbackInfoReturnable> cir final int blobCount = blobCacheProvider.getBlobs().size(); final int pendingCount = ((IBlobCache) blobCache).viaFabricPlus$getPending().size(); - if (totalSize != 0 || blobCount != 0 || pendingCount != 0) { - information.add("Blob Cache: S: " + StringUtil.formatBytes(totalSize) + " / C: " + blobCount + " / Pending: " + pendingCount); - } - } - - // r1_7_10 - final EntityTracker entityTracker1_7_10 = userConnection.get(EntityTracker.class); - if (entityTracker1_7_10 != null) { - information.add( - "1.7 Entities: " + entityTracker1_7_10.getTrackedEntities().size() + - " / Virtual holograms: " + entityTracker1_7_10.getVirtualHolograms().size() - ); + information.add("Blob Cache: S: " + StringUtil.formatBytes(totalSize) + ", C: " + blobCount + ", P: " + pendingCount); } - - // r1_1 and bedrock - final SeedStorage seedStorage = userConnection.get(SeedStorage.class); - if (seedStorage != null) { - information.add("World Seed: " + seedStorage.seed); - } else if (joinGameTracker != null) { - information.add("World Seed: " + joinGameTracker.getSeed()); + final ChunkTracker chunkTracker = userConnection.get(ChunkTracker.class); + if (chunkTracker != null) { + final int subChunkRequests = ((IChunkTracker) chunkTracker).viaFabricPlus$getSubChunkRequests(); + final int pendingSubChunks = ((IChunkTracker) chunkTracker).viaFabricPlus$getPendingSubChunks(); + final int chunks = ((IChunkTracker) chunkTracker).viaFabricPlus$getChunks(); + cir.getReturnValue().add("Chunk Tracker: R: " + subChunkRequests + ", P: " + pendingSubChunks + ", C: " + chunks); } - - // c0.30cpe - final ExtensionProtocolMetadataStorage extensionProtocolMetadataStorage = userConnection.get(ExtensionProtocolMetadataStorage.class); - if (extensionProtocolMetadataStorage != null) { - information.add("CPE extensions: " + extensionProtocolMetadataStorage.getExtensionCount()); + if (userConnection.getChannel() instanceof RakClientChannel rakClientChannel) { + final RakSessionCodec rakSessionCodec = rakClientChannel.parent().pipeline().get(RakSessionCodec.class); + if (rakSessionCodec != null) { + final int transmitQueue = ((IRakSessionCodec) rakSessionCodec).viaFabricPlus$getOutgoingPackets(); + final int retransmitQueue = ((IRakSessionCodec) rakSessionCodec).viaFabricPlus$SentDatagrams(); + cir.getReturnValue().add("RTT: " + Math.round(rakSessionCodec.getRTT()) + " ms, P: " + rakSessionCodec.getPing() + " ms" + ", TQ: " + transmitQueue + ", RTQ: " + retransmitQueue); + } } information.add(""); diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinDownloadingTerrainScreen.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinDownloadingTerrainScreen.java index 226d8908b..1e6fb79f2 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinDownloadingTerrainScreen.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinDownloadingTerrainScreen.java @@ -45,6 +45,9 @@ private void renderClassicProgress(DrawContext context, int mouseX, int mouseY, if (GeneralSettings.global().showClassicLoadingProgressInConnectScreen.getValue()) { // Check if ViaVersion is translating final UserConnection connection = ProtocolHack.getPlayNetworkUserConnection(); + if (connection == null) { + return; + } // Check if the client is connecting to a classic server final ClassicProgressStorage classicProgressStorage = connection.get(ClassicProgressStorage.class); diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinMultiplayerServerListWidget_ServerEntry.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinMultiplayerServerListWidget_ServerEntry.java index 4a55a7b8e..4d8cf3417 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinMultiplayerServerListWidget_ServerEntry.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinMultiplayerServerListWidget_ServerEntry.java @@ -21,20 +21,15 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import de.florianmichael.viafabricplus.injection.access.IServerInfo; -import de.florianmichael.viafabricplus.settings.impl.GeneralSettings; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget; import net.minecraft.client.network.ServerInfo; import net.minecraft.text.Text; -import net.raphimc.vialoader.util.VersionEnum; 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 java.util.ArrayList; import java.util.List; @Mixin(MultiplayerServerListWidget.ServerEntry.class) @@ -46,7 +41,7 @@ public abstract class MixinMultiplayerServerListWidget_ServerEntry { @WrapOperation(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/multiplayer/MultiplayerScreen;setMultiplayerScreenTooltip(Ljava/util/List;)V", ordinal = 0)) private void drawTranslatingState(MultiplayerScreen instance, List tooltip, Operation original) { - if (GeneralSettings.global().showAdvertisedServerVersion.getValue()) { + /*if (GeneralSettings.global().showAdvertisedServerVersion.getValue()) { final IServerInfo mixinServerInfo = ((IServerInfo) server); if (mixinServerInfo.viaFabricPlus$enabled()) { @@ -55,7 +50,7 @@ private void drawTranslatingState(MultiplayerScreen instance, List tooltip tooltip.add(Text.translatable("base.viafabricplus.via_translates_to", versionEnum != VersionEnum.UNKNOWN ? versionEnum.getName() + " (" + versionEnum.getVersion() + ")" : mixinServerInfo.viaFabricPlus$translatingVersion())); tooltip.add(Text.translatable("base.viafabricplus.server_version", server.version.getString() + " (" + server.protocolVersion + ")")); } - } + }*/ original.call(instance, tooltip); } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinRakSessionCodec.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinRakSessionCodec.java new file mode 100644 index 000000000..45b180fe2 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/base/integration/MixinRakSessionCodec.java @@ -0,0 +1,50 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.base.integration; + +import de.florianmichael.viafabricplus.injection.access.IRakSessionCodec; +import io.netty.util.collection.IntObjectMap; +import org.cloudburstmc.netty.channel.raknet.packet.EncapsulatedPacket; +import org.cloudburstmc.netty.channel.raknet.packet.RakDatagramPacket; +import org.cloudburstmc.netty.handler.codec.raknet.common.RakSessionCodec; +import org.cloudburstmc.netty.util.FastBinaryMinHeap; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(value = RakSessionCodec.class, remap = false) +public abstract class MixinRakSessionCodec implements IRakSessionCodec { + + @Shadow + private FastBinaryMinHeap outgoingPackets; + + @Shadow + private IntObjectMap sentDatagrams; + + @Override + public int viaFabricPlus$getOutgoingPackets() { + return this.outgoingPackets.size(); + } + + @Override + public int viaFabricPlus$SentDatagrams() { + return this.sentDatagrams.size(); + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/authlib/MixinKeyPairResponse.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/authlib/MixinKeyPairResponse.java index ed8714399..4bbedd86a 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/authlib/MixinKeyPairResponse.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/authlib/MixinKeyPairResponse.java @@ -39,4 +39,5 @@ public abstract class MixinKeyPairResponse implements ILegacyKeySignatureStorage public void viafabricplus$setLegacyPublicKeySignature(byte[] signature) { this.viaFabricPlus$legacyKeySignature = signature; } + } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/authlib/MixinYggdrasilUserApiService.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/authlib/MixinYggdrasilUserApiService.java index 247bdce90..321f01258 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/authlib/MixinYggdrasilUserApiService.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/authlib/MixinYggdrasilUserApiService.java @@ -22,8 +22,9 @@ import com.mojang.authlib.minecraft.client.MinecraftClient; import com.mojang.authlib.yggdrasil.YggdrasilUserApiService; import com.mojang.authlib.yggdrasil.response.KeyPairResponse; -import de.florianmichael.viafabricplus.injection.reference.KeyPairResponse1_19_0; +import de.florianmichael.viafabricplus.ViaFabricPlus; import de.florianmichael.viafabricplus.injection.access.ILegacyKeySignatureStorage; +import de.florianmichael.viafabricplus.injection.reference.KeyPairResponse1_19_0; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -36,9 +37,13 @@ @Mixin(value = YggdrasilUserApiService.class, remap = false) public abstract class MixinYggdrasilUserApiService { - @Shadow @Final private MinecraftClient minecraftClient; + @Shadow + @Final + private MinecraftClient minecraftClient; - @Shadow @Final private URL routeKeyPair; + @Shadow + @Final + private URL routeKeyPair; @Inject(method = "getKeyPair", at = @At("HEAD"), cancellable = true) private void storeLegacyPublicKeySignature(CallbackInfoReturnable cir) { @@ -58,8 +63,11 @@ private void storeLegacyPublicKeySignature(CallbackInfoReturnable. */ -package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen; +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; -import de.florianmichael.viafabricplus.fixes.TripleChestHandler1_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.minecraft.client.network.Address; +import net.minecraft.client.network.AddressResolver; +import net.minecraft.client.network.AllowedAddressResolver; +import net.minecraft.client.network.ServerAddress; import net.raphimc.vialoader.util.VersionEnum; -import org.jetbrains.annotations.Nullable; +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.callback.CallbackInfoReturnable; -@Mixin(HandledScreens.class) -public abstract class MixinHandledScreens { +import java.util.Optional; - @Inject(method = "getProvider", at = @At("HEAD"), cancellable = true) - private static void returnFakeProvider(ScreenHandlerType type, CallbackInfoReturnable cir) { - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_13_2) && type instanceof TripleChestHandler1_13_2.TripleChestScreenHandlerType) { - cir.setReturnValue((handler, playerInventory, title) -> new GenericContainerScreen((GenericContainerScreenHandler) handler, playerInventory, title)); +@Mixin(AllowedAddressResolver.class) +public abstract class MixinAllowedAddressResolver { + + @Shadow + @Final + private AddressResolver addressResolver; + + @Inject(method = "resolve", at = @At("HEAD"), cancellable = true) + private void oldResolveBehaviour(ServerAddress address, CallbackInfoReturnable> cir) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_16_4tor1_16_5) || ProtocolHack.getTargetVersion().equals(VersionEnum.bedrockLatest)) { + cir.setReturnValue(this.addressResolver.resolve(address)); } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/merchant/MixinMerchantScreenHandler.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinBuiltChunk.java similarity index 75% rename from src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/merchant/MixinMerchantScreenHandler.java rename to src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinBuiltChunk.java index d3a7c9988..3e2ff1c57 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/merchant/MixinMerchantScreenHandler.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinBuiltChunk.java @@ -17,24 +17,23 @@ * along with this program. If not, see . */ -package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen.merchant; +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; -import net.raphimc.vialoader.util.VersionEnum; -import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; -import net.minecraft.screen.MerchantScreenHandler; +import net.minecraft.client.render.chunk.ChunkBuilder; +import net.raphimc.vialoader.util.VersionEnum; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -@Mixin(MerchantScreenHandler.class) -public abstract class MixinMerchantScreenHandler { +@Mixin(ChunkBuilder.BuiltChunk.class) +public abstract class MixinBuiltChunk { - @Inject(method = "switchTo", at = @At("HEAD"), cancellable = true) - private void dontSwitchTo(int recipeId, CallbackInfo ci) { - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_13_2)) { - ci.cancel(); + @Inject(method = "shouldBuild", at = @At("HEAD"), cancellable = true) + private void modifyRenderCondition(CallbackInfoReturnable cir) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) { + cir.setReturnValue(true); } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinChatInputSuggestor.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinChatInputSuggestor.java new file mode 100644 index 000000000..177e565f2 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinChatInputSuggestor.java @@ -0,0 +1,95 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; + +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ChatInputSuggestor; +import net.minecraft.client.gui.widget.TextFieldWidget; +import net.minecraft.text.OrderedText; +import net.minecraft.text.Style; +import net.raphimc.vialoader.util.VersionEnum; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.glfw.GLFW; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.List; + +@Mixin(ChatInputSuggestor.class) +public abstract class MixinChatInputSuggestor { + + @Shadow + public abstract void refresh(); + + @Shadow + @Nullable + private ChatInputSuggestor.@Nullable SuggestionWindow window; + + @Shadow + @Final + TextFieldWidget textField; + + @Shadow + @Final + private List messages; + + @Inject(method = "provideRenderText", at = @At(value = "HEAD"), cancellable = true) + private void disableTextFieldColors(String original, int firstCharacterIndex, CallbackInfoReturnable cir) { + if (!this.cancelTabComplete()) return; + + cir.setReturnValue(OrderedText.styledForwardsVisitedString(original, Style.EMPTY)); + } + + @Inject(method = "keyPressed", at = @At("HEAD"), cancellable = true) + private void handle1_12_2KeyPressed(int keyCode, int scanCode, int modifiers, CallbackInfoReturnable cir) { + if (!this.cancelTabComplete()) return; + + if (keyCode == GLFW.GLFW_KEY_TAB && this.window == null) { + this.refresh(); + } else if (this.window != null) { + if (this.window.keyPressed(keyCode, scanCode, modifiers)) { + cir.setReturnValue(true); + return; + } + this.textField.setSuggestion(null); + this.window = null; + } + } + + @Inject(method = "render", at = @At("HEAD")) + private void clearMessages(DrawContext drawContext, int mouseX, int mouseY, CallbackInfo ci) { + if (!this.cancelTabComplete()) return; + + this.messages.clear(); + } + + @Unique + private boolean cancelTabComplete() { + return ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_12_2) && this.textField.getText().startsWith("/"); + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinClientCommandSource.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinClientCommandSource.java new file mode 100644 index 000000000..26da11a2e --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinClientCommandSource.java @@ -0,0 +1,49 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; + +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.minecraft.client.network.ClientCommandSource; +import net.raphimc.vialoader.util.VersionEnum; +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.callback.CallbackInfoReturnable; + +import java.util.Collection; +import java.util.Set; + +@Mixin(ClientCommandSource.class) +public abstract class MixinClientCommandSource { + + @Shadow + @Final + private Set chatSuggestions; + + @Inject(method = {"getPlayerNames", "getChatSuggestions"}, at = @At("HEAD"), cancellable = true) + private void returnChatSuggestions(CallbackInfoReturnable> cir) { + if (ProtocolHack.getTargetVersion().equals(VersionEnum.bedrockLatest)) { + cir.setReturnValue(this.chatSuggestions); + } + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinClientPlayerInteractionManager.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinClientPlayerInteractionManager.java deleted file mode 100644 index 4a715bbcc..000000000 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinClientPlayerInteractionManager.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus - * Copyright (C) 2021-2023 FlorianMichael/EnZaXD - * Copyright (C) 2023 RK_01/RaphiMC 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 . - */ - -package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; - -import com.llamalad7.mixinextras.injector.WrapWithCondition; -import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; -import com.viaversion.viaversion.api.type.Type; -import com.viaversion.viaversion.protocols.protocol1_16_2to1_16_1.ServerboundPackets1_16_2; -import com.viaversion.viaversion.protocols.protocol1_17to1_16_4.Protocol1_17To1_16_4; -import de.florianmichael.viafabricplus.ViaFabricPlus; -import de.florianmichael.viafabricplus.fixes.ClientPlayerInteractionManager1_18_2; -import de.florianmichael.viafabricplus.injection.access.IClientConnection; -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.util.ItemTranslator; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.network.ClientPlayerInteractionManager; -import net.minecraft.client.network.SequencedPacketCreator; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.network.packet.Packet; -import net.minecraft.network.packet.c2s.play.ClickSlotC2SPacket; -import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; -import net.minecraft.screen.slot.SlotActionType; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.raphimc.vialoader.util.VersionEnum; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.*; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.List; - -@SuppressWarnings("DataFlowIssue") -@Mixin(ClientPlayerInteractionManager.class) -public abstract class MixinClientPlayerInteractionManager { - - @Shadow - @Final - private MinecraftClient client; - - @Shadow - protected abstract ActionResult interactBlockInternal(ClientPlayerEntity player, Hand hand, BlockHitResult hitResult); - - @Shadow - @Final - private ClientPlayNetworkHandler networkHandler; - - @Shadow - private BlockPos currentBreakingPos; - - @Shadow private float currentBreakingProgress; - @Unique - private ItemStack viaFabricPlus$oldCursorStack; - - @Unique - private List viaFabricPlus$oldItems; - - @Inject(method = "getBlockBreakingProgress", at = @At("HEAD"), cancellable = true) - private void changeCalculation(CallbackInfoReturnable cir) { - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_19_4)) { - cir.setReturnValue((int)(this.currentBreakingProgress * 10.0F) - 1); - } - } - - @Inject(method = "sendSequencedPacket", at = @At("HEAD")) - private void handleBlockAcknowledgements(ClientWorld world, SequencedPacketCreator packetCreator, CallbackInfo ci) { - if (ProtocolHack.getTargetVersion().isBetweenInclusive(VersionEnum.r1_14_4, VersionEnum.r1_18_2) && packetCreator instanceof PlayerActionC2SPacket playerActionC2SPacket) { - ClientPlayerInteractionManager1_18_2.trackBlockAction(playerActionC2SPacket.getAction(), playerActionC2SPacket.getPos()); - } - } - - @ModifyVariable(method = "clickSlot", at = @At(value = "STORE"), ordinal = 0) - private List captureOldItems(List oldItems) { - assert client.player != null; - viaFabricPlus$oldCursorStack = client.player.currentScreenHandler.getCursorStack().copy(); - return this.viaFabricPlus$oldItems = oldItems; - } - - // Special Cases - @Unique - private boolean viaFabricPlus$shouldEmpty(final SlotActionType type, final int slot) { - // quick craft always uses empty stack for verification - if (type == SlotActionType.QUICK_CRAFT) return true; - - // quick move always uses empty stack for verification since 1.12 - if (type == SlotActionType.QUICK_MOVE && ProtocolHack.getTargetVersion().isNewerThan(VersionEnum.r1_11_1to1_11_2)) return true; - - // pickup with slot -999 (outside window) to throw items always uses empty stack for verification - return type == SlotActionType.PICKUP && slot == -999; - } - - @WrapWithCondition(method = "clickSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/packet/Packet;)V")) - private boolean modifySlotClickPacket(ClientPlayNetworkHandler instance, Packet packet) { - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_16_4tor1_16_5) && packet instanceof ClickSlotC2SPacket clickSlot) { - ItemStack slotItemBeforeModification; - - if (this.viaFabricPlus$shouldEmpty(clickSlot.getActionType(), clickSlot.getSlot())) - slotItemBeforeModification = ItemStack.EMPTY; - else if (clickSlot.getSlot() < 0 || clickSlot.getSlot() >= viaFabricPlus$oldItems.size()) - slotItemBeforeModification = viaFabricPlus$oldCursorStack; - else - slotItemBeforeModification = viaFabricPlus$oldItems.get(clickSlot.getSlot()); - - final var clickSlotPacket = PacketWrapper.create(ServerboundPackets1_16_2.CLICK_WINDOW, ((IClientConnection)networkHandler.getConnection()).viaFabricPlus$getUserConnection()); - - clickSlotPacket.write(Type.UNSIGNED_BYTE, (short) clickSlot.getSyncId()); - clickSlotPacket.write(Type.SHORT, (short) clickSlot.getSlot()); - clickSlotPacket.write(Type.BYTE, (byte) clickSlot.getButton()); - clickSlotPacket.write(Type.SHORT, ((IScreenHandler) client.player.currentScreenHandler).viaFabricPlus$getAndIncrementLastActionId()); - clickSlotPacket.write(Type.VAR_INT, clickSlot.getActionType().ordinal()); - clickSlotPacket.write(Type.ITEM1_13_2, ItemTranslator.MC_TO_VIA_LATEST_TO_TARGET(slotItemBeforeModification, VersionEnum.r1_16)); - - try { - clickSlotPacket.sendToServer(Protocol1_17To1_16_4.class); - } catch (Exception e) { - ViaFabricPlus.global().getLogger().error("Failed to send Click Slot Packet", e); - } - - viaFabricPlus$oldCursorStack = null; - viaFabricPlus$oldItems = null; - return false; - } - return true; - } - - @WrapWithCondition(method = "interactItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/packet/Packet;)V", ordinal = 0), - slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;syncSelectedSlot()V"), - to = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;sendSequencedPacket(Lnet/minecraft/client/world/ClientWorld;Lnet/minecraft/client/network/SequencedPacketCreator;)V", ordinal = 0))) - private boolean redirectInteractItem(ClientPlayNetworkHandler instance, Packet packet) { - return ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_17); - } - - @Inject(method = "breakBlock", at = @At("TAIL")) - private void resetBlockBreaking(BlockPos pos, CallbackInfoReturnable cir) { - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_14_3)) { - this.currentBreakingPos = new BlockPos(this.currentBreakingPos.getX(), -1, this.currentBreakingPos.getZ()); - } - } - - @Unique - private ActionResult viaFabricPlus$actionResult; - - @Inject(method = "interactBlock", at = @At("HEAD"), cancellable = true) - private void cacheActionResult(ClientPlayerEntity player, Hand hand, BlockHitResult hitResult, CallbackInfoReturnable cir) { - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_12_2)) { - this.viaFabricPlus$actionResult = this.interactBlockInternal(player, hand, hitResult); - - if (this.viaFabricPlus$actionResult == ActionResult.FAIL) { - cir.setReturnValue(this.viaFabricPlus$actionResult); - } - } - } - - @Redirect(method = "method_41933", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;interactBlockInternal(Lnet/minecraft/client/network/ClientPlayerEntity;Lnet/minecraft/util/Hand;Lnet/minecraft/util/hit/BlockHitResult;)Lnet/minecraft/util/ActionResult;")) - private ActionResult provideCachedResult(ClientPlayerInteractionManager instance, ClientPlayerEntity player, Hand hand, BlockHitResult hitResult) { - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_12_2)) { - return this.viaFabricPlus$actionResult; - } - return interactBlockInternal(player, hand, hitResult); - } - - @Inject(method = "interactItem", at = @At("HEAD")) - private void trackLastUsedItem(PlayerEntity player, Hand hand, CallbackInfoReturnable cir) { - ViaFabricPlusHandItemProvider.lastUsedItem = player.getStackInHand(hand).copy(); - } - - @Inject(method = "interactBlock", at = @At("HEAD")) - private void trackLastUsedBlock(ClientPlayerEntity player, Hand hand, BlockHitResult hitResult, CallbackInfoReturnable cir) { - ViaFabricPlusHandItemProvider.lastUsedItem = player.getStackInHand(hand).copy(); - } - -} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinClientWorld.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinClientWorld.java new file mode 100644 index 000000000..d2e2f5185 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinClientWorld.java @@ -0,0 +1,135 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; + +import de.florianmichael.viafabricplus.fixes.PendingUpdateManager1_18_2; +import de.florianmichael.viafabricplus.injection.access.IEntity; +import de.florianmichael.viafabricplus.settings.impl.DebugSettings; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.network.PendingUpdateManager; +import net.minecraft.client.render.WorldRenderer; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.registry.DynamicRegistryManager; +import net.minecraft.registry.Registries; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.profiler.Profiler; +import net.minecraft.world.EntityList; +import net.minecraft.world.MutableWorldProperties; +import net.minecraft.world.World; +import net.minecraft.world.dimension.DimensionType; +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.function.Supplier; + +@Mixin(value = ClientWorld.class, priority = 900) +public abstract class MixinClientWorld extends World { + + @Shadow + @Final + EntityList entityList; + + @Mutable + @Shadow + @Final + private PendingUpdateManager pendingUpdateManager; + + protected MixinClientWorld(MutableWorldProperties properties, RegistryKey registryRef, DynamicRegistryManager registryManager, RegistryEntry dimensionEntry, Supplier profiler, boolean isClient, boolean debugWorld, long biomeAccess, int maxChainedNeighborUpdates) { + super(properties, registryRef, registryManager, dimensionEntry, profiler, isClient, debugWorld, biomeAccess, maxChainedNeighborUpdates); + } + + @Inject(method = "", at = @At("RETURN")) + private void removePendingUpdateManager(ClientPlayNetworkHandler networkHandler, ClientWorld.Properties properties, RegistryKey registryRef, RegistryEntry dimensionTypeEntry, int loadDistance, int simulationDistance, Supplier profiler, WorldRenderer worldRenderer, boolean debugWorld, long seed, CallbackInfo ci) { + if (DebugSettings.global().disableSequencing.isEnabled()) { + this.pendingUpdateManager = new PendingUpdateManager1_18_2(); + } + } + + /** + * @author RK_01 + * @reason ProtocolHack + */ + @Overwrite + public void tickEntity(Entity entity) { + entity.resetPosition(); + final IEntity mixinEntity = (IEntity) entity; + if (mixinEntity.viaFabricPlus$isInLoadedChunkAndShouldTick() || entity.isSpectator()) { + entity.age++; + this.getProfiler().push(() -> Registries.ENTITY_TYPE.getId(entity.getType()).toString()); + entity.tick(); + this.getProfiler().pop(); + } + this.checkChunk(entity); + + if (mixinEntity.viaFabricPlus$isInLoadedChunkAndShouldTick()) { + for (Entity entity2 : entity.getPassengerList()) { + this.tickPassenger(entity, entity2); + } + } + } + + /** + * @author RK_01 + * @reason ProtocolHack + */ + @Overwrite + private void tickPassenger(Entity entity, Entity passenger) { + if (!passenger.isRemoved() && passenger.getVehicle() == entity) { + if (passenger instanceof PlayerEntity || this.entityList.has(passenger)) { + final IEntity mixinPassenger = (IEntity) passenger; + passenger.resetPosition(); + if (mixinPassenger.viaFabricPlus$isInLoadedChunkAndShouldTick()) { + passenger.age++; + passenger.tickRiding(); + } + this.checkChunk(passenger); + + if (mixinPassenger.viaFabricPlus$isInLoadedChunkAndShouldTick()) { + for (Entity entity2 : passenger.getPassengerList()) { + this.tickPassenger(passenger, entity2); + } + } + } + } else { + passenger.stopRiding(); + } + } + + @Unique + private void checkChunk(Entity entity) { + this.getProfiler().push("chunkCheck"); + final IEntity mixinEntity = (IEntity) entity; + final int chunkX = MathHelper.floor(entity.getX() / 16.0D); + final int chunkZ = MathHelper.floor(entity.getZ() / 16.0D); + if (!mixinEntity.viaFabricPlus$isInLoadedChunkAndShouldTick() || entity.getChunkPos().x != chunkX || entity.getChunkPos().z != chunkZ) { + if (!(this.getChunk(chunkX, chunkZ).isEmpty())) { + mixinEntity.viaFabricPlus$setInLoadedChunkAndShouldTick(true); + } + } + this.getProfiler().pop(); + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinEnchantmentHelper.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinEnchantmentHelper.java new file mode 100644 index 000000000..ff6c265c7 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinEnchantmentHelper.java @@ -0,0 +1,50 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; + +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.minecraft.enchantment.EnchantmentHelper; +import net.raphimc.vialoader.util.VersionEnum; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.ModifyConstant; + +@Mixin(EnchantmentHelper.class) +public abstract class MixinEnchantmentHelper { + + @ModifyConstant(method = "getLevelFromNbt", constant = @Constant(intValue = 0)) + private static int usePossibleMinLevel(int constant) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_14_4)) { + return Short.MIN_VALUE; + } + + return constant; + } + + @ModifyConstant(method = "getLevelFromNbt", constant = @Constant(intValue = 255)) + private static int usePossibleMaxLevel(int constant) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_14_4)) { + return Short.MAX_VALUE; + } + + return constant; + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinFlowableFluid.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinFlowableFluid.java new file mode 100644 index 000000000..44192019b --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinFlowableFluid.java @@ -0,0 +1,55 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; + +import de.florianmichael.viafabricplus.fixes.diff.Material1_19_4; +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.minecraft.block.*; +import net.minecraft.fluid.FlowableFluid; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.BlockView; +import net.raphimc.vialoader.util.VersionEnum; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(FlowableFluid.class) +public abstract class MixinFlowableFluid { + + @Redirect(method = "isFlowBlocked", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;isSideSolidFullSquare(Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/Direction;)Z")) + private boolean modifyIsSolidBlock(BlockState instance, BlockView blockView, BlockPos blockPos, Direction direction) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_11_1to1_11_2)) { + return Material1_19_4.getMaterial(instance).solid(); + } else if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_13_2)) { + final Block block = instance.getBlock(); + if (block instanceof ShulkerBoxBlock || block instanceof LeavesBlock || block instanceof TrapdoorBlock || + block == Blocks.BEACON || block == Blocks.CAULDRON || block == Blocks.GLASS || + block == Blocks.GLOWSTONE || block == Blocks.ICE || block == Blocks.SEA_LANTERN || + block instanceof StainedGlassBlock || block == Blocks.PISTON || block == Blocks.STICKY_PISTON || + block == Blocks.PISTON_HEAD || block instanceof StairsBlock) { + return false; + } + } + + return instance.isSideSolidFullSquare(blockView, blockPos, direction); + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinFontStorage.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinFontStorage.java index 4268150e5..9c4d04643 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinFontStorage.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinFontStorage.java @@ -19,9 +19,13 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; +import com.llamalad7.mixinextras.sugar.Local; +import de.florianmichael.viafabricplus.fixes.diff.RenderableGlyphDiff; import de.florianmichael.viafabricplus.injection.reference.BuiltinEmptyGlyph1_12_2; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; -import de.florianmichael.viafabricplus.settings.impl.VisualSettings; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.*; import net.minecraft.util.Identifier; import net.raphimc.vialoader.util.VersionEnum; @@ -31,97 +35,89 @@ import org.spongepowered.asm.mixin.Unique; 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; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import java.util.HashMap; -import java.util.Iterator; import java.util.List; -import java.util.Map; @Mixin(FontStorage.class) public abstract class MixinFontStorage { @Shadow - protected abstract GlyphRenderer getGlyphRenderer(RenderableGlyph c); + private GlyphRenderer blankGlyphRenderer; @Shadow - private GlyphRenderer blankGlyphRenderer; + protected abstract GlyphRenderer getGlyphRenderer(RenderableGlyph c); @Shadow @Final private Identifier id; @Unique - private Map> viaFabricPlus$forbiddenCharacters; + private GlyphRenderer blankGlyphRenderer1_12_2; @Unique - private boolean viaFabricPlus$obfuscation; + private Object2IntMap providedGlyphsCache; - @Inject(method = "setFonts", at = @At("HEAD")) - private void trackForbiddenCharacters(List fonts, CallbackInfo ci) { -// viaFabricPlus$forbiddenCharacters = CharacterMappings.getForbiddenCharactersForID(this.id); - viaFabricPlus$forbiddenCharacters = new HashMap<>(); // TODO | Fix + @Inject(method = "setFonts", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/font/BuiltinEmptyGlyph;bake(Ljava/util/function/Function;)Lnet/minecraft/client/font/GlyphRenderer;", ordinal = 0)) + private void bakeBlankGlyph1_12_2(List fonts, CallbackInfo ci) { + this.blankGlyphRenderer1_12_2 = BuiltinEmptyGlyph1_12_2.INSTANCE.bake(this::getGlyphRenderer); + this.providedGlyphsCache = new Object2IntOpenHashMap<>(); } - @Unique - private boolean viaFabricPlus$isForbiddenCharacter(final Font font, final int codePoint) { - String fontName = null; - if (font instanceof BitmapFont) { - fontName = "BitmapFont"; - } else if (font instanceof BlankFont) { - fontName = "BlankFont"; - } else if (font instanceof SpaceFont) { - fontName = "SpaceFont"; - } else if (font instanceof UnihexFont) { - fontName = "UnihexFont"; + @Inject(method = "findGlyph", at = @At("RETURN"), cancellable = true) + private void filterGlyphs1(int codePoint, CallbackInfoReturnable cir, @Local Font font) { + if (this.shouldBeInvisible(cir.getReturnValue().equals(FontStorage.GlyphPair.MISSING) ? null : font, codePoint)) { + cir.setReturnValue(this.getBlankGlyphPair()); } - if (fontName == null) return false; - final var forbiddenCodepoints = viaFabricPlus$forbiddenCharacters.get(fontName); - if (forbiddenCodepoints == null) return false; - return forbiddenCodepoints.contains(codePoint); } - @Inject(method = "findGlyph", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/font/Font;getGlyph(I)Lnet/minecraft/client/font/Glyph;"), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true) - private void injectFindGlyph(int codePoint, CallbackInfoReturnable cir, Glyph glyph, Iterator var3, Font font) { - if (!this.id.getNamespace().equals("minecraft")) return; - - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_19_4)) { - if (viaFabricPlus$isForbiddenCharacter(font, codePoint)) cir.setReturnValue(FontStorage.GlyphPair.MISSING); - - if (VisualSettings.global().changeFontRendererBehaviour.isEnabled() && cir.getReturnValue() == FontStorage.GlyphPair.MISSING) { - cir.setReturnValue(new FontStorage.GlyphPair(BuiltinEmptyGlyph1_12_2.VERY_MISSING, BuiltinEmptyGlyph1_12_2.VERY_MISSING)); - } + @Inject(method = "findGlyphRenderer", at = @At("RETURN"), cancellable = true) + private void filterGlyphs2(int codePoint, CallbackInfoReturnable cir, @Local Font font) { + if (this.shouldBeInvisible(cir.getReturnValue().equals(this.blankGlyphRenderer) ? null : font, codePoint)) { + cir.setReturnValue(this.getBlankGlyphRenderer()); } } - @Inject(method = "findGlyphRenderer", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/font/Font;getGlyph(I)Lnet/minecraft/client/font/Glyph;"), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true) - private void injectFindGlyphRenderer(int codePoint, CallbackInfoReturnable cir, Iterator var2, Font font) { - if (!this.id.getNamespace().equals("minecraft")) return; + @Inject(method = "findGlyph", at = @At("RETURN"), cancellable = true) + private void fixBlankGlyph1_12_2(int codePoint, CallbackInfoReturnable cir) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_12_2)) { + final FontStorage.GlyphPair glyphPair = cir.getReturnValue(); + final Glyph glyph1 = glyphPair.glyph(); + final Glyph glyph2 = glyphPair.advanceValidatedGlyph(); + cir.setReturnValue(new FontStorage.GlyphPair(glyph1 == BuiltinEmptyGlyph.MISSING ? BuiltinEmptyGlyph1_12_2.INSTANCE : glyph1, glyph2 == BuiltinEmptyGlyph.MISSING ? BuiltinEmptyGlyph1_12_2.INSTANCE : glyph2)); + } + } - if (!viaFabricPlus$obfuscation && ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_19_4)) { - if (viaFabricPlus$isForbiddenCharacter(font, codePoint)) cir.setReturnValue(this.blankGlyphRenderer); + @Redirect(method = "findGlyphRenderer", at = @At(value = "FIELD", target = "Lnet/minecraft/client/font/FontStorage;blankGlyphRenderer:Lnet/minecraft/client/font/GlyphRenderer;")) + private GlyphRenderer fixBlankGlyphRenderer1_12_2(FontStorage instance) { + return this.getBlankGlyphRenderer(); + } - if (VisualSettings.global().changeFontRendererBehaviour.isEnabled() && cir.getReturnValue() == this.blankGlyphRenderer) { - cir.setReturnValue(BuiltinEmptyGlyph1_12_2.VERY_MISSING.bake(this::getGlyphRenderer)); - } + @Unique + private boolean shouldBeInvisible(final Font font, final int codePoint) { + if (font != null && this.providedGlyphsCache.computeIfAbsent(font, f -> ((Font) f).getProvidedGlyphs().size()) == 1) { + return false; // Probably a custom icon character from a resource pack } - } - /* - Minecraft uses all characters that exist for obfuscation mode, even those that no longer exist in the selected target version, - so we must not make the fix in case it is executed from an obfuscated text, because otherwise the obfuscation would have missing characters - */ + return (this.id.equals(MinecraftClient.DEFAULT_FONT_ID) || this.id.equals(MinecraftClient.UNICODE_FONT_ID)) && !RenderableGlyphDiff.isGlyphRenderable(codePoint); + } - @Inject(method = "getObfuscatedGlyphRenderer", at = @At("HEAD")) - private void trackObfuscationState(Glyph glyph, CallbackInfoReturnable cir) { - viaFabricPlus$obfuscation = true; + @Unique + private FontStorage.GlyphPair getBlankGlyphPair() { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_12_2)) { + return new FontStorage.GlyphPair(BuiltinEmptyGlyph1_12_2.INSTANCE, BuiltinEmptyGlyph1_12_2.INSTANCE); + } + return FontStorage.GlyphPair.MISSING; } - @Inject(method = "getGlyphRenderer(I)Lnet/minecraft/client/font/GlyphRenderer;", at = @At("RETURN")) - private void revertObfuscationState(int codePoint, CallbackInfoReturnable cir) { - viaFabricPlus$obfuscation = false; + @Unique + private GlyphRenderer getBlankGlyphRenderer() { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_12_2)) { + return this.blankGlyphRenderer1_12_2; + } + return this.blankGlyphRenderer; } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinGameOptions.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinGameOptions.java new file mode 100644 index 000000000..ebc5d27d6 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinGameOptions.java @@ -0,0 +1,57 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; + +import de.florianmichael.viafabricplus.ViaFabricPlus; +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.minecraft.client.option.GameOptions; +import net.raphimc.vialoader.util.VersionEnum; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +@Mixin(GameOptions.class) +public abstract class MixinGameOptions { + + @Shadow + public boolean useNativeTransport; + + @ModifyVariable(method = "setServerViewDistance", at = @At("HEAD"), ordinal = 0, argsOnly = true) + private int changeServerViewDistance(int viewDistance) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_17_1)) return 0; + return viewDistance; + } + + /** + * @author RK_01 + * @reason Needed as an indicator if the client wants to ping a server or connect to a server + */ + @Overwrite + public boolean shouldUseNativeTransport() { + if (!this.useNativeTransport) { + ViaFabricPlus.global().getLogger().error("Native transport is disabled, but enabling it anyway"); + } + + return true; + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinGameRenderer.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinGameRenderer.java new file mode 100644 index 000000000..4aa3428ca --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinGameRenderer.java @@ -0,0 +1,68 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.entity.Entity; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.HitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.raphimc.vialoader.util.VersionEnum; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(GameRenderer.class) +public abstract class MixinGameRenderer { + + @Shadow + @Final + MinecraftClient client; + + @ModifyExpressionValue(method = "updateTargetedEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;raycast(DFZ)Lnet/minecraft/util/hit/HitResult;")) + private HitResult bedrockReachAroundRaycast(HitResult hitResult) { + if (ProtocolHack.getTargetVersion().equals(VersionEnum.bedrockLatest)) { + final Entity entity = this.client.getCameraEntity(); + if (hitResult.getType() != HitResult.Type.MISS) return hitResult; + if (!this.canReachAround(entity)) return hitResult; + + final int x = MathHelper.floor(entity.getX()); + final int y = MathHelper.floor(entity.getY() - 0.2F); + final int z = MathHelper.floor(entity.getZ()); + final BlockPos floorPos = new BlockPos(x, y, z); + + return new BlockHitResult(floorPos.toCenterPos(), entity.getHorizontalFacing(), floorPos, false); + } + + return hitResult; + } + + @Unique + private boolean canReachAround(final Entity entity) { + return entity.isOnGround() && entity.getVehicle() == null && entity.getPitch() >= 45; + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinKeyboard.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinKeyboard.java new file mode 100644 index 000000000..ac780ada6 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinKeyboard.java @@ -0,0 +1,60 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; + +import de.florianmichael.viafabricplus.injection.access.IMouseKeyboard; +import de.florianmichael.viafabricplus.settings.impl.DebugSettings; +import net.minecraft.client.Keyboard; +import net.minecraft.client.MinecraftClient; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +@Mixin(Keyboard.class) +public abstract class MixinKeyboard implements IMouseKeyboard { + + @Shadow + @Final + private MinecraftClient client; + + @Unique + private final Queue viaFabricPlus$pendingScreenEvents = new ConcurrentLinkedQueue<>(); + + @Redirect(method = {"method_22676", "method_22675"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;execute(Ljava/lang/Runnable;)V")) + private void storeEvent(MinecraftClient instance, Runnable runnable) { + if (this.client.getNetworkHandler() != null && this.client.currentScreen != null && DebugSettings.global().executeInputsInSync.isEnabled()) { + this.viaFabricPlus$pendingScreenEvents.offer(runnable); + } else { + instance.execute(runnable); + } + } + + @Override + public Queue viaFabricPlus$getPendingScreenEvents() { + return this.viaFabricPlus$pendingScreenEvents; + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinMinecraftClient.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinMinecraftClient.java index e77c251e0..e8521bfaa 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinMinecraftClient.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinMinecraftClient.java @@ -20,34 +20,36 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; -import com.llamalad7.mixinextras.injector.WrapWithCondition; -import com.viaversion.viaversion.api.connection.UserConnection; import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; import com.viaversion.viaversion.api.type.Type; import com.viaversion.viaversion.protocols.protocol1_12to1_11_1.Protocol1_12To1_11_1; import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ServerboundPackets1_9_3; -import de.florianmichael.viafabricplus.ViaFabricPlus; +import de.florianmichael.viafabricplus.fixes.diff.ItemRegistryDiff; +import de.florianmichael.viafabricplus.injection.access.IMouseKeyboard; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; import de.florianmichael.viafabricplus.settings.impl.DebugSettings; +import net.minecraft.client.Keyboard; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.Mouse; import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.render.item.HeldItemRenderer; -import net.minecraft.item.SwordItem; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.raphimc.vialoader.util.VersionEnum; import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; 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; -import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.Queue; @Mixin(MinecraftClient.class) public abstract class MixinMinecraftClient { @@ -56,58 +58,85 @@ public abstract class MixinMinecraftClient { @Nullable public ClientPlayerEntity player; - @Shadow protected int attackCooldown; - - @Shadow @Nullable public abstract ClientPlayNetworkHandler getNetworkHandler(); - + @Shadow + public int attackCooldown; - @Unique - private final ConcurrentLinkedDeque viaFabricPlus$mouseInteractions = new ConcurrentLinkedDeque<>(); + @Shadow + @Final + public Mouse mouse; - @Unique - private final ConcurrentLinkedDeque viaFabricPlus$keyboardInteractions = new ConcurrentLinkedDeque<>(); + @Shadow + @Final + public Keyboard keyboard; - @SuppressWarnings("ConstantConditions") - @Inject(method = "tick", at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;currentScreen:Lnet/minecraft/client/gui/screen/Screen;", - ordinal = 4, shift = At.Shift.BEFORE)) - private void injectTick(CallbackInfo ci) { - if (!DebugSettings.global().executeInputsInSync.isEnabled()) { - return; + @Redirect(method = "doItemPick", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerInventory;addPickBlock(Lnet/minecraft/item/ItemStack;)V")) + private void filterItem(PlayerInventory instance, ItemStack stack) { + if (ItemRegistryDiff.keepItem(stack.getItem())) { + instance.addPickBlock(stack); } + } - while (!viaFabricPlus$mouseInteractions.isEmpty()) { - viaFabricPlus$mouseInteractions.poll().run(); - } - while (!viaFabricPlus$keyboardInteractions.isEmpty()) { - viaFabricPlus$keyboardInteractions.poll().run(); + @Redirect(method = "doItemPick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;clickCreativeStack(Lnet/minecraft/item/ItemStack;I)V")) + private void dontSendEmptyItem(ClientPlayerInteractionManager instance, ItemStack stack, int slotId) { + if (!stack.isEmpty()) { + instance.clickCreativeStack(stack, slotId); } } - @Inject(method = "handleInputEvents", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;hasRidingInventory()Z")) - private void onInventoryKeyPressed(CallbackInfo ci) { - if (getNetworkHandler() != null && DebugSettings.global().sendOpenInventoryPacket.isEnabled()) { - final UserConnection userConnection = ProtocolHack.getPlayNetworkUserConnection(); + @Redirect(method = "doItemUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/ActionResult;shouldSwingHand()Z", ordinal = 0)) + private boolean disableSwing(ActionResult instance) { + return instance.shouldSwingHand() && ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_15); + } + + @Redirect(method = "doItemUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/ActionResult;shouldSwingHand()Z", ordinal = 2)) + private boolean disableSwing2(ActionResult instance) { + return instance.shouldSwingHand() && ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_15); + } - if (userConnection != null && userConnection.getProtocolInfo().getPipeline().contains(Protocol1_12To1_11_1.class)) { - final PacketWrapper clientStatus = PacketWrapper.create(ServerboundPackets1_9_3.CLIENT_STATUS, userConnection); - clientStatus.write(Type.VAR_INT, 2); // Open Inventory Achievement + @Redirect(method = "handleInputEvents", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;swingHand(Lnet/minecraft/util/Hand;)V")) + private void disableSwing(ClientPlayerEntity instance, Hand hand) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_14_4)) return; + instance.swingHand(hand); + } - try { - clientStatus.sendToServer(Protocol1_12To1_11_1.class); - } catch (Exception e) { - ViaFabricPlus.global().getLogger().error("Failed to send Open Inventory Packet", e); - } - } + @Inject(method = "tick", + at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;currentScreen:Lnet/minecraft/client/gui/screen/Screen;", ordinal = 0, shift = At.Shift.BEFORE), + slice = @Slice( + from = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;attackCooldown:I", ordinal = 0), + to = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/Screen;wrapScreenError(Ljava/lang/Runnable;Ljava/lang/String;Ljava/lang/String;)V") + ) + ) + private void processInputQueues(CallbackInfo ci) { + if (DebugSettings.global().executeInputsInSync.isEnabled()) { + Queue inputEvents = ((IMouseKeyboard) this.mouse).viaFabricPlus$getPendingScreenEvents(); + while (!inputEvents.isEmpty()) inputEvents.poll().run(); + + inputEvents = ((IMouseKeyboard) this.keyboard).viaFabricPlus$getPendingScreenEvents(); + while (!inputEvents.isEmpty()) inputEvents.poll().run(); } } - @WrapWithCondition(method = "doItemUse", - slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;interactItem(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/Hand;)Lnet/minecraft/util/ActionResult;")), - at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/HeldItemRenderer;resetEquipProgress(Lnet/minecraft/util/Hand;)V", ordinal = 0)) - private boolean removeEquipProgressReset(HeldItemRenderer instance, Hand hand) { - return ProtocolHack.getTargetVersion().isNewerThan(VersionEnum.r1_8) || !(player.getStackInHand(hand).getItem() instanceof SwordItem); + @Inject(method = "handleInputEvents", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/tutorial/TutorialManager;onInventoryOpened()V", shift = At.Shift.AFTER)) + private void sendOpenInventoryPacket(CallbackInfo ci) throws Exception { + if (DebugSettings.global().sendOpenInventoryPacket.isEnabled()) { + final PacketWrapper clientStatus = PacketWrapper.create(ServerboundPackets1_9_3.CLIENT_STATUS, ProtocolHack.getPlayNetworkUserConnection()); + clientStatus.write(Type.VAR_INT, 2); // Open Inventory Achievement + clientStatus.scheduleSendToServer(Protocol1_12To1_11_1.class); + } + } + + @Inject(method = "doAttack", at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;crosshairTarget:Lnet/minecraft/util/hit/HitResult;", shift = At.Shift.BEFORE, ordinal = 0)) + private void fixSwingPacketOrder(CallbackInfoReturnable cir) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) { + this.player.swingHand(Hand.MAIN_HAND); + } } + @Redirect(method = "doAttack", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;swingHand(Lnet/minecraft/util/Hand;)V")) + private void fixSwingPacketOrder(ClientPlayerEntity instance, Hand hand) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) return; + instance.swingHand(Hand.MAIN_HAND); + } @Redirect(method = "tick", at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;attackCooldown:I", ordinal = 1)) private int dontIncrementCooldown(MinecraftClient instance) { @@ -126,17 +155,6 @@ private void postIncrementCooldown(CallbackInfo ci) { } } - @Redirect(method = "doItemUse", - slice = @Slice(to = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;interactEntity(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/entity/Entity;Lnet/minecraft/util/Hand;)Lnet/minecraft/util/ActionResult;")), - at = @At(value = "INVOKE", target = "Lnet/minecraft/util/ActionResult;isAccepted()Z", ordinal = 0)) - private boolean preventGenericInteract(ActionResult instance) { - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_7_6tor1_7_10)) { - return false; - } - - return instance.isAccepted(); - } - @ModifyExpressionValue(method = "handleBlockBreaking", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isUsingItem()Z")) private boolean allowBlockBreakAndItemUsageAtTheSameTime(boolean original) { if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_7_6tor1_7_10)) { diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinMouse.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinMouse.java new file mode 100644 index 000000000..9c5bef66a --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinMouse.java @@ -0,0 +1,73 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; + +import de.florianmichael.viafabricplus.injection.access.IMouseKeyboard; +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import de.florianmichael.viafabricplus.settings.impl.DebugSettings; +import de.florianmichael.viafabricplus.util.MouseSensitivityUtil; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.Mouse; +import net.minecraft.client.option.SimpleOption; +import net.raphimc.vialoader.util.VersionEnum; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +@Mixin(Mouse.class) +public abstract class MixinMouse implements IMouseKeyboard { + + @Shadow + @Final + private MinecraftClient client; + + @Unique + private final Queue viaFabricPlus$pendingScreenEvents = new ConcurrentLinkedQueue<>(); + + @Redirect(method = {"method_22684", "method_22685"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;execute(Ljava/lang/Runnable;)V")) + private void storeEvent(MinecraftClient instance, Runnable runnable) { + if (this.client.getNetworkHandler() != null && this.client.currentScreen != null && DebugSettings.global().executeInputsInSync.isEnabled()) { + this.viaFabricPlus$pendingScreenEvents.offer(runnable); + } else { + instance.execute(runnable); + } + } + + @Redirect(method = "updateMouse", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/option/SimpleOption;getValue()Ljava/lang/Object;", ordinal = 0)) + private Object adjustMouseSensitivity1_13_2(SimpleOption instance) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_13_2)) { + return (double) MouseSensitivityUtil.get1_13SliderValue(instance.getValue().floatValue()).keyFloat(); + } + + return instance.getValue(); + } + + @Override + public Queue viaFabricPlus$getPendingScreenEvents() { + return this.viaFabricPlus$pendingScreenEvents; + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinPlayerInventory.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinPlayerInventory.java new file mode 100644 index 000000000..c62a36aaa --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinPlayerInventory.java @@ -0,0 +1,62 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; + +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.util.collection.DefaultedList; +import net.raphimc.vialoader.util.VersionEnum; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.Slice; + +import java.util.AbstractList; + +@Mixin(PlayerInventory.class) +public abstract class MixinPlayerInventory { + + @Redirect(method = "", slice = @Slice(from = @At(value = "CONSTANT", args = "intValue=1")), at = @At(value = "INVOKE", target = "Lnet/minecraft/util/collection/DefaultedList;ofSize(ILjava/lang/Object;)Lnet/minecraft/util/collection/DefaultedList;", ordinal = 0)) + private DefaultedList redirectOffhandInventory(int size, T def) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) { + //noinspection MixinInnerClass + return new DefaultedList<>(new AbstractList() { + @Override + public T get(int index) { + return def; + } + + @Override + public T set(int index, T element) { + return def; + } + + @Override + public int size() { + return 0; + } + }, def) { + }; + } + + return DefaultedList.ofSize(size, def); + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinPendingUpdateManager.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinRedirectResolver.java similarity index 62% rename from src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinPendingUpdateManager.java rename to src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinRedirectResolver.java index 48c6f9068..cb9b75d40 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinPendingUpdateManager.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinRedirectResolver.java @@ -19,20 +19,25 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; -import de.florianmichael.viafabricplus.settings.impl.DebugSettings; -import net.minecraft.client.network.PendingUpdateManager; +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.minecraft.client.network.RedirectResolver; +import net.minecraft.client.network.ServerAddress; +import net.raphimc.vialoader.util.VersionEnum; 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(PendingUpdateManager.class) -public abstract class MixinPendingUpdateManager { +import javax.naming.directory.DirContext; +import java.util.Optional; - @Inject(method = "incrementSequence", at = @At(value = "FIELD", target = "Lnet/minecraft/client/network/PendingUpdateManager;pendingSequence:Z", shift = At.Shift.BEFORE), cancellable = true) - private void injectIncrementSequence(CallbackInfoReturnable cir) { - if (DebugSettings.global().disableSequencing.isEnabled()) { - cir.setReturnValue((PendingUpdateManager) (Object) this); +@Mixin(RedirectResolver.class) +public interface MixinRedirectResolver { + + @Inject(method = "method_36911", at = @At("HEAD"), cancellable = true) + private static void disableSrvForPre1_3(DirContext context, ServerAddress address, CallbackInfoReturnable> cir) { + if (ProtocolHack.getTargetVersion().isOlderThan(VersionEnum.r1_3_1tor1_3_2)) { + cir.setReturnValue(Optional.empty()); } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinServerAddress.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinServerAddress.java new file mode 100644 index 000000000..bb190605b --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinServerAddress.java @@ -0,0 +1,47 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; + +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.minecraft.client.network.AllowedAddressResolver; +import net.minecraft.client.network.ServerAddress; +import net.raphimc.vialoader.util.VersionEnum; +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.callback.CallbackInfoReturnable; + +@Mixin(ServerAddress.class) +public abstract class MixinServerAddress { + + @Shadow + @Final + private static ServerAddress INVALID; + + @Inject(method = "parse", at = @At("RETURN"), cancellable = true) + private static void resolveSrv(String address, CallbackInfoReturnable cir) { + if (!cir.getReturnValue().equals(INVALID) && ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_16_4tor1_16_5)) { + cir.setReturnValue(AllowedAddressResolver.DEFAULT.redirectResolver.lookupRedirect(cir.getReturnValue()).orElse(cir.getReturnValue())); + } + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinServerResourcePackProvider.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinServerResourcePackProvider.java index 04a464a42..eee9a8f98 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinServerResourcePackProvider.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinServerResourcePackProvider.java @@ -22,6 +22,7 @@ import com.google.common.hash.HashCode; import com.google.common.hash.Hashing; import com.google.common.io.Files; +import com.llamalad7.mixinextras.sugar.Local; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; import net.minecraft.GameVersion; import net.minecraft.SharedConstants; @@ -29,7 +30,6 @@ import net.raphimc.vialoader.util.VersionEnum; import org.apache.commons.codec.digest.DigestUtils; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; @@ -45,9 +45,6 @@ @Mixin(ServerResourcePackProvider.class) public abstract class MixinServerResourcePackProvider { - @Unique - private File viaFabricPlus$trackedFile; - @Redirect(method = "getDownloadHeaders", at = @At(value = "INVOKE", target = "Lnet/minecraft/SharedConstants;getGameVersion()Lnet/minecraft/GameVersion;")) private static GameVersion editHeaders() { // return PackFormatsMappings.current(); @@ -68,23 +65,16 @@ private static void removeHeaders(CallbackInfoReturnable> ci cir.setReturnValue(modifiableMap); } - @Inject(method = "verifyFile", at = @At("HEAD")) - private void keepFile(String expectedSha1, File file, CallbackInfoReturnable cir) { - viaFabricPlus$trackedFile = file; - } - @Redirect(method = "verifyFile", at = @At(value = "INVOKE", target = "Lcom/google/common/hash/HashCode;toString()Ljava/lang/String;", remap = false)) - private String revertHashAlgorithm(HashCode instance) { - try { - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) { - //noinspection deprecation - return Hashing.sha1().hashBytes(Files.toByteArray(viaFabricPlus$trackedFile)).toString(); - } else if (ProtocolHack.getTargetVersion().isOlderThan(VersionEnum.r1_18tor1_18_1)) { - return DigestUtils.sha1Hex(new FileInputStream(viaFabricPlus$trackedFile)); - } - } catch (IOException ignored) { + private String revertHashAlgorithm(HashCode instance, @Local File file) throws IOException { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) { + //noinspection deprecation + return Hashing.sha1().hashBytes(Files.toByteArray(file)).toString(); + } else if (ProtocolHack.getTargetVersion().isOlderThan(VersionEnum.r1_18tor1_18_1)) { + return DigestUtils.sha1Hex(new FileInputStream(file)); + } else { + return instance.toString(); } - return instance.toString(); } @Redirect(method = "verifyFile", at = @At(value = "INVOKE", target = "Ljava/lang/String;toLowerCase(Ljava/util/Locale;)Ljava/lang/String;")) diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinStringHelper.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinStringHelper.java index 67241a17b..84d8fb719 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinStringHelper.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinStringHelper.java @@ -20,7 +20,6 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; import de.florianmichael.viafabricplus.fixes.ClientsideFixes; -import net.minecraft.client.MinecraftClient; import net.minecraft.util.StringHelper; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.Constant; @@ -30,12 +29,8 @@ public abstract class MixinStringHelper { @ModifyConstant(method = "truncateChat", constant = @Constant(intValue = 256)) - private static int expandChatLength(int constant) { - if (MinecraftClient.getInstance().isInSingleplayer()) { - return 256; - } - - return ClientsideFixes.getCurrentChatLimit(); + private static int modifyMaxChatLength(int constant) { + return ClientsideFixes.getCurrentChatLength(); } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinTextRenderer.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinTextRenderer.java index 3dc90eeea..e5308af2f 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinTextRenderer.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinTextRenderer.java @@ -41,17 +41,24 @@ @Mixin(TextRenderer.class) public abstract class MixinTextRenderer { - @Shadow public abstract List wrapLines(StringVisitable text, int width); + @Shadow + public abstract List wrapLines(StringVisitable text, int width); - @Shadow public abstract int draw(OrderedText text, float x, float y, int color, boolean shadow, Matrix4f matrix, VertexConsumerProvider vertexConsumers, TextRenderer.TextLayerType layerType, int backgroundColor, int light); + @Shadow + public abstract int draw(OrderedText text, float x, float y, int color, boolean shadow, Matrix4f matrix, VertexConsumerProvider vertexConsumers, TextRenderer.TextLayerType layerType, int backgroundColor, int light); - @Shadow public abstract String mirror(String text); + @Shadow + public abstract String mirror(String text); - @Shadow @Final public int fontHeight; + @Shadow + @Final + public int fontHeight; - @Shadow protected abstract int drawInternal(OrderedText text, float x, float y, int color, boolean shadow, Matrix4f matrix, VertexConsumerProvider vertexConsumers, TextRenderer.TextLayerType layerType, int backgroundColor, int light); + @Shadow + protected abstract int drawInternal(OrderedText text, float x, float y, int color, boolean shadow, Matrix4f matrix, VertexConsumerProvider vertexConsumers, TextRenderer.TextLayerType layerType, int backgroundColor, int light); - @Shadow public abstract int getWidth(OrderedText text); + @Shadow + public abstract int getWidth(OrderedText text); @Inject(method = "draw(Ljava/lang/String;FFIZLorg/joml/Matrix4f;Lnet/minecraft/client/render/VertexConsumerProvider;Lnet/minecraft/client/font/TextRenderer$TextLayerType;IIZ)I", at = @At("HEAD"), cancellable = true) private void allowNewLines_String(String text, float x, float y, int color, boolean shadow, Matrix4f matrix, VertexConsumerProvider vertexConsumers, TextRenderer.TextLayerType layerType, int backgroundColor, int light, boolean rightToLeft, CallbackInfoReturnable cir) { diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/entity/MixinBoatEntity.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/entity/MixinBoatEntity.java index b3fd94f70..56c895893 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/entity/MixinBoatEntity.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/entity/MixinBoatEntity.java @@ -1,3 +1,22 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.entity; import de.florianmichael.viafabricplus.fixes.EntityHeightOffsetsPre1_20_2; diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/entity/MixinLivingEntity.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/entity/MixinLivingEntity.java index e3fd46ed5..9a4abaef3 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/entity/MixinLivingEntity.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/entity/MixinLivingEntity.java @@ -98,12 +98,11 @@ private boolean allowPlayerToBeMovedByEntityPackets(LivingEntity instance) { return instance.isLogicalSideForUpdatingMovement(); } - @Redirect(method = "tickCramming", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;isClient()Z")) - private boolean revertOnlyPlayerCramming(World instance) { - if (DebugSettings.global().alwaysTickOnlyPlayer.isEnabled()) { - return false; + @Inject(method = "tickCramming", at = @At("HEAD"), cancellable = true) + private void preventEntityPush(CallbackInfo ci) { + if (DebugSettings.global().preventEntityCramming.isEnabled()) { + ci.cancel(); } - return instance.isClient(); } @Redirect(method = "travel", at = @At(value = "INVOKE", target = "Ljava/lang/Math;cos(D)D", remap = false)) diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/entity/MixinSkeletonHorseEntity.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/entity/MixinSkeletonHorseEntity.java index 28472bbb6..0d652892e 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/entity/MixinSkeletonHorseEntity.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/entity/MixinSkeletonHorseEntity.java @@ -1,3 +1,22 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.entity; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/item/MixinDrawContext.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/item/MixinDrawContext.java index 5cb18e222..4a3bd3fa7 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/item/MixinDrawContext.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/item/MixinDrawContext.java @@ -31,7 +31,7 @@ public abstract class MixinDrawContext { @Redirect(method = "drawItemInSlot(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/item/ItemStack;IILjava/lang/String;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getCount()I")) private int handleNegativeItemCount(ItemStack instance) { - if (((IItemStack) (Object) instance).viaFabricPlus$has1_10ProtocolHackTag()) { + if (((IItemStack) (Object) instance).viaFabricPlus$has1_10ViaFabricPlusTag()) { return ((IItemStack) (Object) instance).viaFabricPlus$get1_10Count(); } return instance.getCount(); diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/item/MixinItemGroup_EntriesImpl.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/item/MixinItemGroup_EntriesImpl.java index d632eb173..5bf526d7d 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/item/MixinItemGroup_EntriesImpl.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/item/MixinItemGroup_EntriesImpl.java @@ -19,6 +19,7 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.item; +import de.florianmichael.viafabricplus.fixes.diff.ItemRegistryDiff; import de.florianmichael.viafabricplus.settings.impl.GeneralSettings; import net.minecraft.client.MinecraftClient; import net.minecraft.item.Item; @@ -34,7 +35,9 @@ @Mixin(targets = "net.minecraft.item.ItemGroup$EntriesImpl") public abstract class MixinItemGroup_EntriesImpl { - @Shadow @Final private ItemGroup group; + @Shadow + @Final + private ItemGroup group; @Redirect(method = "add", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/Item;isEnabled(Lnet/minecraft/resource/featuretoggle/FeatureSet;)Z")) private boolean removeUnknownItems(Item instance, FeatureSet featureSet) { @@ -43,11 +46,9 @@ private boolean removeUnknownItems(Item instance, FeatureSet featureSet) { if (index == 2 || MinecraftClient.getInstance().isInSingleplayer()) return instance.isEnabled(featureSet); if (index == 1 && !Registries.ITEM_GROUP.getId(this.group).getNamespace().equals("minecraft")) return instance.isEnabled(featureSet); - // TODO | Fix - -// if (ItemRegistryDiffPre1_20_2.INSTANCE.getCurrentMap().contains(instance)) { -// return instance.isEnabled(featureSet); -// } + if (ItemRegistryDiff.keepItem(instance)) { + return instance.isEnabled(featureSet); + } return false; } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/item/MixinItemStack.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/item/MixinItemStack.java index dc85f9c98..836e51495 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/item/MixinItemStack.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/item/MixinItemStack.java @@ -105,7 +105,7 @@ private void copyProtocolHackData(CallbackInfoReturnable cir) { } @Override - public boolean viaFabricPlus$has1_10ProtocolHackTag() { + public boolean viaFabricPlus$has1_10ViaFabricPlusTag() { return this.viaFabricPlus$has1_10ProtocolHackTag; } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinChatMessageC2SPacket.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinChatMessageC2SPacket.java index 917876c8c..76ea07bb1 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinChatMessageC2SPacket.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinChatMessageC2SPacket.java @@ -20,22 +20,17 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.network; import de.florianmichael.viafabricplus.fixes.ClientsideFixes; -import net.minecraft.client.MinecraftClient; import net.minecraft.network.packet.c2s.play.ChatMessageC2SPacket; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.ModifyConstant; @Mixin(ChatMessageC2SPacket.class) public abstract class MixinChatMessageC2SPacket { - @ModifyArg(method = "write", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/PacketByteBuf;writeString(Ljava/lang/String;I)Lnet/minecraft/network/PacketByteBuf;")) + @ModifyConstant(method = "write", constant = @Constant(intValue = 256)) private int modifyChatLength(int maxLength) { - if (MinecraftClient.getInstance().isInSingleplayer()) { - return 256; - } - - return ClientsideFixes.getCurrentChatLimit(); + return ClientsideFixes.getCurrentChatLength(); } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinClientCommonNetworkHandler.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinClientCommonNetworkHandler.java index 5252ac994..3aa76b3e6 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinClientCommonNetworkHandler.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinClientCommonNetworkHandler.java @@ -19,11 +19,14 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.network; +import com.viaversion.viaversion.protocols.protocol1_17to1_16_4.storage.InventoryAcknowledgements; import de.florianmichael.viafabricplus.fixes.ClientsideFixes; +import de.florianmichael.viafabricplus.injection.access.IClientConnection; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; import net.fabricmc.fabric.impl.networking.payload.PacketByteBufPayload; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientCommonNetworkHandler; +import net.minecraft.network.ClientConnection; import net.minecraft.network.listener.ServerPacketListener; import net.minecraft.network.packet.Packet; import net.minecraft.network.packet.s2c.common.CommonPingS2CPacket; @@ -42,14 +45,22 @@ import java.util.function.BooleanSupplier; @SuppressWarnings("UnstableApiUsage") -@Mixin(value = ClientCommonNetworkHandler.class, priority = 1 /* Has to be applied before Fabric's Networking API, so it doesn't cancel our custom-payload packets */) +@Mixin(value = ClientCommonNetworkHandler.class, priority = 1001 /* Has to be applied before Fabric's Networking API, so it doesn't cancel our custom-payload packets */) public abstract class MixinClientCommonNetworkHandler { - @Shadow @Final protected MinecraftClient client; + @Shadow + @Final + protected MinecraftClient client; - @Shadow protected abstract void send(Packet packet, BooleanSupplier sendCondition, Duration expiry); + @Shadow + protected abstract void send(Packet packet, BooleanSupplier sendCondition, Duration expiry); - @Shadow public abstract void sendPacket(Packet packet); + @Shadow + public abstract void sendPacket(Packet packet); + + @Shadow + @Final + protected ClientConnection connection; @Redirect(method = "onKeepAlive", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientCommonNetworkHandler;send(Lnet/minecraft/network/packet/Packet;Ljava/util/function/BooleanSupplier;Ljava/time/Duration;)V")) private void forceSendKeepAlive(ClientCommonNetworkHandler instance, Packet packet, BooleanSupplier sendCondition, Duration expiry) { @@ -63,19 +74,22 @@ private void forceSendKeepAlive(ClientCommonNetworkHandler instance, Packet> 16) & 0xFF); + + ScreenHandler handler = null; + if (inventoryId == 0) handler = client.player.playerScreenHandler; + else if (inventoryId == client.player.currentScreenHandler.syncId) handler = client.player.currentScreenHandler; + + if (handler != null) { + acks.addId(packet.getParameter()); + } else { + ci.cancel(); + } + } } - - final int inventoryId = (packet.getParameter() >> 16) & 0xFF; // Fix Via Bug from 1.16.5 (Window Confirmation -> PlayPing) Usage for MiningFast Detection - ScreenHandler handler = null; - - if (client.player == null) return; - - if (inventoryId == 0) handler = client.player.playerScreenHandler; - if (inventoryId == client.player.currentScreenHandler.syncId) handler = client.player.currentScreenHandler; - - if (handler == null) ci.cancel(); } @Inject(method = "onCustomPayload(Lnet/minecraft/network/packet/s2c/common/CustomPayloadS2CPacket;)V", at = @At("HEAD"), cancellable = true) diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinClientConfigurationNetworkHandler.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinClientConfigurationNetworkHandler.java new file mode 100644 index 000000000..a7237249e --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinClientConfigurationNetworkHandler.java @@ -0,0 +1,45 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.network; + +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import de.florianmichael.viafabricplus.util.ChatUtil; +import net.minecraft.client.network.ClientConfigurationNetworkHandler; +import net.minecraft.network.packet.s2c.config.FeaturesS2CPacket; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; +import net.raphimc.vialoader.util.VersionEnum; +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(ClientConfigurationNetworkHandler.class) +public abstract class MixinClientConfigurationNetworkHandler { + + @Inject(method = "onFeatures", at = @At(value = "HEAD")) + private void notifyAboutFeatures(FeaturesS2CPacket packet, CallbackInfo ci) { + if (ProtocolHack.getTargetVersion().isOlderThan(VersionEnum.r1_20tor1_20_1) && packet.features().contains(new Identifier("update_1_20"))) { + ChatUtil.sendPrefixedMessage(Text.literal("This server has the update_1_20 features enabled. This is not fully supported and may cause issues.").formatted(Formatting.RED)); + } + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinClientLoginNetworkHandler.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinClientLoginNetworkHandler.java new file mode 100644 index 000000000..c40d8648b --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinClientLoginNetworkHandler.java @@ -0,0 +1,38 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.network; + +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.minecraft.client.network.ClientLoginNetworkHandler; +import net.minecraft.network.ClientConnection; +import net.raphimc.vialoader.util.VersionEnum; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(ClientLoginNetworkHandler.class) +public abstract class MixinClientLoginNetworkHandler { + + @Redirect(method = "onCompression", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;setCompressionThreshold(IZ)V")) + private void pre1_17_1CompressionBehaviour(ClientConnection instance, int compressionThreshold, boolean rejectsBadPackets) { + instance.setCompressionThreshold(compressionThreshold, ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_17)); + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinClientPlayNetworkHandler.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinClientPlayNetworkHandler.java index 9d5e3ea03..17e3ebad2 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinClientPlayNetworkHandler.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinClientPlayNetworkHandler.java @@ -20,22 +20,21 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.network; import com.llamalad7.mixinextras.injector.WrapWithCondition; -import de.florianmichael.viafabricplus.fixes.diff.RecipesPre1_12; +import de.florianmichael.viafabricplus.fixes.recipe.RecipeInfo; +import de.florianmichael.viafabricplus.fixes.recipe.Recipes1_11_2; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; import de.florianmichael.viafabricplus.settings.impl.VisualSettings; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.DownloadingTerrainScreen; -import net.minecraft.client.network.ClientConnectionState; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.network.PlayerListEntry; -import net.minecraft.client.world.ClientWorld; +import net.minecraft.client.network.*; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.vehicle.BoatEntity; import net.minecraft.network.ClientConnection; import net.minecraft.network.packet.s2c.play.*; -import net.minecraft.recipe.Recipe; import net.minecraft.recipe.RecipeEntry; import net.minecraft.util.Identifier; +import net.minecraft.world.GameMode; import net.raphimc.vialoader.util.VersionEnum; import org.slf4j.Logger; import org.spongepowered.asm.mixin.Final; @@ -49,11 +48,9 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Set; -import java.util.stream.Collectors; -@SuppressWarnings("DataFlowIssue") @Mixin(ClientPlayNetworkHandler.class) -public abstract class MixinClientPlayNetworkHandler { +public abstract class MixinClientPlayNetworkHandler extends ClientCommonNetworkHandler { @Shadow public abstract void onEntityStatus(EntityStatusS2CPacket packet); @@ -66,23 +63,47 @@ public abstract class MixinClientPlayNetworkHandler { @Shadow public abstract void onSimulationDistance(SimulationDistanceS2CPacket packet); - @Shadow public abstract ClientConnection getConnection(); + @Shadow + public abstract ClientConnection getConnection(); + + @Shadow + public abstract void onSynchronizeRecipes(SynchronizeRecipesS2CPacket packet); + + protected MixinClientPlayNetworkHandler(MinecraftClient client, ClientConnection connection, ClientConnectionState connectionState) { + super(client, connection, connectionState); + } @WrapWithCondition(method = "onChatMessage", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;error(Ljava/lang/String;Ljava/lang/Object;)V", remap = false)) - private boolean removeError(Logger instance, String s, Object o) { + private boolean removeChatPacketError(Logger instance, String s, Object o) { return ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_20_2); } + @Redirect(method = "handlePlayerListAction", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;onGameModeChanged(Lnet/minecraft/world/GameMode;)V")) + private void dontResetVelocity(ClientPlayerEntity instance, GameMode gameMode) { + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_20tor1_20_1)) { + instance.onGameModeChanged(gameMode); + } + } + @WrapWithCondition(method = "setPublicSession", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;)V", remap = false)) private boolean removeInvalidSignatureWarning(Logger instance, String s, Object o) { return ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_19_4); } @WrapWithCondition(method = "onPlayerList", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;)V", remap = false)) - private boolean removeWarning(Logger instance, String s, Object o) { + private boolean removeUnknownPlayerListEntryWarning(Logger instance, String s, Object o) { return ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_19_3); } + @Redirect(method = {"onEntityPosition", "onEntity"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;isLogicalSideForUpdatingMovement()Z")) + private boolean allowPlayerToBeMovedByEntityPackets(Entity instance) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_19_3) || ProtocolHack.getTargetVersion().equals(VersionEnum.bedrockLatest)) { + return instance.getControllingPassenger() instanceof PlayerEntity player ? player.isMainPlayer() : !instance.getWorld().isClient; + } + + return instance.isLogicalSideForUpdatingMovement(); + } + @Inject(method = "", at = @At("RETURN")) private void fixPlayerListOrdering(MinecraftClient client, ClientConnection clientConnection, ClientConnectionState clientConnectionState, CallbackInfo ci) { if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_19_1tor1_19_2)) { @@ -90,7 +111,7 @@ private void fixPlayerListOrdering(MinecraftClient client, ClientConnection clie } } - @Redirect(method = "onServerMetadata", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/s2c/play/ServerMetadataS2CPacket;isSecureChatEnforced()Z")) + @Redirect(method = "onServerMetadata", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/s2c/play/ServerMetadataS2CPacket;isSecureChatEnforced()Z", ordinal = 1)) private boolean removeSecureChatWarning(ServerMetadataS2CPacket instance) { return instance.isSecureChatEnforced() || VisualSettings.global().disableSecureChatWarning.isEnabled(); } @@ -102,17 +123,18 @@ private boolean moveDownloadingTerrainClosing(DownloadingTerrainScreen instance) @Inject(method = "onPlayerPositionLook", at = @At("RETURN")) private void closeDownloadingTerrain(PlayerPositionLookS2CPacket packet, CallbackInfo ci) { - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_18_2) && MinecraftClient.getInstance().currentScreen instanceof DownloadingTerrainScreen) { - MinecraftClient.getInstance().setScreen(null); + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_18tor1_18_1) && this.client.currentScreen instanceof DownloadingTerrainScreen downloadingTerrainScreen) { + downloadingTerrainScreen.setReady(); } } + @SuppressWarnings({"InvalidInjectorMethodSignature"}) @ModifyConstant(method = "onEntityPassengersSet", constant = @Constant(classValue = BoatEntity.class)) - private Class dontChangePlayerYaw(Object entity, Class constant) { - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_18_2)) { + private Class dontChangeYawWhenMountingBoats(Object entity, Class boatClass) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_18tor1_18_1)) { return Integer.class; } - return constant; + return boatClass; } @Inject(method = "onChunkLoadDistance", at = @At("RETURN")) @@ -122,29 +144,27 @@ private void emulateSimulationDistance(ChunkLoadDistanceS2CPacket packet, Callba } } - @Redirect(method = "onSynchronizeRecipes", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/s2c/play/SynchronizeRecipesS2CPacket;getRecipes()Ljava/util/List;")) - private List> rewriteRecipes(SynchronizeRecipesS2CPacket instance) { - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_11_1to1_11_2)) { - final List> recipes = instance.getRecipes().stream().map(RecipeEntry::value).collect(Collectors.toList()); - RecipesPre1_12.editRecipes(recipes, ProtocolHack.getTargetVersion()); - - final List> entries = new ArrayList<>(); - int recipeId = 0; - for (final Recipe recipe : recipes) { - entries.add(new RecipeEntry<>(new Identifier(String.valueOf(recipeId++)), recipe)); - } - - return entries; + @Redirect(method = "onEntityPosition", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;updateTrackedPositionAndAngles(DDDFFI)V")) + private void cancelSmallChanges(Entity instance, double x, double y, double z, float yaw, float pitch, int interpolationSteps) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_16_1) && Math.abs(instance.getX() - x) < 0.03125 && Math.abs(instance.getY() - y) < 0.015625 && Math.abs(instance.getZ() - z) < 0.03125) { + instance.updateTrackedPositionAndAngles(instance.getX(), instance.getY(), instance.getZ(), yaw, pitch, ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_15_2) ? 0 : interpolationSteps); + } else { + instance.updateTrackedPositionAndAngles(x, y, z, yaw, pitch, interpolationSteps); } - return instance.getRecipes(); } - @Inject(method = {"onGameJoin", "onPlayerRespawn"}, at = @At("TAIL")) - private void injectOnOnGameJoinOrRespawn(CallbackInfo ci) { + @Inject(method = "onGameJoin", at = @At("RETURN")) + private void sendAdditionalData(CallbackInfo ci) { if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) { - ClientPlayerEntity player = MinecraftClient.getInstance().player; - assert player != null; - onEntityStatus(new EntityStatusS2CPacket(player, (byte) 28)); + this.onEntityStatus(new EntityStatusS2CPacket(this.client.player, (byte) 28)); // Op-level 4 + } + if (ProtocolHack.getTargetVersion().isOlderThan(VersionEnum.r1_12)) { + final List> recipes = new ArrayList<>(); + final List> recipeInfos = Recipes1_11_2.getRecipes(); + for (int i = 0; i < recipeInfos.size(); i++) { + recipes.add(recipeInfos.get(i).create(new Identifier("viafabricplus", "recipe/" + i))); + } + this.onSynchronizeRecipes(new SynchronizeRecipesS2CPacket(recipes)); } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinClientPlayerInteractionManager.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinClientPlayerInteractionManager.java new file mode 100644 index 000000000..036bf0b2f --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinClientPlayerInteractionManager.java @@ -0,0 +1,324 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.network; + +import com.llamalad7.mixinextras.injector.WrapWithCondition; +import com.llamalad7.mixinextras.sugar.Local; +import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; +import com.viaversion.viaversion.api.type.Type; +import com.viaversion.viaversion.protocols.protocol1_16_2to1_16_1.ServerboundPackets1_16_2; +import com.viaversion.viaversion.protocols.protocol1_17to1_16_4.Protocol1_17To1_16_4; +import de.florianmichael.viafabricplus.fixes.ActionResultException; +import de.florianmichael.viafabricplus.fixes.ClientPlayerInteractionManager1_18_2; +import de.florianmichael.viafabricplus.injection.access.IClientConnection; +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.translator.ItemTranslator; +import de.florianmichael.viafabricplus.settings.impl.VisualSettings; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.SnowBlock; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.client.network.SequencedPacketCreator; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemPlacementContext; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemUsageContext; +import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.c2s.play.ClickSlotC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket; +import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.GameMode; +import net.raphimc.vialoader.util.VersionEnum; +import org.apache.commons.lang3.mutable.MutableObject; +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.List; + +@SuppressWarnings("DataFlowIssue") +@Mixin(ClientPlayerInteractionManager.class) +public abstract class MixinClientPlayerInteractionManager { + + @Shadow + @Final + private MinecraftClient client; + + @Shadow + protected abstract ActionResult interactBlockInternal(ClientPlayerEntity player, Hand hand, BlockHitResult hitResult); + + @Shadow + @Final + private ClientPlayNetworkHandler networkHandler; + + @Shadow + private BlockPos currentBreakingPos; + + @Shadow + private float currentBreakingProgress; + + @Shadow + protected abstract void sendSequencedPacket(ClientWorld world, SequencedPacketCreator packetCreator); + + @Shadow + private GameMode gameMode; + + @Unique + private ItemStack viaFabricPlus$oldCursorStack; + + @Unique + private List viaFabricPlus$oldItems; + + @Inject(method = "getBlockBreakingProgress", at = @At("HEAD"), cancellable = true) + private void changeCalculation(CallbackInfoReturnable cir) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_19_4)) { + cir.setReturnValue((int) (this.currentBreakingProgress * 10.0F) - 1); + } + } + + @Inject(method = "sendSequencedPacket", at = @At("HEAD")) + private void trackPlayerAction(ClientWorld world, SequencedPacketCreator packetCreator, CallbackInfo ci) { + if (ProtocolHack.getTargetVersion().isBetweenInclusive(VersionEnum.r1_14_4, VersionEnum.r1_18_2) && packetCreator instanceof PlayerActionC2SPacket playerActionC2SPacket) { + ClientPlayerInteractionManager1_18_2.trackPlayerAction(playerActionC2SPacket.getAction(), playerActionC2SPacket.getPos()); + } + } + + @Redirect(method = {"attackBlock", "cancelBlockBreaking"}, at = @At(value = "NEW", target = "(Lnet/minecraft/network/packet/c2s/play/PlayerActionC2SPacket$Action;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/Direction;)Lnet/minecraft/network/packet/c2s/play/PlayerActionC2SPacket;")) + private PlayerActionC2SPacket trackPlayerAction(PlayerActionC2SPacket.Action action, BlockPos pos, Direction direction) { + if (ProtocolHack.getTargetVersion().isBetweenInclusive(VersionEnum.r1_14_4, VersionEnum.r1_18_2)) { + ClientPlayerInteractionManager1_18_2.trackPlayerAction(action, pos); + } + return new PlayerActionC2SPacket(action, pos, direction); + } + + @Redirect(method = "interactItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/packet/Packet;)V", ordinal = 0)) + private void redirectPlayerPosPacket(ClientPlayNetworkHandler instance, Packet packet) { + if (ProtocolHack.getTargetVersion().isNewerThan(VersionEnum.r1_16_4tor1_16_5)) { + instance.sendPacket(packet); + } + } + + @ModifyVariable(method = "clickSlot", at = @At(value = "STORE"), ordinal = 0) + private List captureOldItems(List oldItems) { + viaFabricPlus$oldCursorStack = client.player.currentScreenHandler.getCursorStack().copy(); + return this.viaFabricPlus$oldItems = oldItems; + } + + @WrapWithCondition(method = "clickSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/packet/Packet;)V")) + private boolean handleWindowClick1_16_5(ClientPlayNetworkHandler instance, Packet packet) throws Exception { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_16_4tor1_16_5) && packet instanceof ClickSlotC2SPacket clickSlot) { + ItemStack slotItemBeforeModification; + + if (this.viaFabricPlus$shouldBeEmpty(clickSlot.getActionType(), clickSlot.getSlot())) + slotItemBeforeModification = ItemStack.EMPTY; + else if (clickSlot.getSlot() < 0 || clickSlot.getSlot() >= viaFabricPlus$oldItems.size()) + slotItemBeforeModification = viaFabricPlus$oldCursorStack; + else + slotItemBeforeModification = viaFabricPlus$oldItems.get(clickSlot.getSlot()); + + final var clickWindowPacket = PacketWrapper.create(ServerboundPackets1_16_2.CLICK_WINDOW, ((IClientConnection) networkHandler.getConnection()).viaFabricPlus$getUserConnection()); + clickWindowPacket.write(Type.UNSIGNED_BYTE, (short) clickSlot.getSyncId()); + clickWindowPacket.write(Type.SHORT, (short) clickSlot.getSlot()); + clickWindowPacket.write(Type.BYTE, (byte) clickSlot.getButton()); + clickWindowPacket.write(Type.SHORT, ((IScreenHandler) client.player.currentScreenHandler).viaFabricPlus$incrementAndGetActionId()); + clickWindowPacket.write(Type.VAR_INT, clickSlot.getActionType().ordinal()); + clickWindowPacket.write(Type.ITEM1_13_2, ItemTranslator.mcToVia(slotItemBeforeModification, VersionEnum.r1_16_4tor1_16_5)); + clickWindowPacket.scheduleSendToServer(Protocol1_17To1_16_4.class); + + viaFabricPlus$oldCursorStack = null; + viaFabricPlus$oldItems = null; + return false; + } + + return true; + } + + @Redirect(method = {"method_41936", "method_41935"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;breakBlock(Lnet/minecraft/util/math/BlockPos;)Z")) + private boolean checkFireBlock(ClientPlayerInteractionManager instance, BlockPos pos, @Local Direction direction) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_15_2)) { + if (!this.extinguishFire(pos, direction)) { + return instance.breakBlock(pos); + } else { + return false; + } + } + + return instance.breakBlock(pos); + } + + @Inject(method = "breakBlock", at = @At("TAIL")) + private void resetBlockBreaking(BlockPos pos, CallbackInfoReturnable cir) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_14_3)) { + this.currentBreakingPos = new BlockPos(this.currentBreakingPos.getX(), -1, this.currentBreakingPos.getZ()); + } + } + + @Inject(method = "interactBlockInternal", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;isEmpty()Z", ordinal = 2, shift = At.Shift.BEFORE)) + private void interactBlock1_12_2(ClientPlayerEntity player, Hand hand, BlockHitResult hitResult, CallbackInfoReturnable cir) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_12_2)) { + final ItemStack itemStack = player.getStackInHand(hand); + BlockHitResult checkHitResult = hitResult; + if (itemStack.getItem() instanceof BlockItem) { + final BlockState clickedBlock = this.client.world.getBlockState(hitResult.getBlockPos()); + if (clickedBlock.getBlock().equals(Blocks.SNOW)) { + if (clickedBlock.get(SnowBlock.LAYERS) == 1) { + checkHitResult = hitResult.withSide(Direction.UP); + } + } + final ItemUsageContext itemUsageContext = new ItemUsageContext(player, hand, checkHitResult); + final ItemPlacementContext itemPlacementContext = new ItemPlacementContext(itemUsageContext); + if (!itemPlacementContext.canPlace() || ((BlockItem) itemPlacementContext.getStack().getItem()).getPlacementState(itemPlacementContext) == null) { + throw new ActionResultException(ActionResult.PASS); + } + } + + this.networkHandler.sendPacket(new PlayerInteractBlockC2SPacket(hand, hitResult, 0)); + if (itemStack.isEmpty()) { + throw new ActionResultException(ActionResult.PASS); + } + final ItemUsageContext itemUsageContext = new ItemUsageContext(player, hand, checkHitResult); + ActionResult actionResult; + if (this.gameMode.isCreative()) { + final int count = itemStack.getCount(); + actionResult = itemStack.useOnBlock(itemUsageContext); + itemStack.setCount(count); + } else { + actionResult = itemStack.useOnBlock(itemUsageContext); + } + if (!actionResult.isAccepted()) { + actionResult = ActionResult.PASS; // In <= 1.12.2 FAIL is the same as PASS + } + throw new ActionResultException(actionResult); + } + } + + @Inject(method = "method_41929", at = @At("HEAD")) + private void trackLastUsedItem(Hand hand, PlayerEntity playerEntity, MutableObject mutableObject, int sequence, CallbackInfoReturnable> cir) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) { + ViaFabricPlusHandItemProvider.lastUsedItem = playerEntity.getStackInHand(hand).copy(); + } + } + + @Inject(method = "interactItem", at = @At("HEAD"), cancellable = true) + private void cancelOffHandItemInteract(PlayerEntity player, Hand hand, CallbackInfoReturnable cir) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8) && !Hand.MAIN_HAND.equals(hand)) cir.setReturnValue(ActionResult.PASS); + } + + @Inject(method = "interactBlock", at = @At("HEAD"), cancellable = true) + private void cancelOffHandBlockPlace(ClientPlayerEntity player, Hand hand, BlockHitResult hitResult, CallbackInfoReturnable cir) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8) && !Hand.MAIN_HAND.equals(hand)) cir.setReturnValue(ActionResult.PASS); + } + + /** + * @author RK_01 + * @reason Block place fix + */ + @Overwrite + private Packet method_41933(MutableObject mutableObject, ClientPlayerEntity clientPlayerEntity, Hand hand, BlockHitResult blockHitResult, int sequence) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) { + ViaFabricPlusHandItemProvider.lastUsedItem = clientPlayerEntity.getStackInHand(hand).copy(); + } + try { + mutableObject.setValue(this.interactBlockInternal(clientPlayerEntity, hand, blockHitResult)); + return new PlayerInteractBlockC2SPacket(hand, blockHitResult, sequence); + } catch (ActionResultException e) { + mutableObject.setValue(e.getActionResult()); + throw e; + } + } + + @Redirect(method = "interactBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;sendSequencedPacket(Lnet/minecraft/client/world/ClientWorld;Lnet/minecraft/client/network/SequencedPacketCreator;)V")) + private void catchPacketCancelException(ClientPlayerInteractionManager instance, ClientWorld world, SequencedPacketCreator packetCreator) { + try { + this.sendSequencedPacket(world, packetCreator); + } catch (ActionResultException ignored) { + } + } + + @Inject(method = "clickSlot", at = @At("HEAD"), cancellable = true) + private void removeClickActions(int syncId, int slotId, int button, SlotActionType actionType, PlayerEntity player, CallbackInfo ci) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.b1_5tob1_5_2) && !actionType.equals(SlotActionType.PICKUP)) { + ci.cancel(); + } else if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_4_6tor1_4_7) && !actionType.equals(SlotActionType.PICKUP) && !actionType.equals(SlotActionType.QUICK_MOVE) && !actionType.equals(SlotActionType.SWAP) && !actionType.equals(SlotActionType.CLONE)) { + ci.cancel(); + } + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8) && actionType == SlotActionType.SWAP && button == 40) { // Pressing 'F' in inventory + ci.cancel(); + } + } + + @Inject(method = "hasExperienceBar", at = @At("HEAD"), cancellable = true) + private void removeExperienceBar(CallbackInfoReturnable cir) { + if (VisualSettings.global().removeNewerHudElements.isEnabled()) { + cir.setReturnValue(false); + } + } + + @Inject(method = "getReachDistance", at = @At("RETURN"), cancellable = true) + private void modifyReachDistance(CallbackInfoReturnable cir) { + if (ProtocolHack.getTargetVersion().isOlderThan(VersionEnum.r1_0_0tor1_0_1) && !this.gameMode.isCreative()) { + cir.setReturnValue(4F); + } + } + + @Unique + private boolean extinguishFire(BlockPos blockPos, final Direction direction) { + blockPos = blockPos.offset(direction); + if (this.client.world.getBlockState(blockPos).getBlock() == Blocks.FIRE) { + this.client.world.syncWorldEvent(this.client.player, 1009, blockPos, 0); + this.client.world.removeBlock(blockPos, false); + return true; + } + return false; + } + + @Unique + private boolean viaFabricPlus$shouldBeEmpty(final SlotActionType type, final int slot) { + // quick craft always uses empty stack for verification + if (type == SlotActionType.QUICK_CRAFT) return true; + + // Special case: throw always uses empty stack for verification + if (type == SlotActionType.THROW) return true; + + // quick move always uses empty stack for verification since 1.12 + if (type == SlotActionType.QUICK_MOVE && ProtocolHack.getTargetVersion().isNewerThan(VersionEnum.r1_11_1to1_11_2)) return true; + + // pickup with slot -999 (outside window) to throw items always uses empty stack for verification + return type == SlotActionType.PICKUP && slot == -999; + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinCustomPayloadS2CPacket.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinCustomPayloadS2CPacket.java new file mode 100644 index 000000000..237628fb9 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinCustomPayloadS2CPacket.java @@ -0,0 +1,71 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.network; + +import com.google.common.collect.ImmutableMap; +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.packet.BrandCustomPayload; +import net.minecraft.network.packet.CustomPayload; +import net.minecraft.network.packet.s2c.common.CustomPayloadS2CPacket; +import net.minecraft.network.packet.s2c.custom.DebugGameTestAddMarkerCustomPayload; +import net.minecraft.network.packet.s2c.custom.DebugGameTestClearCustomPayload; +import net.minecraft.util.Identifier; +import net.raphimc.vialoader.util.VersionEnum; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.Map; + +@Mixin(CustomPayloadS2CPacket.class) +public abstract class MixinCustomPayloadS2CPacket { + + @Unique + private static final Map PAYLOAD_DIFF = ImmutableMap.builder() + .put(BrandCustomPayload.ID, VersionEnum.c0_0_15a_1) + .put(DebugGameTestAddMarkerCustomPayload.ID, VersionEnum.r1_14) + .put(DebugGameTestClearCustomPayload.ID, VersionEnum.r1_14) + .build(); + + @Redirect(method = "readPayload", at = @At(value = "INVOKE", target = "Ljava/util/Map;get(Ljava/lang/Object;)Ljava/lang/Object;", remap = false)) + private static Object filterAllowedCustomPayloads(Map instance, Object identifier) { + if (instance.containsKey(identifier)) { + if (!PAYLOAD_DIFF.containsKey(identifier) || ProtocolHack.getTargetVersion().isOlderThan(PAYLOAD_DIFF.get(identifier))) { + return null; + } + + final PacketByteBuf.PacketReader reader = (PacketByteBuf.PacketReader) instance.get(identifier); + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_20tor1_20_1)) { + return (PacketByteBuf.PacketReader) packetByteBuf -> { + final CustomPayload result = reader.apply(packetByteBuf); + packetByteBuf.skipBytes(packetByteBuf.readableBytes()); + return result; + }; + } else { + return reader; + } + } + + return null; + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinMultiplayerServerListPinger.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinMultiplayerServerListPinger.java new file mode 100644 index 000000000..eb52217c7 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinMultiplayerServerListPinger.java @@ -0,0 +1,41 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.network; + +import net.minecraft.client.network.MultiplayerServerListPinger; +import net.minecraft.client.network.ServerAddress; +import net.minecraft.client.network.ServerInfo; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; + +import java.net.InetSocketAddress; + +@Mixin(MultiplayerServerListPinger.class) +public abstract class MixinMultiplayerServerListPinger { + + /** + * @author RK_01 + * @reason Remove legacy ping which didn't even work + */ + @Overwrite + public void ping(InetSocketAddress socketAddress, ServerAddress address, ServerInfo serverInfo) { + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinPacketByteBuf.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinPacketByteBuf.java index 2636030af..b7b374d09 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinPacketByteBuf.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinPacketByteBuf.java @@ -19,24 +19,43 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.network; -import net.raphimc.vialoader.util.VersionEnum; -import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; +import de.florianmichael.viafabricplus.injection.access.IItemStack; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; import net.minecraft.network.PacketByteBuf; -import net.minecraft.text.Text; +import net.raphimc.vialoader.util.VersionEnum; 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; +import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(value = PacketByteBuf.class) public abstract class MixinPacketByteBuf { - @Inject(method = "readText", at = @At(value = "INVOKE", target = "Lio/netty/handler/codec/DecoderException;(Ljava/lang/String;)V", shift = At.Shift.BEFORE, remap = false), cancellable = true) - private void injectReadText(CallbackInfoReturnable cir) { - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_18tor1_18_1)) { - cir.setReturnValue(null); + @Redirect(method = "readItemStack", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;setNbt(Lnet/minecraft/nbt/NbtCompound;)V")) + private void removeViaFabricPlusTag(ItemStack instance, NbtCompound tag) { + if (tag != null && tag.contains("1_10_ViaFabricPlus_ItemCount", NbtElement.BYTE_TYPE) && ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_10)) { + final IItemStack mixinItemStack = ((IItemStack) (Object) instance); + mixinItemStack.viaFabricPlus$set1_10Count(tag.getByte("1_10_ViaFabricPlus_ItemCount")); + tag.remove("1_10_ViaFabricPlus_ItemCount"); + if (tag.isEmpty()) tag = null; + } + + instance.setNbt(tag); + } + + @Redirect(method = "writeItemStack", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getNbt()Lnet/minecraft/nbt/NbtCompound;")) + private NbtCompound addViaFabricPlusTag(ItemStack instance) { + NbtCompound tag = instance.getNbt(); + + final IItemStack mixinItemStack = ((IItemStack) (Object) instance); + if (mixinItemStack.viaFabricPlus$has1_10ViaFabricPlusTag()) { + if (tag == null) tag = new NbtCompound(); + tag.putByte("1_10_ViaFabricPlus_ItemCount", (byte) mixinItemStack.viaFabricPlus$get1_10Count()); } + + return tag; } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinUpdatePlayerAbilitiesC2SPacket.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinUpdatePlayerAbilitiesC2SPacket.java index a8cb152b8..e794f014f 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinUpdatePlayerAbilitiesC2SPacket.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/network/MixinUpdatePlayerAbilitiesC2SPacket.java @@ -19,27 +19,35 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.network; -import net.raphimc.vialoader.util.VersionEnum; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; -import net.minecraft.client.MinecraftClient; import net.minecraft.entity.player.PlayerAbilities; import net.minecraft.network.PacketByteBuf; import net.minecraft.network.packet.c2s.play.UpdatePlayerAbilitiesC2SPacket; +import net.raphimc.vialoader.util.VersionEnum; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; 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(UpdatePlayerAbilitiesC2SPacket.class) public abstract class MixinUpdatePlayerAbilitiesC2SPacket { + @Unique + private PlayerAbilities viaFabricPlus$abilities; + + @Inject(method = "(Lnet/minecraft/entity/player/PlayerAbilities;)V", at = @At("RETURN")) + private void capturePlayerAbilities(PlayerAbilities abilities, CallbackInfo ci) { + this.viaFabricPlus$abilities = abilities; + } + @Redirect(method = "write", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/PacketByteBuf;writeByte(I)Lnet/minecraft/network/PacketByteBuf;")) private PacketByteBuf implementFlags(PacketByteBuf instance, int value) { if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_15_2)) { - final PlayerAbilities playerAbilities = MinecraftClient.getInstance().player.getAbilities(); - - if (playerAbilities.invulnerable) value |= 1; - if (playerAbilities.allowFlying) value |= 4; - if (playerAbilities.creativeMode) value |= 8; + if (viaFabricPlus$abilities.invulnerable) value |= 1; + if (viaFabricPlus$abilities.allowFlying) value |= 4; + if (viaFabricPlus$abilities.creativeMode) value |= 8; } return instance.writeByte(value); diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinAbstractCommandBlockScreen.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinAbstractCommandBlockScreen.java new file mode 100644 index 000000000..08135d537 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinAbstractCommandBlockScreen.java @@ -0,0 +1,40 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen; + +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.minecraft.client.gui.screen.ChatInputSuggestor; +import net.minecraft.client.gui.screen.ingame.AbstractCommandBlockScreen; +import net.raphimc.vialoader.util.VersionEnum; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(AbstractCommandBlockScreen.class) +public abstract class MixinAbstractCommandBlockScreen { + + @Redirect(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ChatInputSuggestor;refresh()V")) + private void cancelAutoComplete(ChatInputSuggestor instance) { + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_13)) { + instance.refresh(); + } + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinBookEditScreen.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinBookEditScreen.java new file mode 100644 index 000000000..bfab9eb65 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinBookEditScreen.java @@ -0,0 +1,50 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen; + +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.minecraft.client.gui.screen.ingame.BookEditScreen; +import net.raphimc.vialoader.util.VersionEnum; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.ModifyConstant; + +@Mixin(BookEditScreen.class) +public abstract class MixinBookEditScreen { + + @ModifyConstant(method = "method_27596", constant = @Constant(intValue = 1024)) + private int modifyPageLength(int oldVal) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_13_2)) { + return 256; + } else { + return oldVal; + } + } + + @ModifyConstant(method = "appendNewPage", constant = @Constant(intValue = 100)) + private int modifyPageCount(int oldVal) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_13_2)) { + return 50; + } else { + return oldVal; + } + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinChatScreen.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinChatScreen.java index ad9565b60..0cb85a0e2 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinChatScreen.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinChatScreen.java @@ -19,15 +19,18 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen; -import de.florianmichael.viafabricplus.settings.impl.VisualSettings; import de.florianmichael.viafabricplus.fixes.ClientsideFixes; -import net.minecraft.client.MinecraftClient; +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import de.florianmichael.viafabricplus.settings.impl.VisualSettings; import net.minecraft.client.gui.hud.ChatHud; import net.minecraft.client.gui.hud.MessageIndicator; +import net.minecraft.client.gui.screen.ChatInputSuggestor; import net.minecraft.client.gui.screen.ChatScreen; import net.minecraft.client.gui.widget.TextFieldWidget; +import net.raphimc.vialoader.util.VersionEnum; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; @@ -36,13 +39,18 @@ @Mixin(ChatScreen.class) public abstract class MixinChatScreen { - @Shadow protected TextFieldWidget chatField; + @Shadow + protected TextFieldWidget chatField; + + @Shadow + private String originalChatText; + + @Shadow + ChatInputSuggestor chatInputSuggestor; @Inject(method = "init", at = @At("RETURN")) private void changeChatLength(CallbackInfo ci) { - if (!MinecraftClient.getInstance().isInSingleplayer()) { - this.chatField.setMaxLength(ClientsideFixes.getCurrentChatLimit()); - } + this.chatField.setMaxLength(ClientsideFixes.getCurrentChatLength()); } @Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ChatHud;getIndicatorAt(DD)Lnet/minecraft/client/gui/hud/MessageIndicator;")) @@ -54,4 +62,37 @@ private MessageIndicator removeIndicator(ChatHud instance, double mouseX, double return instance.getIndicatorAt(mouseX, mouseY); } + @Redirect(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/TextFieldWidget;setText(Ljava/lang/String;)V")) + private void moveSetTextDown(TextFieldWidget instance, String text) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_12_2)) return; + + instance.setText(text); + } + + @Inject(method = "init", at = @At("RETURN")) + private void moveSetTextDown(CallbackInfo ci) { + if (!ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_12_2)) return; + + this.chatField.setText(this.originalChatText); + this.chatInputSuggestor.refresh(); + } + + @Redirect(method = "onChatFieldUpdate", at = @At(value = "INVOKE", target = "Ljava/lang/String;equals(Ljava/lang/Object;)Z")) + private boolean fixCommandKey(String instance, Object other) { + if (!this.cancelTabComplete()) return instance.equals(other); + return instance.isEmpty(); + } + + @Redirect(method = "onChatFieldUpdate", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ChatInputSuggestor;refresh()V")) + private void disableAutoTabComplete(ChatInputSuggestor instance) { + if (this.cancelTabComplete()) return; + + instance.refresh(); + } + + @Unique + private boolean cancelTabComplete() { + return ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_12_2) && this.chatField.getText().startsWith("/"); + } + } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinCommandBlockScreen.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinCommandBlockScreen.java index d070858f5..46e9b4cb6 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinCommandBlockScreen.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinCommandBlockScreen.java @@ -37,6 +37,7 @@ public abstract class MixinCommandBlockScreen { @Shadow private CyclingButtonWidget conditionalModeButton; + @Shadow private CyclingButtonWidget redstoneTriggerButton; diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinConnectScreen_1.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinConnectScreen_1.java index 335828b4e..806bac7c9 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinConnectScreen_1.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinConnectScreen_1.java @@ -19,6 +19,7 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen; +import com.llamalad7.mixinextras.sugar.Local; import com.viaversion.viaversion.api.connection.UserConnection; import com.viaversion.viaversion.api.minecraft.ProfileKey; import com.viaversion.viaversion.api.minecraft.signature.storage.ChatSession1_19_0; @@ -27,20 +28,12 @@ import de.florianmichael.viafabricplus.injection.access.IClientConnection; import de.florianmichael.viafabricplus.injection.access.ILegacyKeySignatureStorage; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; -import de.florianmichael.viafabricplus.protocolhack.provider.vialegacy.ViaFabricPlusClassicMPPassProvider; -import de.florianmichael.viafabricplus.settings.impl.AuthenticationSettings; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.ConnectScreen; import net.minecraft.client.network.ServerAddress; import net.minecraft.network.ClientConnection; import net.minecraft.network.encryption.PlayerPublicKey; -import net.minecraft.network.packet.Packet; -import net.minecraft.network.packet.c2s.login.LoginHelloC2SPacket; -import net.raphimc.minecraftauth.MinecraftAuth; -import net.raphimc.minecraftauth.util.MicrosoftConstants; import net.raphimc.viabedrock.protocol.storage.AuthChainData; import net.raphimc.vialoader.util.VersionEnum; -import org.apache.http.impl.client.CloseableHttpClient; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -59,72 +52,43 @@ public abstract class MixinConnectScreen_1 { @Shadow ServerAddress field_33737; - @Final - @Shadow - ConnectScreen field_2416; - - @Redirect(method = "run", at = @At(value = "INVOKE", target = "Ljava/net/InetSocketAddress;getHostName()Ljava/lang/String;", ordinal = 0)) - private String replaceAddress(InetSocketAddress instance) { - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_17) || ProtocolHack.getTargetVersion() == VersionEnum.bedrockLatest) { + @Redirect(method = "run", at = @At(value = "INVOKE", target = "Ljava/net/InetSocketAddress;getHostName()Ljava/lang/String;", remap = false)) + private String getRealAddress(InetSocketAddress instance) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_17)) { return field_33737.getAddress(); } return instance.getHostName(); } - @Redirect(method = "run", at = @At(value = "INVOKE", target = "Ljava/net/InetSocketAddress;getPort()I")) - private int replacePort(InetSocketAddress instance) { - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_17) || ProtocolHack.getTargetVersion() == VersionEnum.bedrockLatest) { + @Redirect(method = "run", at = @At(value = "INVOKE", target = "Ljava/net/InetSocketAddress;getPort()I", remap = false)) + private int getRealPort(InetSocketAddress instance) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_17)) { return field_33737.getPort(); } return instance.getPort(); } - @Inject(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;send(Lnet/minecraft/network/packet/Packet;)V", shift = At.Shift.BEFORE)) - private void setupConnectionSessions(CallbackInfo ci) { - final ClientConnection connection = field_2416.connection; - if (connection == null || connection.channel == null) return; - - final UserConnection userConnection = ((IClientConnection) connection).viaFabricPlus$getUserConnection(); + @Inject(method = "run", at = @At(value = "INVOKE", target = "Lio/netty/channel/ChannelFuture;syncUninterruptibly()Lio/netty/channel/ChannelFuture;", shift = At.Shift.AFTER)) + private void setupConnectionSessions(CallbackInfo ci, @Local ClientConnection clientConnection) { + final UserConnection userConnection = ((IClientConnection) clientConnection).viaFabricPlus$getUserConnection(); if (userConnection == null) return; final VersionEnum targetVersion = VersionEnum.fromUserConnection(userConnection); - if (targetVersion == VersionEnum.bedrockLatest) { - var bedrockSession = ViaFabricPlus.global().getSaveManager().getAccountsSave().getBedrockAccount(); - if (bedrockSession == null) return; - - try (final CloseableHttpClient httpClient = MicrosoftConstants.createHttpClient()) { - bedrockSession = MinecraftAuth.BEDROCK_DEVICE_CODE_LOGIN.refresh(httpClient, bedrockSession); - } catch (Exception e) { - ViaFabricPlus.global().getLogger().error("Failed to refresh Bedrock chain data. Please re-login to Bedrock!", e); - return; - } - - final var deviceId = bedrockSession.getMcChain().getXblXsts().getInitialXblSession().getXblDeviceToken().getId(); - final var playFabId = bedrockSession.getPlayFabToken().getPlayFabId(); - final var mcChain = bedrockSession.getMcChain(); - - userConnection.put(new AuthChainData(mcChain.getMojangJwt(), mcChain.getIdentityJwt(), mcChain.getPublicKey(), mcChain.getPrivateKey(), deviceId, playFabId)); - return; - } - - if (targetVersion.isOlderThan(VersionEnum.r1_19)) { - return; // This disables the chat session emulation for all versions <= 1.18.2 - } - if (targetVersion.isOlderThanOrEqualTo(VersionEnum.r1_19_1tor1_19_2)) { - final var profile = MinecraftClient.getInstance().getProfileKeys().fetchKeyPair().join().orElse(null); - if (profile != null) { - final PlayerPublicKey.PublicKeyData publicKeyData = profile.publicKey().data(); + if (targetVersion.isBetweenInclusive(VersionEnum.r1_19, VersionEnum.r1_19_1tor1_19_2)) { + final var keyPair = MinecraftClient.getInstance().getProfileKeys().fetchKeyPair().join().orElse(null); + if (keyPair != null) { + final PlayerPublicKey.PublicKeyData publicKeyData = keyPair.publicKey().data(); final UUID playerUuid = MinecraftClient.getInstance().getSession().getUuidOrNull(); - userConnection.put(new ChatSession1_19_1(playerUuid, profile.privateKey(), new ProfileKey(publicKeyData.expiresAt().toEpochMilli(), publicKeyData.key().getEncoded(), publicKeyData.keySignature()))); + userConnection.put(new ChatSession1_19_1(playerUuid, keyPair.privateKey(), new ProfileKey(publicKeyData.expiresAt().toEpochMilli(), publicKeyData.key().getEncoded(), publicKeyData.keySignature()))); if (targetVersion == VersionEnum.r1_19) { final var legacyKey = ((ILegacyKeySignatureStorage) (Object) publicKeyData).viafabricplus$getLegacyPublicKeySignature(); if (legacyKey != null) { - userConnection.put(new ChatSession1_19_0(playerUuid, profile.privateKey(), new ProfileKey(publicKeyData.expiresAt().toEpochMilli(), publicKeyData.key().getEncoded(), legacyKey))); + userConnection.put(new ChatSession1_19_0(playerUuid, keyPair.privateKey(), new ProfileKey(publicKeyData.expiresAt().toEpochMilli(), publicKeyData.key().getEncoded(), legacyKey))); } else { ViaFabricPlus.global().getLogger().error("Failed to fetch legacy key, can't setup ChatSession"); } @@ -132,6 +96,15 @@ private void setupConnectionSessions(CallbackInfo ci) { } else { ViaFabricPlus.global().getLogger().error("Failed to fetch keyPair, can't setup ChatSession"); } + } else if (targetVersion == VersionEnum.bedrockLatest) { + var bedrockSession = ViaFabricPlus.global().getSaveManager().getAccountsSave().refreshAndGetBedrockAccount(); + if (bedrockSession != null) { + final var deviceId = bedrockSession.getMcChain().getXblXsts().getInitialXblSession().getXblDeviceToken().getId(); + final var playFabId = bedrockSession.getPlayFabToken().getPlayFabId(); + final var mcChain = bedrockSession.getMcChain(); + + userConnection.put(new AuthChainData(mcChain.getMojangJwt(), mcChain.getIdentityJwt(), mcChain.getPublicKey(), mcChain.getPrivateKey(), deviceId, playFabId)); + } } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinCreativeInventoryScreen.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinCreativeInventoryScreen.java index e3cc8378b..be3f1c470 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinCreativeInventoryScreen.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinCreativeInventoryScreen.java @@ -34,8 +34,6 @@ public abstract class MixinCreativeInventoryScreen { @Inject(method = "init", at = @At("RETURN")) private void replaceCreativeMenu(CallbackInfo ci) { if (VisualSettings.global().replaceCreativeInventory.isEnabled()) { - if (ClassicItemSelectionScreen.INSTANCE == null) return; - MinecraftClient.getInstance().setScreen(ClassicItemSelectionScreen.INSTANCE); } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinDownloadingTerrainScreen.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinDownloadingTerrainScreen.java index 166371b64..215bd470e 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinDownloadingTerrainScreen.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinDownloadingTerrainScreen.java @@ -25,7 +25,6 @@ import net.minecraft.client.gui.screen.Screen; import net.minecraft.network.packet.c2s.common.KeepAliveC2SPacket; import net.minecraft.text.Text; -import net.minecraft.util.math.BlockPos; import net.raphimc.vialoader.util.VersionEnum; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -33,14 +32,19 @@ import org.spongepowered.asm.mixin.Unique; 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(DownloadingTerrainScreen.class) public abstract class MixinDownloadingTerrainScreen extends Screen { - @Shadow @Final private long loadStartTime; - @Shadow private boolean closeOnNextTick; - @Shadow private boolean ready; + @Shadow + @Final + private long loadStartTime; + + @Shadow + private boolean ready; + @Unique private int viaFabricPlus$tickCounter; @@ -49,32 +53,30 @@ public MixinDownloadingTerrainScreen(Text title) { } @Inject(method = "tick", at = @At("HEAD"), cancellable = true) - private void injectTick(CallbackInfo ci) { - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_12_1)) { - viaFabricPlus$tickCounter++; - - if (viaFabricPlus$tickCounter % 20 == 0) { - MinecraftClient.getInstance().getNetworkHandler().sendPacket(new KeepAliveC2SPacket(0)); + private void modifyCloseCondition(CallbackInfo ci) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_18tor1_18_1)) { + ci.cancel(); + if (this.ready) { + this.close(); } - } - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_19_1tor1_19_2)) { - final boolean isTimeOver = this.closeOnNextTick || System.currentTimeMillis() > this.loadStartTime + 2000L; - if (isTimeOver && this.client != null && this.client.player != null) { - final BlockPos blockPos = this.client.player.getBlockPos(); - final boolean isWorldLoaded = this.client.world != null && this.client.world.isOutOfHeightLimit(blockPos.getY()); - - if (isWorldLoaded || this.client.worldRenderer.isRenderingReady(blockPos)) { - this.close(); - } + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_12_1)) { + this.viaFabricPlus$tickCounter++; - if (this.ready) { - this.closeOnNextTick = true; + if (this.viaFabricPlus$tickCounter % 20 == 0) { + MinecraftClient.getInstance().getNetworkHandler().sendPacket(new KeepAliveC2SPacket(0)); } - } - ci.cancel(); } } + @Redirect(method = "tick", at = @At(value = "FIELD", target = "Lnet/minecraft/client/gui/screen/DownloadingTerrainScreen;ready:Z")) + private boolean modifyCloseBehaviour(DownloadingTerrainScreen instance) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_19_1tor1_19_2)) { + return this.ready/*TODO: Not in 1.19.2, but make the screen close faster*/ || System.currentTimeMillis() > this.loadStartTime + 2000; + } + + return this.ready; + } + } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinGameModeSelectionScreen.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinGameModeSelectionScreen.java index 16eae269d..a5954afc1 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinGameModeSelectionScreen.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinGameModeSelectionScreen.java @@ -38,7 +38,9 @@ public abstract class MixinGameModeSelectionScreen extends Screen { @Mutable - @Shadow @Final private static int UI_WIDTH; + @Shadow + @Final + private static int UI_WIDTH; @Unique private GameModeSelectionScreen.GameModeSelection[] viaFabricPlus$unwrappedGameModes; diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinGameModeSelectionScreen_GameModeSelection.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinGameModeSelectionScreen_GameModeSelection.java index c34ab4c03..cffb5f657 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinGameModeSelectionScreen_GameModeSelection.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinGameModeSelectionScreen_GameModeSelection.java @@ -19,10 +19,10 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen; -import net.raphimc.vialoader.util.VersionEnum; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.GameModeSelectionScreen; +import net.raphimc.vialoader.util.VersionEnum; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -36,14 +36,18 @@ @Mixin(GameModeSelectionScreen.GameModeSelection.class) public abstract class MixinGameModeSelectionScreen_GameModeSelection { - @Shadow @Final public static GameModeSelectionScreen.GameModeSelection SURVIVAL; + @Shadow + @Final + public static GameModeSelectionScreen.GameModeSelection SURVIVAL; - @Shadow @Final public static GameModeSelectionScreen.GameModeSelection CREATIVE; + @Shadow + @Final + public static GameModeSelectionScreen.GameModeSelection CREATIVE; @Inject(method = "next", at = @At("HEAD"), cancellable = true) private void unwrapGameModes(CallbackInfoReturnable> cir) { if (ProtocolHack.getTargetVersion().isOlderThan(VersionEnum.r1_8)) { - switch ((GameModeSelectionScreen.GameModeSelection)(Object)this) { + switch ((GameModeSelectionScreen.GameModeSelection) (Object) this) { case CREATIVE -> cir.setReturnValue(Optional.of(SURVIVAL)); case SURVIVAL -> { if (ProtocolHack.getTargetVersion().isOlderThan(VersionEnum.r1_2_4tor1_2_5)) { @@ -61,7 +65,7 @@ private void unwrapGameModes(CallbackInfoReturnable cir) { if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_2_4tor1_2_5)) { cir.setReturnValue( - "gamemode " + MinecraftClient.getInstance().getSession().getUsername() + ' ' + switch (((Enum)(Object)this).ordinal()) { + "gamemode " + MinecraftClient.getInstance().getSession().getUsername() + ' ' + switch (((Enum) (Object) this).ordinal()) { case 0, 3 -> 1; case 1, 2 -> 0; default -> throw new AssertionError(); diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinJigsawBlockScreen.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinJigsawBlockScreen.java index e1fd42d9f..c3956f295 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinJigsawBlockScreen.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinJigsawBlockScreen.java @@ -51,7 +51,7 @@ public MixinJigsawBlockScreen(Text title) { } @Inject(method = "init", at = @At("RETURN")) - private void injectInit(CallbackInfo ci) { + private void removeWidgets(CallbackInfo ci) { if (VisualSettings.global().removeNewerFeaturesFromJigsawScreen.isEnabled()) { nameField.active = false; jointRotationButton.active = false; @@ -63,7 +63,7 @@ private void injectInit(CallbackInfo ci) { } @Inject(method = "render", at = @At("HEAD")) - private void injectRender(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { + private void copyText(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { if (VisualSettings.global().removeNewerFeaturesFromJigsawScreen.isEnabled()) { nameField.setText(targetField.getText()); } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinAnvilScreen.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinMouseOptionsScreen.java similarity index 52% rename from src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinAnvilScreen.java rename to src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinMouseOptionsScreen.java index ffc591b56..2a0f7bdd0 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinAnvilScreen.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinMouseOptionsScreen.java @@ -20,39 +20,35 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; -import net.minecraft.client.gui.screen.ingame.AnvilScreen; -import net.minecraft.client.gui.screen.ingame.ForgingScreen; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.network.packet.c2s.play.RenameItemC2SPacket; -import net.minecraft.screen.AnvilScreenHandler; -import net.minecraft.screen.slot.Slot; +import de.florianmichael.viafabricplus.util.MouseSensitivityUtil; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.option.GameOptionsScreen; +import net.minecraft.client.gui.screen.option.MouseOptionsScreen; +import net.minecraft.client.gui.widget.OptionListWidget; +import net.minecraft.client.option.GameOptions; import net.minecraft.text.Text; -import net.minecraft.util.Identifier; import net.raphimc.vialoader.util.VersionEnum; 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(AnvilScreen.class) -public abstract class MixinAnvilScreen extends ForgingScreen { +@Mixin(MouseOptionsScreen.class) +public abstract class MixinMouseOptionsScreen extends GameOptionsScreen { - public MixinAnvilScreen(AnvilScreenHandler handler, PlayerInventory playerInventory, Text title, Identifier texture) { - super(handler, playerInventory, title, texture); - } + @Shadow + private OptionListWidget buttonList; - @Inject(method = "onRenamed", at = @At("HEAD"), cancellable = true) - private void changePacketLogic(String name, CallbackInfo ci) { - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_19_4) && !name.isEmpty()) { - String string = name; - Slot slot = this.handler.getSlot(0); - if (slot != null && slot.hasStack() && !slot.getStack().hasCustomName() && name.equals(slot.getStack().getName().getString())) { - string = ""; - } + public MixinMouseOptionsScreen(Screen parent, GameOptions gameOptions, Text title) { + super(parent, gameOptions, title); + } - this.handler.setNewItemName(string); - this.client.player.networkHandler.sendPacket(new RenameItemC2SPacket(string)); - ci.cancel(); + @Inject(method = "render", at = @At("RETURN")) + private void render1_13SliderValue(DrawContext drawContext, int mouseX, int mouseY, float delta, CallbackInfo ci) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_13_2) && this.buttonList.getWidgetFor(this.gameOptions.getMouseSensitivity()).isHovered()) { + drawContext.drawTooltip(textRenderer, Text.of("<=1.13.2 Sensitivity: " + MouseSensitivityUtil.get1_13SliderValue(this.gameOptions.getMouseSensitivity().getValue().floatValue()).valueInt() + "%"), mouseX, mouseY); } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinScreen.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinScreen.java index 098ece8f3..8ec1a7860 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinScreen.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinScreen.java @@ -35,7 +35,9 @@ @Mixin(Screen.class) public abstract class MixinScreen { - @Shadow @Nullable protected MinecraftClient client; + @Shadow + @Nullable + protected MinecraftClient client; @Inject(method = "handleTextClick", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;error(Ljava/lang/String;Ljava/lang/Object;)V", shift = At.Shift.BEFORE, ordinal = 1, remap = false), cancellable = true) private void allowRunCommandAction(Style style, CallbackInfoReturnable cir) { diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinStructureBlockScreen_1.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinStructureBlockScreen_1.java index ef2a9bb6c..471ef326c 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinStructureBlockScreen_1.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/MixinStructureBlockScreen_1.java @@ -19,12 +19,11 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen; -import net.raphimc.vialoader.util.VersionEnum; -import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.widget.TextFieldWidget; import net.minecraft.text.Text; +import net.raphimc.vialoader.util.VersionEnum; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -38,7 +37,7 @@ public MixinStructureBlockScreen_1(TextRenderer textRenderer, int x, int y, int } @Inject(method = "charTyped(CI)Z", at = @At("HEAD"), cancellable = true) - private void onCharTyped(char chr, int keyCode, CallbackInfoReturnable ci) { + private void removeValidation(char chr, int keyCode, CallbackInfoReturnable ci) { if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_12_2)) { ci.setReturnValue(super.charTyped(chr, keyCode)); } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/hud/MixinChatHud.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/hud/MixinChatHud.java index 445131643..38a079669 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/hud/MixinChatHud.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/hud/MixinChatHud.java @@ -19,25 +19,23 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen.hud; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import de.florianmichael.viafabricplus.settings.impl.VisualSettings; import net.minecraft.client.gui.hud.ChatHud; -import net.minecraft.client.gui.hud.ChatHudLine; import net.minecraft.client.gui.hud.MessageIndicator; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; @Mixin(ChatHud.class) public abstract class MixinChatHud { - @WrapOperation(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ChatHudLine$Visible;indicator()Lnet/minecraft/client/gui/hud/MessageIndicator;"), require = 0) - private MessageIndicator removeIndicators(ChatHudLine.Visible instance, Operation original) { + @ModifyVariable(method = "addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;ILnet/minecraft/client/gui/hud/MessageIndicator;Z)V", at = @At("HEAD"), ordinal = 0, argsOnly = true) + private MessageIndicator removeIndicator(MessageIndicator instance) { if (VisualSettings.global().hideSignatureIndicator.isEnabled()) { return null; } - return original.call(instance); + return instance; } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/hud/MixinInGameHud.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/hud/MixinInGameHud.java index 47b2180dc..b2d61246b 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/hud/MixinInGameHud.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/hud/MixinInGameHud.java @@ -28,7 +28,10 @@ import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.*; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -40,11 +43,6 @@ public abstract class MixinInGameHud { // Removing newer elements - @Inject(method = "renderExperienceBar", at = @At("HEAD"), cancellable = true) - private void removeExperienceBar(DrawContext context, int x, CallbackInfo ci) { - if (VisualSettings.global().removeNewerHudElements.isEnabled()) ci.cancel(); - } - @Inject(method = "renderMountJumpBar", at = @At("HEAD"), cancellable = true) private void removeMountJumpBar(JumpingMount mount, DrawContext context, int x, CallbackInfo ci) { if (VisualSettings.global().removeNewerHudElements.isEnabled()) ci.cancel(); diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/merchant/MixinMerchantScreen.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/merchant/MixinMerchantScreen.java deleted file mode 100644 index 3ceedf244..000000000 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/merchant/MixinMerchantScreen.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus - * Copyright (C) 2021-2023 FlorianMichael/EnZaXD - * Copyright (C) 2023 RK_01/RaphiMC 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 . - */ - -package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen.merchant; - -import de.florianmichael.viafabricplus.settings.impl.DebugSettings; -import net.minecraft.client.gui.screen.ingame.HandledScreen; -import net.minecraft.client.gui.screen.ingame.MerchantScreen; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.network.packet.c2s.play.SelectMerchantTradeC2SPacket; -import net.minecraft.screen.MerchantScreenHandler; -import net.minecraft.text.Text; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(MerchantScreen.class) -public abstract class MixinMerchantScreen extends HandledScreen { - - @Shadow - private int selectedIndex; - - @Unique - private int viaFabricPlus$previousRecipeIndex; - - public MixinMerchantScreen(MerchantScreenHandler handler, PlayerInventory inventory, Text title) { - super(handler, inventory, title); - } - - @Inject(method = "init", at = @At("HEAD")) - private void reset(CallbackInfo ci) { - viaFabricPlus$previousRecipeIndex = 0; - } - - @Inject(method = "syncRecipeIndex", at = @At("HEAD")) - private void smoothOutRecipeIndex(CallbackInfo ci) { - if (DebugSettings.global().smoothOutMerchantScreens.isEnabled()) { - if (viaFabricPlus$previousRecipeIndex != selectedIndex) { - int direction = viaFabricPlus$previousRecipeIndex < selectedIndex ? 1 : -1; - for (int smooth = viaFabricPlus$previousRecipeIndex + direction /* don't send the page we already are on */; smooth != selectedIndex; smooth += direction) { - client.getNetworkHandler().sendPacket(new SelectMerchantTradeC2SPacket(smooth)); - } - viaFabricPlus$previousRecipeIndex = selectedIndex; - } - } - } - -} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinAbstractFurnaceScreenHandler.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinAbstractFurnaceScreenHandler.java new file mode 100644 index 000000000..f8615b3eb --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinAbstractFurnaceScreenHandler.java @@ -0,0 +1,50 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen.screenhandler; + +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.AbstractFurnaceScreenHandler; +import net.raphimc.vialoader.util.VersionEnum; +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(AbstractFurnaceScreenHandler.class) +public abstract class MixinAbstractFurnaceScreenHandler { + + @Shadow + protected abstract boolean isSmeltable(ItemStack itemStack); + + @Shadow + protected abstract boolean isFuel(ItemStack itemStack); + + @Redirect(method = "quickMove", at = @At(value = "INVOKE", target = "Lnet/minecraft/screen/AbstractFurnaceScreenHandler;isSmeltable(Lnet/minecraft/item/ItemStack;)Z")) + private boolean disableShiftClickSmeltingSlot(AbstractFurnaceScreenHandler instance, ItemStack itemStack) { + return this.isSmeltable(itemStack) && !ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_2_1tor1_2_3); + } + + @Redirect(method = "quickMove", at = @At(value = "INVOKE", target = "Lnet/minecraft/screen/AbstractFurnaceScreenHandler;isFuel(Lnet/minecraft/item/ItemStack;)Z")) + private boolean disableShiftClickFuelSlot(AbstractFurnaceScreenHandler instance, ItemStack itemStack) { + return this.isFuel(itemStack) && !ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_2_1tor1_2_3); + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinBrewingStandScreenHandler_FuelSlot.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinBrewingStandScreenHandler_FuelSlot.java index cf2df4610..ef5c7b29d 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinBrewingStandScreenHandler_FuelSlot.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinBrewingStandScreenHandler_FuelSlot.java @@ -19,11 +19,10 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen.screenhandler; -import net.raphimc.vialoader.util.VersionEnum; -import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; import net.minecraft.inventory.Inventory; import net.minecraft.screen.slot.Slot; +import net.raphimc.vialoader.util.VersionEnum; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -37,9 +36,9 @@ public MixinBrewingStandScreenHandler_FuelSlot(Inventory inventory, int index, i } @Inject(method = "matches(Lnet/minecraft/item/ItemStack;)Z", at = @At("HEAD"), cancellable = true) - private static void removeFuelSlot(CallbackInfoReturnable ci) { + private static void removeFuelSlot(CallbackInfoReturnable cir) { if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) { - ci.setReturnValue(false); + cir.setReturnValue(false); } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinCraftingScreenHandler.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinCraftingScreenHandler.java index 0517fbd9b..4cc16fef4 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinCraftingScreenHandler.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinCraftingScreenHandler.java @@ -19,10 +19,11 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen.screenhandler; -import de.florianmichael.viafabricplus.fixes.diff.RecipesPre1_12; +import de.florianmichael.viafabricplus.fixes.recipe.Recipes1_11_2; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; import net.minecraft.inventory.Inventory; import net.minecraft.inventory.RecipeInputInventory; +import net.minecraft.item.ItemStack; import net.minecraft.screen.AbstractRecipeScreenHandler; import net.minecraft.screen.CraftingScreenHandler; import net.minecraft.screen.ScreenHandlerType; @@ -32,21 +33,30 @@ 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(CraftingScreenHandler.class) public abstract class MixinCraftingScreenHandler extends AbstractRecipeScreenHandler { - @Shadow @Final private RecipeInputInventory input; + @Shadow + @Final + private RecipeInputInventory input; public MixinCraftingScreenHandler(ScreenHandlerType screenHandlerType, int i) { super(screenHandlerType, i); } + @Redirect(method = "quickMove", at = @At(value = "INVOKE", target = "Lnet/minecraft/screen/CraftingScreenHandler;insertItem(Lnet/minecraft/item/ItemStack;IIZ)Z", ordinal = 1)) + private boolean noShiftClickMoveIntoCraftingTable(CraftingScreenHandler instance, ItemStack itemStack, int startIndex, int endIndex, boolean fromLast) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_14_4)) return false; + return this.insertItem(itemStack, startIndex, endIndex, fromLast); + } + @Inject(method = "onContentChanged", at = @At("HEAD")) - private void updateResultSlot(Inventory inventory, CallbackInfo ci) { + private void clientSideCrafting(Inventory inventory, CallbackInfo ci) { if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_11_1to1_11_2)) { - RecipesPre1_12.setCraftingResultSlot(syncId, this, input); + Recipes1_11_2.setCraftingResultSlot(syncId, this, input); } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinMerchantScreenHandler.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinMerchantScreenHandler.java new file mode 100644 index 000000000..dc1bed9d2 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinMerchantScreenHandler.java @@ -0,0 +1,118 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen.screenhandler; + +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.MerchantScreenHandler; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.ScreenHandlerType; +import net.minecraft.screen.slot.Slot; +import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.village.MerchantInventory; +import net.minecraft.village.TradeOfferList; +import net.raphimc.vialoader.util.VersionEnum; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(MerchantScreenHandler.class) +public abstract class MixinMerchantScreenHandler extends ScreenHandler { + + @Shadow + @Final + private MerchantInventory merchantInventory; + + @Shadow + public abstract TradeOfferList getRecipes(); + + protected MixinMerchantScreenHandler(@Nullable ScreenHandlerType type, int syncId) { + super(type, syncId); + } + + @Inject(method = "switchTo", at = @At("HEAD"), cancellable = true) + private void onSwitchTo(int recipeId, CallbackInfo ci) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_13_2)) { + ci.cancel(); + + if (recipeId >= this.getRecipes().size()) return; + + final ClientPlayerInteractionManager interactionManager = MinecraftClient.getInstance().interactionManager; + final ClientPlayerEntity player = MinecraftClient.getInstance().player; + + // move 1st input slot to inventory + if (!this.merchantInventory.getStack(0).isEmpty()) { + final int count = this.merchantInventory.getStack(0).getCount(); + interactionManager.clickSlot(syncId, 0, 0, SlotActionType.QUICK_MOVE, player); + if (count == this.merchantInventory.getStack(0).getCount()) return; + } + + // move 2nd input slot to inventory + if (!this.merchantInventory.getStack(1).isEmpty()) { + final int count = this.merchantInventory.getStack(1).getCount(); + interactionManager.clickSlot(syncId, 1, 0, SlotActionType.QUICK_MOVE, player); + if (count == this.merchantInventory.getStack(1).getCount()) return; + } + + // refill the slots + if (this.merchantInventory.getStack(0).isEmpty() && this.merchantInventory.getStack(1).isEmpty()) { + this.autofill(interactionManager, player, 0, this.getRecipes().get(recipeId).getAdjustedFirstBuyItem()); + this.autofill(interactionManager, player, 1, this.getRecipes().get(recipeId).getSecondBuyItem()); + } + } + } + + @Inject(method = "canInsertIntoSlot", at = @At("HEAD"), cancellable = true) + private void modifyCanInsertIntoSlot(ItemStack stack, Slot slot, CallbackInfoReturnable cir) { + if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_13_2)) { + cir.setReturnValue(true); + } + } + + @Unique + private void autofill(ClientPlayerInteractionManager interactionManager, ClientPlayerEntity player, int inputSlot, ItemStack stackNeeded) { + if (stackNeeded.isEmpty()) return; + + int slot; + for (slot = 3; slot < 39; slot++) { + final ItemStack stack = slots.get(slot).getStack(); + if (ItemStack.canCombine(stack, stackNeeded)) { + break; + } + } + if (slot == 39) return; + + final boolean wasHoldingItem = !player.currentScreenHandler.getCursorStack().isEmpty(); + interactionManager.clickSlot(syncId, slot, 0, SlotActionType.PICKUP, player); + interactionManager.clickSlot(syncId, slot, 0, SlotActionType.PICKUP_ALL, player); + interactionManager.clickSlot(syncId, inputSlot, 0, SlotActionType.PICKUP, player); + if (wasHoldingItem) interactionManager.clickSlot(syncId, slot, 0, SlotActionType.PICKUP, player); + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinPlayerScreenHandler.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinPlayerScreenHandler.java index b737e87d1..7606bc1ec 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinPlayerScreenHandler.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinPlayerScreenHandler.java @@ -19,56 +19,50 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.screen.screenhandler; -import de.florianmichael.viafabricplus.fixes.diff.RecipesPre1_12; -import net.minecraft.inventory.Inventory; -import net.minecraft.inventory.RecipeInputInventory; -import net.raphimc.vialoader.util.VersionEnum; +import de.florianmichael.viafabricplus.fixes.recipe.Recipes1_11_2; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; -import net.minecraft.entity.EquipmentSlot; import net.minecraft.inventory.CraftingInventory; +import net.minecraft.inventory.Inventory; +import net.minecraft.inventory.RecipeInputInventory; import net.minecraft.screen.AbstractRecipeScreenHandler; import net.minecraft.screen.PlayerScreenHandler; import net.minecraft.screen.ScreenHandlerType; import net.minecraft.screen.slot.Slot; +import net.raphimc.vialoader.util.VersionEnum; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.*; +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(PlayerScreenHandler.class) public abstract class MixinPlayerScreenHandler extends AbstractRecipeScreenHandler { - @Shadow @Final private RecipeInputInventory craftingInput; + @Shadow + @Final + private RecipeInputInventory craftingInput; public MixinPlayerScreenHandler(ScreenHandlerType screenHandlerType, int i) { super(screenHandlerType, i); } @Inject(method = "onContentChanged", at = @At("HEAD")) - public void updateResultSlot(Inventory inventory, CallbackInfo ci) { + public void clientSideCrafting(Inventory inventory, CallbackInfo ci) { if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_11_1to1_11_2)) { - RecipesPre1_12.setCraftingResultSlot(syncId, this, craftingInput); + Recipes1_11_2.setCraftingResultSlot(syncId, this, craftingInput); } } @Redirect(method = "", slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/screen/PlayerScreenHandler$2;(Lnet/minecraft/screen/PlayerScreenHandler;Lnet/minecraft/inventory/Inventory;IIILnet/minecraft/entity/player/PlayerEntity;)V")), at = @At(value = "INVOKE", target = "Lnet/minecraft/screen/PlayerScreenHandler;addSlot(Lnet/minecraft/screen/slot/Slot;)Lnet/minecraft/screen/slot/Slot;", ordinal = 0)) - private Slot redirectAddOffhandSlot(PlayerScreenHandler screenHandler, Slot slot) { + private Slot removeOffhandSlot(PlayerScreenHandler screenHandler, Slot slot) { if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) return null; return addSlot(slot); } - @SuppressWarnings("InvalidInjectorMethodSignature") - @ModifyVariable(method = "quickMove", ordinal = 0, at = @At(value = "STORE", ordinal = 0)) - private EquipmentSlot injectTransferSlot(EquipmentSlot slot) { - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8) && slot == EquipmentSlot.OFFHAND) { - return EquipmentSlot.MAINHAND; - } else { - return slot; - } - } - } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinScreenHandler.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinScreenHandler.java index 97e053036..f28a39643 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinScreenHandler.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/screen/screenhandler/MixinScreenHandler.java @@ -21,32 +21,39 @@ import de.florianmichael.viafabricplus.injection.access.IScreenHandler; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; -import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; import net.minecraft.screen.ScreenHandler; -import net.minecraft.screen.slot.SlotActionType; import net.raphimc.vialoader.util.VersionEnum; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; 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.Redirect; @Mixin(ScreenHandler.class) public abstract class MixinScreenHandler implements IScreenHandler { + @Shadow + private ItemStack cursorStack; + @Unique - private short viaFabricPlus$lastActionId = 0; + private short viaFabricPlus$actionId = 0; - @Inject(method = "internalOnSlotClick", at = @At("HEAD"), cancellable = true) - private void injectInternalOnSlotClick(int slot, int clickData, SlotActionType actionType, PlayerEntity player, CallbackInfo ci) { - if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8) && actionType == SlotActionType.SWAP && clickData == 40) { - ci.cancel(); + @Redirect(method = "updateSlotStacks", at = @At(value = "FIELD", target = "Lnet/minecraft/screen/ScreenHandler;cursorStack:Lnet/minecraft/item/ItemStack;")) + private void preventUpdate(ScreenHandler instance, ItemStack value) { + if (ProtocolHack.getTargetVersion().isNewerThanOrEqualTo(VersionEnum.r1_17_1)) { + this.cursorStack = value; } } @Override - public short viaFabricPlus$getAndIncrementLastActionId() { - return ++viaFabricPlus$lastActionId; + public short viaFabricPlus$getActionId() { + return viaFabricPlus$actionId; + } + + @Override + public short viaFabricPlus$incrementAndGetActionId() { + return ++viaFabricPlus$actionId; } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinCommandBlockProvider.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinCommandBlockProvider.java index 391c6dbe9..d71349c28 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinCommandBlockProvider.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinCommandBlockProvider.java @@ -24,12 +24,12 @@ import org.spongepowered.asm.mixin.injection.Constant; import org.spongepowered.asm.mixin.injection.ModifyConstant; -@Mixin(CommandBlockProvider.class) +@Mixin(value = CommandBlockProvider.class, remap = false) public abstract class MixinCommandBlockProvider { - @ModifyConstant(method = "sendPermission", constant = @Constant(intValue = 26), remap = false) + @ModifyConstant(method = "sendPermission", constant = @Constant(intValue = 26)) private int modifyPermissionLevel(int constant) { - return 28; + return 28; // OP level 4 } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinEntityIdRewriter.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinEntityIdRewriter.java index 77b087385..ea6b422b9 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinEntityIdRewriter.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinEntityIdRewriter.java @@ -20,16 +20,39 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.viaversion; import com.viaversion.viaversion.api.minecraft.item.Item; +import com.viaversion.viaversion.libs.opennbt.tag.builtin.ByteTag; +import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag; import com.viaversion.viaversion.protocols.protocol1_11to1_10.EntityIdRewriter; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(value = EntityIdRewriter.class, remap = false) public abstract class MixinEntityIdRewriter { - @Redirect(method = "toClientItem(Lcom/viaversion/viaversion/api/minecraft/item/Item;Z)V", at = @At(value = "INVOKE", target = "Lcom/viaversion/viaversion/api/minecraft/item/Item;setAmount(I)V")) - private static void allowNegativeItems(Item instance, int i) { + @Inject(method = "toClientItem(Lcom/viaversion/viaversion/api/minecraft/item/Item;Z)V", at = @At("HEAD")) + private static void handleNegativeItemCountS2C(Item item, boolean backwards, CallbackInfo ci) { + if (item != null && item.amount() <= 0) { + CompoundTag tag = item.tag(); + if (tag == null) { + tag = new CompoundTag(); + item.setTag(tag); + } + + tag.put("1_10_ViaFabricPlus_ItemCount", new ByteTag((byte) item.amount())); + item.setTag(tag); + } + } + + @Inject(method = "toServerItem(Lcom/viaversion/viaversion/api/minecraft/item/Item;Z)V", at = @At("HEAD")) + private static void handleNegativeItemCountC2S(Item item, boolean backwards, CallbackInfo ci) { + if (item != null && item.tag() != null) { + if (item.tag().contains("1_10_ViaFabricPlus_ItemCount")) { + item.setAmount(item.tag().remove("1_10_ViaFabricPlus_ItemCount").asByte()); + if (item.tag().isEmpty()) item.setTag(null); + } + } } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinEntityPackets1_19_4.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinEntityPackets1_19_4.java new file mode 100644 index 000000000..1cead9e54 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinEntityPackets1_19_4.java @@ -0,0 +1,26 @@ +package de.florianmichael.viafabricplus.injection.mixin.fixes.viaversion; + +import com.viaversion.viaversion.protocols.protocol1_19_3to1_19_1.ClientboundPackets1_19_3; +import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.ClientboundPackets1_19_4; +import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.Protocol1_19_4To1_19_3; +import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.packets.EntityPackets; +import com.viaversion.viaversion.rewriter.EntityRewriter; +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(value = EntityPackets.class, remap = false) +public abstract class MixinEntityPackets1_19_4 extends EntityRewriter { + + protected MixinEntityPackets1_19_4(Protocol1_19_4To1_19_3 protocol) { + super(protocol); + } + + @Inject(method = "registerPackets", at = @At("RETURN")) + private void fixTeleportBehaviour(CallbackInfo ci) { + this.protocol.registerClientbound(ClientboundPackets1_19_3.ENTITY_TELEPORT, ClientboundPackets1_19_4.ENTITY_TELEPORT, wrapper -> { + }, true); + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinInventoryAcknowledgements.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinInventoryAcknowledgements.java index 1cdba175b..34f43e4d8 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinInventoryAcknowledgements.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinInventoryAcknowledgements.java @@ -33,12 +33,15 @@ public abstract class MixinInventoryAcknowledgements { @Mutable - @Shadow @Final private IntList ids; + @Shadow + @Final + private IntList ids; + @Unique private it.unimi.dsi.fastutil.ints.IntList viaFabricPlus$ids; @Inject(method = "", at = @At("RETURN")) - private void fixJavaIssue(CallbackInfo ci) { + private void makeConcurrent(CallbackInfo ci) { this.ids = null; this.viaFabricPlus$ids = IntLists.synchronize(new IntArrayList()); } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinInventoryPackets.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinInventoryPackets.java index 4faefd9fd..93cc1352e 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinInventoryPackets.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinInventoryPackets.java @@ -19,65 +19,36 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.viaversion; -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.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 de.florianmichael.viafabricplus.fixes.ChestHandler1_13_2; import de.florianmichael.viafabricplus.fixes.ClientsideFixes; -import de.florianmichael.viafabricplus.fixes.TripleChestHandler1_13_2; -import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; -import io.netty.buffer.Unpooled; -import net.minecraft.SharedConstants; +import de.florianmichael.viafabricplus.protocolhack.translator.TextComponentTranslator; 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.logging.Level; -import java.util.stream.Collectors; - @Mixin(value = InventoryPackets.class, remap = false) public abstract 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) { + @Inject(method = "lambda$registerPackets$0", at = @At(value = "INVOKE", target = "Ljava/util/logging/Logger;warning(Ljava/lang/String;)V", remap = false), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true) + private static void supportLargeContainers(PacketWrapper wrapper, CallbackInfo ci, Short windowId, String type, JsonElement title, Short slots) { + if ((type.equals("minecraft:container") || type.equals("minecraft:chest")) && (slots > 54 || slots <= 0)) { + ci.cancel(); + + final String uuid = ClientsideFixes.executeSyncTask(ChestHandler1_13_2.OLD_PACKET_HANDLER); wrapper.clearPacket(); wrapper.setPacketType(ClientboundPackets1_14.PLUGIN_MESSAGE); wrapper.write(Type.STRING, ClientsideFixes.PACKET_SYNC_IDENTIFIER); - - final List 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 = ClientsideFixes.executeSyncTask(TripleChestHandler1_13_2.TRIPLE_CHEST_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) { - Via.getPlatform().getLogger().log(Level.SEVERE, "Failed to emulate Triple Chest", e); - } - - ci.cancel(); + wrapper.write(Type.STRING, uuid); + wrapper.write(Type.UNSIGNED_BYTE, windowId); + wrapper.write(Type.UNSIGNED_BYTE, slots); + wrapper.write(Type.COMPONENT, TextComponentTranslator.via1_13_2toViaLatest(title)); } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinInventoryPackets1_13.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinInventoryPackets1_13.java new file mode 100644 index 000000000..262c28ac8 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinInventoryPackets1_13.java @@ -0,0 +1,29 @@ +package de.florianmichael.viafabricplus.injection.mixin.fixes.viaversion; + +import com.viaversion.viaversion.api.minecraft.item.Item; +import com.viaversion.viaversion.api.protocol.remapper.PacketHandler; +import com.viaversion.viaversion.api.type.Type; +import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13; +import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ServerboundPackets1_13; +import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.Protocol1_14To1_13_2; +import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.ServerboundPackets1_14; +import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.packets.InventoryPackets; +import com.viaversion.viaversion.rewriter.ItemRewriter; +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(value = InventoryPackets.class, remap = false) +public abstract class MixinInventoryPackets1_13 extends ItemRewriter { + + public MixinInventoryPackets1_13(Protocol1_14To1_13_2 protocol, Type itemType, Type itemArrayType) { + super(protocol, itemType, itemArrayType); + } + + @Inject(method = "registerPackets", at = @At("RETURN")) + private void dontResyncInventory(CallbackInfo ci) { + this.protocol.registerServerbound(ServerboundPackets1_14.SELECT_TRADE, ServerboundPackets1_13.SELECT_TRADE, (PacketHandler) null, true); + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinInventoryPackets1_17.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinInventoryPackets1_17.java new file mode 100644 index 000000000..af0850972 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinInventoryPackets1_17.java @@ -0,0 +1,51 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.viaversion; + +import com.viaversion.viaversion.api.Via; +import com.viaversion.viaversion.api.minecraft.item.Item; +import com.viaversion.viaversion.api.type.Type; +import com.viaversion.viaversion.protocols.protocol1_16_2to1_16_1.ClientboundPackets1_16_2; +import com.viaversion.viaversion.protocols.protocol1_16_2to1_16_1.ServerboundPackets1_16_2; +import com.viaversion.viaversion.protocols.protocol1_17to1_16_4.Protocol1_17To1_16_4; +import com.viaversion.viaversion.protocols.protocol1_17to1_16_4.ServerboundPackets1_17; +import com.viaversion.viaversion.protocols.protocol1_17to1_16_4.packets.InventoryPackets; +import com.viaversion.viaversion.rewriter.ItemRewriter; +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(value = InventoryPackets.class, remap = false) +public abstract class MixinInventoryPackets1_17 extends ItemRewriter { + + public MixinInventoryPackets1_17(Protocol1_17To1_16_4 protocol, Type itemType, Type itemArrayType) { + super(protocol, itemType, itemArrayType); + } + + @Inject(method = "registerPackets", at = @At("RETURN")) + private void removeWindowClickHandler(CallbackInfo ci) { + this.protocol.registerServerbound(ServerboundPackets1_17.CLICK_WINDOW, ServerboundPackets1_16_2.CLICK_WINDOW, wrapper -> { + Via.getPlatform().getLogger().severe("Tried to remap >=1.17 CLICK_WINDOW packet which is impossible without breaking the content! Find the cause and fix it!"); + wrapper.cancel(); + }, true); + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinSkullHandler.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinInventoryTracker1_16.java similarity index 60% rename from src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinSkullHandler.java rename to src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinInventoryTracker1_16.java index 9e2c907a9..7674c3298 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinSkullHandler.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinInventoryTracker1_16.java @@ -19,19 +19,20 @@ package de.florianmichael.viafabricplus.injection.mixin.fixes.viaversion; -import com.viaversion.viaversion.libs.opennbt.tag.builtin.NumberTag; -import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.providers.blockentities.SkullHandler; +import com.viaversion.viaversion.protocols.protocol1_16to1_15_2.storage.InventoryTracker1_16; 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; +import org.spongepowered.asm.mixin.Overwrite; -@Mixin(value = SkullHandler.class, remap = false) -public abstract class MixinSkullHandler { +@Mixin(value = InventoryTracker1_16.class, remap = false) +public abstract class MixinInventoryTracker1_16 { - @Inject(method = "getLong", at = @At("HEAD"), cancellable = true) - public void checkIfTagExists(NumberTag tag, CallbackInfoReturnable cir) { - if (tag == null) cir.setReturnValue(0L); + /** + * @author RK_01 + * @reason Fix ViaVersion cancelling swing packets even when no inventory is open + */ + @Overwrite + public boolean isInventoryOpen() { + return false; } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinNamedCompoundTagType.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinNamedCompoundTagType.java index 388391b1d..0e9fd4c63 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinNamedCompoundTagType.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinNamedCompoundTagType.java @@ -22,48 +22,15 @@ import com.viaversion.viaversion.api.type.types.misc.NamedCompoundTagType; import com.viaversion.viaversion.libs.opennbt.tag.limiter.TagLimiter; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(value = NamedCompoundTagType.class, remap = false) public abstract class MixinNamedCompoundTagType { - @Unique - private static final TagLimiter viaFabricPlus$tag_limiter = new TagLimiter() { - private final int maxBytes = 2097152; - private int bytes; - - @Override - public void countBytes(int i) { - this.bytes += bytes; - if (this.bytes >= this.maxBytes) { - throw new IllegalArgumentException("NBT data larger than expected (capped at " + this.maxBytes + ")"); - } - } - - @Override - public void checkLevel(int i) {} - - @Override - public int maxBytes() { - return this.maxBytes; - } - - @Override - public int maxLevels() { - return 512; // Not used anymore - } - - @Override - public int bytes() { - return this.bytes; - } - }; - @Redirect(method = "read(Lio/netty/buffer/ByteBuf;Z)Lcom/viaversion/viaversion/libs/opennbt/tag/builtin/CompoundTag;", at = @At(value = "INVOKE", target = "Lcom/viaversion/viaversion/libs/opennbt/tag/limiter/TagLimiter;create(II)Lcom/viaversion/viaversion/libs/opennbt/tag/limiter/TagLimiter;")) - private static TagLimiter replaceTagLimiter(int maxBytes, int maxLevels) { - return viaFabricPlus$tag_limiter; + private static TagLimiter removeNBTSizeLimit(int maxBytes, int maxLevels) { + return TagLimiter.noop(); } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinProtocol1_11To1_10.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinProtocol1_11To1_10.java index 671a85408..349df4807 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinProtocol1_11To1_10.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinProtocol1_11To1_10.java @@ -29,7 +29,7 @@ public abstract class MixinProtocol1_11To1_10 { @ModifyConstant(method = "lambda$register$0", constant = @Constant(intValue = 100)) private static int changeMaxChatLength(int constant) { - return ClientsideFixes.getCurrentChatLimit(); + return ClientsideFixes.getCurrentChatLength(); } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinProtocol1_12To1_11_1.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinProtocol1_12To1_11_1.java new file mode 100644 index 000000000..e95b52390 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinProtocol1_12To1_11_1.java @@ -0,0 +1,16 @@ +package de.florianmichael.viafabricplus.injection.mixin.fixes.viaversion; + +import com.viaversion.viaversion.api.connection.ProtocolInfo; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(targets = "com.viaversion.viaversion.protocols.protocol1_12to1_11_1.Protocol1_12To1_11_1$3", remap = false) +public abstract class MixinProtocol1_12To1_11_1 { + + @Redirect(method = "lambda$register$1", at = @At(value = "INVOKE", target = "Lcom/viaversion/viaversion/api/connection/ProtocolInfo;getProtocolVersion()I")) + private static int dontClearRecipes(ProtocolInfo instance) { + return -1; + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinTagType.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinTagType.java new file mode 100644 index 000000000..24530a3f5 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinTagType.java @@ -0,0 +1,17 @@ +package de.florianmichael.viafabricplus.injection.mixin.fixes.viaversion; + +import com.viaversion.viaversion.api.type.types.misc.TagType; +import com.viaversion.viaversion.libs.opennbt.tag.limiter.TagLimiter; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(value = TagType.class, remap = false) +public abstract class MixinTagType { + + @Redirect(method = "read(Lio/netty/buffer/ByteBuf;)Lcom/viaversion/viaversion/libs/opennbt/tag/builtin/Tag;", at = @At(value = "INVOKE", target = "Lcom/viaversion/viaversion/libs/opennbt/tag/limiter/TagLimiter;create(II)Lcom/viaversion/viaversion/libs/opennbt/tag/limiter/TagLimiter;")) + private TagLimiter removeNBTSizeLimit(int maxBytes, int maxLevels) { + return TagLimiter.noop(); + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinWorldPackets1_19.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinWorldPackets1_19.java index 7162856f2..8a6924e45 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinWorldPackets1_19.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/viaversion/MixinWorldPackets1_19.java @@ -21,7 +21,6 @@ import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType; import com.viaversion.viaversion.api.type.Type; -import com.viaversion.viaversion.protocols.protocol1_14_4to1_14_3.Protocol1_14_4To1_14_3; import com.viaversion.viaversion.protocols.protocol1_18to1_17_1.ClientboundPackets1_18; import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.ClientboundPackets1_19; import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.Protocol1_19To1_18_2; @@ -38,14 +37,9 @@ public abstract class MixinWorldPackets1_19 { @Redirect(method = "register", at = @At(value = "INVOKE", target = "Lcom/viaversion/viaversion/protocols/protocol1_19to1_18_2/Protocol1_19To1_18_2;cancelClientbound(Lcom/viaversion/viaversion/api/protocol/packet/ClientboundPacketType;)V")) private static void passAcknowledgePlayerDigging(Protocol1_19To1_18_2 instance, ClientboundPacketType clientboundPacketType) { instance.registerClientbound(ClientboundPackets1_18.ACKNOWLEDGE_PLAYER_DIGGING, ClientboundPackets1_19.PLUGIN_MESSAGE, wrapper -> { - if (wrapper.user().getProtocolInfo().getPipeline().contains(Protocol1_14_4To1_14_3.class)) { - wrapper.cancel(); - return; - } - wrapper.resetReader(); - final var uuid = ClientsideFixes.executeSyncTask(ClientPlayerInteractionManager1_18_2.OLD_PACKET_HANDLER); + final var uuid = ClientsideFixes.executeSyncTask(ClientPlayerInteractionManager1_18_2.OLD_PACKET_HANDLER); wrapper.write(Type.STRING, ClientsideFixes.PACKET_SYNC_IDENTIFIER); wrapper.write(Type.STRING, uuid); }); diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/viaversion/MixinAbstractFenceConnectionHandler.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/viaversion/MixinAbstractFenceConnectionHandler.java index 5a0b2737f..1453fca48 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/viaversion/MixinAbstractFenceConnectionHandler.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/viaversion/MixinAbstractFenceConnectionHandler.java @@ -22,10 +22,8 @@ import com.viaversion.viaversion.api.connection.UserConnection; import com.viaversion.viaversion.api.minecraft.BlockFace; import com.viaversion.viaversion.api.minecraft.Position; -import net.raphimc.vialoader.util.VersionEnum; -import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.blockconnections.AbstractFenceConnectionHandler; -import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.raphimc.vialoader.util.VersionEnum; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; @@ -44,7 +42,7 @@ public abstract class MixinAbstractFenceConnectionHandler { @Overwrite public byte getStates(UserConnection user, Position position, int blockState) { byte states = 0; - boolean pre1_12 = ProtocolHack.getTargetVersion().isOlderThan(VersionEnum.r1_12); + boolean pre1_12 = VersionEnum.fromUserConnection(user).isOlderThan(VersionEnum.r1_12); if (connects(BlockFace.EAST, getBlockData(user, position.getRelative(BlockFace.EAST)), pre1_12)) states |= 1; if (connects(BlockFace.NORTH, getBlockData(user, position.getRelative(BlockFace.NORTH)), pre1_12)) states |= 2; if (connects(BlockFace.SOUTH, getBlockData(user, position.getRelative(BlockFace.SOUTH)), pre1_12)) states |= 4; diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/viaversion/MixinGlassConnectionHandler.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/viaversion/MixinGlassConnectionHandler.java index 5f34714e3..c80bb37d4 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/viaversion/MixinGlassConnectionHandler.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/viaversion/MixinGlassConnectionHandler.java @@ -22,11 +22,9 @@ import com.viaversion.viaversion.api.connection.ProtocolInfo; import com.viaversion.viaversion.api.connection.UserConnection; import com.viaversion.viaversion.api.minecraft.Position; -import net.raphimc.vialoader.util.VersionEnum; -import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.blockconnections.AbstractFenceConnectionHandler; import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.blockconnections.GlassConnectionHandler; -import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.raphimc.vialoader.util.VersionEnum; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; @@ -47,7 +45,7 @@ public byte getStates(UserConnection user, Position position, int blockState) { if (states != 0) return states; ProtocolInfo protocolInfo = user.getProtocolInfo(); - return ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8) && protocolInfo.getServerProtocolVersion() != -1 ? 0xF : states; + return VersionEnum.fromUserConnection(user).isOlderThanOrEqualTo(VersionEnum.r1_8) && protocolInfo.getServerProtocolVersion() != -1 ? 0xF : states; } } diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/viaversion/MixinProtocolVersion.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/viaversion/MixinProtocolVersion.java index 2145e98bb..dd64bde87 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/viaversion/MixinProtocolVersion.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/viaversion/MixinProtocolVersion.java @@ -19,6 +19,7 @@ package de.florianmichael.viafabricplus.injection.mixin.viaversion; +import com.google.common.collect.ImmutableSet; import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; import com.viaversion.viaversion.api.protocol.version.VersionRange; import com.viaversion.viaversion.util.Pair; @@ -31,15 +32,20 @@ import java.util.HashMap; import java.util.Map; +import java.util.Set; @Mixin(value = ProtocolVersion.class, remap = false) public abstract class MixinProtocolVersion { + @Unique + private static Set viaFabricPlus$skips; + @Unique private static Map> viaFabricPlus$remaps; @Inject(method = "", at = @At("HEAD")) private static void initMaps(CallbackInfo ci) { + viaFabricPlus$skips = ImmutableSet.of("1.4.6/7", "1.5.1", "1.5.2", "1.6.1", "1.6.2", "1.6.3", "1.6.4"); viaFabricPlus$remaps = new HashMap<>(); viaFabricPlus$remaps.put("1.7-1.7.5", new Pair<>("1.7.2-1.7.5", new VersionRange("1.7", 2, 5))); viaFabricPlus$remaps.put("1.9.3/4", new Pair<>("1.9.3-1.9.4", null)); @@ -53,6 +59,7 @@ private static void initMaps(CallbackInfo ci) { @Redirect(method = "", at = @At(value = "INVOKE", target = "Lcom/viaversion/viaversion/api/protocol/version/ProtocolVersion;register(ILjava/lang/String;)Lcom/viaversion/viaversion/api/protocol/version/ProtocolVersion;")) private static ProtocolVersion unregisterAndRenameVersions(int version, String name) { + if (viaFabricPlus$skips.contains(name)) return null; final Pair remapEntry = viaFabricPlus$remaps.get(name); if (remapEntry != null) { if (remapEntry.key() != null) name = remapEntry.key(); @@ -64,6 +71,7 @@ private static ProtocolVersion unregisterAndRenameVersions(int version, String n @SuppressWarnings({"UnresolvedMixinReference", "MixinAnnotationTarget", "InvalidInjectorMethodSignature"}) // Optional injection @Redirect(method = "", at = @At(value = "INVOKE", target = "Lcom/viaversion/viaversion/api/protocol/version/ProtocolVersion;register(IILjava/lang/String;)Lcom/viaversion/viaversion/api/protocol/version/ProtocolVersion;"), require = 0) private static ProtocolVersion unregisterAndRenameVersions(int version, int snapshotVersion, String name) { + if (viaFabricPlus$skips.contains(name)) return null; final Pair remapEntry = viaFabricPlus$remaps.get(name); if (remapEntry != null) { if (remapEntry.key() != null) name = remapEntry.key(); @@ -74,6 +82,7 @@ private static ProtocolVersion unregisterAndRenameVersions(int version, int snap @Redirect(method = "", at = @At(value = "INVOKE", target = "Lcom/viaversion/viaversion/api/protocol/version/ProtocolVersion;register(ILjava/lang/String;Lcom/viaversion/viaversion/api/protocol/version/VersionRange;)Lcom/viaversion/viaversion/api/protocol/version/ProtocolVersion;")) private static ProtocolVersion unregisterAndRenameVersions(int version, String name, VersionRange versionRange) { + if (viaFabricPlus$skips.contains(name)) return null; final Pair remapEntry = viaFabricPlus$remaps.get(name); if (remapEntry != null) { if (remapEntry.key() != null) name = remapEntry.key(); diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/reference/BuiltinEmptyGlyph1_12_2.java b/src/main/java/de/florianmichael/viafabricplus/injection/reference/BuiltinEmptyGlyph1_12_2.java index fa1646d46..f220cc844 100644 --- a/src/main/java/de/florianmichael/viafabricplus/injection/reference/BuiltinEmptyGlyph1_12_2.java +++ b/src/main/java/de/florianmichael/viafabricplus/injection/reference/BuiltinEmptyGlyph1_12_2.java @@ -25,35 +25,34 @@ import java.util.function.Function; -/** - * Implementation of a "Very Missing" Glyph which doesn't have any rendering at all ("Missing" in <= 1.12.2) - */ public enum BuiltinEmptyGlyph1_12_2 implements Glyph { + INSTANCE; - VERY_MISSING; + private static final int WIDTH = 0; + private static final int HEIGHT = 8; @Override public float getAdvance() { - return 1; + return WIDTH; } @Override - public GlyphRenderer bake(Function function) { - return function.apply(new RenderableGlyph() { + public GlyphRenderer bake(Function glyphRendererGetter) { + return glyphRendererGetter.apply(new RenderableGlyph() { @Override public int getWidth() { - return 0; + return WIDTH; } @Override public int getHeight() { - return 0; + return HEIGHT; } @Override public float getOversample() { - return 1.0f; + return 1F; } @Override @@ -66,4 +65,5 @@ public boolean hasColor() { } }); } + } diff --git a/src/main/java/de/florianmichael/viafabricplus/protocolhack/ProtocolHack.java b/src/main/java/de/florianmichael/viafabricplus/protocolhack/ProtocolHack.java index 8b13d7f4e..42b7e3755 100644 --- a/src/main/java/de/florianmichael/viafabricplus/protocolhack/ProtocolHack.java +++ b/src/main/java/de/florianmichael/viafabricplus/protocolhack/ProtocolHack.java @@ -23,11 +23,13 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.RequiredArgumentBuilder; import com.viaversion.viaversion.api.Via; +import com.viaversion.viaversion.api.connection.ProtocolInfo; import com.viaversion.viaversion.api.connection.UserConnection; +import com.viaversion.viaversion.api.protocol.ProtocolPathEntry; +import com.viaversion.viaversion.api.protocol.ProtocolPipeline; +import com.viaversion.viaversion.api.protocol.packet.State; 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 com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage.ConfigurationState; import de.florianmichael.viafabricplus.event.ChangeProtocolVersionCallback; import de.florianmichael.viafabricplus.event.PostViaVersionLoadCallback; import de.florianmichael.viafabricplus.injection.access.IClientConnection; @@ -52,6 +54,7 @@ import org.cloudburstmc.netty.channel.raknet.config.RakChannelOption; import java.io.File; +import java.util.List; import java.util.concurrent.ThreadLocalRandom; /** @@ -131,29 +134,30 @@ public static void setTargetVersion(VersionEnum newVersion) { } /** - * @return Creates a Fake UserConnection class with a valid protocol pipeline to emulate packets + * @param clientVersion The client version + * @param serverVersion The server version + * @return Creates a dummy UserConnection class with a valid protocol pipeline to emulate packets */ - @Deprecated - public static UserConnection createFakerUserConnection() { - return createFakerUserConnection(getPlayNetworkUserConnection().getChannel()); - } - - /** - * @param channel the current channel - * @return Creates a Fake UserConnection class with a valid protocol pipeline to emulate packets - */ - @Deprecated - public static UserConnection createFakerUserConnection(final Channel channel) { - final var fake = new UserConnectionImpl(channel, true); - fake.getProtocolInfo().setPipeline(new ProtocolPipelineImpl(fake)); - - fake.put(new InventoryTracker1_16()); - fake.put(new ConfigurationState()); + public static UserConnection createDummyUserConnection(final VersionEnum clientVersion, final VersionEnum serverVersion) { + final UserConnection user = new UserConnectionImpl(null, true); + final ProtocolPipeline pipeline = new ProtocolPipelineImpl(user); + final List path = Via.getManager().getProtocolManager().getProtocolPath(clientVersion.getVersion(), serverVersion.getVersion()); + for (ProtocolPathEntry pair : path) { + pipeline.add(pair.protocol()); + pair.protocol().init(user); + } - //noinspection DataFlowIssue - fake.get(ConfigurationState.class).setBridgePhase(ConfigurationState.BridgePhase.NONE); + final MinecraftClient mc = MinecraftClient.getInstance(); + final ProtocolInfo info = user.getProtocolInfo(); + info.setState(State.PLAY); + info.setProtocolVersion(clientVersion.getVersion()); + info.setServerProtocolVersion(serverVersion.getVersion()); + if (mc.player != null) { + info.setUsername(MinecraftClient.getInstance().player.getGameProfile().getName()); + info.setUuid(MinecraftClient.getInstance().player.getGameProfile().getId()); + } - return fake; + return user; } /** diff --git a/src/main/java/de/florianmichael/viafabricplus/protocolhack/impl/ViaFabricPlusVLLoader.java b/src/main/java/de/florianmichael/viafabricplus/protocolhack/impl/ViaFabricPlusVLLoader.java index 4eecbb7dc..8304520c6 100644 --- a/src/main/java/de/florianmichael/viafabricplus/protocolhack/impl/ViaFabricPlusVLLoader.java +++ b/src/main/java/de/florianmichael/viafabricplus/protocolhack/impl/ViaFabricPlusVLLoader.java @@ -25,8 +25,8 @@ import com.viaversion.viaversion.api.protocol.version.VersionProvider; import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.providers.PlayerLookTargetProvider; import com.viaversion.viaversion.protocols.protocol1_16to1_15_2.provider.PlayerAbilitiesProvider; +import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.provider.AckSequenceProvider; import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.HandItemProvider; -import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider; import de.florianmichael.viafabricplus.protocolhack.provider.viabedrock.ViaFabricPlusBlobCacheProvider; import de.florianmichael.viafabricplus.protocolhack.provider.viabedrock.ViaFabricPlusNettyPipelineProvider; import de.florianmichael.viafabricplus.protocolhack.provider.viabedrock.ViaFabricPlusTransferProvider; @@ -53,11 +53,11 @@ public void load() { providers.use(VersionProvider.class, new ViaFabricPlusBaseVersionProvider()); - providers.use(MovementTransmitterProvider.class, new ViaFabricPlusMovementTransmitterProvider()); providers.use(HandItemProvider.class, new ViaFabricPlusHandItemProvider()); providers.use(PlayerLookTargetProvider.class, new ViaFabricPlusPlayerLookTargetProvider()); providers.use(PlayerAbilitiesProvider.class, new ViaFabricPlusPlayerAbilitiesProvider()); providers.use(SignableCommandArgumentsProvider.class, new ViaFabricPlusCommandArgumentsProvider()); + providers.use(AckSequenceProvider.class, new ViaFabricPlusAckSequenceProvider()); providers.use(OldAuthProvider.class, new ViaFabricPlusOldAuthProvider()); providers.use(ClassicWorldHeightProvider.class, new ViaFabricPlusClassicWorldHeightProvider()); diff --git a/src/main/java/de/florianmichael/viafabricplus/protocolhack/netty/ViaFabricPlusViaDecoder.java b/src/main/java/de/florianmichael/viafabricplus/protocolhack/netty/ViaFabricPlusViaDecoder.java index 8fccc3d00..3ef614859 100644 --- a/src/main/java/de/florianmichael/viafabricplus/protocolhack/netty/ViaFabricPlusViaDecoder.java +++ b/src/main/java/de/florianmichael/viafabricplus/protocolhack/netty/ViaFabricPlusViaDecoder.java @@ -38,17 +38,18 @@ public ViaFabricPlusViaDecoder(UserConnection user) { public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { final var mode = GeneralSettings.global().ignorePacketTranslationErrors.getIndex(); - if (mode > 0) { - try { - super.channelRead(ctx, msg); - } catch (Throwable t) { + try { + super.channelRead(ctx, msg); + } catch (Throwable t) { + if (mode > 0) { ViaFabricPlus.global().getLogger().error("Error occurred while decoding packet in ViaDecoder", t); if (mode == 1) { ChatUtil.sendPrefixedMessage(Text.literal("An error occurred while decoding a packet! See more details in the logs!").formatted(Formatting.RED)); } + + return; } - return; + throw t; } - super.channelRead(ctx, msg); } } diff --git a/src/main/java/de/florianmichael/viafabricplus/protocolhack/provider/vialegacy/ViaFabricPlusAlphaInventoryProvider.java b/src/main/java/de/florianmichael/viafabricplus/protocolhack/provider/vialegacy/ViaFabricPlusAlphaInventoryProvider.java index 51bdbdafe..2ff19c8ae 100644 --- a/src/main/java/de/florianmichael/viafabricplus/protocolhack/provider/vialegacy/ViaFabricPlusAlphaInventoryProvider.java +++ b/src/main/java/de/florianmichael/viafabricplus/protocolhack/provider/vialegacy/ViaFabricPlusAlphaInventoryProvider.java @@ -21,7 +21,7 @@ import com.viaversion.viaversion.api.connection.UserConnection; import com.viaversion.viaversion.api.minecraft.item.Item; -import de.florianmichael.viafabricplus.protocolhack.util.ItemTranslator; +import de.florianmichael.viafabricplus.protocolhack.translator.ItemTranslator; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.item.ItemStack; @@ -46,7 +46,7 @@ protected Item[] getMinecraftContainerItems(final List trackingItems) final var alphaItem = trackingItems.get(i); if (alphaItem.isEmpty()) continue; - items[i] = ItemTranslator.MC_TO_VIA_LATEST_TO_TARGET(alphaItem, VersionEnum.b1_8tob1_8_1); + items[i] = ItemTranslator.mcToVia(alphaItem, VersionEnum.b1_8tob1_8_1); } return copyItems(items); } @@ -81,7 +81,7 @@ public Item[] getContainerItems(UserConnection user) { @Override public void addToInventory(UserConnection user, Item item) { - getPlayer().getInventory().insertStack(ItemTranslator.VIA_TO_MC_B1_8_TO_LATEST(item)); + getPlayer().getInventory().insertStack(ItemTranslator.viaB1_8toMc(item)); } protected ClientPlayerEntity getPlayer() { diff --git a/src/main/java/de/florianmichael/viafabricplus/protocolhack/provider/vialegacy/ViaFabricPlusEncryptionProvider.java b/src/main/java/de/florianmichael/viafabricplus/protocolhack/provider/vialegacy/ViaFabricPlusEncryptionProvider.java index 1c041ec18..159c4cff9 100644 --- a/src/main/java/de/florianmichael/viafabricplus/protocolhack/provider/vialegacy/ViaFabricPlusEncryptionProvider.java +++ b/src/main/java/de/florianmichael/viafabricplus/protocolhack/provider/vialegacy/ViaFabricPlusEncryptionProvider.java @@ -22,16 +22,12 @@ import com.viaversion.viaversion.api.connection.UserConnection; import de.florianmichael.viafabricplus.injection.access.IClientConnection; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; -import net.minecraft.network.ClientConnection; import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.providers.EncryptionProvider; public class ViaFabricPlusEncryptionProvider extends EncryptionProvider { @Override public void enableDecryption(UserConnection user) { - final ClientConnection clientConnection = user.getChannel().attr(ProtocolHack.CLIENT_CONNECTION_ATTRIBUTE_KEY).get(); - if (clientConnection != null) { - ((IClientConnection) clientConnection).viaFabricPlus$setupPreNettyDecryption(); - } + ((IClientConnection) user.getChannel().attr(ProtocolHack.CLIENT_CONNECTION_ATTRIBUTE_KEY).get()).viaFabricPlus$setupPreNettyDecryption(); } } diff --git a/src/main/java/de/florianmichael/viafabricplus/protocolhack/provider/viaversion/ViaFabricPlusMovementTransmitterProvider.java b/src/main/java/de/florianmichael/viafabricplus/protocolhack/provider/viaversion/ViaFabricPlusAckSequenceProvider.java similarity index 80% rename from src/main/java/de/florianmichael/viafabricplus/protocolhack/provider/viaversion/ViaFabricPlusMovementTransmitterProvider.java rename to src/main/java/de/florianmichael/viafabricplus/protocolhack/provider/viaversion/ViaFabricPlusAckSequenceProvider.java index d1623f217..dfd03067e 100644 --- a/src/main/java/de/florianmichael/viafabricplus/protocolhack/provider/viaversion/ViaFabricPlusMovementTransmitterProvider.java +++ b/src/main/java/de/florianmichael/viafabricplus/protocolhack/provider/viaversion/ViaFabricPlusAckSequenceProvider.java @@ -20,11 +20,12 @@ package de.florianmichael.viafabricplus.protocolhack.provider.viaversion; import com.viaversion.viaversion.api.connection.UserConnection; -import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider; +import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.provider.AckSequenceProvider; -public class ViaFabricPlusMovementTransmitterProvider extends MovementTransmitterProvider { +public class ViaFabricPlusAckSequenceProvider extends AckSequenceProvider { @Override - public void sendPlayer(UserConnection userConnection) { + public void handleSequence(UserConnection connection, int sequence) { } + } diff --git a/src/main/java/de/florianmichael/viafabricplus/protocolhack/provider/viaversion/ViaFabricPlusHandItemProvider.java b/src/main/java/de/florianmichael/viafabricplus/protocolhack/provider/viaversion/ViaFabricPlusHandItemProvider.java index 75c6cee33..169deabc6 100644 --- a/src/main/java/de/florianmichael/viafabricplus/protocolhack/provider/viaversion/ViaFabricPlusHandItemProvider.java +++ b/src/main/java/de/florianmichael/viafabricplus/protocolhack/provider/viaversion/ViaFabricPlusHandItemProvider.java @@ -21,19 +21,21 @@ 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.util.ItemTranslator; +import de.florianmichael.viafabricplus.protocolhack.translator.ItemTranslator; import net.minecraft.item.ItemStack; +import net.raphimc.vialoader.util.VersionEnum; public class ViaFabricPlusHandItemProvider extends HandItemProvider { public static ItemStack lastUsedItem = null; @Override public Item getHandItem(UserConnection info) { - if (lastUsedItem == null) { + if (lastUsedItem == null || lastUsedItem.isEmpty()) { return null; } - return ItemTranslator.MC_TO_VIA_LATEST_TO_TARGET(lastUsedItem, VersionEnum.r1_8); + + return ItemTranslator.mcToVia(lastUsedItem, VersionEnum.r1_8); } + } diff --git a/src/main/java/de/florianmichael/viafabricplus/protocolhack/util/BlockStateTranslator.java b/src/main/java/de/florianmichael/viafabricplus/protocolhack/translator/BlockStateTranslator.java similarity index 52% rename from src/main/java/de/florianmichael/viafabricplus/protocolhack/util/BlockStateTranslator.java rename to src/main/java/de/florianmichael/viafabricplus/protocolhack/translator/BlockStateTranslator.java index 7aab409ec..df89531ec 100644 --- a/src/main/java/de/florianmichael/viafabricplus/protocolhack/util/BlockStateTranslator.java +++ b/src/main/java/de/florianmichael/viafabricplus/protocolhack/translator/BlockStateTranslator.java @@ -17,47 +17,44 @@ * along with this program. If not, see . */ -package de.florianmichael.viafabricplus.protocolhack.util; +package de.florianmichael.viafabricplus.protocolhack.translator; -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.minecraft.Position; 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.protocols.protocol1_18to1_17_1.ClientboundPackets1_18; import de.florianmichael.viafabricplus.ViaFabricPlus; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; -import io.netty.buffer.Unpooled; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.util.math.BlockPos; - -import java.util.List; -import java.util.stream.Collectors; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.raphimc.vialoader.util.VersionEnum; public class BlockStateTranslator { - private static final UserConnection DUMMY_USER_CONNECTION = ProtocolHack.createFakerUserConnection(null); - - public static int translateBlockState1_18(int oldId) { - final List protocolPath = Via.getManager().getProtocolManager().getProtocolPath(ProtocolHack.NATIVE_VERSION.getVersion(), ProtocolVersion.v1_18_2.getVersion()); - if (protocolPath == null) return oldId; - final PacketByteBuf inputData = new PacketByteBuf(Unpooled.buffer()); - inputData.writeBlockPos(new BlockPos(0, 0, 0)); - inputData.writeVarInt(oldId); + private static final UserConnection DUMMY_USER_CONNECTION = ProtocolHack.createDummyUserConnection(ProtocolHack.NATIVE_VERSION, VersionEnum.r1_18_2); + public static BlockState via1_18_2toMc(final int blockStateId) { try { - 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); - return wrapper.read(Type.VAR_INT); - } catch (Exception e) { - ViaFabricPlus.global().getLogger().error("Failed to translate block state " + oldId + " to 1.18.2", e); + var wrapper = PacketWrapper.create(ClientboundPackets1_18.EFFECT, null, DUMMY_USER_CONNECTION); + wrapper.write(Type.INT, 2001); // eventId + wrapper.write(Type.POSITION1_14, new Position(0, 0, 0)); // position + wrapper.write(Type.INT, blockStateId); // data + wrapper.write(Type.BOOLEAN, false); // global + + wrapper.resetReader(); + wrapper.user().getProtocolInfo().getPipeline().transform(Direction.CLIENTBOUND, State.PLAY, wrapper); + + wrapper.read(Type.INT); // eventId + wrapper.read(Type.POSITION1_14); // position + return Block.getStateFromRawId(wrapper.read(Type.INT)); // data + } catch (Throwable t) { + ViaFabricPlus.global().getLogger().error("Error converting ViaVersion 1.18.2 block state to native block state", t); + return Blocks.AIR.getDefaultState(); } - - return oldId; } + } diff --git a/src/main/java/de/florianmichael/viafabricplus/protocolhack/translator/ItemTranslator.java b/src/main/java/de/florianmichael/viafabricplus/protocolhack/translator/ItemTranslator.java new file mode 100644 index 000000000..59937ca5e --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/protocolhack/translator/ItemTranslator.java @@ -0,0 +1,100 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.protocolhack.translator; + +import com.viaversion.viaversion.api.connection.UserConnection; +import com.viaversion.viaversion.api.minecraft.item.Item; +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.type.Type; +import de.florianmichael.viafabricplus.ViaFabricPlus; +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import io.netty.buffer.Unpooled; +import net.minecraft.item.ItemStack; +import net.minecraft.network.NetworkSide; +import net.minecraft.network.NetworkState; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.packet.c2s.play.CreativeInventoryActionC2SPacket; +import net.minecraft.registry.Registries; +import net.raphimc.vialegacy.protocols.beta.protocol1_0_0_1tob1_8_0_1.ClientboundPacketsb1_8; +import net.raphimc.vialegacy.protocols.beta.protocol1_0_0_1tob1_8_0_1.types.Typesb1_8_0_1; +import net.raphimc.vialegacy.protocols.release.protocol1_4_4_5to1_4_2.types.Types1_4_2; +import net.raphimc.vialoader.util.VersionEnum; + +public class ItemTranslator { + + private static final UserConnection VIA_B1_8_TO_MC_USER_CONNECTION = ProtocolHack.createDummyUserConnection(ProtocolHack.NATIVE_VERSION, VersionEnum.b1_8tob1_8_1); + private static final int CREATIVE_INVENTORY_ACTION_ID = NetworkState.PLAY.getHandler(NetworkSide.SERVERBOUND).getId(new CreativeInventoryActionC2SPacket(0, ItemStack.EMPTY)); + + public static Item mcToVia(final ItemStack stack, final VersionEnum targetVersion) { + final UserConnection user = ProtocolHack.createDummyUserConnection(ProtocolHack.NATIVE_VERSION, targetVersion); + + try { + final PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer()); + buf.writeShort(0); // slot + buf.writeItemStack(stack); // item + + final var wrapper = PacketWrapper.create(CREATIVE_INVENTORY_ACTION_ID, null, user); + user.getProtocolInfo().getPipeline().transform(Direction.SERVERBOUND, State.PLAY, wrapper); + + wrapper.read(Type.SHORT); // slot + if (targetVersion.isOlderThanOrEqualTo(VersionEnum.b1_8tob1_8_1)) { + return wrapper.read(Typesb1_8_0_1.CREATIVE_ITEM); + } else if (targetVersion.isOlderThan(VersionEnum.r1_13)) { + return wrapper.read(Type.ITEM1_8); + } else if (targetVersion.isOlderThan(VersionEnum.r1_13_2)) { + return wrapper.read(Type.ITEM1_13); + } else if (targetVersion.isOlderThanOrEqualTo(VersionEnum.r1_20_2)) { + return wrapper.read(Type.ITEM1_13_2); + } else { + return wrapper.read(Type.ITEM1_20_2); + } + } catch (Throwable t) { + ViaFabricPlus.global().getLogger().error("Error converting native item stack to ViaVersion " + targetVersion + " item stack", t); + return null; + } + } + + public static ItemStack viaB1_8toMc(final Item item) { + try { + final var wrapper = PacketWrapper.create(ClientboundPacketsb1_8.SET_SLOT, VIA_B1_8_TO_MC_USER_CONNECTION); + wrapper.write(Type.BYTE, (byte) 0); // window id + wrapper.write(Type.SHORT, (short) 0); // slot + wrapper.write(Types1_4_2.NBTLESS_ITEM, item); // item + + wrapper.resetReader(); + wrapper.user().getProtocolInfo().getPipeline().transform(Direction.CLIENTBOUND, State.PLAY, wrapper); + + wrapper.read(Type.UNSIGNED_BYTE); // sync id + wrapper.read(Type.VAR_INT); // revision + wrapper.read(Type.SHORT); // slot + final var viaItem = wrapper.read(Type.ITEM1_13_2); // item + final ItemStack stack = new ItemStack(Registries.ITEM.get(viaItem.identifier())); + stack.setCount(viaItem.amount()); + stack.setDamage(viaItem.data()); + return stack; + } catch (Throwable t) { + ViaFabricPlus.global().getLogger().error("Error converting ViaVersion b1.8 item to native item stack", t); + return ItemStack.EMPTY; + } + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/protocolhack/translator/TextComponentTranslator.java b/src/main/java/de/florianmichael/viafabricplus/protocolhack/translator/TextComponentTranslator.java new file mode 100644 index 000000000..8521eb43b --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/protocolhack/translator/TextComponentTranslator.java @@ -0,0 +1,56 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.protocolhack.translator; + +import com.viaversion.viaversion.api.connection.UserConnection; +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.type.Type; +import com.viaversion.viaversion.libs.gson.JsonElement; +import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13; +import de.florianmichael.viafabricplus.ViaFabricPlus; +import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; +import net.raphimc.vialoader.util.VersionEnum; + +public class TextComponentTranslator { + + private static final UserConnection DUMMY_USER_CONNECTION = ProtocolHack.createDummyUserConnection(ProtocolHack.NATIVE_VERSION, VersionEnum.r1_13_2); + + public static JsonElement via1_13_2toViaLatest(final JsonElement component) { + try { + var wrapper = PacketWrapper.create(ClientboundPackets1_13.OPEN_WINDOW, DUMMY_USER_CONNECTION); + wrapper.write(Type.VAR_INT, 1); // window id + wrapper.write(Type.VAR_INT, 0); // type id + wrapper.write(Type.COMPONENT, component); // title + + wrapper.resetReader(); + wrapper.user().getProtocolInfo().getPipeline().transform(Direction.CLIENTBOUND, State.PLAY, wrapper); + + wrapper.read(Type.VAR_INT); // window id + wrapper.read(Type.VAR_INT); // type id + return wrapper.read(Type.COMPONENT); // title + } catch (Throwable t) { + ViaFabricPlus.global().getLogger().error("Error converting ViaVersion 1.13.2 text component to native text component", t); + return null; + } + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/protocolhack/util/ItemTranslator.java b/src/main/java/de/florianmichael/viafabricplus/protocolhack/util/ItemTranslator.java deleted file mode 100644 index 9966d2206..000000000 --- a/src/main/java/de/florianmichael/viafabricplus/protocolhack/util/ItemTranslator.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus - * Copyright (C) 2021-2023 FlorianMichael/EnZaXD - * Copyright (C) 2023 RK_01/RaphiMC 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 . - */ - -package de.florianmichael.viafabricplus.protocolhack.util; - -import com.viaversion.viaversion.api.Via; -import com.viaversion.viaversion.api.connection.UserConnection; -import com.viaversion.viaversion.api.minecraft.item.Item; -import com.viaversion.viaversion.api.protocol.ProtocolPathEntry; -import com.viaversion.viaversion.api.protocol.packet.Direction; -import com.viaversion.viaversion.api.protocol.packet.State; -import com.viaversion.viaversion.api.type.Type; -import com.viaversion.viaversion.protocol.packet.PacketWrapperImpl; -import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.InventoryTracker; -import de.florianmichael.viafabricplus.ViaFabricPlus; -import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; -import io.netty.buffer.Unpooled; -import net.minecraft.item.ItemStack; -import net.minecraft.network.NetworkSide; -import net.minecraft.network.NetworkState; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.c2s.play.CreativeInventoryActionC2SPacket; -import net.minecraft.registry.Registries; -import net.raphimc.vialegacy.protocols.beta.protocol1_0_0_1tob1_8_0_1.ClientboundPacketsb1_8; -import net.raphimc.vialegacy.protocols.beta.protocol1_0_0_1tob1_8_0_1.types.Typesb1_8_0_1; -import net.raphimc.vialegacy.protocols.release.protocol1_4_4_5to1_4_2.types.Types1_4_2; -import net.raphimc.vialegacy.protocols.release.protocol1_8to1_7_6_10.storage.WindowTracker; -import net.raphimc.vialoader.util.VersionEnum; - -import java.util.List; -import java.util.stream.Collectors; - -public class ItemTranslator { - private static final UserConnection DUMMY_USER_CONNECTION = ProtocolHack.createFakerUserConnection(null); - - public static Item MC_TO_VIA_LATEST_TO_TARGET(final ItemStack stack, final VersionEnum targetVersion) { - final List protocolPath = Via.getManager().getProtocolManager().getProtocolPath(ProtocolHack.NATIVE_VERSION.getVersion(), targetVersion.getVersion()); - if (protocolPath == null) return null; - - final var dummyPacket = new CreativeInventoryActionC2SPacket(36, stack); - final var emptyBuf = new PacketByteBuf(Unpooled.buffer()); - dummyPacket.write(emptyBuf); - - final int id = NetworkState.PLAY.getHandler(NetworkSide.SERVERBOUND).getId(dummyPacket); - - try { - final var 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); - - if (targetVersion.isOlderThanOrEqualTo(VersionEnum.b1_8tob1_8_1)) { - return wrapper.read(Typesb1_8_0_1.CREATIVE_ITEM); - } else if (targetVersion.isOlderThan(VersionEnum.r1_13)) { - return wrapper.read(Type.ITEM1_8); - } else if (targetVersion.isOlderThan(VersionEnum.r1_13_2)) { - return wrapper.read(Type.ITEM1_13); - } else if (targetVersion.isOlderThanOrEqualTo(VersionEnum.r1_20_2)) { - return wrapper.read(Type.ITEM1_13_2); - } else { - return wrapper.read(Type.ITEM1_20_2); - } - } catch (Exception e) { - ViaFabricPlus.global().getLogger().error("Failed to translate item", e); - } - return null; - } - - public static ItemStack VIA_TO_MC_B1_8_TO_LATEST(final Item item) { - final List protocolPath = Via.getManager().getProtocolManager().getProtocolPath(ProtocolHack.NATIVE_VERSION.getVersion(), VersionEnum.b1_8tob1_8_1.getVersion()); - if (protocolPath == null) return null; - - // Make sure that ViaVersion doesn't track stuff and change its behaviour - DUMMY_USER_CONNECTION.put(new WindowTracker()); - DUMMY_USER_CONNECTION.put(new InventoryTracker()); - - try { - final var wrapper = new PacketWrapperImpl(ClientboundPacketsb1_8.SET_SLOT.getId(), null, DUMMY_USER_CONNECTION); - wrapper.write(Type.BYTE, (byte) 0); // Window ID - wrapper.write(Type.SHORT, (short) 0); // Slot - wrapper.write(Types1_4_2.NBTLESS_ITEM, item); // Item - - wrapper.resetReader(); - - wrapper.apply(Direction.CLIENTBOUND, State.PLAY, 0, protocolPath.stream().map(ProtocolPathEntry::protocol).collect(Collectors.toList()), true); - - wrapper.read(Type.UNSIGNED_BYTE); - wrapper.read(Type.VAR_INT); - wrapper.read(Type.SHORT); - - final var viaItem = wrapper.read(Type.ITEM1_13_2); - return new ItemStack(() -> Registries.ITEM.get(viaItem.identifier()), viaItem.amount()); - } catch (Exception e) { - ViaFabricPlus.global().getLogger().error("Failed to translate item", e); - return null; - } - } -} diff --git a/src/main/java/de/florianmichael/viafabricplus/save/impl/AccountsSave.java b/src/main/java/de/florianmichael/viafabricplus/save/impl/AccountsSave.java index 92178f279..18af782ed 100644 --- a/src/main/java/de/florianmichael/viafabricplus/save/impl/AccountsSave.java +++ b/src/main/java/de/florianmichael/viafabricplus/save/impl/AccountsSave.java @@ -27,6 +27,8 @@ import de.florianmichael.viafabricplus.save.AbstractSave; import net.raphimc.minecraftauth.MinecraftAuth; import net.raphimc.minecraftauth.step.bedrock.session.StepFullBedrockSession; +import net.raphimc.minecraftauth.util.MicrosoftConstants; +import org.apache.http.impl.client.CloseableHttpClient; public class AccountsSave extends AbstractSave { @@ -70,6 +72,18 @@ public void read(JsonObject object) { } } + public StepFullBedrockSession.FullBedrockSession refreshAndGetBedrockAccount() { + if (bedrockAccount == null) return null; + + try (final CloseableHttpClient httpClient = MicrosoftConstants.createHttpClient()) { + bedrockAccount = MinecraftAuth.BEDROCK_DEVICE_CODE_LOGIN.refresh(httpClient, bedrockAccount); + } catch (Throwable t) { + throw new RuntimeException("Failed to refresh Bedrock chain data. Please re-login to Bedrock!", t); + } + + return bedrockAccount; + } + public StepFullBedrockSession.FullBedrockSession getBedrockAccount() { return bedrockAccount; } diff --git a/src/main/java/de/florianmichael/viafabricplus/save/impl/SettingsSave.java b/src/main/java/de/florianmichael/viafabricplus/save/impl/SettingsSave.java index 2122bb212..23083aa75 100644 --- a/src/main/java/de/florianmichael/viafabricplus/save/impl/SettingsSave.java +++ b/src/main/java/de/florianmichael/viafabricplus/save/impl/SettingsSave.java @@ -22,10 +22,10 @@ import com.google.gson.JsonObject; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; import de.florianmichael.viafabricplus.save.AbstractSave; +import de.florianmichael.viafabricplus.settings.SettingsManager; import de.florianmichael.viafabricplus.settings.base.AbstractSetting; import de.florianmichael.viafabricplus.settings.base.ButtonSetting; import de.florianmichael.viafabricplus.settings.base.SettingGroup; -import de.florianmichael.viafabricplus.settings.SettingsManager; import de.florianmichael.viafabricplus.settings.impl.GeneralSettings; import de.florianmichael.viafabricplus.util.ChatUtil; import net.raphimc.vialoader.util.VersionEnum; @@ -71,6 +71,8 @@ public void read(JsonObject object) { if (protocolVersion != VersionEnum.UNKNOWN) { ProtocolHack.setTargetVersion(protocolVersion); } + } else { + ProtocolHack.setTargetVersion(ProtocolHack.NATIVE_VERSION); } } } diff --git a/src/main/java/de/florianmichael/viafabricplus/screen/settings/ModeSettingRenderer.java b/src/main/java/de/florianmichael/viafabricplus/screen/settings/ModeSettingRenderer.java index 1d7fb5927..9a6520f15 100644 --- a/src/main/java/de/florianmichael/viafabricplus/screen/settings/ModeSettingRenderer.java +++ b/src/main/java/de/florianmichael/viafabricplus/screen/settings/ModeSettingRenderer.java @@ -43,7 +43,7 @@ public Text getNarration() { @Override public void mappedMouseClicked(double mouseX, double mouseY, int button) { - final int currentIndex = Arrays.stream(this.value.getOptions()).toList().indexOf(this.value.value) + 1; + final int currentIndex = Arrays.stream(this.value.getOptions()).toList().indexOf(this.value.getValue()) + 1; this.value.setValue(currentIndex > this.value.getOptions().length - 1 ? 0 : currentIndex); } diff --git a/src/main/java/de/florianmichael/viafabricplus/settings/base/AbstractSetting.java b/src/main/java/de/florianmichael/viafabricplus/settings/base/AbstractSetting.java index 5e61a3b45..b8b7b006f 100644 --- a/src/main/java/de/florianmichael/viafabricplus/settings/base/AbstractSetting.java +++ b/src/main/java/de/florianmichael/viafabricplus/settings/base/AbstractSetting.java @@ -23,7 +23,6 @@ import de.florianmichael.viafabricplus.screen.base.VFPListEntry; import de.florianmichael.viafabricplus.util.ChatUtil; import net.minecraft.text.MutableText; -import net.minecraft.text.TranslatableTextContent; /** * This class is the base for all settings. It contains the name, the default value and the current value. @@ -35,7 +34,7 @@ public abstract class AbstractSetting { private final MutableText name; private final T defaultValue; - public T value; + private T value; public AbstractSetting(final SettingGroup parent, final MutableText name, final T defaultValue) { this.name = name; diff --git a/src/main/java/de/florianmichael/viafabricplus/settings/impl/DebugSettings.java b/src/main/java/de/florianmichael/viafabricplus/settings/impl/DebugSettings.java index 324a76115..05a735bba 100644 --- a/src/main/java/de/florianmichael/viafabricplus/settings/impl/DebugSettings.java +++ b/src/main/java/de/florianmichael/viafabricplus/settings/impl/DebugSettings.java @@ -19,24 +19,18 @@ package de.florianmichael.viafabricplus.settings.impl; -import net.raphimc.vialoader.util.VersionEnum; import de.florianmichael.viafabricplus.settings.base.SettingGroup; import de.florianmichael.viafabricplus.settings.base.VersionedBooleanSetting; import net.minecraft.text.Text; +import net.raphimc.vialoader.util.VersionEnum; import net.raphimc.vialoader.util.VersionRange; public class DebugSettings extends SettingGroup { private static final DebugSettings instance = new DebugSettings(); - // 1.19.1/2 -> 1.19 - public final VersionedBooleanSetting alwaysTickOnlyPlayer = new VersionedBooleanSetting(this, Text.translatable("debug_settings.viafabricplus.always_tick_only_player"), VersionRange.andOlder(VersionEnum.r1_19_1tor1_19_2)); - // 1.19 -> 1.18.2 public final VersionedBooleanSetting disableSequencing = new VersionedBooleanSetting(this, Text.translatable("debug_settings.viafabricplus.disable_sequencing"), VersionRange.andOlder(VersionEnum.r1_18_2)); - // 1.14 -> 1.13.2 - public final VersionedBooleanSetting smoothOutMerchantScreens = new VersionedBooleanSetting(this, Text.translatable("debug_settings.viafabricplus.smooth_out_merchant_screens"), VersionRange.andOlder(VersionEnum.r1_13_2)); - // 1.13 -> 1.12.2 public final VersionedBooleanSetting executeInputsInSync = new VersionedBooleanSetting(this, Text.translatable("debug_settings.viafabricplus.execute_inputs_in_sync"), VersionRange.andOlder(VersionEnum.r1_12_2)); public final VersionedBooleanSetting sneakInstant = new VersionedBooleanSetting(this, Text.translatable("debug_settings.viafabricplus.sneak_instant"), VersionRange.of(VersionEnum.r1_8, VersionEnum.r1_12_2)); @@ -49,6 +43,7 @@ public class DebugSettings extends SettingGroup { public final VersionedBooleanSetting removeCooldowns = new VersionedBooleanSetting(this, Text.translatable("debug_settings.viafabricplus.remove_cooldowns"), VersionRange.andOlder(VersionEnum.r1_8)); public final VersionedBooleanSetting sendIdlePacket = new VersionedBooleanSetting(this, Text.translatable("debug_settings.viafabricplus.send_idle_packet"), VersionRange.of(VersionEnum.r1_4_2, VersionEnum.r1_8).add(VersionRange.andOlder(VersionEnum.r1_2_4tor1_2_5))); public final VersionedBooleanSetting replaceAttributeModifiers = new VersionedBooleanSetting(this, Text.translatable("debug_settings.viafabricplus.replace_attribute_modifiers"), VersionRange.andOlder(VersionEnum.r1_8)); + public final VersionedBooleanSetting preventEntityCramming = new VersionedBooleanSetting(this, Text.translatable("debug_settings.viafabricplus.prevent_entity_cramming"), VersionRange.andOlder(VersionEnum.r1_8)); // 1.8.x -> 1.7.6 public final VersionedBooleanSetting replaceSneaking = new VersionedBooleanSetting(this, Text.translatable("debug_settings.viafabricplus.replace_sneaking"), VersionRange.andOlder(VersionEnum.r1_7_6tor1_7_10)); diff --git a/src/main/java/de/florianmichael/viafabricplus/util/MouseSensitivityUtil.java b/src/main/java/de/florianmichael/viafabricplus/util/MouseSensitivityUtil.java new file mode 100644 index 000000000..92f1a455b --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/util/MouseSensitivityUtil.java @@ -0,0 +1,34 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2023 FlorianMichael/EnZaXD + * Copyright (C) 2023 RK_01/RaphiMC 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 . + */ + +package de.florianmichael.viafabricplus.util; + +import it.unimi.dsi.fastutil.floats.FloatIntPair; + +public class MouseSensitivityUtil { + + public static FloatIntPair get1_13SliderValue(final float value1_14) { + final int oldSliderWidth = 150 - 8; + final int mousePos = (int) (oldSliderWidth * value1_14); + final float oldValue = mousePos / (float) oldSliderWidth; + final int oldDisplay = (int) (oldValue * 200); + return FloatIntPair.of(oldValue, oldDisplay); + } + +} diff --git a/src/main/resources/assets/viafabricplus/lang/de_de.json b/src/main/resources/assets/viafabricplus/lang/de_de.json index faf05362f..e120a0c1f 100644 --- a/src/main/resources/assets/viafabricplus/lang/de_de.json +++ b/src/main/resources/assets/viafabricplus/lang/de_de.json @@ -8,6 +8,7 @@ "base.viafabricplus.right_bottom": "Rechts, Unten", "base.viafabricplus.cancel": "Abbrechen", "base.viafabricplus.cancel_and_reset": "Abbrechen und zurücksetzen", + "base.viafabricplus.detecting_server_version": "Erkenne Server version...", "general_settings.viafabricplus.super_secret_settings": "Super Secret Settings", "general_settings.viafabricplus.extra_information_in_debug_hud": "Zusätzliche Informationen im Debug-HUD anzeigen", diff --git a/src/main/resources/assets/viafabricplus/lang/en_us.json b/src/main/resources/assets/viafabricplus/lang/en_us.json index 40be1e5b6..5daa905d9 100644 --- a/src/main/resources/assets/viafabricplus/lang/en_us.json +++ b/src/main/resources/assets/viafabricplus/lang/en_us.json @@ -24,6 +24,7 @@ "base.viafabricplus.kick": "Kick", "base.viafabricplus.cancel_and_notify": "Cancel and notify", "base.viafabricplus.force_version_title": "Please select the version with which the server should be pinged/connected", + "base.viafabricplus.detecting_server_version": "Detecting server version...", "setting_group_name.viafabricplus.authentication": "Authentication", "setting_group_name.viafabricplus.visual": "Visual", @@ -56,7 +57,7 @@ "debug_settings.viafabricplus.long_sneaking": "Long sneaking", "debug_settings.viafabricplus.legacy_mining_speeds": "Legacy mining speeds", "debug_settings.viafabricplus.skip_containers_with_custom_display_names": "Skip containers with custom display names", - "debug_settings.viafabricplus.always_tick_only_player": "Always tick only player", + "debug_settings.viafabricplus.prevent_entity_cramming": "Prevent entity cramming", "authentication_settings.viafabricplus.use_beta_craft_authentication": "Use BetaCraft authentication", "authentication_settings.viafabricplus.verify_session_for_online_mode": "Verify session for online mode servers", diff --git a/src/main/resources/viafabricplus.accesswidener b/src/main/resources/viafabricplus.accesswidener index 1ed4810c8..a47ca1875 100644 --- a/src/main/resources/viafabricplus.accesswidener +++ b/src/main/resources/viafabricplus.accesswidener @@ -1,27 +1,30 @@ accessWidener v1 named -accessible field net/minecraft/client/network/AllowedAddressResolver redirectResolver Lnet/minecraft/client/network/RedirectResolver; accessible field net/minecraft/item/Item ATTACK_DAMAGE_MODIFIER_ID Ljava/util/UUID; accessible field net/minecraft/client/gui/screen/ConnectScreen connection Lnet/minecraft/network/ClientConnection; accessible field net/minecraft/network/ClientConnection channel Lio/netty/channel/Channel; -accessible field net/minecraft/client/network/ServerAddress INVALID Lnet/minecraft/client/network/ServerAddress; -accessible field net/minecraft/client/network/ServerAddress hostAndPort Lcom/google/common/net/HostAndPort; accessible field net/minecraft/client/MinecraftClient fontManager Lnet/minecraft/client/font/FontManager; +accessible field net/minecraft/client/network/AllowedAddressResolver redirectResolver Lnet/minecraft/client/network/RedirectResolver; accessible field net/minecraft/client/font/FontManager fontStorages Ljava/util/Map; accessible field net/minecraft/client/gui/screen/GameMenuScreen exitButton Lnet/minecraft/client/gui/widget/ButtonWidget; accessible field net/minecraft/client/font/FontStorage$GlyphPair MISSING Lnet/minecraft/client/font/FontStorage$GlyphPair; -accessible field net/minecraft/client/network/AllowedAddressResolver addressResolver Lnet/minecraft/client/network/AddressResolver; accessible field net/minecraft/network/ClientConnection packetSizeLogger Lnet/minecraft/network/handler/PacketSizeLogger; accessible field net/minecraft/entity/boss/dragon/EnderDragonEntity body Lnet/minecraft/entity/boss/dragon/EnderDragonPart; accessible field net/minecraft/entity/passive/AbstractHorseEntity lastAngryAnimationProgress F accessible field net/minecraft/entity/vehicle/BoatEntity yawVelocity F accessible field net/minecraft/client/font/FontStorage glyphRendererCache Lnet/minecraft/client/font/GlyphContainer; accessible field net/minecraft/client/font/FontStorage glyphCache Lnet/minecraft/client/font/GlyphContainer; +accessible field net/minecraft/entity/EntityType dimensions Lnet/minecraft/entity/EntityDimensions; +mutable field net/minecraft/entity/EntityType dimensions Lnet/minecraft/entity/EntityDimensions; +accessible field net/minecraft/block/AbstractBlock velocityMultiplier F +mutable field net/minecraft/block/AbstractBlock velocityMultiplier F accessible method net/minecraft/screen/GenericContainerScreenHandler (Lnet/minecraft/screen/ScreenHandlerType;ILnet/minecraft/entity/player/PlayerInventory;I)V accessible method net/minecraft/client/font/FontStorage$GlyphPair (Lnet/minecraft/client/font/Glyph;Lnet/minecraft/client/font/Glyph;)V accessible method net/minecraft/entity/passive/CamelEntity getPassengerAttachmentY (ZFLnet/minecraft/entity/EntityDimensions;F)D accessible method net/minecraft/entity/vehicle/BoatEntity getMaxPassengers ()I +accessible method net/minecraft/client/gui/screen/ConnectScreen setStatus (Lnet/minecraft/text/Text;)V +accessible method net/minecraft/item/BlockItem getPlacementState (Lnet/minecraft/item/ItemPlacementContext;)Lnet/minecraft/block/BlockState; accessible class net/minecraft/client/gui/screen/GameModeSelectionScreen$GameModeSelection accessible class net/minecraft/client/font/FontStorage$GlyphPair diff --git a/src/main/resources/viafabricplus.mixins.json b/src/main/resources/viafabricplus.mixins.json index 6396937f2..53e175c96 100644 --- a/src/main/resources/viafabricplus.mixins.json +++ b/src/main/resources/viafabricplus.mixins.json @@ -10,12 +10,15 @@ "base.connect.MixinClientConnection_1", "base.connect.MixinClientLoginNetworkHandler", "base.integration.MixinAddServerScreen", + "base.integration.MixinChunkTracker", + "base.integration.MixinConnectScreen_1", "base.integration.MixinDebugHud", "base.integration.MixinDownloadingTerrainScreen", "base.integration.MixinMinecraftClient", "base.integration.MixinMultiplayerScreen", "base.integration.MixinMultiplayerServerListPinger_1", "base.integration.MixinMultiplayerServerListWidget_ServerEntry", + "base.integration.MixinRakSessionCodec", "base.perserverversion.MixinConnectScreen_1", "base.perserverversion.MixinMultiplayerServerListPinger", "base.perserverversion.MixinPerformanceLog", @@ -27,15 +30,27 @@ "compat.jsonwebtoken.MixinDefaultJwtParserBuilder", "fixes.authlib.MixinKeyPairResponse", "fixes.authlib.MixinYggdrasilUserApiService", + "fixes.minecraft.MixinAllowedAddressResolver", + "fixes.minecraft.MixinBuiltChunk", "fixes.minecraft.MixinCamera", - "fixes.minecraft.MixinClientPlayerInteractionManager", + "fixes.minecraft.MixinChatInputSuggestor", + "fixes.minecraft.MixinClientCommandSource", + "fixes.minecraft.MixinClientWorld", + "fixes.minecraft.MixinEnchantmentHelper", + "fixes.minecraft.MixinFlowableFluid", "fixes.minecraft.MixinFontStorage", + "fixes.minecraft.MixinGameOptions", + "fixes.minecraft.MixinGameRenderer", + "fixes.minecraft.MixinKeyboard", "fixes.minecraft.MixinKeyboardInput", "fixes.minecraft.MixinMinecraftClient", - "fixes.minecraft.MixinPendingUpdateManager", + "fixes.minecraft.MixinMouse", + "fixes.minecraft.MixinPlayerInventory", "fixes.minecraft.MixinPlayerListEntry", "fixes.minecraft.MixinPlayerPublicKey_PublicKeyData", "fixes.minecraft.MixinProfileKeysImpl", + "fixes.minecraft.MixinRedirectResolver", + "fixes.minecraft.MixinServerAddress", "fixes.minecraft.MixinServerResourcePackProvider", "fixes.minecraft.MixinStringHelper", "fixes.minecraft.MixinTextRenderer", @@ -73,6 +88,7 @@ "fixes.minecraft.entity.MixinAbstractClientPlayerEntity", "fixes.minecraft.entity.MixinAnimalEntity", "fixes.minecraft.entity.MixinBipedEntityModel", + "fixes.minecraft.entity.MixinBoatEntity", "fixes.minecraft.entity.MixinCamelEntity", "fixes.minecraft.entity.MixinClientPlayerEntity", "fixes.minecraft.entity.MixinCowEntity", @@ -87,10 +103,13 @@ "fixes.minecraft.entity.MixinOtherClientPlayerEntity", "fixes.minecraft.entity.MixinPlayerEntity", "fixes.minecraft.entity.MixinPlayerEntityRenderer", + "fixes.minecraft.entity.MixinSkeletonHorseEntity", "fixes.minecraft.entity.MixinSquidEntity", "fixes.minecraft.entity.MixinWolfEntity", + "fixes.minecraft.item.MixinArmorItem", "fixes.minecraft.item.MixinAxeItem", "fixes.minecraft.item.MixinBlockItem", + "fixes.minecraft.item.MixinBowItem", "fixes.minecraft.item.MixinDrawContext", "fixes.minecraft.item.MixinEnderPearlItem", "fixes.minecraft.item.MixinEquipment", @@ -105,15 +124,22 @@ "fixes.minecraft.item.MixinItemRenderer", "fixes.minecraft.item.MixinItemStack", "fixes.minecraft.item.MixinPickaxeItem", + "fixes.minecraft.item.MixinShearsItem", "fixes.minecraft.item.MixinShovelItem", "fixes.minecraft.item.MixinSwordItem", "fixes.minecraft.network.MixinChatMessageC2SPacket", "fixes.minecraft.network.MixinClientCommonNetworkHandler", + "fixes.minecraft.network.MixinClientConfigurationNetworkHandler", + "fixes.minecraft.network.MixinClientLoginNetworkHandler", + "fixes.minecraft.network.MixinClientPlayerInteractionManager", "fixes.minecraft.network.MixinClientPlayNetworkHandler", + "fixes.minecraft.network.MixinCustomPayloadS2CPacket", + "fixes.minecraft.network.MixinMultiplayerServerListPinger", "fixes.minecraft.network.MixinPacketByteBuf", "fixes.minecraft.network.MixinUpdatePlayerAbilitiesC2SPacket", + "fixes.minecraft.screen.MixinAbstractCommandBlockScreen", "fixes.minecraft.screen.MixinAbstractSignEditScreen", - "fixes.minecraft.screen.MixinAnvilScreen", + "fixes.minecraft.screen.MixinBookEditScreen", "fixes.minecraft.screen.MixinChatScreen", "fixes.minecraft.screen.MixinCommandBlockScreen", "fixes.minecraft.screen.MixinConnectScreen_1", @@ -121,21 +147,19 @@ "fixes.minecraft.screen.MixinDownloadingTerrainScreen", "fixes.minecraft.screen.MixinGameModeSelectionScreen", "fixes.minecraft.screen.MixinGameModeSelectionScreen_GameModeSelection", - "fixes.minecraft.screen.MixinHandledScreens", "fixes.minecraft.screen.MixinJigsawBlockScreen", + "fixes.minecraft.screen.MixinMouseOptionsScreen", "fixes.minecraft.screen.MixinOptionsScreen", "fixes.minecraft.screen.MixinScreen", "fixes.minecraft.screen.MixinStructureBlockScreen_1", "fixes.minecraft.screen.hud.MixinChatHud", "fixes.minecraft.screen.hud.MixinInGameHud", - "fixes.minecraft.screen.merchant.MixinMerchantScreen", - "fixes.minecraft.screen.merchant.MixinMerchantScreenHandler", + "fixes.minecraft.screen.screenhandler.MixinAbstractFurnaceScreenHandler", "fixes.minecraft.screen.screenhandler.MixinBrewingStandScreenHandler_FuelSlot", "fixes.minecraft.screen.screenhandler.MixinCraftingScreenHandler", + "fixes.minecraft.screen.screenhandler.MixinMerchantScreenHandler", "fixes.minecraft.screen.screenhandler.MixinPlayerScreenHandler", "fixes.minecraft.screen.screenhandler.MixinScreenHandler", - "viabedrock.MixinBedrockProtocol", - "viabedrock.MixinJoinPackets", "fixes.vialegacy.MixinClassicProtocolExtension", "fixes.vialegacy.MixinClientboundPacketsc0_30cpe", "fixes.vialegacy.MixinExtensionProtocolMetadataStorage", @@ -147,33 +171,32 @@ "fixes.viaversion.MixinCommonBoss", "fixes.viaversion.MixinEntityIdRewriter", "fixes.viaversion.MixinEntityPackets1_17", + "fixes.viaversion.MixinEntityPackets1_19_4", "fixes.viaversion.MixinEntityPackets_6_1", "fixes.viaversion.MixinEntityTracker1_9", "fixes.viaversion.MixinInventoryAcknowledgements", "fixes.viaversion.MixinInventoryPackets", + "fixes.viaversion.MixinInventoryPackets1_13", + "fixes.viaversion.MixinInventoryPackets1_17", + "fixes.viaversion.MixinInventoryTracker1_16", "fixes.viaversion.MixinMetadataRewriter1_15To1_14_4", "fixes.viaversion.MixinMetadataRewriter1_9To1_8", "fixes.viaversion.MixinNamedCompoundTagType", "fixes.viaversion.MixinProtocol1_11To1_10", - "fixes.viaversion.MixinSkullHandler", + "fixes.viaversion.MixinProtocol1_12To1_11_1", + "fixes.viaversion.MixinTagType", "fixes.viaversion.MixinWorldPackets1_13", "fixes.viaversion.MixinWorldPackets1_16_2", "fixes.viaversion.MixinWorldPackets1_17", "fixes.viaversion.MixinWorldPackets1_19", + "viabedrock.MixinBedrockProtocol", + "viabedrock.MixinBlobCache", + "viabedrock.MixinJoinPackets", "viaversion.MixinAbstractFenceConnectionHandler", "viaversion.MixinGlassConnectionHandler", "viaversion.MixinProtocolVersion" ], "injectors": { "defaultRequire": 1 - }, - "mixins": [ - "base.integration.MixinConnectScreen_1", - "fixes.minecraft.entity.MixinBoatEntity", - "fixes.minecraft.entity.MixinSkeletonHorseEntity", - "fixes.minecraft.item.MixinArmorItem", - "fixes.minecraft.item.MixinBowItem", - "fixes.minecraft.item.MixinShearsItem", - "viabedrock.MixinBlobCache" - ] + } }