Is there a way to attach data to a Bukkit ItemStack? - java

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/

Related

Can I use the original class as a type and still use its subclasses?

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();

JAVA/SPIGOT: How can I make a variable called from non static classes?

I'm very new with Java and was introduced to it by creating Minecraft plugins. I am currently using Spigot and want a variable to be accessed through another class. In this plugin, I want players to be able to create a Hero that has certain abilities. The two classes that I use are below.
package me.placerwiz;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
public class Moba extends JavaPlugin {
StompCooldown a;
#Override
public void onEnable() {
getServer().getPluginManager().registerEvents(new MenuClick(this), this);
new PlayerListener(this);
new StompAbility(this);
getLogger().info("This plugin has been enabled!");
a = new StompCooldown(this);
a.runTaskTimer(this, 20, 20);
getCommand("pearl").setExecutor(new WarpAbility());
getCommand("menu").setExecutor(this);
}
#Override
public void onDisable() {
}
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (cmd.getName().equalsIgnoreCase("Menu") && sender instanceof Player) {
Player player = (Player) sender;
player.openInventory(Menu.getMenu());
return true;
}
return false;
}
public static void sircunningham1_1(String args[]) {
SirCunningham_1_1 getLoadout = new SirCunningham_1_1();
getLoadout.heroChosen();
}
public static void sircunningham2_1(String args[]) {
SirCunningham_2_1 getLoadout = new SirCunningham_2_1();
getLoadout.heroChosen();
}
public void gotHero(String heroChoice) {
if (heroChoice == "") {
}
}
public boolean heroTest(CommandSender sender, Command cmd, String label, String[] args) {
if (cmd.getName().equalsIgnoreCase("hero") && sender instanceof Player) {
Player player = (Player) sender;
player.openInventory(Menu.getMenu());
return true;
}
return false;
}}
The code above is my main class, Moba. In this code, a variable called heroChoice is received from the other class. The only problem from this is that I want the code to get what the player has selected as the hero. When it gets the hero, I want it to get the hero that the player has selected. Is there anyway I can get a variable sent to the Moba class after the player clicks on the final inventory item. It might need to use this class where the player selects the final ability for the hero "Sir Cunningham". (See code below)
package me.placerwiz;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
public class SirCunningham_2_1{
static String hero;
public static Inventory getMenu(){
Inventory inv = Bukkit.createInventory(null, 18, ChatColor.GREEN + ChatColor.BOLD.toString() + "Choose ultimate ability!");
ItemStack item = new ItemStack(Material.IRON_BOOTS);
ItemMeta meta = item.getItemMeta();
List<String> lore = new ArrayList<String>();
lore.add(" ");
lore.add(ChatColor.YELLOW + "Thoughts of glory inspire your team to");
lore.add(ChatColor.YELLOW + " win this battle! Everyone on your team");
lore.add(ChatColor.YELLOW + " gains a buff!");
meta.setLore(lore);
meta.setDisplayName(ChatColor.GOLD + ChatColor.BOLD.toString() + "Glory");
item.setItemMeta(meta);
inv.addItem(item);
return inv;
}
#EventHandler
public static void onClick(InventoryClickEvent event) {
if (!ChatColor.stripColor(event.getInventory().getName()).equalsIgnoreCase("Choose ultimate ability!"))
return;
Player player = (Player) event.getWhoClicked();
event.setCancelled(true);
if(event.getCurrentItem()==null || event.getCurrentItem().getType()==Material.AIR || !event.getCurrentItem().hasItemMeta()){
player.closeInventory();
return;
}
if(event.getCurrentItem().getType() == Material.IRON_BOOTS){
player.closeInventory();
String hero = "SirCunnigham_2_1";
player.openInventory(Customizer.getMenu());
}
else{
player.sendMessage(ChatColor.GREEN + "[" + ChatColor.YELLOW + "MOBA" + ChatColor.GREEN + "]" + ChatColor.GOLD + "-Under Construction-");
player.closeInventory();
}
}
public static void heroChosen(){
String heroChoice = hero;
Moba sendLoadout = new Moba();
sendLoadout.gotHero(heroChoice);
}
}
All I need to get this to work is to have the String hero (from the if event above) to equal the String heroChoice. Thanks for reading this far and I hope this will get solved. It means a lot to me!
Do not "hide" a variable! You have a static variable named "hero" of type String but you have created another one with the same type and the same name of the static one. So you want to get the name of the hero.
Declaring that variable static you make that variable equal to all of the instances of that class.
Keep reading if you want to know the real solution.
Note, using OOP (Object-Oriented Programming) is a more efficient way to do this.
From what I understood from the question, you want associate an hero name to a player.
You can simply do it with an HashMap.
public static HashMap<Player,String> playerHero = new HashMap<Player,String>();
or if you're using Java 8
public static HashMap<Player,String> playerHero = new HashMap<>();
To add a player AND a hero name do
MyClass.playerHero.put(player, heroName);
To get the heroName from the player:
MyClass.playerHero.get(player);
To get the players from the heroName:
You can make a method:
public static List<Player> getPlayers(String heroName){
List<Player> players = new ArrayList<Player>();
for(Map.Entry<Player,String> e : MyClass.playerHero.entrySet()){
if(e.getValue().equalsIgnoreCase(heroName)){
players.add(e.getKey());
}
}
return players;
}
All these variables are static, so we can access them with MyClass.variableName
All these methods are static, so we can access them with MyClass.method(parameters);
Hope this helped!
You could use the static modifier for heroChoice and all methods that work with your variable, but this is not best practice because in many cases you will not be able to use static and even for this case, you can't make the Bukkit API's EventHandlers static. So what do you do? Its simple.
Use OOP, pass instance of invoking object's variable through constructor
Every object can have constructors, the constructors contain code that will be run when an instance of that object is created. You can also pass paremters to a constructor just like you would a method. As a result, you can simply pass the variable you want from one class into the constructor of the other and store it. For example:
class Car { //my class Car
double topSpeedMPH; //when a Car is created, it needs to get a top speed
public Car(double topSpeedMPH) { //public constructor for Car, requires a double parameter
this.topSpeedMPH = topSpeedMPH; //set the class' topSpeedMPH variable to the local one
}
}
Then in the invoking code:
double speed = 10;
Car fordFusion = new Car(speed);
So for your code specifically:
class Moba {
String heroChoice; //Moba has heroChoice stored
public Moba(String choice) { //Moba constructor, requires a String (which is the choice)
this.heroChoice = choice; //stores the parameter String to use later
}
}
class SirCunningham_2_1 {
public void heroChosen(){
String heroChoice = hero;
Moba sendLoadout = new Moba(heroChoice);
sendLoadout.gotHero(heroChoice);
}
}
Another solution: Use OOP, pass instance of the entire invoking object through constructor using this keyword
The previous solution is great for just one variable, but what if I wanted to be able to access multiple variables from another object? It would be rather inconvenient to make each of them individual parameters. Luckily, there is a good way to do this. Simply pass the entire instance through. The following example (using Car again) shows it:
class Motor {
Car myCar;
double topSpeed;
double accel;
public Motor(Car c) { //require instance of car
this.myCar = c;
this.topSpeed = myCar.topSpeed; //get values from instance
this.accel = myCar.secondsTo60;
}
}
class Car {
Motor m;
double topSpeed = 108;
double secondsTo60 = 8;
int seats = 4;
public Car() {
m = new Motor(this); //use this keyword to pass entire instance
}
void startEngine() {
System.out.println("Vroom Vroom!");
}
}
A big advantage to this solution is that I could even use methods from the other class:
public Motor(Car c) { //require instance of car
this.myCar = c;
this.topSpeed = myCar.topSpeed; //get values from instance
this.accel = myCar.secondsTo60;
myCar.startEngine();
}

