getting lots of bug reports on light. just going to drop this even though
I really don't see how it could be the source due to my understanding of
the games light engine...
Fixes#1920
Use O(1) patterns for mapping conversions to improve plugin performance.
Optimize collections used by legacy plugin conversion
This should improve plugin performance across the board
on Paper for both Modern and Legacy Plugins.
Also log how long building those tables takes...
Some of these were wrong (scoreboard manager), others are counter to
everything everyone expects (Locations world being null, which wasnt ever safe EVER)
others are just too noisy.
Replace some with Contract to get rid of the nullability constraint and go back to
the old days of IDE not considering it strictly one way or the other.
Also, stop requiring annotations on package-private.
Introduces the next Developer Perk for Paper-API: Your plugin isn't yellow anymore.
Also fixed random dupe code in ensureServerConversions that got mistakenly set in the update.
use a better stack for managing timing tree relationships
remove unnecessary synchronization (i forgot HANDLERS is only touched on main)
this should hopefully resolve any data integrity concerns
turning this to true allows 1 player to deny other players the ability
to have mobs spawn. It really is a bad idea and reverts back to iffy
mob spawn limits where mob farms in the world stops natural spawns
from occuring.
Really recommend resorting to different solutions than ever using this config.
Upstream has released updates that appears to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing
Bukkit Changes:
451bd74e Use gson for decoding version command
CraftBukkit Changes:
51100db8 SPIGOT-4678: Fix placing signs in certain circumstances
This resolves the super common complaint about mobs not spawning.
This was ultimately a flaw in the vanilla count algorithim that allows
spawners and other misc mobs to count against the mob limit, which are
not bounded, and can prevent the entire world from spawning new.
I believe Bukkits changes around persistence may of actually made it
worse than vanilla.
This should fully solve all of the issues around it so that only natural
influences natural spawns.
Allows you to return the SpawnReason for why an Entity Spawned
Pre existing entities will return NATURAL if it was a non
persistenting Living Entity, SPAWNER for spawners,
or DEFAULT since data was not stored.
Mojang stored whitelist state in 2 places (Whitelist Object, PlayerList)
some things checked PlayerList, some checked object. This moves
everything to the Whitelist object.
I really don't know how this could break things with light, but wanted to
let it be an option so we can try turning it off to fix some light bug reports
Also adds a limit to stop sending Sign data to client after 500
signs per chunk to limit client lag.
Use -DPaper.excessiveSignsLimit=500 to configure that limit, or -1
to disable the limit and let your players be abused.
fixes#1878
now 80 chars counts multi sized code points the same so 80 chinese
characters would be allowed too.
Removed outbound limit as it doesn't solve the chunk oversize problem.
proper fix for chunk sending in another patch next.
we missed something in updating this patch and accidently left
hashCode as a 0 value. This caused a pretty nasty performance hit
for BlockStateEnum instances as they would be all a hash collision.
This update fixes that and also promotes the optimizations to cover
ALL cases of Block States, not just enums.
While mojang cached hashCode in 1.13, we can still just use a simple
large prime based hashCode that auto increments guaranteeing no overlap.
Additionally, replace all equals with an identity check.
modified clients can send abnormally large data from the client
to the server and it would get stored on the sign as sent.
the client can barely render around 16 characters as-is, but formatting
codes can get it to be more than 16 actual length.
Set a limit of 80 which should give an average of 16 characters 2
sets of legacy formatting codes which should be plenty for all uses.
This does not strip any existing data from the NBT as plugins
may use this for storing data out of the rendered area.
it only impacts data sent to and from the client.
Set -DPaper.maxSignLength=XX to change limit or -1 to disable
per feedback from @liach about a bug with vanillas previous logic
that we essentially just reverted to. complex recipes could run into
cases where a recipe that does have enough items can be unsatisfied
if the items are in certain orders, making them not truely shapeless.
this scenario doesn't occur in vanilla, but users can load custom recipes.
this improves the logic to do some sorting on the lists to improve
chances of matching the recipes harder ingredients before the easier
to satisfy ingredients.
the likelyhood of someone adding a recipe that still fails this is too
extreme to care about. i doubt mojangs implementation is perfect either.
we can improve this logic more later if we actually get bug reports on it.
Mojang implemented Shapeless different than Shaped
This made the Bukkit RecipeChoice API not work for Shapeless.
This reimplements vanilla logic using the same test logic as Shaped
Adds an event for when the server is going to destroy a current block,
potentially causing it to drop. This event can be cancelled to avoid
the block destruction, such as preventing signs from popping when
floating in the air.
This can replace many uses of BlockPhysicsEvent, as this will not fire
with the same velocity as BPE.
ConcurrentHashMap synchronizes on .computeIfAbsent even on hits,
so this does a .get(key) first, which most of our use should
be hits, and then falls back to the CHM computeIfAbsent for thread safe puts.
Also improve concurrency on handler and group collections to use a synchronized
list instead of an array deque for concurrency safety.
While these logs indicate something is 'off', we've had no reports
of visible 'issues' with entities, and no one is going to take the
time to debug this farther, so just getting rid of the logs so it's
like its never happening!
Ignorance is bliss.
This was a useless exception wrapper that ends up making
stack traces harder to read as well as the JVM cutting off
the important parts
Nothing catches this exception, so its safe to just get rid
of it and let the REAL exception bubble down
Upstream has released updates that appears to apply and compile correctly.
This update has only been PARTIALLY tested by PaperMC and as with ANY update, please do your own testing
I've tested basic region file saving as well as our oversized chunks approach.
Bukkit Changes:
e167e549 Clarify MerchantInventory#getSelectedRecipe.
3a1d5b8f Apply default permissions by registration order.
c64cc93f Make tags Keyed
ec037ed7 Added a method to get a list of tags
bfb6ef86 Introduce rotation methods to the Vector class
fc727372 Remove draft API from FluidLevelChangeEvent
CraftBukkit Changes:
6430d9c0 SPIGOT-4632: BlockState location is not fixed
14cd1688 Fix CraftInventoryMerchant#getSelectedRecipe if there is no active merchant recipe.
c24abab7 Load custom permissions after default permissions.
bc99dfe8 Make tags Keyed
6fce004f Added a method to get a list of tags
Spigot Changes:
e5e5c7c6 Allow Saving Large Chunks
e8d3881c Rebuild patches
Please test this build on a local TEST SERVER before sending to your live server!
PaperMC is not responsible for any data loss to your chunks.
-------------------------------------------------------------------
The Minecraft World Region File format has a hard cap of 1MB per chunk.
This is due to the fact that the header of the file format only allocates
a single byte for sector count, meaning a maximum of 256 sectors, at 4k per sector.
This limit can be reached fairly easily with books, resulting in the chunk being unable
to save to the world. Worse off, is that nothing printed when this occured, and silently
performed a chunk rollback on next load.
This leads to security risk with duplication and is being actively exploited.
This patch catches the too large scenario, falls back and moves any large Entity
or Tile Entity into a new compound, and this compound is saved into a different file.
On Chunk Load, we check for oversized status, and if so, we load the extra file and
merge the Entities and Tile Entities from the oversized chunk back into the level to
then be loaded as normal.
Once a chunk is returned back to normal size, the oversized flag will clear, and no
extra data file will exist.
This fix maintains compatability with all existing Anvil Region Format tools as it
does not alter the save format. They will just not know about the extra entities.
This fix also maintains compatability if someone switches server jars to one without
this fix, as the data will remain in the oversized file. Once the server returns
to a jar with this fix, the data will be restored.
If anything throwable is thrown, be sure its caught too.
Because I totally did new Error() out of javascript habit...
This ensures that chunk loading process cant get stuck due to uncaught errors
if a chunk load was cancelled after generating stage started
it would short circuit return with a null.
however this skipped the creation of the loadTask, which some code
would then invoke in requestChunk and trigger an NPE.
This then likely left an incomplete corrupt request in the chunk map
which then crashes servers.
It should fix these isseues
Fixes#1775Fixes#1743
This restores monster aggression range back to normal when
Activation Range is less than the monsters aggression range.
This allows an entity to try to acquire targets still during
inactive ticks, which will also then let it go into immunity stage.
Per MC-138093 comments, ForkJoinPool uses unlimited threads if
parallelism is ever 1. A 2 core machine will end up with 1
with the change I had previously made, so bumped the min
to 2 so we will never trigger the unlimited thread situation.
This aligns the min back with Spigot, but allows use of more
threads on systems with more cores.
Upstream has released updates that appears to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing
CraftBukkit Changes:
e693496c SPIGOT-4467: Improve ExpiringMap
Splits time updates into incremental updates as well as does
the updates per world, so that we can re-use the same packet
object for every player unless they have per-player time enabled.
Fixes some bugs with urgent priority, improves priority all
around to optimize blocking chunk requests as much as possible.
fixes casing on the -Dpaper.maxchunkthreads to now be -Dpaper.maxChunkThreads
adds -Dpaper.genThreadPriority=3 -Dpaper.loadThreadPriority=4
lowering thread priorities will help ensure main has more
priority over chunk threads
Optimizes small movements by entities by merging the movement
into the entities next larger movement, until enough movement
velocity has been hit.
This reduces collision detection and able to reduce movement
cpu cost by 5-7%.
The default option of 0.75 seems to provide all the gains without
any noticable behavior change to entity movement.
We have to exclude slimes due to weird jumping animation bugs.
Fixes some bugs with urgent priority, improves priority all
around to optimize blocking chunk requests as much as possible.
fixes casing on the -Dpaper.maxchunkthreads to now be -Dpaper.maxChunkThreads
adds -Dpaper.genThreadPriority=3 -Dpaper.loadThreadPriority=4
lowering thread priorities will help ensure main has more
priority over chunk threads
Spigot capped it to 2 threads. This bumps it back up to do
maxcores -2 with a max cap of 6.
A typical 4C8T system can use 6 threads and be done in 6 seconds.
Server owners can use system property to override, but this
improves the default.
this should provide a pretty good across-the-board performance
improvement for the entire server, as it's very common for code
to check if (isLoaded(x, z)) { then do something on that chunk }
Previously, containsKey would not read or set the last access cache
By making it do get() != null, we gain the benefits of last access
and also improves thread safey for async isLoaded checks
This exact usage scenario is used in Entity movement, so that alone
saves us up to 5%~ of CPU time for Entity movement.
it used public method instead of private, and moved to world config
also improved the implementation to not use obfuscated stuff
Also removed the Fix Double chest conversion patch since its
fixed in other ways in vanilla
This will provide quite a major performance boost by avoiding
synchronizing on EVERY chunk lookup.
Synchronize, even without contention, incurs processor cache flushes.
Considering this is the 2nd hottest method in the code base, lets
avoid doing that...
Additionally, chunk conversion operations were occuring while
under synchronization which lead to deadlocks.
Now the conversion will occur outside of the lock, and fix
that issue, resolving #1586
Note, that the chunk map is still thread safe for get operations!
The chunk map was never intended to be modified async with our
changes, as we post to main to modify the map, however
we do still synchronize for write operations (put, remove)
We also synchronize for async get operations, ensuring that
async gets are safe.
We do not need to synchronize main thread gets as the processor
cache will be insync since the map is only updated on the main thread.
However, if someone does try to delete or put concurrently, we
will force their operation back to the main thread.
Mojang was not checking that the chunk did not overwrite, or
was successfully removed.
We're seeing odd reports in #1561 that indicates issues around
this are having problems.
1) Get rid of string interning. can be heavy, has been seen to cause issues for some users
2) Use ConcurrentHashMap instead of a SynchronizedMap
3) Stop use of MRUMapCache which is not thread safe for Group lookups
4) Stop using IdentityHashMap which has performance issues in Java 8
Say a player shoots an arrow through a nether portal, the game
would lose the shooter for determining things such as Player Kills,
because the entity is in another world.
If the projectile fails to find the shooter in the current world, check
other worlds.
we've seen some index lines change in length in some PR's, though
this script was suppose to ignore those changes already.
The only way I can see that not working is if the color mode
of grep is breaking the pattern matching, as some people
default their grep to use color=always
this adds color=none to ensure colors are disabled, should ensure it.
If a chunk load comes in on a chunk load or gen thread,
execute it synchronously on that thread instead of enqueueing it.
It doesn't make sense to enqueue it as that thread is then
going to future.join() it and block until it's ready anyways.
This opens risk to a deadlock if every load or gen thread is
waiting on a recursive chunk but it will never finish because
all of the threads are waiting.
If we identify an invalid offset (negative, or the header sectors),
then back up the region file and erase that specific chunks offset
data.
This will avoid crashing the server with AIOBB errors and also avoids
server owners having to consider the entire region file 'lost'.
I'm not sure what leads to this state, I can only assume write cut
off mid bits.
In this scenario, there is absolutely no way to know where the chunk
actually is in the data file without loading every
single chunk in the file. And even to do that, would be quite extreme
due to the fact the file isn't in some orderly fashion.
Since the file is backed up, the user can use a region fixer tool
externally to try to restore that single chunk. We could even
add a command to restore a chunk from a backup file in a different
commit later on. But this at least prevents the server from crashing.
The server will just generate a new chunk and move on,
after printing an error to the console about it.
Also fixed the case reported in this issue about the server
hanging when a corrupt chunk is encountered, so this issue
is now fully closed.
Resolves#1541
Applied a "Only run this when the blocks are different" to
a place, that apparently must be called even with the same
block but different other data I guess.
This was causing oddness with light data.
Chunk Generation was occuring while inside of the progressCache lock
this caused the progressCache to stay blocked for a long period of time
which then blocked main when main needed to clean the expiring map.
We now maintain a separate map for pending scheduler entries, that
we can join on if a 2nd request comes in while one is starting.
This strategy keeps the lock only for a fraction of time but
maintains thread safety.
So now the chunk is generated without holding a lock and wont
block the main thread on the expiring map as we will insert it
once ready.
1) Removed "Regen" mode of Dupe UUID resolver, forced safe.
Some servers who updated before we had safe mode added still had this value.
There's really no reason to keep this mode, as we've seen that vanilla
triggers this often and 99.9999999% of cases will be an actual duplicate
that needs to be deleted.
2) Made Vanilla Debug messages about dupe UUIDs and dupe uuid resolve messages
only show up if the debug.entities flag is on. This will stop server owners
from panicing from seeing these logs, and stop opening bug reports on this,
only for us to tell you "don't worry about it".
3) Avoid adding entities to world that are already added to world.
This can be triggered by anything that causes an entity to be added
to the world during the chunk load process, such as chunk conversions.
Issue #1544 was a case of this.
4) Removed debug warning about ExpiringMap.
Nothing more I know to do about this anyways. We recover from it,
stop warning to reduce noise of issues to us.
This adds a plethora of useful Tags to let you identify common grouping
of materials. This should complete all of the categories that mojang
did not provide official tags for plus some more.
These are not "registered" tags. They are not usable in any form of
command system that might support tags.
These are provided as a Paper maintained list of items so that plugins
do not have to worry about maintaining all these tags themselves.
This API can technically be copy and pasted into a plugin, and plugins
can add additional Tags's if they wish too to their plugin by
instantiating a MaterialSetTag.