Compare commits

..

13 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
Martin Prokoph
43ffd89a61 Merge pull request #271 from Androser420/1.20.4
Fix Toggle Sprint/Sneak.
2024-03-10 17:07:53 +01:00
Androser420
8a9866f92f Update InputHandlers.java 2024-03-10 00:26:57 +01:00
Androser420
b12413cbcd Update ButtonBinding.java 2024-03-10 00:26:01 +01:00
Martin Prokoph
9f62538197 Replace FAQ with wiki link 2024-02-14 23:42:45 +01:00
Martin Prokoph
ba5143403d Add issue template for mod support 2024-02-14 12:52:16 +01:00
Martin Prokoph
454afa92ec Update issue templates 2024-02-14 12:45:48 +01:00
30 changed files with 329 additions and 161 deletions

View File

@@ -1,7 +1,7 @@
--- ---
name: Bug report name: Bug report
about: Create a report to help us improve about: Create a report to help us improve
title: '' title: 'Bug: TITLE HERE'
labels: bug labels: bug
assignees: '' assignees: ''
@@ -21,15 +21,17 @@ Steps to reproduce the behavior:
A clear and concise description of what you expected to happen. A clear and concise description of what you expected to happen.
**Screenshots** **Screenshots**
If applicable, add screenshots to help explain your problem. If applicable, add screenshots or videos to help explain your problem.
**Desktop (please complete the following information):** **Desktop (please complete the following information):**
- OS: [e.g. Linux] - OS: [e.g. Windows / Linux / MacOS]
- Minecraft [e.g. 1.14.4] - Minecraft [e.g. 1.20.4]
- Fabric [e.g. fabric 0.7.2+build.174] - Modloader [e.g. Fabric Loader 0.15.6]
- Mods [e.g. aurora_keystrokes v1.0.0, modmenu v1.7.15] - Fabric/Quilt Libraries [e.g. Fabric Api 0.96.1+1.20.4]
- Mods [e.g. Puzzle v1.6.1, LilTaterReloaded v1.1.15]
- Version [e.g. 1.0.0] - Version [e.g. 1.0.0]
- Branch [e.g. dev] - Remove this line if you actually completed it
**Additional context** **Additional context**
Add any other context about the problem here. Add any other context about the problem here.
In case of a crash, please provide the crash log.

View File

@@ -0,0 +1,40 @@
---
name: Controller support
about: Report a problem related to a specific controller
title: 'Controller Issues: CONTROLLER NAME HERE'
labels: controller
assignees: ''
---
**Describe the current state**
A clear and concise description of current state of support for the controller and the issues.
**To Reproduce**
If needed, specify steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots or videos to help explain your problem.
**Desktop (please complete the following information):**
- Have you checked #263 for your controller? [e.g. Yes/No]
- Connection method [e.g. Wired / Bluetooth]
- OS: [e.g. Windows / Linux / MacOS]
- Minecraft [e.g. 1.20.4]
- Modloader [e.g. Fabric Loader 0.15.6]
- Fabric/Quilt Libraries [e.g. Fabric Api 0.96.1+1.20.4]
- Mods [e.g. Puzzle v1.6.1, LilTaterReloaded v1.1.15]
- Version [e.g. 1.0.0]
- Remove this line if you actually completed it
**Additional context**
Add any other context about the problem here.
In case of a crash, please provide the crash log.

View File

@@ -1,7 +1,7 @@
--- ---
name: Feature request name: Feature request
about: Suggest an idea for this project about: Suggest an idea for this project
title: '' title: 'Feature: TITLE HERE'
labels: enhancement labels: enhancement
assignees: '' assignees: ''
@@ -17,4 +17,4 @@ A clear and concise description of what you want to happen.
A clear and concise description of any alternative solutions or features you've considered. A clear and concise description of any alternative solutions or features you've considered.
**Additional context** **Additional context**
Add any other context or screenshots about the feature request here. Add any other context or screenshots/videos about the feature request here.

