Raising Sea Level In A Specific Region

Discussion in 'Plugin Development' started by dNiym, May 27, 2014.

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

    dNiym

    I have a region I would like to flood and drain over time.

    I am currently going about this just as a /water <raise/lower> command until I get it working.

    I can find a region by name, find its minimum and maximum vectors, convert those to xyz coords, pass these to a selection, but have been running into a wall on how to go about replacing them.

    My first thought was to just pass the selection to the worldedit replace function but if there's a sleeker way of doing this I am open to suggestions.

    Current Code:
    Code:java
    1. public void execute(CommandSender sender, String[] args) throws CommandException {
    2.  
    3. if (!sender.hasPermission("RisePVP.WaterLevel"))
    4. sender.sendMessage(Msgs.Error_Misc_No_Permission.getString());
    5.  
    6. if (args.length != 1)
    7. {
    8. if (args[1].equalsIgnoreCase("Raise"))
    9. {
    10.  
    11. Player p = (Player) sender;
    12. World world = p.getWorld(); //Need to be able to get this WITHOUT a sender or player.
    13. RegionManager rm = WGBukkit.getRegionManager(p.getWorld());
    14. sender.sendMessage("Raising Water Level +1"); //All sender.sendMessage's are debug code
    15.  
    16. ProtectedRegion region = rm.getRegion("rise_arena");
    17. BlockVector ptmin = region.getMinimumPoint();
    18. BlockVector ptmax = region.getMaximumPoint();
    19. int ptminX = ptmin.getBlockX(); //Find The First Point
    20. int ptminY = ptmin.getBlockY();
    21. int ptminZ = ptmin.getBlockZ();
    22.  
    23. int ptmaxX = ptmax.getBlockX(); //Find the other point of the region
    24. int ptmaxY = ptmax.getBlockY(); // Y is the height of the thing for some silly reason
    25. int ptmaxZ = ptmax.getBlockZ();
    26. int ptnewminX = 0;
    27. int ptnewmaxX = 0;
    28. int ptnewminZ = 0;
    29. int ptnewmaxZ = 0;
    30.  
    31. if(ptminX < ptmaxX) //Step the selection in 1 block (to not take out our wall)
    32. {
    33. ptnewminX = ptminX + 1; //Step the min X coord up by 1
    34. ptnewmaxX = ptmaxX - 1; // Step the max X coord down by 1
    35. }
    36. if(ptminZ < ptmaxZ) //Step the selection in 1 block (to not take out our wall)
    37. {
    38. ptnewminZ = ptminZ + 1; //Step the min Z coord up by 1
    39. ptnewmaxZ = ptmaxZ - 1; // Step the max Z coord down by 1
    40. }
    41. sender.sendMessage("Found Region: New min vector -"+ ptnewminX + "X " + ptminY + "Y " + ptnewminZ + "Z");
    42. sender.sendMessage("Found Region: New Max Vector -"+ ptnewmaxX + "X " + ptmaxY + "Y " + ptnewmaxZ + "Z");
    43. if (ptmaxY > ptminY)
    44. {
    45. sender.sendMessage("Max Y is Greater than Min Y so Min Y is lowest point.");
    46. RegionFunction rf; //still haven't figured out what to do with this
    47.  
    48. Block faceOrigin = world.getBlockAt(ptnewminX, ptminY+1, ptnewminZ);
    49.  
    50. boolean foundAir = false;
    51. while(!foundAir)
    52. {
    53. faceOrigin = world.getBlockAt(ptnewminX, ptminY+1, ptnewminZ);
    54.  
    55.  
    56. if ((faceOrigin.getType() == Material.WATER || faceOrigin.getType() == Material.STATIONARY_WATER)) //this should just increment for any block except air (NOT JUST WATER)
    57. {
    58. sender.sendMessage("Target block IS a water block! increment Y");
    59. ptminY = ptminY + 1;
    60. } else if(faceOrigin.getType() == Material.AIR)
    61. {
    62. sender.sendMessage("Found air block at Ypos:" + ptminY);
    63. foundAir = true;
    64. }
    65. //Add a check to make sure Y cant go over 255
    66. }
    67. org.bukkit.Location l = faceOrigin.getLocation();
    68. p.teleport(l); //teleport me to the location (more debug code)
    69. //We should have valid new coordinates need to replace in the region i suppose.
    70. Vector pos1 = new Vector(ptnewminX, ptminY, ptnewminZ);
    71. Vector pos2 = new Vector(ptnewmaxX, ptminY, ptnewmaxZ);
    72. final CuboidRegionSelector selector;
    73.  
    74. selector = new CuboidRegionSelector();
    75.  
    76. selector.selectPrimary(pos1);
    77. selector.selectSecondary(pos2);
    78. int area = selector.getArea();
    79.  
    80. sender.sendMessage("Area of selected area is: "+area);
    81. // session.setRegionSelector(world, selector);
    82.  
    83.  
    84.  
    85. } else {
    86. sender.sendMessage("Min Y is Greater than Max Y so Max Y is lowest point.");
    87. }
    88.  
    89.  
    90.  
    91. }
    92. else if (args[1].equalsIgnoreCase("Lower"))
    93. {
    94. sender.sendMessage("Lowering Water Level -1");
    95.  
    96. }
    97. else
    98. sender.sendMessage("Syntax: /WaterLevel <raise/lower>");
    99.  
    100. }
    101. else
    102. sender.sendMessage("Syntax: /WaterLevel <raise/lower>");
    103.  
    104. }



    Any ideas on where to go from here?
     
  2. Offline

    Garris0n

    Well, can't you just...loop through the blocks and set them?

    Also, don't cast the sender to a player before actually checking if the sender is a player.
     
  3. Offline

    dNiym

    Thanks for the reply,


    Yes, that is probably an option I suppose what I need to know is is there a way to get a block list (like via the min and max points or coords) like I did with the area.

    I feel like if I had a way to iterate through a dynamic block list this would be pretty simple however I haven't figured out how to get a list of blocks from two sets of coords or vectors

    As for casting the sender to player this won't actually be a player command when it's all said and done so I will need to get the player out of there anyways. It's only there to get the world because I haven't figured out how to get that from the sender yet.
     
  4. Offline

    Garris0n

    dNiym likes this.
  5. Offline

    dNiym

    Okay, Sometimes it seems like it just takes someone to say it to figure out how to go about it. What I ended up doing was looping through the Z blocks, changing the air to water then moving up on the X axis +1 and doing it again until I had covered the entire region.. This seems to happen quite fast on my test server but i'm wondering if I can slow down the effect.. Ideally I would like to create a 2 block high wave above the level that would wash over things / knock players back if it hits them. All efforts to *draw* this wave above the new sea level height happen too fast to actually see the wave passing by.

    I've even tried leaving the blocks there until the wave is about 4 blocks deep then erasing them for more of an effect but it still happens too quickly. I assume the route I need to take to do this is a bukkit runnable. I suppose now the question is how to make the bukkit runnable run through my code of drawing the wave, then moving the wave and have it remember where it is.... Then come back some arbitrary amount of ticks and erase the old wave, draw the next block of stationary water and draw a new wave...

    My current code is like this:

    Code:java
    1.  
    2. //Loop through the X and Z coords and change the blocks...
    3. Block b = null;
    4. int oldx = ptnewminX;
    5. for (int x = ptnewminX;x < ptnewmaxX;x++) //Loop through the X coords
    6. {
    7. for(int z = ptnewminZ; z < ptnewmaxZ; z++) //Loop through the Z coords and change the air to water
    8. {
    9. b= world.getBlockAt(x,ptminY,z); //we do all the Z coords then increment the X and do it again.
    10. if(b.getType() == Material.AIR )
    11. b.setType(Material.STATIONARY_WATER); // This one will stay behind (new sea level)
    12.  
    13. //Create the wave above / in front of the new sea level
    14. b=world.getBlockAt(x,ptminY+1,z+1); //Create a block of water above the current block
    15. if(b.getType() == Material.AIR )
    16. b.setType(Material.STATIONARY_WATER);
    17. b=world.getBlockAt(x,ptminY+2,z+2); //Create a second block of water above the current block
    18. if(b.getType() == Material.AIR )
    19. b.setType(Material.STATIONARY_WATER);
    20.  
    21. }
    22. //Erase old secondary blocks before moving the wave.
    23.  
    24. for (int z = ptnewminZ; z < ptnewmaxZ; z++)
    25. {
    26. b = world.getBlockAt(x,ptminY+1,z);
    27. if(b.getType() == Material.WATER|| b.getType() == Material.STATIONARY_WATER )
    28. b.setType(Material.AIR);
    29. b = world.getBlockAt(x,ptminY+2,z);
    30. if(b.getType() == Material.WATER || b.getType() == Material.STATIONARY_WATER )
    31. b.setType(Material.AIR);
    32.  
    33. }
    34.  
    35. }
    36. }
    37.  
    38. }



    Could I put this function to sleep for X ticks? Like after each time the Wave is drawn have it sleep for 20 ticks before erasing and drawing the new wave? I don't want to make it sleep for 20 ticks inside the main plugin as to not shut everything down until the loops complete.

    Or would it be better to write the X/Y/Z position's somewhere and put this inside a bukkit runnable that would read the position and pick up where the function left off?
     
Thread Status:
Not open for further replies.

Share This Page