The idea is that this might allow for optimization when doing shopkeeper lookups: Previously we had to create and check object ids for all shop object types in order to check if a block or entity is a shopkeeper of a certain type. We still have to go through all registered shop object types, but we can skip those which use the default ids.
However, as of right now this doesn't seem to make much of a difference. In a future step we could further optimize this by caching all object types which use non-default object ids.
Also, some default method implementations were moved into AbstractBlockShopObject and AbstractEntityShopObject.
Monsters usually get set on fire quite frequently when standing in sunlight. We therefore give zombies and skeletons a stone button as helmet now. This prevents them from getting set on fire in sunlight, by which we have to process less EntityCombustEvents. The stone button is also small enough to not be visible inside their head.
Entities standing in lava or fire are still set on fire as before.
This is no handled similarly to parrots (which do not support the baby state either).
Also fixed: The villager editor will no longer show the baby editor option for wandering traders.
Any villagers and wandering traders which are not Citizens NPC or shopkeepers are considered 'regular'.
The editor supports editing the villager trades, similar to how editing works for admin shopkeepers. Note that trades created or edited via the editor will have infinite uses, no xp rewards, no price multipliers and the current uses counter gets reset to 0 (there are currently no options to edit or persist these attributes).
To not accidentally edit all original trades whenever the editor is opened and closed (and thereby change the above mentioned trade attributes), we compare the trades from the editor with the villager's current trades before applying the trades from the editor: If the items of a trade are still the same, we keep the original trade without changes. A message indicates how many trades have been modified.
Since villagers may change their trades whenever they change their profession, we set the villager's xp to at least 1 whenever the villager's trades or profession have been modified via the editor.
If the villager is killed or gets unloaded while editing, any changes in the editor will have no effect.
Other supported villager editor options are:
* Deleting the villager entity.
* Opening a copy of the villager's inventory. Note that any changes to the opened inventory are not reflected in the villager's inventory currently (i.e. you can view, but not modify the villager inventory with this).
* Changing the villager profession. Changing the profession via the editor will keep the current trades.
* Changing the villager type (i.e. the biome specific outfit).
* Changing the villager level (i.e. the badge color). This also affects which level is displayed and whether the villager's xp is shown within the villager's trading UI.
* Toggling the villager's AI on and off. This is useful to make the villager stationary while editing it. Otherwise it may wander away.
Related changes:
* Permissions: Added `shopkeeper.edit-villagers` and `shopkeeper.edit-wandering-traders` (default: `op`). These are required to edit regular villagers or wandering traders respectively.
* Added command `/shopkeeper editVillager [villager]`. This opens an editor to edit the specified villager / wandering trader. The villager / wandering trader can either be specified by uuid or by looking at it.
* Config: Added settings `edit-regular-villagers` and `edit-regular-wandering-traders` (default: `true`). With these settings enabled the villager editor can be opened by simply sneaking and right-clicking a regular villager (similar to how editing works for shopkeepers).
Various related internal changes:
* Added new command arguments to specify an entity by uuid.
* Added new command arguments to select a targeted entity.
* Moved and added some merchant and trading recipe related utilities into MerchantUtils.
* Minor changes to the comparison of merchant recipes.
* Moved the shopkeeper metadata key constant into ShopkeeperUtils.
* Added ItemUtils#getOrEmpty(ItemStack).
* ShopkeeperUIHandler is an interface now. This allows for more flexibility in the class hierarchy of UI handlers. Added a basic implementation 'AbstractShopkeeperUIHandler'.
* Removed the unused SKDefaultUITypes#register() method.
* Various refactoring related to the editor UI. There is now a separate base class for the shared implementation of the shopkeeper editor and the new villager editor UI. Any shopkeeper references had to be removed from the base class. All existing shopkeeper editor buttons had to be slightly adapted to this change.
Other changes:
* Minor fix: If the second buy item of a trading recipe is empty, the corresponding created merchant recipe stores that as an empty second ingredient now. This should help when checking if the existing merchant recipes still match the newly created merchant recipes and thereby cause less recipe updates that are not actually required.
Added messages:
* msg-missing-edit-villagers-perm
* msg-missing-edit-wandering-traders-perm:
* msg-must-target-entity
* msg-must-target-villager
* msg-target-entity-is-no-villager
* msg-villager-editor-title
* msg-villager-editor-description-header
* msg-villager-editor-description
* msg-button-delete-villager
* msg-button-delete-villager-lore
* msg-button-villager-inventory
* msg-button-villager-inventory-lore
* msg-button-mob-ai
* msg-button-mob-ai-lore
* msg-villager-inventory-title
* msg-set-villager-xp
* msg-no-villager-trades-changed
* msg-villager-trades-changed
* msg-command-description-edit-villager
This can still be overridden inside subclasses of TradingHandler.
Also: The created villager trading recipes use a 'max-uses' limit of the maximum integer value now (instead of 10000). If the trade is 'out of stock' both the 'max-uses' and the 'uses' are set to 0. This change should probably not affect anyone though.
* Added UISession#close(), #closeDelayed(), #closeDelayedAndRunTask(Runnable), #abort(), #abortDelayed(), #abortDelayedAndRunTask(Runnable).
* Added Shopkeeper#getUISessions() and #getUISessions(UIType).
* Deprecated Shopkeeper#closeAllOpenWindows() and replaced it with #abortUISessionsDelayed().
* Added UIRegistry#getUISessions(), #getUISessions(Shopkeeper), #getUISessions(Shopkeeper, UIType), #getUISessions(UIType).
* Deprecated UIRegistry#getSession(Player) and added replacement #getUISession(Player).
* Deprecated UIRegistry#getOpenUIType(Player).
* Deprecated UIRegistry#closeAll(), #closeAll(Shopkeeper) and #closeAllDelayed(Shopkeeper) and added replacements #abortUISessions(), #abortUISessions(Shopkeeper) and #abortUISessionsDelayed(Shopkeeper).
* Various related javadoc changes and minor formatting.
* Fixed a few debug messages inside UIListener.
* Minor fix: We check if the shopkeeper is still valid before attempting to open its container now.
Internal changes:
* Removed UIHandler#closeDelayedAndRunTask and replaced it with using the new methods inside UISession.
* The UI listener is only created once now.
* Minor internal renaming inside SKUIRegistry.
* Simplified the implementation of ending / aborting UI sessions.
* Delayed closing of UIs uses the SchedulerUtils now, which guards against issues during plugin shutdown.
It is now possible to create and open UIs that are not associated with any shopkeeper.
* API: UISession#getShopkeeper may return null now.
* API: Added PlayerOpenUIEvent.
* API: The ShopkeeperOpenUIEvent no longer extends ShopkeeperEvent, but the newly added PlayerOpenUIEvent instead.
* API: Removed Shopkeeper#isUIActive, #deactivateUI, #activateUI. This is now part of the UISession.
Related internal changes:
* Moved UIHandler#getShopkeeper into a separate ShopkeeperUIHandler class. The existing editor, trading and hiring UIs extend from that now.
* Replaced EditorHandler#closeEditorAndRunTask with UIHandler#closeDelayedAndRunTask.
* Various changes to javadoc and code comments.
Also added a message (msg-unsupported-container) when a player tries to select a type of container which is not supported by shopkeepers (i.e. hopper, dropper, dispenser, brewing stand, ender chest, or a type of furnace).
Other related changes:
* API: Deprecated PlayerShopkeeper#getChestX/Y/Z, #get/setChest, #getCurrencyInChest, #openChestWindow and PlayerShopCreationData#getShopChest and added corresponding replacements methods with more general names.
* Various internal renaming related to shop containers.
* Various internal formatting of code comments.
Config changes:
* Changed a few comments inside the default config related to the shop container changes.
* Bumped config version to '3'. A few settings were renamed which get automatically migrated:
* `require-chest-recently-placed` (now `require-container-recently-placed`)
* `max-chest-distance` (now `max-container-distance`)
* `protect-chests` (now `protect-containers`)
* `delete-shopkeeper-on-break-chest` (now `delete-shopkeeper-on-break-container`)
* `enable-chest-option-on-player-shop` (now `enable-container-option-on-player-shop`)
* `chest-item` (now `container-item`)
Added messages:
* msg-unsupported-container
Changed messages:
* Some message settings were renamed. If you don't use a custom / separate language file, they get automatically migrated as part of the config migration to version 3. However, most of these messages also had changes to their default contents which need to be applied manually.
* msg-button-chest (now msg-button-container)
* msg-button-chest-lore (now msg-button-container-lore)
* msg-selected-chest (now msg-container-selected)
* msg-must-select-chest (now msg-must-select-container)
* msg-no-chest-selected (now msg-invalid-container)
* msg-chest-too-far (now msg-container-too-far-away)
* msg-chest-not-placed (now msg-container-not-placed)
* msg-chest-already-in-use (now msg-container-already-in-use)
* msg-no-chest-access (now msg-no-container-access)
* msg-unused-chest (now msg-unused-container)
* msg-cant-trade-with-shop-missing-chest (now msg-cant-trade-with-shop-missing-container)
* msg-creation-item-selected
* msg-shop-setup-desc-selling
* msg-shop-setup-desc-buying
* msg-shop-setup-desc-trading
* msg-shop-setup-desc-book
* msg-trade-setup-desc-selling
* msg-trade-setup-desc-buying
* msg-trade-setup-desc-book
Also:
* SKCitizensShopObjectType#isEnabled redundantly checked the config setting.
* The warning which would get printed if citizen shops are enabled but the Citizens plugin is not found has been turned into a debug message.
This was broken since MC 1.14. All shopkeeper entities always use the NoAI flag now.
Note: We still need to overwrite the vanilla pathfinder goals in order to handle the 'look-at-nearby-players' behavior (we currently reuse the vanilla implementation for this).
Also added some comments about possible TODOs, Bukkit's isAware flag and changes to the collidable API.
* The legacy permissions `shopkeeper.player.normal`, `shopkeeper.villager`, `shopkeeper.witch` and `shopkeeper.creeper` have been removed. Use the corresponding replacement permissions instead.
* All players have access to all mob types (permission `shopkeeper.entity.*`) by default now.
The default shop creation item is a villager spawn egg with display name
'&aShopkeeper' now.
Regular usage of the shop creation item is disabled by default now.
* Fixed: We no longer attempt to spawn Citizens NPCs when creating or loading Citizens shopkeepers if the spawn location's world is not loaded currently.
* Fixed: Some versions of Citizens would produce an error when we try to teleport a NPC which has no location and is therefore not spawned currently. The teleport attempt has been replaced with an attempt to spawn the NPC.
Added config option `convert-player-items` (default: false). If enabled, items inside the inventories of players and shop chests gets converted to Spigot's internal data format whenever a player is about to open a shopkeeper UI (eg. trading, editor, hiring, etc.).
Added config options `convert-all-player-items` (default: true) and 'convert-player-items-exceptions' (default: []). These two settings allow limiting which items are affected or ignored by the automatic conversion.
Note: Enabling this setting comes with a performance impact. You should generally try to avoid having to use this setting and instead search for alternative solutions. For more information, see the notes on this setting inside the default config.
Internal changes:
* Added support for Lists of ItemData inside the config.
* We throw an exception now when we encounter an unexpected / not yet handled config setting type.
Instead of serializing and deserializing the items to/from a Yaml config, we only convert and reload the ItemMeta to/from its serialized form.
In my tests this has reduced the worst case timings from around 30+ ms to around 3.5 ms (still not good, but a lot better compared to before).
Other changes:
* Internal: Moved the code handling the serialization and deserialization of ItemMeta from ItemData into ItemUtils. This is used for our item conversions as well now.
* Debug: The item conversion debug messages include the timing information now.
* Debug: Since the item conversions always have some performance impact, even if no items got actually converted, we always print the debug messages now (if debug option 'item-conversions' is enabled) to allow debugging the item conversion times.
This logs whenever we explicitly converted items to Spigot's data format. Note that this does not log when items get implicitly converted, which may happen under various circumstances.
Other internal changes:
* Added a utility function for converting items of a given inventory. This also handles the cursor items of player inventories, and the updating of changed inventories to all current viewers. The convertItems command makes use of this new method now.
* ItemUtils#updateInventoryLater() takes into account the owner of a given player inventory now.
The previous permission `shopkeeper.convertitems` has been replaced by `shopkeeper.convertitems.own` and `shopkeeper.convertitems.others`.
Also made some minor formatting changes to the changelog.
Added corresponding permission node `shopkeeper.convertitems` (default: op).
This command can be used to convert the held (or all) items to conform to Spigot's internal data format. I.e. this runs the items through Spigot's item serialization and deserialization in the same way as it would happen when these items are used inside shopkeeper trades and the plugin gets reloaded.
Added messages:
* msg-command-description-convert-items
* msg-items-converted