Giter VIP home page Giter VIP logo

sparklypower / sparklypaper Goto Github PK

View Code? Open in Web Editor NEW
102.0 5.0 11.0 2.58 MB

✨ "Ooooh, sparkly paper!" - SparklyPower's Paper fork, making large servers snappier with high-performance optimizations and improvements!

Home Page: https://sparklypower.net/

paper-fork papermc java minecraft bukkit craftbukkit minecraft-api minecraft-performance minecraft-server multithreading performance-multithreading

sparklypaper's Introduction

✨ SparklyPaper ✨

Minecraft Version Blazing Fast

SparklyPower's Paper fork, making large servers snappier with high-performance optimizations and improvements! Focused on performance improvements for Survival servers with high player counts.

Our fork has handmade patches to add and optimize some of the things that we have in our server, with some cherry-picked patches from other forks.

ATTENTION - PLEASE READ!

SparklyPaper is a fork tailor-made for our Survival server, SparklyPower. It doesn't strive to be a public stable Paper fork like Purpur, Pufferfish, and other similar forks.

We do provide SparklyPaper builds if you want to use it in your server, but keep in mind that we won't provide support for it! If your server has issues while using SparklyPaper, or if it explodes, we won't help you!

This also means that unless a PR fixes an issue that we are having in SparklyPower, we (probably) won't accept it!

If you have the know how, we recommend making your own Paper fork and copying the SparklyPaper's patches that you need for your server.

Features

This does not include all patches included in SparklyPaper, only the patches handmade for SparklyPaper! To see all patches, check out the "patches" directory.

