Change spreaded block

Discussion in 'Plugin Development' started by xGhOsTkiLLeRx, Jan 7, 2012.

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

    xGhOsTkiLLeRx

    Hey there!

    Two questions:

    1.)

    I have a displayname like this
    xGhOsTkiLLeRx -> every char is colored other!

    Now I want to replace my displayname, but somehow the method doesn't work (no errors, just not changed!)

    Code:java
    1. String displayName = player.getDisplayName();
    2. String newName = ChatColor.RED + displayName;
    3. player.setDisplayName(displayName.replace(displayName, newName + ChatColor.WHITE));

    Simply not working. Don't know why. Tried already ChatColor.stripColor(displayName)

    And idea why? Because this method works, if the displayName got only ONE color

    End of the story: I use setDisplayName again without the replace part


    2.)

    I need to change a block.
    Say lava spreads 3 blocks down -> I want to set the 3rd block to something else.
    I dunno how I can get the third block below the source block and set it to something else.


    Hope you can answer my questions again (like always)

    Sincerely,

    xGhOsTkiLLeRx

    @Avous The best at the end? And the end is 2012, isn't it ;)
     
  2. 1)
    Your display name looks something like that (color codes are "§x", where x is a hexadecimal character):
    $7z§2z§az§2z§0z§cz§ez
    (replaced all actual text with 'z' chars, it would be "zzzzzzz" without color codes)

    Now when you just prefix that string with another color code (line 2 in your example), all you get is: {set color to RED} {set color to SOMETHING} z {set color to SOMETHING} z ...
    The first "SOMETHING" overrides your RED instantly as no text is displayed in between those.

    So ChatColor.stripColor() would be the correct method to use. If you say you already tried that, mind showing the exact code you tried it with?

    2)
    Can't really answer that, take BlockFromToEvent, dunno how to check which relative block is the actual source block, though (I never looked at what block metadata flowing liquid blocks had different compared to a real source block).
     
  3. Ehm, wth ?
    Code:
    player.setDisplayName(displayName.replace(displayName, newName + ChatColor.WHITE));
    Why are you using .replace() with itself ? Just use setDisplayName() and use strip colors if you want to get rid of existing colors and then add your colors.

    And the 2nd... you can get up or down stuff really easily, just getLocation() and add or subtract from it's Y value how many blocks above or below you want to go... then use world.getBlockAt(new location) and there you have it.

    For going sideways it's a bit more difficult, since X/Z values are global not relative, if you just need North/South/West/East they're easy to work with, like the example above... but if you need to go N blocks in your view direction it's kinda tricky, you'll need to getLocation() from player, getDirection() then normalize() and then multiply it by the amount of blocks to go and then add it to the player's getLocation().
     
  4. Oh, completely overlooked the replace part ...

    No! You are senselessly creating all those location objects when you don't need them - considering that that event is fired quite often when liquids flow. The best way would be to just do block.getRelative(0, -2, 0) or block.getRelative(BlockFace.UP, 2). You don't need to do all the hackish stuff with world.getBlockAt and most importantly, don't create locations for that!
    What player are you talking about? I can't remember there were players involved in flowing lava ;)
     
  5. I forgot about getRelative() :} but still, I belive it does the same thing :p Also, what's wrong with creating Location objects ? It's just a class that has variables with information, you're not creating anything in the game.

    And I was talking in general, in case he may need player-directional block setting some time in the future.
     
  6. Offline

    xGhOsTkiLLeRx

    I know my displayname look like this ;)
    So I'll try stipColor() again. Thx

    I want to use replace, because otherwise I'll overwrite some parts.
    (I doing it this way: config -> choose between whole displayname and the exactName (player name) -> To let the prefix or suffix (or other stuff) uneffected, I wanna replace the part - not set it again)

    ----

    Thx, will try it :)
     
  7. No, you are not creating anything game-related, correct.
    But you are doing two new heap allocations with 4 variables each time that is called. Big deal, 8 created variables, you say, but now imagine that being in a million-of-times-a-second-fired event like PLAYER_MOVE. You would be constantly creating new objects dozens of times a tick - that's andriod hell for the garbage collector. gerRelative() uses a similar method, just without the locations (because there really is no need for them here). world.getBlockAt(int x, int y, int z) is called here, with the methods block.getX(), block.getY() and block.getZ(). No unnecessary heap allocations here, it all works with primitives.
    displayName.replace(displayName, something) still doesn't make that much sense, though ;)
    You are replacing a string inside a string with something, but that string you are replacing is the actual string (displayName). If the name would be "aergaeadfA$WTZ4zue4hSA§$", you would be replacing "aergaeadfA$WTZ4zue4hSA§$" with something, which is essentially the same as just overriding it ;)
    So even if you do need replace, the first parameter of replace shouldn't be the same as the string you are calling it on.
     
  8. Offline

    bergerkiller

    @Bone008 Actually, getRelative also creates a new block object regardless. it all ends up in:
    Code:
        public Block getRelative(final int modX, final int modY, final int modZ) {
            return getWorld().getBlockAt(getX() + modX, getY() + modY, getZ() + modZ);
        }
    So no, Blocks are ALWAYS unique, whatever you try, it won't change the internal data of a block. This is because Blocks are kept in a (long)hashmap, which ensures that every block object is always unique for certain coordinates. This makes it possible to use == when comparing blocks (although this always fails when I do so)

    In short: in the end it would be best to just store the x/y/z and perform a final getBlockAt, if performance is an issue. But there is no difference between world.getBlockAt and block.getRelative.

    EDIT

    Nvm, but yeah, evade using Locations unless you need double-precision :)
     
  9. @bergerkiller
    I left out the block that is returned from my calculations, as you get it for every method you are using and it doesn't matter for what I was trying to point out.

    And I thought too that CraftBlock instances were cached so they are unique, but they apparently are not. That's insane! But I guess flaws like that are the price for an easy OOP structure ...
     
  10. Offline

    xpansive

    Yes, block access is very slow currently, as I've learned the hard way. I'm about to release a library called DirectWorld that allows faster (about 30x in my tests) block access and lets you decide if you want to do things like physics or lighting updates. Stay tuned :)
     
  11. Offline

    xGhOsTkiLLeRx

    Hey again,
    I got a strange error!

    This code does work, the third block is unlimited:
    Code:java
    1. public void onBlockFromTo(BlockFromToEvent event)
    2. {
    3. Block sourceBlock = event.getBlock();
    4. Block targetBlock = event.getToBlock();
    5.  
    6. if (plugin.config.getBoolean("fall.lava")) {
    7. plugin.getServer().broadcastMessage("Source: " + sourceBlock + " byte: " + Byte.toString(sourceBlock.getData()));
    8. plugin.getServer().broadcastMessage("Target: " + targetBlock + "byte: " + Byte.toString(targetBlock.getData()));
    9. if (((sourceBlock.getType() == Material.LAVA) || (sourceBlock.getType() == Material.STATIONARY_LAVA)) &&
    10. (sourceBlock.getRelative(BlockFace.DOWN, 1).getType() == Material.LAVA) && (sourceBlock.getRelative(BlockFace.DOWN, 2).getType() == Material.LAVA)) {
    11. Block output = sourceBlock.getRelative(BlockFace.DOWN, 3);
    12. output.setType(Material.STATIONARY_LAVA);
    13. }
    14. }


    But this code causes this error: at the sky appear random lava blocks spreading down!
    Code:java
    1. public void onBlockFromTo(BlockFromToEvent event) {
    2. Block sourceBlock = event.getBlock();
    3. Block targetBlock = event.getToBlock();
    4.  
    5. if (plugin.config.getBoolean("fall.lava") == true) {
    6. if (sourceBlock.getType() == Material.LAVA || sourceBlock.getType() == Material.STATIONARY_LAVA) {
    7. int i = 1;
    8. while (sourceBlock.getRelative(BlockFace.DOWN, i).getType() == Material.LAVA) {
    9. i++;
    10. }
    11. sourceBlock.getRelative(BlockFace.DOWN, i).setType(Material.LAVA);
    12. }
    13. }
    I just want to get where the block hits the ground (not longer air)

    This is what happens in the worlds with the code. My guess is something with lava flowing into the void an spreading again at the sky!?
    [​IMG]

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 23, 2016
  12. Offline

    xGhOsTkiLLeRx

  13. No idea, actually. Maybe world.getBlockAt(x, -1, z) returns the top-most block (127)? You could try it with a test command. If it is like that, you have to check if it's already the bottom layer before going down.

    Oh, and keep calls to getRelative as rare as possible - each call creates a new CraftBlock as mentioned in post #9.
    So in your second example, instead of storing i as an index, I would do that:
    Code:
    Block currentBlock = sourceBlock.getRelative(BlockFace.DOWN);
    while(currentBlock.getType() == Material.LAVA){
        currentBlock = currentBlock.getRelative(BlockFace.DOWN);
    }
    currentBlock.setType(Material.LAVA);
    You don't really save that much, but you don't have to call it again in the line with setType. And it might be more useful when doing the above mentioned check.
     
  14. Offline

    xGhOsTkiLLeRx

    @Bone008
    Code:java
    1. if (plugin.config.getBoolean("fall.lava") == true) {
    2. if (sourceBlock.getY() > 60) {
    3. Block currentBlock = sourceBlock.getRelative(BlockFace.DOWN);
    4. while(currentBlock.getType() == Material.LAVA && currentBlock.getY() > 60){
    5. currentBlock = currentBlock.getRelative(BlockFace.DOWN);
    6. }
    7. currentBlock.setType(Material.LAVA);
    8. }
    9. }
    This will prevent the random lava blocks at the sky (and leaves naturally field unaffected -> hight will be configurable)
    But this strange effect appears, too:

    Lava spreads, down -> air gets lava, but any other block, too!
    (even with my more resource intensive code and the height check)

    Any idea why?
     
  15. Offline

    xGhOsTkiLLeRx

    bump. I need this fixed :(
     
    1. if (plugin.config.getBoolean("fall.lava") == true) {
    2. if (sourceBlock.getY() > 60) {
    3. Block currentBlock = sourceBlock.getRelative(BlockFace.DOWN);
    4. while(currentBlock.getType() == Material.LAVA && currentBlock.getY() > 60){
    5. currentBlock = currentBlock.getRelative(BlockFace.DOWN);
    6. }
    7. if(currentBlock.getType() != Material.AIR) return;
    8. currentBlock.setType(Material.LAVA);
    9. }
    10. }
    I know I messed up it realy, but mayby it works
    I dont like the WYSIWYG editor
     
    xGhOsTkiLLeRx likes this.
  16. Offline

    xGhOsTkiLLeRx

    Works. Thank you man!
    But somehow this works only one time. The block is "pick-able" with a bucket, but not a second time.

    Already tried to add
    currentBlock.setData((byte) 0x0);
    (http://www.minecraftwiki.net/wiki/Data_values#Water_and_Lava )
     
  17. You tried it like this:
    Code:
    if (plugin.config.getBoolean("fall.lava") == true) {
      if(sourceBlock.getY()>60){
        Block currentBlock = sourceBlock.getRelative(BlockFace.DOWN);
        while(currentBlock.getType()== Material.LAVA&& currentBlock.getY()>60){
        currentBlock = currentBlock.getRelative(BlockFace.DOWN);
      }
      if(currentBlock.getType() != Material.AIR){ return}; // dont replace the block if it isn't air
      currentBlock.setTypeIdAndData(Material.LAVA.getId(), (byte) 0x0 ,true)
    }
    
    also, must it be every time be pickubable? not only when the lava is flowing from the top on it?
     
  18. Offline

    xGhOsTkiLLeRx

    Yep. tried it like this -> works on time.

    Lava flows from top -> Gets lava (pick-able) -> Gets picked up with a bucket -> Gets lava (pick-able again)
    But the second "gets lava" is un-pick-able lava.
     
  19. mayby make it go up 1 block, before setting it to lava, its actually trying to set the block under the blocks thats its flowing to to lava.
     
  20. Offline

    xGhOsTkiLLeRx

    No, bad idea, will spread around like horror ;)
     
  21. You trying to do:
    Lava Source
    Lava fall << this triggered the event
    Air << affected block

    Tell me if I am wrong
     
  22. Offline

    xGhOsTkiLLeRx

    ferrybig
    Well my goal is more like this:

    I place a lava block -> spreading/flowing down because there is air -> stops at a non air block (vanilla until this point - but checked with my method to get the relatives) -> sets the last lava block to a full lava block -> I pick it up -> gets to a full lava block again.
     
  23. Offline

    xGhOsTkiLLeRx

    a little friendly bump again :)
    Still no solution...
     
  24. if the affected block is under the block that started the floqing, set the affected block to an full lava block?
     
  25. Offline

    xGhOsTkiLLeRx

    Bump.
    I still have no solution.
    The code snippet above works only one time.
    Hope anyone can help.
     
  26. Offline

    xGhOsTkiLLeRx

    Basically yes. But it will spread (not vanilla like) to the sides. Even with setData to 0.
    With the stationary lava it won't spread down anymore.
    For the editor use (without the dot):

    [.syntax=java]Code[/syntax]
     
  27. Why would it spread to the sides then?
     
  28. Offline

    Njol

    because you should set the data to 8, not 0. 0 means it's lava on the floor, while 8 means it's falling lava which is the only one which does not spread.
     
Thread Status:
Not open for further replies.

Share This Page