Fix block/entity picking not working in <= 1.21.3

This commit is contained in:
FlorianMichael 2024-12-06 23:10:16 +01:00
parent 54351ef1f2
commit 44adf30ed2
No known key found for this signature in database
GPG Key ID: C2FB87E71C425126
4 changed files with 138 additions and 1 deletions

View File

@ -0,0 +1,117 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> and RK_01/RaphiMC
* Copyright (C) 2023-2024 contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.versioned;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.Protocol1_21_2To1_21_4;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ServerboundPackets1_21_2;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
public class ItemPick1_21_3 {
private static void addPickBlock(final PlayerInventory inventory, final ItemStack stack) {
final int index = inventory.getSlotWithStack(stack);
if (PlayerInventory.isValidHotbarIndex(index)) {
inventory.selectedSlot = index;
} else if (index != -1) {
inventory.swapSlotWithHotbar(index);
} else {
inventory.swapStackWithHotbar(stack);
}
}
private static void addBlockEntityNbt(final ItemStack stack, final BlockEntity blockEntity, final DynamicRegistryManager manager) {
final NbtCompound nbtCompound = blockEntity.createComponentlessNbtWithIdentifyingData(manager);
blockEntity.removeFromCopiedStackNbt(nbtCompound);
BlockItem.setBlockEntityData(stack, blockEntity.getType(), nbtCompound);
stack.applyComponentsFrom(blockEntity.createComponentMap());
}
public static void doItemPick(final MinecraftClient client) {
final boolean creativeMode = client.player.getAbilities().creativeMode;
ItemStack itemStack = null;
final HitResult crosshairTarget = client.crosshairTarget;
if (crosshairTarget.getType() == HitResult.Type.BLOCK) {
final BlockPos blockPos = ((BlockHitResult) crosshairTarget).getBlockPos();
final BlockState blockState = client.world.getBlockState(blockPos);
if (blockState.isAir()) {
return;
}
final Block block = blockState.getBlock();
itemStack = block.getPickStack(client.world, blockPos, blockState, false);
if (itemStack.isEmpty()) {
return;
}
if (creativeMode && Screen.hasControlDown() && blockState.hasBlockEntity()) {
final BlockEntity blockEntity = client.world.getBlockEntity(blockPos);
if (blockEntity != null) {
addBlockEntityNbt(itemStack, blockEntity, client.world.getRegistryManager());
}
}
} else if (crosshairTarget.getType() == HitResult.Type.ENTITY && creativeMode) {
final Entity entity = ((EntityHitResult) crosshairTarget).getEntity();
itemStack = entity.getPickBlockStack();
if (itemStack == null) {
return;
}
}
if (itemStack.isEmpty()) {
return;
}
final PlayerInventory inventory = client.player.getInventory();
final int index = inventory.getSlotWithStack(itemStack);
if (creativeMode) {
addPickBlock(inventory, itemStack);
client.interactionManager.clickCreativeStack(client.player.getStackInHand(Hand.MAIN_HAND), 36 + inventory.selectedSlot);
} else if (index == -1) {
return;
}
if (PlayerInventory.isValidHotbarIndex(index)) {
inventory.selectedSlot = index;
return;
}
final PacketWrapper pickFromInventory = PacketWrapper.create(ServerboundPackets1_21_2.PICK_ITEM, ProtocolTranslator.getPlayNetworkUserConnection());
pickFromInventory.write(Types.VAR_INT, index);
pickFromInventory.sendToServer(Protocol1_21_2To1_21_4.class);
}
}

View File

@ -26,6 +26,7 @@ import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_11_1to1_12.Protocol1_11_1To1_12;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ServerboundPackets1_9_3;
import de.florianmichael.viafabricplus.fixes.versioned.ItemPick1_21_3;
import de.florianmichael.viafabricplus.injection.access.IMouseKeyboard;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import de.florianmichael.viafabricplus.settings.impl.DebugSettings;
@ -66,6 +67,14 @@ public abstract class MixinMinecraftClient {
@Final
public Keyboard keyboard;
@Inject(method = "doItemPick", at = @At("HEAD"), cancellable = true)
public void pickItemClientside(CallbackInfo ci) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_21_2)) {
ItemPick1_21_3.doItemPick((MinecraftClient) (Object) this);
ci.cancel();
}
}
@WrapWithCondition(method = "handleInputEvents", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;swingHand(Lnet/minecraft/util/Hand;)V"))
private boolean disableSwing(ClientPlayerEntity instance, Hand hand) {
return ProtocolTranslator.getTargetVersion().newerThanOrEqualTo(ProtocolVersion.v1_15);

View File

@ -26,6 +26,7 @@ import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_16_1to1_16_2.packet.ServerboundPackets1_16_2;
import com.viaversion.viaversion.protocols.v1_16_4to1_17.Protocol1_16_4To1_17;
import de.florianmichael.viafabricplus.ViaFabricPlus;
import de.florianmichael.viafabricplus.fixes.versioned.ActionResultException1_12_2;
import de.florianmichael.viafabricplus.fixes.versioned.ClientPlayerInteractionManager1_18_2;
import de.florianmichael.viafabricplus.injection.access.IClientConnection;
@ -111,6 +112,14 @@ public abstract class MixinClientPlayerInteractionManager implements IClientPlay
@Unique
private final ClientPlayerInteractionManager1_18_2 viaFabricPlus$1_18_2InteractionManager = new ClientPlayerInteractionManager1_18_2();
@Inject(method = {"pickItemFromBlock", "pickItemFromEntity"}, at = @At("HEAD"), cancellable = true)
public void pickItemClientside(CallbackInfo ci) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_21_2)) {
ViaFabricPlus.global().getLogger().error("Directly calling pickItemFromBlock or pickItemFromEntity is not supported in <=1.21.3. Use MinecraftClient#doItemPick instead.");
ci.cancel();
}
}
@Redirect(method = "interactBlockInternal", at = @At(value = "FIELD", target = "Lnet/minecraft/util/ActionResult;CONSUME:Lnet/minecraft/util/ActionResult$Success;"))
private ActionResult.Success changeSpectatorAction() {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_21)) {
@ -351,7 +360,8 @@ public abstract class MixinClientPlayerInteractionManager implements IClientPlay
if (type == SlotActionType.THROW) return true;
// quick move always uses empty stack for verification since 1.12
if (type == SlotActionType.QUICK_MOVE && ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_11_1)) return true;
if (type == SlotActionType.QUICK_MOVE && ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_11_1))
return true;
// pickup with slot -999 (outside window) to throw items always uses empty stack for verification
return type == SlotActionType.PICKUP && slot == -999;

View File

@ -26,6 +26,7 @@ accessible method net/minecraft/entity/passive/CamelEntity getPassengerAttachmen
accessible method net/minecraft/entity/vehicle/AbstractBoatEntity getMaxPassengers ()I
accessible method net/minecraft/client/gui/screen/multiplayer/ConnectScreen setStatus (Lnet/minecraft/text/Text;)V
accessible method net/minecraft/item/BlockItem getPlacementState (Lnet/minecraft/item/ItemPlacementContext;)Lnet/minecraft/block/BlockState;
accessible method net/minecraft/block/AbstractBlock getPickStack (Lnet/minecraft/world/WorldView;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Z)Lnet/minecraft/item/ItemStack;
accessible class net/minecraft/client/gui/screen/GameModeSelectionScreen$GameModeSelection
accessible class net/minecraft/client/font/FontStorage$GlyphPair