Metadata Q&A - I wrote the Metadata API, AMA

Discussion in 'Plugin Development' started by deltahat, Apr 2, 2012.

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

    Digi

    Then you should set a single key with all player's permissions, that way you know the key.

    Actually it would be best to make a map to remember the keys.
     
  2. Offline

    blablubbabc

    Hey, I am thinking about using this in this scenario:
    Scenario: Players playing paintball (player try to hit the other teams player with snowball by throwing them/using "weapons" that spawn snowballs)
    Currently:
    Player throws snowball-> I check if the player is playing paintball -> snowball gets some boost up etc.
    Player (which is playing paintball) receives damage by a snowball -> check: is the shooter of the snowball playing paintball ? -> get Team information of the shooter -> is shooter still "alive/in-game" ? (Already hit players can't hit other players) -> play some effects (depending on team), mark the player as hit, print some "playerA hit playerB"-message

    Now, I am thinking about differing between different snowball sources (to print different hit messages for example), like one time a player directly throws the snowball and an other time the snowball is spawned by some "grenade-egg".

    Ideas:
    - store the snowballs in different list and check inside that list later on hit, to see if it comes from a special source
    - or: using metadata, to tag the snowball as "paintball" already on creation with source (and maybe team(color)) information:

    Player (which is playing paintball) receives damage by a snowball -> check: is the snowball tagged with "paintball" ? -> Check: is the shooter playing paintball ? -> Check: is the shooter still "alive" in the game - > get get source and team-color information from metadata tags -> play some effects (depending on team), mark the player as hit, print some "playerA hit playerB by <source>"-message

    So, should I use metadata for this? There will be pretty many snowballs being tagged..
    How fast is it, to tag/receive metadata information ? Any suggestions on this ?
    Also, I thought about using FixedMetadata, but I saw a ticket saying FixedMetadata has some problems with performance etc.. https://bukkit.atlassian.net/browse...bucket-connector-plugin:dvcs-commits-tabpanel

    Opinions ?

    In regards, bla
     
  3. Offline

    Izbay

    I'm having difficulty gleaning any information about how to access the datatags on LivingEntities (for example, accessing catType on an Ozelot). Is it simply getMetadata(someOzelot, catType)? I'm mostly interested in how to get/set horse data once 1.6 is live and bukkit is updated. I know many of them are able to be changed with methods (Pig - setSaddle). Is it known if type/coloration/health/armor/chested/jump strentgh/speed methods will be provided?
     
  4. Offline

    Crast

    The Metadata API is for setting arbitrary metadata on many types of objects (blocks, entities, worlds, players) that is keyed on a string. These metadatas are meant for plugins to store data that other plugins can retrieve. Nothing in the core bukkit API will use any of those metadata for in-game values.

    Now, what you appear to be asking about with catType is a matter of methods on the sub-types. In order to get the methods on a specific type of entity you will need to upcast the entity to the appropriate type. For example, say you have an Entity named entity:

    Code:java
    1.  
    2. if (entity.getType() == EntityType.OCELOT) {
    3. Ocelot ocelot = (Ocelot) entity
    4. if (ocelot.getCatType() == Ocelot.Type.RED_CAT) {
    5. // do something
    6. }
    7. }
    8.  


    Similarly, you can add checks like this before upcasting to other specific type classes. If you try to upcast to Ocelot with an entity which isn't an Ocelot, you will get a ClassCastException.
    When 1.6 exists, and bukkit updates to 1.6, there will probably be a Horse class. What methods it contains depends on how much work someone is willing to do, and to some extent, the limitations of bukkit in how it can effect the operation of this.

    You can already update the health and armor on many living entities. Type/coloration varies, you can change ocelots between the available colors of cats, for example. Beyond that, it depends. Jump strength and speed are not really something that's easy to change, as it involves modifying the AI of the mob.
     
  5. Offline

    Codisimus

    Why don't more devs use this!
     
  6. Offline

    AstramG

    Does MetaData still clear on reloads?
     
  7. Offline

    DarkBladee12

    AstramG Well, I'm using metadata very often and noticed that it only sometimes clears on reload, not every time.
     
  8. Offline

    AstramG

    Randomly?
     
  9. Offline

    DarkBladee12

    AstramG I found that it'll reset every time you reload now, at some previous builds the metadata didn't reset after a reload ;)
     
  10. Offline

    ZeusAllMighty11 Retired Staff

    Why isn't metadata persistent? :\
     
    NathanWolf likes this.
  11. Offline

    MoonStorm

    There is almost no value in this API in the current state. I'm looking forward to using it when metadata gets persisted with the item. This is a half baked implementation.
     
  12. Offline

    Crast

    It is half baked, and I have been working along with the bukkit devs to change / clean it up. However, when keeping in mind API breakage and all the other associated issues therein, this is actually far more complex than one would be led to believe.

    In the process of cleaning up the Metadata system, I had to address several glaring issues including memory bloat/performance issues. In addition, I had to implement a weak-reference system to prevent classloader leakage, but unfortunately that has the side effect of causing metadata in most cases to be cleared on a reload.

    This is all leading up to a new feature I've been trying to get approved: Metadata Providers. The idea of metadata from the beginning was to faciliate inter-plugin data exchange, but the way it was done was actually quite limiting for a number of reasons. The discussion in that ticket got heated, and continued in another thread. At this point it's been at a stalemate, and no action has been taken since then.
     
  13. Offline

    ZachBora

    I thought plugins had to provide the metadata, like that they stored it and connected to objects whent they're enabled.
    That metadata was used for other plugins to easily access another plugins settings on objects.

    If metadata was persistent (or if it is) where is that data saved?
     
  14. Offline

    Minnymin3

    Now why does this not persist on server restart? D: It would be so awesome if it did... It would remove all need for player config files (ie. essentials)! You could store the player metadata in the player.dat
     
  15. Offline

    Codisimus

    I disagree, somethings you want to be editable by simply modifying the file.
     
  16. Offline

    Minnymin3

    But if you want to do that then just make a separate player file
     
  17. Offline

    GetGoodKid

    Can someone explain how to store and retrieve location metadata for a player?
    Example:
    A player selects a block. Block location stored into player's metadata. Block location retrieved from player's metadata and stored in Location variable.
    Storing it seems to be fine with:
    player.setMetadata("selected-block-loc", new FixedMetadataValue(RaceTournaments.getInstance(), selectedBlockLoc));
    But this line throws an error and says "FixedMetadataValue cannot be cast to Location".
    selectedBlockLoc = (Location) player.getMetadata("end-block").get(0);

    Side Question:
    How should I store a list of players that are in multiple different race queues? I think server metadata would be the best option but I'm not quite sure how.
     
  18. Offline

    ZachBora

    GetGoodKid Why are you placing it in "selected-block-loc" but retrieving "end-block" ?
     
  19. Offline

    GetGoodKid

    Oh my bad, I was trying to change variable names to make my code more readable. End-block is supposed to be "selected-block-loc".
    It seems I fixed the issue though, by using .get(0).value();
    What should I use in place of 0 index to make it specific to my plugin?
     
  20. Offline

    iKeirNez

    This looks really awesome! It's useful even for transferring data from place to place inside one plugin. IE removing the need for hashmaps and stuff. Will definitely implement this in my plugins. What would make this even better is if the data were persistent otherwise we have to store an entities UUID, save the metadata, then load it to the entities on startup.
     
  21. Offline

    AmShaegar

    GetGoodKid You would need to check the owning plugin for your plugin like my getMetadata() method. I am using this Util class whenever accessing metadata:
    Code:java
    1. import org.bukkit.block.Block;
    2. import org.bukkit.metadata.FixedMetadataValue;
    3. import org.bukkit.metadata.MetadataValue;
    4. import org.bukkit.metadata.Metadatable;
    5.  
    6. import de.wrenchbox.CaptureTheFlag.CaptureTheFlag;
    7.  
    8. public class Meta {
    9.  
    10. public static void setMetadata(Metadatable obj, String key, Object value) {
    11. obj.setMetadata(key,new FixedMetadataValue(CaptureTheFlag.getPlugin(), value));
    12. }
    13.  
    14. public static MetadataValue getMetadata(Metadatable obj, String key){
    15. for(MetadataValue value : obj.getMetadata(key)){
    16. if(value.getOwningPlugin().getDescription().getName().equals(CaptureTheFlag.getPlugin().getDescription().getName())){
    17. return value;
    18. }
    19. }
    20. return null;
    21. }
    22.  
    23. public static void removeMetadata(Metadatable obj, String key) {
    24. obj.removeMetadata(key, CaptureTheFlag.getPlugin());
    25. }
    26.  
    27. public static void protect(Block block) {
    28. setMetadata(block, "protected", true);
    29. }
    30.  
    31. public static void unprotect(Block block) {
    32. removeMetadata(block, "protected");
    33. }
    34.  
    35. public static boolean isProtected(Block block) {
    36. return getMetadata(block, "protected") == null ? false : getMetadata(block, "protected").asBoolean();
    37. }
    38.  
    39. }
     
  22. Offline

    Crast

    Really smart way to wrap metadata access :)

    By the way, JavaPlugin implements .equals() so
    Code:
    if (value.getOwningPlugin().getDescription().getName().equals(CaptureTheFlag.getPlugin().getDescription().getName())){
    can be changed to simply
    Code:
    if (value.getOwningPlugin().equals(CaptureTheFlag.getPlugin()))
    It's probably a minor performance gain, but worth pointing out.
     
  23. Offline

    AmShaegar

  24. Offline

    Pinaz9

    Will there be any future support for exporting metadata to a file?

    Actually, it would be nice to provide a new type of metadata, PersistantMetadata. It would still be pretty lazy, but it could be told to be stored in the relevant .dat or NBT
     
  25. Offline

    Sleaker

    You mention metadata being thread safe, but generally, there is little way to access objects that contain metadata in a thread safe manner, so what's the benefit of having 'thread safe metadata'
     
  26. Offline

    Crast

    The metadata API is thread safe because it was written that way, having "synchronized" on every method. While this may be thread-safe, it does cause locking on the -entire- store, so if the metadata was actually being used from many threads there would be a lot of waiting going on.

    The "synchronized all methods" way is really a very old-school way of looking at concurrency, and really doesn't scale. In the interest of removing all those extraneous full-store locks, I have a pull request out to deal with that, https://github.com/Bukkit/Bukkit/pull/878 . However, I don't have time these days to work on pull requests for Bukkit, so if someone else wants to take this one over, it'd be great
     
  27. Offline

    Sleaker

    Right, but the blockstore is not thread-safe, nor is the player list. So if you want to get data from a player/block you have to go through areas that need to be synchronized and have yet to be.
     
  28. Offline

    usevalue

    Been plugin-ing for a few weeks. Just discovered this. Thankyouthankyouthankyouthankyou.
     
Thread Status:
Not open for further replies.

Share This Page