Skip to content

Conversation

@Euphillya
Copy link

@Euphillya Euphillya commented Oct 28, 2025

Close #3013

Following the Citizens API update, I'm starting to propose this PR for Folia support.
Several features may not work; please report them to me if you notice any.

Environmental Test:

[02:25:58 INFO]: Checking version, please wait...
[02:25:58 INFO]: This server is running Folia version 1.21.8-6-ver/1.21.8@612d9bd (2025-09-30T14:11:15Z) (Implementing API version 1.21.8-R0.1-SNAPSHOT)
You are running the latest version
Previous version: 1.21.8-DEV-05d3e7a (MC: 1.21.8)

Admin commands:

  • Command: /citizens save
  • Command: /citizens reload (with respawn)

Test NPC Player

  • Player NPCs can spawn when the plugin starts.
  • If we use /citizens reload, the Player NPCs can respawn normally.
  • Command: /npc sitting
  • Command: /npc path
  • Command: /npc chunkload
  • Command: /npc create (but there is no longer any verification)
  • Command: /npc command
  • Command; /npc configgui
  • Command: /npc hologram
  • Command: /npc inventory
  • Command: /npc jump
  • Command: /npc model (tested with BetterModel)
  • Command: /npc tphere
  • Command: /npc setequipment
  • Command: /npc teleport

Test NPC mobs

  • Command: /npc create --type
  • Variant Wolf
  • Variant Chiken
  • Bee anger
  • AI npc
  • Bossbar
  • hitbox

Currently broken:

  • Scoreboard (not supported on Folia)

@CLAassistant
Copy link

CLAassistant commented Oct 28, 2025

CLA assistant check
All committers have signed the CLA.

@Euphillya Euphillya changed the title Ajout Folia Supported dans plugin.yml [WIP] Support Folia Oct 28, 2025
@Euphillya
Copy link
Author

I think the changes to make it compatible with Folia are complete. I’m no longer seeing any errors on my end, even after multiple restarts and reloads.

@Euphillya Euphillya marked this pull request as ready for review November 8, 2025 00:13
@Euphillya Euphillya changed the title [WIP] Support Folia Support Folia Nov 8, 2025
Copy link
Member

@fullwall fullwall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume that async safety is not checked at all right?

registry.saveToStore();
}
}
if (net.citizensnpcs.api.util.SpigotUtil.isFoliaServer()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this necessary?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because you can't "despawn" the NPCs while the server is down. But fortunately, they despawn during the shutdown.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because you can't "despawn" the NPCs while the server is down. But fortunately, they despawn during the shutdown.

More specifically, Folia's regional threads are all shutting down during the server shutdown, so it is impossible to interact with them.


@Override
public void onDespawn(DespawnReason reason) {
if (net.citizensnpcs.api.util.SpigotUtil.isFoliaServer()) return; // Not Supported on Folia
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://docs.papermc.io/folia/faq/#what-commands-does-folia-disable

Scoreboards are disabled directly in Folia's CraftBukkit API because they're not safe.
So instead of constantly getting an error, we can remove it.
Later, we could add an alternative using the PDC on entities, but we'll have to see.

return world != null ? world.getChunkAt(x, z) : null;
}

public World getWorld() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added it to avoid doing multiple Bukkit.getWorld calls in CitizensNavigator, but it can be removed.

}

public static <T> T callPossiblySync(Callable<T> callable, boolean sync) {
if (SpigotUtil.isFoliaServer()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this method should be deleted then

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete callPossiblySync ?


@Override
public void setLocationDirectly(org.bukkit.entity.Entity entity, Location location) {
// Todo temp teleport
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any equivalent method in folia?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried unsuccessfully to find a solution because the entity can leave the regional thread if it has to travel a long distance. Since this method is used during the entity's summoning, I found it more practical to teleport it for the time being.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I said earlier, I can't restore it exactly to the way it was before, but I did this to maintain the same behavior if we're on the same ticked region:
469dcb9

@Euphillya
Copy link
Author

I assume that async safety is not checked at all right?

I did everything I could to avoid any strange surprises due to async, but it's possible I overlooked something. However, at first glance, it seems to be working on my game server.

I will, however, make the changes you requested above.

Petite explication: Sur Folia, un déplacement d'entité effectué via snapTo déclenche une mise à jour des sections qui necessite d'être exécutée sur le thread propriétaire de la région initiale.
Cependant, il est possible que ce dernier ne soit pas dans la même region initiale, de ce fait Folia rejette la demande en générant l'erreur: Cannot move entity off-main qu'on se mette sur le thread de l'entité, ou le thread de la future localisation.
De ce fait, je fais une vérification au préalable si c'est le même monde et que la region tické pour l'entité et la future localisation est le même, et si c'est le cas, snapTo fonctionne, sinon il faut lancer une teleportation async.

De ce fait, quand tout est réuni, je garde le fonctionnement initial, sinon on est obligé de teleporter l'entité
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.

Folia support

3 participants