forked from Clones/Controlify
fix bugs:
fix reconnecting controllers are unidentified fix some mod keybinds failing to register fix crash with unmapped joysticks
This commit is contained in:
@ -13,7 +13,7 @@ quilt_mappings = "10"
|
|||||||
fabric_loader = "0.14.19"
|
fabric_loader = "0.14.19"
|
||||||
fabric_api = "0.78.0+1.19.4"
|
fabric_api = "0.78.0+1.19.4"
|
||||||
mixin_extras = "0.2.0-beta.6"
|
mixin_extras = "0.2.0-beta.6"
|
||||||
yet_another_config_lib = "2.4.2"
|
yet_another_config_lib = "2.5.0+1.19.4"
|
||||||
mod_menu = "6.1.0-rc.4"
|
mod_menu = "6.1.0-rc.4"
|
||||||
hid4java = "0.7.0"
|
hid4java = "0.7.0"
|
||||||
quilt_json5 = "1.0.3"
|
quilt_json5 = "1.0.3"
|
||||||
@ -28,7 +28,7 @@ fabric_loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric_l
|
|||||||
|
|
||||||
fabric_api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric_api" }
|
fabric_api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric_api" }
|
||||||
mixin_extras = { module = "com.github.llamalad7.mixinextras:mixinextras-fabric", version.ref = "mixin_extras" }
|
mixin_extras = { module = "com.github.llamalad7.mixinextras:mixinextras-fabric", version.ref = "mixin_extras" }
|
||||||
yet_another_config_lib = { module = "dev.isxander:yet-another-config-lib", version.ref = "yet_another_config_lib" }
|
yet_another_config_lib = { module = "dev.isxander.yacl:yet-another-config-lib-fabric", version.ref = "yet_another_config_lib" }
|
||||||
mod_menu = { module = "com.terraformersmc:modmenu", version.ref = "mod_menu" }
|
mod_menu = { module = "com.terraformersmc:modmenu", version.ref = "mod_menu" }
|
||||||
hid4java = { module = "org.hid4java:hid4java", version.ref = "hid4java" }
|
hid4java = { module = "org.hid4java:hid4java", version.ref = "hid4java" }
|
||||||
quilt_json5 = { module = "org.quiltmc:quilt-json5", version.ref = "quilt_json5" }
|
quilt_json5 = { module = "org.quiltmc:quilt-json5", version.ref = "quilt_json5" }
|
||||||
|
@ -7,10 +7,10 @@
|
|||||||
| **Controller rumble** | ✅ Individual rumble effect intensity configuration | ⛔ Not present. |
|
| **Controller rumble** | ✅ Individual rumble effect intensity configuration | ⛔ Not present. |
|
||||||
| **In-game button guide** | Extensible by 3rd party mods | Harcoded buttons and positions |
|
| **In-game button guide** | Extensible by 3rd party mods | Harcoded buttons and positions |
|
||||||
| **Reach-around block placement** | ✅ Emulates Bedrock Edition reach-around | ✅ Takes custom liberties and has behaviour not present in bedrock |
|
| **Reach-around block placement** | ✅ Emulates Bedrock Edition reach-around | ✅ Takes custom liberties and has behaviour not present in bedrock |
|
||||||
| **Gyro support** | ✅ Option to require a button held and flick stick. Bypasses some sensitivity modifiers. | ⛔ Only works with Steam Deck due to Steam Input emulation |
|
| **Gyro support** | ✅ Supported on all controllers with native gyro. | ⛔ Only works with Steam Deck due to Steam Input emulation |
|
||||||
| **Controller detection** | Powered by resource packs for unlimited data-driven detection | Hardcoded identifiers in code |
|
| **Controller detection** | Powered by resource packs for unlimited data-driven detection | Hardcoded identifiers in code |
|
||||||
| **Controller button rendering** | Powered by resource pack controller detection | Texture atlas for hardcoded identifiers |
|
| **Controller button rendering** | Powered by resource pack controller detection | Texture atlas for hardcoded identifiers |
|
||||||
| **In-game look sensitivity & behaviour** | Emulated Bedrock Edition with good defaults and snappy behaviour | testing required - reported bad defaults |
|
| **In-game look sensitivity & behaviour** | Emulated Bedrock Edition with good defaults and snappy behaviour | Default sensitivity is insane - more testing required |
|
||||||
| **Container interaction** | Controlled cursor snaps to container slots (with API) with power of left click, right click and shift click | No slot snapping, testing required |
|
| **Container interaction** | Controlled cursor snaps to container slots (with API) with power of left click, right click and shift click | No slot snapping, testing required |
|
||||||
| **Touchscreen support** | ⛔ | ✅ No multi-touch support |
|
| **Touchscreen support** | ⛔ | ✅ No multi-touch support |
|
||||||
| **Joystick support** | ✅ Multiple joysticks can be combined together (no UI yet) | ✅ Multiple joysticks can be combined together |
|
| **Joystick support** | ✅ Multiple joysticks can be combined together (no UI yet) | ✅ Multiple joysticks can be combined together |
|
||||||
|
@ -298,6 +298,8 @@ public class Controlify implements ControlifyApi {
|
|||||||
Controller.CONTROLLERS.values().stream().filter(controller -> controller.joystickId() == jid).findAny().ifPresent(controller -> {
|
Controller.CONTROLLERS.values().stream().filter(controller -> controller.joystickId() == jid).findAny().ifPresent(controller -> {
|
||||||
Controller.remove(controller);
|
Controller.remove(controller);
|
||||||
|
|
||||||
|
controller.hidInfo().ifPresent(controllerHIDService::unconsumeController);
|
||||||
|
|
||||||
setCurrentController(Controller.CONTROLLERS.values().stream().findFirst().orElse(null));
|
setCurrentController(Controller.CONTROLLERS.values().stream().findFirst().orElse(null));
|
||||||
LOGGER.info("Controller disconnected: " + controller.name());
|
LOGGER.info("Controller disconnected: " + controller.name());
|
||||||
this.setInputMode(currentController == null ? InputMode.KEYBOARD_MOUSE : InputMode.CONTROLLER);
|
this.setInputMode(currentController == null ? InputMode.KEYBOARD_MOUSE : InputMode.CONTROLLER);
|
||||||
|
@ -17,6 +17,13 @@ import java.util.Optional;
|
|||||||
* Anything that is asked for from this API is safe to use, even if it is not in the API package.
|
* Anything that is asked for from this API is safe to use, even if it is not in the API package.
|
||||||
*/
|
*/
|
||||||
public interface ControlifyApi {
|
public interface ControlifyApi {
|
||||||
|
/**
|
||||||
|
* The controller that is currently enabled and in use.
|
||||||
|
* If there is no controller disconnected or disabled, this will return {@link Optional#empty()}.
|
||||||
|
* This is the controller that is used for {@link dev.isxander.controlify.api.event.ControlifyEvents#ACTIVE_CONTROLLER_TICKED}
|
||||||
|
*/
|
||||||
|
@NotNull Optional<Controller<?, ?>> getCurrentController();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use {@link #getCurrentController()} instead.
|
* @deprecated Use {@link #getCurrentController()} instead.
|
||||||
* @return the controller currently in use. If disabled, this will return {@link Controller#DUMMY}
|
* @return the controller currently in use. If disabled, this will return {@link Controller#DUMMY}
|
||||||
@ -24,10 +31,8 @@ public interface ControlifyApi {
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
@NotNull Controller<?, ?> currentController();
|
@NotNull Controller<?, ?> currentController();
|
||||||
|
|
||||||
@NotNull Optional<Controller<?, ?>> getCurrentController();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current input mode for the game.
|
* The last input received: a controller or keyboard/mouse.
|
||||||
*/
|
*/
|
||||||
@NotNull InputMode currentInputMode();
|
@NotNull InputMode currentInputMode();
|
||||||
boolean setInputMode(@NotNull InputMode mode);
|
boolean setInputMode(@NotNull InputMode mode);
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
package dev.isxander.controlify.api.bind;
|
package dev.isxander.controlify.api.bind;
|
||||||
|
|
||||||
import dev.isxander.controlify.controller.Controller;
|
import dev.isxander.controlify.controller.Controller;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface BindingSupplier {
|
public interface BindingSupplier {
|
||||||
ControllerBinding onController(Controller<?, ?> controller);
|
ControllerBinding onController(@NotNull Controller<?, ?> controller);
|
||||||
}
|
}
|
||||||
|
@ -417,7 +417,12 @@ public class ControllerBindings<T extends ControllerState> {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var identifier = new ResourceLocation("fabric-key-binding-api-v1", keyMapping.getName());
|
var idPath = keyMapping.getName()
|
||||||
|
.toLowerCase()
|
||||||
|
.replaceAll("[^a-z0-9/._-]", "_")
|
||||||
|
.trim();
|
||||||
|
|
||||||
|
var identifier = new ResourceLocation("fabric-key-binding-api-v1", idPath);
|
||||||
BooleanSupplier toggleOverride = () -> false;
|
BooleanSupplier toggleOverride = () -> false;
|
||||||
if (keyMapping instanceof ToggleKeyMapping toggleKeyMapping) {
|
if (keyMapping instanceof ToggleKeyMapping toggleKeyMapping) {
|
||||||
toggleOverride = ((ToggleKeyMappingAccessor) toggleKeyMapping).getNeedsToggle();
|
toggleOverride = ((ToggleKeyMappingAccessor) toggleKeyMapping).getNeedsToggle();
|
||||||
|
@ -16,6 +16,7 @@ import org.libsdl.SDL;
|
|||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public abstract class AbstractController<S extends ControllerState, C extends ControllerConfig> implements Controller<S, C>, RumbleCapable {
|
public abstract class AbstractController<S extends ControllerState, C extends ControllerConfig> implements Controller<S, C>, RumbleCapable {
|
||||||
@ -24,6 +25,7 @@ public abstract class AbstractController<S extends ControllerState, C extends Co
|
|||||||
private final String uid;
|
private final String uid;
|
||||||
private final String guid;
|
private final String guid;
|
||||||
private final ControllerType type;
|
private final ControllerType type;
|
||||||
|
private final ControllerHIDService.ControllerHIDInfo hidInfo;
|
||||||
|
|
||||||
protected ControllerBindings<S> bindings;
|
protected ControllerBindings<S> bindings;
|
||||||
protected C config, defaultConfig;
|
protected C config, defaultConfig;
|
||||||
@ -34,6 +36,8 @@ public abstract class AbstractController<S extends ControllerState, C extends Co
|
|||||||
if (!GLFW.glfwJoystickPresent(joystickId))
|
if (!GLFW.glfwJoystickPresent(joystickId))
|
||||||
throw new IllegalArgumentException("Joystick " + joystickId + " is not present and cannot be initialised!");
|
throw new IllegalArgumentException("Joystick " + joystickId + " is not present and cannot be initialised!");
|
||||||
|
|
||||||
|
this.hidInfo = hidInfo;
|
||||||
|
|
||||||
this.joystickId = joystickId;
|
this.joystickId = joystickId;
|
||||||
this.guid = GLFW.glfwGetJoystickGUID(joystickId);
|
this.guid = GLFW.glfwGetJoystickGUID(joystickId);
|
||||||
|
|
||||||
@ -121,6 +125,11 @@ public abstract class AbstractController<S extends ControllerState, C extends Co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<ControllerHIDService.ControllerHIDInfo> hidInfo() {
|
||||||
|
return Optional.of(hidInfo);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
@ -48,6 +48,8 @@ public interface Controller<S extends ControllerState, C extends ControllerConfi
|
|||||||
RumbleManager rumbleManager();
|
RumbleManager rumbleManager();
|
||||||
boolean canRumble();
|
boolean canRumble();
|
||||||
|
|
||||||
|
Optional<ControllerHIDService.ControllerHIDInfo> hidInfo();
|
||||||
|
|
||||||
default boolean canBeUsed() {
|
default boolean canBeUsed() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -156,6 +158,11 @@ public interface Controller<S extends ControllerState, C extends ControllerConfi
|
|||||||
return ControllerType.UNKNOWN;
|
return ControllerType.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<ControllerHIDService.ControllerHIDInfo> hidInfo() {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String name() {
|
public String name() {
|
||||||
return "DUMMY";
|
return "DUMMY";
|
||||||
|
@ -105,6 +105,10 @@ public class ControllerHIDService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void unconsumeController(ControllerHIDInfo hid) {
|
||||||
|
hid.hidDevice.ifPresent(device -> attachedDevices.remove(device.getPath()));
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isController(HidDevice device) {
|
private boolean isController(HidDevice device) {
|
||||||
boolean isControllerType = ControllerType.getTypeMap().containsKey(new HIDIdentifier(device.getVendorId(), device.getProductId()));
|
boolean isControllerType = ControllerType.getTypeMap().containsKey(new HIDIdentifier(device.getVendorId(), device.getProductId()));
|
||||||
boolean isGenericDesktopControlOrGameControl = device.getUsagePage() == 0x1 || device.getUsagePage() == 0x5;
|
boolean isGenericDesktopControlOrGameControl = device.getUsagePage() == 0x1 || device.getUsagePage() == 0x5;
|
||||||
|
@ -6,6 +6,7 @@ import com.google.gson.JsonElement;
|
|||||||
import dev.isxander.controlify.Controlify;
|
import dev.isxander.controlify.Controlify;
|
||||||
import dev.isxander.controlify.bindings.ControllerBindings;
|
import dev.isxander.controlify.bindings.ControllerBindings;
|
||||||
import dev.isxander.controlify.controller.ControllerType;
|
import dev.isxander.controlify.controller.ControllerType;
|
||||||
|
import dev.isxander.controlify.controller.hid.ControllerHIDService;
|
||||||
import dev.isxander.controlify.controller.joystick.mapping.JoystickMapping;
|
import dev.isxander.controlify.controller.joystick.mapping.JoystickMapping;
|
||||||
import dev.isxander.controlify.controller.joystick.mapping.RPJoystickMapping;
|
import dev.isxander.controlify.controller.joystick.mapping.RPJoystickMapping;
|
||||||
import dev.isxander.controlify.rumble.RumbleCapable;
|
import dev.isxander.controlify.rumble.RumbleCapable;
|
||||||
@ -14,6 +15,7 @@ import dev.isxander.controlify.rumble.RumbleSource;
|
|||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class CompoundJoystickController implements JoystickController<JoystickConfig>, RumbleCapable {
|
public class CompoundJoystickController implements JoystickController<JoystickConfig>, RumbleCapable {
|
||||||
private final String uid;
|
private final String uid;
|
||||||
@ -177,4 +179,9 @@ public class CompoundJoystickController implements JoystickController<JoystickCo
|
|||||||
private int getHatCountForJoystick(int joystick) {
|
private int getHatCountForJoystick(int joystick) {
|
||||||
return GLFW.glfwGetJoystickHats(joystick).capacity();
|
return GLFW.glfwGetJoystickHats(joystick).capacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<ControllerHIDService.ControllerHIDInfo> hidInfo() {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ public class UnmappedJoystickMapping implements JoystickMapping {
|
|||||||
this.axes[i] = new UnmappedAxis(i, new GenericRenderer.Axis(Integer.toString(i + 1)));
|
this.axes[i] = new UnmappedAxis(i, new GenericRenderer.Axis(Integer.toString(i + 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.buttons = new UnmappedButton[axisCount];
|
this.buttons = new UnmappedButton[buttonCount];
|
||||||
for (int i = 0; i < buttonCount; i++) {
|
for (int i = 0; i < buttonCount; i++) {
|
||||||
this.buttons[i] = new UnmappedButton(i, new GenericRenderer.Button(Integer.toString(i + 1)));
|
this.buttons[i] = new UnmappedButton(i, new GenericRenderer.Button(Integer.toString(i + 1)));
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import dev.isxander.controlify.Controlify;
|
|||||||
import dev.isxander.controlify.bindings.ControllerBindings;
|
import dev.isxander.controlify.bindings.ControllerBindings;
|
||||||
import dev.isxander.controlify.controller.Controller;
|
import dev.isxander.controlify.controller.Controller;
|
||||||
import dev.isxander.controlify.controller.ControllerType;
|
import dev.isxander.controlify.controller.ControllerType;
|
||||||
|
import dev.isxander.controlify.controller.hid.ControllerHIDService;
|
||||||
import dev.isxander.controlify.controller.joystick.JoystickConfig;
|
import dev.isxander.controlify.controller.joystick.JoystickConfig;
|
||||||
import dev.isxander.controlify.controller.joystick.JoystickController;
|
import dev.isxander.controlify.controller.joystick.JoystickController;
|
||||||
import dev.isxander.controlify.controller.joystick.JoystickState;
|
import dev.isxander.controlify.controller.joystick.JoystickState;
|
||||||
@ -16,6 +17,7 @@ import dev.isxander.controlify.rumble.RumbleManager;
|
|||||||
import dev.isxander.controlify.rumble.RumbleSource;
|
import dev.isxander.controlify.rumble.RumbleSource;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class FakeController implements JoystickController<JoystickConfig> {
|
public class FakeController implements JoystickController<JoystickConfig> {
|
||||||
public static int JOYSTICK_COUNT = 0;
|
public static int JOYSTICK_COUNT = 0;
|
||||||
@ -139,6 +141,11 @@ public class FakeController implements JoystickController<JoystickConfig> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<ControllerHIDService.ControllerHIDInfo> hidInfo() {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JoystickMapping mapping() {
|
public JoystickMapping mapping() {
|
||||||
return UnmappedJoystickMapping.EMPTY;
|
return UnmappedJoystickMapping.EMPTY;
|
||||||
|
Reference in New Issue
Block a user