SparklyPaper's config file is sparklypaper.yml, the file is, by default, placed on the root of your server.

  • Skip distanceToSqr call in ServerEntity#sendChanges if the delta movement hasn't changed
    • The distanceToSqr call is a bit expensive, so avoiding it is pretty nice, around ~15% calls are skipped with this check. Currently, we only check if both Vec3 objects have the same identity, that means, if they are literally the same object. (that works because Minecraft's code reuses the Vec3 object when caching the current delta movement)
  • Skip MapItem#update() if the map does not have the default CraftMapRenderer present
    • By default, maps, even those with custom renderers, fetch the world data to update the map data. With this change, "image in map" maps that have removed the default CraftMapRenderer can avoid these hefty updates, without requiring the map to be locked, which some old map plugins may not do.
    • This has the disadvantage that the vanilla map data will never be updated while the CraftMapRenderer is not present, so if you readd the default renderer, the server will need to update the map data, but that's not a huuuge problem, after all, it is a very rare circumstance that you may need the map data to always be up-to-date when you have a custom renderer on the map.
    • But still, if you made your own custom "image on map" plugin, don't forget to mapView.isLocked = true to get the same performance benefits in vanilla Paper!
  • Fix concurrency issues when using imageToBytes in multiple threads
    • Useful if one of your plugins is parallelizng map creation on server startup
  • Skip dirty stats copy when requesting player stats
    • There's literally only one getDirty call. Because the map was only retrieved once, we don't actually need to create a copy of the map just to iterate it, we can just access it directly and clear it manually after use.
  • Avoid unnecessary ItemFrame#getItem() calls
    • When ticking an item frame, on each tick, it checks if the item on the item frame is a map and, if it is, it adds the map to be carried by the entity player
    • However, the getItem() call is a bit expensive, especially because this is only really used if the item in the item frame is a map
    • We can avoid this call by checking if the cachedMapId is not null, if it is, then we get the item in the item frame, if not, then we ignore the getItem() call.
    • Replaced by Warriorrrr's "Rewrite framed map tracker ticking" patch (Paper #9605)
  • Optimize EntityScheduler's executeTick
    • On each tick, Paper runs EntityScheduler's executeTick of each entity. This is a bit expensive, due to ArrayDeque's size() call because it ain't a simple "get the current queue size" function, due to the thread checks, and because it needs to iterate all server entities to tick them.
    • To avoid those hefty calls, instead of iterating all entities in all worlds, we use a set to track which entities have scheduled tasks that we need to tick. When a task is scheduled, we add the entity to the set, when all entity tasks are executed, the entity is removed from the set. We don't need to care about entities that do not have any tasks scheduled, even if the scheduler has a tickCount, because tickCount is relative and not bound to the server's current tick, so it doesn't matter if we don't increase it.
    • Most entities won't have any scheduled tasks, so this is a nice performance bonus, even if you have plugins that do use the entity scheduler because, for 99,99% of use cases, you aren't going to create tasks for all entities in your server. With this change, the executeTick loop in tickChildren CPU % usage drops from 7.60% to 0.00% (!!!) in a server with ~15k entities! Sweet!
      • Yeah, I know... "but you are cheating! the loop doesn't show up in the profiler because you replaced the loop with a for each!" and you are right! Here's a comparison of the tickChildren function CPU usage % between vanilla Paper and SparklyPaper, removing all other functions from the profiler result: 7.70% vs 0.02% (wow, such improvement, low mspt)
    • Of course, this doesn't mean that ArrayDeque#size() is slow! It is mostly that because the executeTick function is called each tick for each entity, it would be better for us to avoid as many useless calls as possible.
  • Blazingly Simple Farm Checks
    • Changes Minecraft's farm checks for crops, stem blocks, and farm lands to be simpler and less resource intensive
    • If a farm land is moisturised, the farm land won't check if there's water nearby to avoid intensive block checks. Now, instead of the farm land checking for moisture, the crops themselves will check when attempting to grow, this way, farms with fully grown crops won't cause lag.
    • The growth speed of crops and stems are now fixed based on if the block below them is moist or not, instead of doing vanilla's behavior of "check all blocks nearby to see if at least one of them is moist" and "if the blocks nearby are of the same time, make them grow slower".
      • In my opinion: Who cares about the vanilla behavior lol, most players only care about farm land + crop = crop go brrrr
    • Another optimization is that crop behavior can be changed to skip from age zero to the last age directly, while still keeping the original growth duration of the crop. This way, useless block updates due to crop growth can be avoided!
    • (Incompatible with Paper's Dry and Wet Farmland custom tick rates)
  • Spooky month optimizations
    • The quintessential patch that other performance forks also have for... some reason??? I thought that this optimization was too funny to not do it in SparklyPaper.
    • Caches when Bat's spooky season starts and ends, and when Skeleton and Zombies halloween starts and ends. The epoch is updated every 90 days. If your server is running for 90+ days straight without restarts, congratulations!
    • Avoids unnecessary date checks, even tho that this shouldn't really improve performance that much... unless you have a lot of bats/zombies/skeletons spawning.
  • Cache coordinate key used for nearby players when ticking chunks
    • The getChunkKey(...) call is a bit expensive, using 0.24% of CPU time with 19k chunks loaded.
    • So instead of paying the price on each tick, we pay the price when the chunk is loaded.
    • Which, if you think about it, is actually better, since we tick chunks more than we load chunks.
  • Optimize canSee(...) checks
    • The canSee(...) checks is in a hot path (ChunkMap#updatePlayers()), invoked by each entity for each player on the server if they are in tracking range, so optimizing it is pretty nice.
    • First, we change the original HashMap to fastutil's Object2ObjectOpenHashMap, because fastutil's containsKey throughput is better.
    • Then, we add a isEmpty() check before attempting to check if the map contains something. This seems stupid, but it does seem that it improves the performance a bit, and it makes sense, containsKey(...) does not attempt to check the map size before attempting to check if the map contains the key.
  • Fix MC-117075: TE Unload Lag Spike
    • Paper already has a patch that fixes the lag spike, however, we can reduce the lag even... further, beyond!
    • We replaced the blockEntityTickers list with a custom list based on fastutil's ObjectArrayList with a small yet huge change for us: A method that allows us to remove a list of indexes from the list.
      • This is WAY FASTER than using removeAll with a list of entries to be removed (which is what Paper currently does), because we don't need to calculate the identity of each block entity to be removed, and we can jump directly to where the search should begin, giving a performance boost for small removals (because we don't need to loop thru the entire list to find what element should be removed) and a performance boost for big removals (no need to calculate the identity of each block entity).
  • Optimize tickBlockEntities
    • We cache the last shouldTickBlocksAt result, because the shouldTickBlocksAt is expensive because it requires pulling chunk holder info from an map for each block entity (even if the block entities are on the same chunk!) every single time. So, if the last chunk position is the same as our cached value, we use the last cached shouldTickBlocksAt result!
      • We could use a map for caching, but here's why this is way better than using a map: The block entity ticking list is sorted by chunks! Well, sort of... It is sorted by chunk when the chunk has been loaded, newly placed blocks will be appended to the end of the list until the chunk unloads and loads again. Most block entities are things that players placed to be there for a long time anyway (like hoppers, etc)
      • But here's the thing: We don't care if we have a small performance penalty if the players have placed new block entities, the small performance hit of when a player placed new block entities is so small ('tis just a long comparsion after all), that the performance boost from already placed block entities is bigger, this helps a lot if your server has a lot of chunks with multiple block entities, and the block entities will be automatically sorted after the chunk is unloaded and loaded again, so it ain't that bad.
    • And finally, we also cache the chunk's coordinate key when creating the block entity, which is actually "free" because we just reuse the already cached chunk coordinate key from the chunk!
  • Reset dirty flag when loading maps from the disk
    • By default, the server will start rewriting all map datas to the disk after loading it, even if the map didn't have any changes
    • This also slows down world saving a lot if you have a lot of maps if you have an "image on map" plugin that preloads all maps during server startup
  • Check how much MSPT (milliseconds per tick) each world is using in /mspt
    • Useful to figure out which worlds are lagging your server. Per World MSPT
  • Parallel World Ticking

While we could cherry-pick everything from other forks, only patches that I can see and think "yeah, I can see how this would improve performance" or patches that target specific performance/feature pain points in our server are cherry-picked! In fact, some patches that are used in other forks may be actually borked...

Upstreamed Optimizations & Features

These optimizations and features were originally in SparklyPaper, but now they are in Paper, yay! Thanks Paper team :3

  • Lazily create LootContext for criterions (Merged in Paper #9969)
    • For each player on each tick, enter block triggers are invoked, and these create loot contexts that are promptly thrown away since the trigger doesn't pass the predicate.
    • To avoid this, we now lazily create the LootContext if the criterion passes the predicate AND if any of the listener triggers require a loot context instance.
  • Remove unnecessary durability check in ItemStack#isSimilar(...) (Merged in Paper #9979)
    • I know that this looks like a stupid optimization that doesn't do anything, but hear me out: getDurability() ain't free, when you call getDurability(), it calls getItemMeta(), which then allocates a new ItemMeta or clones the current item's item meta.
    • However, this means that we are unnecessarily allocating useless ItemMeta objects if we are comparing two items, or one of the two items, that don't have any durability, and this impact can be noticed if one of your plugins has a canHoldItem function that checks if a inventory can hold an item.
    • To avoid this, we can just... not check for the item's durability! Don't worry, the durability of the item is checked when it checks if both item metas are equal.
    • This is a leftover from when checking for the item's durability was "free" because the durability was stored in the ItemStack itself, this was changed in Minecraft 1.13.
    • (The reason I found out that this had a performance impact was because the getDurability() was using 0.08ms each tick according to spark... yeah, sadly it ain't a super big crazy optimization, the performance impact would be bigger if you have more plugins using isSimilar(...) tho)
  • Configurable Farm Land moisture tick rate when the block is already moisturised (Merged in Paper #9968)
    • The isNearWater check is costly, especially if you have a lot of farm lands. If the block is already moistured, we can change the tick rate of it to avoid these expensive isNearWater checks.
    • (Incompatible with the Blazingly Simple Farm Checks feature)

We attempt to upstream everything that we know helps performance and makes the server go zoom, and not stuff that we only hope that it improves performance. I'm still learning after all, so some of my patches may be worthless and not good enough. :)

Results

If you are curious about SparklyPaper's performance, check out our results page!

Support

Because this is a fork made for SparklyPower, we won't give support for any issues that may happen in your server when using SparklyPaper. We know that SparklyPaper may break some plugins, but unless we use these plugins on SparklyPower, we won't go out of our way to fix it!

If you only care about some of the patches included in SparklyPaper, it is better for you to create your own fork and cherry-pick the patches, this way you have full control of what patches you want to use in your server, and even create your own changes!

Downloads

There are two kinds of builds: One with the Parallel World Ticking feature, and another without it. If you don't want to risk using a very experimental feature that may lead to server crashes and corruption, or if you aren't a developer that can't fix plugin issues related to the feature, then use the version without Parallel World Ticking! (We do run Parallel World Ticking in production @ SparklyPower tho, we live on the edge :3)

It is recommended to use a Mojang mapped (mojmap) version unless if you really have a reason (example: plugins that break on a mojmap JAR) to use a Spigot mapped (reobf) version. Paper, since 1.20.5, provides a mojmapped server JAR and remaps any class/field/Reflection access made by non-mojmap aware plugins, so things (hopefully!) shouldn't break.

Click on a workflow run, scroll down to the Artifacts, and download!

sparklypaper's People

Contributors

lorittamorenitta avatar mrpowergamerbr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

sparklypaper's Issues

Very good

Veryy interesting and good project. Keep it up <3

1.20.6 upstreams?

Hi, I'm just wondering if the 1.20.6 branch will still get updates or you're focused on 1.21 development now?

Pufferfish's Async Mob Spawning

Hi, is it possible to add pufferfish's Async Mob spawning? I noticed my server lags at 100+ players because I think the spawning of entities are not done in Async.

Pufferfish was recently updated to 1.20.6 so you can check it out.

log of respawning player

[STDOUT] [net.minecraft.server.players.PlayerList] respawning player - current player container is net.minecraft.world.inventory.ContainerPlayer@42958eff but their inventory is net.minecraft.world.inventory.ContainerPlayer@42958eff

Is it normal? Because it's referencing same inventory but it says "but" in log. Like it was expected something else.

Inventory Error?

image

This keeps showing up on my console and Idk what's causing it

Exception ticking world

I simply downloaded the jar and put it on the server and started it (clean install), and then these errors came up.

image
image

Worldedit not working properly

The worldedit plugin is not working properly. Here is what commonly happens:

  • //set a large area sometimes causes an unprocessed chunk
  • //paste a large build sometimes causes an unprocessed chunk
  • //copy -e and //paste -e sometimes doesn't keep the entities
  • //up doesn't work properly
  • //ascend doesn't work properly

Question

What performance benefits does Parallel World Ticking provide?
Do Pathfinder, Entity Tracker, etc. work asynchronously between worlds?

feature request: giant ai

Hey there,

I know this fork aims to improve performance on high playercounts. Also that's why this is very important for us. There might be some server owners who use Purpur and consider to switch their server software with SparklyPaper.

I just wanted to ask, could you add Giant's AI to server internal, like Purpur did? Mojang removed Giant's AI in 1.8 and it didn't add back. I really need this feature. Also I opened this issue on Paper's issue page but it would be nice if SparklyPaper add this feature to itself.

Thanks for this good fork.

Exception related to portals in The End

TODO: Debug this further

I don't think this is related to player portal ticks? Maybe a entity fell on a portal and that's causing problems?

Took this long to find this issue because we don't use normal Nether/End portals on SparklyPower lol

When running the server with hard throws disabled, the server does actually crash because it attempts to query the chunks of another world.

[18:39:26] [serverlevel-tick-worker [EtaTheEnd]/ERROR]: THE SERVER IS GOING TO CRASH! - Thread serverlevel-tick-worker [EtaTheEnd] failed main thread check: Cannot query another world's (world) chunk (25, 16) in a ServerLevelTickThread - Is tick thread? true; Is server level tick thread? true; Currently ticking level: EtaTheEnd; Is iterating over levels? true; Are we going to hard throw? true
java.lang.Throwable: null
        at net.minecraft.server.level.ServerChunkCache.getChunk(ServerChunkCache.java:272) ~[?:?]
        at net.minecraft.world.level.Level.getChunk(Level.java:900) ~[?:?]
        at net.minecraft.world.level.Level.getChunk(Level.java:839) ~[?:?]
        at net.minecraft.world.level.Level.getChunkAt(Level.java:825) ~[?:?]
        at net.minecraft.world.entity.Entity.findDimensionEntryPoint(Entity.java:3730) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"ad57a12"]
        at net.minecraft.world.entity.Entity.teleportTo(Entity.java:3592) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"ad57a12"]
        at net.minecraft.world.entity.Entity.tickEndPortal(Entity.java:531) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"ad57a12"]
        at net.minecraft.world.entity.Entity.handleNetherPortal(Entity.java:3124) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"ad57a12"]
        at net.minecraft.world.entity.Entity.postTick(Entity.java:808) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"ad57a12"]
        at net.minecraft.server.level.ServerLevel.tickNonPassenger(ServerLevel.java:1395) ~[?:?]
        at net.minecraft.world.level.Level.guardEntityTick(Level.java:1328) ~[?:?]
        at net.minecraft.server.level.ServerLevel.lambda$tick$8(ServerLevel.java:908) ~[?:?]
        at net.minecraft.world.level.entity.EntityTickList.forEach(EntityTickList.java:49) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"ad57a12"]
        at net.minecraft.server.level.ServerLevel.tick(ServerLevel.java:888) ~[?:?]
        at net.minecraft.server.MinecraftServer.lambda$tickChildren$15(MinecraftServer.java:1621) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"ad57a12"]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572) ~[?:?]
        at java.util.concurrent.FutureTask.run(FutureTask.java:317) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[?:?]
        at java.lang.Thread.run(Thread.java:1583) ~[?:?]
