Skip to content

Conversation

TheFlagCourier
Copy link
Contributor

@TheFlagCourier TheFlagCourier commented Aug 4, 2025

What a mess...

This is an attempt to modernize Citizens' technology stack, or at least give a blueprint to do so.

This is the culmination of countless hours spent over the last three days. Proper implementation would require retooling the CI/CD pipeline that Jenkins provides, and ironing out any issues with maven publishing.

However, it does maintain most of the source code. It contains some minor edits on my part, mainly to the API's test suite.

It i,s in its current state, capable of building the API, MAIN, and shaded JAR files with proper relocation. I have only mapped versions 1.19 - 1.21 to gradle.

I have not even looked at resource filtering yet - so don't trust the JARs to have valid plugin.yml files.

Who are you?

Nobody important. Though, I did split FlagWar out of Towny and maintain it for a few years.

Do I expect this to get merged?

Excuse me? have you seen the files changed, or the commits? 🤣

It may be easier to digest if you viewed it from my fork, rather than this PR. Clone it locally and give it a shot!

A better way forward would be to create an empty Citizens 3 repository, and merge this there as a baseline instead. (But that doesn't exist. [yet])

My Intentions

  • Find a pathway to migrate to paper (& maybe support Folia down the line)

    • paperweight-userdev can replace the need for BuildTools entirely, but requires Gradle to implement.
    • Note: This is implemented, my primary concern was getting close enough to a 1:1 representation of the current code base. Though... API now uses JUnit Jupiter for its tests.
  • Make Citizens friendlier to work on without having to swap between two different repositories.

  • Cut the Technical Debt

    • Java 8 is the new Java CE 6
      • It's old, inefficient, and is ready for the retirement home.
      • Yet it insists that it can drive the speed limit and stay in its lane.
    • Locking the API and main methods to MC 1.8 has resulted many workarounds and reflections
      • These are now rendered mostly unnecessary, and can be stripped out to optimize for a new common denominator.

My Reasoning

Look at this photograph screenshot taken from bstats.org.

Less than 8% of servers using Citizens (and reporting metrics) target Mincraft below version 1.19.

image

That is no reason to lock development to this god-forsaken toolchain. Nobody should require three versions of the JDK (JDK 8, JDK 11, and JDK 21) just to get everything required via BuildTools.jar for running mvn package -P full.

Credits

Closing Notes

This started as just some way to kill free time I had this weekend. Whether or not it gets merged, provides a basis for new development, or becomes digital dust... I'm honestly fine with whatever.

I just didn't want to waste my time and have nothing to show for it.

fullwall added 30 commits May 15, 2023 01:01
… have too much friction, and a custom passable state combining API would run into difficulties with cross-plugin compatibility. One alternative would be to expose some passability bits for ground, water, flying, etc. in the storage to both slightly optimise block lookups and allow safer passability overrides.
fullwall and others added 26 commits July 26, 2025 12:25
While delving into Citizens2, several build warnings derived from CitizensAPI.

This commit addresses these otherwise benign warnings, and includes minor
grammar changes. Documentation style for @param tags is preserved.

It does not reflect changes where the javadoc may no longer accurately portray
the described methods, or the intent behind them.
Linting: Fix multiple Javadoc Errors / Warnings
Preparation for Gradle-fication:

1) New Git Attributes & Git Ignore files

2) Relocate legacy directories to new paths:
  - `CitizensAPI/src/` -> `API/lib/`
  - `Citizens2/main/src/` -> `Citizens/lib/`
  - `Citizens2/v1_21_R5/src` -> `v1_25_R5/lib/`

3) Move all old build files (and legacy NBT modules) to LegacyFiles for
   reference (to be deleted)

All NBT stuff banished to LegacyFiles, except for v1_21_R5 (obv.)
Basic `gradle init` execution, sans the changes to the gitattributes and
gitignore files.
The move from src > lib was me going off of memory... yeah...

Starting the process to hook up the API to a build script.
Migrated tests to JUnit Jupiter

Rigged up Sources Jar & Javadoc Jar

Fixed some Javadoc errors

Tested that it builds appropriately via:

```bash
./gradlew :API:publishToMavenLocal
```
Initial Build Script and Relocating from lib to src
Should prove to be backwards compatible.

