FastAsyncWorldEdit fork retargeted for Fabric 1.20.4 / Java 17 (community fork continued, was silently Java-21-only and crashing clients until fixed 2026-07-31)
  • Java 99.5%
  • JavaScript 0.2%
  • Kotlin 0.2%
Find a file
Aca. 13f5ebb698
Some checks failed
Build / build (push) Has been skipped
CodeQL / Analyze (push) Failing after 4s
Label conflicting PRs / main (push) Failing after 3s
draft release / update_release_draft (push) Failing after 4s
Rewrite README for this fork specifically
The previous README was upstream FAWE's stock generic one (project blurb,
feature list, links to the Bukkit/CurseForge distribution) - said nothing
about this being a Fabric-specific fork, what changed here, or how to
actually build it (which has a real two-JDK gotcha: fabric-loom 1.14.x
needs a Java 21+ runtime to run Gradle at all, while the actual compiled
output targets Java 17). Replaced with fork-specific docs: what this fork
is and why it exists, the full Java 21->17 retargeting changelog from this
session, concrete build instructions, an updating-from-upstream section,
and known limitations.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 16:56:53 +02:00
.github Enlarge error log category 2025-12-21 14:04:25 +01:00
.idea Fix Misaligned SVG In IJ project view (#2174) 2023-04-10 11:54:46 +02:00
build-logic Retarget Fabric module to Java 17 2026-07-31 16:49:39 +02:00
contrib/craftscripts style: Fix spelling mistake of 'FastAsyncWorldEdit' in craftscript readme (#1431) 2021-11-20 12:02:25 +01:00
gradle Retarget Fabric module to Java 17 2026-07-31 16:49:39 +02:00
worldedit-bukkit Add working Fabric port and runtime fixes 2026-02-06 14:17:57 -06:00
worldedit-cli Add working Fabric port and runtime fixes 2026-02-06 14:17:57 -06:00
worldedit-core Retarget Fabric module to Java 17 2026-07-31 16:49:39 +02:00
worldedit-fabric Retarget Fabric module to Java 17 2026-07-31 16:49:39 +02:00
worldedit-forge ref: switch from adventure NBT to LinBus (#2778) 2024-06-26 21:55:47 +02:00
worldedit-libs Add working Fabric port and runtime fixes 2026-02-06 14:17:57 -06:00
worldedit-mod Refactor Gradle build logic and update dependencies (#3309) 2025-10-08 00:13:24 -04:00
worldedit-sponge Add working Fabric port and runtime fixes 2026-02-06 14:17:57 -06:00
.editorconfig Track paperweight-userdev versions with renovate (#2548) 2024-01-22 19:14:10 +01:00
.git-blame-ignore-revs Ensure CRLF stays out of the repo 2020-08-24 12:41:26 -04:00
.gitattributes Fix gitattributes 2021-02-22 11:08:45 +01:00
.gitconfig java based merging? 2019-11-19 15:10:36 +00:00
.gitignore Retarget Fabric module to Java 17 2026-07-31 16:49:39 +02:00
Annotation-Explanation.adoc docs: Document a few undocumented annotations 2022-01-04 21:15:45 +01:00
build.gradle.kts Update plugin com.gradleup.nmcp.aggregation to v1.4.4 (#3425) 2026-01-24 21:44:30 +00:00
COMPILING.adoc Add working Fabric port and runtime fixes 2026-02-06 14:17:57 -06:00
crowdin.yml Update Crowdin configuration file 2020-01-20 11:30:00 +01:00
gradle.properties Retarget Fabric module to Java 17 2026-07-31 16:49:39 +02:00
gradlew Update Gradle to v9.2.0 (#3362) 2025-11-03 02:26:10 +00:00
gradlew.bat Update Gradle to v9.2.0 (#3362) 2025-11-03 02:26:10 +00:00
HEADER.txt Officially propagate GPL downwards to all files 2020-09-01 16:30:43 -04:00
Jenkinsfile Add working Fabric port and runtime fixes 2026-02-06 14:17:57 -06:00
LICENSE.txt Officially propagate GPL downwards to all files 2020-09-01 16:30:43 -04:00
NOTICE.txt Update build files and NOTICE.txt 2020-08-14 15:29:15 -04:00
README.md Rewrite README for this fork specifically 2026-07-31 16:56:53 +02:00
settings.gradle.kts Add working Fabric port and runtime fixes 2026-02-06 14:17:57 -06:00

FAWE for Fabric 1.20.4 (MTR France fork)

This is a fork of Plaaasma/FabricAsyncWorldEdit, itself a community continuation that ports FastAsyncWorldEdit's real engine (worldedit-core) to the Fabric platform. This is not a rewrite from scratch — it reuses upstream FAWE's actual codebase plus a worldedit-fabric platform module, the same way upstream itself has worldedit-bukkit, worldedit-cli, etc.

Why this exists

FAWE only has an officially maintained Bukkit/Paper (and CLI) build upstream — there is no maintained official Fabric release. The MTR France server (Fabric 1.20.4) needs fast, async world editing to build large rail infrastructure at scale, and vanilla WorldEdit-Fabric (7.3.0, kept as a reference/fallback at mods_backup/worldedit-mod-7.3.0.jar on the server) doesn't have FAWE's performance or feature set. Rather than write a Fabric port from zero, this fork continues Plaaasma's existing work (which had already done the hard part: real block placement mapping, permission checks, command forwarding, startup wiring between FAWE's engine and Fabric's API) and gets it working correctly for our specific target instead of abandoning that work.

For what FAWE itself actually is and does (the 200+ commands, brushes, masks, CFI, clipboard web integration, etc.), see upstream's own README and wiki — this fork changes nothing about FAWE's actual editing functionality, only what platform/Java version it runs on.

Status as of 2026-07-31

  • Branch name (fabric-1.20.1) is historical/stale from before this fork's own version catalog was updated — despite the name, gradle/libs.versions.toml is pinned to MC 1.20.4 / Fabric Loader 0.19.3 / Fabric API 0.97.3+1.20.4, matching the actual MTR France server. Don't rename the branch casually; check gradle/libs.versions.toml for ground truth on what version this actually targets, not the branch name.
  • Builds cleanly and produces a correctly Java-17-bytecode jar (see "What changed" below). Deployed to the MTR France server and its client modpack.
  • Not yet actually tested in-game. Only compile-time and javap-verified bytecode-version checks have been done so far. Test //wand, //set, //copy///paste, //undo, and schematic load/save on a disposable world (world_flatcontinents_test or world_flathills_test on the server) before trusting this for real construction.

What changed in this fork (2026-07-31 session)

The jar previously deployed to the server (worldedit-fabric-mc1.20.4-2.15.1-SNAPSHOT.jar) silently contained Java 21 bytecode (class file version 65) despite its name claiming 1.20.4 compatibility. This crashed every normal Java-17 Minecraft client at bootstrap (UnsupportedClassVersionError, thrown while loading WorldChunk right after this mod's mixins merged in) — the reason it went unnoticed for over a week is that the MTR France server itself happens to run Java 21 (ghcr.io/pterodactyl/yolks:java_21 Docker image), so it worked there while silently breaking every client.

Root cause: build-logic/src/main/kotlin/buildlogic.common.gradle.kts hardcodes a project-wide JavaLanguageVersion.of(21) toolchain, inherited from upstream FAWE's own Bukkit/Paper build (which genuinely needs 21 for newer MC versions). Nobody had overridden this for the Fabric module specifically.

The fix, and everything that cascaded from it:

  1. Toolchain override, in worldedit-core/build.gradle.kts and worldedit-fabric/build.gradle.kts only (not globally — other platforms in this fork, bukkit/forge/sponge/cli, are irrelevant to us and left untouched):
    java {
        toolchain {
            languageVersion.set(JavaLanguageVersion.of(17))
        }
    }
    
  2. buildlogic.common-java.gradle.kts compiler args: it also force-sets options.release.set(21) and adds -Xlint:-this-escape (a lint category that only exists on JDK 21+ javac — passing it to a 17 javac is a hard "invalid flag" error, not just a warning). Overrode both modules' compileJava/ compileTestJava tasks to set release.set(17) and rebuild compilerArgs without that flag. Kept --add-modules=jdk.incubator.vector — that module is available since 17 (just incubating), it wasn't the problem.
  3. buildlogic.libs.gradle.kts (shared by every worldedit-libs:* submodule) hardcoded a Gradle variant metadata attribute TargetJvmVersion=21. This isn't about real bytecode — those submodules just shade third-party jars via ShadowJar, no first-party compilation happens there — so dropping it to 17 was a pure metadata fix, not a functional risk.
  4. Three external dependencies were themselves Java-21-only and had to be pinned back to their last Java-17-compatible release (found by checking each candidate version's Gradle Module Metadata .module file for org.gradle.jvm.version):
    • plotsquared-core 7.5.117.3.8compileOnly, an optional Bukkit-only protection-plugin integration, irrelevant to Fabric.
    • lin-bus (-tree/-common/-stream/-format-snbt/-bom) 0.2.00.1.0not optional, this is FAWE's core NBT/tag library, used pervasively. This one needed real source-level API-compat fixes (see below), not just a version bump.
    • fabric-permissions-api 0.6.10.3.3modCompileOnly, an optional LuckPerms-style permission check.
  5. Real Java 21 language/API usage in FAWE's own source that simply doesn't compile on 17, rewritten:
    • Switch pattern matching (case Type name -> ..., a preview feature on 17, finalized in 21) → plain instanceof chains, in SimdSupport.java, MutatingOperationTransformHolder.java, AbstractPlayerActor.java, FabricTransmogrifier.java.
    • One record pattern (instanceof FacingTagData(String a, ...)) → a plain instanceof binding plus accessor calls, in ExtentEntityCopy.java.
    • Thread.ofVirtual() (virtual threads, finalized in 21) → a plain daemon Thread, in ChangeExchangeCoordinator.java — only ever one such thread per instance, virtual threads buy nothing here.
    • The ForkJoinWorkerThread(ThreadGroup, ForkJoinPool, boolean) 3-arg constructor doesn't exist pre-21; on 17 only the 1-arg protected ForkJoinWorkerThread(ForkJoinPool) constructor is accessible outside java.util.concurrent — fixed in FaweForkJoinThread.java.
    • List.getLast() (SequencedCollection, JDK 21) → list.get(list.size() - 1), in RandomTransformParser.java.
    • Math.ceilDiv (JDK 18+) → the classic -Math.floorDiv(-a, b) ceiling-division trick (works since Java 8), in MathMan.java.
  6. The lin-bus downgrade needed real API-compat fixes, not just a version bump:
    • LinReadOptions (a legacy-UTF8-decoding option class used for reading old MCEdit/Sponge-v1/v2 schematics) doesn't exist at all in 0.1.0 — no options-accepting overload of LinBinaryIO.read/readUsing exists in that version either. Dropped the option entirely in BuiltInClipboardFormat.java (3 call sites). Consequence: very old schematics with non-standard NBT string encoding may fail to import; normal/modern schematics are unaffected.
    • LinCompoundTag.value() returns a wildcard-bounded Map<String, ? extends LinTag<?>> in 0.1.0, simplified to Map<String, LinTag<?>> in later versions Java won't let you assign one to the other directly. Widened three local variable declarations to match (all read-only usage, so semantically safe) in BaseEntity.java, BlockTransformExtent.java, MinecraftStructure.java.

Building this fork

You need two JDKs, not one

This is the part that will trip you up if you skip it. Two separate Java version requirements are in play, for two different reasons:

  • fabric-loom 1.14.x's own build tooling requires a Java 21+ runtime just to run Gradle at all (unrelated to what Java version your code targets — the loom plugin's own compiled classes need a JVM that can load them). If you only have a Java 17 JDK, configuring the project will fail immediately with Dependency requires at least JVM runtime version 21.
  • The actual compiled output (worldedit-core, worldedit-fabric) targets Java 17, per the toolchain overrides described above, because that's what Fabric Loader 0.19.3 / MC 1.20.4 clients actually run.

Gradle's toolchain resolution handles this split automatically if it can find both JDKs — you just need to tell it where they are.

  1. Install a JDK 21 (a full JDK, not just a JRE — you need javac; a Temurin/Adoptium build works fine, get one from adoptium.net if you don't have one) and a JDK 17 (same source).
  2. Point Gradle at both in gradle.properties (already set up in this repo, but verify the paths match your machine):
    org.gradle.java.installations.paths=C:/path/to/jdk-17,C:/path/to/jdk-21
    org.gradle.java.installations.auto-detect=true
    
  3. Launch Gradle itself with the Java 21 JDK as JAVA_HOME (this is what satisfies loom's own runtime requirement — Gradle's toolchain feature then separately picks Java 17 for the actual worldedit-core/worldedit-fabric compilation, because that's what their build.gradle.kts files request):
    # from a shell where JAVA_HOME can be set for this command only
    JAVA_HOME=/path/to/jdk-21 ./gradlew :worldedit-fabric:build
    
    On Windows PowerShell:
    $env:JAVA_HOME = "C:\path\to\jdk-21"; .\gradlew.bat :worldedit-fabric:build
    

Building the whole multi-module project (./gradlew build with no target) will also try to build worldedit-bukkit/worldedit-forge/worldedit-sponge/etc., which this fork doesn't maintain and doesn't need — just build the one module we actually ship:

JAVA_HOME=/path/to/jdk-21 ./gradlew :worldedit-fabric:build

Output

The file to actually deploy is:

worldedit-fabric/build/libs/worldedit-fabric-mc1.20.4-2.15.1-SNAPSHOT-dist.jar

Not the plain worldedit-fabric-mc1.20.4-2.15.1-SNAPSHOT.jar in the same folder — that one has no bundled dependencies and won't run standalone. The -dist.jar is the shaded-and-remapped artifact (via shadowJar + remapShadowJar), ~14MB, containing worldedit-core's classes plus the runtime libraries FAWE needs that vanilla/Fabric don't ship (zstd, lz4, parallelgzip, json-simple, jchronic, snakeyaml, antlr4-runtime, jlibnoise).

Verify the output actually targets Java 17 before trusting it (checks the first 4 bytes after the 0xCAFEBABE magic number — 0x003d = decimal 61 = Java 17; 0x0041 = 65 = Java 21, the bug this fork exists to avoid regressing back into):

unzip -p worldedit-fabric-mc1.20.4-2.15.1-SNAPSHOT-dist.jar com/sk89q/worldedit/WorldEdit.class | xxd -l 8 -p

COMPILING.adoc in this repo is upstream's original generic instructions (says "Java 21", ./gradlew clean build, mentions all four platform modules) — it predates this fork's retargeting and doesn't reflect the two-JDK setup above. Treat this README as the accurate one for this fork specifically.

Updating from upstream

Two places changes could come from:

  • origin — this fork's actual parent, Plaaasma/FabricAsyncWorldEdit. Check it periodically for Fabric-integration fixes (block placement, mixins, command forwarding). git fetch origin and diff/merge/cherry-pick as needed — don't blindly git merge origin/<branch>, since a straight merge would very likely reintroduce the Java 21 toolchain (upstream's own buildlogic.common hasn't been fixed the way ours has) and the dependency versions we downgraded. After merging anything from upstream, re-check:
    • build-logic/src/main/kotlin/buildlogic.common.gradle.kts line setting JavaLanguageVersion.of(...) — should stay overridden to 17 in our two modules' own build.gradle.kts, but confirm the override still applies cleanly after a merge.
    • gradle/libs.versions.toml — confirm plotsquared, linbus, fabric-permissions-api haven't been silently bumped back to Java-21-only versions by an upstream merge.
  • Upstream FAWE itself (IntellectualSites/FastAsyncWorldEdit) — worldedit-core is shared code; Plaaasma's fork presumably rebases onto FAWE releases periodically. If pulling newer FAWE-core changes directly (rather than through Plaaasma's fork), watch for new Java 21-only syntax/API usage introduced by FAWE's own ongoing modernization (this is exactly what caused the switch-pattern/record-pattern/virtual-thread issues fixed in this session) — there's no reason to expect that trend to stop, since upstream fully supports Java 21+ now.

Known limitations

  • Very old MCEdit/Sponge-v1/v2 schematic files using non-standard NBT string encoding may fail to import (see LinReadOptions note above). Normal/modern schematics (Sponge v3, .schem) are unaffected.
  • No PlotSquared, WorldGuard-Bukkit, or LuckPerms-native integration on this platform (those are Bukkit-only or pinned to old versions here specifically because they're optional and Java-21-only in their current releases) — not a regression, FAWE-Fabric never had these; just don't expect them.
  • Not yet tested in-game (see "Status" above) — treat as unverified for actual world-editing correctness, only verified to build and load without crashing the client/server class loader.

Where this is deployed

  • MTR France server: mods/worldedit-fabric-mc1.20.4-2.15.1-SNAPSHOT.jar (the -dist.jar renamed on deployment) on the Pterodactyl volume.
  • Client pack: mods.adlmrl.fr/pack/mods/worldedit-fabric-mc1.20.4-2.15.1-snapshot.pw.toml (packwiz entry, side = "both"), also hosted directly at mods.adlmrl.fr/worldedit-fabric-mc1.20.4-2.15.1-SNAPSHOT.jar.