Server won't give ItemStack when a Player joins - java

I have created an ItemStack which should be given to players when they join, but it doesn't work as expected.
Here is my attempt:
public class Main extends JavaPlugin implements Listener{
public void onEnable(){
Bukkit.getServer().getPluginManager().registerEvents(this, this);
registerListeners();
}
private void registerListeners() {
PluginManager pm = Bukkit.getPluginManager();
}
public static void giveItems(Player p) {
}
#EventHandler
public void onPlayerJoin(PlayerJoinEvent e) {
Player p = e.getPlayer();
ItemStack t = new ItemStack(Material.TNT, 1);
ItemMeta tmeta = t.getItemMeta();
tmeta.setDisplayName("§cTNT §7(Right click to use)");
t.setItemMeta(tmeta);
for(Player pl : Bukkit.getOnlinePlayers()){
p.getInventory().setItem(4, t);
p.getInventory().addItem(t);
}
}
#SuppressWarnings("deprecation")
#EventHandler
public void onRightClick(PlayerInteractEvent e) {
if(e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK) {
if(e.getItem() != null && e.getItem().getType() == Material.TNT) {
Player p = e.getPlayer();
TNTPrimed tnt = (TNTPrimed) p.getWorld().spawn(p.getLocation(), TNTPrimed.class);
tnt.setVelocity(p.getLocation().getDirection().normalize().multiply(1));
p.updateInventory();
And it failed.
How can I successfully give ItemStacks to Players when they join the server?

Uh, why are you looping through all players in the server when you already have the player you want to give the item to in the variable p? You're also not using proper chat color codes.
Use this instead:
// Imports and other code here...
#EventHandler
public void onPlayerJoin(PlayerJoinEvent e){
Player p = e.getPlayer();
ItemStack t = new ItemStack(Material.TNT);
ItemMeta tmeta = t.getItemMeta();
tmeta.setDisplayName(ChatColor.RED + "TNT " + ChatColor.GRAY + "(Right click to use)");
t.setItemMeta(tmeta);
p.getInventory().addItem(t);
}
Other than that, I don't see anything wrong with your setup.

Looking into your code the following mistakes should be corrected:
Remove the useless method registerLiteners() and all of its calls. The method doesn't really do anything.
You should not interate all online players to add the ItemStack to your Player.
Second of all: from your question, what I can understand as your situation is: you want a player to join the server and receive an item for that. The way you're handling it is that everytime a player joins the server, he will get items added to his inventory for every player online in the server. The situation you're probably in is that you're testing the plugin on your own, and there is no player online when you join, what leads to no items being given.
All things considered, the correct way to get your intended behaviour should be the following:
#EventHandler
public void onPlayerJoin(PlayerJoinEvent e) {
Player joined = e.getPlayer();
ItemStack itemToAdd = new ItemStack(Material.TNT);
ItemMeta stackMeta = itemToAdd.getItemMeta();
stackMeta.setDisplayName(ChatColor.RED + "TNT " + ChatColor.GRAY + "(Right click to use)"); //Using ChatColor is recommended over § character.
itemToAdd.setItemMeta(stackMeta);
joined.getInventory().addItem(itemToAdd);
}
The event will add your custom itemstack to the player's inventory after he joins the server.
It's also important to point out that, although it's not part of your question, your PlayerInteractEvent should be fixed to only listen to your custom ItemStack. It will be fired with any TnT held.

Related

Trying to get getView().getTitle() to work

I was first using only getTitle() for this but then found you need to use getView() as well. So i did but I stil can't get it to work.
FYI This is the error :
Cannot resolve method 'getView' in 'Inventory'
I tried changing getInventory() for InventoryView() but still the same error but also the Cannot resolve method 'InventoryView' in 'Chest' error so this means I cant get the inventory view from a block?
#EventHandler
public void onInteract(PlayerInteractEvent e) {
Action a = e.getAction();
Player p = e.getPlayer();
ItemStack hand = e.getItem();
Block clicked = e.getClickedBlock();
if (a != Action.PHYSICAL) {
assert clicked != null;
if(clicked.getType() == Material.CHEST){
hand.getType();
Chest chest = (Chest) clicked.getState();
Inventory inv = chest.getInventory();
if(inv.getView().getTitle().equalsIgnoreCase("Test")) {
p.sendMessage("Event triggered");
e.setCancelled(true);
}
}
}
}
I have figured it out after searching on around 100 sites I found a solution that works, I don't know if it's the best solution but good for me.
I changed the whole event to use InventoryOpenEvent insted of PlayerInteractEvent.
Here is the full code :
#EventHandler
public void onInventoryOpen(InventoryOpenEvent e) {
Player player = (Player) e.getPlayer();
if (e.getView().getTitle().equals("Test")) {
e.setCancelled(true);
player.sendMessage("Succesfull");
}
}
Here is the code stripped down :
#EventHandler
public void onInventoryOpen(InventoryOpenEvent e) {
if (e.getView().getTitle().equals("Test")) {
e.setCancelled(true);
}
}

How to make a List<Entity> on a variable with a cast

so I am trying to make a Minecraft plugin that listens to the configuration file for input of which mobs to not target players. Here is what I have so far
public class ZombieListener implements Listener {
private final List<String> entities;
public ZombieListener(List<String> entities){
this.entities = entities;
}
#EventHandler
public void onEntityTargetEvent(EntityTargetLivingEntityEvent event) {
if (event.getTarget() event.getTarget() instanceof Player ) {
final Player targeted = (Player) event.getTarget();
if (targeted.hasPermission("dont.target.me") && entities.contains(targeted)){
event.setCancelled(true);
}
}
}
}
I realise that I can't check for an entity from an object and therefore I need to make targeted a List. How should I do this?
The other answer is way more complex than it needs to be. Try to do this instead:
public class ZombieListener implements Listener {
private final List<String> entities;
public ZombieListener(List<String> entities){
this.entities = entities;
}
#EventHandler
public void onEntityTargetEvent(EntityTargetLivingEntityEvent event) {
if (event.getTarget() instanceof Player && entities.contains(event.getEntityType().getName())) {
final Player targeted = (Player) event.getTarget();
if (targeted.hasPermission("dont.target.me") && entities.contains(targeted)) {
event.setCancelled(true);
}
}
}
}
All I did was add a small bit of code in the first if-statement:
entities.contains(event.getEntityType().getName())
This makes it so the application checks if the entity is one of the affected types, and carries on with the listener accordingly.
Hope this helps!
Use the entity class instead.
For example I created a mod that caused animals to age over time, making them die (they also would breed on their own). In order to allow the config to determine how quickly animals aged, I used the animal class:
private Class species;
private Entity entity;
public EntityAIAging(Random random, EntityAnimal ent, Class spec, EntityAgeTracker ageTracker) {
species = spec;
entity = ent;
//...
}
public void updateTask() {
// Both of these function the same:
// Unaging animals do not age, do not die, and do not procreate
if(HardLibAPI.animalManager.isUnaging(species)) {
return;
}
if(HardLibAPI.animalManager.isUnaging(entity.getClass())) {
return;
}
//...
}
So what you'd want to do is call entity.getClass() and check if it exists within a List<Class> entities. If you want to see how I parsed a config file to locate classes, you can see that code here. Its complicated and has some additional logic to handle minor misspellings.

I want to check if my player holds a specific item upon entering a room

I'm making the "World of Zuul" text based adventure game right now, and I would like to make it so that upon entering a room it will check if my player holds a specific item in the inventory. This is what I have so far for inventory code (Player class):
/**
* Gets an item from the inventory
*/
public Item getInventoryItem(String itemName)
{
Item item = inventory.get(itemName);
currentWeight -= item.itemWeight();
inventory.remove(itemName);
return item;
}
/**
* Lists all the items currently in the inventory
*/
public String listInventory()
{
String itemList = "";
for(String key : inventory.keySet())
{
String item = inventory.get(key).showName();
itemList += " -" + item;
}
return "Your inventory contains \n" + itemList;
}
/**
* Adds an item to the inventory
*/
public void addItemToInventory(String itemName, Item item)
{
if(item.itemWeight() + currentWeight <maxWeightInv)
{
inventory.put(itemName, item);
currentWeight += item.itemWeight();
System.out.println(itemName + " was added to your inventory.");
}
else
{
System.out.println("You can't carry this");
}
}
So I'm honestly wondering how I could make it so that it first checks if a player has a specific item in the inventory (in this case it would be a sword) before entering a room. I have not really tried something yet since I don't really know how to start (Game class):
/**
* Exceptions upon entering Room15
*/
private void Room15()
{
player.getInventoryItem("Sword");
if(inventory.contains("Sword"))
{
System.out.println("Congratulations! You won the game and your freedom!");
}
else {
System.out.println("Hurry back and find a sword!!!");
}
}
I hope I have given enough info about what exactly I would like to accomplish. I just need a way of checking if the player holds an item. I can pretty much finish the rest on my own.
You could add a method like this in your Player class:
public boolean hasItemInInventory(String itemName)
{
return inventory.containsKey(itemName);
}
Then you could modify your Game class method:
private void Room15()
{
if(player.hasItemInInventory("Sword"))
{
System.out.println("Congratulations! You won the game and your freedom!");
}
else {
System.out.println("Hurry back and find a sword!!!");
}
}

ItemMeta - command and listener

How can I use itemmeta in another class?
public class Kart implements CommandExecutor {
#Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
Player p = (Player) sender;
if (label.equalsIgnoreCase("kart")) {
if (p.hasPermission("teamenders.komut.kart")) {
ItemStack kart = new ItemStack(Material.PAPER);
ItemMeta kartM = kart.getItemMeta();
ArrayList<String> tt = new ArrayList<String>();
kartM.setDisplayName(ChatColor.DARK_AQUA + "Yetki Karti");
tt.add(ChatColor.DARK_GREEN + "Giris Yetkisi");
kartM.setLore(tt);
kart.setItemMeta(kartM);
p.getInventory().addItem(new ItemStack(kart));
} else {
p.sendMessage(ChatColor.DARK_RED + "Yetersiz Yetki!!!!!");
}
}
return false;
}
}
My 2nd class:
#EventHandler
public void onPInteract(PlayerInteractEvent e) {
Player p = e.getPlayer();
if (e.getAction() == Action.RIGHT_CLICK_AIR) {
if (p.getItemInHand().getType() == Material.PAPER && p.getItemInHand().hasItemMeta()) {
p.sendMessage(ChatColor.DARK_AQUA + "Yetkiyi aldin.");
}
}
}
I want use first class itemmeta in 2nd class "p.getItemInHand"
Store it using an ArrayList outside of your Kart class, then retrieve the data in your EventHandler.
In your first class, create a global variable (outside any function) and store the value of kart.getItemMeta().
Still in your first class, create a function that returns this variable.
In your second class, create another global variable Kart kart and create a function public *nameOfYourClass*(Kart kart){this.kart = kart}. You should then be able to do kart.*functionOfFirstStep*.
Please tell me if I wasn't clear enough.

How do I declare a projectile and cancel the damage from it with this event code in Bukkit

I need to know how to declare a projectile inside the if statement using the getCause() conditional.
Then, I need to know how to cancel the damage from that projectile if the players are in the same gang.
Please give me an explanation on how to do with along with some example code please!
Here is my event.
#EventHandler
public void onEntityDamage(EntityDamageByEntityEvent event){
if(event.getEntity() instanceof Player){
Player damaged = (Player) event.getEntity();
String DUUID = damaged.getUniqueId().toString().toLowerCase();
if(event.getCause() == DamageCause.PROJECTILE){
//I NEED THE CODE TO PUT IN HERE
}
if(event.getDamager() instanceof Player){
Player damager = (Player) event.getDamager();
String DRUUID = damager.getUniqueId().toString().toLowerCase();
if(MinecraftGTA.config.getString(DRUUID + ".Gang").equalsIgnoreCase(MinecraftGTA.config.getString(DUUID + ".Gang"))){
event.setCancelled(true);
}
}
}
}
EntityDamageByEntityEvent has a method public Entity getDamager(), and there's an interface Projectile extends Entity, I should imagine that calling getDamager() when the cause is DamageCause.PROJECTILE will be the Projectile Entity.
As for cancelling it, I'm not certain but there are some methods which sound promising; Entity#remove(), EntityDamageEvent#setDamage(double), or event.setCancelled(true); as you use later in your code.
When you fire the projectile, you should save the UUID of it in a HashMap.
As an example, we'll use a SnowBall as our projectile:
public Map<String, String> projectileUUID = new HashMap<String, String>
public void launch(Player p){//call this to launch the projectile
String uuid = p.launchProjectile(Snowball.class).getUniqueId().toString(); //launch a snowball & get the UUID
projectileUUID.put(uuid, p.getName());//put the UUID of the projectile in the map
}
Then on entity damage event, check if the shooter & the damaged player are in the same gang:
#EventHandler
public void entityDamage(EntityDamageByEntityEvent e){
if(e.getDamager() instanceof SnowBall && e.getEntity() instanceof Player){//make sure the damager is a snowball & the damaged entity is a Player
String uuid = ((SnowBall) e.getDamager()).getUniqueId().toString(); //get the UUID of the snowball
if(projectileUUID.contains(uuid)){//check if our HashMap contains the UUID
String damaged = ((Player) e.getEntity()).getName(); //get the damaged player's name
String shooter = projectileUUID.get(uuid); //get the shooter's name
if(getGang(shooter).equals(getGang(damaged)){//check if the two player's gangs are the same here
e.setCancelled(true); //cancel the event
}
}
}
}
You could always change the snowball to something else like an arrow... Just make sure to change all of the SnowBall related code to be whatever projectile you're using.
Not sure how much has changed, but if you want the player, you should be able to get it from the entity object.
I.e.
#EventHandler
public void entityDamage(EntityDamageByEntityEvent e){
if(e.getDamager() instanceof Projectile && e.getEntity() instanceof Player){
//make sure the damager is a snowball & the damaged entity is a Player
ProjectileSource shooter = ((Projectile) event.getDamager()).getShooter();
if (!(shooter instanceof Player)) {
return;
}
// compare shooter and entity here...
if (isSameGang((Player) shooter, (Player) e.getEntity()) {
e.setCancelled(true); // cancel damage
}
}
}

Categories