[18:39:26] [serverlevel-tick-worker [EtaTheEnd]/ERROR]: Entity threw exception at EtaTheEnd:1.4327545604115497,61.0,1.5756690891092255
java.lang.IllegalStateException: Cannot query another world's (world) chunk (25, 16) in a ServerLevelTickThread
        at net.minecraft.server.level.ServerChunkCache.getChunk(ServerChunkCache.java:274) ~[?:?]
        at net.minecraft.world.level.Level.getChunk(Level.java:900) ~[?:?]
        at net.minecraft.world.level.Level.getChunk(Level.java:839) ~[?:?]
        at net.minecraft.world.level.Level.getChunkAt(Level.java:825) ~[?:?]
        at net.minecraft.world.entity.Entity.findDimensionEntryPoint(Entity.java:3730) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"ad57a12"]
        at net.minecraft.world.entity.Entity.teleportTo(Entity.java:3592) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"ad57a12"]
        at net.minecraft.world.entity.Entity.tickEndPortal(Entity.java:531) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"ad57a12"]
        at net.minecraft.world.entity.Entity.handleNetherPortal(Entity.java:3124) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"ad57a12"]
        at net.minecraft.world.entity.Entity.postTick(Entity.java:808) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"ad57a12"]
        at net.minecraft.server.level.ServerLevel.tickNonPassenger(ServerLevel.java:1395) ~[?:?]
        at net.minecraft.world.level.Level.guardEntityTick(Level.java:1328) ~[?:?]
        at net.minecraft.server.level.ServerLevel.lambda$tick$8(ServerLevel.java:908) ~[?:?]
        at net.minecraft.world.level.entity.EntityTickList.forEach(EntityTickList.java:49) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"ad57a12"]
        at net.minecraft.server.level.ServerLevel.tick(ServerLevel.java:888) ~[?:?]
        at net.minecraft.server.MinecraftServer.lambda$tickChildren$15(MinecraftServer.java:1621) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"ad57a12"]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572) ~[?:?]
        at java.util.concurrent.FutureTask.run(FutureTask.java:317) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[?:?]
        at java.lang.Thread.run(Thread.java:1583) ~[?:?]

