Change block name

Discussion in 'Plugin Development' started by Stuperfied, Oct 12, 2014.

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

    Stuperfied

    Hi. Ive made a plugin that will change the type of a clicked block through getclickedblock but I cant find how to change the name of the block.

    This code is way off, im in the middle of editing it but here is what I have at the moment.
    Code:
                        int subBlock = 1;
                        plugin.myDisplayName = "whatever";
                        plugin.lores.add("block description");
                        plugin.location = event.getClickedBlock().getLocation();
                        player.getWorld().strikeLightning(player.getTargetBlock(null, 200).getLocation());
                        event.getClickedBlock().setTypeId(subBlock);
                        ItemStack block = new ItemStack(1, 1);
                        block.getItemMeta().setDisplayName(plugin.myDisplayName);
                        player.sendMessage(ChatColor.YELLOW + "/ld help:" + ChatColor.WHITE + plugin.location);
                        event.getClickedBlock().setTypeIdAndData(block, block, block);
    Would like to change the meta description "lore" of the item also if possible
     
  2. Offline

    Code0

    I'm not fully sure what you're trying to accomplish, but just to let you know, you can't change the name of a placed (block) item. You can however set names by using
    Code:java
    1. itemStack.setDisplayName(String name);
    Stuperfied
     
  3. Offline

    Stuperfied

    The method setDisplayName(String) is undefined for the type ItemStack

    I should clarify.
    Player right clicks block
    Block changes to dirt with the name "whatever" and the lore "whatever"
    Player breaks that block, plugin can detect by reading the type, name and lore of broken block. To make sure is not just any old dirt block.

    Can you change the name and lore of a block in an item stack and then set the clicked block to be that one?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 14, 2016
  4. Offline

    Watto

    Stuperfied

    I don't think that would work, you would probably have to apply metadata to the block and then retrieve it and apply it to the dropped ItemStack
     
  5. Offline

    CaptainUniverse

    You would have to destroy the block, get its item type, do the meta stuff, then place it again
     
  6. Offline

    Stuperfied

    Can anyone provide examples because im having difficulties with itemstack type and getclickedblock.settypeid Dont care how, just need to tell if its the special block they clicked on.
     
  7. Offline

    xMrPoi

    The way I would go about doing this is: When you click the block, change the block type to dirt. Save the name and lore with the location of the block. Listen for a blockbreakevent. If the location of the block broken matches that of the location you previously saved, set the block to air and cancel drops from it. Make a new itemstack with the custom name and lore. Drop that item at the location the block was broken.
     
  8. Offline

    Stuperfied

    Doing that would mean having to save the location of every block created, however, if I can just change something in the meta of the block or its name I can read that on block break to see if it was one of the blocks.

    Can anyone post an example code please?

    As I am having trouble with type cast.
     
  9. Offline

    FabeGabeMC

    Code0
    Do you mean itemStack.getItemMeta().setDisplayName(String name);? :p
     
  10. Offline

    xMrPoi

    A block isn't an itemstack when you place it though; it's a block. As far as I know, there's no way to save data in a block using the block object. If there's a way to do it other than mine, someone please tell me. I'd actually want to know :D
     
    Code0 likes this.
  11. Offline

    ChipDev

    Code:java
    1. ItemStack is = new ItemStack(Material.CAKE);
    2. ItemMeta isim = is.getItemMeta();
    3. isim.setDisplayName(ChatColor.RED + "YO");
    4. is.setItemMeta(isim);
     
  12. Offline

    fireblast709

    Stuperfied blocks don't have names. Like Watto mentioned earlier, you can attach metadata to a block
    Code:java
    1. block.setMetadata("future-name", new FixedMetadataValue(pluginInstance, ChatColor.RED+"The name"));
    and fetch it when it's broken
    Code:java
    1. for(MetadataValue value : block.getMetadata("future-name"))
    2. {
    3. if(value.getOwningPlugin() == pluginInstance)
    4. {
    5. String name = value.asString();
    6. // Do something with the name;
    7. break;
    8. }
    9. }
    xMrPoi The above is a built-in system of attaching data to blocks and entities (including Players).

    Then just apply the name to the drop. Get the ItemMeta of the ItemStack, set the displayname of the ItemMeta, and set the ItemMeta of the ItemStack. (you might have to drop it manually. If that's the case, cancel the event, set the block to AIR, create an ItemStack and drop it after applying the ItemMeta).

    For more information about Metadata, I suggest you read the plugin tutorial on the Bukkit wiki (they have a section about it, and you will find that most code in this post is much like the code on there). Moreover, the javadocs might be useful to find more about the classes, interfaces and methods provided by the org.bukkit.metadata package.
     
  13. Offline

    xMrPoi

    Is that method a lot more efficient than the way I had suggested?
     
  14. Offline

    fireblast709

    xMrPoi Strictly efficiency, probably equally fast. Metadata has a few advantages though:
    • It can be accessed from anywhere
    • Locations could potentially create memory leaks since they hold a reference to a World object. Metadata, however, does not.
    • Metadata would survive reloads (not restarts)
     
  15. Offline

    xMrPoi

    Cool thanks. I'll try that out sometime
     
  16. Offline

    97WaterPolo

    fireblast709
    Is there a way to clear all metadata? I haven't looked at the javadocs, they don't load well on my phone.
     
  17. Offline

    fireblast709

    97WaterPolo nope. However, you could easily track this (in fact, you could even use metadata for this) and delete them manually.
     
  18. Offline

    Plo124

    Stuperfied
    There is no way to store the item that the block was when it was placed.
    There is no bukkit method to store data with the block

    I would store the location in a SQL Database along with its type
     
  19. Offline

    fireblast709

    Metadata?
    Why would you even use SQL in this case? Just stick with YAML/JSON if you need persistence.
     
  20. Offline

    Plo124

    fireblast709
    metadata does not store through restarts,
    and YAML/JSON uses lots of disk power for searching files.

    Face it, MySQL has better indexing
     
  21. Offline

    fireblast709

    Plo124 Face it, MySQL comes with latency. Moreover, once you load the file in a HashMap, you pretty much get O(1) lookups (which you cannot replicate with MySQL unless you do the same, while files most likely load faster).
     
  22. Offline

    Plo124

    fireblast709
    What latency is there on the local area network? You could search 100000 different entries .yml file in maybe 1/2 of a second, but the same in MySQL if configured correctly can take 1/32 of a second, and in total about 1/8 of a second to send it all.
     
  23. Offline

    fireblast709

    Plo124 I generated a million random entries, looped over the keys and fetched their values (and as everyone should know, this is unoptimized: I could optimize it more by looping over entries instead).

    Amortized running time: 30155222 nanoseconds, in other words: 30 milliseconds.

    I'll be benchmarking your MySQL approach next, but I honestly don't expect better results...

    [EDIT] MySQL benchmarked, on a localhost connection (before you blame that)

    Amortized running time: 84253341 nanoseconds, in other words 84 milliseconds. The database is pretty much stock WAMP, had about 48779 entries (which is 20 times less than the HashMap had)

    Conclusion: HashMap > ResultSet.

    [EDIT #2] SQLite benchmarked

    Amortized running time: 28758590 nanoseconds, in other words 29 milliseconds. This database contained 10000 entries, randomised like the HashMap implementation. So in order for SQLite to be faster, our data set has to be 100 times smaller...

    HashMaps are still faster.

    Note: YamlConfigurations are backed by a (Linked)HashMap, so i thought a HashMap should be a valid replacement in the tests. They seem to be about 3.5 times slower than the pure HashMap implementation, but that is still fast enough to beat MySQL.

    [EDIT #3] File per block benchmarked

    Running time if a million blocks were broken, and all their files existed: 10605905744.
    Note that this means that if the block is broken, the File is checked for existance (which we know it does in this test). Then it is loaded into memory with a YamlConfiguration object, and we get a single property, the name in this case. Then we allow the GC to reclaim that memory by letting the YamlConfiguration fall out of scope. This keeps no data in memory, and is till faster than MySQL (since it takes about 80% of the time with 20 times less fetches)

    Also, as later stated, single queries will absolutely kill your performance. Take YamlConfiguration as your overlord while you can.
     
  24. Offline

    Watto

    fireblast709 Plo124

    The use of the MySQL does seem pretty pointless for something like this.
    Also to note since no one brought it up, you can use SQLite which doesn't even require a mysql server.
     
  25. Offline

    Plo124

    Watto fireblast709
    He obviously wants this to be held upon a restart, so you can store it in a MySQL database and read it quicker, as opposed to a flat-file.

    I do see the possible confusion here, but do you really need to store each block in RAM?
    This is especially important since you will exceed the maximum HashMap length if enough blocks are modified.

    I wasnt saying that MySQL > HashMap, I was saying MySQL > FlatFile because of the indexing features.

    In conclusion:
    The OP should need to store the block data between restarts, and I recommend using MySQL as it is better for having a large amount of small rows, i.e. 3 integers and a string
     
  26. Offline

    fireblast709

    Plo124 Have you even read my benchmarks... MySQL is a lot slower than YamlConfiguration, especially if we load the blocks in a regular HashMap onEnable.

    I don't think you actually know what you are talking about. If you not load it in the RAM, you will have to query your database every block break. Since you want to be able to modify your event, you will not be able to use (async) tasks. This means that you would have to query your database on the main thread, which will most certainly cause some nice TPS drop, even on localhost (once more, see my benchmark results).

    Provide me with some actual runtime, instead of giving the OP some false advice.
     
    mythbusterma likes this.
  27. Offline

    Deleted user

    +1 to fireblast
    Integer.MIN_VALUE to plo.

    I don't think you've used SQL enough if you think querying will be faster than memory lookups.
     
  28. Offline

    DevRosemberg

    NO NO NO. You should use Cloud to be able to load your blocks on all devices.
     
  29. Offline

    Plo124

    fireblast709
    I guess you could say YAML loads the whole file into ram, defeating the purpose of saving ram.
    MySQL can query much faster than a HashMap, even when the SQL isnt loaded in memory, but the biggest letdown is network latency.

    Advantages of MySQL ->
    Can be on another server, to save disk speed
    Support for multiple servers.
    Instantly saved, great incase the server crashes
    Is made to support tens of thousands of entries

    Disadvantes of MySQL ->
    Latency can be an issue, especially if running on the main thread

    Advantages of YAML ->
    On same machine, latency is not an issue

    Disadvantage of YAML ->
    YAML is meant for configurating things, note how bukkit has lots of .yml files for configuration
    YAML will use up lots of disk cycles if you arent loading it all in RAM. This will bring down the performance of your server
    If you do load it in RAM, it uses additional RAM which can limit the amount of ram you can save
    You need to save it often otherwise a servercrash will roll back a lot.

    Advantages of a HashMap ->
    Can query very fast since the data is already on RAM

    Disadvantages of a HashMap ->
    You need to save and load the hashmap on Enable and Disable
    This means you could potentially lose a heap of data if the server crashes and you dont save it enough, which defeats the purpose of saving to ram if your only going to write to a file.
    Uses ram.
     
  30. Offline

    fireblast709

    In fact you could split them up in a lot of tiny files, allowing you to selectively load data.
    I've proven this to be wrong in my benchmarks (they were run on an already fetched ResultSet)
    As for the multiple server support, I don't think that would be included in the OPs use case (since it is about a specific block in a specific world in a specific server). The instantly saved doesn't make much sense since you need to save both continuously, and neither are instant (in fact, SQL will need to push the data over a socket. Moreover, to support fast YAML saving, a file-per-block will enhance this greatly)
    The main reason why you should not run SQL on the main thread.
    YAML is not just meant for configurations. YAML is a superset of JSON, which in turn is used in NoSQL databases like MongoDB (which most certainly is meant for persistent storage). And once more I would like to mention the file-per-block system. Even loading the file on demand it is faster than MySQL, and will minimize the RAM being used. Moreover, it can be used to quickly store some data, minimizing data loss on crashes.
    While simply relying on HashMaps might result to severe loss of data, you could use it as a cache for "YAML on demand" to create a latency free, 'instant' save, fast storage by caching already read files. Yes, it comes with an additional RAM cost, but that's what you should expect from a cache (in fact, you will find that a lot of people cache their SQL data in order to avoid the need to SELECT it twice)
     
Thread Status:
Not open for further replies.

Share This Page