Make an Apple give you Experience?? | Minecraft Forge Modding 1.7.10

Hello people of the internet, I would like to know if there was a way to make a custom food item give you XP. I am in the middle of making a mod and would like "SimonApple" To give me XP. Please let me know if there is a way to do this.
package com.notsimon.blocksplus;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.block.Block;
import net.minecraft.block.material.MapColor;
import net.minecraft.block.material.Material;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraft.item.ItemFood;
import net.minecraft.item.ItemStack;
#Mod(modid = "ep", name = "Experience Plus", version = "1.0")
public class ExperiencePlus {
public static Item SimonApple;
public static Item MagentaDust;
public static Block MagentaOre;
public static Block MagentaBlock;
#EventHandler
public void preInit(FMLPreInitializationEvent event) {
//Item/Block init and registering
//Config handling
//X * 0.5 = 20 Hunger
SimonApple = new ItemFood(10, 0.5F, false).setUnlocalizedName("SimonApple").setTextureName("bp:SimonApple").setCreativeTab(tabBlocksPlus);
MagentaOre = new BlockTable(Material.iron).setBlockName("MagentaOre").setBlockTextureName("bp:MagentaOre").setCreativeTab(tabBlocksPlus);
MagentaDust = new ItemTable().setUnlocalizedName("MagentaDust").setTextureName("bp:MagentaDust").setCreativeTab(tabBlocksPlus);
MagentaBlock = new MagentaBlock(Material.iron).setBlockName("MagentaBlock").setBlockTextureName("bp:MagentaBlock").setCreativeTab(tabBlocksPlus);
//item.itemTable and substring(5) removes "item."
GameRegistry.registerItem(SimonApple, SimonApple.getUnlocalizedName().substring(5));
GameRegistry.registerBlock(MagentaOre, MagentaOre.getUnlocalizedName().substring(5));
GameRegistry.registerItem(MagentaDust, MagentaDust.getUnlocalizedName().substring(5));
GameRegistry.registerBlock(MagentaBlock, MagentaBlock.getUnlocalizedName().substring(5));
GameRegistry.registerWorldGenerator(new OreGeneration(), 0);
}
#EventHandler
public void init(FMLInitializationEvent event) {
//Proxy, TileEntity, entity, GUI and Packet Registering
GameRegistry.addRecipe(new ItemStack(SimonApple, 2), new Object[]{"MMM","MBM","MMM", 'M', ExperiencePlus.MagentaDust, 'B', ExperiencePlus.MagentaBlock});
GameRegistry.addRecipe(new ItemStack(MagentaBlock), new Object[] {"MMM", "MMM", "MMM",'M', ExperiencePlus.MagentaDust});
}
#EventHandler
public void postInit(FMLPostInitializationEvent event) {
}
public static CreativeTabs tabBlocksPlus = new CreativeTabs("tabBlocksPlus"){
#Override
public Item getTabIconItem() {
return new ItemStack(MagentaOre).getItem();
}
};
}
You can't edit the current apple item in the game, you would have to create your own one as a forge mod item, which seems like what oyu have done. To make an item give XP, you use this:
player.addExperienceLevel(1); //player is an EntityPlayer or an EntityPlayerMP
SimonApple Item Class
This is what the item class for the SimonApple would look like (without imports):
public class SimonApple extends ItemFood {
private static final int LevelsToAdd = 10; //just an example number; play around with it
public SimonApple(String unlocalizedName, int healAmount, float saturationModifier, boolean wolvesFavorite, CreativeTab creativeTab) {
super(healAmount, saturationModifier, wolvesFavorite);
this.setUnlocalizedName(unlocalizedName);
this.setTextureName(Main.MODID + ":" + unlocalizedName);
this.setCreativeTab(creativeTab);
}
#Override
protected void onFoodEaten(ItemStack stack, World world, EntityPlayer player) {
super.onFoodEaten(stack, world, player);
player.addExperienceLevel(LevelsToAdd);
}
}
Changing Variables in the ExperiencePlus Class
You would need to change this:
public static Item SimonApple;
To something around the lines of this:
public static Item simonApple;
And you would need to change this:
SimonApple = new ItemFood(10, 0.5F, false).setUnlocalizedName("SimonApple").setTextureName("bp:SimonApple").setCreativeTab(tabBlocksPlus);
To just this:
simonApple = new SimonApple("SimonApple", 10, .5f, false, tabBlocksPlus);
NOTE: 10 should be the heal amount, and .5f should be the saturation amount (see table here)
Either create a new item as Abob78 suggests, or create an eventHandler that subscribes to the PlayerUseItem event to be triggered at the Finish state.
To limit the items that that trigger it, you'll have to look at using the itemstack NBT data to store a flag to identify "simon apples" from regular apples. this can be something as simple as a boolean flag such as "isSimonApple"
From the event, you should be able to extract an EntityLiving reference that can be cast to a player reference.
Then either augment the triggering player's XP or spawn XP orbs at their location.

Minecraft Bukkit: How can I access properties/methods in another class from the main class?

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.

Getting an inventory in another if statement

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

Categories