Redstone shinanigans with non alternate-current

Redstone lag machine randomly crashes server 🤨
Simple redstone stuff sometimes (and sometimes not?!?) crushes server with exeption:

[19:04:59 ERROR]: Encountered an unexpected exception
java.lang.RuntimeException: java.util.concurrent.ExecutionException: net.minecraft.ReportedException: Exception while updating neighbours
        at net.minecraft.server.MinecraftServer.tickChildren(MinecraftServer.java:1818) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at net.minecraft.server.dedicated.DedicatedServer.tickChildren(DedicatedServer.java:464) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at net.minecraft.server.MinecraftServer.tickServer(MinecraftServer.java:1520) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:1221) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:324) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at java.lang.Thread.run(Thread.java:833) ~[?:?]
Caused by: java.util.concurrent.ExecutionException: net.minecraft.ReportedException: Exception while updating neighbours
        at java.util.concurrent.FutureTask.report(FutureTask.java:122) ~[?:?]
        at java.util.concurrent.FutureTask.get(FutureTask.java:191) ~[?:?]
        at net.minecraft.server.MinecraftServer.tickChildren(MinecraftServer.java:1815) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        ... 5 more
Caused by: net.minecraft.ReportedException: Exception while updating neighbours
        at net.minecraft.server.MinecraftServer.lambda$tickChildren$16(MinecraftServer.java:1807) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) ~[?:?]
        at java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[?:?]
        ... 1 more