Also reset version to 2.0.39-SNAPSHOT (it's not quite 3.0 yet!)
Otherwise, you get issues with pulling Mojang Auth.
Should probably be resolved...
So, apparently this causes both source and class files to find their way into the regular jar file. Which kind of makes the sources.jar pointless, bloaty, and breaks convention.
…o non-api modules

Necessary if you want to run the javadoc or publish* tasks on the parent.
Re-added README.md (Based on API's, and merged main's info ontop)

Add back the .github/ directory

Removed dist/ from LegacyFiles
@fullwall
Copy link
Member

fullwall commented Aug 4, 2025

I appreciate the effort here, it's a lot of work to do this kind of stuff. It's not mergeable in this state.
Some thoughts:

  1. This would be better done as a series of changes rather than all at once. I'm not opposed to a monorepo but maybe that could be one PR (and I would have to think about whether it makes sense to be built separately still). I actually don't think the commit history is necessarily required in that transition.
  2. I don't like gradle really. Does it have to be gradle?
  3. Point taken re Java version. Java 11 would probably be fine (sadly I can't break down JVM versions by Minecraft version).
  4. Probably closer to 20% of users still use pre-1.19 versions of Minecraft, so I was thinking we do need some migration story.

@TheFlagCourier
Copy link
Contributor Author

I appreciate the effort here, it's a lot of work to do this kind of stuff. It's not mergeable in this state. Some thoughts:

1. This would be better done as a series of changes rather than all at once. I'm not opposed to a monorepo but maybe that could be one PR (and I would have to think about whether it makes sense to be built separately still). I actually don't think the commit history is necessarily required in that transition.

2. I don't like gradle really. Does it have to be gradle?

3. Point taken re Java version. Java 11 would probably be fine (sadly I can't break down JVM versions by Minecraft version).

4. Probably closer to 20% of users still use pre-1.19 versions of Minecraft, so I was thinking we do need some migration story.

Thanks. And yeah, I agree that it's too far gone to get merged into C2 directly.

1.

This could definitely be done in a more steady manner, over time.
There are benefits to the mono-repo approach:

  • No direct reliance on Citizens' Maven repository when building.
  • The API version never risks getting out of lock-step with C2's.
  • Everything is accessible from a single IDE project/session.

As for the commit history, I think it's actually super important to maintain attribution for any changes.
Both from the perspective of "who wrote this junk|treasure of a class", and a copyright attribution perspective.

Merging the CitizensAPI into Citizens2 without that history dilutes both.
In that sense, it would be better to keep them separate.

2.

I get that. It has it's upsides and downsides.

No, it does not have to be Gradle. Maven is completely fine, if you're wanting to stick to the Spigot ecosystem. The project could even have both - though that's bloat...

That being said, not migrating locks out the only other alternative for handling Mojang internals, without having to use BuildTools. (And that in itself is a much nicer way to do it, in my humble opinion.)

The nice thing is, once implemented, it should be very low maintenance.

Say we need to update to 1_22? One could copy the build script from v1_21, copy it and change a version string or two, include the directory in the settings file, and it will build if told to with the same parameters
It may require updating some dependencies, or the toolchain to use a newer java version, but those are minor edits.

It also allows anyone to be super selective of what they build. For example, say I only want v1_20?
./gradlew :v1_20_R4:shadowJar — that's it. No requirement to build the latest version in a 'dev' profile;
no having to build the whole project by calling the parent build.

Similarly, if someone just wants to generate the API javadocs? ./gradlew :API:javadoc. Super helpful for the five people still building their own projects with Apache Ant.

Having it dynamically pulled in with the included wrapper also means we can choose when to update to a newer version of the gradle spec, or to take a "if it ain't broke don't fix it" approach.

3.

Honestly, I would say Java 17 is the sweet spot. You'll only have to be committed to the releases already built with the
spigot build profile. Unless you have an outsized reason to be actively supporting 1.13, they would be better off shelved.

4.

Everything else could be put into "maintenance only" mode: only receiving necessary patches,
and get sectioned off to a dedicated branch. The sun has to set eventually.

@fullwall
Copy link
Member

fullwall commented Aug 4, 2025

Perhaps putting the API as a git submodule would be better then?

@TheFlagCourier
Copy link
Contributor Author

TheFlagCourier commented Aug 4, 2025

It has its own trade offs but it's indeed an option. I'm not a fan of how obtuse they can be.

As far as linking the project from the submodule, into C2's build it should be fine to handle dynamically with DependencySubstitutions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants