Compare commits

..

7 Commits

Author SHA1 Message Date
Martin Prokoph
d3a787090e Always respect minor version in name 2024-04-29 20:55:08 +02:00
Martin Prokoph
00780e13fd Apply mixins conditionally & bump version 2024-04-29 20:51:50 +02:00
Martin Prokoph
a5554ee21d Improve Ranged Combat code 2024-04-29 20:24:42 +02:00
Martin Prokoph
728a2d4603 Merge pull request #272 from kabliz/eye_tracking_range_combat
Improved Range Combat While Eye Tracking
2024-04-29 20:05:21 +02:00
Martin Prokoph
eb54245c21 Merge branch '1.20.5' into eye_tracking_range_combat 2024-04-29 20:05:05 +02:00
Martin Prokoph
e6fcd1469c Port to 1.20.5
Also implemented some nice small fixes :)
2024-04-29 20:03:09 +02:00
Kabliz
8a30b5ee73 Improved Range Combat While Eye Tracking
Adjusted the dynamic camera sensitivity while using an item intended to be used at a distance: the bow, crossbow, trident, and splash potion. The deadzone is now ignored, making slight adjustments to aim a little easier. The deadzone was meant to assist mining and building, but it is a hindrance in ranged combat.
2024-03-17 12:04:24 -07:00
23 changed files with 254 additions and 144 deletions

View File

