When 1.3.1 was released, a try-catch block was removed from the tick
loop that called the method in NMS to handle commands. This restores a
try-catch to prevent the console from crashing the server.
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.
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)
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.
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.
TextWrapper used to try to ensure a message would wrap correctly on the
client by counting the width of the characters in pixels and wrapping
before hitting that limit. This was needed because the client would lose
color information when wrapping and could not handle long lines of text.
Now that both of these problems are solved in the client we can replace
TextWrapper with simple code to split the message into multiple packets on
newlines and ensure chat colors carry across to the new packet.
Make EntityLiving call AI logic every tick again.
Rework PathfinderGoalSelector logic.
Adds UnsafeList for use in places where we use ArrayList and know we won't
get index out of range errors. Added usage to World's tickEntities, Chunk's
entitySlices to speed up searching for entities, and to PathfinderGoalSelector
to speed up dealing with AI goals.
Reworked logic in PathfinderGoalSelector with help from fullwall. This code
no longer uses an extra ArrayList for setting up goals and only updates which
goals should be run every other time it is called.
Removed only calling PathfinderGoalSelector every other tick from EntityLiving
as we now only setup new goals every other tick. This ensures existing goals
run every tick to properly update mob movement.
- Allows drops in creative mode by adding items to the getDrops() list
- Contents of containers are not reported
- Contents of storage minecarts are not reported
Details:
- The attributes of custom inventory views are no longer ignored
- Enchanting or crafting inventories no longer ignore the passed inventory and open a new one
- Inventories associated with tile entities no longer raise a class cast exception if there was no associated tile entity
- InventoryOpenEvent and InventoryCloseEvent (if they already had some other inventory open) now fire in all cases
- If for any reason the inventory failed to open, the method now returns null instead of returned the previous inventory they had open (or the default inventory, if none)
Also adds CraftEventFactory.callEvent(Event), which returns the event called. Currently only used for n.m.s.BlockStationary's lava
BlockIgniteEvent calls.
See the corresponding Bukkit commit for details.
Implementation details:
- Any packets that include an itemstack will send air stacks as null; maybe this will even eliminate the client crash that occurs if the client receives an air stack
- Better handling of null itemstacks in general (ie less converting them to air stacks)
- Inventory.setContents() can now take an array smaller than the inventory without error
- Player.updateInventory() should now correctly update the result slot in a crafting inventory
Some small credit goes to Afforess (initial implementation of openInventory() methods) and Drakia (initial implementation of InventoryOpenEvent and InventoryCloseEvent).
This commit modifies the construction of PortalCreateEvents to specify
a reason for the event. Reasons are either:
1. FIRE: the portal is being created because a player set fire to an
obsidian frame.
2. DESTINATION: the portal is being created as a destination for an existing portal.
- Removed the useless world field.
- Made it so changes to a CraftSign (which is a Block*State*) no longer reflect into the world without calling sign.update().
- All StructureGrowEvent handling for these is in BlockSapling now, using a BlockChangeDelegate to collect the data.
- Moved StructureGrowDelegate into a separate class
Add a recipe iterator to make it possible to retrieve and remove recipes (BUKKIT-738), and updated the recipe classes to not clip the data to 127 (BUKKIT-624)
Remove players that cannot see a player from their EntityTrackerEntry and only
send user list updates to players who can see the player they reference.
useExactLoginLocation() looks for settings.use-exact-login-location within bukkit.yml.
If true, we will bypass Vanilla's behaviour of checking for collisions and moving the player if needed when they login.
If false, we will continue to follow Vanilla's behaviour and move players that 'collide' with objects when they login.
Fixes BUKKIT-589: if you call damage on an instance of EnderDragon, no damage
is done.
Reason for bug: damage calls Entity.damageEntity. But EntityComplex
overrides damageEntity to do nothing.
Fix: CraftComplexLiving should call EntityComplex.e instead of
Entity.damageEntity. e is the method that actually does damage to an
instance of EntityComplex.