So basically what I am trying to do is make it so every player has their own extra storage bag that they can upgrade(starting on that later), but at the moment I am stuck with this. I am making it so if the Hashmap "storage" does not contain a value, to create a new inventory and set it a value. The only problem is I cannot then use the inventory "bag" in another if statement to open it when the value is set. Here is my code :
package me.impatheimpaler.aqw;
import java.util.HashMap;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.Inventory;
public class Storage implements Listener{
public me.impatheimpaler.aqw.Main plugin;
public HashMap<String, Inventory> storage = new HashMap<String, Inventory>();
public Storage(Main main) {
plugin = main;
}
#EventHandler
public void onInteract(PlayerInteractEvent e) {
if (!(e.getItem().getType() == Material.CHEST)) return;
if (!(e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK)) return;
if (e.getItem().getItemMeta().hasLore() &&
e.getItem().getItemMeta().getLore().contains(ChatColor.GREEN + "A bag for extra storage.")) {
if (storage.containsKey(null) && storage.containsValue(null)) {
Inventory bag = Bukkit.getServer().createInventory(e.getPlayer(), 9, "Storage");
storage.put(e.getPlayer().getName(), bag);
}
if (storage.contains(e.getPlayer().getName(), bag)) {
//Here is the error, as I cannot use the value "bag", because it cannot be
accessed from another if statement.
}
}
}
}
You could just declare bag outside of the if statement, then set it inside of the statement:
Inventory bag;
if(storage.containsKey(null) && storage.containsValue(null)){
//code
}
So, it could look something like this:
Inventory bag;
if (storage.containsKey(null) && storage.containsValue(null)) {
bag = Bukkit.getServer().createInventory(e.getPlayer(), 9, "Storage");
storage.put(e.getPlayer().getName(), bag);
}
if (storage.contains(e.getPlayer().getName(), bag)) {
//use "bag" however you want
}
Also, instead of checking if storage.containsKey(null), to check if the player's name NOT is in the HashMap, you should use:
if(!storage.containsKey(e.getPlayer().getName()){
Doing storage.containsKey(null) will check if the map has null as a key, it won't find anything out about the player
Related
I am trying to develop a blacklist system for blocks for my server and this is how it should work: In the config.yml there are names of the materials of the blocks that are not allowed to be placed. Then a check is made for each placed block whether the material is contained in config.yml.
Here is my code:
package de.blocklog.blocklog;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.List;
public final class Main extends JavaPlugin implements Listener {
#Override
public void onEnable() {
// Plugin startup logic
}
#Override
public void onDisable() {
// Plugin shutdown logic
}
#EventHandler
public void onBlockPlace(BlockPlaceEvent event){
Block block = event.getBlock();
Material material = block.getType();
Player placer = event.getPlayer();
double x = block.getLocation().getX();
double y = block.getLocation().getY();
double z = block.getLocation().getZ();
List<String> bannedmats = this.getConfig().getStringList("banned-blocks");
for(World w : Bukkit.getWorlds()){
for(Player p : w.getPlayers()){
if(p.hasPermission("blocklogsystem.see") || p.hasPermission("blocklogsystem.*"))
p.sendMessage("[BLOCKLOG] Player " + placer.getDisplayName() + " placed " + material + " at X:" + x + " Y: " + y +" Z: "+ z);
if(material.name().equals(bannedmats))
p.sendMessage("[BLOCKLOG] Player " + placer.getDisplayName() + " placed an illegal " + material + " at X:" + x + " Y: " + y +" Z: "+ z);
}
}
}
}
But somehow it doesn't work :/
Yout need to register your Event in the onEnable Method like:
#Override
public void onEnable() {
// Plugin startup logic
Bukkit.getPluginManager().registerEvents(this, this);
}
To be fair, your provided information is a bit vague but I've recently implemented exactly this feature except with the banned blocks stored in memory as an ArrayList of Material objects.
Effectively what I do is make use of the .contains() method of an ArrayList object to check for presence of a given block in a list of blocks.
All this considered here is the basic run down, assuming you've already developed parsing your config.yml data into specifically an ArrayList of Material objects that looks something like this:
public static ArrayList<Material> PlacementBanned = new ArrayList<>();
{
PlacementBanned.addAll(Arrays.asList(Material.BARRIER, Material.COMMAND_BLOCK,
Material.CHAIN_COMMAND_BLOCK, Material.REPEATING_COMMAND_BLOCK, Material.COMMAND_BLOCK_MINECART,
Material.WATER, Material.LAVA, Material.STRUCTURE_BLOCK, Material.STRUCTURE_VOID));
}
Firstly, I highly recommend you use a separate class for the listener. like this:
Main
package myPlugin;
import myPlugin.myPackage.myListenerClass;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
public class Main extends JavaPlugin {
public static Plugin instance;
#Override
public void onEnable() {
instance = this;
PluginManager pm = getServer().getPluginManager();
pm.registerEvents(new myListenerClass(), this);
}
}
myPackage.myListenerClass
package myPlugin.myPackage;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.event.Listener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockPlaceEvent;
public class myListenerClass implements Listener {
#EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = false)
public void onPlace(BlockPlaceEvent event) {
Block block = event.getBlockPlaced();
Material blockType = block.getType();
if (PlacementBanned.contains(blockType)) {
event.setCancelled(true);
return;
}
}
}
Note, LOWEST priority means it will be queued up in the first of 5 batches of all methods triggered by the listener in your code.
I was working on this code and I happened to put the type as the original class. Now if I plug the variable in with its subclasses (extended classes) it errors. I'm running a Spigot plugin, but obviously this problem has nothing to do with Spigot itself but rather my lack of knowledge regarding Java.
I can't come up with any single solution and I've looked all over.
Edit (My Explaination): If you look at the PlayerClass, you will see a variable called Kit, it uses the KitClass type. If you look at the KitClass it is a class that has one subclass called Alchemist. My question is, does the KitClass type encompass all the inherited classes and original class? If not then what type/modifications would I have to use for the Kit variable within PlayerClass in order for it to allow an instance of the Alchemist class to be set as the Kit variable?
package me.kckeith.KitPvP;
import org.bukkit.entity.Player;
public class PlayerClass {
public Player Player;
public double Coins;
public KitClass Kit;
public PlayerClass(Player Player, double Coins, KitClass Kit) {
this.Player = Player;
this.Coins = Coins;
this.Kit = Kit;
}
public void setKit(KitClass Kit) {
this.Kit = Kit;
this.Kit.giveStuff();
}
}
package me.kckeith.KitPvP;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import net.md_5.bungee.api.ChatColor;
public class KitClass {
public Player Player;
public Material InventoryIcon;
public KitClass(Player player) {
this.Player = player;
}
public void giveStuff() {
Bukkit.getServer().getConsoleSender().sendMessage(ChatColor.GOLD + "Given items!");
}
}
package me.kckeith.KitPvP.Kits;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import me.kckeith.KitPvP.KitClass;
public class Alchemist extends KitClass {
public static Material InventoryIcon = Material.SPLASH_POTION;
public Alchemist(Player player) {
super(player);
}
public void giveStuff() {
// Clear items
this.Player.getInventory().clear();
// Give the player their armor
ItemStack[] Armor = new ItemStack[4];
Armor[0] = new ItemStack(Material.LEATHER_BOOTS);
Armor[1] = new ItemStack(Material.LEATHER_LEGGINGS);
Armor[2] = new ItemStack(Material.LEATHER_CHESTPLATE);
Armor[3] = new ItemStack(Material.LEATHER_HELMET);
// Add Enchants
Armor[0].addEnchantment(Enchantment.PROTECTION_ENVIRONMENTAL, 1);
Armor[1].addEnchantment(Enchantment.PROTECTION_ENVIRONMENTAL, 1);
Armor[2].addEnchantment(Enchantment.PROTECTION_ENVIRONMENTAL, 1);
Armor[3].addEnchantment(Enchantment.PROTECTION_ENVIRONMENTAL, 1);
// Give Armor
this.Player.getInventory().setArmorContents(Armor);
// Give Golden Sword
ItemStack GoldenSword = new ItemStack(Material.GOLDEN_SWORD);
GoldenSword.addEnchantment(Enchantment.DURABILITY, 1);
this.Player.getInventory().addItem(GoldenSword);
// Give Regen Potions
ItemStack RegenPotion = new ItemStack(Material.POTION, 4);
PotionMeta RegenPotionMeta = (PotionMeta) RegenPotion.getItemMeta();
RegenPotionMeta.addCustomEffect(new PotionEffect(PotionEffectType.REGENERATION, 20, 2), true);
RegenPotion.setItemMeta(RegenPotionMeta);
this.Player.getInventory().addItem(RegenPotion);
// Give Damage Potions
ItemStack DamagePotion = new ItemStack(Material.SPLASH_POTION, 8);
PotionMeta DamagePotionMeta = (PotionMeta) DamagePotion.getItemMeta();
DamagePotionMeta.addCustomEffect(new PotionEffect(PotionEffectType.HARM, 0, 2), true);
DamagePotion.setItemMeta(DamagePotionMeta);
this.Player.getInventory().addItem(DamagePotion);
super.giveStuff();
}
}
The specific error I believe was NullStackException however I am not sure. I got into more detail into this issue at the top of the code.
My question is does the KitClass type encompass all the inherited classes and original class?
Yes it does, so when you create an Alchemist you can still use all of the KitClass methods. This would be correct: Alchemist myAlchemistObject = new Alchemist(myPlayer);
You have a lot of code that may be confusing. You should not have a Class and an object/variable with the same name.
For example, when declaring a variable this is not good:
public Player Player;
But this is clear and easy to read:
public Player player;
This is better again, and there will be no mixup/confusion:
public Player myPlayer;
Another example. This is unclear:
PlayerClass PlayerClass = MainClass.PlayerList.get(Player.getUniqueId());
Alchemist Alchemist = new Alchemist(Player);
PlayerClass.Kit = Alchemist;
PlayerClass.Kit.giveStuff();
And this is easy to understand:
PlayerClass myPlayerObject = MainClass.PlayerList.get(myPlayer.getUniqueId());
Alchemist myAlchemistObject = new Alchemist(myPlayer);
myPlayerObject.Kit = myAlchemistObject;
myPlayerObject.Kit.giveStuff();
Hi everyone I'm trying to use variables from the Main class into my Event Listener class. This is a Minecraft Java Bukkit code that I'm working with. I'm trying to receive the "CanRestart" static boolean variable from my MainClass and trying to use it in the Event Listeners class. No errors popup in the program, but in the console there are errors and the plugin does not work.
I know that the problem is this line of code from the Event Listeners class (which I created to try and get the variables from the Main class):
MainProgram MainCode = new MainProgram();
I do not have that much knowledge with Java's OOP, but I was really wondering if I could get help.
I'm trying to get a code like this work:
MainProgram MainCode = new MainProgram();
if(MainCode.CanRestart == true){
//We received a variable from the main class!
}
Here is my Main Class:
package me.Shadowsych;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
public class MainProgram extends JavaPlugin{
public static boolean CanRestart = true;
public int CDNumber = 5;
public int DetermineCounter;
#Override
public void onEnable(){ //Essential, when your plugin is enabled.
getLogger().info("Shadowsych's Command Plugin is working!"); //CMD will print this out.
new EventListeners(this); //Inherits the EventListeners class
}
#Override
public void onDisable(){//Essential, when your plugin is disabled.
}
#SuppressWarnings("deprecation")
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { //Creates command function.
Player player = (Player) sender;
if(cmd.getName().equalsIgnoreCase("timer")){
if(CanRestart == true){ //Checks to see if the Timer is still running
CanRestart = false; //The timer has ran.
CDNumber = 5;
DetermineCounter = Bukkit.getServer().getScheduler().scheduleAsyncRepeatingTask(this, new Runnable(){
public void run(){
if(CDNumber > -1){ //This can be a 0 integer
if(!(CDNumber == 0)){ //If once it is 0.
player.sendMessage("" + CDNumber); //The "" is used to make number a String.
}
CDNumber --; //Makes the number -1 if it's already a 0.
}
if(CDNumber == -1){ //Now catches that the number is -1.
player.sendMessage("Count down finished");
Bukkit.getServer().getScheduler().cancelTask(DetermineCounter); //Disables counter.
CanRestart = true; //You can restart your timer now.
return;
}
}
}, 0L, 20L);
}
}
return false; //Is essential in a boolean function.
}
}
Here is my Event Listener Class:
package me.Shadowsych;
import me.Shadowsych.MainProgram;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerToggleFlightEvent;
public class EventListeners implements Listener {
MainProgram MainCode = new MainProgram();
public EventListeners(MainProgram plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin); //Registers Event Main
}
#EventHandler
public void PlayerToggleFlight(PlayerToggleFlightEvent EventFloat){
Player player = EventFloat.getPlayer();
if(player.getGameMode() == GameMode.CREATIVE)
return; //If the player is creative then don't do this Event.
EventFloat.setCancelled(true);
player.setAllowFlight(false);
player.setVelocity(player.getLocation().getDirection().multiply(0).setY(1));
player.sendMessage(ChatColor.AQUA + "You have double jumped!");
}
#EventHandler
public void PlayerJump(PlayerMoveEvent EventJumped){
Player player = EventJumped.getPlayer();
if((player.getGameMode() != GameMode.CREATIVE) //Player is not creative
&& (player.getLocation().subtract(0, 1, 0).getBlock().getType() != Material.AIR) //Block beneath them is not air
&& (!player.isFlying())) //Player is not flying
{
player.setAllowFlight(true); //Allow the player to fly
}
}
}
Here is what the console says:
http://prntscr.com/9ki7a5
In your listener class, you take the MainProgram object passed in through the constructer and create an reference variable for it in. This way you can access your MainProgram class in your listeners class.
EventListeners class:
//Change
MainProgram MainCode = new MainProgram();
//to
MainProgram MainCode;
public EventListeners(MainProgram plugin) {
//Add this
this.MainCode = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
Also remove the static modifier from CanRestart.
You're creating another instance of your plugin's main class with new MainProgram(), which is not necessary in order to access variables in the original instance of the main class created when the plugin is first loaded, especially if the variables you are trying to access are static and thus don't belong to only a specific object. Since the CanRestart boolean is public and static, you can use just MainProgram.CanRestart to access that boolean. If the variable were however not static and therefore an "instance variable" (where each object has their own copy of a variable), then you'd need to add a reference to the original main class (not a new instance) in the listener so you could access variables/methods from the main class in the listener class.
//Example 1:
package com.practice;
import java.util.ArrayList;
public class Testing1{
public Testing1()
{
super();
}
public ArrayList getFruits()
{
Arraylist <fruits> = new ArrayList <fruits>();
fruits.add("Orange");
fruits.add("Apple");
fruits.add("grape");
return fruits;
}
}
//Example 2:
package com.practice;
import java.util.ArrayList;
import java.util.List;
public class Testing1{
public Testing1()
{
super();
}
public List getFruits()
{
List <fruits> = new ArrayList<fruits>();
fruits.add("Orange");
fruits.add("Apple");
fruits.add("grape");
return fruits;
}
}
//I made typos on my original code
//contain mycontain; should have been a package name. I corrected that as //well.
//Corrected import java.util.Array.List; to import java.util.Array.List;
//I tried adding a string after List and ArrayList and still does not work //well
//I still don't understand.
//No, this is not a school assignment
//Maybe some can explain which one is correct or the two examples or both //need work? Thank you.
//
All programs need a main method. So no.
Ok, I am trying to attach data to a Minecraft Bukkit ItemStack. I would like it so the entity that it drops would also have it, but that is optional. If I can not do this directly, is there some other way I can keep a piece of data (java int, java string) with the item as it moves through players and their inventory slots? Thanks!
EDIT: Here's a code example.
package path.to.the.package;
import org.bukkit.event.*;
import org.bukkit.event.PlayerInteractEvent;
import org.bukkit.plugin.java.JavaPlugin;
public ExamplePlugin extends JavaPlugin
{
public List<ItemStack> stacks = new ArrayList<ItemStack>();
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args)
{
if(cmd.getName().equalsIgnoreCase("tester123"))
{
ItemStack stack = new ItemStack(272, 0, (byte)0);
Player p = (Player)sender;
stacks.add(stack);
p.getLocation().getWorld().dropItem(player.getLocation(), stack);
}
return true;
}
#EventHandler(priority = EventPriority.HIGHEST)
public void onItemStackRightClick(PlayerInteractEvent e)
{
Player player = e.getPlayer();
for(ItemStack item : items)
{
if(player.getItemInHand() == item)
{
//What I DO want is something like: if(item.getPluginData(this, "KEY") == "SPECIAL")
//And I would have set it like: item.setPluginData(this, "KEY", "SPECIAL");
player.sendMessage("You got one of our SPECIAL stone swords!!!!");
}
}
}
}
I whipped up this example but it does not work when I right click with the one special sword.
I would use ItemStack.getItemMeta() to set the lore value:
import java.util.ArrayList;
import java.util.List;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.*;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.java.JavaPlugin;
public class ExamplePlugin extends JavaPlugin
{
public List<ItemStack> stacks = new ArrayList<ItemStack>();
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args)
{
if(cmd.getName().equalsIgnoreCase("tester123"))
{
ItemStack stack = new ItemStack(272, 0, (byte)0);
Player p = (Player)sender;
stacks.add(stack);
ItemMeta i = stack.getItemMeta();
List<String> lore = new ArrayList<String>();
lore.add("Special");
i.setLore(lore);
p.getLocation().getWorld().dropItem(((Player)sender).getLocation(), stack);
}
return true;
}
#EventHandler(priority = EventPriority.HIGHEST)
public void onItemStackRightClick(PlayerInteractEvent e)
{
Player player = e.getPlayer();
if(player.getItemInHand().getItemMeta().hasLore())
{
if (player.getItemInHand().getItemMeta().getLore().get(0).equals("Special"))
{
player.sendMessage("You got one of our SPECIAL stone swords!!!!");
}
}
}
}
There is the http://jd.bukkit.org/apidocs/org/bukkit/metadata/Metadatable.html where you can store your data in a key-value way. Looks like it already provides an interface to store/retrieve data.
If you want to store invisible data (insteed of lore), just use metadata :
Good article from Samer Alsayegh -> http://sameralsayegh.com/how-to-use-metadata/