@@ -1,5 +1,5 @@
plugins {
id 'fabric-loom' version '1.1-SNAPSHOT'
id 'fabric-loom' version '1.6-SNAPSHOT'
id 'java-library'
id 'maven-publish'
id 'com.github.johnrengelman.shadow' version '7.0.0'
@@ -13,7 +13,7 @@ group = project.maven_group
version = "${project.mod_version}+${getMCVersionString()}"
// This field defines the Java version your mod target.
def targetJavaVersion = 17
def targetJavaVersion = 21
boolean isMCVersionNonRelease() {
return project.minecraft_version.matches('^\\d\\dw\\d\\d[a-z]$')
@@ -21,11 +21,7 @@ boolean isMCVersionNonRelease() {
}
String getMCVersionString() {
if (isMCVersionNonRelease() || project.minecraft_version == "1.20.4") {
return project.minecraft_version
}
def version = project.minecraft_version.split('\\.')
return version[0] + '.' + version[1]
return project.minecraft_version
}
boolean pingUrl(String address) {

View File

@@ -3,12 +3,12 @@ org.gradle.jvmargs=-Xmx1G
# Fabric Properties
# check these on https://fabricmc.net/use
minecraft_version=1.20.4
yarn_mappings=1.20.4+build.3
loader_version=0.15.3
minecraft_version=1.20.5
yarn_mappings=1.20.5+build.1
loader_version=0.15.10
# Mod Properties
mod_version = 1.9.4
mod_version = 1.9.5
maven_group = eu.midnightdust
archives_base_name = midnightcontrols
modrinth_id = bXX9h73M
@@ -17,11 +17,11 @@ changelog = See changes at: https://github.com/TeamMidnightDust/MidnightControls
# Dependencies
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
fabric_version=0.91.3+1.20.4
fabric_version=0.97.7+1.20.5
sodium_version=mc1.19.2-0.4.4
spruceui_version=5.0.3+1.20.4
midnightlib_version=1.5.3-fabric
modmenu_version=7.0.0
midnightlib_version=1.5.4-fabric
modmenu_version=10.0.0-beta.1
emotecraft_version=2.1.3-SNAPSHOT-build.29-MC1.19-fabric
bendylib_version=2.0.+
emi_version=1.1.1+1.20.4+fabric

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@@ -9,15 +9,18 @@
package eu.midnightdust.midnightcontrols;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.event.PlayerChangeControlsModeCallback;
import eu.midnightdust.midnightcontrols.packet.ControlsModePacket;
import eu.midnightdust.midnightcontrols.packet.FeaturePacket;
import eu.midnightdust.midnightcontrols.packet.HelloPacket;
import io.netty.buffer.Unpooled;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.Identifier;
import net.minecraft.network.packet.CustomPayload;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
@@ -34,9 +37,9 @@ import java.util.Optional;
*/
public class MidnightControls implements ModInitializer {
private static MidnightControls INSTANCE;
public static final Identifier CONTROLS_MODE_CHANNEL = new Identifier(MidnightControlsConstants.CONTROLS_MODE_CHANNEL.toString());
public static final Identifier FEATURE_CHANNEL = new Identifier(MidnightControlsConstants.FEATURE_CHANNEL.toString());
public static final Identifier HELLO_CHANNEL = new Identifier(MidnightControlsConstants.HELLO_CHANNEL.toString());
public static final CustomPayload.Id<CustomPayload> CONTROLS_MODE_CHANNEL = CustomPayload.id(MidnightControlsConstants.CONTROLS_MODE_CHANNEL.toString());
public static final CustomPayload.Id<CustomPayload> FEATURE_CHANNEL = CustomPayload.id(MidnightControlsConstants.FEATURE_CHANNEL.toString());
public static final CustomPayload.Id<CustomPayload> HELLO_CHANNEL = CustomPayload.id(MidnightControlsConstants.HELLO_CHANNEL.toString());
public static boolean isExtrasLoaded;
public final Logger logger = LogManager.getLogger("MidnightControls");
@@ -47,19 +50,19 @@ public class MidnightControls implements ModInitializer {
isExtrasLoaded = FabricLoader.getInstance().isModLoaded("midnightcontrols-extra");
this.log("Initializing MidnightControls...");
ServerPlayNetworking.registerGlobalReceiver(HELLO_CHANNEL, (server, player, handler, buf, responseSender) -> {
String version = buf.readString(32);
ControlsMode.byId(buf.readString(32))
.ifPresent(controlsMode -> server
.execute(() -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(player, controlsMode)));
server.execute(() -> {
ServerPlayNetworking.send(player, FEATURE_CHANNEL, this.makeFeatureBuffer(MidnightControlsFeature.HORIZONTAL_REACHAROUND));
});
PayloadTypeRegistry.playC2S().register(HelloPacket.PACKET_ID, HelloPacket.codec);
PayloadTypeRegistry.playC2S().register(ControlsModePacket.PACKET_ID, ControlsModePacket.codec);
PayloadTypeRegistry.playS2C().register(ControlsModePacket.PACKET_ID, ControlsModePacket.codec);
PayloadTypeRegistry.playS2C().register(FeaturePacket.PACKET_ID, FeaturePacket.codec);
ServerPlayNetworking.registerGlobalReceiver(HelloPacket.PACKET_ID, (payload, context) -> {
ControlsMode.byId(payload.controlsMode())
.ifPresent(controlsMode -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(context.player(), controlsMode));
context.responseSender().sendPacket(new FeaturePacket(MidnightControlsFeature.HORIZONTAL_REACHAROUND));
});
ServerPlayNetworking.registerGlobalReceiver(CONTROLS_MODE_CHANNEL,
(server, player, handler, buf, responseSender) -> ControlsMode.byId(buf.readString(32))
.ifPresent(controlsMode -> server
.execute(() -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(player, controlsMode))));
ServerPlayNetworking.registerGlobalReceiver(ControlsModePacket.PACKET_ID,
(payload, context) -> ControlsMode.byId(payload.controlsMode())
.ifPresent(controlsMode -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(context.player(), controlsMode)));
}
/**
@@ -80,44 +83,6 @@ public class MidnightControls implements ModInitializer {
this.logger.info("[MidnightControls] " + warning);
}
/**
* Returns a packet byte buffer made for the midnightcontrols:controls_mode plugin message.
*
* @param controlsMode the controls mode to send
* @return the packet byte buffer
*/
public PacketByteBuf makeControlsModeBuffer(@NotNull ControlsMode controlsMode) {
Objects.requireNonNull(controlsMode, "Controls mode cannot be null.");
return new PacketByteBuf(Unpooled.buffer()).writeString(controlsMode.getName(), 32);
}
/**
* Returns a packet byte buffer made for the midnightcontrols:feature plugin message.
*
* @param features the features data to send
* @return the packet byte buffer
*/
public PacketByteBuf makeFeatureBuffer(MidnightControlsFeature... features) {
if (features.length == 0)
throw new IllegalArgumentException("At least one feature must be provided.");
var buffer = new PacketByteBuf(Unpooled.buffer());
buffer.writeVarInt(features.length);
for (var feature : features) {
buffer.writeString(feature.getName(), 64);
buffer.writeBoolean(feature.isAllowed());
}
return buffer;
}
public PacketByteBuf makeHello(@NotNull ControlsMode controlsMode) {
var version = "";
Optional<ModContainer> container;
if ((container = FabricLoader.getInstance().getModContainer(MidnightControlsConstants.NAMESPACE)).isPresent()) {
version = container.get().getMetadata().getVersion().getFriendlyString();
}
return new PacketByteBuf(Unpooled.buffer()).writeString(version, 32).writeString(controlsMode.getName(), 32);
}
/**
* Gets the MidnightControls instance.
*

View File

@@ -29,6 +29,9 @@ import eu.midnightdust.midnightcontrols.client.ring.MidnightRing;
import dev.lambdaurora.spruceui.hud.HudManager;
import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
import eu.midnightdust.midnightcontrols.client.util.RainbowColor;
import eu.midnightdust.midnightcontrols.packet.ControlsModePacket;
import eu.midnightdust.midnightcontrols.packet.FeaturePacket;
import eu.midnightdust.midnightcontrols.packet.HelloPacket;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
@@ -37,6 +40,7 @@ import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.fabricmc.fabric.api.resource.ResourcePackActivationType;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.option.KeyBinding;
@@ -48,9 +52,7 @@ import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFW;
import java.io.File;
import java.util.Objects;
import java.util.Timer;
import java.util.TimerTask;
import java.util.*;
/**
* Represents the midnightcontrols client mod.
@@ -94,19 +96,19 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo
this.ring.registerAction("buttonbinding", ButtonBindingRingAction.FACTORY);
ClientPlayNetworking.registerGlobalReceiver(CONTROLS_MODE_CHANNEL, (client, handler, buf, responseSender) ->
responseSender.sendPacket(CONTROLS_MODE_CHANNEL, this.makeControlsModeBuffer(MidnightControlsConfig.controlsMode)));
ClientPlayNetworking.registerGlobalReceiver(FEATURE_CHANNEL, (client, handler, buf, responseSender) -> {
int features = buf.readVarInt();
for (int i = 0; i < features; i++) {
var name = buf.readString(64);
boolean allowed = buf.readBoolean();
MidnightControlsFeature.fromName(name).ifPresent(feature -> client.execute(() -> feature.setAllowed(allowed)));
}
});
ClientPlayNetworking.registerGlobalReceiver(CONTROLS_MODE_CHANNEL, (payload, context) ->
context.responseSender().sendPacket(new ControlsModePacket(MidnightControlsConfig.controlsMode.getName())));
ClientPlayNetworking.registerGlobalReceiver(FeaturePacket.PACKET_ID, ((payload, context) -> {}));
ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> {
sender.sendPacket(HELLO_CHANNEL, this.makeHello(MidnightControlsConfig.controlsMode));
sender.sendPacket(CONTROLS_MODE_CHANNEL, this.makeControlsModeBuffer(MidnightControlsConfig.controlsMode));
var version = "";
Optional<ModContainer> container;
if ((container = FabricLoader.getInstance().getModContainer(MidnightControlsConstants.NAMESPACE)).isPresent()) {
version = container.get().getMetadata().getVersion().getFriendlyString();
}
var controlsMode = MidnightControlsConfig.controlsMode.getName();
sender.sendPacket(new HelloPacket(version, controlsMode));
sender.sendPacket(new ControlsModePacket(controlsMode));
});
ClientPlayConnectionEvents.DISCONNECT.register(this::onLeave);
@@ -255,6 +257,7 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo
MidnightControlsConfig.controlsMode = this.previousControlsMode;
}
ClientPlayNetworking.getSender().sendPacket(new ControlsModePacket(MidnightControlsConfig.controlsMode.getName()));
}
}

View File

@@ -489,7 +489,7 @@ public class MidnightInput {
state = 1;
asButtonState = 1;
}
if (MidnightControlsConfig.debug) System.out.println(axis + " "+ value + " " + absValue + " " + state);
//if (MidnightControlsConfig.debug) System.out.println(axis + " "+ value + " " + absValue + " " + state);
}
}

View File

@@ -15,6 +15,7 @@ import net.minecraft.block.BlockState;
import net.minecraft.block.FluidBlock;
import net.minecraft.block.SlabBlock;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.util.hit.BlockHitResult;
@@ -74,7 +75,7 @@ public class MidnightReacharound {
}
public static float getPlayerRange(@NotNull MinecraftClient client) {
return client.interactionManager != null ? client.interactionManager.getReachDistance() : 0.f;
return client.player != null ? Double.valueOf(client.player.getAttributeValue(EntityAttributes.PLAYER_BLOCK_INTERACTION_RANGE)).floatValue() : 0.f;
}
/**

View File

@@ -9,6 +9,7 @@
package eu.midnightdust.midnightcontrols.client.compat;
import eu.midnightdust.lib.util.PlatformFunctions;
import net.fabricmc.loader.api.FabricLoader;
import org.jetbrains.annotations.NotNull;
import org.objectweb.asm.tree.ClassNode;
@@ -22,23 +23,16 @@ import java.util.Set;
/**
* This plugin is only present for the conditional mixins.
*
* @author LambdAurora
* @version 1.5.0
* @author LambdAurora & Motschen
* @version 1.6.0
* @since 1.2.0
*/
public class MidnightControlsMixinPlugin implements IMixinConfigPlugin {
private final HashMap<String, Boolean> conditionalMixins = new HashMap<>();
public MidnightControlsMixinPlugin() {
//this.putConditionalMixin("SodiumOptionsGUIAccessor", FabricLoader.getInstance().isModLoaded("sodium"));
}
private void putConditionalMixin(@NotNull String path, boolean condition) {
this.conditionalMixins.put("eu.midnightdust.midnightcontrols.client.compat.mixin." + path, condition);
}
private String mixinPackage;
@Override
public void onLoad(String mixinPackage) {
this.mixinPackage = mixinPackage + ".";
}
@Override
@@ -48,7 +42,13 @@ public class MidnightControlsMixinPlugin implements IMixinConfigPlugin {
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
return this.conditionalMixins.getOrDefault(mixinClassName, Boolean.TRUE);
final String mixinName = mixinClassName.substring(this.mixinPackage.length());
final String packageName = mixinName.substring(0, mixinName.lastIndexOf('.'));
if (packageName.startsWith("sodium") && !PlatformFunctions.isModLoaded("sodium"))
return false;
return true;
}
@Override

View File

@@ -2,7 +2,7 @@ package eu.midnightdust.midnightcontrols.client.compat;
import eu.midnightdust.midnightcontrols.MidnightControls;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.compat.mixin.SodiumOptionsGUIAccessor;
import eu.midnightdust.midnightcontrols.client.compat.mixin.sodium.SodiumOptionsGUIAccessor;
import me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI;
import net.minecraft.client.gui.screen.Screen;

View File

@@ -1,4 +1,4 @@
package eu.midnightdust.midnightcontrols.client.compat.mixin;
package eu.midnightdust.midnightcontrols.client.compat.mixin.sodium;
import me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI;
import me.jellysquid.mods.sodium.client.gui.options.OptionPage;

View File

@@ -151,25 +151,17 @@ public record Controller(int id) implements Nameable {
private static boolean updateMappingsSync() {
try {
MidnightControlsClient.get().log("Updating controller mappings...");
File databaseFile = new File("config/gamecontrollerdatabase.txt");
try {
BufferedInputStream in = new BufferedInputStream(new URL("https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt").openStream());
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(databaseFile));
byte[] dataBuffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
out.write(dataBuffer, 0, bytesRead);
}
out.close();
} catch (Exception ignored) {/* Just continue when internet connection is not available */}
var database = ioResourceToBuffer(databaseFile.getPath(), 1024);
if (database != null) GLFW.glfwUpdateGamepadMappings(database);
Optional<File> databaseFile = getDatabaseFile();
if (databaseFile.isPresent()) {
var database = ioResourceToBuffer(databaseFile.get().getPath(), 1024);
if (database != null) GLFW.glfwUpdateGamepadMappings(database);
}
if (!MidnightControlsClient.MAPPINGS_FILE.exists())
return false;
var buffer = ioResourceToBuffer(MidnightControlsClient.MAPPINGS_FILE.getPath(), 1024);
if (buffer != null) GLFW.glfwUpdateGamepadMappings(buffer);
} catch (IOException e) {
e.printStackTrace();
e.fillInStackTrace();
}
try (var memoryStack = MemoryStack.stackPush()) {
@@ -182,8 +174,8 @@ public record Controller(int id) implements Nameable {
if (client != null) {
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.PERIODIC_NOTIFICATION,
Text.translatable("midnightcontrols.controller.mappings.error"), Text.literal(string)));
MidnightControls.get().log(I18n.translate("midnightcontrols.controller.mappings.error")+string);
}
MidnightControls.get().log(I18n.translate("midnightcontrols.controller.mappings.error")+string);
}
} catch (Throwable e) {
/* Ignored :concern: */
@@ -205,4 +197,19 @@ public record Controller(int id) implements Nameable {
}
return true;
}
private static Optional<File> getDatabaseFile() {
File databaseFile = new File("config/gamecontrollerdatabase.txt");
try {
BufferedInputStream in = new BufferedInputStream(new URL("https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt").openStream());
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(databaseFile));
byte[] dataBuffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
out.write(dataBuffer, 0, bytesRead);
}
out.close();
} catch (Exception e) {return Optional.empty();}
return Optional.of(databaseFile);
}
}

View File

@@ -27,6 +27,7 @@ import dev.lambdaurora.spruceui.widget.SpruceLabelWidget;
import dev.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
import dev.lambdaurora.spruceui.widget.container.SpruceOptionListWidget;
import dev.lambdaurora.spruceui.widget.container.tabbed.SpruceTabbedWidget;
import eu.midnightdust.midnightcontrols.packet.ControlsModePacket;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
@@ -92,6 +93,7 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
id = GLFW.GLFW_JOYSTICK_1;
id = searchNextAvailableController(id, false);
MidnightControlsConfig.setController(Controller.byId(id));
if (MidnightControlsConfig.debug) System.out.println(Controller.byId(id).getName() + "'s Controller GUID: " + Controller.byId(id).getGuid());
},
option -> {
var controller = MidnightControlsConfig.getController();
@@ -182,7 +184,7 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
MidnightControlsConfig.save();
if (this.client != null && this.client.player != null) {
ClientPlayNetworking.getSender().sendPacket(MidnightControls.CONTROLS_MODE_CHANNEL, this.mod.makeControlsModeBuffer(next));
ClientPlayNetworking.getSender().sendPacket(new ControlsModePacket(next.getName()));
}
}, option -> option.getDisplayText(Text.translatable(MidnightControlsConfig.controlsMode.getTranslationKey())),
Text.translatable("midnightcontrols.menu.controls_mode.tooltip"));

