Solved ItemMeta & ItemMetaData

Discussion in 'Plugin Development' started by Adriani6, May 8, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    Adriani6

    Hi, I would like to know if there's possibly anything to go about this.
    1. I spawn a pressure plate (Stone Plate) and set custom name on it.
    2. When player steps on it, I want to check if it has the set name above.

    Problem is step 2. I am using PlayerInteractEvent in the following way

    Code:
    if(event.getAction().equals(Action.PHYSICAL)){
    if(event.getClickedBlock().getType() == Material.STONE_PLATE){
    now the big problem is, I need to check the custom name (Display Name), doing event.getClickedBlock() doesn't let me check that, all there is, is Metadata which is no use to me as it gets removed when server is shut...

    How would I check ItemMeta ?
     
  2. Offline

    Zethariel

    Adriani6 You need to set a Collection or Array that will hold the positions for you, and check with that. No other reliable way around that for the time being.
     
  3. Offline

    desht

    As you've discovered, ItemMeta applies to items, not blocks. If you want the special ItemMeta to transfer to blocks you're placing, you'll need to do this manually:
    • In your BlockPlaceEvent handler, check for the appropriate ItemMeta data.
    • If the item being placed has that data, record this on the Block. Probably the easiest way is via Bukkit Metadata - https://forums.bukkit.org/threads/metadata-q-a-i-wrote-the-metadata-api-ama.68447/ but you can use some kind of custom storage mapping the block to your data if you want. If you do that, don't use a Block or Location object directly as a Map key.
    • You'll probably also want to do the reverse - in your BlockBreakEvent handler, check for the Bukkit Metadata and if found, remove it, and place your custom ItemMeta on the dropped item. To do this, you'll need to set the block to AIR, and explicitly drop the item with world.dropItemNaturally().
    • Be very sure to set your place and break handlers to use ignoreCancelled=true and priority=MONITOR.
    • It's up to you to ensure that the block metadata is persisted somehow. Whether you use a database, flat files, etc. is your choice, but you need to save that metadata either when it's placed or your plugin is disabled, and restore it when your plugin is enabled.
     
  4. Offline

    Etsijä

    In my plugin (ImpactTNT), I am actually using a very similar concept as what desht described, although I am not using ItemMeta for my purpose:
    • my plugin recognises dispensers loaded up with my "grenade-like TNT" (class ImpactTNT) as CannonDispensers
    • on plugin level, I have a List<CannonDispenser> cannons, which gets updated whenever a player sets up a "cannon". The list includes the dispenser's coordinates, along with some other info
    • when a player breaks a Dispenser somewhere, the plugin loops through this list and if it finds a cannon at those coordinates, it removes the item from the list
    • on server shutdown, I serialize the list of cannons and write it as a binary datafile
    • on server startup, I read the datafile and deserialize back into a List<CannonDispenser>
    This approach works very well for me. If you're interested, have a lookat my code at https://github.com/Etsija/ImpactTNT

    The parts of the code relevant to your question are ImpactTNT.saveCannons(), ImpactTNT.loadCannons(), ImpactTNTEvents.onDispenserInteract(), ImpactTNTEvents.onDispenserBreak() and the whole of CannonDispenser class.
     
    Adriani6 likes this.
  5. Offline

    desht

    Yep, that's a good approach, but if you're dealing with (or could possibly deal with in future) more than a very few cannons, you really should be using a Map (HashMap), not a List. Key the map by the coordinates of the cannon, and lookups and removals will perform far better. I like this link: http://initbinder.com/articles/cheat-sheet-for-selecting-maplistset-in-java.html - if you follow it through for your approach (finding a cannon given its location), you'll end up with a HashMap.

    Also, saving the list only on server shutdown (plugin disable?) does risk losing data if the server crashes for any reason, including circumstances beyond your control. On the other hand, saving the list of cannons every time one is added or removed could be bad for performance. A compromise between safety and efficiency is to set a boolean flag whenever a change is made, and check for that periodically (say 30 or 60 seconds). If the flag is set, then do a save and reset the flag. The check interval can be made configurable too, so the server owner gets to decide on the trade-off.
     
  6. Offline

    Etsijä

    desht: really good suggestions, thanks for those! Will certainly change the List to a HashMap. And, regarding the saving, I do have an admin command to save the list whenever wanted, but your approach would of course be a safer one, from persistence point of view.
     
  7. Offline

    Adriani6

    Thank for all the suggestions, I figured it out :)
     
Thread Status:
Not open for further replies.

Share This Page