* Actually capture all the data of TileEntities. This is done by creating a copy of the TileEntity. The methods of BlockState which currently directly access the TileEntity reference will modify the data of that TileEntity-snapshot instead.
* With the call to BlockState.update, the captured TileEntity data gets applied to the current TileEntity in the world.
* Methods which trigger block specific actions will use the current TileEntity from the world.
* CraftBlockState does not hand out the wrapped or the snapshot TileEntity directly. Instead, it provides an applyTo method to copy the data to a given TileEntity and a method to directly get a copy of the TileEntity NBT data represented by the BlockState. CraftMetaBlockState was updated to make use of that.
* Added #getSnapshotInventory() to bukkit which allows modifiying the captured inventory snapshots of containers.
* Tried to clarify which methods only work if the BlockState is placed, which methods require the block in the world to still be of the same type (methods which trigger actions), and that .getInventory() directly modifies the inventory of the block in the world if the BlockState is placed and becomes invalid if the block type is changed.
Backwards compatibility
* If the BlockState acts as InventoryHolder, getInventory() will still return the inventory directly backed by the TileEntity in the world (like before), and not the snapshot inventory. This compromise should reduce the potential of these changes to break existing plugins, or craftbukkit's own use of BlockState.
* The snapshot's inventory can be accessed by a new method getSnapshotInventory()
* In case the BlockState is not placed (if it was retrieved from the MetaBlockState of an item), the getInventory() method will however return the snapshot inventory. So that when the BlockState gets applied back to the item, the inventory changes are properly included.
* With the changes to CraftMetaBlockState it is no longer required to call the update method before passing a modified BlockState to the CraftMetaBlockState. For backwards compatibility the update method will simply return true for a non-placed BlockState, without actually doing anything.
Impact on plugins
* Restoring blocks now actually works as expected, properly restoring the TileEntity data, reglardless if the block changed its type in the meantime.
* Plugins are now consistently required to call the update method in order to apply changes to blocks. Though, regarding the Javadoc they should have been required to do so anyways.
* New feature: Plugins can take and modify inventory snapshots.
* Breaking change: If a plugin gets the BlockState of a block in the world, modifies the inventory returned by .getInventory(), and then tries to use the same BlockState to apply the TileEntity data to an ItemStack block meta, the ItemStack will use the snapshot inventory, disregarding the changes made to the inventory returned by .getInventory(). This is the compromise of .getInventory() returning the inventory directly backed by the TileEntity in the world.
Other fixes related to BlockState:
* TileEntityContainer#getLocation() will run into a NPE if the TileEntity is non-placed (ex. when getting the BlockState from a CraftMetaBlockState).
* Beacon.getEntitiesInRange() would previously throw a NPE if called for a non-placed BlockState. It was changed to now require to be placed and use the current TileEntity in the world. If the TileEntity in the world is no longer a beacon, it will return an empty list.
* EndGateway now supports setting and getting the exit location even for non-placed EndGateways (inside BlockStateMeta) by using / returning a location with world being null.
HideFlags will be serialized as a list and deserialized as an Iterable.
This will allow maximum flexibility on both the formats it can be
serialized into and formats it can be deserialized from.
This change properly identifies the creative inventory as one with 5 crafting slots (as that's the default set in ContainerPlayer, and handled properly in other containers), instead of having the same inventory twice (which breaks slot identification).
This happened because "joining" wasn't cleared until the player was ticked. Runnables (presumably) ran _after_ the player list packet was sent, but before the player was ticked; thus, the player list packet was sent, but not cleared. The fix is to replace joining with hasSentListPacket, which is set immediately before sending any player list packets (thus, if hidePlayer is called after, it sees that the list packet has been sent and sends a new one to reset it). With this fix, the player is added to the list and then removed shortly afterwards.
The reason why running /hideall in the example wouldn't fix the invisibility is because the server already thinks the player's been removed from the list (as they're hidden), and thus doesn't want to send another hide packet. This is correct behavior assuming that they get hidden correctly the first time, which they now do.
The Minecraft implementation of spawn eggs is able to construct an entity using all data that is present in the save format, however since the Bukkit API has no such way to construct an entity unattached to a world, and it appears creating such a way is a very challenging task, the decision was instead made to add this API now that 1.11 has entities which may not be represented by data values.
In the future it may be possible to implement a more expanded API cognate with this one.
Previously an UnhandledException would be thrown and the stack trace / message would be printed to System.err in the default UncaughtExceptionHandler for ThreadGroup. This was undesirable as it meant that logging frameworks / exception monitors such as Sentry were unable to get the exception. Additionally it would cause the death of the thread in the ExecutorService. This change mimics the behaviour of exceptions occuring during synchronous tasks.
https://bugs.mojang.com/browse/MC-100524
Log files were previously overwritten when more than 7 were created on the same day. This is caused by Log4J's default behavior with DefaultRolloverStrategy, which defaults to a max of 7.
While a max of 1000 doesn't fully stop this problem from happening, for 1000 log files in a single day to be reached the server would have to restart faster than once every 1.5 minutes, which is unlikely to happen. So 1000 seems like a good limit. A higher max isn't used because when it gets higher, there are performance hits due to the way Log4J checks for the next file.
Clean up implementation and firing of both of these events by routing
both unload and load behaviors to consistent method calls.
This fixes issues where a few places would not call Load or Unload events
when it should have.
Additionally, reduces diff by moving the neighbor marking code into these
consistent points.
Additional benefits of the change include improving the neighbor marking
methods to use getChunkIfLoaded instead of getLoadedChunkAt in some places,
as the latter will cause chunks to be marked active and not unload.
Finally, this also updates CraftWorld.loadChunk to use the new methods, as the
previous logic did not properly handle the new unload queue.
* Added hasGeneration()
* Fixed `applyHash()` (used by `CraftMetaItem.hashCode()`) not taking generation into account
* Fixed `equalsCommon()` (used by `CraftMetaItem.equals()`) not taking generation into account
Not technically 100% correct since null != "null", but without sacrficing performance this is the best way to fix the issue in the current implementation.
Changed assignment of pickup delays in such a way that they may not be larger than the value actually stored inside the NBT format that is Short.MAX_VALUE. Did not change method signature in order not to produce any shortening cast warnings in existing code. All values larger than 32767 are generally used to indicate that an item should never be picked up. Shortening this to 32767 will actually cause the pickup delay to never decrease, thus resulting in non-pickupable item stacks.
More APIs to follow pending feedback of whether this is the preferred implementation. Methods marked as deprecated and subject to change, but work as is.
Confirmed fix for itemframes not showing up. Based on the code in
CraftPainting.
Besids this fix we now pass null itemstacks directly to the
EntityItemFrame to allow the removal of items in ItemFrames.
If the server crashes during chunk generation then the chunk would have never
been added to the executor, this caused a second exception to be thrown when
the server shutdown from the first exception
Adds an check for existing entities before selecting the location allowing
for hanging entities to be spawned in blocks where there already is an
hanging entity at the default rotation.
Fixes the CraftHanging setRotation function to use the new 1.8 logic.
Related to SPIGOT-206.
Currently HangingEntities should be located next to the block they are
hanging on. With the direction set to the opposite of the block they
are hanging from.
This code is modified to find the correct direction.
calling CraftWorld.save() currently does not call WorldSaveEvent, and WorldSaveEvent could fire on worlds that have saving disabled.
New location will always fire during a world save and only during an actual save.
* commit '7371301edb1c44ab9153e1fba3722ba2f4e3c411':
Forgot that i work in Bukkit... Screw sun conventions
Implementation for the new rotation values. Fixes SPIGOT-93
Up until Minecraft version 1.5 it was not possible to teleport entities
within vehicles. With the 1.5 update came the change in the Minecraft
teleportation logic to dismount before teleporting the entity, if
applicable.
This commit ammends the existing CraftBukkit logic for rejecting
teleportation for entities in vehicles to permit the action. Due to this
change, CraftBukkit is now in-line with Minecraft 1.5 teleportation logic.
When a player dies their inventory is normally scattered over the the area
in which they died. Plugins should be able to modify this behaviour by
defining whether or not the player's inventory will be dropped on the ground or waiting for the player when they eventually respawn.
This commit implements the methods included in the Bukkit half for the new
behaviour by acting upon the boolean flag. The boolean flag is tested
prior to clearing the inventory as well as prior to dropping the items on
the ground. If the flag is true (indicating "keep inventory"), the items
are not removed from the player's inventory and are not dropped on the
ground.
When using a "vanilla" Minecraft server using the "pick block" key on a
command block yields the invoker with a command block within their
inventory while in creative mode. Implications of the invalid items set
containing the command block also include having a "ghost" item that
cannot be placed due to it not actually existing.
This commit resolves the problem and brings Craftbukkit closer to vanilla
behaviour by removing the command block item ID, 137, from the invalid
items set.
Prior to this commit cancelling the PlayerFishEvent would cause various
states of the fishing routine to be incorrectly or wrongly fired. This
incorrect behaviour was due to the miscommunication between the server and
client regarding the fishing state. When the event was cancelled, the
bobber entity was removed and caused the client to incorrectly determine
what the "next state" was to logically be.
This commit resolves the issue by ensuring the client is made aware of the
correct changes at the correct time regarding the bobber entity, therefore
keeping the logical steps of "fishing" proper and in-tact.
Up until this commit the PlayerDropItemEvent, if cancelled, would return
items to the first available slot in the inventory - which is clearly
undesirable as a player and plugin author to deal with.
This commit changes that by ensuring that the item is returned to where
it came from in the player's inventory. This still supports modifying the
drop from the player and will default to "first available slot" if the
item has changed since the event was fired. Other remaining behaviour of
the event is still in tact and has not been modified.
This change improves the quality of life for plugin developers using
iterator iteration with side-effects. In the specified Guava patch, the
internal iterator no longer relies on the AbstractList iterator which
iterates by index, and will instead wrap the provided iterator in a
transformer given the Function.
Many chunk sections contain parts of their data that are the same for
every block they contain. In these cases we can save memory by saving
a single value instead of an array of 4096 copies of that value. Block light
and block data are most likely to be uniform followed closely by sky light
data. Block ids are far less likely to be uniform but give the largest
saving when they are. Because of this we use a compact format for every
part of the chunk. Memory saved from this technique will vary based on the
world but seems to be about 50% on normal Minecraft generated chunks.
This commit centralizes event handling to where damage is actually applied
to the entity to avoid bugs that have resulted from nodamageticks,
modifications to damage after the event has been called, and similar
mishaps. This also implements new API for getting and setting of
modifications made to the damage amount actually applied to the entity.
This is done by storing the change in the damage amount as each modifier
is applied by vanilla code.
The method that actually damages the armor worn by an entity has been
relocated beneath the event called as to not apply durability loss when
the event has been cancelled.
When a chunk is loaded the server tries to ensure it has its initial light
calculations done before sending it to the player. When ticking entities
the server tries to ensure the entity does not walk into an unloaded chunk.
To accomplish these the server checks a one chunk radius around the chunk
to be lit or a two chunk radius around the chunk the entity is in. These
lookups happen every tick even though their result is unlikely to change
that often. To reduce the cost of these checks we replace them with a
system to keep track of what neighbor chunks a chunk has loaded and update
it when chunks load or unload which is a much less frequent action. On a
server with ten players this change removes about 100,000 calls a tick to
LongObjectHashMap's containsKey method.
In commits 71a238ee and c8591397 we added checks while ticking to ensure
we never ticked anything in a chunk meant to be unloaded. We did this to
prevent these chunks being removed from the unload queue and leaked.
However, this causes a ridiculously large number of lookups on the queue
for a somewhat rare occurance. We also now have the chunk GC which will
take care of these leaked chunks when they do happen. With this in mind
we now remove these checks which removes almost all uses of the
LongHashSet backing the unload queue.
After the changes in d611cff2 we started including a mob's equipment when
calling EntityDeathEvent so plugins can access this data. However, the
changes to enable this triggered a bug that makes skeletons and pig zombies
no longer drop equipment because they handle this differently than the rest.
On top of this we don't handle dropping equipment for mobs that cannot
pick up items in vanilla even though vanilla does drop equipment for them
if you summon them with it. We also do not include a horse's inventory
in the event so they drop their saddle, armor, chest, and chest contents
with no way for a plugin to control this.
To solve this issues we revert mob item dropping back to vanilla logic
and instead just capture all their drops in the method they all call to
spawn them into the world. We also move horse inventory dropping so it
happens at a time when we're capturing these drops. With these changes
all items mobs drop on death should now be included in the event and
we have less diff to worry about for future updates.
Waiting to log until after PlayerCommandPreprocessEvent makes the server
not log anything if the event is cancelled. It also makes the server log
what a plugin changed the command to instead of what the player actually
tried to run. As the point of the log is to have a record of every command
a player attempts to run these are both not desirable.
In 7e37cf96 we modified the container logic to handle custom max stack
sizes better and ensure the client stays in sync with this scenario. This
had the effect of sending an extra set slot packet for every inventory
click a player did which was not wanted. These extra packets also cause the
client to recalculate recipes which breaks the result slot for custom
recipes. To avoid the extra packets in general we now only send them if the
max stack is not the one we started with. In the case of a setting a custom
max stack size on a workbench this is still not enough so we also now send
another extra packet to make sure the result slot is always correct.
To handle changes in 1.7.9 we changed skull meta to use GameProfile
instances instead of strings of player names. This reflects what vanilla is
actually storing for skulls now. As skulls still require a name our API was
not changed and we instead look up the rest of the profile information from
the name. The way this was implemented made it so that deserializing a skull
or setting its name potentially involved a network request. As skull meta
itself does not actually require a complete profile we now simply create one
that only contains a name and leave populating it to the server when it is
actually needed.
With the current API it is possible to create an inventory with a specific
type, but it is not possible to give such an inventory a title other than
the default.
The commit changes that by adding a method to optionally supply the title
for the given inventory type and holder, creating the functionality to
display any supported inventory type with a 32 character length String.
If the inventory title supplied is larger than 32 characters then an
IllegalArgumentException is thrown stating so.
In commit 6efeddfe57, TALL_REDWOOD was used instead of the proper TreeType
of MEGA_REDWOOD. Additionally, this fixes an issue in CraftWorld with an
improper boolean flag related to the generation of MEGA_REDWOOD trees.
23 classes have been removed as they are no longer needed using the new
capture logic. This should help quite a bit with future MC updates.
BlockPlaceEvent Refactor
Before calling Item.interactWith, a recording flag is turned on for
setTypeAndData to capture a blockstate for each block that attempts to be set.
When a block place event is cancelled, the recorded blockstate, stack
size, and metadata will revert back to the captured state. If the event is
not cancelled, a notification will be sent to clients and block physics
will be updated.
BlockChangeDelegate Refactor
Now that we have the ability to capture blockstates through world, there
is no need to modify world gen classes with BlockChangeDelegate. Instead
we will simply capture blocks during world generation in order to "replay"
all of the captured blockstates to send back to delegates.
StructureGrowDelegate and BlockSapling.TreeGenerator have also been
removed as part of this change. BlockSapling and BlockMushroom will
capture blockstates the same as block placement and revert back any grow
events if needed.
After the changes in c549609d anvils started incorrectly limiting their
inputs to single item stacks. Vanilla allows for full size stacks here and
this is useful for using materials to repair items so now we do too.
Make sure we check the inventory's max stack size where appropriate and
don't assume the inventory slot is able to take our entire stack just
because it is empty. We also ensure the client is updated with the correct
slot contents and cursor contents in cases where the max stack changes
result in different behavior than the client expected.
The AnvilInventory reports its size as the sum of the ingredient and
result inventories, but when trying to access the slots, only the
ingredient inventory is used, leading to an ArrayIndexOutOfBounds exception.
This change overrides getItem(I) and setItem(I) to use both inventories,
with the slot number adjusted based on their size.
It's currently not possible for a plugin to allow enchanting of an
otherwise un-enchantable item using the enchanting table. This commit
causes EnchantItemEvent to be called with an empty list of enchantments,
allowing a plugin to provide it's own set of enchantments when vanilla
Minecraft would not allow any. It also bypasses the unsafe enchantment check
since a plugin should be permitted to apply any enchantments they like, and
vanilla should not generate unsafe enchantments of its own.
Setting the goal target overrides the entity's will to do something
else. This makes it so entities like wolves with attack another player
with .setTarget(), instead of hanging next to their owner.
Currently, whenever a player places a block in a protected area the
equipped itemstack size on client is never updated properly since the
client thinks the block was placed. The reason this happens is because
ItemStack.matches returns true since the server does not decrement stack
size if a BlockPlaceEvent is cancelled. To correct this on cancel we set
the flag to always update the client regardless of matching.
Currently if a plugin cancels an InventoryOpenEvent for vanilla chests,
the chest animation for clients is stuck in the open state since
IInventory's closeContainer method is never called. To fix the issue,
closeContainer is called before exiting the display GUI method.
If a conversation is abandoned due to a player disconnecting and an
exception is thrown in a ConversationAbandonedListener, the server will
crash. This commit prevents the exception from propagating further up
the stack and instead just logs the error.
Chunk caching in the World class does not know about outdated cache values.
This caused various problems when accessing previously unloaded chunks. The
caching also did not improve the performance so it is removed.
Synchronization is also not necessary, because all accesses to getChunkAt
may only come from the main thread.
Previously, Detector Rails were the only rails that properly called
BlockRedstoneEvent when they changed from powered to unpowered. This commit
adds BlockRedstoneEvent calls for both Powered Rails and Activator Rails.
Currently, plugins can set a player's display name to null, which could
cause issues for other calls to getDisplayName that aren't expecting a null
value. This changes setDisplayName to follow the same logic as
setPlayerListName, which sets the player's name back to their unmodified
"vanilla" name if it receives a null value as a parameter.
Previously, whenever BlockFadeEvent was called for ice melting, it returned
the new BlockState with a type of Material.STATIONARY_WATER. However, in
the Nether, ice melting does not form water, but is simply replaced by air
instead. This changes the event to use the proper BlockState based on
whether the block is located in the Nether or not.
CraftBukkit adds the ability to specify the maxStack size for most
inventories. However, some inventories were not overriding the getMaxStack
method properly, and so the functionality was unavailable. This fixes the
maxStack setting for Anvils, Minecarts, PlayerInventory, and Hoppers.
Previously, the SlotType for the last 4 slots in a player's inventory
returned QUICKBAR when it should have returned SlotType.CONTAINER. This
updates the code for determining slot type to return the proper value.