170 lines
8.3 KiB
Java
170 lines
8.3 KiB
Java
/*
|
|
* 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.injection.mixin.fixes.minecraft;
|
|
|
|
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
|
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_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.fixes.data.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.Mouse;
|
|
import net.minecraft.client.network.ClientPlayerEntity;
|
|
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.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.Queue;
|
|
|
|
@Mixin(MinecraftClient.class)
|
|
public abstract class MixinMinecraftClient {
|
|
|
|
@Shadow
|
|
@Nullable
|
|
public ClientPlayerEntity player;
|
|
|
|
@Shadow
|
|
public int attackCooldown;
|
|
|
|
@Shadow
|
|
@Final
|
|
public Mouse mouse;
|
|
|
|
@Shadow
|
|
@Final
|
|
public Keyboard keyboard;
|
|
|
|
@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);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Never happens in Vanilla, this is only for {@link ItemRegistryDiff} to work
|
|
*/
|
|
@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);
|
|
}
|
|
}
|
|
|
|
@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);
|
|
}
|
|
|
|
@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);
|
|
}
|
|
|
|
@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<Runnable> inputEvents = ((IMouseKeyboard) this.mouse).viaFabricPlus$getPendingScreenEvents();
|
|
while (!inputEvents.isEmpty()) inputEvents.poll().run();
|
|
|
|
inputEvents = ((IMouseKeyboard) this.keyboard).viaFabricPlus$getPendingScreenEvents();
|
|
while (!inputEvents.isEmpty()) inputEvents.poll().run();
|
|
}
|
|
}
|
|
|
|
@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<Boolean> cir) {
|
|
if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) {
|
|
this.player.swingHand(Hand.MAIN_HAND);
|
|
}
|
|
}
|
|
|
|
@WrapWithCondition(method = "doAttack", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;swingHand(Lnet/minecraft/util/Hand;)V"))
|
|
private boolean fixSwingPacketOrder(ClientPlayerEntity instance, Hand hand) {
|
|
return ProtocolHack.getTargetVersion().isNewerThan(VersionEnum.r1_8);
|
|
}
|
|
|
|
@Redirect(method = "tick", at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;attackCooldown:I", ordinal = 1))
|
|
private int dontIncrementCooldown(MinecraftClient instance) {
|
|
if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) {
|
|
return 0;
|
|
}
|
|
return attackCooldown;
|
|
}
|
|
|
|
@Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;handleInputEvents()V", shift = At.Shift.BEFORE))
|
|
private void postIncrementCooldown(CallbackInfo ci) {
|
|
if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) {
|
|
if (this.attackCooldown > 0) {
|
|
--this.attackCooldown;
|
|
}
|
|
}
|
|
}
|
|
|
|
@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)) {
|
|
return false;
|
|
}
|
|
return original;
|
|
}
|
|
|
|
}
|