Chest refill every X minutes within area

Discussion in 'Plugin Development' started by KarimAKL, May 23, 2018.

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

    KarimAKL

    @Sploon And then what do i do? :7
    I have this for the state now.
    Code:Java
    1.  
    2. BlockState state = chests.getBlock().getState();
    3.  
     
  2. Offline

    Sploon

    A chest if a type of block state. So if you know that the block at "chests" is a chest, you can cast the block state to the chest.
    If you've ever used bukkit commands, you should be familiar with this:
    Code:
    Player player = (Player) sender;
    In this example, sender is already player; you cast the sender (CommandSender) object to the Player type; sender was already a player, but now you can access it as one.
    Likewise, if you are sure that this block state is a chest (and not some other state, like a sign) you can cast it to a chest. The chest has methods that allow you to access it's inventory.
     
  3. Offline

    KarimAKL

    @Sploon I already have this:
    Code:Java
    1.  
    2. if (state instanceof Chest) {
    3. }
    4.  

    EDIT: Now i just need to fill the chest up with random stuff(from a list of items i'll make)
     
  4. Offline

    Sploon

    Then you can cast the state to a Chest. The chest allows you to modify the inventory.
     
  5. Offline

    KarimAKL

    @Sploon How? :p EDIT: Like this?:
    Code:Java
    1.  
    2. Chest chest = (Chest) state.getBlock();
    3.  
     
  6. Offline

    Sploon

    Yes. Then you can modify the inventory from the chest object.
     
  7. Offline

    KarimAKL

    @Sploon Okay, thank you. :) I'll try looking up how to modify a chest now. :)
     
  8. Offline

    Sploon

    Code:
    chest.getBlockInventory()
    Returns the inventory. From there, it's the same as modifying any inventory.
     
  9. Offline

    KarimAKL

    @Sploon I have this error:
    Code:
    java.lang.ClassCastException: org.bukkit.craftbukkit.v1_8_R3.block.CraftBlock cannot be cast to org.bukkit.block.Chest
    
    When i use this:
    Code:Java
    1.  
    2. Chest chest = (Chest) state.getBlock();
    3.  

    What am i doing wrong? I can't test it when it comes with this error. :7
    EDIT: Fixed by removing ".getBlock()"
    EDIT2: Okay, i've made this:
    Code:Java
    1.  
    2. Random r = new Random();
    3. int n = r.nextInt(100);
    4. if (n >= 50) {
    5. inv.addItem(new ItemStack(Material.APPLE));
    6. } else if (n >= 25) {
    7. inv.addItem(new ItemStack(Material.GOLDEN_APPLE));
    8. }
    9.  

    And it seems to work.(for chance) but how would i make it so that it adds only a specific number of items? I'll say 4 for now, how would i make it so that it only adds 4 items from a list of items? Also when i reload/restart the server the chests get reset to normal chests, should i save the locations in a yml file for it to save them?
     
    Last edited by a moderator: May 28, 2018
  10. Offline

    Tabuu_

    I thought that since this post has gotten so much atention I'd also contribute.

    Below are 2 examples of how I would make refilling chest, one where the chest coordinates are saved in the config and one where your want to refill the chest in a radius. Please note that I am using TabuuCore to simplify a lot of the tasks, so please check the imports to see what classes are from TabuuCore so you can replicate that/not get confused.

    Example 1 (chest locations saved in the config) (open)

    Main Plugin Class
    Code:
    package nl.tabuu.exampleplugin;
    
    
    import nl.tabuu.exampleplugin.commandhandlers.ExampleCH;
    import nl.tabuu.exampleplugin.eventhandlers.PlayerEH;
    import nl.tabuu.tabuucore.configuration.Config;
    import nl.tabuu.tabuucore.configuration.ConfigManager;
    import org.bukkit.Bukkit;
    import org.bukkit.Location;
    import org.bukkit.block.Block;
    import org.bukkit.block.Chest;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.plugin.java.JavaPlugin;
    
    import java.util.List;
    import java.util.Random;
    
    public class ExamplePlugin extends JavaPlugin {
      
        private static ConfigManager _configManager;
    
        @Override
        public void onEnable() {
            _plugin = this;
            _configManager = new ConfigManager(this);
            _configManager.addConfig("config");
    
            Runnable refillChests = () -> {
                Config config = ExamplePlugin.getConfigManager().getConfig("config");
                Random random = new Random();
    
                for(Location location : config.getLocationList("ChestLocations")){
                    Block chestBlock = location.getBlock();
                    if(!(chestBlock.getState() instanceof Chest)) continue;
    
                    Chest chest = (Chest) chestBlock.getState();
                    chest.getBlockInventory().clear();
    
                    List<ItemStack> lootTable = config.getItemStackList("ChestLootTable");
                    for(int i = 0; i < 4; i++){
                        int lootIndex = random.nextInt(lootTable.size());
                        chest.getBlockInventory().addItem(lootTable.get(lootIndex));
                    }
                }
            };
            Bukkit.getScheduler().scheduleSyncRepeatingTask(this, refillChests, 0L, 1200L);
        }
    
        public static ConfigManager getConfigManager(){
            return _configManager;
        }
    
    }
    Config.yml
    Code:
    ChestLocations:
    
      - "world 0 0 0"
      - "world 0 1 0"
    
    ChestLootTable:
      '0':
        Material: 'APPLE'
        DisplayName: 'Just an apple'
      '1':
        Material: 'GOLDEN_APPLE'
        DisplayName: 'A golden apple'
      '1':
        Material: 'GOLDEN_APPLE'
        DisplayName: 'A notch apple'
        Data: 1

    Example 2 (in radius) (open)

    Main Plugin Class
    Code:
    package nl.tabuu.exampleplugin;
    
    import nl.tabuu.exampleplugin.commandhandlers.ExampleCH;
    import nl.tabuu.exampleplugin.eventhandlers.PlayerEH;
    import nl.tabuu.tabuucore.configuration.Config;
    import nl.tabuu.tabuucore.configuration.ConfigManager;
    import org.bukkit.Bukkit;
    import org.bukkit.Location;
    import org.bukkit.block.Block;
    import org.bukkit.block.Chest;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.plugin.java.JavaPlugin;
    
    import java.util.List;
    import java.util.Random;
    
    public class ExamplePlugin extends JavaPlugin {
      
        private static ConfigManager _configManager;
    
        @Override
        public void onEnable() {
            _plugin = this;
            _configManager = new ConfigManager(this);
            _configManager.addConfig("config");
    
            Runnable refillChests = () -> {
                Config config = ExamplePlugin.getConfigManager().getConfig("config");
                Random random = new Random();
    
            for(Block block : BukkitTools.getBlocksInRadius(config.getLocation("CenterLocation"), 20)){
                    Block chestBlock = block;
                    if(!(chestBlock.getState() instanceof Chest)) continue;
    
                    Chest chest = (Chest) chestBlock.getState();
                    chest.getBlockInventory().clear();
    
                    List<ItemStack> lootTable = config.getItemStackList("ChestLootTable");
                    for(int i = 0; i < 4; i++){
                        int lootIndex = random.nextInt(lootTable.size());
                        chest.getBlockInventory().addItem(lootTable.get(lootIndex));
                    }
                }
            };
            Bukkit.getScheduler().scheduleSyncRepeatingTask(this, refillChests, 0L, 1200L);
        }
    
        public static ConfigManager getConfigManager(){
            return _configManager;
        }
    
    }
    
    Config.yml
    Code:
    CenterLocation: "world 0 0 0"
    
    ChestLootTable:
      '0':
        Material: 'APPLE'
        DisplayName: 'Just an apple'
      '1':
        Material: 'GOLDEN_APPLE'
        DisplayName: 'A golden apple'
      '1':
        Material: 'GOLDEN_APPLE'
        DisplayName: 'A notch apple'
        Data: 1


    I hope you can get some ideas from my code!
     
  11. Offline

    KarimAKL

    @Tabuu_ Thank you, that gave me some ideas. :)
    Currently i have this for testing:
    Code:Java
    1.  
    2. for (int i = 0; i < 4; i++) {
    3. int n = r.nextInt(5);
    4. if (n >= 3) {
    5. inv.addItem(new ItemStack(Material.APPLE));
    6. } else if (n >= 2) {
    7. inv.addItem(new ItemStack(Material.ARROW, 2));
    8. } else if (n >= 1) {
    9. inv.addItem(new ItemStack(Material.GOLDEN_APPLE));
    10. }
    11. }
    12.  

    Seems to work, but how would i make it so items can have the same chance to spawn in the chest? Example:
    Code:Java
    1.  
    2. if (n >= 3) {
    3. inv.addItem(new ItemStack(Material.APPLE));
    4. } else if (n >= 3) {
    5. inv.addItem(new ItemStack(Material.ARROW, 2));
    6.  

    This would spawn the apple only because the "else" won't get triggered because the amount is 3 or more at the start. :7 How would i make it so that it's possible to have the same amount of chance? EDIT: Is there another way of making % chance?
     
  12. Offline

    Tabuu_

    There is, I use an if-statement like this most of the time:
    Code:
    double n = random.nextDouble();
    
    if(n > 0 && n <= 0.25) //item with 25% chance;
    else if(n > 0.25 && n <= 0.5) //item with 25% chance;
    else if(n > 0.5 && n <= 1) //item with 50% chance;
     
  13. Offline

    KarimAKL

    @Tabuu_ But if i did it like that the first one would be the one that gets triggered, right? :7 Or would i be able to just make it "if" instead of "else if"? The "for (int i = 0; i < 4; i++) {" should make it so only up to 4 of them can get triggered anyway, right?
     
  14. Offline

    Tabuu_

    Putting that code in a for loop would trigger it 4 times, indeed.
     
  15. Offline

    KarimAKL

    @Tabuu_ I just tried this:
    Code:Java
    1.  
    2. for (int i = 0; i < 4; i++) {
    3. int n = r.nextInt(3);
    4. if (n == 3) {
    5. inv.addItem(new ItemStack(Material.APPLE));
    6. }
    7. if (n == 2) {
    8. inv.addItem(new ItemStack(Material.ARROW, 2));
    9. }
    10. if (n == 1) {
    11. inv.addItem(new ItemStack(Material.GOLDEN_APPLE));
    12. }
    13. }
    14.  

    And only the Arrows and Golden Apples get in the chest, not the normal apples, why is that?
     
  16. Offline

    timtower Administrator Administrator Moderator

    @KarimAKL n = 0, 1 or 2, never 3.
    The number gives the limit, it will always be lower.
     
  17. Offline

    KarimAKL

    @timtower Oh, it starts from 0 in this case? :eek:
     
  18. Offline

    timtower Administrator Administrator Moderator

    Java starts counting at 0 for everything... Unless specified otherwise.
     
  19. Offline

    KarimAKL

    @timtower I see, so only a few things start from 1? Thanks for the information. :)
     
  20. Offline

    timtower Administrator Administrator Moderator

    It is very uncommon to start from 1. There are other languages that do it but those are weird.
     
  21. Offline

    KarimAKL

    @timtower Okay. :p Also, how would i check if any of the chests are set? (If any locations is set) Is there a way to check if the list is empty? I want to move the locations to a yml file so is there any way to check if the list in yml is empty?(Strike through because i found out)
    EDIT: Also, if i use cancel(); would it still keep trying until it succeeds? Example:
    Found out (open)

    Code:Java
    1.  
    2. if (plugin.getServer().getWorld("world").getPlayers().isEmpty()) {
    3. cancel();
    4. Bukkit.getServer().getConsoleSender().sendMessage("No players online.")
    5. }
    6.  


    Would that still keep trying until a player is online in world "world"?
    EDIT2: Is it possible to make a list of locations like this?:

    Foundt out (open)

    Code:
    #This is the config
    Locations:
        - world 126 72 756
        - world 732 75 239
        #- etc
    

    or would i need to make it like this?:
    Found out (open)

    Code:
    #This is the config
    Locations:
        Location1:
            World: world
            X: 126
            Y: 72
            Z: 756
        Location2:
            World: world
            X: 732
            Y: 75
            Z: 239
        #etc
    

    If the first one is possible i would like to make something like that, maybe if it isn't possible to make that but this:
    Found out (open)

    Code:
    #This is the config
    Locations:
        world:
            - 126 72 756
            - 732 75 239
            #- etc
        anotherWorld:
            - 243 34 345
    

    And if the first one is not possible then the second one and for the second one how would i make it increase the number by 1 for every location? (location1, location2, location3, etc)
    EDIT3: Sorry for all the questions. :p

    EDIT4: I've been trying to put the locations inside a YML file like this:
    Code:
    Locations:
    - world 230 67 -105
    
    And it puts it inside the locations file like that and removes it when i want it removed but how would i get the StringList instead of the LocationList(ArrayList)?
    For the ArrayList:
    Code:Java
    1.  
    2. for (Location chests : LocationList.locations) {
    3.  

    For the StringList:
    Code:Java
    1.  
    2. for (String chests : plugin.locations.getStringList("Locations")) {
    3.  

    But if i do this the following will not work. :7
    The following:
    Code:Java
    1.  
    2. BlockState state = chests.getBlock().getState();
    3.  

    And without that i can't do what i want. :/ So what should i do?
     
    Last edited by a moderator: Jun 10, 2018
  22. Offline

    KarimAKL

    bump, how would i do this?
    My guess:
    Check if "Locations" in the yml file contains the world name and if it does then get the numbers after the world name and check if those numbers equal the location of a chest. (or something like this)
    EDIT: Just wanted to say that if my guess is correct then i don't know how i would check if the StringList contains one word. :7 (one part of a line)
     
    Last edited by a moderator: Jun 11, 2018
  23. Offline

    timtower Administrator Administrator Moderator

    @KarimAKL Change the string list to a list of locations when loading.
     
  24. Offline

    KarimAKL

    @timtower When loading what? The chests? If so then wouldn't changing the string list to a list of locations make it so that the world name at the start of the string makes an error? Maybe i didn't understand correctly?
     
  25. Offline

    timtower Administrator Administrator Moderator

    onEnable to load the worlds that are active.
    on world load for the others.
     
  26. Offline

    KarimAKL

    @timtower Should i load all the worlds that exist and then what? (Sorry but i don't understand completely)
     
  27. Offline

    timtower Administrator Administrator Moderator

    You have a list of chests.
    In the onEnable you fill that list with the worlds that are loaded already.
    on world load you add the chests that should be in that world.
    Then you just use the list.
    Or a map, not my call to make.
     
  28. Offline

    KarimAKL

    @timtower
    1. I should put the chest locations in a "List<Location>"?
    2. I don't understand. :/
    3. So when i've done 2 i add the locations from the "List<Location>" and check if they are chests?
    4. Use the list? "StringList" or "List<Location>"?
    5. I'll just use a list.

    (Again i don't think i understand. :/ (I don't understand what you mean by load the worlds and if i should use the stringlist in the yml file or an arraylist and if you mean an arraylist then what should it be? "<Location>"?))
    EDIT: When i look at these messages i really seem hopeless. :7
     
  29. Offline

    timtower Administrator Administrator Moderator

    @KarimAKL What do you have already? Might be easier to explain it backwards.

    And chance exists that I don't see your edits, I check the thread and then leave it till there is a new post again.
     
  30. Offline

    KarimAKL

    @timtower I thought that was the case, i just don't wanna double post so that's why i edit until a few days has passed. :p
    Anyway, here is the class for the BukkitRunnable:
    Code:Java
    1.  
    2. public class RepeatRun {
    3.  
    4. @SuppressWarnings("unused")
    5. private Main plugin;
    6.  
    7. public RepeatRun(Main plugin) {
    8. this.plugin = plugin;
    9. new BukkitRunnable() {
    10. @Override
    11. public void run() {
    12. if (plugin.getServer().getWorld(plugin.locations.getString("World")) != null) {
    13. if (!plugin.getServer().getWorld(plugin.locations.getString("World")).getPlayers().isEmpty()) {
    14. if (!LocationList.locations.isEmpty()) {
    15. for (Location chests : LocationList.locations) {
    16. BlockState state = chests.getBlock().getState();
    17. if (state instanceof Chest) {
    18. Chest chest = (Chest) state;
    19. Inventory inv = chest.getBlockInventory();
    20. Random r = new Random();
    21. for (ItemStack items : inv.getContents()) {
    22. if (items != null) {
    23. inv.clear();
    24. }
    25. }
    26. for (int i = 0; i < 4; i++) {
    27. int n = r.nextInt(100);
    28. if (n < 80) {
    29. inv.addItem(new ItemStack(Material.APPLE));
    30. }
    31. if (n < 25) {
    32. inv.addItem(new ItemStack(Material.ARROW, 2));
    33. }
    34. if (n == 0) {
    35. inv.addItem(new ItemStack(Material.GOLDEN_APPLE));
    36. }
    37. }
    38. }
    39. }
    40. if (LocationList.locations.size() == 1) {
    41. Bukkit.broadcastMessage(Color.here("&bChest refilled."));
    42. } else {
    43. Bukkit.broadcastMessage(Color.here("&bChests refilled."));
    44. }
    45. }
    46. }
    47. } else {
    48. cancel();
    49. Bukkit.getConsoleSender().sendMessage(Color.here("&cWorld specified in the locations.yml doesn't exist!"));
    50. }
    51. }
    52. }.runTaskTimer(plugin, 0, 20*plugin.loot.getInt("Delay"));
    53. }
    54. }
    55.  

    That is what i have right now, i don't get what i should do from here. :7
     
Thread Status:
Not open for further replies.

Share This Page