Caused by: java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1013) ~[?:?]
        at java.util.ArrayList$Itr.next(ArrayList.java:967) ~[?:?]
        at com.destroystokyo.paper.util.RedstoneWireTurbo.breadthFirstWalk(RedstoneWireTurbo.java:633) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at com.destroystokyo.paper.util.RedstoneWireTurbo.updateSurroundingRedstone(RedstoneWireTurbo.java:807) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at net.minecraft.world.level.block.RedStoneWireBlock.updateSurroundingRedstone(RedStoneWireBlock.java:273) ~[?:?]
        at net.minecraft.world.level.block.RedStoneWireBlock.neighborChanged(RedStoneWireBlock.java:544) ~[?:?]
        at net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase.neighborChanged(BlockBehaviour.java:1234) ~[?:?]
        at net.minecraft.world.level.redstone.NeighborUpdater.executeUpdate(NeighborUpdater.java:66) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at net.minecraft.world.level.redstone.CollectingNeighborUpdater$SimpleNeighborUpdate.runNext(CollectingNeighborUpdater.java:160) ~[?:?]
        at net.minecraft.world.level.redstone.CollectingNeighborUpdater.runUpdates(CollectingNeighborUpdater.java:79) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at net.minecraft.world.level.redstone.CollectingNeighborUpdater.addAndRun(CollectingNeighborUpdater.java:63) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at net.minecraft.world.level.redstone.CollectingNeighborUpdater.neighborChanged(CollectingNeighborUpdater.java:35) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at net.minecraft.server.level.ServerLevel.neighborChanged(ServerLevel.java:1912) ~[?:?]
        at net.minecraft.world.level.block.DiodeBlock.updateNeighborsInFront(DiodeBlock.java:198) ~[?:?]
        at net.minecraft.world.level.block.DiodeBlock.onPlace(DiodeBlock.java:183) ~[?:?]
        at net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase.onPlace(BlockBehaviour.java:1264) ~[?:?]
        at net.minecraft.world.level.chunk.LevelChunk.setBlockState(LevelChunk.java:474) ~[?:?]
        at net.minecraft.world.level.Level.setBlock(Level.java:953) ~[?:?]
        at net.minecraft.world.level.Level.setBlock(Level.java:913) ~[?:?]
        at net.minecraft.world.level.block.DiodeBlock.tick(DiodeBlock.java:72) ~[?:?]
        at net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase.tick(BlockBehaviour.java:1276) ~[?:?]
        at net.minecraft.server.level.ServerLevel.tickBlock(ServerLevel.java:1365) ~[?:?]
        at net.minecraft.world.ticks.LevelTicks.runCollectedTicks(LevelTicks.java:197) ~[?:?]
        at net.minecraft.world.ticks.LevelTicks.tick(LevelTicks.java:94) ~[?:?]
        at net.minecraft.server.level.ServerLevel.tick(ServerLevel.java:860) ~[?:?]
        at net.minecraft.server.MinecraftServer.lambda$tickChildren$16(MinecraftServer.java:1778) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) ~[?:?]
        at java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[?:?]
        ... 1 more

or sometimes

