HomeJavaModsFarlandsOrigin
FarlandsOrigin
ModsJava

FarlandsOrigin

Folia/Paper port of ClassicFarlands to restore the farlands on modern servers

⬇ Download on Hangar
# FarlandsOrigin - Paper/Folia port Port of [ThePotatoArchivist's ClassicFarlands](https://github.com/ThePotatoArchivist/ClassicFarlands) (MIT licensed - `LICENSE` carried over unmodified) from Fabric to Paper/Folia, targeting Minecraft 26.1 / 26.2. ## WARNING: Made with AI (cuz idk how to use Java) ## PLEASE SUPPORT [THE ORIGINAL DEVELOPER](https://github.com/ThePotatoArchivist) I am a random dev, and you should really not trust random stuff you find on the Internet. Take a look at the source code which is only a few hundred lines long. (click on the GitHub "view source" link on the side). And if you prefer, compile the project yourself with `mvn clean package` (requires Java JDK 21+ and Maven installed). **Read this whole file before deploying.** This is not a routine "recompile against a different API" port. Fabric gives mods three things Paper's plugin API does not: an init hook that runs before Mojang's registries freeze, Mixin bytecode injection into internal worldgen classes, and generic JSON-patching of datapack files at load time. Everything below exists to replace those three things without either of them. ## What changed vs. the Fabric mod, and why | Fabric mod piece | Paper port | Why | |---|---|---| | `Registry.register(BuiltInRegistries.DENSITY_FUNCTION_TYPE, ...)` in `onInitialize` | `FarlandsOriginBootstrap` (a `PluginBootstrap`) + `NmsRegistryUnfreezer`, reflection | Paper plugins load *after* `BuiltInRegistries` is already frozen; there's no Paper API for this registry at all (checked against the current `RegistryEvents` javadocs - it only covers enchantments/entity variants/dialogs/etc., not worldgen). | | `RadiusCheck.java` | Ported verbatim | Plain vanilla `DensityFunction` code, nothing Fabric-specific. | | `BlendedNoiseMixin` / `PerlinNoiseMixin` (SpongePowered Mixin) | `FarlandsOriginAgent` + `BlendedNoiseTransformer` / `PerlinNoiseTransformer` (raw ASM via a `java.lang.instrument` agent) | Modern SpongePowered Mixin (the version mixinextras/`@ModifyExpressionValue` needs) has no supported standalone mode outside a mod loader - it's built around an `IMixinService` tied to a specific launch platform. Rather than ship an unverifiable Mixin bootstrap sequence, I did the same two bytecode edits directly with ASM, which *is* fully standalone-capable. | | Mixson (generic runtime JSON patching of `noise_settings`) | `FarlandsOriginDatapackInstaller` (auto, at bootstrap) / `tools/build_datapack.py` (manual fallback) + companion datapack | No equivalent exists outside Fabric's resource-reload events. Datapacks can only override a whole registry file, not patch one field - so instead of guessing at vanilla's `noise_settings.json` content for a Minecraft version I have no way to verify from here, this reads it from **the running server's own classpath** (or, manually, your server jar) and patches only `final_density`, the same way Mixson did, just at install time instead of every load. | | Quilt Config (`FarlandsOriginConfig`) | `FarlandsOriginState` + `config.yml` | Kaleido/Quilt Config isn't available on Paper; swapped for a plain Bukkit config. Same `distance` option, same arithmetic. | ## Install 0. **Generate a Gradle wrapper first, if you don't have one.** Use Gradle 9.1.0 or newer - Gradle only added support for *running on* JDK 25 in 9.1.0 (older Gradle, including the whole 8.x line, fails with "Unsupported class file major version 69" on a JDK 25 system): ``` cd farlandsorigin gradle wrapper --gradle-version 9.7 ``` From then on use `./gradlew` instead of `gradle` for every command below. **Build with JDK 25**, not just "any recent LTS" - Paper 26.2's dev bundle itself requires a 25+ runtime to compile against (`build.gradle`'s `options.release`/`sourceCompatibility` are already set to 25 to match; don't lower them without also lowering `minecraft_version`, or you'll hit "Dependency resolution is looking for a library compatible with JVM runtime version X, but paper-api ... is only compatible with ... 25"). 1. **Set your exact target version** in `gradle.properties` - `minecraft_version=26.2` (or `26.1.2`) resolves to the *latest* published build for that version via `.build.+`; pin it to a specific build (e.g. `26.2.build.102`) once you've picked one, so a later rebuild doesn't silently jump to a newer Paper build underneath you. 2. **Build.** `./gradlew shadowJar` - needs network access, since it pulls the paperweight dev bundle for `minecraft_version` from Paper's Maven the first time. Output: `build/libs/farlandsorigin-.jar`. No separate "reobf" step - Paper 26.1+ ships fully unobfuscated (Mojang mappings all the way down), so this jar already *is* what the server runs; there's nothing to remap. 3. Drop that jar in `plugins/` on your Folia (or Paper) server. 4. **Add the java agent flag.** In your start script, *before* `-jar paper.jar` (works identically for Folia's jar): ``` java -javaagent:plugins/farlandsorigin-.jar -jar folia-.jar nogui ``` This is not optional and can't be set from inside the plugin - agents are a JVM-level concept, fixed at process launch, before any plugin code runs. 5. **Start the server.** As of this version, the companion datapack is generated and installed automatically - `FarlandsOriginBootstrap` reads your server's own vanilla `noise_settings.json` files straight off the classpath (the same way it already reads real NMS classes) and writes the datapack into `/datapacks/farlandsorigin/` before that folder gets scanned, so there's no manual jar-hunting or script-running step needed for the common case. Check the log for: - `Wrote Far Lands override for overworld.` (and `amplified`, `large_biomes`) - `FarlandsOrigin datapack auto-installed at ...` If you don't see those - e.g. your server uses a non-default `plugins` folder location, so the installer's server-root guess is wrong - fall back to the manual path instead: ``` python3 farlandsorigin/tools/build_datapack.py path/to/your/server.jar farlandsorigin cp datapack/farlandsorigin/data/farlandsorigin/worldgen/density_function/old_overworld_noise.json \ farlandsorigin/data/farlandsorigin/worldgen/density_function/ cp -r farlandsorigin /datapacks/ ``` (the script auto-detects Mojang's bundler-jar format too, so any server jar you point it at - launcher stub, raw Mojang jar, already-extracted one - works) Either way (auto or manual), this has to be in place *before* a world is first created/loaded - Far Lands worldgen registries are baked once at server boot and won't retroactively apply to chunks generated earlier, same limitation the original mod has. 6. Check the rest of the log for: - `Registered farlandsorigin:radius_check density function type.` - `[FarlandsOrigin] BlendedNoise.compute: patched 2 call site(s).` - `[FarlandsOrigin] PerlinNoise.wrap: patched to identity function.` - `FarlandsOrigin agent attached; Far Lands generation active at distance ...` If any of these are missing or show 0 patched sites, Far Lands generation is **not** active - see Troubleshooting. ## Configuration `plugins/FarlandsOrigin/config.yml`: ```yaml distance: 12550824 ``` Same option and arithmetic as the Fabric mod's config. ## Folia notes Nothing in this port does per-region scheduling, so there was nothing to port to Folia's threaded-regions model specifically - worldgen density functions run on whichever thread is generating a given region regardless of Folia vs. Paper, and none of this plugin's code touches Bukkit's single-threaded APIs (no entities, no block updates, no scheduling). The one thing to double check on Folia specifically is that `PluginBootstrap` timing relative to registry freezing is the same as on Paper (Folia is a Paper fork, so it should be, but verify on your Folia build). ## Known limitations / what to verify before trusting this in production This was written and reviewed without the ability to compile or run it against a real Paper/Folia 26.1/26.2 server (no network or NMS jars available in the environment that produced it). Specifically unverified: - **`NmsRegistryUnfreezer.FROZEN_FIELD = "frozen"`** - the field name inside vanilla's `MappedRegistry` holding its frozen state. If this throws `NoSuchFieldException` at boot, inspect `MappedRegistry` in your version (e.g. via a decompiler on the Paper/NMS jar) and update the constant. - **`BlendedNoiseTransformer`/`PerlinNoiseTransformer` target signatures** - built from the method/class names your own Fabric mod's mixins already target (`BlendedNoise.compute`, `PerlinNoise.wrap`, `FunctionContext.blockX/ blockZ`), which are Mojang's official mapped names and should carry over identically to Paper's mojmap runtime. Both transformers log how many call sites they patched at startup specifically so a mismatch is loud, not silent - if you see the "found 0 ... to patch" warnings, decompile the actual class in your version and adjust. - **`build_datapack.py` / `FarlandsOriginDatapackInstaller`'s reference-vs-inline detection for `final_density`** - based on the pattern already visible in your mod's own `old_overworld_noise.json` (which references sibling entries like `minecraft:overworld/sloped_cheese` by ID), so `final_density` is very likely also a plain string reference in modern vanilla data - but both handle the inline-object case too, just in case. - **`FarlandsOriginDatapackInstaller`'s server-root detection** - uses the server process's working directory (`Path.of("").toAbsolutePath()`), which is where `server.properties`/`world/`/`plugins/` all live relative to for a normally-launched server (`java -jar ... folia.jar` run from inside the server folder). An earlier version of this tried to derive it from `context.getDataDirectory()` instead and threw a `NullPointerException` on a real server - that path turned out to be relative, not absolute, so walking up two parents overshot past the root. If you launch the server with a working directory that ISN'T the actual server folder (unusual, but possible with some wrapper scripts/process managers), this will still get it wrong - same symptom as before ("Wrote Far Lands override..." logs appearing but generation not actually changing) and same fix (fall back to the manual script, which sidesteps this by taking the world's datapacks path from you directly). - **`pack_format` in `pack.mcmeta`** - auto-detected from `version.json` on the classpath (or in the server jar, for the manual script) if present; verify against your server's actual vanilla datapack if generation refuses to load with a pack-format warning/error. - **Java agent self-sufficiency** - `Launch-Agent-Class`/`Premain-Class` are both set in the manifest so the same jar works whether attached via `-javaagent:` (recommended, used above) or (if you ever need it) a self-attach at runtime; only the `-javaagent:` path has been reasoned through carefully here. None of these are "this definitely won't work" - they're the concrete, falsifiable things to check on a real test server before relying on this, listed instead of glossed over. ## Fixed during real-server testing (kept here as a record) Confirmed against a live Folia 26.1.2 server: - **ASM couldn't parse JDK 25 class files at all** (`Unsupported class file major version 69`) - ASM added Java 25 support in 9.8; anything earlier fails outright. Pinned to `asm_version=9.8`. - **`ClassWriter`'s default `getCommonSuperClass` can't see NMS types** - it resolves via the agent's own classloader by default, which has no visibility into Folia's server classes. Fixed with `TargetLoaderClassWriter`, which resolves against the classloader that's actually loading the class being transformed. - **A plain `invokestatic` from `BlendedNoise` to a separate helper class failed with `NoClassDefFoundError`** - the JVM resolves that symbolic reference using BlendedNoise's own defining classloader, and Paperclip/Folia's loader doesn't have this plugin's jar on its search path. Fixed by having `BlendedNoiseTransformer` copy the helper's compiled field+method bytecode directly onto `BlendedNoise` itself (see that class's Javadoc), so nothing needs cross-classloader resolution at runtime. Configuration crosses the same boundary via JVM system properties (`farlandsorigin.coordinateDistance` / `farlandsorigin.baseDistance`) rather than a shared class's static fields, for the same reason.

FarlandsOrigin is a free Minecraft Java mod. Compatible with Minecraft 26.1, 26.1.1, 26.1.2, 26.2. Downloaded 1 times (via Hangar). Download it and open it directly in the game.

Explore more