mirror of
https://github.com/TeamMidnightDust/MidnightControls.git
synced 2025-12-14 15:45:09 +01:00
MidnightControls 0.1.0 (Beta)
Changes from LambdaControls: - Support for Steam Deck and Dualsense - Support for L4, L5, R4, R5 buttons - Updated Libraries - New Logo and Name - Lots of Bugfixes - MidnightConfig backend
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import net.minecraft.advancement.Advancement;
|
||||
import net.minecraft.client.gui.screen.advancement.AdvancementTab;
|
||||
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
|
||||
import net.minecraft.client.network.ClientAdvancementManager;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents an accessor of {@link AdvancementsScreen}.
|
||||
*/
|
||||
@Mixin(AdvancementsScreen.class)
|
||||
public interface AdvancementsScreenAccessor {
|
||||
@Accessor("advancementHandler")
|
||||
ClientAdvancementManager getAdvancementManager();
|
||||
|
||||
@Accessor("tabs")
|
||||
Map<Advancement, AdvancementTab> getTabs();
|
||||
|
||||
@Accessor("selectedTab")
|
||||
AdvancementTab getSelectedTab();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import net.minecraft.client.gui.widget.ClickableWidget;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(ClickableWidget.class)
|
||||
public interface ClickableWidgetAccessor {
|
||||
@Accessor("height")
|
||||
int getHeight();
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.MovementHandler;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.input.Input;
|
||||
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
||||
import net.minecraft.client.network.ClientPlayerEntity;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.entity.MovementType;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
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.CallbackInfo;
|
||||
|
||||
/**
|
||||
* Injects the anti fly drifting feature.
|
||||
*/
|
||||
@Mixin(ClientPlayerEntity.class)
|
||||
public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity {
|
||||
private boolean midnightcontrols$driftingPrevented = false;
|
||||
|
||||
@Shadow
|
||||
protected abstract boolean hasMovementInput();
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
protected MinecraftClient client;
|
||||
|
||||
@Shadow
|
||||
public Input input;
|
||||
|
||||
@Shadow
|
||||
protected abstract boolean isCamera();
|
||||
|
||||
public ClientPlayerEntityMixin(ClientWorld world, GameProfile profile) {
|
||||
super(world, profile);
|
||||
}
|
||||
|
||||
@Inject(method = "move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/AbstractClientPlayerEntity;move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V"))
|
||||
public void onMove(MovementType type, Vec3d movement, CallbackInfo ci) {
|
||||
var mod = MidnightControlsClient.get();
|
||||
if (type == MovementType.SELF) {
|
||||
if (this.getAbilities().flying && (!MidnightControlsConfig.flyDrifting || !MidnightControlsConfig.verticalFlyDrifting)) {
|
||||
if (!this.hasMovementInput()) {
|
||||
if (!this.midnightcontrols$driftingPrevented) {
|
||||
if (!MidnightControlsConfig.flyDrifting)
|
||||
this.setVelocity(this.getVelocity().multiply(0, 1.0, 0));
|
||||
}
|
||||
this.midnightcontrols$driftingPrevented = true;
|
||||
} else
|
||||
this.midnightcontrols$driftingPrevented = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/input/Input;tick(Z)V", shift = At.Shift.AFTER))
|
||||
public void onInputUpdate(CallbackInfo ci) {
|
||||
MovementHandler.HANDLER.applyMovement((ClientPlayerEntity) (Object) this);
|
||||
}
|
||||
|
||||
@Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isCamera()Z"))
|
||||
public void onTickMovement(CallbackInfo ci) {
|
||||
if (this.getAbilities().flying && this.isCamera()) {
|
||||
if (MidnightControlsConfig.verticalFlyDrifting)
|
||||
return;
|
||||
int moving = 0;
|
||||
if (this.input.sneaking) {
|
||||
--moving;
|
||||
}
|
||||
|
||||
if (this.input.jumping) {
|
||||
++moving;
|
||||
}
|
||||
|
||||
if (moving == 0) {
|
||||
this.setVelocity(this.getVelocity().multiply(1.0, 0.0, 1.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.option.ControlsOptionsScreen;
|
||||
import net.minecraft.client.gui.screen.option.GameOptionsScreen;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.option.GameOptions;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Injects the new controls settings button.
|
||||
*/
|
||||
@Mixin(ControlsOptionsScreen.class)
|
||||
public class ControlsOptionsScreenMixin extends GameOptionsScreen {
|
||||
public ControlsOptionsScreenMixin(Screen parent, GameOptions gameOptions, Text text) {
|
||||
super(parent, gameOptions, text);
|
||||
}
|
||||
@Inject(method = "init", at = @At(value = "INVOKE", ordinal = 4, shift = At.Shift.AFTER, target = "Lnet/minecraft/client/gui/screen/option/ControlsOptionsScreen;addDrawableChild(Lnet/minecraft/client/gui/Element;)Lnet/minecraft/client/gui/Element;"))
|
||||
private void addControllerButton(CallbackInfo ci) {
|
||||
int i = this.width / 2 - 155;
|
||||
int j = i + 160;
|
||||
int k = this.height / 6 - 12 + 48;;
|
||||
this.addDrawableChild(new ButtonWidget(j, k, 150, 20, new TranslatableText("midnightcontrols.menu.title.controller").append("..."), (button) -> {
|
||||
this.client.setScreen(new MidnightControlsSettingsScreen(this, false));
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
||||
import net.minecraft.item.ItemGroup;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
/**
|
||||
* Represents an accessor to CreativeInventoryScreen.
|
||||
*/
|
||||
@Mixin(CreativeInventoryScreen.class)
|
||||
public interface CreativeInventoryScreenAccessor {
|
||||
/**
|
||||
* Gets the selected tab.
|
||||
*
|
||||
* @return the selected tab index
|
||||
*/
|
||||
@Accessor("selectedTab")
|
||||
int getSelectedTab();
|
||||
|
||||
/**
|
||||
* Sets the selected tab.
|
||||
*
|
||||
* @param group the tab's item group
|
||||
*/
|
||||
@Invoker("setSelectedTab")
|
||||
void midnightcontrols$setSelectedTab(@NotNull ItemGroup group);
|
||||
|
||||
/**
|
||||
* Returns whether the slot belongs to the creative inventory or not.
|
||||
*
|
||||
* @param slot the slot to check
|
||||
* @return true if the slot is from the creative inventory, else false
|
||||
*/
|
||||
@Invoker("isCreativeInventorySlot")
|
||||
boolean midnightcontrols$isCreativeInventorySlot(@Nullable Slot slot);
|
||||
|
||||
/**
|
||||
* Returns whether the current tab has a scrollbar or not.
|
||||
*
|
||||
* @return true if the current tab has a scrollbar, else false
|
||||
*/
|
||||
@Invoker("hasScrollbar")
|
||||
boolean midnightcontrols$hasScrollbar();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import net.minecraft.client.gui.widget.EntryListWidget;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
@Mixin(EntryListWidget.class)
|
||||
public interface EntryListWidgetAccessor {
|
||||
@Invoker("moveSelection")
|
||||
void midnightcontrols$moveSelection(EntryListWidget.MoveDirection direction);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import net.minecraft.client.option.GameOptions;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Represents a mixin to GameOptions.
|
||||
* <p>
|
||||
* Sets the default of the Auto-Jump option to false.
|
||||
*/
|
||||
@Mixin(GameOptions.class)
|
||||
public class GameOptionsMixin {
|
||||
@Shadow
|
||||
public boolean autoJump;
|
||||
|
||||
@Inject(method = "load", at = @At("HEAD"))
|
||||
public void onInit(CallbackInfo ci) {
|
||||
// Set default value of the Auto-Jump option to false.
|
||||
this.autoJump = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.GameRenderer;
|
||||
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.CallbackInfo;
|
||||
|
||||
@Mixin(GameRenderer.class)
|
||||
public class GameRendererMixin {
|
||||
@Shadow
|
||||
@Final
|
||||
private MinecraftClient client;
|
||||
|
||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Mouse;getX()D"))
|
||||
private void onRender(float tickDelta, long startTime, boolean fullRender, CallbackInfo ci) {
|
||||
if (this.client.currentScreen != null && MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER)
|
||||
MidnightControlsClient.get().input.onPreRenderScreen(this.client, this.client.currentScreen);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
|
||||
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.screen.slot.SlotActionType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* Represents the mixin for the class ContainerScreen.
|
||||
*/
|
||||
@Mixin(HandledScreen.class)
|
||||
public abstract class HandledScreenMixin implements HandledScreenAccessor {
|
||||
|
||||
@Accessor("x")
|
||||
public abstract int getX();
|
||||
|
||||
@Accessor("y")
|
||||
public abstract int getY();
|
||||
|
||||
@Invoker("getSlotAt")
|
||||
public abstract Slot midnightcontrols$getSlotAt(double posX, double posY);
|
||||
|
||||
@Invoker("isClickOutsideBounds")
|
||||
public abstract boolean midnightcontrols$isClickOutsideBounds(double mouseX, double mouseY, int x, int y, int button);
|
||||
|
||||
|
||||
@Invoker("onMouseClick")
|
||||
public abstract void midnightcontrols$onMouseClick(@Nullable Slot slot, int slotId, int clickData, SlotActionType actionType);
|
||||
|
||||
@Inject(method = "render", at = @At("RETURN"))
|
||||
public void onRender(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo ci) {
|
||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) {
|
||||
var client = MinecraftClient.getInstance();
|
||||
int x = 2, y = client.getWindow().getScaledHeight() - 2 - MidnightControlsRenderer.ICON_SIZE;
|
||||
|
||||
x = MidnightControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_A}, "midnightcontrols.action.pickup_all", true, client) + 2;
|
||||
x = MidnightControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_B}, "midnightcontrols.action.exit", true, client) + 2;
|
||||
if (MidnightControlsCompat.isReiPresent()) {
|
||||
x = 2;
|
||||
y -= 24;
|
||||
}
|
||||
x = MidnightControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_X}, "midnightcontrols.action.pickup", true, client) + 2;
|
||||
MidnightControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_Y}, "midnightcontrols.action.quick_move", true, client);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
|
||||
import net.minecraft.client.option.KeyBinding;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
@Mixin(KeyBinding.class)
|
||||
public class KeyBindingMixin implements KeyBindingAccessor {
|
||||
@Shadow
|
||||
private int timesPressed;
|
||||
|
||||
@Shadow
|
||||
private boolean pressed;
|
||||
|
||||
@Override
|
||||
public boolean midnightcontrols$press() {
|
||||
boolean oldPressed = this.pressed;
|
||||
if (!this.pressed)
|
||||
this.pressed = true;
|
||||
++this.timesPressed;
|
||||
return oldPressed != this.pressed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean midnightcontrols$unpress() {
|
||||
if (this.pressed) {
|
||||
this.pressed = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||
import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
||||
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.network.ClientPlayerEntity;
|
||||
import net.minecraft.client.network.ClientPlayerInteractionManager;
|
||||
import net.minecraft.client.render.GameRenderer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.hit.HitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
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.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(MinecraftClient.class)
|
||||
public abstract class MinecraftClientMixin {
|
||||
@Shadow
|
||||
@Nullable
|
||||
public HitResult crosshairTarget;
|
||||
|
||||
@Shadow
|
||||
@Nullable
|
||||
public ClientPlayerEntity player;
|
||||
|
||||
@Shadow
|
||||
@Nullable
|
||||
public ClientPlayerInteractionManager interactionManager;
|
||||
|
||||
@Shadow
|
||||
@Nullable
|
||||
public ClientWorld world;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
public GameRenderer gameRenderer;
|
||||
|
||||
@Shadow
|
||||
private int itemUseCooldown;
|
||||
|
||||
private BlockPos midnightcontrols$lastTargetPos;
|
||||
private Vec3d midnightcontrols$lastPos;
|
||||
private Direction midnightcontrols$lastTargetSide;
|
||||
|
||||
@Inject(method = "<init>", at = @At("RETURN"))
|
||||
private void onInit(CallbackInfo ci) {
|
||||
MidnightControlsClient.get().onMcInit((MinecraftClient) (Object) this);
|
||||
}
|
||||
|
||||
@Inject(method = "tick", at = @At("HEAD"))
|
||||
private void onStartTick(CallbackInfo ci) {
|
||||
if (this.player == null)
|
||||
return;
|
||||
|
||||
if (!MidnightControlsFeature.FAST_BLOCK_PLACING.isAvailable())
|
||||
return;
|
||||
if (this.midnightcontrols$lastPos == null)
|
||||
this.midnightcontrols$lastPos = this.player.getPos();
|
||||
|
||||
int cooldown = this.itemUseCooldown;
|
||||
BlockHitResult hitResult;
|
||||
if (this.crosshairTarget != null && this.crosshairTarget.getType() == HitResult.Type.BLOCK && this.player.getAbilities().flying) {
|
||||
hitResult = (BlockHitResult) this.crosshairTarget;
|
||||
var targetPos = hitResult.getBlockPos();
|
||||
var side = hitResult.getSide();
|
||||
|
||||
boolean sidewaysBlockPlacing = this.midnightcontrols$lastTargetPos == null || !targetPos.equals(this.midnightcontrols$lastTargetPos.offset(this.midnightcontrols$lastTargetSide));
|
||||
boolean backwardsBlockPlacing = this.player.input.movementForward < 0.0f && (this.midnightcontrols$lastTargetPos == null || targetPos.equals(this.midnightcontrols$lastTargetPos.offset(this.midnightcontrols$lastTargetSide)));
|
||||
|
||||
if (cooldown > 1
|
||||
&& !targetPos.equals(this.midnightcontrols$lastTargetPos)
|
||||
&& (sidewaysBlockPlacing || backwardsBlockPlacing)) {
|
||||
this.itemUseCooldown = 1;
|
||||
}
|
||||
|
||||
this.midnightcontrols$lastTargetPos = targetPos.toImmutable();
|
||||
this.midnightcontrols$lastTargetSide = side;
|
||||
}
|
||||
// Removed front placing sprinting as way too cheaty.
|
||||
/*else if (this.player.isSprinting()) {
|
||||
hitResult = midnightcontrolsClient.get().reacharound.getLastReacharoundResult();
|
||||
if (hitResult != null) {
|
||||
if (cooldown > 0)
|
||||
this.itemUseCooldown = 0;
|
||||
}
|
||||
}*/
|
||||
this.midnightcontrols$lastPos = this.player.getPos();
|
||||
}
|
||||
|
||||
@Inject(method = "render", at = @At("HEAD"))
|
||||
private void onRender(boolean fullRender, CallbackInfo ci) {
|
||||
MidnightControlsClient.get().onRender((MinecraftClient) (Object) (this));
|
||||
}
|
||||
|
||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/GameRenderer;render(FJZ)V", shift = At.Shift.AFTER))
|
||||
private void renderVirtualCursor(boolean fullRender, CallbackInfo ci) {
|
||||
MidnightControlsRenderer.renderVirtualCursor(new MatrixStack(), (MinecraftClient) (Object) this);
|
||||
}
|
||||
|
||||
@Inject(method = "doItemUse()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/hit/HitResult;getType()Lnet/minecraft/util/hit/HitResult$Type;"), locals = LocalCapture.CAPTURE_FAILEXCEPTION, cancellable = true)
|
||||
private void onItemUse(CallbackInfo ci, Hand[] hands, int handCount, int handIndex, Hand hand, ItemStack stackInHand) {
|
||||
var mod = MidnightControlsClient.get();
|
||||
if (!stackInHand.isEmpty() && this.player.getPitch(0.f) > 35.0F && mod.reacharound.isReacharoundAvailable()) {
|
||||
if (this.crosshairTarget != null && this.crosshairTarget.getType() == HitResult.Type.MISS && this.player.isOnGround()) {
|
||||
if (!stackInHand.isEmpty() && stackInHand.getItem() instanceof BlockItem) {
|
||||
var hitResult = mod.reacharound.getLastReacharoundResult();
|
||||
|
||||
if (hitResult == null)
|
||||
return;
|
||||
|
||||
hitResult = mod.reacharound.withSideForReacharound(hitResult, stackInHand);
|
||||
|
||||
int previousStackCount = stackInHand.getCount();
|
||||
var result = this.interactionManager.interactBlock(this.player, this.world, hand, hitResult);
|
||||
if (result.isAccepted()) {
|
||||
if (result.shouldSwingHand()) {
|
||||
this.player.swingHand(hand);
|
||||
if (!stackInHand.isEmpty() && (stackInHand.getCount() != previousStackCount || this.interactionManager.hasCreativeInventory())) {
|
||||
this.gameRenderer.firstPersonRenderer.resetEquipProgress(hand);
|
||||
}
|
||||
}
|
||||
|
||||
ci.cancel();
|
||||
}
|
||||
|
||||
if (result == ActionResult.FAIL) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.util.MouseAccessor;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.Mouse;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
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.gen.Invoker;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Adds extra access to the mouse.
|
||||
*/
|
||||
@Mixin(Mouse.class)
|
||||
public abstract class MouseMixin implements MouseAccessor {
|
||||
@Shadow
|
||||
@Final
|
||||
private MinecraftClient client;
|
||||
|
||||
@Invoker("onCursorPos")
|
||||
public abstract void midnightcontrols$onCursorPos(long window, double x, double y);
|
||||
|
||||
@Inject(method = "onMouseButton", at = @At(value = "TAIL"))
|
||||
private void onMouseBackButton(long window, int button, int action, int mods, CallbackInfo ci) {
|
||||
if (action == 1 && button == GLFW.GLFW_MOUSE_BUTTON_4 && MinecraftClient.getInstance().currentScreen != null) {
|
||||
if (MidnightControlsClient.get().input.tryGoBack(MinecraftClient.getInstance().currentScreen)) {
|
||||
action = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "isCursorLocked", at = @At("HEAD"), cancellable = true)
|
||||
private void isCursorLocked(CallbackInfoReturnable<Boolean> ci) {
|
||||
if (this.client.currentScreen == null) {
|
||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.virtualMouse) {
|
||||
ci.setReturnValue(true);
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "lockCursor", at = @At("HEAD"), cancellable = true)
|
||||
private void onCursorLocked(CallbackInfo ci) {
|
||||
if (/*config.getControlsMode() == ControlsMode.TOUCHSCREEN
|
||||
||*/ (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.virtualMouse))
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget;
|
||||
import net.minecraft.client.gui.screen.recipebook.RecipeGroupButtonWidget;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mixin(RecipeBookWidget.class)
|
||||
public interface RecipeBookWidgetAccessor {
|
||||
@Accessor("tabButtons")
|
||||
List<RecipeGroupButtonWidget> getTabButtons();
|
||||
|
||||
@Accessor("currentTab")
|
||||
RecipeGroupButtonWidget getCurrentTab();
|
||||
|
||||
@Accessor("currentTab")
|
||||
void setCurrentTab(RecipeGroupButtonWidget currentTab);
|
||||
|
||||
@Invoker("refreshResults")
|
||||
void midnightcontrols$refreshResults(boolean resetCurrentPage);
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.*;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.item.ItemUsageContext;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.hit.HitResult;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
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.CallbackInfo;
|
||||
|
||||
/**
|
||||
* Represents a mixin to WorldRenderer.
|
||||
* <p>
|
||||
* Handles the rendering of the block outline of the reach-around features.
|
||||
*/
|
||||
@Mixin(WorldRenderer.class)
|
||||
public abstract class WorldRendererMixin {
|
||||
@Shadow
|
||||
@Final
|
||||
private MinecraftClient client;
|
||||
|
||||
@Shadow
|
||||
private ClientWorld world;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private BufferBuilderStorage bufferBuilders;
|
||||
|
||||
@Shadow
|
||||
private static void drawShapeOutline(MatrixStack matrixStack, VertexConsumer vertexConsumer, VoxelShape voxelShape, double d, double e, double f, float g, float h, float i, float j) {
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "render",
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
target = "Lnet/minecraft/client/MinecraftClient;crosshairTarget:Lnet/minecraft/util/hit/HitResult;",
|
||||
ordinal = 1,
|
||||
shift = At.Shift.AFTER
|
||||
)
|
||||
)
|
||||
private void onOutlineRender(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer,
|
||||
LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) {
|
||||
if (this.client.crosshairTarget == null || this.client.crosshairTarget.getType() != HitResult.Type.MISS || !MidnightControlsConfig.shouldRenderReacharoundOutline)
|
||||
return;
|
||||
var result = MidnightControlsClient.get().reacharound.getLastReacharoundResult();
|
||||
if (result == null)
|
||||
return;
|
||||
var blockPos = result.getBlockPos();
|
||||
if (this.world.getWorldBorder().contains(blockPos)) {
|
||||
var stack = this.client.player.getStackInHand(Hand.MAIN_HAND);
|
||||
if (stack == null || !(stack.getItem() instanceof BlockItem))
|
||||
return;
|
||||
|
||||
var mod = MidnightControlsClient.get();
|
||||
|
||||
var block = ((BlockItem) stack.getItem()).getBlock();
|
||||
result = mod.reacharound.withSideForReacharound(result, block);
|
||||
var context = new ItemPlacementContext(new ItemUsageContext(this.client.player, Hand.MAIN_HAND, result));
|
||||
|
||||
var placementState = block.getPlacementState(context);
|
||||
if (placementState == null)
|
||||
return;
|
||||
var pos = camera.getPos();
|
||||
|
||||
var outlineShape = placementState.getOutlineShape(this.client.world, blockPos, ShapeContext.of(camera.getFocusedEntity()));
|
||||
int[] color = MidnightControlsConfig.reacharoundOutlineColor;
|
||||
|
||||
var vertexConsumer = this.bufferBuilders.getEntityVertexConsumers().getBuffer(RenderLayer.getLines());
|
||||
drawShapeOutline(matrices, vertexConsumer, outlineShape,
|
||||
(double) blockPos.getX() - pos.getX(), (double) blockPos.getY() - pos.getY(), (double) blockPos.getZ() - pos.getZ(),
|
||||
color[0] / 255.f, color[1] / 255.f, color[2] / 255.f, color[3] / 255.f);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user