Checking if ore is natural

Discussion in 'Spigot Plugin Development' started by RiotShielder, May 28, 2016.

  1. RiotShielder

    Supporter

    Hey all, I'm working on a plugin similar to mcMMO, in that players can gain experience by breaking blocks. I'd like for ores to give more experience than common blocks such as stone, however I've ran into an issue.

    How do I check if an ore is natural, and not user placed? This is to prevent players from mining iron, gold, etc. and then replacing it, and breaking it again to gain more experience.

    I know that vanilla Minecraft only drops EXP orbs when a natural ore is broken, and won't drop and orbs when a user-placed block is broken; is there any way to hook into that? Or is there any other alternative than tracking every player's block place/break events?

    Thanks.
     
  2. You might have to resort to tracking block place/break events.

    However, instead of storing every placed block's location forever, you could just store them in memory (hashmap or something) and when the block is broken, check if it's in the map and remove it from the map.
     
    • Agree Agree x 3
    • Winner Winner x 1
  3. I agree with @mrkirby153, but you shouldnt try to save it through restarts, I think mcMMO doesnt do that also. It would probably start to lag, especially if you run it in bukkits main thread.
     
  4. As they said, just store it in a HashMap, or ArrayList<Block>(when they placed an ore). Then if the player brakes the block and there is data of this block in the ArrayList cancle the reward to get or whatever.
     
  5. oh god no.

    This will cause a large amount of lag when you get into the thousands, which happens pretty fast.

    When a player places a block, set a metadata value on the block letting you know that it's placed, which you can check later.
     
    • Agree Agree x 6
    • Informative Informative x 1
  6. Instead of using ArrayLists of blocks you can use metadata, you can set an metadata value like "isPlaced": true on player places the block and you can check when he breaks

    https://hub.spigotmc.org/javadocs/spigot/org/bukkit/metadata/Metadatable.html

    Sorry for my english...
     
    • Agree Agree x 2
  7. I used this myself once, but is this good for performance?
     
  8. Metadata will work fine... as long as you never restart the server. When you restart, it will all be reset. I hear that NBTs might be a better solution in your case, although I haven't had a chance to work with them myself.
     
    • Agree Agree x 1
  9. one word: Metadata
     
  10. RiotShielder

    Supporter

    How does vanilla Minecraft track it though? It has to know somehow, as EXP orbs only drop on naturally generated ores
     
  11. If EXP orbs truly only drop from natural ores (I'm not 100% sure myself), then you could listen for when EXP orbs spawn from breaking ores.
     
  12. They don't track anything. Ores placed will always give you experience. The only time you can get xp from ores is breaking it with a non silk touch pickaxe.
     
    • Like Like x 1
    • Agree Agree x 1
  13. If a player places a block, give it metadata. Then if the player tries to mine a block that has that specific metadata, return.

    Remember: Metadata does NOT save through restarts.
     
    • Agree Agree x 1
  14. Metadata is at least 6.5 horribads worse than a list, just saying. Just hook in to whatever minecraft uses to determine exp drops, or even simply use the exp event?
     
    • Funny Funny x 1
  15. Minecraft drops exp for every ore that drops a item(diamond, coal, lapis, whatever) it doesn't know the difference(doesn't care) whether it was placed by a user or naturally generated. It does not track this in anyway.

    @FlyingLlama How would storing metadata on a block and checking for the metadata when its broke be worse than iterating through a list of blocks(potentially thousands of blocks) ?
     
    • Agree Agree x 1
  16. Ever looked at how metadata works internally? Also, it tends to leak memory in impressive fashion.
     
  17. I've not looked at the implementation in depth though I probably will now :p As far as leaking memory goes removing the metadata from the block when it is broke should fix that.
     
  18. If java had destructors like C++, that would work.. As it is, that would be an almighty disaster waiting to happen. There are a lot of ways a block can cease existing (chunk unload, world unload, broken, replaced, changed by a plugin). You would to drop that potential for disaster on the average pointer-allergic java newbie?
     
  19. This is a very good point and didn't even consider the possibility of a block being removed via a plugin, etc.

    EDIT: Still though the alternative of using a list is not a great solution either. Imagine if he had a million blocks. Calling List#contains() for every block broken sucks too.
     
  20. A better alternative is just removing or restricting silk touch (make it not work on ores, with the getdroppedblock thingy in BlockBreakEvent), since all it really does is promote exploitation.
     
    • Agree Agree x 1