(Feature Request) MMOItems support.
XXX10Tacles opened this issue · 7 comments
Hi, i am requesting to add feature using which Shopkeeper will update trading items for adminshops. well if i put item and then i update plugin i am no longer able to trade as when plugin updates it also changes NBT tags so i have to update all shops manually.
I have something like this on my internal todo list to look into. However, it is unclear yet how to exactly identify old items inside the shopkeepers that are meant to be replaced with some new item inside the inventory. One can easily come up with several possible item matching conditions, each of which might be suited in some situations but not others.
Example: One matching condition that initially seems to intuitively make sense might be to consider items to 'match' if their type, display name, and lore are equal. However, this would mean that we would ignore all other item data (enchantments, attributes, etc.), which might not actually be what is wanted, because we might not actually want to replace (possibly remove) this data in all trades across all shopkeepers.
But there is no easy way to know (or for a user to define) what data to match and what data to ignore.
And even if there were some way for users to nicely define which data to match or which data to ignore (maybe by specifying a list of NBT tags to match or to ignore by names/paths; which is not really convenient, and error prone), another technical difficulty would then be to actually implement this item matching, because Bukkit does not offer an API to inspect the individual low-level NBT elements of items.
What can be done via Bukkit is to compare the full data of two items. And what can be done in Shopkeepers is to compare one 'source' item with another 'target' item, ignoring any full NBT tags of 'target' that are not present in 'source'.
One idea for users to conveniently define how items should be matched (i.e. without having to write longs lists of NBT data paths) and how items should then be replaced, that only uses the currently available means of matching items, could be to require them to provide 2 items, maybe by holding one in their main hand and one in their off hand: The item in the main hand could be used to match against the items inside the shopkeepers (i.e. it would only contain the NBT data that is meant to be matched and omit all other data), and the item in the off hand would then be the item that replaces the matched items inside the shopkeepers.
Example: If you want to replace all custom emerald items inside shopkeeper trades that have a display name "A" and lore "L1" with a new emerald item that has a name "A" and a lore "L2", you would setup two items (with some item creation plugin of your choice): Item 1 (in your main hand) will have display name "A" but will not have any lore (so the lore is ignored when matching items). And item 2 (in your off hand) will be your new intended item (display name "A" and lore "L2"). The plugin could then identify all items inside shopkeepers based on item 1 (comparing display names but ignoring the omitted lore), and replace those items with the new intended item 2.
Can you post some concrete examples of the NBT data of items you have stored inside your shopkeepers currently and the NBT data of items you want to replace them with?
You can use Minecraft's /data get <player>
command to get a textual representation of the NBT data of items inside a player's inventory. If you execute this command from console you can copy and paste this in text form, which is easier to work with.
Old item.
SelectedItem: {id: "minecraft:heart_of_the_sea", tag: {MMOITEMS_DYNAMIC_LORE: '[
"Material","გამოიყენება შოპში ვილეჯერებთან","სავაჭროდ.","","ხშირადობა: VERY RARE"]', MMOITEMS_ITEM_ID: "BLUE_EMERALD", MMOITEMS_NAME: "Blue Emerald", MMOITEMS_CUSTOM_MODEL_DATA: 21998, MMOITEMS_ENCHANTS: "[]", MMOITEMS_REVISION_ID: 3, AttributeModifiers: [{Name: "mmoitemsDecoy", Operation: 0, UUID: [I; -2021319128, -1357757450, -1987131861, -563359508], Amount: 0.0d, AttributeName: "minecraft:generic.attack_speed"}], MMOITEMS_ITEM_TYPE: "MATERIAL", HideFlags: 2, HSTRY_ENCHANTS: '{"Stat":"ENCHANTS"}', display: {Name: '{"italic":false,"color":"blue","text":"Blue Emerald"}', Lore: ['{"extra":[{"bold":false,"italic":false,"underlined":false,"strikethrough":false,"obfuscated":false,"color":"gold","text":"Material"}],"text":""}', '{"extra":[{"bold":false,"italic":false,"underlined":false,"strikethrough":false,"obfuscated":false,"color":"gray","text":"გამოიყენება შოპში ვილეჯერებთან"}],"text":""}', '{"extra":[{"bold":false,"italic":false,"underlined":false,"strikethrough":false,"obfuscated":false,"color":"gray","text":"სავაჭროდ."}],"text":""}', '{"text":""}', '{"extra":[{"bold":false,"italic":false,"underlined":false,"strikethrough":false,"obfuscated":false,"color":"gray","text":"ხშირადობა: "},{"bold":true,"italic":false,"color":"yellow","text":"VERY RARE"}],"text":""}']}, CustomModelData: 21998, MMOITEMS_LORE: '["გამოიყენება შოპში ვილეჯერებთან","სავაჭროდ."]', MMOITEMS_TIER: "VERY_RARE"}, Count: 1b}, Paper.OriginWorld: [I; -541780948, -1011661656, -2017012581, 1036489364], Purpur.TPSBar: 0b, Paper: {LastLogin: 1647814420547L, LastSeen: 1647817814592L}, EnderItems: [], foodLevel: 20, Air: 300s, XpSeed: -426813573, XpLevel: 16, XpP: 0.99058825f, UUID: [I; 305565685, 396246862, -1453089872, -1333030661], Spigot.ticksLived: 2390594, Inventory: [{Slot: 8b, id: "minecraft:heart_of_the_sea", tag: {MMOITEMS_DYNAMIC_LORE: '["Material","გამოიყენება შოპში ვილეჯერებთან","სავაჭროდ.","","ხშირადობა: VERY RARE"]', MMOITEMS_ITEM_ID: "BLUE_EMERALD", MMOITEMS_NAME:
"Blue Emerald", MMOITEMS_CUSTOM_MODEL_DATA: 21998, MMOITEMS_ENCHANTS: "[]", MMOITEMS_REVISION_ID: 3, AttributeModifiers: [{Name: "mmoitemsDecoy", Operation: 0, UUID: [I; -2021319128, -1357757450, -1987131861, -563359508], Amount: 0.0d, AttributeName: "minecraft:generic.attack_speed"}], MMOITEMS_ITEM_TYPE: "MATERIAL", HideFlags: 2, HSTRY_ENCHANTS: '{"Stat":"ENCHANTS"}', display: {Name: '{"italic":false,"color":"blue","text":"Blue Emerald"}', Lore: ['{"extra":[{"bold":false,"italic":false,"underlined":false,"strikethrough":false,"obfuscated":false,"color":"gold","text":"Material"}],"text":""}', '{"extra":[{"bold":false,"italic":false,"underlined":false,"strikethrough":false,"obfuscated":false,"color":"gray","text":"გამოიყენება შოპში ვილეჯერებთან"}],"text":""}', '{"extra":[{"bold":false,"italic":false,"underlined":false,"strikethrough":false,"obfuscated":false,"color":"gray","text":"სავაჭროდ."}],"text":""}', '{"text":""}', '{"extra":[{"bold":false,"italic":false,"underlined":false,"strikethrough":false,"obfuscated":false,"color":"gray","text":"ხშირადობა: "},{"bold":true,"italic":false,"color":"yellow","text":"VERY RARE"}],"text":""}']}, CustomModelData: 21998, MMOITEMS_LORE: '["გამოიყენება შოპში ვილეჯერებთან","სავაჭროდ."]', MMOITEMS_TIER: "VERY_RARE"}, Count: 1b}], WorldUUIDLeast: -7332783450607473716L, FallDistance: 0.0f, DataVersion: 2730, SleepTimer: 0s, Motion: [0.0d, -0.0784000015258789d, 0.0d], previousPlayerGameType: 1, Pos: [4.769938110308436d, 115.0d, 2.923284105571875d], Health: 25.55f, HurtTime: 0s, FallFlying: 0b, Purpur.ShouldBurnInDay: 0b, Fire: -20s, PortalCooldown: 0, foodExhaustionLevel: 3.997124f, Paper.SpawnReason: "DEFAULT"}
new version of same item.
SelectedItem: {id: "minecraft:heart_of_the_sea", tag: {MMOITEMS_DYNAMIC_LORE: '["Trade re
source.","","&6「」Material","","&7Tier VERY RARE"]', MMOITEMS_ITEM_ID: "BLUE_EMERALD", MMOITEMS_NAME: "Blue Emerald", MMOITEMS_REVISION_ID: 5, MMOITEMS_ENCHANTS: "[]", MMOITEMS_CUSTOM_MODEL_DATA: 21998, AttributeModifiers: [{Name: "mmoitemsDecoy", Operation: 0, UUID: [I; -2021319128, -1357757450, -1987131861, -563359508], AttributeName: "minecraft:generic.attack_speed", Amount: 0.0d}], MMOITEMS_ITEM_TYPE: "MATERIAL", HSTRY_ENCHANTS: '{"Stat":"ENCHANTS","OGStory":[{"MMOITEMS_ENCHANTS_ñstr":"[]"}]}', HideFlags: 2, CustomModelData: 21998, display: {Name: '{"italic":false,"color":"blue","text":"Blue Emerald"}', Lore: ['{"italic":false,"color":"gray","text":"Trade resource."}', '{"italic":false,"text":""}', '{"italic":false,"color":"gold","text":"「」Material"}', '{"italic":false,"text":""}', '{"italic":false,"extra":[{"color":"gray","text":"Tier "},{"bold":true,"color":"yellow","text":"VERY RARE"}],"text":""}']}, MMOITEMS_TIER: "VERY_RARE", MMOITEMS_LORE: '["Trade resource."]'}, Count: 1b}, Paper.OriginWorld: [I; -541780948, -1011661656, -2017012581, 1036489364], Purpur.TPSBar: 0b, Paper: {LastLogin: 1647814420547L, LastSeen: 1647818240942L}, EnderItems: [], foodLevel: 20, Air: 300s, XpSeed: -426813573, XpLevel: 16, XpP: 0.99058825f, UUID: [I; 305565685, 396246862, -1453089872, -1333030661], Spigot.ticksLived: 2399121, Inventory: [{Slot: 0b, id: "minecraft:heart_of_the_sea", tag: {MMOITEMS_DYNAMIC_LORE: '["Trade resource.","","&6「」Material","","&7Tier VERY RARE"]', MMOITEMS_ITEM_ID: "BLUE_EMERALD", MMOITEMS_NAME: "Blue Emerald", MMOITEMS_REVISION_ID: 5, MMOITEMS_ENCHANTS: "[]", MMOITEMS_CUSTOM_MODEL_DATA: 21998, AttributeModifiers: [{Name: "mmoitemsDecoy", Operation: 0, UUID: [I; -2021319128, -1357757450, -1987131861, -563359508], AttributeName: "minecraft:generic.attack_speed", Amount: 0.0d}], MMOITEMS_ITEM_TYPE: "MATERIAL", HSTRY_ENCHANTS: '{"Stat":"ENCHANTS","OGStory":[{"MMOITEMS_ENCHANTS_ñstr":"[]"}]}', HideFlags: 2, CustomMode
lData: 21998, display: {Name: '{"italic":false,"color":"blue","text":"Blue Emerald"}', Lore: ['{"italic":false,"color":"gray","text":"Trade resource."}', '{"italic":false,"text":""}', '{"italic":false,"color":"gold","text":"「」Material"}', '{"italic":false,"text":""}', '{"italic":false,"extra":[{"color":"gray","text":"Tier "},{"bold":true,"color":"yellow","text":"VERY RARE"}],"text":""}']}, MMOITEMS_TIER: "VERY_RARE", MMOITEMS_LORE: '["Trade resource."]'}, Count: 1b}], WorldUUIDLeast: -7084065733221238552L, FallDistance: 0.0f, DataVersion: 2730, SleepTimer: 0s, Motion: [0.0d, -0.0784000015258789d, 0.0d], previousPlayerGameType: 1, Pos: [88.5686256506057d, 72.0d, -105.76359174699468d], Health: 25.55f, HurtTime: 0s, FallFlying: 0b, Purpur.ShouldBurnInDay: 0b, Fire: -20s, PortalCooldown: 0, foodExhaustionLevel: 3.997124f, Paper.SpawnReason: "DEFAULT"}
Like get nbt tag MMOITEMS_ITEM_ID: "BLUE_EMERALD" using API then compare if exists in database and update with full one if it matches.
btw this MMOITEMS_REVISION_ID identify how new item is lets say if i want to make change i just rise revision id and plugin is changing all items on server.
So you are basically asking for something like #773 , but for MMOItems.
So you are basically asking for something like #773 , but for MMOItems.
YEP :))