View File

@@ -86,6 +86,9 @@ public class TouchscreenOverlay extends Screen {
@Override
public void renderInGameBackground(DrawContext context) {}
@Override
protected void applyBlur(float delta) {}
private void pauseGame() {
assert this.client != null;
this.client.setScreen(new GameMenuScreen(true));

View File

@@ -10,14 +10,19 @@
package eu.midnightdust.midnightcontrols.client.mixin;
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen;
import net.minecraft.client.MinecraftClient;
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.OptionListWidget;
import net.minecraft.client.gui.widget.TextIconButtonWidget;
import net.minecraft.client.option.GameOptions;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
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;
@@ -27,14 +32,29 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
*/
@Mixin(ControlsOptionsScreen.class)
public abstract class ControlsOptionsScreenMixin extends GameOptionsScreen {
public ControlsOptionsScreenMixin(Screen parent, GameOptions gameOptions, Text text) {
super(parent, gameOptions, text);
@Shadow @Nullable private OptionListWidget optionListWidget;
public ControlsOptionsScreenMixin(Screen parent, GameOptions gameOptions, Text title) {
super(parent, gameOptions, title);
}
@Inject(method = "init", at = @At(value = "INVOKE", ordinal = 1, 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) {
TextIconButtonWidget iconWidget = TextIconButtonWidget.builder(Text.translatable("midnightcontrols.menu.title.controller"), (button -> this.client.setScreen(new MidnightControlsSettingsScreen(this, false))), true)
.dimension(20,20).texture(new Identifier("midnightcontrols", "icon/controller"), 20, 20).build();
iconWidget.setPosition(this.width / 2 + 158, this.height / 6 - 12);
this.addDrawableChild(iconWidget);
@Unique TextIconButtonWidget button = TextIconButtonWidget.builder(Text.translatable("midnightcontrols.menu.title.controller"), (button -> this.client.setScreen(new MidnightControlsSettingsScreen(this, false))), true)
.dimension(20,20).texture(new Identifier("midnightcontrols", "icon/controller"), 20, 20).build();
@Inject(at = @At("TAIL"), method = "init")
public void midnightcontrols$onInit(CallbackInfo ci) {
this.midnightcontrols$setupButton();
this.addDrawableChild(button);
}
@Override
public void resize(MinecraftClient client, int width, int height) {
super.resize(client, width, height);
this.midnightcontrols$setupButton();
}
@Unique
public void midnightcontrols$setupButton() {
assert optionListWidget != null;
button.setPosition(optionListWidget.getWidth() / 2 + 158, optionListWidget.getY() + 4);
}
}

View File

@@ -9,6 +9,7 @@
package eu.midnightdust.midnightcontrols.client.mixin;
import com.llamalad7.mixinextras.sugar.Local;
import com.mojang.blaze3d.systems.RenderSystem;
import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
@@ -18,14 +19,13 @@ import eu.midnightdust.midnightcontrols.client.touch.TouchUtils;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.util.math.MatrixStack;
import org.joml.Matrix4f;
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(GameRenderer.class)
public abstract class GameRendererMixin {
@@ -38,15 +38,16 @@ public abstract class GameRendererMixin {
if (this.client.currentScreen != null && MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER)
MidnightControlsClient.get().input.onPreRenderScreen(this.client, this.client.currentScreen);
}
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;draw()V", shift = At.Shift.BEFORE), locals = LocalCapture.CAPTURE_FAILSOFT)
private void renderVirtualCursor(float tickDelta, long startTime, boolean tick, CallbackInfo ci, boolean bl, MatrixStack matrixStack, DrawContext drawContext) {
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;draw()V", shift = At.Shift.BEFORE))
private void renderVirtualCursor(float tickDelta, long startTime, boolean tick, CallbackInfo ci, @Local DrawContext drawContext) {
MidnightControlsRenderer.renderVirtualCursor(drawContext, client);
drawContext.draw();
}
@Inject(at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/GameRenderer;renderHand:Z", ordinal = 0), method = "renderWorld")
private void postWorldRender(float tickDelta, long limitTime, MatrixStack matrix, CallbackInfo ci) {
@Inject(at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/GameRenderer;renderHand:Z"), method = "renderWorld")
private void captureProjAndModMatrix(float tickDelta, long limitTime, CallbackInfo ci, @Local(ordinal = 1) Matrix4f matrices) {
TouchUtils.lastProjMat.set(RenderSystem.getProjectionMatrix());
TouchUtils.lastModMat.set(RenderSystem.getModelViewMatrix());
TouchUtils.lastWorldSpaceMatrix.set(matrix.peek().getPositionMatrix());
TouchUtils.lastWorldSpaceMatrix.set(matrices);
}
}

View File

@@ -19,10 +19,14 @@ import net.minecraft.client.MinecraftClient;
import net.minecraft.client.Mouse;
import net.minecraft.client.util.GlfwUtil;
import net.minecraft.client.util.SmoothUtil;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ThrowablePotionItem;
import net.minecraft.util.UseAction;
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;
@@ -51,7 +55,7 @@ public abstract class MouseMixin implements MouseAccessor {
@Shadow private boolean hasResolutionChanged;
@Shadow private double lastMouseUpdateTime;
@Shadow private double glfwTime;
@Shadow @Final private SmoothUtil cursorXSmoother;
@@ -116,8 +120,8 @@ public abstract class MouseMixin implements MouseAccessor {
cursorYSmoother.clear();
}
EyeTrackerHandler.updateMouseWithEyeTracking(x + cursorDeltaX, y + cursorDeltaY, client,
lastMouseUpdateTime, leftButtonClicked, cursorXSmoother, cursorYSmoother);
lastMouseUpdateTime = GlfwUtil.getTime();
glfwTime, leftButtonClicked, isUsingLongRangedTool(), cursorXSmoother, cursorYSmoother);
glfwTime = GlfwUtil.getTime();
cursorDeltaX = 0.0;
cursorDeltaY = 0.0;
ci.cancel();
@@ -127,6 +131,14 @@ public abstract class MouseMixin implements MouseAccessor {
}
}
@Unique
private boolean isUsingLongRangedTool() {
if (client.player == null) return false;
ItemStack stack = client.player.getActiveItem();
return (leftButtonClicked && (stack.getUseAction() == UseAction.BOW || stack.getUseAction() == UseAction.CROSSBOW ||
stack.getUseAction() == UseAction.SPEAR || stack.getItem() instanceof ThrowablePotionItem));
}
@Inject(method = "lockCursor", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/InputUtil;setCursorParameters(JIDD)V",shift = At.Shift.BEFORE), cancellable = true)
private void midnightcontrols$lockCursor(CallbackInfo ci) {
if ((doMixedInput() || MidnightControlsConfig.eyeTrackerAsMouse)) {

View File

@@ -9,6 +9,7 @@
package eu.midnightdust.midnightcontrols.client.mixin;
import com.llamalad7.mixinextras.sugar.Local;
import eu.midnightdust.lib.util.MidnightColorUtil;
import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
@@ -61,6 +62,7 @@ public abstract class WorldRendererMixin {
@Shadow
private static void drawCuboidShapeOutline(MatrixStack matrices, VertexConsumer vertexConsumer, VoxelShape shape, double offsetX, double offsetY, double offsetZ, float red, float green, float blue, float alpha) {
}
@Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/hit/HitResult;getType()Lnet/minecraft/util/hit/HitResult$Type;"))
private HitResult.Type dontRenderOutline(HitResult instance) {
if (MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN && MidnightControlsConfig.touchMode == TouchMode.FINGER_POS) {
@@ -78,8 +80,7 @@ public abstract class WorldRendererMixin {
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) {
private void onOutlineRender(float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, Matrix4f matrix4f2, CallbackInfo ci, @Local MatrixStack matrices) {
if (((MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.touchInControllerMode) || MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN)
&& MidnightControlsConfig.touchMode == TouchMode.FINGER_POS) {
this.renderFingerOutline(matrices, camera);

View File

@@ -15,6 +15,7 @@ public class EyeTrackerHandler {
MinecraftClient client,
double lastMouseUpdateTime,
boolean holdingLeftMouseButton,
boolean usingLongRangedTool,
SmoothUtil smoothX,
SmoothUtil smoothY
) {
@@ -45,7 +46,7 @@ public class EyeTrackerHandler {
} else {
frameScalar = moveScalar;
}
if(holdingLeftMouseButton){
if(holdingLeftMouseButton && !usingLongRangedTool) {
frameScalar *= 0.5; //Don't move the camera so much while mining. It's annoying.
}
@@ -68,7 +69,8 @@ public class EyeTrackerHandler {
if (client.options.getInvertYMouse().getValue()) {
invertY = -1.0;
}
if (client.player != null && moveMagnitude > MidnightControlsConfig.eyeTrackerDeadzone) {
boolean notInDeadzone = (moveMagnitude > MidnightControlsConfig.eyeTrackerDeadzone) && !usingLongRangedTool;
if (client.player != null && notInDeadzone) {
client.player.changeLookDirection(moveX, moveY * invertY);
client.getTutorialManager().onUpdateMouse(moveX, moveY);
}

View File

@@ -0,0 +1,33 @@
package eu.midnightdust.midnightcontrols.packet;
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import io.netty.buffer.Unpooled;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.network.packet.CustomPayload;
import java.util.Objects;
import java.util.Optional;
public record ControlsModePacket(String controlsMode) implements CustomPayload {
public static final Id<ControlsModePacket> PACKET_ID = new Id<>(MidnightControlsConstants.CONTROLS_MODE_CHANNEL);
public static final PacketCodec<RegistryByteBuf, ControlsModePacket> codec = PacketCodec.of(ControlsModePacket::write, ControlsModePacket::read);
public static ControlsModePacket read(RegistryByteBuf buf) {
return new ControlsModePacket(buf.readString(32));
}
public void write(RegistryByteBuf buf) {
Objects.requireNonNull(controlsMode, "Controls mode cannot be null.");
buf.writeString(controlsMode, 32);
}
@Override
public Id<? extends CustomPayload> getId() {
return PACKET_ID;
}
}

View File

@@ -0,0 +1,43 @@
package eu.midnightdust.midnightcontrols.packet;
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.network.packet.CustomPayload;
public record FeaturePacket(MidnightControlsFeature... features) implements CustomPayload {
public static final Id<FeaturePacket> PACKET_ID = new Id<>(MidnightControlsConstants.FEATURE_CHANNEL);
public static final PacketCodec<RegistryByteBuf, FeaturePacket> codec = PacketCodec.of(FeaturePacket::write, FeaturePacket::read);
public static FeaturePacket read(RegistryByteBuf buf) {
int featureLength = buf.readVarInt();
MidnightControlsFeature[] receivedFeatures = new MidnightControlsFeature[featureLength];
for (int i = 0; i < featureLength; i++) {
var name = buf.readString(64);
boolean allowed = buf.readBoolean();
var feature = MidnightControlsFeature.fromName(name);
if (feature.isPresent()) {
feature.get().setAllowed(allowed);
receivedFeatures[i] = feature.get();
}
}
return new FeaturePacket(receivedFeatures);
}
public void write(RegistryByteBuf buf) {
if (features.length == 0)
throw new IllegalArgumentException("At least one feature must be provided.");
buf.writeVarInt(features.length);
for (var feature : features) {
buf.writeString(feature.getName(), 64);
buf.writeBoolean(feature.isAllowed());
}
}
@Override
public Id<? extends CustomPayload> getId() {
return PACKET_ID;
}
}

View File

@@ -0,0 +1,24 @@
package eu.midnightdust.midnightcontrols.packet;
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.network.packet.CustomPayload;
public record HelloPacket(String version, String controlsMode) implements CustomPayload {
public static final CustomPayload.Id<HelloPacket> PACKET_ID = new CustomPayload.Id<>(MidnightControlsConstants.HELLO_CHANNEL);
public static final PacketCodec<RegistryByteBuf, HelloPacket> codec = PacketCodec.of(HelloPacket::write, HelloPacket::read);
public static HelloPacket read(RegistryByteBuf buf) {
return new HelloPacket(buf.readString(32), buf.readString(32));
}
public void write(RegistryByteBuf buf) {
buf.writeString(version, 32).writeString(controlsMode, 32);
}
@Override
public Id<? extends CustomPayload> getId() {
return PACKET_ID;
}
}

View File

@@ -53,13 +53,10 @@
"depends": {
"fabricloader": ">=0.11.3",
"fabric": ">=0.71.0",
"minecraft": "~1.20",
"minecraft": ">=1.20.5",
"spruceui": ">=3.2.0",
"java": ">=17"
},
"recommends": {
"modmenu": ">=1.12.2"
},
"suggests": {
"kontrolo": "*"
},

View File

@@ -4,7 +4,7 @@
"plugin": "eu.midnightdust.midnightcontrols.client.compat.MidnightControlsMixinPlugin",
"compatibilityLevel": "JAVA_16",
"client": [
"SodiumOptionsGUIAccessor"
"sodium.SodiumOptionsGUIAccessor"
],
"injectors": {
"defaultRequire": 1