Minecraft 1.5.2 changed mob spawning by ignoring persistent mobs from the
mob count. In CraftBukkit all mobs that previously used a separate hard
coded persistence system were ported to instead use this one. This causes
all animals to be persistent by default and thus never be counted. To
correct this issue we consider if the mob would be considered persistent
in the hard coded system as well when deciding if a mob should count.
Add a check to avoid doing movement work if an entity doesn't move. This
usually will not ever happen in the current server but is useful when it
does and will be more useful in the future.
Only process mob on mob (non-player) collisions every other tick. Players
tend to pack a lot of mobs into a small space (sheep farm, mob grinder, etc)
so they do a lot of work processing collisions. To help alleviate some of
this we only run these calculations every other tick. This has no visible
effect on the client but can be a huge win on the server depending on
circumstances.
Use generic entity inWater checking for squids. Squids have their own logic
currently for determining if they are in water. This check is almost
identical to the generic entity checking which is run anyway. To avoid
doing duplicate work we just remove the squid version. This does not
have any noticeable effect on gameplay since the checks are so similar.
Use HashSet for tile entities instead of ArrayList. Using an ArrayList for
storing tile entities in a world means we have very expensive inserts and
removes that aren't at the end of the array due to the array copy this
causes. This is most noticeable during chunk unload when a large number of
tile entities are removed from the world at once. Using a HashSet here uses
a little more memory but is O(1) for all operations so removes this
bottleneck.
When a world is created using our API, it does not use secondary world
server and will maintain a reference to its own scoreboard. In vanilla,
this is not an issue as there is only ever one world.
Similarly to maps, an overwrite to the scoreboard reference has been
added for when another world has been created.
This should also address BUKKIT-3982 and BUKKIT-3985
Also fixes: BUKKIT-3477 and BUKKIT-3488
Minecraft likes to double check that tile entities get set after they
are placed, however we didn't set tile entities until after our event
was called. This caused the world to have multiple tile entities in a
single block location; to fix this we now set tile entities before
the event.
In some situations an entity or tile entity can be added to the world but
have its own 'world' field be null or otherwise incorrect. As the entity
was added to this world to be ticked assume it actually is in this world.
This fix changes the 'state' of the last accessed variables to be more
accurate. Changing the coordinates of the last accessed chunk should
never precede actually setting the last accessed chunk, as loading a
chunk may at some point call back to getChunkAt with a new set of
coordinates before the chunk has actually been loaded. The coordinates
would have been set, but the actual chunk would not. With no check for
accuracy, this causes fringe case issues such as null block states.
Big thanks to @V10lator for finding where the root of the problem was
occurring.
This implementation of a visibility API check for sounds
was created by adding extra methods carrying the source entity
in WorldManager and ServerConfigurationManagerAbstract and
adding a test for canSee in the SCMA sendPacketNearby method.
This approach involves no logic copying, just method addition.
I opted to cast to WorldManager as:
1) IWorldAccess is not in CraftBukkit at the moment
2) There is no other IWorldAccess implemented in CraftBukkit,
nor is there likely to be one soon. If that day comes, easy fix.
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.
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
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.