[19:14:19 ERROR]: Encountered an unexpected exception
java.lang.RuntimeException: java.util.concurrent.ExecutionException: net.minecraft.ReportedException: Exception while updating neighbours
        at net.minecraft.server.MinecraftServer.tickChildren(MinecraftServer.java:1818) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at net.minecraft.server.dedicated.DedicatedServer.tickChildren(DedicatedServer.java:464) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at net.minecraft.server.MinecraftServer.tickServer(MinecraftServer.java:1520) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:1221) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:324) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at java.lang.Thread.run(Thread.java:833) ~[?:?]
Caused by: java.util.concurrent.ExecutionException: net.minecraft.ReportedException: Exception while updating neighbours
        at java.util.concurrent.FutureTask.report(FutureTask.java:122) ~[?:?]
        at java.util.concurrent.FutureTask.get(FutureTask.java:191) ~[?:?]
        at net.minecraft.server.MinecraftServer.tickChildren(MinecraftServer.java:1815) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        ... 5 more
Caused by: net.minecraft.ReportedException: Exception while updating neighbours
        at net.minecraft.server.MinecraftServer.lambda$tickChildren$16(MinecraftServer.java:1807) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) ~[?:?]
        at java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[?:?]
        ... 1 more
Caused by: java.lang.NullPointerException: Cannot read field "currentState" because "center_up" is null
        at com.destroystokyo.paper.util.RedstoneWireTurbo.calculateCurrentChanges(RedstoneWireTurbo.java:861) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at com.destroystokyo.paper.util.RedstoneWireTurbo.updateNode(RedstoneWireTurbo.java:444) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at com.destroystokyo.paper.util.RedstoneWireTurbo.breadthFirstWalk(RedstoneWireTurbo.java:638) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at com.destroystokyo.paper.util.RedstoneWireTurbo.updateSurroundingRedstone(RedstoneWireTurbo.java:807) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at net.minecraft.world.level.block.RedStoneWireBlock.updateSurroundingRedstone(RedStoneWireBlock.java:273) ~[?:?]
        at net.minecraft.world.level.block.RedStoneWireBlock.neighborChanged(RedStoneWireBlock.java:544) ~[?:?]
        at net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase.neighborChanged(BlockBehaviour.java:1234) ~[?:?]
        at net.minecraft.world.level.redstone.NeighborUpdater.executeUpdate(NeighborUpdater.java:66) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at net.minecraft.world.level.redstone.CollectingNeighborUpdater$SimpleNeighborUpdate.runNext(CollectingNeighborUpdater.java:160) ~[?:?]
        at net.minecraft.world.level.redstone.CollectingNeighborUpdater.runUpdates(CollectingNeighborUpdater.java:79) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at net.minecraft.world.level.redstone.CollectingNeighborUpdater.addAndRun(CollectingNeighborUpdater.java:63) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at net.minecraft.world.level.redstone.CollectingNeighborUpdater.neighborChanged(CollectingNeighborUpdater.java:35) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at net.minecraft.server.level.ServerLevel.neighborChanged(ServerLevel.java:1912) ~[?:?]
        at net.minecraft.world.level.block.DiodeBlock.updateNeighborsInFront(DiodeBlock.java:198) ~[?:?]
        at net.minecraft.world.level.block.DiodeBlock.onPlace(DiodeBlock.java:183) ~[?:?]
        at net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase.onPlace(BlockBehaviour.java:1264) ~[?:?]
        at net.minecraft.world.level.chunk.LevelChunk.setBlockState(LevelChunk.java:474) ~[?:?]
        at net.minecraft.world.level.Level.setBlock(Level.java:953) ~[?:?]
        at net.minecraft.world.level.Level.setBlock(Level.java:913) ~[?:?]
        at net.minecraft.world.level.block.DiodeBlock.tick(DiodeBlock.java:65) ~[?:?]
        at net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase.tick(BlockBehaviour.java:1276) ~[?:?]
        at net.minecraft.server.level.ServerLevel.tickBlock(ServerLevel.java:1365) ~[?:?]
        at net.minecraft.world.ticks.LevelTicks.runCollectedTicks(LevelTicks.java:197) ~[?:?]
        at net.minecraft.world.ticks.LevelTicks.tick(LevelTicks.java:94) ~[?:?]
        at net.minecraft.server.level.ServerLevel.tick(ServerLevel.java:860) ~[?:?]
        at net.minecraft.server.MinecraftServer.lambda$tickChildren$16(MinecraftServer.java:1778) ~[sparklypaper-1.20.4.jar:git-SparklyPaper-"be7e5e1"]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) ~[?:?]
        at java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[?:?]
        ... 1 more

Here is save.
archive-2024-03-10T190116Z.tar.gz

Steps to replicate (all versions with Parallel World Ticking):
0 - Set redstone implementation something that is not alternate-current
1 - Load this save
2 - Interact with machine (observers and wires)
3 - Have bad luck (sometimes it works perfectly fine)
If good luck:
3.1 - Use worldedit to copy/paste and try again

2024-03-10.22-14-13.mp4

