diff --git a/.vitepress/sidebars/develop.ts b/.vitepress/sidebars/develop.ts index b28b391eb..707f768ec 100644 --- a/.vitepress/sidebars/develop.ts +++ b/.vitepress/sidebars/develop.ts @@ -371,6 +371,20 @@ export default [ }, ], }, + { + text: "develop.class_tweakers", + collapsed: true, + items: [ + { + text: "develop.class_tweakers.introduction", + link: "/develop/class-tweakers/", + }, + { + text: "develop.class_tweakers.access_widening", + link: "/develop/class-tweakers/access-widening", + }, + ], + }, { text: "develop.misc", collapsed: true, diff --git a/develop/class-tweakers/access-widening.md b/develop/class-tweakers/access-widening.md new file mode 100644 index 000000000..dc500e30b --- /dev/null +++ b/develop/class-tweakers/access-widening.md @@ -0,0 +1,189 @@ +--- +title: Access Widening +description: Learn how to use access wideners from class tweaker files. +authors-nogithub: + - lightningtow + - siglong +authors: + - Ayutac + - cassiancc + - cootshk + - Earthcomputer + - florensie + - froyo4u + - haykam821 + - hYdos + - its-miroma + - kb-1000 + - kcrca + - liach + - lmvdz + - matjojo + - MildestToucan + - modmuss50 + - octylFractal + - OroArmor + - T3sT3ro + - Technici4n + - TheGlitch76 + - UpcraftLP + - YTG1234 +--- + +Access widening is a type of [class tweaking](../class-tweakers) used to loosen the access limits of classes, methods and fields and reflect that change in the decompiled source. +This includes making them public, extendable and/or mutable. + +To access fields or methods, it can be safer and simpler to use [accessor mixins](https://wiki.fabricmc.net/tutorial:mixin_accessors), +but there are two situations where accessors are insufficient and access widening is necessary: + +- If you need to access a `private`, `protected` or package-private class +- If you need to override a `final` method, or subclass a `final` class + +However, unlike [accessor mixins](https://wiki.fabricmc.net/tutorial:mixin_accessors), [class tweaking](../class-tweakers) only works on Vanilla Minecraft classes, and not on other mods. + +## Access Directives {#access-directives} + +Access widener entries start with one of three directive keywords to specify the type of modification to apply. + +### Accessible {#accessible} + +`accessible` can target classes, methods and fields: + +- Fields and Classes are made public. +- Methods are made public, and final if originally private. + +Making a method or field accessible also makes its class accessible. + +### Extendable {#extendable} + +`extendable` can target classes and methods: + +- Classes are made public and non-final +- Methods are made protected and non-final + +Making a method extendable also makes its class extendable. + +### Mutable {#mutable} + +`mutable` can make a field non-final. + +To make a private final field both accessible and mutable, you must make two separate entries in the file. + +### Transitive Directives {#transitive-directives} + +In order to expose certain access widener changes to mods depending on yours, you prefix the relevant directives with `transitive-*`: + +```txt:no-line-numbers +transitive-accessible +transitive-extendable +transitive-mutable +``` + +## Specifying Targets {#specifying-targets} + +For class tweaking, classes use their [internal names](../mixins/bytecode#class-names). For fields and methods you must specify their class name, their name, and their [bytecode descriptor](../mixins/bytecode#field-and-method-descriptors). + +::: tip + +The names of targets need to correspond to your current mappings. + +::: + +::: tabs + +== Classes + +Format: + +```txt:no-line-numbers + class +``` + +Example: + +@[code lang=txt:no-line-numbers transcludeWith=:::accesswidening-examples:classes:::](@/reference/latest/src/main/resources/example-mod.classtweaker) + +== Methods + +Format: + +```txt:no-line-numbers + method +``` + +Example: + +@[code lang=txt:no-line-numbers transcludeWith=:::accesswidening-examples:methods:::](@/reference/latest/src/main/resources/example-mod.classtweaker) + +== Fields + +Format: + +```txt:no-line-numbers + field +``` + +Example: + +@[code lang=txt:no-line-numbers transcludeWith=:::accesswidening-examples:fields:::](@/reference/latest/src/main/resources/example-mod.classtweaker) + +::: + +## Generating Entries {#generating-entries} + +Manually writing access widener entries is time-consuming and prone to human error. Let's look at tools that simplify a part of the process by allowing you to generate and copy entries. + +### mcsrc.dev {#mcsrc-dev} + +Available for all versions with an [unobfuscated JAR](../migrating-mappings/index#whats-going-on-with-mappings) namely 1.21.11 and above, +[mcsrc](https://mcsrc.dev) allows you to decompile and navigate Minecraft source in the browser and copy Mixin, access widener or access transformer targets to clipboard. +The names of classes, methods and fields on [mcsrc](https://mcsrc.dev) will align with [Mojang Mappings](../migrating-mappings/index#mappings). + +To copy an access widener entry, first navigate to the class which you want to modify, and right-click on your target to open the popup menu. + +![Right-clicking on a target in mcsrc](/assets/develop/class-tweakers/access-widening/mcsrc-right-click-on-aw-target.png) + +Then, click on `Copy Class Tweaker / Access Widener`, and a confirmation should appear at the top of the page. + +![AW copy confirmation on mcsrc](/assets/develop/class-tweakers/access-widening/mcsrc-aw-copy-confirmation.png) + +You can then paste the entry in your class tweaker file. + +### Minecraft Development Plugin (IntelliJ IDEA) {#mcdev-plugin} + +The [Minecraft Development Plugin](../getting-started/intellij-idea/setting-up#installing-idea-plugins), also known as MCDev, is an IntelliJ IDEA plugin to assist in various aspects of Minecraft mod development. +For example, it lets you copy access widener entries from the decompiled source target to the clipboard. + +To copy an access widener entry, first navigate to the class which you want to modify, and right-click on your target to open the popup menu. + +![Right-clicking on a target with MCDev](/assets/develop/class-tweakers/access-widening/mcdev-right-click-on-aw-target.png) + +Then, click on `Copy / Paste Special` and `AW Entry`. + +![Copy/Paste special with MCDev](/assets/develop/class-tweakers/access-widening/mcdev-copy-paste-special-menu.png) + +A confirmation should now pop up on the element you right-clicked. + +![AW copy confirmation with MCDev](/assets/develop/class-tweakers/access-widening/mcdev-aw-copy-confirmation.png) + +You can then paste the entry in your class tweaker file. + +### Linkie {#linkie} + +[Linkie](https://linkie.shedaniel.dev) is a website that allows you to browse and translate across mappings. It also provides access widener entries for the class, method or field you're viewing. + +First, make sure you have the correct version and mappings selected on the menu on the left: + +![Correct version and mappings selected on Linkie](/assets/develop/class-tweakers/access-widening/linkie-version-mappings-select.png) + +Then, search for the element you want to modify, and the access widener entry will be listed as `AW` under the result: + +![A search result in Linkie](/assets/develop/class-tweakers/access-widening/linkie-search-results.png) + +You can copy it and then paste the entry in your class tweaker file. + +## Applying Changes {#applying-changes} + +To see your changes applied, you must refresh your Gradle project by [regenerating sources](../getting-started/generating-sources). The elements you targeted should +have their access limits modified accordingly. If modifications do not appear, you can try [validating the file](../class-tweakers/index#validating-the-file) +and checking if any errors appear. diff --git a/develop/class-tweakers/index.md b/develop/class-tweakers/index.md new file mode 100644 index 000000000..def3deee3 --- /dev/null +++ b/develop/class-tweakers/index.md @@ -0,0 +1,61 @@ +--- +title: Class Tweakers +description: Learn what class tweakers are, and how to set them up. +authors: + - cassiancc + - Earthcomputer + - its-miroma + - MildestToucan +--- + +Class tweakers, formerly known as access wideners before gaining further functionality, provide transformation tools complementary to Mixin bytecode manipulation. They also allow some runtime modifications to be accessible within the development environment. + +::: warning + +Class tweakers are not specific to a given Minecraft version, but are only available starting from Fabric Loader 0.18.0, and may only target Vanilla Minecraft classes. + +::: + +## Setup {#setup} + +### File Format {#file-format} + +Class tweaker files are conventionally named after your modid, `example-mod.classtweaker`, to help IDE plugins recognize them. They should be stored in `resources`. + +The file must have the following header as its first line: + +```txt +classTweaker v1 named +``` + +Class tweaker files can have blank lines and comments starting with `#`. Comments can start at the end of a line. + +Whilst the specific syntax depends on the feature, modifications are each declared on separate lines. An entry's elements can be separated using any whitespace, including tabs. + +### Specifying The File Location {#specifying-the-file-location} + +The class tweaker file's location must be specified in your `build.gradle` and `fabric.mod.json` files. Remember that you must also depend on Fabric Loader 0.18.0 or above to use class tweakers. + +The specifications are still named after access wideners to preserve backwards compatibility. + +#### build.gradle {#build-gradle} + +@[code lang=gradle:no-line-numbers transcludeWith=:::classtweaker-setup:gradle:::](@/reference/latest/build.gradle) + +#### fabric.mod.json {#fabric-mod-json} + +```json:no-line-numbers +... + +"accessWidener": "example-mod.classtweaker", + +... +``` + +After specifying the file location in your `build.gradle` file, make sure to reload your Gradle project in the IDE. + +## Validating the File {#validating-the-file} + +By default, class tweaker will ignore entries referencing modification targets that cannot be found. To check if all the classes, fields and methods specified in the file are valid, run the `validateAccessWidener` Gradle task. + +Errors will point out any invalid entry, but they can be about which part of an entry is invalid. diff --git a/develop/loom/options.md b/develop/loom/options.md index cae21c022..c74de0cc5 100644 --- a/develop/loom/options.md +++ b/develop/loom/options.md @@ -16,8 +16,8 @@ This page contains a reference for all options present in the `loom` Gradle exte ```groovy loom { - // Set the access widener path, see https://wiki.fabricmc.net/tutorial:accesswidening - accessWidenerPath = file("src/main/resources/example-mod.accesswidener") + // Set the class tweaker file path, see https://docs.fabricmc.net/develop/class-tweakers/ + accessWidenerPath = file("src/main/resources/example-mod.classtweaker") // Add additional log4j config files. log4jConfigs.from(file("log4j.xml")) diff --git a/public/assets/develop/class-tweakers/access-widening/linkie-search-results.png b/public/assets/develop/class-tweakers/access-widening/linkie-search-results.png new file mode 100644 index 000000000..045044660 Binary files /dev/null and b/public/assets/develop/class-tweakers/access-widening/linkie-search-results.png differ diff --git a/public/assets/develop/class-tweakers/access-widening/linkie-version-mappings-select.png b/public/assets/develop/class-tweakers/access-widening/linkie-version-mappings-select.png new file mode 100644 index 000000000..9a9d09248 Binary files /dev/null and b/public/assets/develop/class-tweakers/access-widening/linkie-version-mappings-select.png differ diff --git a/public/assets/develop/class-tweakers/access-widening/mcdev-aw-copy-confirmation.png b/public/assets/develop/class-tweakers/access-widening/mcdev-aw-copy-confirmation.png new file mode 100644 index 000000000..6dc2fd39f Binary files /dev/null and b/public/assets/develop/class-tweakers/access-widening/mcdev-aw-copy-confirmation.png differ diff --git a/public/assets/develop/class-tweakers/access-widening/mcdev-copy-paste-special-menu.png b/public/assets/develop/class-tweakers/access-widening/mcdev-copy-paste-special-menu.png new file mode 100644 index 000000000..74f6abf82 Binary files /dev/null and b/public/assets/develop/class-tweakers/access-widening/mcdev-copy-paste-special-menu.png differ diff --git a/public/assets/develop/class-tweakers/access-widening/mcdev-right-click-on-aw-target.png b/public/assets/develop/class-tweakers/access-widening/mcdev-right-click-on-aw-target.png new file mode 100644 index 000000000..df96cf963 Binary files /dev/null and b/public/assets/develop/class-tweakers/access-widening/mcdev-right-click-on-aw-target.png differ diff --git a/public/assets/develop/class-tweakers/access-widening/mcsrc-aw-copy-confirmation.png b/public/assets/develop/class-tweakers/access-widening/mcsrc-aw-copy-confirmation.png new file mode 100644 index 000000000..53ae00fdb Binary files /dev/null and b/public/assets/develop/class-tweakers/access-widening/mcsrc-aw-copy-confirmation.png differ diff --git a/public/assets/develop/class-tweakers/access-widening/mcsrc-right-click-on-aw-target.png b/public/assets/develop/class-tweakers/access-widening/mcsrc-right-click-on-aw-target.png new file mode 100644 index 000000000..ee820337a Binary files /dev/null and b/public/assets/develop/class-tweakers/access-widening/mcsrc-right-click-on-aw-target.png differ diff --git a/reference/latest/build.gradle b/reference/latest/build.gradle index 83dcef422..4b97f5b43 100644 --- a/reference/latest/build.gradle +++ b/reference/latest/build.gradle @@ -12,6 +12,14 @@ dependencies { productionRuntimeMods "net.fabricmc.fabric-api:fabric-api:${fabricApiVersion}" } +// :::classtweaker-setup:gradle::: +loom { + + accessWidenerPath = file("src/main/resources/example-mod.classtweaker") + +} +// :::classtweaker-setup:gradle::: + // :::automatic-testing:game-test:2 // :::automatic-testing:2 test { diff --git a/reference/latest/src/main/resources/example-mod.classtweaker b/reference/latest/src/main/resources/example-mod.classtweaker new file mode 100644 index 000000000..ed42442bd --- /dev/null +++ b/reference/latest/src/main/resources/example-mod.classtweaker @@ -0,0 +1,23 @@ +classTweaker v1 named + +# Access widening examples +# The targets for these examples are non-transitive versions of Fabric API access wideners for 1.21.11 + +# :::accesswidening-examples:classes::: +# Makes the inner class TypeSpecificTrade in VillagerTrades public +accessible class net/minecraft/world/entity/npc/villager/VillagerTrades$TypeSpecificTrade +# :::accesswidening-examples:classes::: + +# :::accesswidening-examples:methods::: +# Makes the SensorType(Supplier) constructor public +accessible method net/minecraft/world/entity/ai/sensing/SensorType (Ljava/util/function/Supplier;)V + +# Makes the formatValue() method of return type String in TextColor public +accessible method net/minecraft/network/chat/TextColor formatValue ()Ljava/lang/String; +# :::accesswidening-examples:methods::: + + +# :::accesswidening-examples:fields::: +# Makes the field damageTypes of type Registry in DamageSources public. +accessible field net/minecraft/world/damagesource/DamageSources damageTypes Lnet/minecraft/core/Registry; +# :::accesswidening-examples:fields::: diff --git a/reference/latest/src/main/resources/fabric.mod.json b/reference/latest/src/main/resources/fabric.mod.json index 52e63333d..73cce1ff1 100644 --- a/reference/latest/src/main/resources/fabric.mod.json +++ b/reference/latest/src/main/resources/fabric.mod.json @@ -48,5 +48,11 @@ "environment": "client" } ], - "depends": {} + "depends": { + "fabricloader": ">=0.18.0", + "minecraft": "~1.21.11", + "java": ">=21", + "fabric-api": "*" + }, + "accessWidener": "example-mod.classtweaker" } diff --git a/sidebar_translations.json b/sidebar_translations.json index 6b7d50a0d..6f1b81958 100644 --- a/sidebar_translations.json +++ b/sidebar_translations.json @@ -77,6 +77,9 @@ "develop.misc.debugging": "Debugging Mods", "develop.mixins": "Mixins", "develop.mixins.bytecode": "Java Bytecode", + "develop.class_tweakers": "Class Tweakers", + "develop.class_tweakers.introduction": "Introduction", + "develop.class_tweakers.access_widening": "Access Widening", "develop.serialization": "Serialization", "develop.porting": "Porting", "develop.porting.current": "Porting to 1.21.11",