Previously, the timeout would erroneously get converted to milliseconds
twice. The second conversion was removed.
Spurious wakeups were not handled properly, and would instead throw a
TimeoutException even if the waited time was not reached..
The new scheduler uses a non-blocking methodology. Combining volatile
references to make a linked reference chain, with the atomic reference
handling the tail, tasks are queued without waiting for locks. The main
thread will no longer limit the length of time spend for scheduled tasks,
but no task will run twice in the same tick. Scheduling a new task inside of
a synchronous task will always run the new task during the same tick,
assuming there is no supplied delay > 0.
Asynchronous tasks are now run using a thread pool. Any thread-local
implemenation should now account for threads being reused between
executions.
Race conditions were carefully examined and the order of logic is now very
important. Each task is placed in a secondary collection before removal from
primary collections. Thus, by reading tasks from the collections in the same
order they travel, it retains state-safety. This does make modifications
less responsive in some situations, as the task may be transitioning before
the modifier accesses it. This cost outweighs the requirement to synchronize
on the scheduler; previously any conflict would be first-come-first-serve,
with the main thread backing out arbitrarily.
Many codepaths only end up with one iterator being used at a time and
most of the rest only get up to two being used so using a static pool of
three is wasteful. This also allows us to efficiently handle cases that
exceed 3 iterators in use. Overall this dramatically increases the hit rate
and results in less iterators being created.
This ArrayList duplicates part of the functionality of the much more
efficient chunk map so can be removed as the map can be used in the few
places this was needed.
Replace uses of LongHashtable and LongHashset with new implementations.
Remove EntryBase, LongBaseHashtable, LongHashset, and LongHashtable as they
are no longer used.
LongObjectHashMap does not use Entry or EntryBase classes internally for
storage so has much lower object churn and greater performance. LongHashSet
is not as much of performance win for our use case but for general use is
up to seventeen times faster than the old implementation and is in fact
faster than alternatives from "high performance" java libraries. This is
being added so that if someone tries to use it in the future in a place
unrelated to its current use they don't accidentally end up with something
slower than the Java collections HashSet implementation.
Avoid overhead of using an ArrayList and resizing it. Also allows for reuse
of objects in the pool during the same tick by explicitly releasing them
back to the pool. This allows for much better cache performance as well
as reduced cache footprint.
Remove redundant ArrayList to avoid excessive object creation and CPU
overhead, the entries are added to the list then immediately iterated through
to run so just run them directly.
Swap order of some conditionals to perform the more efficient check first
as if it fails the list lookup will not be executed.
Remove profiling hooks including some rather expensive calls to getSimpleName.
ChunkSection.e() is called once per chunk section loaded and is quite
expensive (about 20% of CPU time for loading the chunk). This changes the
logic to add a fast path when extended block data is not being used and
reorganizes the loops for more optimal array traversal. Overall this saves
about 20-30% CPU time in this method.
- Hardcore requires a newly generated world
- You will be banned if you die in a hardcore world
- You will NOT be banned if you die in a non-vanilla world
- Your "heart container" will not change without logging back in. (Vanilla bug)
They can spawn any valid entities now. What is a "valid" entity? A "valid" entity is an EntityType with a non-null getName(). (for example: PRIMED_TNT, FALLING_BLOCK)
The method this.a(world, d0, d1, d2, i, j, k) is responsible for
actually placing the lava or water source block in the world. The event
is currently called after this method, thus canceling the event will
cause the player to keep their water/lava bucket but the water/lava will
still appear where they attempted to place it.
In addition, the check for whether a player has creative inventory is
short circuiting before the event fires, so the event will not be called
for these players.
This moves the event call and cancelled check above these two calls to
ensure it always fires and the results of it are honored.
Closes GH-835.
Added two utility collections for use with PlayerChatEvents allowing lazier
initialization of events and less need to synchronize against the player
list.
Provided a hidden queue system for similar logic to pre-1.3 chat. When a
plugin is listening for the deprecated PlayerChatEvent, all chat will be
delayed to be mirror executed from the main thread. All developers are
encouraged to immediately update to the developmental Bukkit chat API as a
minimum transition for server stability.
Additionally, changes were required to bring thread-safety to the flow
logic. CopyOnWriteArrayList is the only viable means to produce thread
safety with minimal diff; using a sane pre-implemented collection would
require reworking of sections of NMS logic.
As a minor change, implemented expected functionality for
PlayerCommandPreProcessEvent. Setting the player should now change the
player executing the command.
Both the CB 1.3.1 code, and vanilla 1.3.1 code, have modified the
behavior of entity tick processing in a way that can lead to disabling
of entity cleanup. Specifically, the tickEntities() call in n.m.s.World,
which processes both the entity cleanup (removing from the world entity
list) and tile entity tick processing (furnaces and such) does not get
called by n.m.s.MinecraftServer's q() method (which drives tick
processing calls in general) when no players are on the given world.
This causes a serious memory leak when automation processes, like dynmap
mapping, load and unload chunks - as entities on unloaded chunks are
only cleaned up during entity tick processing. It also will cause issues
with any mods that use persistent chunk loading (that is, keeping chunks
loaded so that tile entities will continue being processed), since such
processing will no longer function without at least one player on the
given world.
In any case, the tickEntities() call should be called in the same
fashion as under 1.2.x (each tick, independent of player population, as
opposed to being suspended indefinitely when no players are on the given
world). The specific memory leak observed, with removing the unloaded
entites from the world, requires this call be made regularly (or, at
least, whenever the entity unload queue (world.g) is not empty.
Closes GH-832
Added newlines at the end of files
Fixed improper line endings on some files
Matched start - end comments
Added some missing comments for diffs
Fixed syntax on some spots
Minimized some diff
Removed some no longer used files
Added comment on some required files with no changes
Fixed imports of items used once
Added imports for items used more than once
This allows previous causes to be available during the event, as well as making the damage cause a valid one. If EntityDamageEvent is canceled, then it's not the last DamageCause.
Also prevents setting DamageCause involuntarily through construction.