-
-
Notifications
You must be signed in to change notification settings - Fork 59
Improve public API docs #706
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: multiversion/dev
Are you sure you want to change the base?
Changes from all commits
f964f77
89ca0c4
8cc5f99
4263699
a3d22b0
f6b51ed
4f892cc
fec28f1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,40 +7,54 @@ _Learn how to register new controller bindings._ | |
| ## Registering a custom input binding | ||
|
|
||
| <Callout variant="info"> | ||
| You should register bindings inside of the Controlify init entrypoint. Read more in [Controlify Entrypoint](controlify-entrypoint#using-the-entrypoint). | ||
| The custom input bindings must be registered inside the Controlify pre-init entrypoint. Read more in [Controlify Entrypoint](controlify-entrypoint#using-the-entrypoint). | ||
| </Callout> | ||
|
|
||
| Controlify allows users to configure different buttons on their controllers to actions in-game. You may want your own mod's actions to be able to be invoked from the controller too. | ||
|
|
||
| To register a controller binding, you must use the `ControllerBindingsApi.` | ||
| To register a controller binding, use the `ControlifyBindApi.get()` method: | ||
|
|
||
| ```java | ||
| private BindingSupplier action1Binding; | ||
| private InputBindingSupplier actionBinding; | ||
|
|
||
| @Override | ||
| public void onControlifyInit(InitContext ctx) { | ||
| action1Binding = ctx.bindings().registerBinding( | ||
| final ControlifyBindApi registrar = ControlifyBindApi.get(); | ||
| registerInputBindings(registrar); | ||
| } | ||
|
|
||
| private void registerInputBindings(ControlifyBindApi registrar) { | ||
| actionBinding = registrar.registerBinding( | ||
| builder -> builder | ||
| .id("mymod", "action1") // the id of the binding, this should be unique to your mod | ||
| .category(Component.translatable("mymod.binding.category")) // the category of the binding, this is used to group bindings together in the settings | ||
| .allowedContexts(BindContext.IN_GAME) // a context is where the binding can be used, you can use multiple contexts | ||
| .radialCandiate(RadialIcons.getEffect/getIcon(...)) // if you want to allow your binding to be used in the radial menu | ||
| .id(ResourceLocation.fromNamespaceAndPath(MyMod.MODID, path)) | ||
| // The category of the binding, this is used to group bindings together in the settings. | ||
| .category(Component.translatable("mymod.binding.category")) | ||
| // A context is where the binding can be used. Multiple contexts can be used. | ||
| // For example, using `BindContext.IN_GAME` will cause the binding to always return | ||
| // `false` inside a screen, even if it's pressed. | ||
| .allowedContexts(BindContext.IN_GAME) | ||
| // Allow using the binding in the radial menu. | ||
| // You can't use a custom modded item directly in here, since it's not registered yet | ||
| // and a runtime error will be thrown. Continue reading for a better alternative. | ||
| .radialCandidate(RadialIcons.getItem(Items.BARRIER))) | ||
| // Prevents Controlify from auto-registering controller bindings for the | ||
| // vanilla key mappings due to explicit native support. | ||
| .addKeyCorrelation(MyModKeyMappings.ACTION) | ||
| // Emulates the vanilla KeyMapping behavior. | ||
| // Note: "keyEmulation" calls "addKeyCorrelation" internally, so no need to call both. | ||
| // | ||
| // It will not work with key mappings that are handled using NeoForge `InputEvent`s. | ||
| // It such cases, you can fix the problem either by: | ||
| // 1. Patch the mod to migrate to vanilla `KeyMapping` handling (example: https://github.com/iron431/irons-spells-n-spellbooks/pull/989). | ||
| // 2. Provide explicit Controlify support. | ||
| .keyEmulation(MyModKeyMappings.ACTION) | ||
|
Comment on lines
+49
to
+50
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Option 2 means no key emulation, and therefore, only I will improve this part soon. |
||
| ); | ||
| } | ||
| ``` | ||
|
|
||
| To add a name and description to the binding, you need to define the language keys `controlify.binding.<namespace>.<path>` and `controlify.binding.<namespace>.<path>.desc` respectively, alternatively, you can set `.name(Component)` and `.description(Component)` | ||
|
|
||
| Registering the binding provides you with a `BindingSupplier`, where you can then access the binding with `action1Binding.on(controller);` | ||
|
|
||
| Controlify automatically converts your existed modded `KeyMapping`s to controller bindings, but relying on this behaviour if you are going to explicitly support Controlify is not recommended. You can stop this conversion with the following... | ||
|
|
||
| ```java | ||
| @Override | ||
| public void onControlifyInit(InitContext ctx) { | ||
| ctx.bindings().exclude(MyMod.myKeyMapping); | ||
| } | ||
| ``` | ||
| Registering the binding provides you with a `InputBindingSupplier`, where you can then access the binding with `actionBinding.on(controller);` | ||
|
|
||
| ## Defining a default binding | ||
|
|
||
|
|
@@ -83,3 +97,63 @@ There are more properties available inside of `InputBinding` which you can look | |
| There is nothing special about rendering glyphs for controller bindings, as Controlify utilises custom fonts. | ||
|
|
||
| This means you can use the glyphs within localised text, or just render it with `graphics.drawString(myBinding.inputGlyph(), x, y, -1);` | ||
|
|
||
| ## Registering Custom Radial Icons | ||
|
|
||
| When registering a radial menu candidate, you must provide an icon to render it in the GUI. | ||
| You can use `RadialIcons.getEffect(...)` or `RadialIcons.getItem(...)` (for example, `RadialIcons.getItem(Items.REDSTONE)`). | ||
|
|
||
| However, **do not reference modded items directly** (e.g., `RadialIcons.getItem(ModItems.CUSTOM.get())`), | ||
| as item registration is deferred — meaning those items are not yet registered at this stage. | ||
|
|
||
| What you can do instead, is to reference the texture image file in the bundled resource-pack of your mod, | ||
| using the following approach: | ||
|
|
||
| ```java | ||
| private enum MyRadialIcons { | ||
| CUSTOM(MyMod.rl("textures/item/custom.png")),; | ||
|
|
||
| private final @NotNull ResourceLocation id; | ||
|
|
||
| MyRadialIcons(@NotNull ResourceLocation id) { | ||
| this.id = id; | ||
| } | ||
|
Comment on lines
+114
to
+120
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| public @NotNull ResourceLocation getId() { | ||
| return id; | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public void onControlifyPreInit(PreInitContext context) { | ||
| final ControlifyBindApi registrar = ControlifyBindApi.get(); | ||
| registerCustomRadialIcons(); | ||
|
|
||
| // Must be called after registerCustomRadialIcons | ||
| registerInputBindings(registrar); | ||
| } | ||
|
|
||
| private void registerCustomRadialIcons() { | ||
| for (MyRadialIcons icon : MyRadialIcons.values()) { | ||
| final ResourceLocation location = icon.getId(); | ||
|
|
||
| // For consistency with the current Controlify radial icons, | ||
| // this code is equivalent to: | ||
| // https://github.com/isXander/Controlify/blob/f5c94c57d5e0d4954e413624a0d7ead937b6e8ab/src/main/java/dev/isxander/controlify/bindings/RadialIcons.java#L106-L112 | ||
| RadialIcons.registerIcon(location, (graphics, x, y, tickDelta) -> { | ||
| var pose = CGuiPose.ofPush(graphics); | ||
| pose.translate(x, y); | ||
| pose.scale(0.5f, 0.5f); | ||
| Blit.tex(graphics, location, 0, 0, 0, 0, 32, 32, 32, 32); | ||
| pose.pop(); | ||
| }); | ||
| } | ||
| } | ||
|
Comment on lines
+140
to
+151
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be worth considering making a public API that provides this functionality. |
||
|
|
||
| private void registerInputBindings(ControlifyBindApi registrar) { | ||
| actionBinding = registrar.registerBinding( | ||
| builder -> builder | ||
| .radialCandidate(MyRadialIcons.CUSTOM.getId()) | ||
| ); | ||
| } | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,26 +6,70 @@ _Learn how to hook into Controlify._ | |
|
|
||
| Controlify provides a Fabric entrypoint to hook into important lifecycle stages of Controlify. You do this just like `ClientModInitializer`. | ||
|
|
||
| ## Registering the entrypoint | ||
| ## Adding Controlify dependency | ||
|
|
||
| In your `build.gradle` (or `build.gradle.kts`), you need to add the maven | ||
| repository and the Controlify mod dependency. | ||
|
|
||
| - On Fabric, you register an entrypoint like any other, by adding an entry to your `fabric.mod.json` file under the `entrypoints` section. | ||
| - On NeoForge, you register an entrypoint using a Java service provider interface (SPI) in your `META-INF/services` directory. | ||
|
|
||
| <CodeTabs> | ||
| ```json !!tabs (Fabric) fabric.mod.json | ||
| { | ||
| "entrypoints": { | ||
| "controlify": [ | ||
| "com.example.mymod.ControlifyEntrypoint" | ||
| ] | ||
| } | ||
| <details> | ||
| <summary>Maven repository</summary> | ||
|
|
||
| ```kotlin | ||
| repositories { | ||
| exclusiveContent { | ||
| forRepository { maven { url "https://maven.isxander.dev/releases" } } | ||
| filter { includeGroup "dev.isxander" } | ||
| } | ||
| ``` | ||
| } | ||
| ``` | ||
|
|
||
| </details> | ||
|
|
||
| <details> | ||
| <summary>Dependency</summary> | ||
|
|
||
| ```txt !!tabs (NeoForge) META-INF/services/dev.isxander.controlify.api.entrypoint.ControlifyEntrypoint | ||
| com.example.mymod.ControlifyEntrypoint | ||
| ``` | ||
| </CodeTabs> | ||
| Add the version to your `gradle.properties`: | ||
|
|
||
| ```properties | ||
| # You can find the versions in here: https://maven.isxander.dev/#/releases/dev/isxander/controlify | ||
| controlify_version=2.4.3+1.21.1-neoforge | ||
| ``` | ||
|
|
||
| ```kotlin | ||
| dependencies { | ||
| // Note: "compileOnly" must be replaced with "modCompileOnly" if Fabric Loom is used while targeting an obfuscated Minecraft version. | ||
| // This is not needed for deobfuscated Minecraft versions. | ||
| compileOnly("dev.isxander:controlify:${project.controlify_version}") { | ||
EchoEllet marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // Only need Controlify API, ignore the transitive dependencies (e.g, QuiltMC parsers) | ||
| transitive = false | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't it be better to remove the QuiltMC Parser as a transitive dependency, rather than using this workaround? This is more convenient, because it means users don't have to add YACL as a runtime only. Without |
||
| } | ||
| } | ||
| ``` | ||
|
|
||
| </details> | ||
|
|
||
| ## Registering the entrypoint | ||
|
|
||
| The entrypoint can be registered using a | ||
| Java service provider interface (SPI) in **`META-INF/services/dev.isxander.controlify.api.entrypoint.ControlifyEntrypoint`** | ||
|
|
||
| ```txt | ||
| com.example.mymod.ControlifyEntrypoint | ||
| ``` | ||
|
|
||
| ### Fabric Entrypoint | ||
|
|
||
| On Fabric, the same entrypoint may **also** be registered via `fabric.mod.json`. | ||
|
|
||
| ```json | ||
| { | ||
| "entrypoints": { | ||
| "controlify": [ | ||
| "com.example.mymod.ControlifyEntrypoint" | ||
| ] | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| Then simply create the class and implement the interface: | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.