Block metadata, how should I use it ?

Discussion in 'Plugin Development' started by Digi, Apr 1, 2012.

Thread Status:
Not open for further replies.
  1. I don't quite get the metadata thing, I read about it in Bukkit+ section but it's kinda criptic to me.

    So, I want to use it to store a Double value inside furnaces (for timer), I don't need them to persist over server restarts but I want them to be there when I get them and I will get them every tick.

    I'm currently using a HashMap<Location, Double> to store my double for furnaces, would metadata be an improvement and how to use it, example please :}
  2. Offline


    It depends. Do you want the player to be able to remove the furnace, and have whatever timer to continue? I'm not too knowledgeable on MetaDeta, so I would use HashMaps if that is what you are more confortable.
  3. I need a furnace specific double to keep track of the cooking time, I can't use it's internal cooking time because that gets updated automatically and it gets very confusing to try and work with that.

    Hmm, actually, I need to keep track of locations anyway... so a hashmap would be just fine.

    I'm still curious about metadata behaviour in simple terms for future projects :}
  4. Offline


    I've been trying to get more insight on how it all works too.

    From This Thread, I found the link to this preliminary doc, which gives a lot of insight on how the API works for getting/setting, and what all metadata can store or compute.

    Since writing my post in there, I've done some more searching by looking at the source for both bukkit and CraftBukkit, and reading through the tickets, I've found out a few things:

    Firstly, there's no persistence for metadata currently, and I don't believe it's planned. In layman's terms, that means when the server shuts down, metadata goes poof. Given the fact that metadata are implemented by default as a Future-like object, where the result is computed as the result of a callable (and the FixedMetadataValue is just a special-case where it makes said callable for you) it wouldn't even be really practical to do persistence with the current setup.

    Next, the way metadata is stored is not actually data-local to an object (such as a private field on the entity or Player or Block) but actually in a scope-specific "metadata store." There's a metadata store for blocks in a given world, and one for entities on the whole server, one for players, etc.
    - One downside is there's an extra lookup for metadata for an object, on some deterministic key of that object.
    - The upside is that if an object came by later with the same deterministic key (ie, player logs out and back in making a new Player object, he'd have the same key "disambiguation" thus would inherit the same metadata as was stored on the previous instance of that player. See here.

    Next, though metadata values can be computed and are referenced softly, the metadata containers and the keys they're referenced by are never removed unless you specifically remove it. That means, say your AwesomeProtectionPlugin set a value of "protected' => FixedmetadataValue(false/true) on every single block. You'd be then wasting a whole lot of keys and values in memory pointing to stuff, even when the chunk is unloaded. This means, be careful in what sort of metadata you choose to store. (for what it's worth, for the theoretical awesome protection plugin, you could just store metadata on the blocks which are actually protected, and then use hasMetadata to know a block is not protected, rather than storing false on every non-protected block.)

    That said, metadata has some really cool possibilities available for it, and on certain plugin types it is an extremely useful tool. It takes a lot of repetitive work away from the plugin author in maintaining data structures that are properly scoped and keyed on objects. For example, in my plugin I have things like:
    Map<String, Map<BlockVector, SomeObject>
    which maps world name -> block coordinate -> something I'm storing. If I were to change this to store as a metadata that's a lot less work for me to manage those data structures.

    I'd say that in a large number of use cases, you could use the metadata system to effectively put data about an object. However, there are some scenarios where you need more control over the data storage, so you may want to make your own structures that map things about data. Also, if you need persistence, you may need to maintain a parallel mapping just to allow you to persist the data, though you could still have the stuff as metadata for either other plugins to be able to use, or for quick lookups.
    Plo124, InspiredOne, deltahat and 2 others like this.
  5. Offline


    Excellent writeup on MetaData. I've been meaning to write the introductory overview on it myself.

    Are you planning to share your furnace data with other plugins? The driving force behind the MetaData API is for facilitating inter-plugin communication. If your data is purely internal, you may be better sticking with a simple HashMap.
  6. Crast
    Well, it seems until I try it myself I'll still be confused about it, I never could learn through theory/reading XD, but thanks :}

    deltahat Yes it's internal (useless to other plugins) and I am sticking with HashMap because I belive it's faster to loop through a hashmap of locations and doubles rather than looping through each loaded chunk, getting all tile entities, checking for furnaces and then getting the metadata... and all that every tick xD
Thread Status:
Not open for further replies.

Share This Page