Server specs and config recommendation

How many minimum CPU threads would you recommend I should have to maximize the benefits of parallel worlds?

parallel-world-ticking:
threads: 2

Will this work or it really has to be at 8 threads?

Inventory that was created at

java.lang.Throwable: null
at net.minecraft.world.inventory.AbstractContainerMenu.(AbstractContainerMenu.java:105) ~[?:?]
at org.bukkit.craftbukkit.v1_20_R2.inventory.CraftContainer.(CraftContainer.java:40) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"0e7165d"]
at org.bukkit.craftbukkit.v1_20_R2.inventory.CraftContainer.(CraftContainer.java:50) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"0e7165d"]
at org.bukkit.craftbukkit.v1_20_R2.entity.CraftHumanEntity.openCustomInventory(CraftHumanEntity.java:358) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"0e7165d"]
at org.bukkit.craftbukkit.v1_20_R2.entity.CraftHumanEntity.openInventory(CraftHumanEntity.java:345) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"0e7165d"]
at com.github.hanielcota.cash.utils.external.FastInv.open(FastInv.java:283) ~[Cash-1.0-SNAPSHOT-dev-all.jar:?]
at com.github.hanielcota.cash.commands.CashCommand.onCash(CashCommand.java:29) ~[Cash-1.0-SNAPSHOT-dev-all.jar:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
at co.aikar.commands.RegisteredCommand.invoke(RegisteredCommand.java:152) ~[Cash-1.0-SNAPSHOT-dev-all.jar:?]
at co.aikar.commands.BaseCommand.executeCommand(BaseCommand.java:578) ~[Cash-1.0-SNAPSHOT-dev-all.jar:?]
at co.aikar.commands.BaseCommand.execute(BaseCommand.java:513) ~[Cash-1.0-SNAPSHOT-dev-all.jar:?]
at co.aikar.commands.RootCommand.execute(RootCommand.java:99) ~[Cash-1.0-SNAPSHOT-dev-all.jar:?]
at co.aikar.commands.BukkitRootCommand.execute(BukkitRootCommand.java:84) ~[Cash-1.0-SNAPSHOT-dev-all.jar:?]
at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:155) ~[sparklypaper-api-1.20.2-R0.1-SNAPSHOT.jar:?]
at org.bukkit.craftbukkit.v1_20_R2.CraftServer.dispatchCommand(CraftServer.java:992) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"0e7165d"]
at org.bukkit.craftbukkit.v1_20_R2.command.BukkitCommandWrapper.run(BukkitCommandWrapper.java:64) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"0e7165d"]
at com.mojang.brigadier.CommandDispatcher.execute(CommandDispatcher.java:265) ~[sparklypaper-1.20.2.jar:?]
at net.minecraft.commands.Commands.performCommand(Commands.java:330) ~[?:?]
at net.minecraft.commands.Commands.performCommand(Commands.java:314) ~[?:?]
at net.minecraft.server.network.ServerGamePacketListenerImpl.performChatCommand(ServerGamePacketListenerImpl.java:2208) ~[?:?]
at net.minecraft.server.network.ServerGamePacketListenerImpl.lambda$handleChatCommand$19(ServerGamePacketListenerImpl.java:2168) ~[?:?]
at net.minecraft.util.thread.BlockableEventLoop.lambda$submitAsync$0(BlockableEventLoop.java:59) ~[?:?]
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768) ~[?:?]
at net.minecraft.server.TickTask.run(TickTask.java:18) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"0e7165d"]
at net.minecraft.util.thread.BlockableEventLoop.doRunTask(BlockableEventLoop.java:153) ~[?:?]
at net.minecraft.util.thread.ReentrantBlockableEventLoop.doRunTask(ReentrantBlockableEventLoop.java:24) ~[?:?]
at net.minecraft.server.MinecraftServer.doRunTask(MinecraftServer.java:1330) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"0e7165d"]
at net.minecraft.server.MinecraftServer.d(MinecraftServer.java:194) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"0e7165d"]
at net.minecraft.util.thread.BlockableEventLoop.pollTask(BlockableEventLoop.java:126) ~[?:?]
at net.minecraft.server.MinecraftServer.pollTaskInternal(MinecraftServer.java:1307) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"0e7165d"]
at net.minecraft.server.MinecraftServer.pollTask(MinecraftServer.java:1300) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"0e7165d"]
at net.minecraft.util.thread.BlockableEventLoop.managedBlock(BlockableEventLoop.java:136) ~[?:?]
at net.minecraft.server.MinecraftServer.waitUntilNextTick(MinecraftServer.java:1278) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"0e7165d"]
at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:1166) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"0e7165d"]
at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:321) ~[sparklypaper-1.20.2.jar:git-SparklyPaper-"0e7165d"]
at java.lang.Thread.run(Thread.java:840) ~[?:?]

more explanation

I wonder why we cant access biome, block, entity, etc with Parallel World Ticking in async scheduler using plugin.
I need more info.
I cant understand all....
and I wonder if using async getBiome/Block/Entity without TickThread check code.

