Bukkit create 2 Instances of the same item

39 Views Asked by At

When I use for the first time my item (flame launcher), it works perfectly. But if I give to myself another flame launcher, it seems like that it takes the other one's properties. How can I create 2 separate instances in this context ?

package fr.laponie.ShooterPlugin;

import java.util.Arrays;
import java.util.List;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
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.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;

import net.minecraft.server.v1_8_R3.EnumParticle;
import net.minecraft.server.v1_8_R3.PacketPlayOutWorldParticles;

public class FlameLauncher implements Weapon, Listener {
    
    public FlameLauncher() {
        ItemStack is = new ItemStack(Material.GOLD_BARDING);
        ItemMeta im = is.getItemMeta();
        
        im.setDisplayName("FLAME LAUNCHER [" + ChatColor.GREEN + "▪ ▪ ▪ ▪ ▪" + ChatColor.WHITE + "]");
        List<String> lore = Arrays.asList("This Weapon","produces flames, igniting","the target");
        im.setLore(lore);
        
        is.setItemMeta(im);
        
        this.level = 1;
        this.mat = is;
        this.fuel = 10.0;
    }
    
    
    @EventHandler
    public void onRightClickWeapon(PlayerInteractEvent e) {
        Player p = e.getPlayer();
        Action action = e.getAction();
        
        ItemStack field = this.mat;
        
        ItemStack hand = p.getItemInHand();
        
        
        Location playerEyeLoc = p.getEyeLocation();
        Vector director = p.getEyeLocation().getDirection();
        
        
        if (action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK) {
            if (hand.getType() == field.getType() && hand.getItemMeta().getLore().equals(field.getItemMeta().getLore())) {
                
                if (this.getFuel() > 0) {
                    
                    this.fuel -= 1;
                    this.setFuel(fuel);
                    
                    this.updateColorAccordingToFuel(this.fuel);
                    hand.setItemMeta(this.mat.getItemMeta());
                    
                    EnumParticle particle = EnumParticle.FLAME;
                
                    Location ploc = playerEyeLoc.add(director);
                    PacketPlayOutWorldParticles packet = new PacketPlayOutWorldParticles(particle, false, (float) ploc.getX(),
                        (float) ploc.getY(), (float) ploc.getZ(),0,0,0,0,5, null);
                
                    CraftPlayer cp = (CraftPlayer) p;
                    cp.getHandle().playerConnection.sendPacket(packet);
                
                }
            }
        }
    }
    
    public double getFuel() {
        return this.fuel;
    }
    
    public void setFuel(double newFuel) {
        this.fuel = newFuel;
    }

    @Override
    public double getDamage() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void setDamage(double dp) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public Material getMCMaterial() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setMCMaterial(Material m) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public double getReloadTime() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void setReloadTime(double reloadTime) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public int getAmmoNb() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void setAmmoNb(int ammo) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void onAmmoHitEntity(AmmoHitPlayerEvent event) {
        // TODO Auto-generated method stub
        
    }
    
    void updateColorAccordingToFuel(double fuel) {
        
        ItemStack clone = this.mat.clone();
        ItemMeta cloneM = clone.getItemMeta();
        
        if (fuel >= 8.0) {
            cloneM.setDisplayName("FLAME LAUNCHER [" + ChatColor.GREEN + "▪ ▪ ▪ ▪ ▪" + ChatColor.WHITE +"]");
            this.mat.setItemMeta(cloneM);
            
        } else if (fuel >= 6.0) {
            cloneM.setDisplayName("FLAME LAUNCHER ["  + ChatColor.GREEN + "▪ ▪ ▪ ▪" + ChatColor.WHITE + " ▪]");
            this.mat.setItemMeta(cloneM);
            
        } else if (fuel >= 4.0) {
            cloneM.setDisplayName("FLAME LAUNCHER [" + ChatColor.GREEN + "▪ ▪ ▪" + ChatColor.WHITE + " ▪ ▪]");
            this.mat.setItemMeta(cloneM);
            
        } else if (fuel >= 2.0) {
            cloneM.setDisplayName("FLAME LAUNCHER [" + ChatColor.GREEN + "▪ ▪" + ChatColor.WHITE +" ▪ ▪ ▪]");
            this.mat.setItemMeta(cloneM);
            
        } else if (fuel > 0) {
            cloneM.setDisplayName("FLAME LAUNCHER [" + ChatColor.GREEN + "▪" + ChatColor.WHITE +" ▪ ▪ ▪ ▪]");
            this.mat.setItemMeta(cloneM);
        } else {
            cloneM.setDisplayName("FLAME LAUNCHER [▪ ▪ ▪ ▪ ▪]");
            this.mat.setItemMeta(cloneM);
        }
    }
    
    int level;
    ItemStack mat;
    double damage, fuel;
    
}

As you can see, when the player right clicks, it consumes 'fuel' I've realised when debugging that when I use the second flame launcher, fuel is set to 0.0, so I understand that the problem is in the 'if (this.getFuel > 0)' line, but I really don't know how to properly solve it.

1

There are 1 best solutions below

3
Elikill58 On

You declared one listener, so one object, and it's the same for all users. Here, the issue comes because there is no way to make the value for each player.

You should create an external object that will contains informations according to player. For example:

public class FlamePlayer {

   private Player p;
   private int fuel, level;

   public FlamePlayer(Player p) {
       this.p = p;
   }

   public Player getPlayer() {
      return p;
   }

   public int getFuel() {
      return fuel;
   }

   public void reduceFuel() {
      this.fuel--;
   }

   public void getFuel(int fuel) {
      this.fuel = fuel;
   }

   public int getLevel() {
      return level;
   }
}

Then, you have to save this object into like an hashmap. And change everything to use this. Example :


private static final HashMap<Player, FlamePlayer> FLAME_PLAYERS = new HashMap<>();
public static FlamePlayer getOrCreate(Player p) {
   return FLAME_PLAYERS.computeIfAbsent(p, FlamePlayer::new); // get object or create a new one that put into map
}

@EventHandler
public void onRightClickWeapon(PlayerInteractEvent e) {
    Player p = e.getPlayer();
    Action action = e.getAction();
    
    ItemStack field = this.mat;
    
    ItemStack hand = p.getItemInHand();
    
    Location playerEyeLoc = p.getEyeLocation();
    Vector director = p.getEyeLocation().getDirection();
    
    if (action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK) {
        if (hand.getType() == field.getType() && hand.getItemMeta().getLore().equals(field.getItemMeta().getLore())) {
            FlamePlayer fp = getOrCreate(p); // get the object
            if (fp.getFuel() > 0) {
                
                fp.reduceFuel();
                
                // for example, here you need to put the method 'updateColorAccordingToFuel' into FlamePlayer
                this.updateColorAccordingToFuel(this.fuel);
                hand.setItemMeta(this.mat.getItemMeta());
                
                EnumParticle particle = EnumParticle.FLAME;
            
                Location ploc = playerEyeLoc.add(director);
                PacketPlayOutWorldParticles packet = new PacketPlayOutWorldParticles(particle, false, (float) ploc.getX(),
                    (float) ploc.getY(), (float) ploc.getZ(),0,0,0,0,5, null);
            
                CraftPlayer cp = (CraftPlayer) p;
                cp.getHandle().playerConnection.sendPacket(packet);
            
            }
        }
    }
}

All of this code is example that I wrote manually. Take the time to understand and use the map carefully, and put required method into the FlamePlayer.