Solved Setting chest inventory title.

Discussion in 'Plugin Help/Development/Requests' started by oceantheskatr, Apr 16, 2015.

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

    oceantheskatr

    Hello again Bukkit!

    Today I'm wondering how I'd set a chest's name/title when placing a block at a location.

    My plugin is a loot chest plugin, and I'd like to make it so that if the chest's name is "Loot Chest" then to execute some code.

    When I place a chest with the name Loot Chest, it'll store the chest's world, location, and direction it's facing in the config.yml. Then when the server starts up it'll place those chests at the specified locations. Right now I have it set so that when you open any chest it'll create a virtual inventory with the correct name, though I'd like to make it so that it'll only happen for certain chests.

    I do know how to get a chests name though, so checking for the name won't be a a problem, just setting it when the item is placed.

    Thank you in advance to anyone who may be able to help out with this.

    Here is my current code:

    Code:
    package me.themineshack;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    
    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.Effect;
    import org.bukkit.Location;
    import org.bukkit.Material;
    import org.bukkit.block.Block;
    import org.bukkit.block.Chest;
    import org.bukkit.block.DoubleChest;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.FallingBlock;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.Action;
    import org.bukkit.event.block.BlockPlaceEvent;
    import org.bukkit.event.entity.EntityChangeBlockEvent;
    import org.bukkit.event.inventory.InventoryCloseEvent;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.inventory.Inventory;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.ItemMeta;
    import org.bukkit.plugin.java.JavaPlugin;
    import org.bukkit.util.Vector;
    import org.fusesource.jansi.Ansi;
    
    public class LootChest extends JavaPlugin implements Listener {
       
        ArrayList<String> chesty = new ArrayList<String>();
       
        @Override
        public void onEnable() {
            Bukkit.getServer().getPluginManager().registerEvents(this, this);
            List<String> chests = getConfig().getStringList("chests");
            getConfig().set("chests", chests);
            saveConfig();
            for (String str : chests) {
                String[] words = str.split(",");
                String aWorld = words[0];
                byte dir = Byte.parseByte(words[2]);
                String aX = words[3];
                double aX1 = Double.parseDouble(aX);
                String aY = words[4];
                double aY1 = Double.parseDouble(aY);
                String aZ = words[5];
                double aZ1 = Double.parseDouble(aZ);
                Location chestLoc = new Location (Bukkit.getWorld(aWorld), aX1, aY1, aZ1);
               
                if (chestLoc.getBlock().getType() != Material.CHEST) {
                    // Set to chest
                    chestLoc.getBlock().setType(Material.CHEST);
                    // Getting chest object from BlockState
                    Chest ch = (Chest) chestLoc.getBlock().getState();
                    // Now apply the byte       
                    chestLoc.getBlock().setData((byte) dir);
                   
                    // Converting ItemStack to a placeable block would be nice! :P
                       ItemStack lc = new ItemStack(Material.CHEST);
                       ItemMeta meta = lc.getItemMeta();
                       meta.setDisplayName(ChatColor.GOLD + ("Loot Chest"));
                       lc.setItemMeta(meta);
                  
                } else {
                    // Some one didn't break the chest before the restart? Surprising! :o
                    getLogger().info(Ansi.ansi().fg(Ansi.Color.YELLOW) + "A loot chest was already located at " + aX + "," + aY + "," + aZ + "!" + Ansi.ansi().fg(Ansi.Color.DEFAULT));
                }
            }
        }
       
        @Override
        public void onDisable() {
            List<String> chests = getConfig().getStringList("chests");
            chesty.addAll(chests);
            getConfig().set("chests", chesty);
            saveConfig();
        }
       
        // If a chest with the display name "Loot Chest" is placed, add world/location/direction to config.
        @EventHandler
        public void onBlockPlace(BlockPlaceEvent e) {
            Player player = e.getPlayer();
            ItemStack bih = e.getItemInHand();
            Block b = e.getBlock();
            Chest chest = (Chest) b.getState();
            String bLoc = b.getLocation().getWorld().getName() + "," + b.getType() + "," + chest.getData().getData() + "," + b.getLocation().getBlockX() + "," + b.getLocation().getBlockY() + "," + b.getLocation().getBlockZ();
            if (b.getType() == Material.CHEST) {
                if (bih.getItemMeta().getDisplayName().contains("Loot Chest")) {
                    player.sendMessage(ChatColor.GREEN + "Loot Chest placed!");
                    chesty.add(bLoc);
                   
                }
            } else {
                return;
            }
        }
       
        // Create virtual inventory
        private void openInv (Player player) {
            Inventory i = Bukkit.createInventory(null, 27, "" + ChatColor.GOLD + ChatColor.BOLD + "Loot Chest");
            Random random = new Random();
           
            int rn1 = random.nextInt(6) + 1;
            int rn2 = random.nextInt(6) + 1;
            int rn3 = random.nextInt(6) + 1;
           
            int invSlot1 = random.nextInt(27);
            int invSlot2 = random.nextInt(27);
            int invSlot3 = random.nextInt(27);
           
           
            ItemStack gold1 = new ItemStack(Material.GOLD_NUGGET, rn1);
            ItemMeta goldMeta1 = gold1.getItemMeta();
            goldMeta1.setDisplayName(ChatColor.GOLD + ("Gold"));
            gold1.setItemMeta(goldMeta1);
           
           
           
            ItemStack gold2 = new ItemStack(Material.GOLD_NUGGET, rn2);
            ItemMeta goldMeta2 = gold2.getItemMeta();
            goldMeta2.setDisplayName(ChatColor.GOLD + ("Gold"));
            gold2.setItemMeta(goldMeta2);
           
           
            ItemStack gold3 = new ItemStack(Material.GOLD_NUGGET, rn3);
            ItemMeta goldMeta3 = gold3.getItemMeta();
            goldMeta3.setDisplayName(ChatColor.GOLD + ("Gold"));
            gold3.setItemMeta(goldMeta3);
           
            i.setItem(invSlot1, gold1);
            i.setItem(invSlot2, gold2);
            i.setItem(invSlot3, gold3);
           
            player.openInventory(i);
        }
       
        // On chest open
        @EventHandler
        public void onInvOpen(final PlayerInteractEvent e) {
            Action a = e.getAction();
            if (a == Action.RIGHT_CLICK_BLOCK) {
                final Player player = e.getPlayer();
                if (e.getClickedBlock().getType() == Material.CHEST) {
                    // Get chest direction
                    final Byte dir = e.getClickedBlock().getLocation().getBlock().getState().getData().getData();
                    // Get chest object from BlockState
                    Chest ch = (Chest) e.getClickedBlock().getLocation().getBlock().getState();
                    // Send player chest's title
                    player.sendMessage("" + ch.getBlockInventory().getTitle());
                    // Cancel opening of chest
                    e.setCancelled(true);
                    // Open virtual chest
                    openInv(player);
                   
                    // Set chest to air and play CRIT effect
                    final Location loc = e.getClickedBlock().getLocation();
                    player.getWorld().playEffect(loc, Effect.CRIT, 12);
                    player.getWorld().playEffect(loc, Effect.CRIT, 12);
                    player.getWorld().playEffect(loc, Effect.CRIT, 12);
                    player.getWorld().playEffect(loc, Effect.CRIT, 12);
                    player.getWorld().playEffect(loc, Effect.CRIT, 12);
                    e.getClickedBlock().setType(Material.AIR);
                   
                    // Create falling block
                    float x = 0;
                    float y = 1;
                    float z = 0;
                    FallingBlock fall = loc.getWorld().spawnFallingBlock(loc, Material.CHEST, e.getClickedBlock().getState().getData().getData());
                    fall.setDropItem(false);
                    fall.setVelocity(new Vector(x, y, z));
                   
                    // Respawn chest and play MAGIC_CRIT effect
                    this.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
                          public void run() {
                                // Set the block
                                  e.getClickedBlock().getLocation().getBlock().setType(Material.CHEST);
                                // Now apply the byte
                                e.getClickedBlock().getLocation().getBlock().setData((byte) dir);
                                player.getWorld().playEffect(loc, Effect.MAGIC_CRIT, 0, 12);
                                player.getWorld().playEffect(loc, Effect.MAGIC_CRIT, 0, 12);
                                player.getWorld().playEffect(loc, Effect.MAGIC_CRIT, 0, 12);
                                player.getWorld().playEffect(loc, Effect.MAGIC_CRIT, 0, 12);
                                player.getWorld().playEffect(loc, Effect.MAGIC_CRIT, 0, 12);
                                player.getWorld().playEffect(loc, Effect.MAGIC_CRIT, 0, 12);
                          }
                        }, 100L); // Set to only 5 seconds for testing
                }
            }
        }
       
        // Remove falling item
        @EventHandler
        public void onBlockChange(final EntityChangeBlockEvent e){
                e.setCancelled(true);
                if (e.getEntity() instanceof FallingBlock){
                    FallingBlock fb = (FallingBlock) e.getEntity();
                    fb.getWorld().playEffect(fb.getLocation(), Effect.STEP_SOUND, fb.getMaterial());
                    fb.remove();
                }
            }
       
        // Just for checking stuff
        @EventHandler
        public void onInvClose(InventoryCloseEvent e) {
            if (e.getInventory().getHolder() instanceof Chest || e.getInventory().getHolder() instanceof DoubleChest) {
                Player player = (Player) e.getPlayer();
                player.sendMessage("Closed.");
               
            }
        }
    }
    @I Al Istannen going for the hat trick of helping Ocean? ;)
     
  2. Offline

    I Al Istannen

    @oceantheskatr Just has a method to get the title and none to change it. Just like the inventory.But you can instantiate an Inventory and define the name with the constructor via Bukkit.createInventory(). This just doesnt seem to be the case with a Chest. You can't instantiate is as there are no Classes which implement it. And you cant create it afaik with the Bukkit API. So i would conclude, that i have no idea, and didn't find anything to change it. You could try to store all lootChests in a file, create a for example HashSet (you may need a volatile or a synchronized, if two threads access the set at the same time) with the Location. Then check if the block.getLocation() from the OpenIvEvent is in that set, and react based on that. Saving could be done with a StringList, like you did.
     
  3. Offline

    oceantheskatr

    @I Al Istannen Alright thanks for the response! I think I'll try using those chest locations to decide whether or not to open the custom inventory. Do you think it would be possible to give the chest some sort of metadata when creating it? Then check to see if it has that metadata when opening it?
     
  4. Offline

    I Al Istannen

    @oceantheskatr Yes. The only problem is that metadata are not persistent. They get deleted when you reload or restart the server. Use block.setMetadata() and block.hasMetadata() and block.getMetadata() (you can get a description of the metadata methods here: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/metadata/Metadatable.html).

    Metadata types: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/metadata/LazyMetadataValue.html
    https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/metadata/FixedMetadataValue.html
     
  5. Offline

    oceantheskatr

    I'd be adding it in the same area as where I place the chests, and where I respawn them after breaking :)
     
  6. Offline

    I Al Istannen

    @oceantheskatr So it would't be required to have them persistent. Then Metadata might be the better way. You don't have to worry about storing, reading or other things, so try it out :D
     
  7. Offline

    oceantheskatr

    Alright I'll be sure to!
     
Thread Status:
Not open for further replies.

Share This Page