#paper
33814 messages · Page 34 of 34 (latest)
2960379 fix inverted check in RedStoneOreBlock - Lulu13022002
Fixed in 296037944d74daa4976ddabbbde4e332d932acdc
Thanks, I added a mention for the related bug since it's older and I figure they're actually just both the same issue
I added Minecraft and paper version flag at startup.
nice that you did that I suppose, but we really don't need that information to be printed every time gradle is used
Expected behavior
When creating a VirtualComponent with a custom VirtualComponentRenderer, the component should be rendered by the Paper server as long as the renderer doesn't return null.
Observed/Actual behavior
The component isn't rendered anywhere
Steps/models to reproduce
- Create a custom virtual component
- Send it to your player
- Receive empty message
Plugin and Datapack List
Only my plugin
Paper version
This server is running Paper version 26.1.2-5-main@d61d8df (2026-04-11T14:20:55Z) (Implementing API version 26.1.2.build.5-alpha)
Other
This is an API issue, not a plugin or gameplay bug
This seems to be an adventure design limitation. Last time I checked, the renderer isn't actually called in adventure anywhere
Closes #13900
Features
- Event Purpose: Allows plugins to monitor, modify, or cancel the disenchanting/repair action inside the grindstone.
- Experience Control: Plugins can read and modify the amount of experience dropped from the action via
getExperience()andsetExperience(). - Bulletproof Cancellation: The cancellation handling correctly covers standard clicks, Shift-clicks (via
quickMoveStack), and dropping the item using the drop key (viaContainerInput.THROW), preventing any item duplication or ghost item bugs.
Expected behavior
PlayerInventorySlotChangeEvent#getSlot() and PlayerInventorySlotChangeEvent#getRawSlot() should reliably identify the changed slot in the player's own inventory, especially for armor/offhand slots.
Observed/Actual behavior
When a player has another inventory view open, for example a chest, and an armor slot changes due to external causes, such as a zombie attacking the player and damaging armor durability, PlayerInventorySlotChangeEvent is fired, but the slot values appear incorrect or misleading.
In this case:
event.getRawSlot()does not behave as expected for the currently changed player inventory slot.event.getSlot()appears to be converted using the currently openInventoryView.- Because the player is viewing a chest,
event.getSlot()may map to a slot in the chest view instead of representing the actual armor slot that changed.
This makes it difficult or impossible for plugins to safely detect armor slot changes using this e...
Expected behavior
Calling LimitedRegion#spawnEntity(Location, EntityType) from a BlockPopulator during chunk generation should spawn the entity (or, if the entity can't be
created, fail gracefully / return null) — regardless of the world's difficulty. This works on easy, normal, and hard.
Observed/Actual behavior
On a peaceful world, calling LimitedRegion#spawnEntity(...) with a monster type (e.g. ZOMBIE, DROWNED, GUARDIAN) during chunk generation throws an NPE inside Paper. Peaceful disallows hostile mobs, so the entity factory produces a null entity, and RegionAccessor#spawnEntity does not null-check it before calling entity.absSnapTo(...). The exception is raised on a chunk-system worker thread, so it escalates to unrecoverableChunkSystemFailure → "Chunk system crash" → the server shuts down.
It is difficulty-dependent: identical code/world spawns the same monster fine on easy/normal/hard, and crashes only on peaceful. Non-monster entities are unaf...
I can replicate this with just a world in peaceful and using spawnEntity that throw and exception but not the crash by the time where this happen...
This PR resolve https://github.com/PaperMC/Paper/issues/13992 by making the request to spawn ignore the internal checks, most of them are already make in the API side, this make the behaviour of the spawn works like 26.1 where the method just not spawn the mob if cannot.
PD: Also add a few Nullable annotation for consider in the future the methods for createLiving use another where a null is expected in future...
Fixed in 747c984fcba30da6b159f58f71b75fdea8b2a9b0
250ea42 add missing kick event causes - Lulu13022002
1e3ffb9 clean block placement from API - Lulu13022002
19d83f9 Add missing obsolete on Bukkit.getWorldC... - Doc94
13f9986 fail fast for out of bound access in LimitedRegion - Lulu13022002
193803d Migrate to leafpile - Spottedleaf
dbde0e0 fix compile errors without feature patches - Lulu13022002
daf505c update item meta - Lulu...
58e1f84 deprecate Mob#setDespawnInPeacefulOverride - Lulu13022002
done in 58e1f844b1f37a2efe4e9536f57f4a288733e0cb, this will now throw a more proper exception the client no longer render these entities.
Stack trace
Both Vanilla and Paper have this issue when loading deep dark biomes.
See MC-307918.
This is not exactly a stacktrace or exception, is an error log that might get spammed without printing any stacktrace or interrupting the execution of any code.
Still it print a large wall of error logs that is hard to ignore.
Log in Paper:
https://pastes.dev/x7sueyL2oN
Plugin and Datapack List
Datapacks:
None
Plugins:
Worlds
Actions to reproduce (if known)
To re-create on Paper:
- Create a new server
- Install a world manager, in this case Worlds
- Generate a single-biome deep dark world using
/world create test type single-biome minecraft:deep_dark - When teleported, fly around for a bit
- Check the console
Seems to be related to the sculk propagating randomly, so it might take a couple of tries, although the single biome world should make it extremely co...
528ed2b Call EntityUnleashEvent after prime even... - Lulu13022002
5c18495 [ci skip] move dead flag as well in defe... - Lulu13022002
Expected behavior
A plugin that resolves protobuf-java 4.34.0 (e.g. transitively through micrometer-registry-otlp or the OTLP exporter) should be able to use it at runtime. That satisfies protobuf's runtime >= gencode rule.
Observed/Actual behavior
Paper bundles mysql-connector-j, which pulls com.google.protobuf 4.29.x onto the shared classpath. Paper's bundled copy wins over the plugin's 4.34.0, so protobuf's runtime check blows up at class init:
com.google.protobuf.RuntimeVersion$ProtobufRuntimeVersionException:
... runtime 4.29.x. Runtime version cannot be older than the linked gencode version.
This was already reported in #13835 and closed as won't fix, with relocation suggested as the workaround. I'm opening this because relocation doesn't fully work for OpenTelemetry.
Relocating OTel isn't really viable: the Java agent relies on canonical class names (io.opentelemetry., io.grpc.) to instrument libraries, and context keys can't be relocated withou...
Summary
Respect the ticks-per.autosave setting on server shutdown. When autosave is
disabled (ticks-per.autosave <= 0), Paper no longer writes w...
Disabling autosaving should not disable world saving entirely
Disabling autosaving should not disable world saving entirely
Agree and to clarify, this PR doesn't disable world saving entirely.
Explicit saves are completely unaffected:
/sav...
these changes should be merged into source/respective patches
Expected behavior
Zombies with ShouldBurnInDay false shouldn't burn in Daylight
Observed/Actual behavior
Zombies still catching fire.
Steps/models to reproduce
Summon Zombie:
/summon zombie ~ ~ ~ {Paper.ShouldBurnInDay: 0b}
Check Data:
/data get entity @e[type=minecraft:zombie,sort=nearest,limit=1]
Plugin and Datapack List
[20:49:40 INFO]: ℹ Server Plugins (24):
[20:49:40 INFO]: Bukkit Plugins:
[20:49:40 INFO]: - CoreProtect, MEAdmin, MEBuild, MEchat, MEClans, MEconomy, MEHandler, MEitems, MEMarket, MEMounts
[20:49:40 INFO]: MEnpc, MEPets, MERoles, MESlots, MESpawner, MEStorage, MEVote, MEWars, MEWorlds, Plan
[20:49:40 INFO]: ProtocolLib, Spartan, Tebex, VotifierPlus
Paper version
[20:50:09 INFO]: This server is running Paper version 1.21.11-132-ver/1.21.11@c5eb079 (2026-05-11T11:43:09Z) (Implementing API version 1.21.11-R0.1-SNAPSHOT)
Other
[20:46:09] [Render thread/INFO]: [System] [CHAT] Zombie has the following entity data: {Paper.Spa...
these changes should be merged into source/respective patches
Done ✅
[PaperMC/Paper] branch deleted: feature/dc
6d23ced Preliminary update to dataconverter (#13965) - kennytv
Waiting at least a day before switching to the beta channel, but it's time for main since the last noisy bit is done
[PaperMC/Paper] branch deleted: dev/26.2
Some random issues I have found so far while working on updating Newwind to 26.2:
- EntitySpawnEvent is called twice for XP orbs.
- Non-savable passengers can save even if miscSerialization isn't allowed because its checking the wrong entity.
- CraftCreatureSpawner uses maxInclusive twice instead of minInclusive.
- PaperWrittenBookContent.asBook() uses requireNonNull wrongly.
- PaperConsumable data component toBuilder() doesn't include hasConsumeParticles.
- BukkitBrigForwardingMap wrongly returns early (probably doesn't matter though)
- SizeLimitedSet is off by one (basically inconsequential)
- Vanilla world migration (probably?) doesn't clear legacy PDC properly because dynamics are immutable.
- "changed" and "clicked" are swapped in PlayerBucketFillEvent (you might wanna keep this one as is incase it breaks existing plugins idk)
- PlayerShearEntityEvent drops weren't actually immutable.
- There are some typos and missing closing curly brackets/apostrophes.
Summary
Adds a projectiles.uncertainty section to paper-global.yml that allows server owners to override the uncertainty parameter passed to Projectile#shoot on a per-entity-type basis.
- Introduces
ProjectileUncertainty.resolve(EntityType, float)to look up configured values fromGlobalConfiguration - Configuration keys are Minecraft entity type ids (e.g.
minecraft:arrow,minecraft:snowball) - Unconfigured types keep vanilla behavior; setting a value to
0removes random spread for that projectile type - Per-entry
defaultpreserves the vanilla uncertainty for that call site
Configuration is applied at the call sites where uncertainty is originally passed (bow/crossbow shootProjectile, throwable items, mob ranged attacks, dispensers, and Bukkit API launch paths), not inside Projectile#shoot or the shared spawn helpers.
Configuration example
projectiles:
uncertainty:
minecraft:arrow: 0
minecraft:snowball: 0
mi...
Summary
Adds a projectiles.uncertainty section to paper-global.yml that allows server owners to override the uncertainty parameter passed to Projectile#shoot on a per-entity-type basis.
- Introduces
ProjectileUncertainty.resolve(EntityType, float)to look up configured values fromGlobalConfiguration - Configuration keys are Minecraft entity type ids (e.g.
minecraft:arrow,minecraft:snowball) - Unconfigured types keep vanilla behavior; setting a value to
0removes random spread for that projectile type - Per-entry
defaultpreserves the vanilla uncertainty for that call site
Configuration is applied at the call sites where uncertainty is originally passed (bow/crossbow shootProjectile, throwable items, mob ranged attacks, dispensers, and Bukkit API launch paths), not inside Projectile#shoot or the shared spawn helpers.
Configuration example
projectiles:
uncertainty:
minecraft:arrow: 0
minecraft:snowball: 0
mi...
Why this got moved here?
This was done on purpose (vector is used as a location here), can you revert except the link reference which should be changed for the other vector methods in this class.
Can you remove the double space as well while you're at it.
It might be better to not call the event in the other place, to still run the logic when cancelled (so cancelling the event still works).
The // methods below are overridden to make final comment
Yes but the override here can be removed it's a leftover so this can be final actually.
Is your feature request related to a problem?
It is currently impossible to update a specific world clock using it's key (ex: "minecraft:overworld")
Describe the solution you'd like.
An api to update world clocks, maybe
In Player:
void setPlayerTime(Key clock, long time, boolean tickTime)
long getPlayerTime(Key clock)
in World:
void setTime(Key clock, long time)
long getTime(Key clock)
void setFullTime(Key clock, long time)
long getFullTime(Key clock)
Describe alternatives you've considered.
1/ Sending ClientboundSetTimePacket using the protocolib plugin, however the clockUpdates field of this packet does not yet have an api for it.
2/ Sending ClientboundSetTimePacket using NMS. haven't tried yet, but i should work.
Other
No response
Thanks to @Lulu13022002, i can reference the related branch: https://github.com/PaperMC/Paper/tree/feature/clock-api
This PR is related too https://github.com/PaperMC/Paper/pull/12119
Same than https://github.com/PaperMC/Paper/pull/13955 closed when @kennytv merge 26.2 to main.
This PR add missing Causes for EntityPotionEffectEvent and make a few improvements.
This also applies to CraftPig
I don't understand your change, why not just remove this part and keep radius > 0 instead. The event should never be null at this point.
Sorry I meant to remove the overriden method in OldEnumHolderable and make this method final.
Isn't it possible to recreate the world_gen_settings.dat, like done in createNewWorldData if missing? I don't think paper should fail this gracefully here, especially if this also happens when the server fails to fully create the world the first time it starts up (like when e.g. another server is running on the same port)
See an example of where this is a problem here: https://mclo.gs/rUXPi0V (This is not using your patch for world migration, but it should come to the same conclusion)
Sure, this can be easily fixed, although I think it shouldn't be a too difficult fix for something that will definetly happen to more people in the future
Isn't it possible to recreate the world_gen_settings.dat, like done in
createNewWorldDataif the overworld dimension missing? I don't think paper should fail this gracefully here, especially if this also happens when the server fails to fully create the world the first time it starts up (like when e.g. another server is running on the same port)See an example of where this is a problem here: mclo.gs/rUXPi0V (This is not using your patch for world migration, but it should come to the same conclusion)
Sure, this can be easily fixed by users, although I think it shouldn't be a too difficult fix for something that will definitely happen to more people in the future
This require maybe not remove the gen file when migration its done for use when remove in vanilla (in vanilla you can force this error too but require more steps)... but this PR is for another thing, if you can open an issue related to this.
A drawback of BlockDropItemEvent is that the list of drops provided covers all items produced during the entire neighbor update phase. As a result, if you break a block with a torch on top you get one BlockDropItemEvent with both the block's drop and the torch.
If you want to replace the dropped item, this usually wouldn't be an issue since most blocks only drop one item. If you wanted to replace what torches drop via a plugin you'd just replace all instances of Material.TORCH in all BlockDropItemsEvent.
The problem is if vanilla loot tables have been modified via a datapack. It may not be possible to look at the list of drops from the entire update chain and determine what blocks dropped items and which drops belong to which block.
BlockDropResourcesEvent is called from within Block.dropResources and so will capture the exact list of drops generated for each individual block being broken, whether it was broken directly by a player or indirectly. Without t...
Can confirm an event like this would fill a huge gap in the existing API, I actually brought up making this exact kind of event in the paper discord (and made the changes locally) but I never opened the PR because I wasn't sure it would be accepted. (I didn't much of a response from the paper team in the discord server.)
See: [Original Conversation](#paper-dev message) & [Paper Team Question](#paper-dev message) for context on other reasons you might need an event like this.
[PaperMC/Paper] Pull request opened: #14011 Fix connection throttle cleanup wiping the whole tracker
Problem
The connection throttle cleanup in ServerHandshakePacketListenerImpl wipes the entire throttleTracker every ~200 connections. The cleanup predicate compares a stored timestamp against the throttle duration:
throttleTracker.values().removeIf(time -> time > connectionThrottle);
time is an epoch-millisecond timestamp (~1.7e12); connectionThrottle is a duration (default 4000ms). So time > connectionThrottle is always true and every entry is removed. The check a few lines above already does it correctly:
currentTime - throttleTracker.get(address) < connectionThrottle
Within a cleanup cycle the per-IP throttle works, but every 200th connection clears the map, so a client can time reconnects around the cleanup and slip past the throttle.
Fix
Compare elapsed time, reusing the currentTime already computed in the same block:
throttleTracker.values().removeIf(time -> currentTime - time > connectionThrottle);
This is...
Picking this up in #14011. The cleanup predicate compares the stored timestamp against the duration instead of the elapsed time, so it clears the whole tracker every 200 connections. The PR compares currentTime - time, matching the throttle check just above it.
Rebased and fixed up for 26.2
Expected behavior
org.bukkit.block.Block#applyBoneMeal(BlockFace) returns true when bone meal is successfully applied (e.g. a crop advances a growth stage).
Observed/Actual behavior
It returns false even when the application succeeds and the block visibly grows. The growth happens - only the boolean is wrong. This breaks any plugin that branches on the return value (e.g. to consume an item / count successes).
CraftBlock#applyBoneMeal(BlockFace) checks the result against InteractionResult.SUCCESS:
return result == InteractionResult.SUCCESS && (event == null || !event.isCancelled());
But since the 1.21.2 InteractionResult refactor, BoneMealItem.applyBonemeal(...)`` returns InteractionResult.SUCCESS_SERVER, not SUCCESS`:
// net/minecraft/world/item/BoneMealItem.java (Paper-extracted applyBonemeal)
if (growCrop(boneMealStack, level, pos)) {
if (!level.isClientSide()) {
...
return InteractionResult.SUCCESS_SERVER; //````...
Expected behavior
Keep inventory works for all dimensions
Observed/Actual behavior
Only enables it for the overworld
Steps/models to reproduce
Enable keep inventory
Plugin and Datapack List
/plugins
i
[18:07:22 INFO]: Server Plugins (18): [18:07:22 INFO]: Paper Plugins (2):
[18:07:22 INFO]: JEIRecipeBridge, Veinmine
r
[18:07:22 INFO]: Bukkit Plugins (16):
[18:07:22 INFO]: Essentials, EssentialsCha t, EssentialsGeoIP, floodgate, Geyser-Spigot, GriefPrevention, Invsee, LuckPerms, Orebfusc ator, ProtocolLib
[18:07:22 INFO]: ServerLinksZ, *Vault, ViaBa ckwards, ViaVersion, WorldEdit, WorldGuard
Paper version
/version
[18:11:29 INF0]: Checking version, please wai
t.
[18:11:29 INF0]: This server is running Paper
version 26.1.2-72-ver/26.1.2@1a6b910 (2026-0
6-19T13:08:47Z) (Implementing API version 26.
1.2.build.72-stable)
You are running the latest version
Other
No response
game rules are per dimension and need to be set in each world to apply to all worlds
Fixes https://github.com/PaperMC/Paper/issues/14012 making the server success its consider for the return in the API method.
Should just check if the result is an instance of InteractionResult.Success.
Should just check if the result is an instance of InteractionResult.Success.
i can make that if its not an isssue consider "CONSUME" like valid for this case.
Is your feature request related to a problem?
Currently when trying to gate logic behind MC versions in plugins you need to implement some sort of a version matcher for MC versions or use protocol versions.
Describe the solution you'd like.
I would like to see the server’s latest supported API version exposed in the API along with an isCompatible() method to make version dependent plugin code cleaner.
A possible implementation could look similar to to ServerBuildInfo with the latest plugin API version supported by the server being exposed along with something like ApiVersionInfo#isCompatible(String version)
Describe alternatives you've considered.
mentioned above
Other
No response
This could also land under UnsafeValues
I am a bit confused what "isCompatible" would look like in your mind.
Is what compatible? your plugin with the server version? The answer is generally gonna be yes if you use non experimental API and "depends" if you use experimental API.
idk how you'd scope that to a single method?
If I remember correctly the reason why https://github.com/PaperMC/Paper/pull/10253's isAtLeast was dropped from the final ServerBuildInfo was complexity of checking that for snapshots, but with the new Minecraft versioning I think that wouldn't be a problem anymore
I meant as if the API version is equal to or lower than the latest supported by the server
like the methods in org.bukkit.craftbukkit.util.ApiVersion which i would love to see exposed to the API
Yea I mean, their new version scheme should make this a good bit easier and we wouldn't be porting something like this back so, no need to handle old snapshot builds as no plugin was developing against those anyway 💀
The same async catcher should probably be added to the registerAttribute method right below as well. It modifies the same non-thread-safe NMS AttributeMap if the attribute is not yet registered on this entity.
Otherwise tested this with my RPG plugin which uses a lot of attribute modification and it seems to be working fine.
Simply adds a method to Player which exposes the resetFlyingTicks method from ServerGamePacketListenerImpl.
This is particularly useful for preventing the "flying" kick without having event spam. While you could enable the "allow-flight" option in server.properties, I find that allowing developers to have a method to reset this counter themselves would be useful.
For example, my use case is for my PacketBlocks plugin where players standing on them would be kicked for flying. Currently I require you to enable"allow-flight" however understandbly some server owners may not want to do this.
Is your feature request related to a problem?
Currently, paper-plugin.yml uses name as both the plugin’s identifier and its display name. This couples two different concepts:
- a unique, stable plugin ID used for dependency resolution, lookup, and internal references
- a human-readable display name used in logs, plugin lists, help output, and other user-facing contexts
This makes it harder for plugin authors to define a clean display name without also making that display name part of the plugin’s identity. It also means that renaming or rebranding a plugin can affect references that should ideally remain stable.
Describe the solution you'd like.
Add an optional id field to paper-plugin.yml.
The id field would act as the plugin’s unique identifier, while name would remain the plugin’s display name.
Example:
id: MyPlugin
name: My Plugin
version: '1.0.0'
main: com.example.myplugin.ExamplePlugin
api-version: '26.1.2'
The id does not nec...
a human-readable display name used in logs, plugin lists, help output, and other user-facing contexts
Can you provide some examples where the current plugin name cannot possibly be human readable?
It also means that renaming or rebranding a plugin can affect references that should ideally remain stable.
How often does this happen?
The name has long been treaded as the canonical referential ID for plugins and slowly expected to conform to specific things, fairly sure that there is already a mechanism for being able to sit in place of another plugin unless that was only added to plugin.yml, I wouldn't entirely be against a display name thing but tilting from the "name as the identifier" to a different id as the canonical thing would be a pretty large amount of code shift for something that would semantically make 0 difference for 99.9% of plugins
Prevent the sign editor to pop for already edited sign.
This is a small bandaid until #13608 is merged.
Can you provide some examples where the current plugin name cannot possibly be human readable?
The issue is more thatnameis doing two jobs at the same time. It is both the plugin's technical identifier and the thing shown to users.
For example,
A plugin might already be known internally as WorldGuardExtraFlags, but the author may want it displayed as WorldGuard Extra Flags. The stable identifier stays the same, while the user-facing name can use spacing and nicer formatting.
Or a plugin might want a namespaced ID like "com.example.myplugin" while showing "Example Plugin" to users.
Rebrands, ownership transfers, forks, trademark issues, or just better branding can also happen.
How often does this happen?
I don't think the frequency is the main thing here. Even if it is not common, the impact can be annoying when it does happen, and the proposed change can be changed to be backwards compatible.
tilting from the "name as the identifier" to a different id a...
Frequency of this being a problem is an important thing for introducing a change in something as fundamental as plugin identification.
Your examples:
- Dev wants spaces in the name.
- Hasn't seemed to hurt anyone in the dozen years since spaces were disallowed. Users have been able to identify their plugins just fine.
- Dev wants a namespaced ID.
- Seems like the dev just wants to be special, doesn't seem worth catering to.
- Rebrand / better branding
- Plugins are neat tools for your server, not brand identities.
- Ownership transfer
- This isn't going to cause a rename.
- Fork
- This should cause a full rename, to avoid breakage.
- Trademark issues.
- A user who names their plugin Fortnite can pick up the pieces themselves.
Stop is very explicitly meant and used to save all state of the server, that has nothing to do with the autosave setting
[PaperMC/Paper] Pull request opened: #14021 Implement dynamic inventory title updates via Components
Summary
This pull request adds modern Adventure Component support for dynamically setting inventory titles via InventoryView#title(Component).
Description
The existing InventoryView#setTitle(String) method has been deprecated since 1.21.1 due to poorly defined and broken behaviors. Currently, there is no proper way to update an open inventory's title using the modern Adventure API.
This PR addresses the issue by introducing:
InventoryView#title(Component)toPaper-API.- A proper packet-based implementation in
Paper-Server(CraftInventoryView) that updates the client UI on the fly usingClientboundOpenScreenPacket. - Throwing an
UnsupportedOperationExceptionif a title update is requested for an inventory context that does not support it (e.g., if the player inventory is active or the view is detached).
There is no proper way to do this because this is relying on client side state hackery which is
- not garaunteed behavior we can promise for the next decade
- has pretty jarring side-effects for clients when devs use this
There is no proper way to do this because this is relying on client side state hackery which is
1. not garaunteed behavior we can promise for the next decade 2. has pretty jarring side-effects for clients when devs use this
What if we just expose it as an experimental API via @ApiStatus.Experimental with a heavy warning in the Javadoc? That way, devs stop hacking with raw packets, but Paper isn't bound to guarantee its behavior for the next decade.
Hacking isn't needed now anyways, devs can just reopen same inventory view then modify the title in open event, which also properly exposes to devs what is happening when setting a title (as the client doesn't support just changing the title which the setter would suggest)
Duplicate of #14014, I opted to check against Success explicitly but this works too indeed.
Expected behavior
The player should rejoin at the exact logout location.
The player's inventory should remain in the chest after logging out.
World changes, including placed chests, should be saved consistently without rollback.
Observed/Actual behavior
Player location rolls back.
Player inventory rolls back, causing item duplication.
Repeating the process eventually causes some chests to disappear.
Steps/models to reproduce
I'm experiencing a player data rollback issue on Paper 26.2. Experimental Alpha
When I leave the server and rejoin, my player sometimes does not spawn at the location where I logged out. Instead, I appear at an earlier location.
If I place all of my inventory into a chest before logging out and then rejoin, my inventory is restored as if I never placed the items in the chest. The chest still contains all of the items as well, resulting in duplicated items.
If this process is repeated multiple times, some of the chests that were placed...
Cleanup PRs like this are generally not accepted as the code base is massive and cleanups like removal of usless FQN in imports would be better for large scale automated PRs by team members once checkstyle (https://github.com/PaperMC/Paper/pull/11859) is in.
Thank you anyway!
Is your feature request related to a problem?
There's no API to change drops when Item Frame is destroyed, while also having access to the ItemFrame entity to e.g., read its PDC.
Describe the solution you'd like.
EntityDropItemEventcalled for Item Frame and the item inside of it.HangingBreakEvent#getItemsorHangingBreakEvent#getDrops
Describe alternatives you've considered.
Marking frame location on HangingBreakEvent then retrieving it on ItemSpawnEvent and handling the rest of the logic.
Other
Let me know if there's a cleaner solution. Basically trying to apply item_model component to a dropped item frame if the entity was invisible.
Discussion Category: Ideas
Is this replicable for you over a few attempts?
If so, can you attempt this without geyser or floodgate?
No need for paper comments in non mojang owned files anymore, we have hardforked 🥳
Also please add javadocs here.
Same applies for the diff in the CraftPlayer
Following https://github.com/PaperMC/Paper/pull/14016#discussion_r3515187279 and the diff in https://github.com/PaperMC/Paper/pull/13639, I have removed the Paper comments here and added an import instead of using the FQCN.
fab8887 Fix connection throttle cleanup wiping t... - gunjanjaswal
Thanks for the reviews and merge, @electronicboy and @lynxplay!
Summary
Fixes #13678.
TypedKeyImpl is a record implementing Key, but it never overrides equals/hashCode, so Java generates them from both record components and only matches another TypedKeyImpl. Adventure's KeyImpl.equals compares any Key by namespace + value, so equality is one-directional:
Key key = Key.key("minecraft:stone");
TypedKey<ItemType> typedKey = TypedKey.create(RegistryKey.ITEM, key);
key.equals(typedKey); // true
typedKey.equals(key); // false
That breaks the symmetry clause of Object.equals, and the two hash differently, so a TypedKey can go missing in a HashSet<Key> built from plain keys, and contains/remove turn order dependent when both types are mixed.
This overrides equals/hashCode on TypedKeyImpl:
- Against another
TypedKey, compare underlying key and registry key (same as before, so keys from different registries stay distinct). - Against a plain
Key, compare namespace + value to match adventure...
Opened #14025. It overrides equals/hashCode on TypedKeyImpl so a TypedKey is symmetric with an equal plain Key and hashes the same, while typed-vs-typed keeps the registry distinction. Flagged the transitivity tradeoff in the PR in case you'd prefer key-only equality.
Problem
PlayerLinksSendEvent is gated behind an isEmpty() check on the server's
global ServerLinks. This means the event is never fired when no global links
are configured, making it impossible for plugins to add per-player links from
scratch without a workaround.
Plugins that want to show player-specific links (e.g. localized links based on
client language) are currently forced to pre-populate the global ServerLinks
with dummy entries just to make the event trigger — even though those global
entries are irrelevant and must then be cleared inside the event handler.
Solution
Remove the isEmpty() guard before the event, and move it to after the event
has been processed. The event now always fires, and the packet is only sent if
the resulting ServerLinks is non-empty (either from global config or from
plugin modifications).
Are you testing this on Windows by any chance?
With a Windows file system Files#isWritable, which checkAttributes mostly is, will resolve the full path, check per-file security settings, ACLs, read-only volumes. Additionally Windows Defender or other AVs can also intercept this and do their stuff unless the directory is excluded.
This will be rather slow.
On a Unix file system, it just checks the file writable bit, which would be a single syscall and pretty fast.
Though I am not entirely convinced that isWritable on every single file is really needed here, checking just the directory should be enough.
namealso determines the location/name of the plugin data folder. Introducing an unique, stableidbut then not using it for this important area where uniqueness actually matters would be rather silly. Changing this would be a massive change. Also how would namespaces look here and what benefit would they even provide?nameis used for the creation of NamespacedKeys. Changing this to useidwhile also allowingiditself to be namespaced would not be possible, as double-namespaces (plugin-namespace:plugin:key) are disallowed by the underlying vanilla system.
A few things you brought up can also already be done today:
- The log prefix can be configured in your
plugin.ymlby settingprefix:to some value. org.bukkit.helpallows full customization of the help system, including names displayed there.
Overall this essentially leaves "the way your plugin shows up in /plugins and /version". Which is a command often disabled on servers and not something...
geyser doesnt interefer with java\ java players and floodgate too
They both sit very deep in the servers networking stack...
Given the fact we have not received any other reports like this nor was I able to replicate it, I think it is fair to ask for replication without plugins?
Are there any form of errors in your logs?
Given the fact that the containers still open, a timeout is probably not happening which would have been my first guess.
The overall behavior seems like something is messing heavily with incoming packets...
My guess would be either an anti cheat or a protocol hack plugin
Expected behavior
Changelog on download page (now just sais No changes, lame!!).
Observed/Actual behavior
Newest releases missing changelog on download page, fix it now!!
<img width="1518" height="529" alt="Image" src="https://github.com/user-attachments/assets/6858071f-fbd9-439a-a906-d3e2544ef066" />
Steps/models to reproduce
Go here: https://papermc.io/downloads/paper
Plugin and Datapack List
NOPE
Paper version
26.2.x
Other
No response
This is known and being tracked internally
Might be better on the connection otherwise check if the connection is null before for early events.
87aa6ee update fill-gradle to fix changelog - MiniDigger
[PaperMC/Paper] New branch created: fix/changelog
ad5d26a update fill-gradle to fix changelog (#14028) - MiniDigger
[PaperMC/Paper] branch deleted: fix/changelog
Summary
Adds an opt-in feature that moves the expensive A* search in mob pathfinding
(PathFinder#findPath) off the main server thread onto a worker pool. Gated
per-world behind entities.behavior.async-pathfinding (default off).
How it works
- The request is prepared on the main thread (validation, world-border
check,EntityPathfindEvent,PathNavigationRegionsnapshot). - Only the expensive A* search runs on a worker pool, using a
thread-confinedPathFindercreated per call — the shared, mutable
NodeEvaluatoronthis.pathFinderis never touched off-thread. - The finished
Pathis applied back on the main thread via the server
executor, so the world mutation model is unchanged. - Only the create-and-apply
moveTo(coords/entity, speed)overloads opt in;
createPath(...)stays fully synchronous, so goals that inspect the path
directly keep exact vanilla behaviour.
Safety / no-regression
- Exceptions in the worker fall...
Not looking forward to this, overworld is over 4TB. Actually not even sure how to do this since we use symlinks for all dimensions atm.
Expected behavior
When compiling against Paper 26.1.2 (or before) using the BookMeta#pages setter methods should also work on a 26.2 server since it is api.
Observed/Actual behavior
[17:35:25 INFO]: TheosRee issued server command: /bookmetatest getter
[17:35:29 INFO]: TheosRee issued server command: /bookmetatest setterArray
[17:35:29 ERROR]: Command exception: /bookmetatest setterArray
java.lang.NoSuchMethodError: 'net.kyori.adventure.inventory.Book org.bukkit.inventory.meta.BookMeta.pages(net.kyori.adventure.text.Component[])'
at TR-Test.jar//de.ree.theos.Test$1.execute(TRBQAddon.java:69) ~[?:?]
at io.papermc.paper.command.brigadier.bukkit.BukkitCommandNode$BukkitBrigCommand.run(BukkitCommandNode.java:83) ~[paper-26.2.jar:26.2-20-2c0341f]
at com.mojang.brigadier.context.ContextChain.runExecutable(ContextChain.java:73) ~[brigadier-1.3.10.jar:?]
at net.minecraft.commands.execution.tasks.ExecuteCommand.execute(ExecuteCommand.java:30)...
Has this been tested on a running server?
How much of this as AI-generated?
I'm strongly against this, TypedKey should just not extends Key, Keyed maybe at best.
Agree with Lulu. It is a bit nasty, a typed key should be able to extend Key, it is identifying something via a namespace and value but the fact that a the plain key implementation considers any key with equal namespace and value equal means we should probably bite the bullet and make this keyed instead. A pretty meh equal impl of KeyImpl imo, idk if this is worth bringing up with adventure folks.
See above, virtual components are weird and do not make sense. But, this is intentional.
Makes sense, thanks both. Agree that having TypedKey extend Keyed rather than Key is the cleaner fix instead of patching equals. That's a breaking API change and a call for you all (and possibly the adventure folks), so I'll close this and leave #13678 for that direction. Appreciate the look.
This is my first time modifying patches let me know if I need to change something about how I did it
Stack trace
Plugin and Datapack List
Paper Plugins (2):
- HuskHomes, HuskSync
Bukkit Plugins (45): - Bolt, Chunky, Citizens, CMI, CMILib, CoreProtect, CoreProtectFilter,
dDiscordBot, Denizen, Depenizen
dynmap, dynmapHider, EffectLib, FastAsyncWorldEdit,
*ForcedGrammar, GuestMode, HeadDatabase, ImageDisplay,
LibsDisguises, LiteBans
LuckPerms, MapModCompanion, MapSync, MCCinema, Multiverse-Core,
MyCommand, NoteBlockAPI, packetevents, PlaceholderAPI, ProtocolLib
PvPToggle, RC_BetterSync, RC_BetterTreasure, RC_EntityCounter,
Shopkeepers, SystemChat, Vault, ViaBackwards, ViaVersion, VoidGen
Votifier, WorldBorder, WorldEditDisplay, WorldGuard,
WorldGuardExtraFlags
Actions to reproduce (if known)
Paper version
paper #48
Other
No response
When the servers data converter, either mojangs DFU or papers data converter, drops a block entity, plugins can loose valuable data they previously stored in the block entity via the persistent data container api.
To implement this, pass the level identifier to the data converter context via the __context tag vanilla already maintains. Both DFU and DC have implementations for the event to ensure the event is available even if the DC feature patch is not in.
Please provide the crash and the exact /version output.
Well feel expected.. in 26.1 the whole BookMeta has a mention for
Warning: in an upcoming version of Paper, this interface will no longer extend Adventure's net.kyori.adventure.inventory.Book
and that pages() method comes from the adventure Book, in 26.2 with the upgrade of Adventure a new method was added but that method return BookMeta and not Book like in the Adventure Book class... so not really sure if this is a thing can be fixed in a nice way because in that case you dont use the return value but in other cases this can happen and cause the same error...
Should probably be rewritten via bytecode for plugins using plugin.yml
In the base game for Java Edition, there is a security flaw with the "/chase" command. By default, it is available to all players, even if they don't have operator privileges. This allows any player with malicious intentions to abuse the tool. I reported this to Mojang, but they refused to address the issue (https://imgur.com/a/chase-exploit-jXYUTD0).
This patch changes the required permission level to 3. This ensures that the command is restricted to operators, which significantly reduces the risk of it being abused. However, the "minecraft.command.chase" permission node can still be used if a server owner wishes to customise who has access to "/chase".
This should be a file patch, but it's worth noting this command is only enabled on servers which doubly opt into this
Yeah this is a debug tool, which should not be enabled on production.
And even if its enabled (what require the owner of the server to make that) you can still block the command with permission minecraft.command.chase like any other vanilla commmand (ex: LuckPerms)
From what I've seen, when Mojang closes an issue as "Won't Fix", that's a sign that they're probably not going to fix it for a long time. By patching the security flaw using a patch, you are preventing people from creating a vulnerability in their server. Even if "/chase" is a debug tool, it should still have a proper security configuration.
looks like ProtocolLib Problem
This server is running Paper version 26.2-48-main@87c4d42
(2026-07-04T14:09:05Z) (Implementing API version
26.2.build.48-alpha)
You are running the latest version
Previous version: 26.2-47-ad5d26a (MC: 26.2)
in 26.1 the whole BookMeta has a mention for
The mention existed for too short amount of time for this level of breakage, such api changes must also be handled by bytecode rewrite (like commodore)
and that pages() method comes from the adventure Book
The signature as shown in the error is on book meta so it shouldn't be hard to swap with an internal static book meta + List -> Book method
Expected behavior
The EntityUnleashEvent should only be called if the sulfur cube was actually leashed, like for other mobs on their death.
Observed/Actual behavior
The EntityUnleashEvent is triggered every single time any TNT sulfur cube explodes, regardless of leash status.
Some plugins assume that if an EntityUnleashEvent is triggered before the leash breaks, the entity is leashed, but since this now no longer the case, IllegalStateException can get thrown when getting the leash holder.
It should be fairly simple to add an isLeashed() check before throwing the event.
Steps/models to reproduce
- Create a plugin that listens to EntityUnleashEvent.
- Spawn a sulfur cube
- Give it TNT
- Ignite it and wait
- Event will be triggered even tho the entity is not leashed
Plugin and Datapack List
Testing plugin
Paper version
Paper version: 26.2-48-main@87c4d42
Other
No response
Fixs https://github.com/PaperMC/Paper/issues/14035 by adding a check for know if the Sulfur Cube is leashed and then call the event like happen with other entities in this event.
I've also read in the release of Adventure 5.0 that there should be no breaking changes and assumed with that it should also be the case for the platform implementations, even when the Book interface just got removed.
And well, the deprecation and removing was in just like 2 weeks, this is not really a huge timeframe ^^
Last to the chaining of methods, they can easily be changed to just not chain on older versions, so that is not really a problem.
A useful next step might be to separate the repro into input, state/cache update, and final output for api-version. That would make it clearer whether “NoSuchMethodError for (removed adventure) Book interface's setter” is failing during parsing/configuration, during internal state updates, or only at the user-visible result.
@hiSandog not so sure how that is related to this issue, do you mean make some sort auto detection of such stuff for the future etc?
Yes, but on static server, i don't have enough ppl to test performance, i think it's 40-50% ai generated
I managed to reproduce this with the following code:
public final class TestPlugin extends JavaPlugin implements Listener {
private Entity victim;
@Override
public void onEnable() {
this.getServer().getPluginManager().registerEvents(this, this);
this.getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS, event -> event.registrar().register(
Commands.literal("tracker-crash")
.executes(ctx -> {
if (!(ctx.getSource().getSender() instanceof Player player))
return Command.SINGLE_SUCCESS;
var base = player.getLocation();
this.victim = player.getWorld().spawn(base.clone().add(0.0, 0.0, 2.0), ArmorStand.class);
player.getScheduler().run(this, _ ->
player.setVelocity(player.getVelocity().add(new Vector(0.0, 0.01, 0.0))), null);
player.sendPlainMessage("waiting for```...
https://github.com/PaperMC/Paper/commit/eb44b4bfd0dbcfa7a5c8c099654407ce9aeb344f takes most of the changes... the only left its publish-pr using other action for access token....
Will be added in a later commit to the workflow files, thanks :>
3f59d1e Add registry api for trim patterns and m... - Machine-Maker
[PaperMC/Paper] branch deleted: feature/registry-trims
f6ce454 Expose client brand to connection (#13931) - Lulu13022002
[PaperMC/Paper] New branch created: feat/pr-review-status
78efa3b Add action to set PR Projects review status - kennytv
Objective#getFormattedDisplayName() is only used internally by vanilla commands ScoreboardCommand and TriggerCommand.
So its unnecessary to build it if its if only a small part of Objective will ever use it.
Is this fixing a bug or something? What exactly is the purpose of this rather than stopping the allocation of this?
I made it cause for example in fastboard when you update title it create a new objective each time, so if you have an animated scoreboard it yust send most of the time creating this Component
I dont wanna bump this more than needed but would like a devteam reply if possible. Is this something that is gonna be fixed eventually or will we forever need to bypass with misc -1 to let it act like vanilla behaviour?
Confirmed the issue on paper 26.1 and 26.2
Expected behavior
Inventorys created via following Code work with the PrepareAnvilEvent
Inventory inventory = Bukkit.createInventory(this, InventoryType.ANVIL, title);
Observed/Actual behavior
Inventorys created via Bukkit.createInventory with a InventoryType of ANVIL do not call the PrepareAnvilEvent
Steps/models to reproduce
Create a InventoryHolder with a getInventory return of InventoryType.ANVIL
Inventory inventory = Bukkit.createInventory(this, InventoryType.ANVIL, title);
Create a Listener for the PrepareAnvilEvent
Observe
Plugin and Datapack List
The Plugin to test this Bug
Paper version
This server is running Paper version 26.2-53-main@3a3d1c0 (2026-07-06T18:15:12Z) (Implementing API version 26.2.build.53-alpha)
You are running the latest version
Previous version: 26.2-47-ad5d26a (MC: 26.2)
Other
No response
That's semi intended, createInventory makes chests with texture, you would want to use https://jd.papermc.io/paper/26.2/org/bukkit/inventory/MenuType.html#ANVIL to make a working anvil inventory
MenuType Anvil doesnt work good with the PrepareAnvilEvent either as it only works when inserting or removing items.
Can I store data with a MenuType like i can with an InventoryHolder?
Is your feature request related to a problem?
The PlayerItemFrameChangeEvent is scoped to player-related triggers only, and there is no general ItemFrameChangeEvent encompassing the other triggers for why an item frame's state might change.
Describe the solution you'd like.
I am curious if Paper would see value in a PR adding some kind of ItemFrameEjectItemEvent, which, unlike PlayerItemFrameChangeEvent, would listen for any item frame ejection, regardless of the entity that caused it.
Or, alternatively, some kind of general ItemFrameChangeEvent which would deprecate PlayerItemFrameChangeEvent, but this may be difficult as I don't see a clean way to handle the consequence of ItemFrameChangeAction's PLACE and ROTATE enumerators being unused in the case of all other entities (in other words, it is not possible afaik for any other entity to have any value for...
This looks like a shared-classpath dependency conflict rather than a plugin bug. A regression plugin that brings protobuf 4.34 transitively through OTLP/Micrometer would help validate any fix, whether that fix is classloader isolation, relocating Paper's bundled connector dependency, or avoiding exposure of mysql-connector-j's protobuf at runtime.
if the exposure of this in the API is not needed for connector-j then this really should be filed as a bug against them, can't really just remove libraries on a whim
mysql-connector-j exposing protobuf is fine in an isolated classloader, that's the setup it's built for. It only collides because Paper puts connector-j and its transitive protobuf on a classpath shared with plugins, which is Paper's call, not connector-j's. A shade upstream would help, but the conflict itself comes from a bundled lib's transitive deps leaking into plugin's code
I can put together an MRE that reproduces this if you'd be willing to take a look? @electronicboy
it is connector-j's call to expose protobuf as a dependency to their API consumers, not ours; Plugins have to be able to access the servers classpath, and so that has impacts on them and us; We can't just blindly remote a library here, if protobuf is NOT a runtime dependency for jconnector at all then jconnector should not expose it as a runtime dependency
you're right that it's connector-j's call but protobuf has a runtime dependency only for the X Protocol path.
standard JDBC never touches mysqlx, which is all plugins use. So it's a real runtime dep for connector-j as a whole, just not one that plugins actually rely on.
the reason I hit this at all is OpenTelemetry, which is a CNCF/Linux Foundation project and pretty much the standard for observability these days. It'd be a shame if the classpath collision effectively made OTLP unusable for plugins, so I'd like to see it resolved one way or another. Would you be able to raise this with the team once more down the line?
this is expected, documented behavior: https://docs.papermc.io/paper/reference/spigot-configuration/#settings_restart_script
we don't plan on changing this.
Thanks for taking the time to look at this. I understand the reasoning that
stop is meant to flush the full server state, that's a fair design stance.
That said, I'd have appreciated a chance to iterate before this was closed
outright. The objection isn't really with the goal - making an ephemeral main
world genuinely non-persistent across restarts, which is a common need for
minigame/lobby networks - but with how it was wired in, by overloading
ticks-per.autosave. That's a legitimate critique, and it's also easy to
address: decouple it into an explicit, dedicated option (e.g. a save-on-stop
world default) that keeps the current behaviour as the default. stop would
still save everything for everyone out of the box, and only operators who
deliberately opt out would see a change. That directly answers the "this has
nothing to do with the autosave setting" point rather than fighting it.
I'd genuinely rather land something clean upstream than carry yet a...
disabling saving entirely comes with a whole load of caveats and expectations around "don't mutate stuff on the disk ever" that we're just not really comfortable trying to promise. changing the promise of some other config option was an inherient no go, but I'm not really sure if this could ever take a shape we'd be happy with, especially with the desired configuration knobs people have asked for here
One more data point - in older versions (around 1.8), the autosave
setting did influence saving behaviour here, so coupling the two wasn't
entirely without precedent to begin with.
An event for items ejected from item frames would close a gap in the current Bukkit event system. The item frame uses setItem() to receive items, and there is already PlayerTakeItemFrameItemEvent for players taking items out. But the frame ejecting an item due to redstone signal or explosion damage is currently only detectable via a EntityChangeBlockEvent listener that checks for item frames - which is unreliable because the event covers too broad a scope.
The new event should extend EntityEvent and expose the item frame and the dropped ItemStack. It should fire in ItemFrameEntity.updateArmorstandMetadata() or the equivalent tick method where the frame releases its held item. Paper already adds custom events for entity interactions that Minecraft doesn't natively expose as events (like PlayerItemFrameChangeItemEvent), so the pattern is established.
The event should also include the cause of the ejection: Cause enum with values like REDSTONE_LOST, EXPLOSI...
The unsafe terrain read during worldgen in 26.2 relates to chunk loading during world generation when another thread is concurrently accessing the same region. The error surfaces from the ChunkMap or ThreadedWorldGeneration code paths where a ConcurrentModificationException or null access occurs because the generator attempts to read a chunk section that has been unloaded or is mid-construction.
In 26.2, the worldgen parallelism changed with the new region-based chunk system. The Detected unsafe terrain read message is thrown by the debug assertion check in ChunkAccess.getBlockState() or similar accessor that validates thread safety. The assertion fires when the access pattern crosses thread boundaries without proper synchronization.
The fix options: either lower the assertion to a warning in production builds (since it doesn't guarantee corruption, just potential data race), or add the proper read lock acquisition in the worldgen paths that access foreign chunks....
Expected behavior
BlockBreakEvent should be cancelled if block wasn't actually broken.
Observed/Actual behavior
BlockBreakEvent fires when player in adventure mode switches item in a last tick while breaking a block,
https://github.com/user-attachments/assets/8a6e9b28-c1aa-4dac-96e4-b162e6351314
look in the chat
Steps/models to reproduce
- Set gamemode in Adventure
- /give @p minecraft:wooden_shovel[can_break={blocks:["minecraft:sand"]}] 1
- Start breaking sand and press F on a last kick
Plugin and Datapack List
none
Paper version
This server is running Paper version 26.1.2-74-ver/26.1.2@e4e17fc (2026-07-06T16:51:09Z) (Implementing API version 26.1.2.build.74-stable)
Other
There is a chance that the fix will be backported to 1.21.11 👉👈
111d388 Deprecate concrete custom tag in favour... - Lulu13022002
Updated your patch to
a) include the comment and
b) to require owner level permission. A command that enables owner level execution of commands should not be available on the admin level.
Approved under the idea that, if somehow there actually is a server owner out there that went out of their way to enable the chase server debug flag and then, in addition to that, somehow thought it was a great idea to make the server public, this patch will prevent them from shooting themselves in the foot even if they probably deserved it at that point.
a313ca1 Require permission level for chase comma... - Mickey42302
Thank you for the PR but paper is currently not interested in maintaining an async pathfinding patch without larger efforts from the team to investigate such a patches maintainability and effect on the server as a whole.
Some other forks attempted this prior and required a lot more diff than your suggested patch :sweat_smile:
[PaperMC/Paper] New branch created: enhancement/deprecate-spawn-friendlies
e78403c Deprecate spawnAnimals spawn flag - lynxplay
The flag has not been maintained by vanilla for a while and the API
should start phasing it out as well. Appropriate events exist for
plugins to hook into natural spawning of animals.
Move the blockActionRestricted check to be made before the event itself is called.
https://github.com/user-attachments/assets/b01e2b59-a6f5-4b69-b4f2-ea7fad0f5568
as you can see in the video, no BBE is called unless I switch back to the correct item (I think that's just a side effect of lag compensation)
The issue is kind of weird from my tests:
https://github.com/user-attachments/assets/fc00290f-72de-4e52-9f48-541887eff2ac
as you can see, it takes a few seconds for the BBE to be incorrectly triggered, and switching back to the correct item instantly triggers the BBE properly. I think this has to do with lag compensation, but I am not too sure. Anyhow, I made a PR attempting to fix it so we'll see what the team thinks about it: https://github.com/PaperMC/Paper/pull/14044
Is your feature request related to a problem?
Yes. The current MCA (Anvil) format uses zlib compression, which is outdated and inefficient for modern large-scale servers. Many server admins are forced to choose between staying on old, unsupported software or losing compatibility with newer, more efficient formats. LeafMC already supports these formats natively, putting Paper at a competitive disadvantage.
Describe the solution you'd like.
Add an experimental (disabled by default) world loading/saving engine that supports LINEAR_V2 and B_LINEAR region formats using ZSTD compression.
- Implement as a config flag (e.g.,
use-region-format: BLINEAR_V3) inpaper-global.yml - Allow conversion via external tools like LuminolMC/region_converter_
- ZSTD offers ~5x faster compression and ~4x faster decompression than zlib (Zstd Benchmarks)
Describe alternatives you'v...
06f4a14 add deprecated annotation - lynxplay
[PaperMC/Paper] branch deleted: enhancement/deprecate-spawn-friendlies
Would love for this to be added, allows protection/claiming plugins to prevent untrusted players from being able to push mobs around in protected regions.
Yes, I totally agree, especially with 26.2. Detecting collisions with the sulfur cube would be really practical.
Hi, would just like to ask if there is currently any blockers causing the linked PR to not be merged?
Expected behavior
No error should occur.
Observed/Actual behavior
During startup, an error occurs in the console:
Starting org.bukkit.craftbukkit.Main
Juli 09, 2026 2:01:27 PM org.jline.terminal.impl.ffm.CLibrary <clinit>
WARNUNG: Unable to find openpty native method in static libraries and unable to load the util library.
- java.lang.UnsatisfiedLinkError: no util in java.library.path: /usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib
The error is only visible in the console and not within the logs.
Steps/models to reproduce
Start a server on Linux with the latest jdk. On Windows the error doesn't occur.
Plugin and Datapack List
Paper version
Affected versions:
26.1.2-74
26.2-56
Most recent version:
This server is running Paper version 26.2-56-main@8cd4f47 (2026-07-09T08:35:16Z) (Implementing API version 26.2.build.56-alpha)
Other
On 1.21.11 with Java 21, the error didn't occur.
What causes the error? Has it an...
What operating system are you running on? Only instance of this error I can find from jline involves someone running AIX.
@mbax It's Ubuntu. Can you eventually explain what the error is about? Then I might be able to help with the research. What changed with Java 25/Minecraft 26.1?
You should be able to ignore it, but updating our jline dependency might fix it
@kennytv Alright. So, you're saying the error is purely cosmetic, without any real impact? Overall, the server boots up and seems to run normally.
Expected behavior
I expected it to launch normally and me being able to easily connect without any issues
Observed/Actual behavior
i launch the run.bat and it launches normally but as soon as it finishes launching, then it just wont respond and nobody can join at all.
Steps/models to reproduce
I have no idea, i will send a compressed zip file of my server files here:
https://drive.google.com/file/d/1bpM8Oh18tCNwb7ENt_h7yg4FjKpY_Mzs/view?usp=sharing
Plugin and Datapack List
Skript, Skbee, FAWE and Worldguard
Paper version
i am running paper 1.21.11
Other
<img width="595" height="380" alt="Image" src="https://github.com/user-attachments/assets/4aebbfd4-64d7-414c-ab2e-709c856a632c" />
Users should visit our Discord for support. This definitely isn't a Paper bug, though.
This is a vanilla bug. The corresponding link is MC-306936. This bug theoretically exists in all versions 1.21.2 and above. A preliminary analysis of this bug has been provided at the link.
Expected behavior
Expected behavior
Piston pushes moss block (which should break and drop) with a sign placed on top in certain orientations, same as vanilla. The sign loses support and drops, moss block breaks and drops.
Observed/Actual behavior
Piston does not extend at all when the sign is placed on the moss block in specific orientations.
Changing the sign orientation makes it work, but vanilla does not have this restriction.
Steps to reproduce
- Place a normal piston facing +X
- Place moss block in front of it
- Place a sign on top of / attached to the moss block (specific orientation: ...)
- Power the piston
- On Vanilla 1.21.1: moss block drops, sign drops, piston extends normally
- On Paper 1.21.1 build 130: piston does not move at all
Paper version
This server is running Paper version git-Paper-130 (MC: 1.21.1)
Plugin list
None / clean test
Additional info
allow-headless-pistons,allow-piston-duplication,allow-permanen...
Please give this a try on the latest 26.2 build with zero plugins and datapacks. 🙂
It works fine on 26-2, but we can't upgrade the server version. Can you provide a fix?
1.21.11 has been unsupported for a while. A few months ago was the time to start your upgrade to 26.1.2!
Sorry to bother you, I tried reproducing it on 1.21.11-130 without any plugins and found it works fine! Really sorry about that! Hope you have a great day.
I've removed the method from the API, it's now just the impl for the deprecated shouldBurnInDay methods as it seems good enough to me for that still, I hope that addresses your concerns
Expected behavior
Given the following setup:
- A wandering trader spawns with two llamas, only one is required for this example
- One llama is 4 blocks closer to the player compared to the trader
If the player moves far enough for the trader (that is slightly farther away than the llama) to not being tracked, but still keeps the llama within tracking distance, when the player comes closer to make the trader appear again, the leash will connect back to the wandering trader.
Observed/Actual behavior
If the player moves far enough for the trader to not being tracked, but still keeps the llama within distance, when the player comes closer to make the trader appear again, the leash will be stuck on the air in the same position the trader was before going out of tracking distance.
Steps/models to reproduce
-
Load the following world with Paper 26.2 build 56 (jar not included):
server.zip -
Fly to the...
Hi, is PR ready? The protection plugin requires it.
This will have my approval in 14 days
Adding false && instead of fully removing this, and comments saying moved up to above and moved up from below would make this seem more maintainable to me
Pretty much all other methods in CraftPlayer silently return if the method is called, so I think it would be best if this also follows that de-facto convention. The javadoc would need updating to remove the throws and line about it only being valid with an initialized connection.
This seems like fine API to have to me, and does already work when tested. One important thing that will either need to be documented or addressed is that the event won't be fired if the server doesn't have code of conducts enabled, or has no txt files configured in the codeofconduct folder.
One important thing that will either need to be documented or addressed is that the event won't be fired if the server doesn't have code of conducts enabled, or has no txt files configured in the codeofconduct folder.
Would it be worth looking into firing it cancelled, making it possible to uncancel in those situations? Like, would that behavior match how other events work or would it be considered a problem for server admins wanting to disable it?
@kacpermajkowski the first two checks are exactly what Mob#checkDespawn
does, but MobCategory#isPersistent isn't part of the despawn path — it's
only used by NaturalSpawner to decide whether to spawn more of that
category. The actual third gate is the per-type
Mob#removeWhenFarAway(double) override, and since that one is dynamic,
the category check breaks on the edge cases: an untamed cat older than
~2 min and a chicken jockey's chicken are despawnable despite CREATURE
being a "persistent" category, and an axolotl that was ever bucketed never
despawns despite AXOLOTLS not being one. It happens to line up for
zombies/cows/wild axolotls, which is why your testing passed. There's no
clean way to replicate it statically since the real check takes a distance
and reads mob state — which is kind of the whole problem with this API.
I feel that pre-cancelled events are generally more of a legacy compat behavioral hack of "we're firing this when it really shouldn't, this is cancelled because no side-effects will occur from this, we just want to let you know" - I guess you could argue that applies here, but I think the reality is that the intent works just fine here, the intent is to send it unless something cancels it, it will just do nothing if there is no data to send, etc
@Lulu13022002 given the rename shape is still open — would you take a
javadoc-only clarification first as an immediate fix, or go straight for
the rename? For the latter, something like Mob#isPersistenceRequired()/
setPersistenceRequired(boolean) could work — mirrors the vanilla name,
and the flag only exists on Mob anyway.
I was viewing it as a "this is where I'd put my code of conduct, IF I HAD ONE!" opportunity for plugins to define their own so server admins don't have to define a dummy one just to get their pre-player code of conduct plugin to work.
Yea, I understand that, my thought was more "empty by default rather than a cancelled boolean", or something to that effect; cancellation to me always felt like it should be more plugin driven rather than api caller driven
Ah, so empty message doesn't send, like the join/quit event messages? That seems reasonable.
Applied the changes and also moved the if check below because the diff was a bit awkward otherwise
Updated to always fire!
I fail to understand why this event would even fire empty if there was no code of conduct.
Is there no API to send a code of conduct?
You can only send the COC inside of configuration mode which is generally a chore for plugins to deal with the whole rigamarole of when the server is already there with the handling for this process anyways
Flow, etc, looks fine to me
Pushed this diff at the advice of @Warriorrrr
-+ if (true || !codeOfConducts.isEmpty()) { // Always fire the task
++ if (io.papermc.paper.event.player.PlayerCodeOfConductSendEvent.getHandlerList().getRegisteredListeners().length > 0 || !codeOfConducts.isEmpty()) { // Fire even if empty, if there are event listeners to potentially send one
These paper comments dont properly wrap the diff
Allow an external service to own the players entity id by exposing an api to set the players entity id during configuration.
entity ids are now per world, I don't exactly understand the usecase for this outside of stuff we generally don't want to support, but as-is this is fairly dangerous
If messing with entity IDs yourself, wouldn't you want to be just bumping the next ID the same way the server does, instead of this? Wouldn't this also be an issue for non-player entities?
Is this for seemless transitions?
Is this for seemless transitions?
Correct it is for seemless transitions, I want to make my velocity proxy own the entity id as im not sending the join game packet to the client anymore
These paper comments dont properly wrap the diff
Took me forever to notice the single linebreak at the bottom. Next time please share the specific issue! 😭
Is this something we should plug into UnsafeValues if we decided to pull something like this.
E.g. via a UnsafeValues#reserveEntityId(PlayerConfigurationConnection, long)?
I do not care to expose entity ids into the public API and this API can literally break everything with a wrong call.
Is this something we should plug into UnsafeValues if we decided to pull something like this. E.g. via a UnsafeValues#reserveEntityId(PlayerConfigurationConnection, long)? I do not care to expose entity ids into the public API and this API can literally break everything with a wrong call.
I think putting this API in UnsafeValues would be a good call, this API does seem good for people with specialized use-cases but I agree making this a public api someone can accidentally mess with seems like a bad call.
Is this something we should plug into UnsafeValues if we decided to pull something like this. E.g. via a UnsafeValues#reserveEntityId(PlayerConfigurationConnection, long)? I do not care to expose entity ids into the public API and this API can literally break everything with a wrong call.
I've went ahead and moved this to UnsafeValues#reserveEntityId(PlayerConfigurationConnection, int), I do agree that its a better spot to have something like this
IMO this should not be part of the API, even in UnsafeValues. Way too easy to break the server in fun ways. And UnsafeValues in general is a bit of a questionable concept to have in general, we really should not add even more to that mess.
I am fine with just the NMS parts of it though. That would put it in a similar position as the ChannelInitializeListener "API", which is also only intended for packet-modifying stuff.
I think getMatchingBlocks should run height then width to match the patterns used to detect, even though the javadocs don't make any promises.
Otherwise, though, tested it out and it gave me the blocks I expected.
IMO this should not be part of the API, even in UnsafeValues. Way too easy to break the server in fun ways. And UnsafeValues in general is a bit of a questionable concept to have in general, we really should not add even more to that mess.
I am fine with just the NMS parts of it though. That would put it in a similar position as the ChannelInitializeListener "API", which is also only intended for packet-modifying stuff.
I mean the alternative to allowing this is listening on the LoginEvent and using NMS/paperweight to modify the entity id of the player yourself then.
But the LoginEvent is deprecated & causes the player to be created prematurely, this simply allows you to do the same thing in a safe manner where the player is not created prematurely and the flow is generally the same.
Like it's "easy to break the server" but I just...
Is your feature request related to a problem?
When using a PersistentDataContainer to hold Booleans, you can basically treat the key existing as the boolean value. So, I figured why not add a way to make a valueless tag so I can just store a NamespacedKey on a PDC and check if it exists.
Describe the solution you'd like.
A new function could be added to PersistentDataContainer
void tag(NamespacedKey key)
All it'd do is run set(key, PersistentDataType.BOOLEAN, false) or something.
Then, you can use PersistentDataContainerView#has and PersistentDataContainer#remove like you would now.
Alt
Three functions would be added to the API (I'm a little unsure of the internal PDC workings, sorry)
Inside PersistentDataContainerView:
boolean hasTag(NamespacedKey key)
Inside PersistentDataContainer:
void tag(NamespacedKey key)void untag(NamespacedKey key)
Alternatively, it could be addTag and removeTag.
These could be stored in a list attached...
Like it's "easy to break the server" but I just don't know how much I love that line of thinking as you quickly end up restricting developer freedom from doing some cool stuff, I mean if someone breaks the server by using a colliding entity id that's their fault and it's clearly documented
What malfrador suggested here is to maintain this as internal "API". E.g. your plugin would require paperweight userdev to effectively do what the PR rn does in UnsafeValues. It is effectively another "beware here be dragons" guard for the method. We'd keep the additional field and methods on the configuration connection impl and have it be applied but it just isn't exposed at all to the normal API but instead requires you to opt into internals via paperweight.
I can kinda see malfs point too, UnsafeValues, while doing unsafe things, generally still is "safe" but possibly breaking and might return unexpected things. I don't have strong feelings either way, but if usage of paperweigh...
How do you plan on managing entity ids both on the proxy and avoiding conflict on the backend, both for existing and then-added entities? Knowing more details of the actual use makes designing this easier
all the periods at the end of these have to be removed
Otherwise good and tested
[PaperMC/Paper] New branch created: feature/do-not-delay-on-minor-file-fix
55d901d Do not delay when running minor file fix - lynxplay
Paper halts the server for 30 seconds when performing the large world
import from 1.21.11 to newer versions.
This should not be performed when applying file fixes for 26.1 to 26.2,
which is a single non applicable file fix.
It'll still be performed when importing a spigot or a vanilla world into
the server, however after the applicable file fixes were run (including
the 1.21.11 to 26.1 file fixes).
This should be fixed once we correctly migrate the place where the paper
migration is executed.
aaa6591 Do not delay when running minor file fix (#14054) - lynxplay
[PaperMC/Paper] branch deleted: feature/do-not-delay-on-minor-file-fix
I think
getMatchingBlocksshould run height then width to match the patterns used to detect, even though the javadocs don't make any promises.
It looks like it is always width then height though?
<img width="1033" height="332" alt="image" src="https://github.com/user-attachments/assets/c1ceefe9-09e9-4f3e-bc8c-9e1db7212ea9" />
<img width="994" height="422" alt="image" src="https://github.com/user-attachments/assets/3df7ab78-9500-4e0c-bdee-ed55a674e3ba" />
I was referring to the pattern used, such as "~^~", "###", "~#~" (where ~ is air, ^ is pumpkin, and # is iron block). See getOrCreateIronGolemFull for what I meant.
It's not a requirement, just when testing my brain was expecting to see ~^~###~#~ but instead got ~#~^##~#~
[00:12:57] [Server thread/INFO]: FifthColumnMC (/213.152.161.54:39237) lost connection: Disconnected
[00:32:07] [Server thread/INFO]: FifthColumnMC (/213.152.161.54:41475) lost connection: Disconnected
[00:39:23] [Server console handler/ERROR]: Caught previously unhandled exception :
java.io.IOError: java.io.IOException: Eingabe-/Ausgabefehler
at org.jline.keymap.BindingReader.readCharacter(BindingReader.java:170) ~[jline-reader-3.20.0.jar:?]
at org.jline.reader.impl.LineReaderImpl.readCharacter(LineReaderImpl.java:901) ~[jline-reader-3.20.0.jar:?]
at org.jline.reader.impl.LineReaderImpl.doList(LineReaderImpl.java:4906) ~[jline-reader-3.20.0.jar:?]
at org.jline.reader.impl.LineReaderImpl.doList(LineReaderImpl.java:4883) ~[jline-reader-3.20.0.jar:?]
at org.jline.reader.impl.LineReaderImpl.doComplete(LineReaderImpl.java:4509) ~[jline-reader-3.20.0.jar:?]
at org.jline.reader.impl.LineReaderImpl.doComplete(LineReaderImpl.java:4347) ~[jline-reader-3.20.0.jar:?]
at org.jlin```...
This reads better than the default "Server performance will be affected" warning it uses
[PaperMC/Paper] New branch created: cat/chore/bump-jline
The bug I was holding back on for this has been resolved, updates jline
to 4.3.1, noting that now we're targetting Java 25 as the base, we no
longer need the JNI terminal; This has been kept for now as jline can use
it for a fallback, but will likely be removed in the future.
https://github.com/PaperMC/Paper/pull/14056 - will bump the jline version and should have a jar to test
This is a standard ubuntu kernel running on a standard x86_64 machine?
f2d7ce8 [ci skip] Fix GraalVmProcessor compile t... - WouterGritter
@electronicboy Yes: [bootstrap] Running Java 25 (OpenJDK 64-Bit Server VM 25.0.3+9-LTS; Eclipse Adoptium Temurin-25.0.3+9) on Linux 5.4.0-231-generic (amd64)
The jar gets called via screen. Nothing special. On 1.21.11 with Java 21 everything worked without problems.
Starting org.bukkit.craftbukkit.Main
Juli 12, 2026 6:55:38 PM org.jline.terminal.impl.ffm.CLibrary <clinit>
WARNUNG: Unable to find openpty native method in static libraries and unable to load the util library.
- java.lang.UnsatisfiedLinkError: no util in java.library.path: /usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib
[18:55:38 INFO]: [bootstrap] Running Java 25 (OpenJDK 64-Bit Server VM 25.0.3+9-LTS; Eclipse Adoptium Temurin-25.0.3+9) on Linux 5.4.0-231-generic (amd64)
[18:55:38 INFO]: [bootstrap] Loading Paper 26.2-DEV-HEAD@c420ed4 (1970-01-01T00:00:00Z) for Minecraft 26.2
The error remains on https://github.com/PaperMC/Paper/pull/14056.
That patch will skip entities if something behind the cursor is removed
[19:08:14 INFO]: [ChunkHolderManager] Saved 0 block chunks, 0 entity chunks, 0 poi chunks in world 'minecraft:the_end' in 0,00s
[19:08:14 INFO]: [ChunkHolderManager] Waiting 60s for chunk I/O to halt for world 'minecraft:the_end'
[19:08:14 INFO]: [ChunkHolderManager] Halted I/O scheduler for world 'minecraft:the_end'
2026-07-12T17:08:14.586221900Z Log4j2-AsyncAppenderEventDispatcher-1-Async ERROR An exception occurred processing Appender TerminalConsole
java.lang.IllegalStateException: Terminal has been closed
at org.jline.terminal.impl.AbstractTerminal.checkClosed(AbstractTerminal.java:796)
at org.jline.terminal.impl.AbstractWindowsTerminal.writer(AbstractWindowsTerminal.java:242)
at org.jline.terminal.impl.AbstractTerminal.flush(AbstractTerminal.java:276)
at org.jline.utils.Display.update(Display.java:786)
at org.jline.utils.Display.update(Display.java:417)
at org.jline.reader.impl.LineReaderImpl.printAbove(LineReaderImpl.jav```...
The terminal errors on stopping are interesting but not entirely too surprising, cleaning up during the server stopping has long been an issue between the logging stuff closing too early due to how that works and plugins in some looser cases, etc. I wonder if this is an issue primarily due to how old that kernel baseline is
Like it's "easy to break the server" but I just don't know how much I love that line of thinking as you quickly end up restricting developer freedom from doing some cool stuff, I mean if someone breaks the server by using a colliding entity id that's their fault and it's clearly documented
What malfrador suggested here is to maintain this as internal "API". E.g. your plugin would require paperweight userdev to effectively do what the PR rn does in UnsafeValues. It is effectively another "beware here be dragons" guard for the method. We'd keep the additional field and methods on the configuration connection impl and have it be applied but it just isn't exposed at all to the normal API but instead requires you to opt into internals via paperweight.
I can kinda see malfs point too, UnsafeValues, while doing unsafe things, generally still is "safe" but possibly breaking and might return unexpected things. I don't have strong feelings either way, but if usage of...
How do you plan on managing entity ids on the proxy and avoiding conflict on the backend, both for existing and then-added entities? Knowing more details of the actual use makes designing this easier in a way that isn't either too convoluted or too dangerous to expose publicly
I increment starting from 1.6 billion instead of 1, so realistically should never collide as the paper backend would have to create 1.6 billion entities before the ranges could collide. Is there a safer way to do this? Probably, but for my use case it should be good enough
Filtering disallowed chat characters before adding the command to the suggestion click event, prevents component serialization from failing on malformed console input and crashing the server instantly.
To Reproduce
- Launch the server
- Type any unicode control chars or
§in the console - Press enter and server crashed
Crash Logs
Description: Exception in server tick loop
java.lang.RuntimeException: Failed to encode Minecraft Component: empty[style={color=gray,clickEvent=SuggestCommand[command=/§]}, siblings=[literal{§}[style={color=red,underlined}], translation{key='command.context.here', args=[]}[style={color=red,italic}]]]; Disallowed chat character: '§'
at io.papermc.paper.adventure.WrapperAwareSerializer.lambda$deserialize$0(WrapperAwareSerializer.java:28)
at com.mojang.serialization.DataResult$Error.getOrThrow(DataResult.java:287)
at io.papermc.paper.adventure.WrapperAwareSerializer.deserialize(WrapperAwareSerializer.jav```...
https://github.com/jline/jline3
@electronicboy Hard to tell what JLine really needs for which setup. Their documentation just states "JLine 4.x requires Java 11 as the minimum runtime version".
Your server isn't breaking on the java part, it's breaking on the "interfacing with the terminal" part
[PaperMC/Paper] branch deleted: feat/pr-review-status
Install ubuntu 20.04 and enabled the ESM junk to get the same kernel version and I cannot reproduce the issue on the latest paper 26.2 jar
Ubuntu 22:
Starting org.bukkit.craftbukkit.Main
[18:36:10 INFO]: [bootstrap] Running Java 25 (OpenJDK 64-Bit Server VM 25.0.1+8-LTS; Eclipse Adoptium Temurin-25.0.1+8) on Linux 5.15.0-177-generic (amd64)
[18:36:10 INFO]: [bootstrap] Loading Paper 26.2-53-main@3a3d1c0 (2026-07-06T18:15:12Z) for Minecraft 26.2
Ubuntu 18:
Starting org.bukkit.craftbukkit.Main
Juli 12, 2026 6:43:21 PM org.jline.terminal.impl.ffm.CLibrary <clinit>
WARNUNG: Unable to find openpty native method in static libraries and unable to load the util library.
- java.lang.UnsatisfiedLinkError: no util in java.library.path: /usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib
[18:43:21 INFO]: [bootstrap] Running Java 25 (OpenJDK 64-Bit Server VM 25.0.1+8-LTS; Eclipse Adoptium Temurin-25.0.1+8) on Linux 5.4.0-150-generic (amd64)
[18:43:21 INFO]: [bootstrap] Loading Paper 26.2-53-main@3a3d1c0 (2026-07-06T18:15:12Z) for Minecraft 26.2
What's interesting, with an even older kernel and Java v...
I was using the kernel version as a proxy to try to figure out the distribution in use, I was going to test 18 as well but I was confused on what kernel version was being provided for that. if this is down to the JDK breaking this you'd basically need to file an issue with them, not sure what their support policy is for supporting outdated distributions however
@electronicboy As https://github.com/PaperMC/Paper/pull/14056 produces addtional problems on Windows with Log4J, without any clear benefit, I'd advice against this change.
However, beside an OS-side fix, I don't know if the native lib loading could be improved on the side of Paper or JLine directly? Or if there are more, other platforms affected?
Expected behavior
Hello,
I am using Paper 26.1.2 (Build 74), and loading or creating a world takes significantly longer than it did with Paper version 1.21.11.
The issue is that the worlds I am importing use a void generator, meaning very few chunks are actually stored in the region folder.
Observed/Actual behavior
[00:51:57 INFO]: Selecting spawn point for level 'minecraft:hub-1'... [00:52:04 INFO]: Loading 0 persistent chunks for level 'minecraft:hub-1'... [00:52:04 INFO]: Preparing spawn area: 100%
Steps/models to reproduce
load and import or creation world (with or without plugin world [Multiverse-core, MultiWorld,...])
Plugin and Datapack List
[01:03:18 INFO]: ℹ Server Plugins (9):
[01:03:18 INFO]: Paper Plugins (1):
[01:03:18 INFO]: - SkBee
[01:03:18 INFO]: Bukkit Plugins (8):
[01:03:18 INFO]: - ConsoleSpamFixReborn, FileCleaner, Multiverse-Core, Skript, skript-db, skript-reflect, TAB, Vault
Paper version
[01:02:15 INFO]: Checking version,...
I believe this will result in some janky undefined behaviour if abused incorrectly. This seems rather unsafe to include in paper itself.
[00:51:57 INFO]: Selecting spawn point for level 'minecraft:hub-1'...
You need a better void generator plugin that overrides spawn point. The server has to generate and load lots of chunks in order to find one, which is a complex pipeline that would explain the 5 second load time
[00:51:57 INFO]: Selecting spawn point for level 'minecraft:hub-1'...
You need a better void generator plugin that overrides spawn point. The server has to generate and load lots of chunks in order to find one, which is a complex pipeline that would explain the 5 second load time
How do I fix it? Is there an in-game solution or a Paper configuration setting?
As I said, using a better void generator that provides a fixed spawn location. Including you can't remove the void generator that you used to generate the world
As I said, using a better void generator that provides a fixed spawn location. Including you can't remove the void generator that you used to generate the world
I use the vanilla world generator (MC Vanilla) and then import it to my server.
Then to fix it use a void world generator plugin instead
Stack trace
I've been working on containerizing paper, and it's going fine enough, but I found some unfortunate behavior in world storage migration between versions. This may be an upstream bug, and if it is, then consider this report a feature request to reimplement/extend the current logic.
As is often the case with containers, I am working with host file systems being mounted into the container's file system (volumes). Since container images are immutable, if you allow the Minecraft world to be created inside the container's file system, you would lose the world as soon as it shuts down.
During one of my tests I spun up a 26.2 paper image (build 47 or so? latest stable), and reused a world that I created in a 1.20.4 paper image. This triggered the automatic storage migration process.
Unfortunately, it appears paper (vanilla Minecraft?) tries to create a new directory and rename the old one or some such operation that assumes <server_cwd>/world and <server_cwd> are on...
Could we create a temporary workaround by not opening the stdin reader until the world is loaded, perhaps?
Fixes #11245
When you open another player's inventory (invsee-style, via player.openInventory(target.getInventory())) and then click an item in your own inventory at the bottom, InventoryClickEvent reports a completely unrelated slot and item. It has been broken since around 1.14.
The top inventory in that case is drawn as a generic 9x4 chest, so it only shows 36 slots. A player inventory, though, reports a size of 41 because it also counts the four armour slots and the off-hand. The slot conversion in CraftAbstractInventoryView keyed off that reported size, so every raw slot in the bottom inventory ended up five out. The first few slots of your own inventory were even treated as part of the top.
This adds a small getTopSlots() hook (it defaults to the current behaviour, so nothing else changes) and, for a player inventory opened in a container, returns the slot count that is actually laid out. With that, convertSlot, getSlotType, and countSlots line up with the...
i have a suggestion to
make this safer, also expose entity id creation for normal entities to userdev so it can be overridden and handled the same way (using proxy and SSOT)
When using the vanilla void preset there is no spawn point calculation, it always uses a fixed point.
I would never ever recommend using a void generator plugin.
If you provide a spark report of when the lag is happening we could look into it.
i have a suggestion to make this safer, also expose entity id creation for normal entities to userdev so it can be overridden and handled the same way (using proxy as SSOT)
how is the proxy meant to
Add a new event to the sulfur cube swallowing an item after the player interaction.
@lynxplay don't mean to be a bother but i closed this PR by mistake and re-opened it, but the project automation bot kept its status in closed in the paper pr queue 😛
Going to close this. Generally would be very low priority with how its Windows-specific and most people have small worlds.
Outright disabling the checks is not a great option, given people run some really weird filesystem setups and the potential risks involved here.
In theory someone could PR a system property to reduce the checks, that would be an acceptable solution.
If you have a very large world, you might want to consider doing a manual migration anyways though. The migration does not delete the old files, so to do an automatic migration with a 4TB world you would need 8TB of disk space.
The Minecraft Wiki changelog for 26.1 lists the file/folder changes in detail, so while its completely unsupported it is possible to carefully migrate your world manually by moving files and using an NBTEditor. For that world size, it might be worth the effort.
I generally like the QoL this event provides. For anyone following along, with PlayerInteractAtEntityEvent, replacing the cube's contained item on interact can be done like so:
@EventHandler
void onInteractWithSulfurCube(PlayerInteractAtEntityEvent event) {
if (!(event.getRightClicked() instanceof SulfurCube cube)) {
return;
}
ItemStack is = event.getPlayer().getInventory().getItemInMainHand();
if (is.getType().asItemType() == ItemType.SHEARS) {
return;
}
if (!cube.getEquipment().getItem(EquipmentSlot.BODY).isEmpty()) {
return;
}
event.setCancelled(true);
cube.getEquipment().setItem(EquipmentSlot.BODY, ItemType.BIRCH_LOG.createItemStack());
event.getPlayer().swingMainHand();
}
With this new event, that is simplified to just this:
@EventHandler
void onSulfurCubeSwallowItem(SulfurCubeSwallowItemEvent event) {
event.setNewItem(ItemType.BIRCH_LOG.createItemStack());
}
Generally, a lot o...
I would replace the <br> with <p> and also fix some punctuation stuff while we are at it.
/**
* Called when a SulfurCube swallows an item.
* <p>
* If the ItemStack is modified, the SulfurCube will swallow the new item
* and not remove the original one from the player's inventory.
* <p>
* If the event is cancelled, the SulfurCube will not swallow the item, and
* it will not be removed from the player's inventory.
*/
The // Paper end comment should contain the full diff.
+ boolean itWorked = this.equipItem(result ? heldItem : org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getNewItem())); // Paper - SulfurCubeSwallowItemEvent
+ // Paper end - SulfurCubeSwallowItemEvent
We have a related but slightly different storage layout that makes the current migration approach a serious blocker for us.
Our server stores the dimensions on separate filesystems and exposes them to Paper through symlinks, for example:
world -> /data/LUN1/world
world_nether -> /data/LUN2/world_nether
world_the_end -> /data/LUN3/world_the_end
The Overworld is currently larger than 4 TB and continues to grow.
If the 26.x migration may temporarily require close to the full size of the existing world again, this effectively prevents us from upgrading. Having another 4+ TB available on the same filesystem only for a one-time migration is not realistic for us, even though the existing world itself fits and runs without any storage problem.
The separate-disk layout also makes the migration more complicated. The final 26.x structure places all dimensions below the main world directory, while in our case the actual dimension data must remain on separate filesystems. Symli...
We have a related but slightly different storage layout that makes the current migration approach a serious blocker for us.
Our server stores the dimensions on separate filesystems and exposes them to Paper through symlinks, for example:
world -> /data/LUN1/world
world_nether -> /data/LUN2/world_nether
world_the_end -> /data/LUN3/world_the_end
The Overworld is currently larger than 4 TB and continues to grow.
If the 26.x migration may temporarily require close to the full size of the existing world again, this effectively prevents us from upgrading. Having another 4+ TB available on the same filesystem only for a one-time migration is not realistic for us, even though the existing world itself fits and runs without any storage problem.
The separate-disk layout also makes the migration more complicated. The final 26.x structure places all dimensions below the main world directory, while in our case the actual dimension data must remain on separate filesystems. S...
Is approximately 2× the world size really the expected worst-case storage requirement, even on filesystems with hard-link support?
There really shouldn't be any large increases in disk usage, only files which are modified end up as temp files on the disk, everything else basically sits as a series of operations to occur, but mojangs logic expects that stuff occurs as atomic operations, otherwise they would actually need to deal with file copying, etc
Can the migration reuse unchanged region files through hard links, or are most large files rewritten and duplicated?
files are not rewritten, they should just be moved
Is there any supported way to pre-create the new directory layout and move the dimensions manually within their existing filesystems before starting 26.x?
This is handled with mojangs filefix mostly, which expects to just be able to move stuff around; But, there are also file operations in here such as splitting the level.dat up, etc; as well as papers...
The punctuation and comments should be all resolved now
Yea I mean, fwiw, the heavy moves across FS (region, entities and poi folder) if you can move them to e.g. migrate_region on the same FS, start the server, let it migrate the world and then move them into the world/dimensions/minecraft/overworld folder.
Notably I don't think this would work too well with nether and end dimension as moving those into the folder is a paper migration and I don't know if we leave "unexpected" folders intact in those worlds.
And well, there is a rather valid reason to have this use a COW fs. Inplace migrating this and the server dying halfway through would be rather deadly.
This PR exposes the NMS-internal SulfurCube#equipItem method as an API-method.
Currently, if you want to set the item swallowed by a SulfurCube, you have to call the following code:
cube.getEquipment().setItem(
EquipmentSlot.BODY,
ItemType.BIRCH_LOG.createItemStack()
);
This is fine if you know about it. However that skips a little bit of logic that's inside the NMS SulfurfCube#equipItem method. Additionally, it's not intuitive for anyone simply scrolling through the SulfurCube API methods.
(Discussion: #paper-contrib message)
If it isn't just a shortcut to editing the equipment I'm not sure I like it being called equipItem. Especially with the potential dropping of another item. I want some more thoughts on naming. I like SulfurCube#swallow(ItemStack)
Well its based in the nms method maybe just a tryEquipItem but the original name is fine to me... (maybe can mention the events for what this method can pass?)
While I can't speak to the large world dilema, I more or less understand electronicboy's response, so it seems that there's probably nothing to worry about in that case (unless a lot of data has to be changed).
For the actual cross-device data issue though, the only 'patch' I can think of off the top of my head that paper could do (recognizing that yeah, this probably is an upstream issue), would be for stuff to be done inside the world folder itself.
i.e.
- mkdir "world/world original"
- mv world/* "world/world original/" # pretend * doesn't capture the new directory
- mkdir "world/world upgraded"
- cd world
- run vanilla world upgrade logic (pointing it to "world original" instead of "world", or just
mkdir world/worldat the start) - cleanup...
granted, if the user has individual directories/files inside world on a different device, this would still not work, but at that point I do think it's somewhat unreasonable to expect that level of indirection
Let's not turn this into an ad or drama tracker please
If you want the fastest compression, you can use the Vanilla option that already exists to change it to lz4, which is considerably faster than zstd still.
If we implemented zstd, it'd likely be taken from https://github.com/PaperMC/Paper/pull/10231 not those versions you mentioned (one of which, by their own admission, is flawed). Compression ratio would likely be slightly worse, but require less memory and be faster. so the specific ask here is a no
Expected behavior
Using BlockData#merge with a BlockData created from string should not throw errors
Observed/Actual behavior
I have a little Skript add-on, and I have a syntax which allows people to get/set block data "tags".
I recently had a report that setting the "rotation" tag on a banner would not work, but it would work on a sign (as expected).
Upon some digging, I noticed this error:
[07:35:37 INFO]: [SkBee ERROR] Could not parse block data: 'minecraft:light_gray_banner[rotation=2]' Message: Block data not created via string parsing
[07:35:37 INFO]: [SkBee ERROR] Stack Trace: com.google.common.base.Preconditions.checkArgument(Preconditions.java:141)
[07:35:37 INFO]: [SkBee ERROR] Stack Trace: org.bukkit.craftbukkit.block.data.CraftBlockData.merge(CraftBlockData.java:82)
Its saying the BlockData was not created from String, even though it most definitely was.
Upon further digging, I see this in CraftBlockData#merge
Preconditions.checkArgument(cra...
I think that the issue here is that you're putting extra data, i.e. the name of a block, into the data string?
Okay, nvm, I'm blind, it's not handling the lack of defined block data from a glance of the messaging
I didn't want to type out a bunch of reflection to test the parsed states, but in Skript we can do that....
So I just wanted to show that with the sign it works perfectly fine, but the banner for some reason the parsedStates are getting lost somewhere
<img width="554" height="195" alt="Image" src="https://github.com/user-attachments/assets/686a40f8-8ebf-43c6-a2fd-733c7e38b5a2" />
In a fast check i notice a thing...
BlockData lightGrayBanner = Bukkit.createBlockData("minecraft:light_gray_banner"); // call convert from string and save to cache (computeIfAbsent)
BlockData lightGrayBannerChange = Bukkit.createBlockData("minecraft:light_gray_banner[rotation=1]"); // call convert from string but get from cache and not use the parseData of the computeIfAbsent
lightGrayBanner.merge(lightGrayBannerChange); // fails because the checkState for extra data coming from parseData not exists
not sure why the cached of minecraft:light_gray_banner[rotation=1] seems to have issues...
Expected behavior
PlayerTeleportEvent#setCancelled(true) should cancel teleportation at all times
Observed/Actual behavior
Mounted to an entity (spectator target) in spectator gamemode, teleporting using the spectator menu (using mouse wheel or keyboard numbers) does NOT cancel the teleportation event.
Steps/models to reproduce
- Write some code to cancel PlayerTeleportEvent. I used this:
public class Main extends JavaPlugin implements Listener {
@Override
public void onEnable() {
getServer().getPluginManager().registerEvents(this, this);
}
// i know Entity shouldn't be cached in a field, but this is just for testing
private final AtomicReference<Entity> target = new AtomicReference<>();
@EventHandler
void onEntityTargetEvent(PlayerStartSpectatingEntityEvent event) {
Entity entity = event.getNewSpectatorTarget();
getServer().getScheduler().runTaskLater(this, () -> {
target.set(entity);```...
Not entirely sure how much changed here, but you're still a spectator of the new entity when you cancel the event, so I'm guessing that the server is just re-aligning their position as like any other failed movement, etc
You don't get mounted to the entity you teleport to though
Expected behavior
The server starts normally and re-generated the missing world_gen_settings.dat file, filling it with default values.
Observed/Actual behavior
The following stack trace (+ log) is printed, after which the server startup process does not continue operation and has to be manually shut down.
Server Log:
||```
[21:24:42 INFO]: [bootstrap] Running Java 25 (Java HotSpot(TM) 64-Bit Server VM 25.0.3+9-LTS-jvmci-b01; Oracle Corporation Oracle GraalVM 25.0.3+9.1) on Linux 7.0.12-arch1-1 (amd64)
[21:24:42 INFO]: [bootstrap] Loading Paper 26.2-DEV (2026-07-14T19:24:42Z) for Minecraft 26.2
[21:24:43 INFO]: [PluginInitializerManager] Initializing plugins...
[21:24:44 INFO]: [PluginInitializerManager] Initialized 2 plugins
[21:24:44 INFO]: [PluginInitializerManager] Paper plugins (1):
- Paper-Test-Plugin (1.0.0-SNAPSHOT)
[21:24:44 INFO]: [PluginInitializerManager] Bukkit plugins (1): - Debuggery (1.5.1)
WARNING: A restricted method in java.lang.System ha```...
I talk about this in a few PRs related to migration...
In vanilla this just happen if delete the dimension and also the file mentioned...
For paper the issue is that file its moved and in migration/regen the fallback try to catch that file fails when overworld was deleted....
The "easy" way can be copy and not move that file for keep the fallback... Or mess with the fallback for generate that file again
(Im in phone but in the PRs for world migration i remember put mentions for that or was in discord....)
This PR https://github.com/PaperMC/Paper/pull/13874 mention that detail... in vanilla you can replicate this but need delete the global file and also the dimension.
just added a missing period to README.md.
just added a missing period to README.md.
We usually do not accept such README PRs, but showing 2 seconds of kindness is a good way of celebrating 20,000 commits I think
Is there another event that is triggered in this situation, that can be cancelled?
Experienced similar issues where some block data merge worked:
BlockData stairs = Material.OAK_STAIRS.createBlockData();
stairs.merge(Material.OAK_LOG.createBlockData("[facing=north]"));
but some others threw the IllegalArgumentException
BlockData oak = Material.OAK_LOG.createBlockData();
oak.merge(Material.OAK_LOG.createBlockData("[axis=y]"));
The old patch also threaded the known name into the events so plugins can serve textures by name. That behaviour is kept, but via guava's get(key, Callable) rather than the previous Pair<UUID, GameProfile> cache key, which made by-name and by-id lookups separate entries for the same UUID. Lookups by id pass a blank name, as before.
Fixes #13652
Related to https://github.com/PaperMC/Paper/commit/eb44b4bfd0dbcfa7a5c8c099654407ce9aeb344f#diff-5c3fa597431eda03ac3339ae6bf7f05e1a50d6fc7333679ec38e21b337cb6721 not sure why a that action was not updated...
This has already been fixed.
In which build of Paper 21.6.2 is it fixed?
Not consuming the original item based on the setter feels weird, that should either just be removed or be a separate method in the event (unless there's many existing events doing the same, but I couldn't think of any)
iirc that's what PlayerItemConsumeEvent does, it doesn't remove the original item if you change it with the setter as said in the javadocs
This event will fire when a player is finishing consuming an item (food, potion, milk bucket).
If the ItemStack is modified the server will use the effects of the new item and not remove the original one from the player's inventory.
If the event is cancelled the effect will not be applied and the item will not be removed from the player's inventory.
I mean both of the implementations will feel weird; removing the item even if it was changed sounds weird since it doesn't use the original item so why remove it? But also not removing feels like something where players could just click on every sulfur cube which is weird too...
I guess it's between choosing what is more appropriate and feels less weird
Set
chunks.auto-save-intervalto -1 should disable level data saving and chunks auto save, if there's no other plugins trying to save or unload the worlds. Chunks will still save on unload. Level data saves on shutdown. Both can be saved by/save-allorWorld.save().There are cases that some chunk data have to syncLoad on server thread, mostly poi searching, can be triggered by for example using eye of ender / entity AI. It may be alleviated by increasing region file cache.
About the async issue.. Mojang does have a async saving logic for other level data (maps, raids, etc.), however for level.dat it's on server thread though it does not require much changes for async. Personally I think there's no reason, maybe Mojang thinks it's a crucial file. However, Their file operations is not atomicly, so it's possible to leave no level.dat file if the process get terminated.
I don't think this is a good idea; I don't want to disable auto-save—it just doesn't sound secur...
How do you guys feel about adding in this event? It says "Status: Accepted" from way back when I first made the suggestion and someone thought it was valid.
Discussion Category: Ideas
Internal testing showed that (without changing region size), storage size of Vanilla worlds at the default compression level is effectively equal to that deflate, and that's with a trained dictionary. zstd is indeed faster, but doesn't come close to lz4, and given the somewhat unfitting/wasteful region format, is "only" 2-3x faster than deflate.
Given that the gains without a dictionary are negative and that maintaining dictionaries takes time and effort both on us and on world upgrades every time a dictionary is replaced (on top of needing to ship every single previous dictionary forever), we decided not to implement it as of now. It would need to be joined with much more drastic storage changes to be worth the effort, i.e. leaf's sector format. Otherwise server owners can/need to train their own dictionaries and deal with the conversion themselves if really wanted
If storage size is your bottleneck, a simple change of the compression algorithm won't help you, if anything...
Expected behavior
Create a ClickEvent without a payload, without crashing, as specified by the API
Observed/Actual behavior
I saw tons of errors in my logs :(
Steps/models to reproduce
Component component = Component.text("Helo!")
.clickEvent(ClickEvent.custom(Key.key("milo", "bilo")));
player.sendMessage(component);
Logs:
[22:26:10 ERROR]: Error sending packet clientbound/minecraft:system_chat
io.netty.handler.codec.EncoderException: Failed to encode packet 'clientbound/minecraft:system_chat'
at net.minecraft.network.codec.IdDispatchCodec.encode(IdDispatchCodec.java:63) ~[paper-26.2.jar:26.2-60-1cb58fb]
at net.minecraft.network.codec.IdDispatchCodec.encode(IdDispatchCodec.java:13) ~[paper-26.2.jar:26.2-60-1cb58fb]
at net.minecraft.network.PacketEncoder.encode(PacketEncoder.java:27) ~[paper-26.2.jar:26.2-60-1cb58fb]
at net.minecraft.network.PacketEncoder.encode(PacketEncoder.java:12) ~[paper-26.2.jar:26.2-```...
I was using this.isEnabled() to check if my plugin was being enabled twice. This caused the init to get messed up because all plugins are marked as enabled before onEnable is executed. I changed it to update enabled after the plugin is enabled/disabled so that people can check this flag in their onEnable functions.
Why the massive diff? From what this does, it seems to me that simply replacing if (isEnable) with if (enabled) and moving the isEnable = enabled; assignment after the if/else would've sufficed.
Anyways, I don't know about potential implications of what this might cause to behave differently, I leave this up to someone with more knowledge in the plugin loading system.
I also changed some of the logic to remove some nesting.
Basically just
if (x) {
// do x
}
to
if (!x) {
return;
}
// do x
Wouldn't this break a lot of api checks like scheduling tasks in onEnable? Also I agree that tons of plugins definitely already depends too much on this behaviour, it's too old to be touched
I could totally run through and find all those checks. That kind of thing should probably use the more specific isBeingEnabled variable, though that currently doesn't have a public accessor. I could add that though!
The big issue is this would break any plugin relying on this behavior in their onEnable.
I don't really understand the usecase here. How is your plugin "being enabled twice"? That should not happen during normal startup, duplicate plugins are simply not loaded.
And plugin enabling/disabling/reloading at runtime is entirely unsupported.
I feel like the proper solution is for your plugin to have this flag that you track and check it instead of isEnable. Even if you increase this pr from a 50 lines change to a 50000 lines change to adapt the rest of the api, you won't be able to adapt the plugins. And if you're fine with isBeingEnabled but you need it in the API and not a private field in your own plugin, then I think this is more of a xy problem that you could get help with in discord instead
Alright, if it's gonna cause trouble, I'll just close this then.
Is your feature request related to a problem?
In the combined 26.2 development changes (#14001), CraftItemStack#asBukkitCopy(net.minecraft.world.item.ItemStack) was changed from public to private, while a new public overload accepting ItemInstance was introduced.
Our project is a dependency library that provides a compatibility layer across multiple Minecraft server versions. Because of that, lower-level conversion methods such as this one are particularly important to us when the required functionality is not consistently available through the public API.
Existing library binaries compiled against previous Paper versions reference the original asBukkitCopy(ItemStack) method directly. Changing its visibility to private causes those binaries to fail on the new version, rather than allowing them to use the new ItemInstance overload.
This breaks the shared compatibility path used across all previously supported...
Why are libraries poking server internals expecting to continue working on future versions?
Why are libraries poking server internals expecting to continue working on future versions?
This is also a very common operation. A GitHub code search shows that many plugins and libraries call this method directly, so the impact is not limited to our project.
We understand that it is an internal API and that compatibility is not guaranteed. However, given its widespread usage and the relatively low cost of retaining the existing overload, we believe this specific case is worth reconsidering. If preserving it is not feasible, we will adapt our compatibility layer accordingly.
Fixs https://github.com/PaperMC/Paper/issues/14072
Looks like since Adventure 5 the BinaryTagHolder for ClickEvent#custom can be null causing issues in the Adventure Codec because mark that field like NonNull, this PR just handle that case for use the correct behaviour.
Why are libraries poking server internals expecting to continue working on future versions?为什么库要干涉服务器内部实现,还指望在未来的版本中继续工作?
Isn't this normal practice? Some operations are impossible with just the encapsulated bukkit methods. Using the internal implementation allows for more flexibility and more possibilities. We can't keep asking you to add new methods every time, and those requests might be rejected. Our use of the internal implementation doesn't affect your server's operation, but your modification makes it unusable for us, requiring us to spend time making compatibility adjustments and increasing the workload for others. If you think we shouldn't access the internal implementation, how can the encapsulated methods perform more operations?
If you think we shouldn't access the internal implementation, how can the encapsulated methods perform more operations?
The question was about asking to revert internal changes, not about the usage. Libraries that are poking around in internals should be preparing compatibility layers for different versions
While I agree that it wouldn't hurt anyone to make this method public again, you should keep in mind that internals are internals, they're not a part of the public stable API. You could for example use MethodHandles to access that method, they are much faster than reflection, almost as fast as direct call, and they would (for now) work for all versions.
Lucky for you I found a reason to update the code there, so I also made that method public again. It's eventually going to break much more than that though, and this is ofc a rare nicety etc. etc.
While I agree that it wouldn't hurt anyone to make this method public again, you should keep in mind that internals are internals, they're not a part of the public stable API. You could for example use MethodHandles to access that method, they are much faster than reflection, almost as fast as direct call, and they would (for now) work for all versions.
This raises a question: if it's almost as fast as a simple call, why go through a detour to execute it when you can call it directly? Secondly, it's encapsulated content; why make it private? I understand you say it's the core logic, but it only converts internal item objects into Bukkit items, which doesn't affect the server's correct operation. Why make it private? You said you created another class; you could keep this and let another class with the same name handle it, instead of removing or making it private. If you use my library, and I make this type of method private in the next update, what will you choose? Continu...
This is internal code, not an exposed part of a library, nobody makes guarantees over the ABI of internals which exist solely for their own code, where practices like the least visibility requires for a method is usually the default.
ItemStacks in the API have been modified a lot over the past few years, methods like a bukkit copy make limited sense when bukkit stacks a wrapper over a mojang stack
Expected behavior
Having a custom argument, which throws a command exception inside its parser, declared before a signed argument type should throw the command exception as normal, whilst not causing a signed command mismatch error.
Observed/Actual behavior
The executing client gets a different exception:
This command had unexpected or missing command argument signatures.
The following errors appear in the console:
[17:43:53 INFO]: Strokkur24 issued server command: /this-crashes-execution hi hi
[17:43:53 ERROR]: Signed command mismatch between server and client ('this-crashes-execution hi hi'): got [signedmessage] from client, but expected []
[17:43:53 WARN]: Failed to update secure chat state for Strokkur24: 'The command had unexpected or missing command argument signatures.'
Additionally, when the very same client that send the command tries to send a chat message, it gets hit with a:
Chat disabled due to broken chain. Please try reconnecting.
```...
3e70398 Pre-load crash report and data fixers off-ain - kennytv
[PaperMC/Paper] New branch created: startup-perf
Mildly disgusting, but that brings startup time down to 7 seconds on my Windows machine (from >8 seconds, or ~8.5 seconds before the last commit)
Why not builders like Thread.ofPlatform().daemon(true).name("CrashReport preload thread").start(CrashReport::preload) to not need the helper method?
Because I haven't been using Java 25 enough 😢
Expected behavior
Migrate world to new format
Observed/Actual behavior
Instantly hits a cross-device link error due to trying to link a file outside the filesystem boundaries.
Steps/models to reproduce
- Make a dataset or filesystem mountpoint for mcserver/world (or any depth down to: world/dimensions/minecraft/overworld for example)
- Install into mcserver/ using a papermc version from earlier this year (Say, a release for 1.21.11)
- Run it
- Stop it once some world generates
- Upgrade
- Run it
- Migration fails due to a hardlink attempt across different filesystems
Plugin and Datapack List
None
Paper version
26.2-38-dev/26.2@58e1f84
Previous version: 26.1.2-61-8dea6f1 (MC: 26.1.2)
(It was also 1.21.11 earlier)
Other
I think this niche problem could be solved by Paper retrying this preparation step with a traditional copy of the world data rather than making a link. Though this would not be very efficient on a CoW filesystem, it w...
Expected behavior
When specifying an item in the dialog body, it should properly apply MiniMessage formatting there, that was the behaviour on PaperMC 1.21.11.
Observed/Actual behavior
<img width="610" height="205" alt="Image" src="https://github.com/user-attachments/assets/3a98045f-c174-4571-9371-bfe974c0c6c5" />
The MiniMessage formatting is completely skipped in dialog body items on latest PaperMC 26.2.
Steps/models to reproduce
I have prepared this sample java code to debug the issue:
String itemName = "stick[custom_name=\"<red>test\",lore=['<gold>This is a test lore line']]";
ItemStack item = Bukkit.getItemFactory().createItemStack(itemName);
data.caster().getEquipment().setItemInMainHand(item);
Dialog dialog = Dialog.create(builder -> {
builder.empty().type(DialogType.notice())
.base(DialogBase.builder(Component.text("Test Dialog"))
.body(List.of(```...
Minimessage formatting is only applied when text is ran through the minimessage serializer, it has never automatically been applied to items like in your example, you need to run it through yourself.
Rebased and change the argument to reachRange based in the last changes in NMS (and the comment of lynx)
Fixes #14064
Retain parsedStates for preloaded BlockData cache entries by storing them on isolated cached copies. This allows merge to correctly handle fully specified string-created BlockData while leaving BlockState-backed instances unchanged
I also added regression tests covering banners and oak logs
Tracked this down to cached block states losing their parsedStates, so I opened a PR with a fix and regression tests based on the examples above
Fixes #14030 with simply re-routing all calls to the BookMeta, which now itself has (or inherits) the relevant methods.
I don't know if or how in that context the api version from the plugin.yml should be respected, but since the interface does no longer exist at all I guess it is not relevant because you just can't compile against it.
I could maybe see a use case for being able to set one part of the rotation relative and the other absolute, which wouldn't be possible with just an
addRotation(yaw, pitch)method. I'm not immediately a fan of the current proposed method since I dislike having ambiguous boolean parameters in methods, something like asetRotation(Something.relative(2f), Something.absolute(90f))could fix that.
I added Angle for that
Allows retrieving the spawn category of an entity type without needing to spawn an instance of it first.
closes #13930
Allows retrieving the spawn category of an entity type without needing to spawn an instance of it first.
closes #13930
Is this already fixed? I’ve waited so long for the behaviour to work and heavily depend on it for my pvp changes
Fixes #13839
Restore synchronous container opening while keeping container closing deferred, and add a regression test
Hi! I opened #14084, which restores synchronous container opening while keeping container closing deferred. This fixes datapacks such as Waystones that rely on the open=true state being observable immediately after block interaction. The PR also includes a regression test covering this behavior
I would like to know if the version check should be dropped (the method with a different signature can't be compiled against 26.2 anyways) and if the added code should be at the start or end of the method. I tried to figure it from the changes but it did not lead me to a fixed result.
I also hope that the removal of the remnant method is ok and if I should also remove the methods which now just call super.
Range annotations should be added to the new params to indicate that they must not be negative, it would also be nice if the javadocs could explain what the param actually does
Range annotations should be added to the new params to indicate that they must not be negative, it would also be nice if the javadocs could explain what the param actually does
the positive annotation not?
for the javadocs... not sure if you have a suggestion for that.. (my way to explaint things its not the best...)
As I couldn’t find a direct way to check whether a world has a World Clock, I quickly added this method.
This is my first PR on Paper, I hope everything’s okay :)
As I couldn’t find a direct way to check whether a world has a World Clock, I quickly added this method.
This is my first PR on Paper, I hope everything’s okay :)
Positive works too as long as IDEs support it, I am just more familiar with jetbrains'.
I don't have any suggestions for the javadocs, just needs to be sufficient enough so that plugin devs can know what it does without needing to ask in paper-dev
Positive works too as long as IDEs support it, I am just more familiar with jetbrains'.
I don't have any suggestions for the javadocs, just needs to be sufficient enough so that plugin devs can know what it does without needing to ask in paper-dev
okay i use the NonNegative (like components) annotation because 0 its a valid number and Positive not allow that...
and for docs... im try something i hope basic explain what this does....
Expected behavior
Clients receive some form of plugin channels as early as possible during configuration phase.
Observed/Actual behavior
It is only send on placeNewPlayer, e.g. in play state.
Steps/models to reproduce
NA
Plugin and Datapack List
NA
Paper version
NA
Other
No response
docs modified with a little of help... i include a mention to a external site for what the algorithms used by internals.
Wouldn't this break if
- it was used in a chain, so
bookMeta.method1().method2()would have had a Book#method2() signature and not a BookMeta#method2(), method1's rewrite to return bookmeta instead of book will break method2 - The result is passed into a non api method that accepts only an adventure book, and it would result in some error as book meta isn't a book anymore
- Yes, any chained call after one of the
pagessetter methods will break with ajava.lang.IncompatibleClassChangeError: Class org.bukkit.craftbukkit.inventory.CraftMetaBookSigned does not implement the requested interface net.kyori.adventure.inventory.Book. When I am correct that can't be fixed easily because that is an independent call to a different interface? Changing that would also rewrite all "legit" calls to adventure books. Having that method at the end of the chain works however since all other methods (author and title) return the BookMeta and not the Book. - That is nothing that I thought of but like my thoughts to 1.: With the
openBookmethod on the player that is kinda legit, but you could also pass the item stack when you work with meta anyways - without you would just work with a Book directly?
Here is my test with the branch::
||java @Override public boolean execute(final CommandSender sender, final String commandLabel, final String[] args)...
Yeah those are harder to fix, that's why in the original issue I mentioned redirecting instead the calls to an internal class with static methods that take the book meta + the arguments and returns an adventure book, this way nothing further should be affected as it's continuing to expect the Book instance
Expected behavior
When a player disconnects, the server releases all references to their ServerPlayer object once nothing legitimate holds it. Specifically, per-map holder tracking (MapItemSavedData.carriedByPlayers and the associated HoldingPlayer records) should remove entries for disconnected players, allowing the player object and any per-player map render state to be garbage collected.
Observed/Actual behavior
Disconnected players' ServerPlayer objects are retained indefinitely. Each map's carriedByPlayers list keeps a strong reference to every player who ever received that map's data; entries are only removed by tickCarriedBy, which never runs again for a departed player (maps displayed in item frames are never "carried" by them again). After 100 players joined, received map data from ~3,600 maps in item frames, and disconnected, a forced full GC left 101 ServerPlayer instances and ~42,000 stale holder records on the heap. Reusing/recycling the map ids (540 r...
Your suggestion works like a charm!
All test calls now work, however any call after the first page just creates a new book and does not modify the Meta anymore, but who would do that anyway? Right?
In my opinion that is fine, lots of deprecated methods become no-op in new version releases without a warning period (and this one had a bit of warning period), while the plugin at least loads. But better wait for a team member to decide
I would also like if I should put another fix for the WritableBookMeta storing the pages as legacy string and converting them leads to that components or if I should put all changes to the Craft classes into a separate PR:
<img width="636" height="148" alt="grafik" src="https://github.com/user-attachments/assets/7aac7f0c-b42f-461e-b530-4288047ee65f" />
Code:
||```java
final Component deserialized = MiniMessage.miniMessage().deserialize("Really");
for (final Material material : new Material[]{Material.WRITTEN_BOOK, Material.WRITABLE_BOOK}) {
final ItemStack book = ItemStack.of(material);
final BookMeta bookMeta = (BookMeta) book.getItemMeta();
bookMeta.title(deserialized).author(deserialized).pages(deserialized);
book.setItemMeta(bookMeta);
player.give(book);
}||
if that breakage isn't realted to this then a seperate PR is preferred, prevents one thing blocking the other needlessly
Sent an enquiry to mojang about it, will see what they say
Hey cat, just wondering if you ever heard back anything regarding this issue?
Nope
well dang.
I'll close this for now, and hopefully a solution can be found.
It wasn't a hard requirement (vanilla just checks for a BedBlock to mark it as occupied), so I removed the BedBlock requirement so sleeping works on any block in my latest push.
Moonrise has a configuration, currently commented, for TPS catchup.
This basically makes this configuration accessible so people that don't want TPS catchup can disable it in their servers.
This addresses the discussion at https://github.com/PaperMC/Paper/discussions/10488.
Some plugins probably still rely on the catchup, although documentation on proper practices has been around for years to not rely on that, plus this is an opt-in feature, since I kept the default value as 5 ticks.
There's a candidate implementation in a downstream fork worth reviewing: rafalohaki/CanvaSigma@65b979c. As far as I can verify, it correctly clears carriedByPlayers, carriedBy, and player decorations. In its 512-map/24-viewer test, retained state falls to the
active-player baseline.
One scaling consideration: this implementation scans the complete global saved-data cache separately for every departing player, and the callback may also run when players leave a level during world/dimension transitions.
This could make two workloads expensive:
- Disconnect storms, where the full catalogue is scanned once per departing player.
- Hub-style servers with frequent world transitions.
One possible approach is to queue departures briefly and perform one catalogue scan for the batch, removing all queued players during
that pass. This would reduce a 100-player storm from 100 catalogue scans to one, while preserving the same cleanup semantics, though the batched pass would n...
As offered above, here are measurements at approximately 50× the downstream test's map catalogue size.
The rig used 25,000 real cached MapItemSavedData instances and 100 Mineflayer clients with 420 holder relationships each, giving 42,000 relationships before departure, on stock Paper 26.2 build 48 (87c4d42). A rig-only reflection plugin performed the same holder removals as the candidate implementation.
Single disconnect
- Per-player scan: 10.934 ms
- One-player batched scan: 9.563 ms
Isolated departures look acceptable at this catalogue size — though not literally free on a server already near its 50 ms tick budget.
100-client disconnect storm
- Control: retained all 42,000 relationships.
- Per-player cleanup: 100 catalogue scans, 1,504.2 ms total measured cleanup.
- Coalesced cleanup: one catalogue scan, 30.308 ms total measured cleanup.
- Both cleanup modes removed all 42,000 relationships.
In this run, coalescing reduced cleanup wor...
Great work kennytv, approved
[PaperMC/Paper] branch deleted: startup-perf
The two Craft* changes don't belong here, but the commodore changes look reasonable
Expected behavior
entity.getData(DataComponentTypes.SULFUR_CUBE_CONTENT); should return the sulfur sube content and not throw an exception.
Observed/Actual behavior
Class cast exception: https://haste.devcord.club/nj1BB8
Steps/models to reproduce
Simply try to access the contents of a sulfur cube using getData
Plugin and Datapack List
<img width="887" height="119" alt="Image" src="https://github.com/user-attachments/assets/43ef09f1-ab7e-4f32-a8d8-e93e827aeb9a" />
Only built in datapacks.
Paper version
This server is running Paper version 26.2-65-main@fc9375a (2026-07-22T08:55:19Z) (Implementing API version 26.2.build.65-beta)
You are running the latest version
Previous version: 26.2-63-3a55f62 (MC: 26.2)
Other
When I try to access the contents of a sulfur cube via the getData() method using this code:
https://haste.devcord.club/8bSbQw
I get the following exception:
https://haste.devcord.club/nj1BB8
Full server log:
https://haste.devcord.club/...
This pull request changes how chunk packets are constructed to send separate Block Entity Update packets based on the block entity's size, and not just on how many block entities are in the chunk.
Each block entity is serialized once to not add overhead for checking the data size:
- If it's not too big or hasn't exceeded the block entity limit per chunk, it's added to the regular block entity data list directly.
- If it is, it's re-serialized as a packet to be sent separately alongside the chunk packet
The client-bound block entity data packet now also has a fallback for when it's too large to be sent, to prevent being kicked.
- A new
AsyncBlockEntityUpdateTooLargeEventis fired - The block entity update is ignored
I was not able to perceive any performance loss for normal or large block entities when profiling, however there is a theoretical tradeoff where large block entities would be serialized twice, this should not matter in most cases
I figured out the cause of this, its because its submitting a request to paper common worker then blocking until it gets a response, its not doing anything computationally expensive, but if the paper common worker pool is overworked i.e doing heavy world gen, it will take a long time to complete newly queued tasks, even if the tasks are priority.BLOCKING
This PR add a new Workflow for label the minecraft version in issues replacing Sniffer (who now is working hard in fill).
This PR addesses https://github.com/PaperMC/Paper/issues/13832
This does not trigger for world generation (when the end portal generates with all eyes)
It also, at the moment of writing this, does not trigger for the end gateway and exit end portal, as those don't have straightforward access to the Entity that will trigger the portal creation.
See:
net.minecraft.world.level.levelgen.feature.EndGatewayFeaturenet.minecraft.world.level.levelgen.feature.EndPodiumFeature
Compared to:
net.minecraft.world.level.levelgen.feature.EndPlatformFeatureat L28net.minecraft.world.level.block.EndPortalBlockat L100
Is your feature request related to a problem?
I would like to log command execution. I can easily track players that try to execute any command with PlayerCommandPreprocessEvent. This event however does not give any insights whether the command was executed successfully or not.
Describe the solution you'd like.
A PostCommandInvocationEvent like velocity has it already, would solve this problem perfectly with a result argument.
Describe alternatives you've considered.
You could just not log the command result, but especially for logging purpose this is extremely helpful to identify irregular behavior.
Other
No response
Discussion Category: Ideas
Genrallly support this, always felt like a huge gap in a world with stuff like command cooldown type plugins, ofc, the api is kinda broken here around commands and how they work (bukkit not making the return success/fail has long been big sad)
Discussion Category: Ideas
What about 26.2?
can confirm in 26.2
This server is running Paper version 26.2-65-main@fc9375a (2026-07-22T08:55:19Z) (Implementing API version 26.2.build.65-beta)
You are running the latest version
Previous version: 26.1.2-72-1a6b910 (MC: 26.1.2)
This PR improvement the logic for PlayerItemConsumeEvent, currently only its called when the use of item reach 0 (consume) this logic works when the consume time is set and its not 0, when its 0 this logic is skipped and the event its not called, for fix this i call this event for that case too and handle the most of logic like happen with the item in use...
This can close https://github.com/PaperMC/Paper/issues/13138
I open a PR for handle this in https://github.com/PaperMC/Paper/pull/14096 with a preview in case any wanna help testing.
for the checks i make the event its now called and the whole behaviour for using items works for the instant use (0 seconds) where the use item logic its not used.
Is your feature request related to a problem?
There is no problem. But this comes from an inconsistency; TNTPrimed and Creeper both have a method to get the igniter of the explosive. ExplosiveMinecart does not.
Describe the solution you'd like.
Add a way to get the igniter of an explosive minecart. TNTPrimed has getSource(), Creeper has getIgniter(), yet ExplosiveMinecart entity has no way to get the igniter.
Describe alternatives you've considered.
I've considered adding data to the persistent data container of the explosive minecart to know who ignited the minecart.
Other
No response
Internally PrimedTnt has a Source and Creeper the Igniter.. but the MinecartTnt not has that logic... exists a ignitionSource (DamageSource) but not sure if handle for this case to expose...
Is your feature request related to a problem?
Currently the air change event only returns the new oxygen ticks, if you wanted to, let's say, make air deplete twice as fast, you would need to know what was the change and multiply that by two, which the API does not currently provide.
Describe the solution you'd like.
To fix the issue the API should provide either a "getOldAmount" or a "getChange" method (or both!)
Describe alternatives you've considered.
The only alternative I could think of is tracking the old tick amount every time the event is called and compare it with the current event, but that's janky
Other
No response
events usually fire before mutation, you should just be able to get the current air level from the entity itself
That feels a bit inconsistent with other events, but if that's the response then I'm fine with that
This fixes wrong crasting in CraftEntity for data components. Closes Issue #14090
There's no reason to use FQN in .java files, those are used only in .patch files to avoid extra diff from imports (other FQN are from pre-hardfork)
can this not just be imported or was there a conflict?
Yes it can be imported, I just used the fqn because I used it in CraftEntity (where I used it because it was done everywhere else), I'll change it real quick
default void playSound(net.kyori.adventure.sound.Sound sound, io.papermc.paper.math.FinePosition pos) {
playSound(sound, pos.x(), pos.y(), pos.z());
default void playSound(net.kyori.adventure.sound.Sound sound, io.papermc.paper.math.FinePosition pos) {
playSound(sound, pos.x(), pos.y(), pos.z());
why not just Position then? Also, wouldn't it make using that method show a warning regarding Position being experimental?
Interesting question—does this mean that, thanks to this very quirk, a dual-dimension mob farm built around Nether portals could outperform vanilla, albeit with a slight lag increase? Mobs teleport one tick earlier the instant they spawn, so the local cap is reached more slowly and more mobs can generate. Has this been fixed yet?
I never expected to have to refute my own self from a year ago. Based on my more detailed testing recently, this non‑vanilla behavior does indeed improve the efficiency of double‑dimension mob farms—by up to a factor of two. This is because the mobs' lifetime is reduced by 1 game tick, which frees up the mob cap earlier, allowing the next batch of mobs to spawn sooner. I tested this using a Zombified Piglin farm that produces 10 million drops in vanilla, and the result was that the output doubled to 20 million. However, as I mentioned before, this also causes slight differences in the position and momentum of entities after they pass through porta...
I changed Location to Position as requested, should be fine now :)
I am not a huge fan of of possibly skipping an entire block entity.
What is the end goal here? What in-game scenario and then plugin response would benefit from this addition?
I can partially understand that a "byte size" threshold might be more relevant than a plain "count" threshold on the oversized block entity logic but I cannot see much use in letting plugins handle an oversized block entity that somehow does not even fit into a ClientboundBlockEntityDataPacket
Make this an IntOr.Default
I partially agree with mbax here, the method name should reflect that this is an attempt at equipping an item. I love cube.nom(ItemStack) /s. SulfurCube#attemptAbsorb / tryAbsorb / absorb would work. So would swallow. Its not really an active equipping.
Javadocs should mention that events are called.
Also unsure about the boolean return, how do I get the itemstack that was possibly dropped from the sulfur cube?
Tho the more I think about it the less convinced I am that this method is even needed in the first place. The use case for actually running the vanilla logic seem small. E.g. how often would a plugin really need to "simulate" a player actively attempting to place a block into a sulfur cube. Most of the times it'd probably be a direct set and playing the noise, which this method does not offer fine control over.
The primary motivation for adding this method seem to be related to API simplicity, which is a fair goal but that could be solved via a p...
The two Craft* changes don't belong here, but the commodore changes look reasonable
As already wrote to mbax in the DC I made these changes to retain the behavior to before the adventure 5 change. After that the Writable Book no longer had colorful pages and the WrittenBook no longer had neither title nor author.
For that reason I see that as required part of the fix to maintain backwards compatibility/have consistent behavior.
@lynxplay
Agree with Lulu. It is a bit nasty, a typed key should be able to extend Key, it is identifying something via a namespace and value but the fact that a the plain key implementation considers any key with equal namespace and value equal means we should probably bite the bullet and make this keyed instead. A pretty meh equal impl of KeyImpl imo, idk if this is worth bringing up with adventure folks.
I don't think that TypedKey should be able to extend Key. It is not really a key by itself, but a tuple of two keys (registry identifier + element identifier). Even if adventure's KeyImpl were to check for the exact class and thereby make this adhere to the contract of equals, it would still be very unintuitive to have two different Keys where namespace and value match but they're not equal. This becomes especially confusing when a TypedKey gets passed into a function that accepts Key and the static type information of one of them being a TypedKey is lost....
Your concerns sound very reasonable. Based on that, would the following changes be accepted?
- Addition of
SulfurCube#setEquipped(ItemStack), with the sole purpose of silently setting the currently equipped item stack, with the goal being API simplicity. - Addition of
ItemStack SulfurCube#getEquipped(), the appropriate getter, same use case as above. - Rename
boolean equipItem(ItemStack)toboolean swallow(ItemStack), noting the events + logical difference tosetEquipped, cross referencing both in@seeJavadoc note?
Yea, sorry there have been some internal chatter. It shouldn't even be Keyed really, it is quite a mess :sweat:
c1408c2 Position riders before API teleportation (#13342) - lynxplay
This all based around the idea that once a packet is too big the player will be kicked from the server.
When a chunk contains an excessive amount of block entities, or a few massive block entities, the player will be kicked and unless the server sends the player to spawn when they rejoin, they won't be able to join back.
In any case, when this is hit we want the safest recovery possible, which in my opinion is skipping the block data and instead showing a "data-less" block.
The new event is useful for server owners / plugin developers as when this happens it's usually a sign of a chunk that may need to be purged or have the block entity be removed, without the event Paper would simply be silently hiding the block data without plugins being able to do something about it.
Well, the question is if a player can actually managed to get kicked from a single blockentity.
The existing logic in place is very much there to prevent the chunk bans that you mention when a chunk is filled with e.g. chests of large utf 8 books.
I have not heard of a single block entity chunk ban yet that would actually require this kind of change.
Yes, a single filled shulker in a shelf block is enough to create a chunk packet large enough to get kicked.
Done, should I also add a constraint to be min 0?
The constraint doesn't do anything since there's a Math.max handling the value, it would be more for clarity
Sounds good yea :+1:
Hi! I’ve previously contributed to the PaperMC documentation, and I’d like to work on this as my first contribution to the Paper codebase.
My proposed scope is to update LootGenerateEvent so its loot-table field, constructor parameter, and getLootTable() return value are correctly marked nullable, and to clarify in the Javadocs that an unknown or unregistered loot table can result in null.
I would leave a possible getLootTableKey() API addition for a separate change because that requires additional API design and may overlap with the loot-table registry work in #13657.
Would this narrower nullability and documentation fix be acceptable?
Please remove the test and squash the change into the file patches otherwise lgtm
Can you create a PR on papermc/docs for this?
Same issue here. Upgraded to experimental from 1.21.3. World folder is on a single volume. Here's a snippet from the log output if it helps:
[17:38:56 WARN]: [WorldFolderMigration] ===================== ! ALERT ! =====================
[17:38:56 WARN]: [WorldFolderMigration] World storage migration is required during startup.
[17:38:56 WARN]: [WorldFolderMigration] If you do not have a backup: interrupt the server now. Use Ctrl+C, your panel kill function, etc.
[17:38:56 WARN]: [WorldFolderMigration] =====================================================
[17:38:56 WARN]: [WorldFolderMigration] Continuing in 30 seconds...
[17:39:26 INFO]: [WorldFolderMigration] Continuing with startup world migration.
[17:39:26 INFO]: Starting upgrade for world "Telvanni"
[17:39:26 INFO]: Upgrading progress: 0%
[17:39:27 INFO]: Upgrading progress: 38%
[17:39:28 INFO]: Upgrading progress: 72%
[17:39:30 INFO]: Upgrading progress: 98%
[17:39:32 INFO]: Upgrading progress: 99%
[17:39:32 INFO]: File```...
This was fixed in 26.3
Fixes #13266
Updates LootGenerateEvent to reflect that its loot table can be null
when the referenced loot table is unknown or unregistered.
This changes the constructor parameter and getLootTable() return value to
@Nullable and clarifies the behavior in the method's Javadocs.
Testing
./gradlew :paper-api:check
Rather than closing this, I think it would be better to backport the fix Mojang did in 26.3
And add a comment to remove the patch once the 26.3 cycle beings
Otherwise 26.2 will throw that error, although it will just be this version anyway
a00ccce Add Adventure playSound(Sound, Position) (#14100) - GliczDev
Is your feature request related to a problem?
Based on the discussion here and [this message](#1530836467763511387 message).
tl;dr of this. is discussion about the usefulness of the various old configuration files - in this case - commands.yml
Describe the solution you'd like.
If we're going to touch commands.yml, it's a good time to make it even more useful and give it some more abilities that will save time from making or looking for plugins having to do with the simplest things regarding commands.
- ability to create commands with basic functionality, like command that sends minimessage message to the command sender
Describe alternatives you've considered.
Using messy plugins like mycommand or skript to alias or create commands that just send text back, which is not ideal, because the aliases made by those commands are usually...
26a624b Add internal API to configure pending pl... - AhmadNasser04
I don't quite think the existing method needs to be deprecated, feels more like it's obsolete at best. Linking to the new method and explaining that it can avoid jitter with relative angles in this method's javadoc would be best imo.
public sealed interface Angle permits AngleImpl {
record AngleImpl(float degrees, boolean relative) implements Angle {
Doesn't look like there's any way for an entity to be removed with this reason and not be added back, so lgtm
Effect validation has been fixed/added in 26.2 as Owen pointed out, and since there doesn't seem to be much interest in a backport of it I will be closing this one instead
[PaperMC/Paper] New branch created: extra-files
cca21cb Don't create help and permissions files by default - kennytv
8a52ce8 Don't create help and permissions files by default - kennytv
[PaperMC/Paper] branch deleted: extra-files
If my comment about making the parameter a Position is applied, these checks should still apply if the passed position is an instance of Location
Position could be used as the param here to indicate that it's only valid for the entity's current world
[PaperMC/Paper] New branch created: extra-files
93ead8f Move version and console history to .paper dir - kennytv
Final thought, maybe this would better for the io.papermc.paper.event.connection.configuration package instead.
What about migration (moving from old directory to new) of existing files? Or, at least, automatic deletion of it... because after that they will become useless?
Also, it would be very nice (at least for me and my team) if the default path to ".paper" directory could be changed via command line argument at server startup, i.e. -DPaper.cacheDirectory=... or --paper-cache-directory ... (similar to already existing --paper-settings-directory) <3
Idk if a migration for any of these is too useful. Deletion sounds like a lot of effort for something server owners could just yank themselves if they cared. Additionally, we do not have that good of a tool to delete them once instead of every server start.
Also, it would be very nice (at least for me and my team) if the default path to ".paper" directory could be changed via command line argument at server startup, i.e.
-DPaper.cacheDirectory=...or--paper-cache-directory ...(similar to already existing--paper-settings-directory) <3
That would be a really nice addition when we are already creating a single source of truth for that in PaperCacheDir :+1:
Is your feature request related to a problem?
A fresh Paper install generates nine config surfaces: server.properties,
bukkit.yml, spigot.yml, commands.yml, permissions.yml, help.yml,
config/paper-global.yml, config/paper-world-defaults.yml, and a paper-world.yml
per world.
bukkit.yml and spigot.yml aren't laid out the way Paper is laid out. They're
laid out the way Bukkit was in 2011 and Spigot was in 2013. Keeping them is
reasonable, but the side effect is that new options land in config/ while the
related old ones stay where they were, so a lot of single knobs are now spread
over two to four files under different names and different units.
Here's what we have with fresh configs:
Dimension toggles. bukkit.yml:
settings:
allow-end: true
paper-global.yml:
misc:
enable-nether: true
Same scope, same meaning. One is allow-, one is enable-. One is under
settings, one is buried in misc. enable-nether was allow-nether in
server.properties b...
Sharing these two files between servers doesn't make any sense
Please do not create issues that are fully or largely LLM-generated, this offers little value to us. Regardless, this is something that's been planned/considered internally already and doesn't really need an issue tracking it.
Sharing these two files between servers doesn't make any sense
I was mostly thinking directly piping the cache dir into a tmp folder so my root dir stays even leaner.
Fwiw, upcoming paperclip changes are going to be using this folder as well. In that regard, changing this dir makes less sense as the dir will exist anyway. Sharing them between servers is def not the goal of the cache dir (console and ver history for example).
It would be better diff-wise and usefulness-wise to instead have an event for modifying the uncertainty, instead of throwing it into the config
LLM is used solely for some verification and formatting; the value of the report is not diminished as a result.
And even though a merge is already planned, there are good points worth keeping and/or considering.
If we wanted to ask AI for input, we'd do it ourselves. Otherwise this just ends up throwing 1000+ words of noise at us
Slightly more complex concept - introducing some form of "command condition", plugins could potentially register new custom conditions to the server too, that could then be used in the commands.yml to allow creating slightly more complicated commands.
Although I am not sure if this would necessarily provide any new functionality over an alias and could just make the file complicated for niche reasons
Valid point, but the Position class is still marked as Experimental, and from what I seen it would need to edit CraftLocation#toBlockPos to get Position and not Location
This should log instead of throwing an exception, not worth potentially crashing things if a not very important file is failed to be moved
Could delete the existing file if target already exists?
Updated for 26.2 & switched it over to DamageSource
the CraftLocation thing isn't much of a concern, but doesn't seem like Position will be un-stabled soon, so ignore that suggestion
05277d4 Expose relative parameters to setRotation (#13901) - Clexus
Yea I think that seems fine. The equip methods can be default in the interface and forward directly there to the correct but maybe hard to know about equipment methods using BODY slot. They should also probably explain that they are a simple alias / utility for that.
Previously, I used PlayerInteractEntityEvent in conjunction with the ItemTag-sulfur_cube_swallowable.
[PaperMC/Paper] New branch created: exp-annotations
255591f Remove experimental annotations from a lot of API - kennytv
Mainly:
- Data components
- Bed enter actions
- Connection
- Inventory view and menu builders
- Structure placement
- Combat tracker
- Server links
- Dialogs
It's not a goal to add the new annotation everywhere that it would realistically fit here, just to where it replaces existing experimental annotations.
Expected behavior
When a repeating ScheduledTask is cancelled while it is running, I would expect it to report CANCELLED_RUNNING until the callback finishes and CANCELLED afterwards.
Observed/Actual behavior
Future runs are cancelled correctly, but the task never leaves CANCELLED_RUNNING. Calling cancel() later also returns NEXT_RUNS_CANCELLED_ALREADY, even though the callback has already finished
I reproduced this with a repeating global-region task on Paper 26.2-83. The callback only ran once, but the state was still CANCELLED_RUNNING one and two seconds after it returned.
Log from the reproduction:
[21:36:47 INFO]: [ScheduledTaskStateRepro] callback-start run=1 state-before-cancel=RUNNING
[21:36:47 INFO]: [ScheduledTaskStateRepro] cancel-during-callback=NEXT_RUNS_CANCELLED
[21:36:47 INFO]: [ScheduledTaskStateRepro] state-after-cancel-in-callback=CANCELLED_RUNNING
[21:36:47 INFO]: [ScheduledTaskStateRepro] callback-returning run=1
[21:36:48```...
Is your feature request related to a problem?
Using paper-26.1.2-74.jar (currently marked as supported on download page).
Currently to ignoreVanillaPermissions you have to set it manually in commands.yml or via
((CraftServer) Bukkit.getServer()).ignoreVanillaPermissions = true;
I'm managing a mini games network, where on each backend server a single plugin exists, that should take control of this backend server and therefore the minigame. I find it a better solution to configure the server to my liking via plugins than via configuration files. As commands.yml was made optional, i'd favor to set this via plugin.
Describe the solution you'd like.
Expose a setter (and maybe a getter) for CraftServer#ignoreVanillaPermissions.
Something like org.bukkit.Server#setIgnoreVanillaPermissions(boolean) and org.bukkit.Server#getIgnoreVanillaPermissions().
I would say, that changing this via plugin is temporary for the current runtime of the server and is not...
Fixes #14107
Repeating scheduled tasks cancelled while they are running currently stop being rescheduled, but remain in CANCELLED_RUNNING after their callback finishes.
This finalizes the cancellation in all three Folia-friendly schedulers once the current execution completes. The task then reports CANCELLED, and later calls to cancel() return CANCELLED_ALREADY.
Rebased, no behavioral changes (hopefully this merges soon)
What about Position? Also, what will happen to the Paper Dialog API once Adventure eventually has one?
Rebased to latest and made the scroll direction more convenient to use. Also fixed an edge case where the direction would be incorrectly set to either +1 or -1 if there are less than 3 item stacks inside the bundle, so the direction is now represented by an enum: forward, backward, unknown
It would be better diff-wise and usefulness-wise to instead have an event for modifying the uncertainty, instead of throwing it into the config
Actually, I joined this just to conveniently set uncertainty to zero. There are already many events related to projectiles, and I'm not sure how to name and implement such a new event.
Is your feature request related to a problem?
Yes it is related, the main problem is that Spigot 26.2-R0.1-SNAPSHOT contains this method and would be very nice if also Paper had also this method since it would make plugins more easly compatible with different server softwares
Describe the solution you'd like.
Add that method
Describe alternatives you've considered.
I've considered using an Adapter that detect which software is running and uses the right method but more work that could be avoided by adding that method
Other
Paper hardforked, whole api newer than 1.21.4 is completely incompatible with spigot. If you want to support both and use api newer than 1.21.4 you need to make 2 different plugins
As far as I can tell this isn't just due to the presence of a requires predicate (i.e., _ -> true works & source.getSender().hasPermission("some.permission") does too (NullCommandSender#hasPermission always returns true)), but more that instanceof Player returns false for the NullCommandSender used when testing whether the node is restricted.
As a workaround you could additionally test if the sender's name is empty when wanting to restrict commands to only
This has been determined to still be something that plugins should rather do
Not sure if can be part of this PR... but with the new annotation can be good include in the generator for all the fields added? (like ItemType or Tags)
Something else that may be worth mentioning is that, tested using only the code from above, it sometimes makes the player move in unexpected ways, including:
[13:00:45 WARN]: JustEli moved too quickly! 9.930077890270105,0.0,-12.614604219647621
And using code that is extremely similar to the above code, I have had players report getting teleported into weird positions, even to the void at Y -300!
If this behavior is as expected, is there a way to detect this "teleportation" because currently it goes under the radar. I can't detect where the player is going, other than for the event that is canceled (but it still happens). This is still an issue on 26.2.
Closes #10708.
CraftMerchantRecipe's scalar setters (setUses, setDemand, setExperienceReward, setSpecialPrice, and so on) write straight through to the backing NMS MerchantOffer, so they take effect the moment you call them. The ingredient methods did not: addIngredient, removeIngredient, and setIngredients were inherited unchanged from the API's MerchantRecipe and only touched the base list. The handle's baseCostA/costB were rebuilt exclusively inside toMinecraft(), which runs on trade refresh, so setExperienceReward(true) applied instantly while setIngredients(...) only landed once the trade screen rebuilt.
The issue asks to make this consistent one way or another. This picks write-through, since it matches the eight existing scalar setters and the fact that getRecipe() hands back a live-backed wrapper. Ingredient changes now sync to the handle immediately; ingredient-agnostic behavior is unchanged.
- Overrides
addIngredient,removeIngredien...
+ if (!event.callEvent()) {
I talk about this in [discord](#paper-contrib message) this PR make a few improvements to allow more uses for the Interaction Entity
- Allow modify behaviour for projectiles, currently the projectile just ignore the entity, this PR allow change that and then you can listen the ProjectileHitEvent, this can help for cases where wanna use a Display and also an Interaction
- Call Damage Events for damages not related to Player, currently only the direct damage by Player are called, other damages are ignored... the PR now call for the others damages in cancel state because the final damage its ignored, i follow the same logic than ArmorStand where the damage events are called even if the entity cannot be damaged (Invulnerable tag)
Expected behavior
Sulfur cube doesn't disappear if PlayerInteractAtEntityEvent cancelled, Bucket in player's hand remains empty.
Observed/Actual behavior
Bucket remains empty, sulfur cube still exists in the world
Steps/models to reproduce
- Install a plugin that has this:
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = false)
public void onPlayerInteractAtEntityEvent(PlayerInteractAtEntityEvent event) {
event.setCancelled(true);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = false)
public void onPlayerInteractAtEntityEventMonitor(PlayerInteractAtEntityEvent event) {
getLogger().info(String.format("PlayerInteractAtEntityEvent %s: %b", event.getRightClicked(), event.isCancelled()));
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = false)
public void onPlayerBucketEntityEvent(PlayerBucketEntityEvent event) {
getLogger().info(String.format("PlayerBucketEntityEvent %s: %b", e```...
Alright, I've gone ahead with the proposed changes. Let me know if the Javadocs' wording is not yet ideal or clear.
Why was this file deleted? I almost feel like this entire package could also be annotated as @MinecraftVersionDependent, as is the case for all tags.
that package not has only DamageTypeTags with deprecations when a TAG its broken?
io.papermc.paper.registry.keys.tags makes more sense keep that annotation
Expected behavior
Setting either 'chat-spam-threshold-seconds' or 'command-spam-threshold-seconds' in server.properties to 0 prevents players from being kicked for spam when sending chat messages/typing commands.
Observed/Actual behavior
On Paper servers, setting these properties to 0 makes it so you can't send any chat messages/commands at all without being kicked from the server for spam.
On vanilla, however, setting these properties simply makes it so players no longer get kicked for spam, as intended.
Steps/models to reproduce
Create a new Paper 26.2 server and set both 'chat-spam-threshold-seconds' and 'command-spam-threshold-seconds' to 0
Start the server
Without being opped, send a single message or type a single command and see what happens.
Plugin and Datapack List
No plugins or datapacks apart from the built-in ones: [vanilla (built-in)], [file/bukkit (world)], [paper (built-in)]
Paper version
[16:13:54 INFO]: Checking version, please w...
i think you can just replace the destroyBlock/setBlock using BlockStateListPopulator like the other clases rather than copy the logic because are still called later
This PR isn't meant to add the annotation everywhere that fits, that's a large task and can be done separately/in smaller steps. This is mainly about removing the experimental annotation.
Position isn't all too useful yet and with Location implementing it doesn't have its immutability promise
I started this PR just trying to fix #14113, but after attempting to clean up the logic, I found that it missed quite a bit of client prediction, so I decided to do a bit of a bigger refactor. More notes on the commit messages.
I also figured it'd be safe to tackle #11496 while I was modifying this part of the code, noting that right now it is safe to not resend tracked entity data for interaction entities as they don't do any client-side prediction.
Opening as a draft as I have yet to test all the cases that have been fixed, I'll try to edit the PR with a video showing the parts that were missed in the previous logic. If someone suffering from #14113 or #11496 wants to test the PR, you can hit me up in the Paper discord if you do find issues
Adds two useful utility methods to the API's CommandSourceStack to make life easier
Expected behavior
A world created or saved by Paper 26.2 beta should be fully compatible with Vanilla 26.2 and NeoForge 26.2.
The world should start without requiring any manual file modifications or file copying.
Observed/Actual behavior
Vanilla 26.2 and NeoForge 26.2 fail to load the world with:
Unable to read or access the world gen settings file!
world/data/minecraft/world_gen_settings.dat
IllegalStateException: Overworld settings missing
The file world/data/minecraft/world_gen_settings.dat is missing.
However, Paper stores world_gen_settings.dat in:
world/dimensions/minecraft/overworld/data/minecraft/world_gen_settings.dat
After manually copying this file to:
world/data/minecraft/world_gen_settings.dat
both Vanilla 26.2 and NeoForge 26.2 start successfully and the world loads correctly.
Steps/models to reproduce
- Create or start a Minecraft 26.2 world using Paper 26.2 beta.
- Stop the Paper server normally.
- Copy...
The world should start without requiring any manual file modifications or file copying.
Not viable due to multi-dimension support in craftbukkit having made a whole bunch of stuff per dimension, retaining support with vanilla is basically unviable here without breaing dimension support in paper (and upsetting a lot of people)