Skip to content

Commit 7d1137c

Browse files
committed
Merge branch 'multiversion/dev' into feature/splitscreen
# Conflicts: # src/main/java/dev/isxander/controlify/api/bind/InputBinding.java # src/main/java/dev/isxander/controlify/config/ControlifyConfig.java # src/main/java/dev/isxander/controlify/config/TypeAdapters.java # src/main/java/dev/isxander/controlify/controller/info/UIDComponent.java # src/main/java/dev/isxander/controlify/controller/input/InputComponent.java # src/main/java/dev/isxander/controlify/controllermanager/AbstractControllerManager.java # stonecutter.gradle.kts # versions/1.21.5-fabric/gradle.properties
2 parents 1cdf8e0 + aec7bb1 commit 7d1137c

439 files changed

Lines changed: 12447 additions & 5943 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/README.md

Lines changed: 35 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -25,54 +25,48 @@ Controlify Splitscreen is a **separate mod in development** that adds splitscree
2525

2626
![splitscreen demo](https://cdn.modrinth.com/data/cached_images/23ac6e3fc051e7aaa473ef3af2c510399d9448cc.png)
2727

28-
## What is Controlify?
29-
30-
Controlify is a mod that adds the best controller support to Minecraft: Java Edition. It aims to meet (or exceed) a console-like experience with support for as many controllers as possible, including their advanced features, such as vibration (rumble), gyro, HD haptics and vendor-specific buttons (like mute).
31-
32-
## Why Controlify?
33-
34-
### User friendly
35-
36-
Despite advanced settings available for power users, Controlify is beginner-friendly. It comes by default with
37-
button guides that appear across the whole game, helping you learn the controller layout. It also automatically detects
38-
your controller's make and model, displaying relevant Minecraft-style button textures for a more intuitive experience.
39-
Controlify "just works" out of the box, no need to spend tens of minutes getting your controller feeling like any other
40-
game, thanks to the sane defaults I have created.
41-
42-
### Feature-rich
28+
## [Wiki](https://moddedmc.wiki/project/controlify)
4329

44-
Controlify strives to support all the added features that may come with your controller.
30+
Read up on the [Controlify Wiki](https://moddedmc.wiki/project/controlify) for more information on how to use Controlify, how to configure it, and how to develop for it.
4531

46-
- It supports gyroscopes natively, allowing for precise movements.
47-
- It comes with vibration/rumble support, making your gameplay more immersive (this is even missing on Bedrock Edition!)
48-
- Soon, HD haptics support for DualSense controllers, something never seen outside a Playstation game.
49-
- Support for non-standard joysticks such as flight sticks, given a small amount of setup.
32+
## What is Controlify?
5033

51-
### Compatibility focus
34+
Controlify is the best controller support mod for Minecraft: Java Edition. It exceeds the first-party Bedrock Edition controller support in every way possible. It is feature-complete, with support for vibration, gyroscope, HD haptics, and more.
5235

53-
I, the developer have actively collaborated with fellow mod creators of performance mods like Sodium and Iris to
54-
ensure seamless controller functionality throughout these custom GUIs. This will mean a more friction-free environment
55-
that lets you focus on playing the game, instead of battling through the menus.
36+
Controlify supports *all* controllers, thanks to its usage of the [SDL3](https://libsdl.org/) library, which is the most advanced cross-platform input library available.
5637

57-
## Q&A
38+
Controlify is designed to be both user-friendly and feature-rich. It has sensible defaults, with default sensitivity matched to Bedrock Edition for easy transition, and a simple yet informative settings screen that allows you to tweak your experience to your liking.
5839

59-
### Does it support Steam Deck?
40+
## Feature overview
6041

61-
**Yes!** Controlify has been tested and is fully working on the Steam Deck, and works great.
62-
However, due to limitations with SteamOS, only Steam games can currently interface with the gyroscope and the
63-
back buttons directly, though [this is set to change in the coming months](https://github.com/libsdl-org/SDL/issues/9148)!
64-
For now, you can use Steam Input to convert the gyro into a mouse input, and map the back buttons to other, more common
65-
buttons.
42+
- **Vibration support**; Controlify vibrates your controller upon events such as taking damage, breaking blocks, lightning strikes.
43+
- **Gyroscope support**; Controlify can use the gyroscope in your controller for precise aiming.
44+
- **Vendor-specific input support**; Controlify supports reading paddles, mute buttons (and their LEDs), touchpads, and more, on some controllers including Xbox, DualSense and Steam Deck.
45+
- **GUI operation**: Controlify allows you to navigate all Minecraft GUIs with your controller, without needing a mouse or keyboard. This includes the inventory, out-of-game menus, and modded GUIs. It features cursor snapping in inventory screens, allowing you to use your controller without needing to be precise with your cursor movements.
46+
- **DualSense/DualShock support**; Controlify does not require any additional software for PlayStation controllers, even on Windows.
47+
- **Controller identification**; Controlify has bespoke button glyphs for many controller models, including Xbox, Playstation, Nintendo Switch, Steam Deck, and more.
48+
- **On-screen keyboard**; Controlify includes a fully functional on-screen keyboard that allows you to type with your controller - truly no keyboard needed!
49+
- **Radial menu**; Controlify features a configurable menu that allows you to bind less-used actions to a radial menu, saving up buttons.
50+
- **DualSense HD haptics** support; Controlify allows for advanced vibration effects on DualSense controllers.
51+
- **DualSense adaptive triggers support**; Controlify allows for advanced trigger effects on DualSense controllers.
52+
- **Data-driven design**; Controlify allows resource packs to change default bindings, theme button glyphs, on-screen button guides, on-screen keyboard layouts, add more controller models, and more.
53+
- **Steam Deck support**
54+
- **Mod compatibility**; Controlify has led the efforts to make controller support work seamlessly with mods like Sodium, Iris, Simple Voice Chat, Do A Barrel Roll, and more.
55+
- **Cross-platform and multi-version**; Controlify works on Fabric and NeoForge, and actively supports and updates for Minecraft versions 1.21.1 and above.
56+
- **Quick to update**; Controlify is updated even for Minecraft snapshots, although snapshot builds are only available to patreon members.
57+
- **Joystick support**; Controlify supports flight sticks, racing wheels, and other non-standard joysticks. Users of such devices have the option between mapping the joystick to a standard gamepad, or creating their own custom bindings and defaults and glyphs for the joystick, allowing for a fully-featured experience.
6658

67-
### Does it support my controller?
59+
## Who uses Controlify?
6860

69-
Controlify supports most controllers out of the box, any generic gamepad-like controller is bound to work fine, at
70-
least in a basic state, giving inputs. Though, more strange and uncommon controllers such as handhelds like the ROG
71-
Ally may be missing features such as gyroscope.
61+
The following is actual feedback I have received from users of Controlify, and I'm very proud to have been able to help them enjoy Minecraft in a way they couldn't before:
7262

73-
If you are having trouble getting your controller working correctly, you can
74-
[join my discord server](https://short.isxander.dev/discord) or consult
75-
[the wiki](https://docs.isxander.dev/controlify/users/controller-compatibility-guide) for assistance.
63+
- Couch gamers who want to sit back and relax playing their favourite edition of Minecraft.
64+
- First-time modded players who have previously played Minecraft on a console and don't want to learn how to use a keyboard and mouse.
65+
- People with accessibility requirements who cannot use a keyboard and mouse and/or requires an adaptive controller.
66+
- Parents who want to expose their kids to modded Minecraft in an accessible manner.
67+
- People who just prefer using a controller over a keyboard and mouse.
68+
- People who want to play local multiplayer with their friends and family using the companion [Splitscreen Mod](https://patreon.com/isxander)
69+
- Hopefully you!
7670

7771
## Features
7872

@@ -92,7 +86,7 @@ To save up some buttons on your controller, dedicate some less-used actions to t
9286
It is fully customizable through the settings and intuitive to use. Any modded keybind is
9387
compatible with this menu.
9488

95-
### Built-in gyro support
89+
### Gyro support
9690

9791
Controlify has built-in support for controller gyroscopes, allowing you to make fine movements in-game
9892
with your controller. This can be combined with [flick stick](https://www.reddit.com/r/gamedev/comments/bw5xct/flick_stick_is_a_new_way_to_control_3d_games_with/) to be able to use a controller without
@@ -149,15 +143,9 @@ meaning you don't have to worry about it.
149143

150144
![image of calibration screen](https://cdn.modrinth.com/data/DOUdJVEm/images/f5f8e2a0a05e61adb95dd919760b424165ca5d14.png)
151145

152-
## What is to come?
153-
154-
A few features in various points in the horizon are:
155-
156-
- Explicit Steam Deck support, with the ability to interface with its gyroscope and be able to handle its extra buttons on the back of the device.
157-
- A better way to change controller bindings, possibly a custom graphical GUI to pick what buttons do what actions, not the other way around.
158-
- Split-screen support of some degree.
159-
160146
## Backports?
161147

162148
This mod is only and will only be available for **1.19.4** and above, this is because in 1.19.4, Mojang
163149
introduced arrow key navigation which was easily ported to controller, below 1.19.4, this is not possible.
150+
151+
Controlify is currently actively supported for Minecraft versions 1.21.1 and above, and is compatible with both Fabric and NeoForge.

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ jobs:
4545
- name: Set up JDK
4646
uses: actions/setup-java@v4
4747
with:
48-
java-version: 21
48+
java-version: 25
4949
distribution: temurin
5050
- name: Make gradlew executable
5151
run: chmod +x ./gradlew

build.gradle.kts

Lines changed: 58 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ plugins {
66

77
id("me.modmuss50.mod-publish-plugin")
88
`maven-publish`
9+
id("com.gradleup.nmcp")
910

1011
id("dev.kikugie.postprocess.j52j") version "2.1-beta.3"
1112
}
@@ -101,6 +102,10 @@ dependencies {
101102
// Already included by YetAnotherConfigLib, but we need it too, so let's define explicit dep
102103
api("org.quiltmc.parsers:json:${property("deps.quiltparsers")}")
103104

105+
if (stonecutter.current.parsed < "1.21.11") {
106+
compileOnly("org.jspecify:jspecify:1.0.0")
107+
}
108+
104109
// sodium compat
105110
modDependency("sodium", { "maven.modrinth:sodium:$it" })
106111
// RSO compat
@@ -152,7 +157,7 @@ val nativeTargets = listOf(
152157
val nativeConfigurations = nativeTargets.associate { target ->
153158
target.configurationName to configurations.create(target.configurationName)
154159
}
155-
val nativeHashConfiguration = configurations.create("nativeHashes")
160+
val nativeHashConfiguration: Configuration = configurations.create("nativeHashes")
156161

157162
nativeTargets.forEach { target ->
158163
dependencies {
@@ -194,12 +199,7 @@ Include native libraries for SDL3 in the jar.
194199

195200
val releaseModVersion by tasks.registering {
196201
group = "controlify/versioned"
197-
198202
dependsOn("publishMods")
199-
200-
if (!project.publishMods.dryRun.get()) {
201-
dependsOn("publish")
202-
}
203203
}
204204
createActiveTask(releaseModVersion)
205205

@@ -243,42 +243,40 @@ publishMods {
243243
// modrinth and curseforge use different formats for snapshots. this can be expressed globally
244244
val stableMCVersions = versionList("pub.stableMC")
245245

246-
val modrinthId: String by project
247-
if (modrinthId.isNotBlank() && hasProperty("modrinth.token")) {
248-
modrinth {
249-
projectId.set(modrinthId)
250-
accessToken.set(findProperty("modrinth.token")?.toString())
251-
minecraftVersions.addAll(stableMCVersions)
252-
minecraftVersions.addAll(versionList("pub.modrinthMC"))
246+
modrinth {
247+
accessToken = secrets.gradleProperty("modrinth.accessToken")
253248

254-
announcementTitle = "Download $mcVersion for ${loader.replaceFirstChar { it.uppercase() }} from Modrinth"
249+
projectId = providers.gradleProperty("pub.modrinthId")
255250

256-
requires { slug.set("yacl") }
251+
minecraftVersions.addAll(stableMCVersions)
252+
minecraftVersions.addAll(versionList("pub.modrinthMC"))
257253

258-
if (modstitch.isLoom) {
259-
requires { slug.set("fabric-api") }
260-
optional { slug.set("modmenu") }
261-
}
254+
announcementTitle = "Download $mcVersion for ${loader.replaceFirstChar { it.uppercase() }} from Modrinth"
255+
256+
requires { slug.set("yacl") }
257+
258+
if (modstitch.isLoom) {
259+
requires { slug.set("fabric-api") }
260+
optional { slug.set("modmenu") }
262261
}
263262
}
264263

265-
val curseforgeId: String by project
266-
if (curseforgeId.isNotBlank() && hasProperty("curseforge.token")) {
267-
curseforge {
268-
projectId = curseforgeId
269-
projectSlug = findProperty("curseforgeSlug")!!.toString()
270-
accessToken = findProperty("curseforge.token")?.toString()
271-
minecraftVersions.addAll(stableMCVersions)
272-
minecraftVersions.addAll(versionList("pub.curseMC"))
264+
curseforge {
265+
accessToken = secrets.gradleProperty("curseforge.accessToken")
273266

274-
announcementTitle = "Download $mcVersion for ${loader.replaceFirstChar { it.uppercase() }} from CurseForge"
267+
projectId = providers.gradleProperty("pub.curseforgeId")
268+
projectSlug = providers.gradleProperty("pub.curseforgeSlug")
275269

276-
requires { slug.set("yacl") }
270+
minecraftVersions.addAll(stableMCVersions)
271+
minecraftVersions.addAll(versionList("pub.curseMC"))
277272

278-
if (modstitch.isLoom) {
279-
requires { slug.set("fabric-api") }
280-
optional { slug.set("modmenu") }
281-
}
273+
announcementTitle = "Download $mcVersion for ${loader.replaceFirstChar { it.uppercase() }} from CurseForge"
274+
275+
requires { slug.set("yacl") }
276+
277+
if (modstitch.isLoom) {
278+
requires { slug.set("fabric-api") }
279+
optional { slug.set("modmenu") }
282280
}
283281
}
284282
}
@@ -289,6 +287,33 @@ publishing {
289287

290288
artifactId = "controlify"
291289
groupId = "dev.isxander"
290+
291+
pom {
292+
name = modstitch.metadata.modName
293+
description = modstitch.metadata.modDescription
294+
url = "https://www.isxander.dev/projects/controlify"
295+
licenses {
296+
license {
297+
name = "LGPL-3.0-or-later"
298+
url = "https://www.gnu.org/licenses/lgpl-3.0.en.html"
299+
}
300+
}
301+
developers {
302+
developer {
303+
id = "isXander"
304+
name = "Xander"
305+
email = "business@isxander.dev"
306+
}
307+
}
308+
scm {
309+
url = "https://github.com/isXander/Controlify"
310+
connection = "scm:git:git//github.com/isXander/Controlify.git"
311+
developerConnection = "scm:git:ssh://git@github.com/isXander/Controlify.git"
312+
}
313+
}
292314
}
293315
}
294316
}
317+
signing {
318+
sign(publishing.publications["mod"])
319+
}

buildSrc/build.gradle.kts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
plugins {
22
`kotlin-dsl`
3-
kotlin("jvm") version "2.2.0"
3+
kotlin("jvm") version "2.2.21"
44
}
55

66
repositories {
@@ -30,8 +30,9 @@ repositories {
3030
dependencies {
3131
fun plugin(id: String, version: String) = "$id:$id.gradle.plugin:$version"
3232

33-
implementation(plugin("dev.isxander.modstitch.base", "0.7.0-unstable"))
34-
implementation(plugin("dev.kikugie.stonecutter", "0.7.6"))
35-
implementation(plugin("fabric-loom", "1.11.4"))
36-
implementation(plugin("net.neoforged.moddev", "2.0.103"))
33+
implementation(plugin("dev.isxander.modstitch.base", "0.8.4"))
34+
implementation(plugin("dev.isxander.secrets", "0.1.0"))
35+
implementation(plugin("dev.kikugie.stonecutter", "0.8.2"))
36+
implementation(plugin("fabric-loom", "1.14.9"))
37+
implementation(plugin("net.neoforged.moddev", "2.0.137"))
3738
}

buildSrc/src/main/kotlin/dev/isxander/controlify/project.gradle.kts

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ package dev.isxander.controlify
33
import net.fabricmc.loom.task.prod.ClientProductionRunTask
44

55
plugins {
6+
`java-library`
67
id("dev.isxander.modstitch.base")
78
`maven-publish`
8-
`java-library`
9+
signing
10+
id("dev.isxander.secrets")
911
}
1012

1113
modstitch.apply {
1214
minecraftVersion = mcVersion
13-
javaVersion = 21
1415

1516
parchment {
1617
propMap("parchment.version") { mappingsVersion = it }
@@ -92,6 +93,10 @@ if (modstitch.isLoom) {
9293

9394
java {
9495
withSourcesJar()
96+
withJavadocJar()
97+
}
98+
tasks.javadoc {
99+
isFailOnError = false
95100
}
96101

97102
/*
@@ -101,18 +106,32 @@ stonecutter.apply {
101106
constants {
102107
put("fabric", modstitch.isLoom)
103108
put("neoforge", modstitch.isModDevGradleRegular)
104-
put("immediately-fast", isPropDefined("deps.immediatelyFast"))
109+
put("immediately_fast", isPropDefined("deps.immediatelyFast"))
105110
put("iris", isPropDefined("deps.iris"))
106-
put("mod-menu", isPropDefined("deps.modMenu"))
111+
put("mod_menu", isPropDefined("deps.modMenu"))
107112
put("sodium", isPropDefined("deps.sodium"))
108-
put("simple-voice-chat", isPropDefined("deps.simpleVoiceChat"))
109-
put("reeses-sodium-options", isPropDefined("deps.reesesSodiumOptions"))
110-
put("fancy-menu", isPropDefined("deps.fancyMenu"))
113+
put("simple_voice_chat", isPropDefined("deps.simpleVoiceChat"))
114+
put("reeses_sodium_options", isPropDefined("deps.reesesSodiumOptions"))
115+
put("fancy_menu", isPropDefined("deps.fancyMenu"))
116+
117+
put("unobf", eval(current.version, ">=26"))
118+
put("intermediary_lambdas", !eval(current.version, ">=26") && !modstitch.isModDevGradle)
111119
}
112120

113121
dependencies {
114122
put("fapi", prop("deps.fabricApi") ?: "0.0.0")
115123
}
124+
125+
replacements {
126+
string {
127+
direction = eval(current.version, ">=1.21.11")
128+
replace("ResourceLocation", "Identifier")
129+
}
130+
string {
131+
direction = eval(current.version, ">=1.21.11")
132+
replace("import net.minecraft.Util;", "import net.minecraft.util.Util;")
133+
}
134+
}
116135
}
117136

118137
tasks.named<ProcessResources>("generateModMetadata") {
@@ -124,20 +143,23 @@ tasks.named<ProcessResources>("generateModMetadata") {
124143
}
125144
}
126145

127-
publishing {
128-
repositories {
129-
val username = prop("XANDER_MAVEN_USER")
130-
val password = prop("XANDER_MAVEN_PASS")
131-
if (username != null && password != null) {
132-
maven(url = "https://maven.isxander.dev/releases") {
133-
name = "XanderReleases"
134-
credentials {
135-
this.username = username
136-
this.password = password
137-
}
146+
val signingKeyProvider = secrets.gradleProperty("signing.secretKey")
147+
val signingPasswordProvider = secrets.gradleProperty("signing.password")
148+
// not configuration cache friendly, but neither is the whole of signing plugin
149+
// this plugin does not support lazy configuration of signing keys
150+
gradle.taskGraph.whenReady {
151+
val willSign = allTasks.any { it.name.startsWith("sign") }
152+
if (willSign) {
153+
signing {
154+
val signingKey = signingKeyProvider.orNull
155+
val signingPassword = signingPasswordProvider.orNull
156+
157+
isRequired = signingKey != null && signingPassword != null
158+
if (isRequired) {
159+
useInMemoryPgpKeys(signingKey, signingPassword)
160+
} else {
161+
logger.error("Signing keys not found; skipping signing!")
138162
}
139-
} else {
140-
logger.warn("Xander Maven credentials not satisfied.")
141163
}
142164
}
143165
}

0 commit comments

Comments
 (0)