sry for bad english...

Error that cause huge TPS drop

[13:29:25 ERROR]: --- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH  - 1.20.6-DEV-6df23d1 (MC: 1.20.6) ---
[13:29:25 ERROR]: The server has not responded for 15 seconds! Creating thread dump
[13:29:25 ERROR]: ------------------------------
[13:29:25 ERROR]: Server thread dump (Look for plugins here before reporting to SparklyPaper!):
[13:29:25 ERROR]: ------------------------------
[13:29:25 ERROR]: Current Thread: Server thread
[13:29:25 ERROR]:       PID: 44 | Suspended: false | Native: true | State: RUNNABLE
[13:29:25 ERROR]:       Stack:
[13:29:25 ERROR]:               [email protected]/sun.nio.ch.UnixFileDispatcherImpl.write0(Native Method)
[13:29:25 ERROR]:               [email protected]/sun.nio.ch.UnixFileDispatcherImpl.write(UnixFileDispatcherImpl.java:65)
[13:29:25 ERROR]:               [email protected]/sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:137)
[13:29:25 ERROR]:               [email protected]/sun.nio.ch.IOUtil.write(IOUtil.java:102)
[13:29:25 ERROR]:               [email protected]/sun.nio.ch.IOUtil.write(IOUtil.java:72)
[13:29:25 ERROR]:               [email protected]/sun.nio.ch.FileChannelImpl.write(FileChannelImpl.java:300)
[13:29:25 ERROR]:               [email protected]/sun.nio.ch.ChannelOutputStream.writeFully(ChannelOutputStream.java:68)
[13:29:25 ERROR]:               [email protected]/sun.nio.ch.ChannelOutputStream.write(ChannelOutputStream.java:105)
[13:29:25 ERROR]:               [email protected]/java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:125)
[13:29:25 ERROR]:               [email protected]/java.io.BufferedOutputStream.implFlush(BufferedOutputStream.java:252)
[13:29:25 ERROR]:               [email protected]/java.io.BufferedOutputStream.flush(BufferedOutputStream.java:240)
[13:29:25 ERROR]:               [email protected]/java.util.zip.DeflaterOutputStream.flush(DeflaterOutputStream.java:290)
[13:29:25 ERROR]:               [email protected]/java.io.BufferedOutputStream.implFlush(BufferedOutputStream.java:253)
[13:29:25 ERROR]:               [email protected]/java.io.BufferedOutputStream.flush(BufferedOutputStream.java:240)
[13:29:25 ERROR]:               [email protected]/java.io.DataOutputStream.flush(DataOutputStream.java:131)
[13:29:25 ERROR]:               [email protected]/java.io.FilterOutputStream.close(FilterOutputStream.java:184)
[13:29:25 ERROR]:               net.minecraft.nbt.NbtIo.writeCompressed(NbtIo.java:222)
[13:29:25 ERROR]:               net.minecraft.nbt.NbtIo.writeCompressed(NbtIo.java:174)
[13:29:25 ERROR]:               net.minecraft.world.level.storage.LevelStorageSource$LevelStorageAccess.saveLevelData(LevelStorageSource.java:617)
[13:29:25 ERROR]:               net.minecraft.world.level.storage.LevelStorageSource$LevelStorageAccess.saveDataTag(LevelStorageSource.java:608)
[13:29:25 ERROR]:               net.minecraft.server.level.ServerLevel.saveIncrementally(ServerLevel.java:1517)
[13:29:25 ERROR]:               net.minecraft.server.MinecraftServer.tickServer(MinecraftServer.java:1597)
[13:29:25 ERROR]:               net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:1236)
[13:29:25 ERROR]:               net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:328)
[13:29:25 ERROR]:               net.minecraft.server.MinecraftServer$$Lambda/0x00007fc930cd2430.run(Unknown Source)
[13:29:25 ERROR]:               [email protected]/java.lang.Thread.runWith(Thread.java:1596)
[13:29:25 ERROR]:               [email protected]/java.lang.Thread.run(Thread.java:1583)
[13:29:25 ERROR]: ------------------------------
[13:29:25 ERROR]: --- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH ---
[13:29:25 ERROR]: ------------------------------

My server freezes and this error appears.

[Feature]Implement Purpur and fork patches

Sparklypaper is amazing, if some patches of other forks can be implemented on sparklypaper, it will be more perfect.
Suggestions:

  1. Some purpur patches for removed Vanilla features (PurpurMC/Purpur)
  2. Pufferfish patches (pufferfish-gg/Pufferfish)
  3. patches from Lithium mod which optimizes minecraft (DivineMC/DivineMC)
  4. [Not Stable]Some patches from C2ME mod that speeds up the chunk loading (Dreeam-qwq/Mirai)
  5. .Linear world format, decreases file size by 50% (xymb-endcrystalme/LinearPaper)
    Hope sparklypaper get better!❤

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.