20
.github/ISSUE_TEMPLATE/mod_support.md vendored Normal file
View File

@@ -0,0 +1,20 @@
---
name: Mod Support
about: Compatibility improvements with a specific mod (not for crashes)
title: 'Mod Support: MOD NAME HERE'
labels: mod compatibility
assignees: ''
---
**Is your compatibility request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I've always wanted to [...]
**Describe the way of compatibility you'd imagine**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative mods or workarounds you've considered.
**Additional context**
Add any other context or screenshots/videos about the compatibility request here.

View File

@@ -64,11 +64,7 @@ After this is done, everything should be built just fine!
## FAQ: ## FAQ:
### The controller does not work, and it's name appears in orange, what can I do? ### The controller does not work, and it's name appears in orange, what can I do?
Orange controller names indicate a missing controller mapping. Create a custom mapping as pointed out in the [wiki](https://midnightdust.eu/wiki/midnightcontrols/)
Download [GamepadTool](https://generalarcade.com/gamepadtool/), create and copy a mapping, go to MidnightControls' Mappings File Editor and paste the string.
Alternatively, you can use [AntiMicroX](https://github.com/AntiMicroX/antimicroX) to create the mappings, in case the Gamepad Tool is not working for you.
If that works, you might as well consider submitting the mapping by opening a PR in this repo: https://github.com/gabomdq/SDL_GameControllerDB
That will make sure other people using the same controller as you don't have to use gamepad-tool anymore.
[Quilt]: https://quiltmc.org [Quilt]: https://quiltmc.org

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists 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 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

View File

@@ -9,15 +9,18 @@
package eu.midnightdust.midnightcontrols; package eu.midnightdust.midnightcontrols;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.event.PlayerChangeControlsModeCallback; 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 io.netty.buffer.Unpooled;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer; import net.fabricmc.loader.api.ModContainer;
import net.minecraft.network.PacketByteBuf; 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.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -34,9 +37,9 @@ import java.util.Optional;
*/ */
public class MidnightControls implements ModInitializer { public class MidnightControls implements ModInitializer {
private static MidnightControls INSTANCE; private static MidnightControls INSTANCE;
public static final Identifier CONTROLS_MODE_CHANNEL = new Identifier(MidnightControlsConstants.CONTROLS_MODE_CHANNEL.toString()); public static final CustomPayload.Id<CustomPayload> CONTROLS_MODE_CHANNEL = CustomPayload.id(MidnightControlsConstants.CONTROLS_MODE_CHANNEL.toString());
public static final Identifier FEATURE_CHANNEL = new Identifier(MidnightControlsConstants.FEATURE_CHANNEL.toString()); public static final CustomPayload.Id<CustomPayload> FEATURE_CHANNEL = CustomPayload.id(MidnightControlsConstants.FEATURE_CHANNEL.toString());
public static final Identifier HELLO_CHANNEL = new Identifier(MidnightControlsConstants.HELLO_CHANNEL.toString()); public static final CustomPayload.Id<CustomPayload> HELLO_CHANNEL = CustomPayload.id(MidnightControlsConstants.HELLO_CHANNEL.toString());
public static boolean isExtrasLoaded; public static boolean isExtrasLoaded;
public final Logger logger = LogManager.getLogger("MidnightControls"); public final Logger logger = LogManager.getLogger("MidnightControls");
@@ -47,19 +50,19 @@ public class MidnightControls implements ModInitializer {
isExtrasLoaded = FabricLoader.getInstance().isModLoaded("midnightcontrols-extra"); isExtrasLoaded = FabricLoader.getInstance().isModLoaded("midnightcontrols-extra");
this.log("Initializing MidnightControls..."); this.log("Initializing MidnightControls...");
ServerPlayNetworking.registerGlobalReceiver(HELLO_CHANNEL, (server, player, handler, buf, responseSender) -> { PayloadTypeRegistry.playC2S().register(HelloPacket.PACKET_ID, HelloPacket.codec);
String version = buf.readString(32); PayloadTypeRegistry.playC2S().register(ControlsModePacket.PACKET_ID, ControlsModePacket.codec);
ControlsMode.byId(buf.readString(32)) PayloadTypeRegistry.playS2C().register(ControlsModePacket.PACKET_ID, ControlsModePacket.codec);
.ifPresent(controlsMode -> server PayloadTypeRegistry.playS2C().register(FeaturePacket.PACKET_ID, FeaturePacket.codec);
.execute(() -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(player, controlsMode)));
server.execute(() -> { ServerPlayNetworking.registerGlobalReceiver(HelloPacket.PACKET_ID, (payload, context) -> {
ServerPlayNetworking.send(player, FEATURE_CHANNEL, this.makeFeatureBuffer(MidnightControlsFeature.HORIZONTAL_REACHAROUND)); 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, ServerPlayNetworking.registerGlobalReceiver(ControlsModePacket.PACKET_ID,
(server, player, handler, buf, responseSender) -> ControlsMode.byId(buf.readString(32)) (payload, context) -> ControlsMode.byId(payload.controlsMode())
.ifPresent(controlsMode -> server .ifPresent(controlsMode -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(context.player(), controlsMode)));
.execute(() -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(player, controlsMode))));
} }
/** /**
@@ -80,44 +83,6 @@ public class MidnightControls implements ModInitializer {
this.logger.info("[MidnightControls] " + warning); 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. * Gets the MidnightControls instance.
* *

View File

@@ -29,6 +29,9 @@ import eu.midnightdust.midnightcontrols.client.ring.MidnightRing;
import dev.lambdaurora.spruceui.hud.HudManager; import dev.lambdaurora.spruceui.hud.HudManager;
import eu.midnightdust.midnightcontrols.client.touch.TouchInput; import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
import eu.midnightdust.midnightcontrols.client.util.RainbowColor; 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.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; 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.ResourceManagerHelper;
import net.fabricmc.fabric.api.resource.ResourcePackActivationType; import net.fabricmc.fabric.api.resource.ResourcePackActivationType;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.option.KeyBinding; import net.minecraft.client.option.KeyBinding;
@@ -48,9 +52,7 @@ import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import java.io.File; import java.io.File;
import java.util.Objects; import java.util.*;
import java.util.Timer;
import java.util.TimerTask;
/** /**
* Represents the midnightcontrols client mod. * Represents the midnightcontrols client mod.
@@ -94,19 +96,19 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo
this.ring.registerAction("buttonbinding", ButtonBindingRingAction.FACTORY); this.ring.registerAction("buttonbinding", ButtonBindingRingAction.FACTORY);
ClientPlayNetworking.registerGlobalReceiver(CONTROLS_MODE_CHANNEL, (client, handler, buf, responseSender) -> ClientPlayNetworking.registerGlobalReceiver(CONTROLS_MODE_CHANNEL, (payload, context) ->
responseSender.sendPacket(CONTROLS_MODE_CHANNEL, this.makeControlsModeBuffer(MidnightControlsConfig.controlsMode))); context.responseSender().sendPacket(new ControlsModePacket(MidnightControlsConfig.controlsMode.getName())));
ClientPlayNetworking.registerGlobalReceiver(FEATURE_CHANNEL, (client, handler, buf, responseSender) -> { ClientPlayNetworking.registerGlobalReceiver(FeaturePacket.PACKET_ID, ((payload, context) -> {}));
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)));
}
});
ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> { ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> {
sender.sendPacket(HELLO_CHANNEL, this.makeHello(MidnightControlsConfig.controlsMode)); var version = "";
sender.sendPacket(CONTROLS_MODE_CHANNEL, this.makeControlsModeBuffer(MidnightControlsConfig.controlsMode)); 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); ClientPlayConnectionEvents.DISCONNECT.register(this::onLeave);
@@ -255,6 +257,7 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo
MidnightControlsConfig.controlsMode = this.previousControlsMode; MidnightControlsConfig.controlsMode = this.previousControlsMode;
} }
ClientPlayNetworking.getSender().sendPacket(new ControlsModePacket(MidnightControlsConfig.controlsMode.getName()));
} }
} }

View File

@@ -489,7 +489,7 @@ public class MidnightInput {
state = 1; state = 1;
asButtonState = 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.FluidBlock;
import net.minecraft.block.SlabBlock; import net.minecraft.block.SlabBlock;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.item.BlockItem; import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.hit.BlockHitResult;
@@ -74,7 +75,7 @@ public class MidnightReacharound {
} }
public static float getPlayerRange(@NotNull MinecraftClient client) { 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; package eu.midnightdust.midnightcontrols.client.compat;
import eu.midnightdust.lib.util.PlatformFunctions;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.ClassNode;
@@ -22,23 +23,16 @@ import java.util.Set;
/** /**
* This plugin is only present for the conditional mixins. * This plugin is only present for the conditional mixins.
* *
* @author LambdAurora * @author LambdAurora & Motschen
* @version 1.5.0 * @version 1.6.0
* @since 1.2.0 * @since 1.2.0
*/ */
public class MidnightControlsMixinPlugin implements IMixinConfigPlugin { public class MidnightControlsMixinPlugin implements IMixinConfigPlugin {
private final HashMap<String, Boolean> conditionalMixins = new HashMap<>(); private String mixinPackage;
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);
}
@Override @Override
public void onLoad(String mixinPackage) { public void onLoad(String mixinPackage) {
this.mixinPackage = mixinPackage + ".";
} }
@Override @Override
@@ -48,7 +42,13 @@ public class MidnightControlsMixinPlugin implements IMixinConfigPlugin {
@Override @Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { 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 @Override

View File

@@ -2,7 +2,7 @@ package eu.midnightdust.midnightcontrols.client.compat;
import eu.midnightdust.midnightcontrols.MidnightControls; import eu.midnightdust.midnightcontrols.MidnightControls;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; 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 me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI;
import net.minecraft.client.gui.screen.Screen; 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.SodiumOptionsGUI;
import me.jellysquid.mods.sodium.client.gui.options.OptionPage; import me.jellysquid.mods.sodium.client.gui.options.OptionPage;

View File

@@ -88,7 +88,7 @@ public class ButtonBinding {
public static final ButtonBinding SNEAK = new Builder("sneak").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_THUMB) public static final ButtonBinding SNEAK = new Builder("sneak").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_THUMB)
.actions(InputHandlers::handleToggleSneak).onlyInGame().cooldown().register(); .actions(InputHandlers::handleToggleSneak).onlyInGame().cooldown().register();
public static final ButtonBinding SPRINT = new Builder("sprint").buttons(GLFW_GAMEPAD_BUTTON_LEFT_THUMB) public static final ButtonBinding SPRINT = new Builder("sprint").buttons(GLFW_GAMEPAD_BUTTON_LEFT_THUMB)
.actions(InputHandlers::handleToggleSprint).onlyInGame().register(); .actions(InputHandlers::handleToggleSprint).onlyInGame().cooldown().register();
public static final ButtonBinding SWAP_HANDS = new Builder("swap_hands").buttons(GLFW_GAMEPAD_BUTTON_X).onlyInGame().cooldown().register(); public static final ButtonBinding SWAP_HANDS = new Builder("swap_hands").buttons(GLFW_GAMEPAD_BUTTON_X).onlyInGame().cooldown().register();
public static final ButtonBinding TAB_LEFT = new Builder("tab_back").buttons(GLFW_GAMEPAD_BUTTON_LEFT_BUMPER) public static final ButtonBinding TAB_LEFT = new Builder("tab_back").buttons(GLFW_GAMEPAD_BUTTON_LEFT_BUMPER)
.action(InputHandlers.handleHotbar(false)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements).or((client, binding) -> client.currentScreen != null)).cooldown().register(); .action(InputHandlers.handleHotbar(false)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements).or((client, binding) -> client.currentScreen != null)).cooldown().register();

View File

@@ -151,25 +151,17 @@ public record Controller(int id) implements Nameable {
private static boolean updateMappingsSync() { private static boolean updateMappingsSync() {
try { try {
MidnightControlsClient.get().log("Updating controller mappings..."); MidnightControlsClient.get().log("Updating controller mappings...");
File databaseFile = new File("config/gamecontrollerdatabase.txt"); Optional<File> databaseFile = getDatabaseFile();
try { if (databaseFile.isPresent()) {
BufferedInputStream in = new BufferedInputStream(new URL("https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt").openStream()); var database = ioResourceToBuffer(databaseFile.get().getPath(), 1024);
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(databaseFile)); if (database != null) GLFW.glfwUpdateGamepadMappings(database);
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);
if (!MidnightControlsClient.MAPPINGS_FILE.exists()) if (!MidnightControlsClient.MAPPINGS_FILE.exists())
return false; return false;
var buffer = ioResourceToBuffer(MidnightControlsClient.MAPPINGS_FILE.getPath(), 1024); var buffer = ioResourceToBuffer(MidnightControlsClient.MAPPINGS_FILE.getPath(), 1024);
if (buffer != null) GLFW.glfwUpdateGamepadMappings(buffer); if (buffer != null) GLFW.glfwUpdateGamepadMappings(buffer);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.fillInStackTrace();
} }
try (var memoryStack = MemoryStack.stackPush()) { try (var memoryStack = MemoryStack.stackPush()) {
@@ -182,8 +174,8 @@ public record Controller(int id) implements Nameable {
if (client != null) { if (client != null) {
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.PERIODIC_NOTIFICATION, client.getToastManager().add(SystemToast.create(client, SystemToast.Type.PERIODIC_NOTIFICATION,
Text.translatable("midnightcontrols.controller.mappings.error"), Text.literal(string))); 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) { } catch (Throwable e) {
/* Ignored :concern: */ /* Ignored :concern: */
@@ -205,4 +197,19 @@ public record Controller(int id) implements Nameable {
} }
return true; 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

@@ -320,12 +320,12 @@ public class InputHandlers {
boolean sprintToggled = client.options.getSprintToggled().getValue(); boolean sprintToggled = client.options.getSprintToggled().getValue();
if (client.player.getAbilities().flying && sprintToggled) if (client.player.getAbilities().flying && sprintToggled)
client.options.getSprintToggled().setValue(false); client.options.getSprintToggled().setValue(false);
else if (MidnightControlsConfig.controllerToggleSneak != sprintToggled) else if (MidnightControlsConfig.controllerToggleSprint != sprintToggled)
client.options.getSprintToggled().setValue(!sprintToggled); client.options.getSprintToggled().setValue(!sprintToggled);
binding.setPressed(button.pressed); binding.setPressed(button.pressed);
if (client.player.getAbilities().flying && sprintToggled) if (client.player.getAbilities().flying && sprintToggled)
client.options.getSprintToggled().setValue(true); client.options.getSprintToggled().setValue(true);
else if (MidnightControlsConfig.controllerToggleSneak != sprintToggled) else if (MidnightControlsConfig.controllerToggleSprint != sprintToggled)
client.options.getSprintToggled().setValue(sprintToggled); client.options.getSprintToggled().setValue(sprintToggled);
}); });
return true; return true;

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

View File

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

View File

@@ -10,14 +10,19 @@
package eu.midnightdust.midnightcontrols.client.mixin; package eu.midnightdust.midnightcontrols.client.mixin;
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen; 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.Screen;
import net.minecraft.client.gui.screen.option.ControlsOptionsScreen; import net.minecraft.client.gui.screen.option.ControlsOptionsScreen;
import net.minecraft.client.gui.screen.option.GameOptionsScreen; 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.gui.widget.TextIconButtonWidget;
import net.minecraft.client.option.GameOptions; import net.minecraft.client.option.GameOptions;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin; 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.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -27,14 +32,29 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
*/ */
@Mixin(ControlsOptionsScreen.class) @Mixin(ControlsOptionsScreen.class)
public abstract class ControlsOptionsScreenMixin extends GameOptionsScreen { 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;")) @Unique TextIconButtonWidget button = TextIconButtonWidget.builder(Text.translatable("midnightcontrols.menu.title.controller"), (button -> this.client.setScreen(new MidnightControlsSettingsScreen(this, false))), true)
private void addControllerButton(CallbackInfo ci) { .dimension(20,20).texture(new Identifier("midnightcontrols", "icon/controller"), 20, 20).build();
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(); @Inject(at = @At("TAIL"), method = "init")
iconWidget.setPosition(this.width / 2 + 158, this.height / 6 - 12); public void midnightcontrols$onInit(CallbackInfo ci) {
this.addDrawableChild(iconWidget); 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; package eu.midnightdust.midnightcontrols.client.mixin;
import com.llamalad7.mixinextras.sugar.Local;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import eu.midnightdust.midnightcontrols.ControlsMode; import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; 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.MinecraftClient;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.render.GameRenderer; 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.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(GameRenderer.class) @Mixin(GameRenderer.class)
public abstract class GameRendererMixin { public abstract class GameRendererMixin {
@@ -38,15 +38,16 @@ public abstract class GameRendererMixin {
if (this.client.currentScreen != null && MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) if (this.client.currentScreen != null && MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER)
MidnightControlsClient.get().input.onPreRenderScreen(this.client, this.client.currentScreen); 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) @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, boolean bl, MatrixStack matrixStack, DrawContext drawContext) { private void renderVirtualCursor(float tickDelta, long startTime, boolean tick, CallbackInfo ci, @Local DrawContext drawContext) {
MidnightControlsRenderer.renderVirtualCursor(drawContext, client); MidnightControlsRenderer.renderVirtualCursor(drawContext, client);
drawContext.draw(); drawContext.draw();
} }
@Inject(at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/GameRenderer;renderHand:Z", ordinal = 0), method = "renderWorld") @Inject(at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/GameRenderer;renderHand:Z"), method = "renderWorld")
private void postWorldRender(float tickDelta, long limitTime, MatrixStack matrix, CallbackInfo ci) { private void captureProjAndModMatrix(float tickDelta, long limitTime, CallbackInfo ci, @Local(ordinal = 1) Matrix4f matrices) {
TouchUtils.lastProjMat.set(RenderSystem.getProjectionMatrix()); TouchUtils.lastProjMat.set(RenderSystem.getProjectionMatrix());
TouchUtils.lastModMat.set(RenderSystem.getModelViewMatrix()); 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.Mouse;
import net.minecraft.client.util.GlfwUtil; import net.minecraft.client.util.GlfwUtil;
import net.minecraft.client.util.SmoothUtil; 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.lwjgl.glfw.GLFW;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; 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.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -51,7 +55,7 @@ public abstract class MouseMixin implements MouseAccessor {
@Shadow private boolean hasResolutionChanged; @Shadow private boolean hasResolutionChanged;
@Shadow private double lastMouseUpdateTime; @Shadow private double glfwTime;
@Shadow @Final private SmoothUtil cursorXSmoother; @Shadow @Final private SmoothUtil cursorXSmoother;
@@ -116,8 +120,8 @@ public abstract class MouseMixin implements MouseAccessor {
cursorYSmoother.clear(); cursorYSmoother.clear();
} }
EyeTrackerHandler.updateMouseWithEyeTracking(x + cursorDeltaX, y + cursorDeltaY, client, EyeTrackerHandler.updateMouseWithEyeTracking(x + cursorDeltaX, y + cursorDeltaY, client,
lastMouseUpdateTime, leftButtonClicked, cursorXSmoother, cursorYSmoother); glfwTime, leftButtonClicked, isUsingLongRangedTool(), cursorXSmoother, cursorYSmoother);
lastMouseUpdateTime = GlfwUtil.getTime(); glfwTime = GlfwUtil.getTime();
cursorDeltaX = 0.0; cursorDeltaX = 0.0;
cursorDeltaY = 0.0; cursorDeltaY = 0.0;
ci.cancel(); 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) @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) { private void midnightcontrols$lockCursor(CallbackInfo ci) {
if ((doMixedInput() || MidnightControlsConfig.eyeTrackerAsMouse)) { if ((doMixedInput() || MidnightControlsConfig.eyeTrackerAsMouse)) {

View File

@@ -9,6 +9,7 @@
package eu.midnightdust.midnightcontrols.client.mixin; package eu.midnightdust.midnightcontrols.client.mixin;
import com.llamalad7.mixinextras.sugar.Local;
import eu.midnightdust.lib.util.MidnightColorUtil; import eu.midnightdust.lib.util.MidnightColorUtil;
import eu.midnightdust.midnightcontrols.ControlsMode; import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
@@ -61,6 +62,7 @@ public abstract class WorldRendererMixin {
@Shadow @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) { 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;")) @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) { private HitResult.Type dontRenderOutline(HitResult instance) {
if (MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN && MidnightControlsConfig.touchMode == TouchMode.FINGER_POS) { if (MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN && MidnightControlsConfig.touchMode == TouchMode.FINGER_POS) {
@@ -78,8 +80,7 @@ public abstract class WorldRendererMixin {
shift = At.Shift.AFTER shift = At.Shift.AFTER
) )
) )
private void onOutlineRender(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, private void onOutlineRender(float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, Matrix4f matrix4f2, CallbackInfo ci, @Local MatrixStack matrices) {
LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) {
if (((MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.touchInControllerMode) || MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN) if (((MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.touchInControllerMode) || MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN)
&& MidnightControlsConfig.touchMode == TouchMode.FINGER_POS) { && MidnightControlsConfig.touchMode == TouchMode.FINGER_POS) {
this.renderFingerOutline(matrices, camera); this.renderFingerOutline(matrices, camera);

View File

@@ -15,6 +15,7 @@ public class EyeTrackerHandler {
MinecraftClient client, MinecraftClient client,
double lastMouseUpdateTime, double lastMouseUpdateTime,
boolean holdingLeftMouseButton, boolean holdingLeftMouseButton,
boolean usingLongRangedTool,
SmoothUtil smoothX, SmoothUtil smoothX,
SmoothUtil smoothY SmoothUtil smoothY
) { ) {
@@ -45,7 +46,7 @@ public class EyeTrackerHandler {
} else { } else {
frameScalar = moveScalar; frameScalar = moveScalar;
} }
if(holdingLeftMouseButton){ if(holdingLeftMouseButton && !usingLongRangedTool) {
frameScalar *= 0.5; //Don't move the camera so much while mining. It's annoying. 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()) { if (client.options.getInvertYMouse().getValue()) {
invertY = -1.0; 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.player.changeLookDirection(moveX, moveY * invertY);
client.getTutorialManager().onUpdateMouse(moveX, moveY); 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": { "depends": {
"fabricloader": ">=0.11.3", "fabricloader": ">=0.11.3",
"fabric": ">=0.71.0", "fabric": ">=0.71.0",
"minecraft": "~1.20", "minecraft": ">=1.20.5",
"spruceui": ">=3.2.0", "spruceui": ">=3.2.0",
"java": ">=17" "java": ">=17"
}, },
"recommends": {
"modmenu": ">=1.12.2"
},
"suggests": { "suggests": {
"kontrolo": "*" "kontrolo": "*"
}, },

View File

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