Minecraft bukkit plugin right click item - java

I am making a plugin for a server I am developer on and I was developing a plugin!
I wanted to do commands to spawn a boss egg in by doing /boss give lvl <lvl> slime after you did the command it would give you an item that you can right click to spawn the boss in! Well like all new developers stuff doesn't always go the way you think it does. Here's my code I put in for checking if a player right click air or a block with the item SLIME_BALL in the players hand.
#EventHandler
public void onPlayerClicks(PlayerInteractEvent event) {
Player player = event.getPlayer();
Action action = event.getAction();
if (action.equals(Action.RIGHT_CLICK_AIR) || action.equals(Action.RIGHT_CLICK_BLOCK)) {
if (player.getItemInHand().getType() == Material.SLIME_BALL) {
player.sendMessage("You have right click a slime ball!");
}
}
}

Given that you are not seeing any stack traces in your logs, I would concur that your event listener is not registered. Let's say your listener class is called MyEventHandler it would be registered in onEnable() method, something similar to this
class MyPlugin extends JavaPlugin {
...
public void onEnable() {
Listener myEvtHnd = new MyEventHandler();
Bukkit.getPluginManager().registerEvents( myEvtHnd, this );
...
}
}
In general, your handler looks appropriate. PlayerInteractEvent provides a convenience method getItem() that returns the player's current item-in-hand. However, regardless of which method is used, you must check that the ItemStack returned is not null, which will happen if the player has no item in-hand.
#EventHandler
public void onPlayerClicks(PlayerInteractEvent event) {
Player player = event.getPlayer();
Action action = event.getAction();
ItemStack item = event.getItem();
if ( action.equals( Action.RIGHT_CLICK_AIR ) || action.equals( Action.RIGHT_CLICK_BLOCK ) ) {
if ( item != null && item.getType() == Material.SLIME_BALL ) {
player.sendMessage( "You have right click a slime ball!" );
}
}
}

Maybe instead of action.equals(), you can use action ==, as in:
if (action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK) {
if (player.getItemInHand().getType() == Material.SLIME_BALL) {
player.sendMessage("You have right click a slime ball!");
}
}

Related

Player Head Movement Detection Bukkit

today I'm here to ask you a question, on Minecraft in particular in the PaperMc development (Bukkit Fork) I'm trying to create the "animations" effect like the famous Hypixel lootboxes (Opening phase) so I needed know how I could identify the PlayerHeadMovement Event. I tried with
#EventHandler
public void onPlayerMove(PlayerMoveEvent e) {
System.out.println("A");
}
But it would appear not to detect head movement.
There is no event that specifically focuses on the movement of the player's head.
You can, however, on the PlayerMoveEvent get the from and to movements.
So, to see if the player's head has moved, your code could look like:
private boolean hasPlayerHeadMoved(PlayerMoveEvent e) {
Location from = e.getFrom();
Location to = e.getTo();
return from.getYaw() != to.getYaw() || from.getPitch() != to.getPitch();
}
In your event handler, you would then call the method:
#EventHandler
public void onPlayerMove(PlayerMoveEvent e) {
boolean headHasMoved = hasPlayerHeadMoved(e);
}

Healing/Damage Blocks are outputting twice?

#EventHandler
public void playerInteraction(PlayerInteractEvent event)
{
Action action = event.getAction();
Player player = event.getPlayer();
Block block = event.getClickedBlock();
if (action.equals(Action.RIGHT_CLICK_BLOCK))
{
if (block.getType().equals(Material.NETHER_WART_BLOCK))
{
player.setHealth(player.getHealth() -1);
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_HURT, 10, 1);
}
else if (block.getType().equals(Material.DIAMOND_BLOCK))
{
player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 1000, 2));
player.playSound(player.getLocation(), Sound.ENTITY_SPLASH_POTION_BREAK, 10, 1);
}
else if(block.getType().equals(Material.EMERALD_BLOCK))
{
if (player.getHealth() != 20)
{
player.setHealth(player.getHealth() + 1);
player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 10, 1);;
}
if (player.getHealth() == 20)
{
player.sendMessage(ChatColor.DARK_RED + "You are already at full health!");
}
}
}
}
For some reason, all of these things happen twice whenever I right click the designated blocks. Anyone know why? I have posted the entire method, it's a player interaction event.
Thanks :)
First of all, make sure yo haven't registered the Listener class containing the event handler twice.
If that's not the case, according to this thread on the spigot forums, since Mojang added the left hand slot to Minecraft some events like PlayerInteractEvent or InventoryClickEvent will be called twice (once for each hand).
One possible fix is to "disable" the left hand on the event handler:
#EventHandler
public void onPlayerInteraction(PlayerInteractEvent event) {
if(event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getHand() == EquipmentSlot.HAND) {
//Do something once
}
}
If you require that both hands could be used to trigger the event you could do the following:
First time the code gets executed you add the player to a list.
Before executing the code you check if the player is in the list. If it's in the list it means the code was executed once so you can skip it.
Schedule a task to remove the player from the list some ticks later.
The code could be as follows:
public class Foo implements Listener {
//An instance of the main plugin class
private MainClass plugin;
private List<UUID> playerBlacklist = new ArrayList<>();
#EventHandler
public void onPlayerInteractEvent(PlayerInteractEvent event) {
if(playerBlacklist.contains(event.getPlayer().getUniqueId)) {
return;
} else {
blacklistPlayer(event.getPlayer());
}
//Do something
}
private void blacklistPlayer(UUID uuid) {
playerBlacklist.add(uuid);
BukkitRunnable runnable = new BukkitRunnable(){
#Override
public void run() {
playerBlacklist.remove(uuid);
}
}
runnable.runTaskLaterAsynchronously(plugin, 5L);
}
}
Let me know if this solved your issue.

Inventory ClickEvent not working

When I click the Item in the Inventory, it simply does nothing and I can drag it anywhere I want. Then I re-open the inventory and the Item is back. I want the item a click (The Notify item in this case) to toggle the notify boolean and close the Inventory. Please help. It may be a stupid solution but sometimes the simple stuff can escape me. Thanks.
This is the Inventory:
public class GUI extends JavaPlugin implements Listener
{
private API api;
AlphaCommand command = new AlphaCommand();
public static Inventory inv = Bukkit.createInventory(null, 9, ChatColor.AQUA + "Alpha Config");
public static boolean isNotifyEnabled()
{
return AlphaCommand.notify;
}
protected String getCheckName()
{
return this.getCheckName();
}
public static void openGUI(Player player, Inventory inv)
{
ItemStack checks = new ItemStack(Material.DIAMOND_SWORD);
ItemStack banPlayer = new ItemStack(Material.GOLD_AXE);
ItemStack autoBan = new ItemStack(Material.DIAMOND_AXE);
ItemStack notify = new ItemStack(Material.SLIME_BALL);
ItemMeta checksMeta = checks.getItemMeta();
ItemMeta autoBanMeta = autoBan.getItemMeta();
ItemMeta notifyMeta = notify.getItemMeta();
ItemMeta banPlayerMeta = banPlayer.getItemMeta();
checksMeta.setDisplayName(ChatColor.BLUE + "Checks");
autoBanMeta.setDisplayName(ChatColor.BLUE + "AutoBan");
notifyMeta.setDisplayName(ChatColor.BLUE + "Notify");
banPlayerMeta.setDisplayName(ChatColor.BLUE + "Ban Player");
checks.setItemMeta(checksMeta);
autoBan.setItemMeta(autoBanMeta);
notify.setItemMeta(notifyMeta);
banPlayer.setItemMeta(banPlayerMeta);
inv.setItem(7, banPlayer);
inv.setItem(1, checks);
inv.setItem(3, autoBan);
inv.setItem(5, notify);
player.openInventory(inv);
}
public static void open(Player player, Inventory inv)
{
if(player instanceof Player)
{
player.openInventory(inv);
}
}
public static Inventory getGUI(){
return inv;
}
#EventHandler
public void onInventoryClick(InventoryClickEvent e)
{
Bukkit.getPluginManager().registerEvents(this, Bukkit.getPluginManager().getPlugins()[0]);
String invName = ChatColor.stripColor(e.getClickedInventory().getName());
Player player = (Player) e.getWhoClicked(); // The player that clicked the item
ItemStack clicked = e.getCurrentItem(); // The item that was clicked
#SuppressWarnings("unused")
Inventory inventory = e.getInventory(); // The inventory that was clicked in
if(invName.equalsIgnoreCase(inv.getName()))
{
if((clicked == null) || (clicked.getType() == Material.AIR) || (!clicked.hasItemMeta()))
{
player.closeInventory();
return;
}
if(clicked.getItemMeta().getDisplayName().equalsIgnoreCase("AutoBan"))
{
Configuration config = this.api.getConfiguration();
boolean autoBan = config.readBoolean("checks." + getCheckName() + ".AutoBan");
if (config.readBoolean("checks." + getCheckName() + ".AutoBan") == true)
{
autoBan = false;
e.setCancelled(true);
player.closeInventory();
return;
}
else if(autoBan == false)
{
autoBan = true;
e.setCancelled(true);
player.closeInventory();
return;
}
else
{
e.setCancelled(true);
player.closeInventory();
return;
}
}
if(clicked.getItemMeta().getDisplayName().equalsIgnoreCase("Notify"))
{
boolean notify = isNotifyEnabled();
if(notify == true)
{
notify = false;
e.setCancelled(true);
player.closeInventory();
return;
}
else if(notify == false)
{
notify = true;
e.setCancelled(true);
player.closeInventory();
return;
}
}
if(clicked.getItemMeta().getDisplayName().equalsIgnoreCase("Checks"))
{
player.sendMessage(ChatColor.RED + "This Feature is coming soon to Alpha.");
e.setCancelled(true);
player.closeInventory();
return;
}
if(e.getCurrentItem().getItemMeta().getDisplayName().equalsIgnoreCase("Ban Player"))
{
player.sendMessage("This Feature is coming soon to Alpha V.4");
e.setCancelled(true);
player.closeInventory();
return;
}else
{
player.closeInventory();
e.setCancelled(true);
return;
}
}
}
}
There seems to be multiple issues in the code that you have provided above that will cause the expected result to not be seen.
#1
Firstly you register the events for this class, inside the event itself, which means it'll never get registered unless the event get's called, which will never happen unless you register it... See the problem? So what you need to do is move the following line of code into your onEnable method.
Bukkit.getPluginManager().registerEvents(this, Bukkit.getPluginManager().getPlugins()[0]);
You need to make a few changes to this line of code. You need to replace this with a new instance of the listener object, new GUI(). It's also recommended that you register the listener with the plugin that your calling it from, but fortunately, if you put this in your onEnable, your onEnable method is inside your plugin class. This means that you can change your plugin to this. You new line of code will look like this.
Bukkit.getPluginManager().registerEvents(new GUI(), this);
Put that in your onEnable and that issue here should be resolved.
#2
The second issue is that when you're checking your item names and you're not stripping colour. This get's rid of an colours in the string. This is because your item names are ChatColor.BLUE + "AutoBan" however you're checking if it equals "AutoBan" which is different. All you need to do to fix this issue is exactly the same with what you did with the inventory name, and use ChatColor.stripColor(itemName) to get a string you can check against.
For example:
String itemName = ChatColor.stripColor(clicked.getItemMeta().getDisplayName());
if (itemName.equals("AutoBan")){
Note: I also replaced equalsIgnoreCase with equals as the cases always matched, so was an unnecessary check.

replace handleEvent(Event e) by processEvent(AWTEvent e)

I can't find a way to transform the code when replacing the deprecated functionhandleEvent withprocessEvent. can anyone help?
how to get x, y and the id of the event on processEvent?
here is my function:
public boolean handleEvent(Event evt) {
if (evt.target == this) {
// move floatting text zone
if (dragingTextZone == true) {
this.posStr.x = evt.x;
this.posStr.y = evt.y;
repaint(this.posStr.x,
this.posStr.y,
1000,
(int) (_imageViewer.getCurrent_font().getSize() * _imageViewer.getScalefactor()));
if (evt.id == Event.MOUSE_DOWN) {
dragingTextZone = false;
addTextToPicture();
}
}
if (evt.id == Event.MOUSE_DRAG) {
if (dragitem.isDragging()) {
repaint(dragitem.getX(),
dragitem.getY(),
dragitem.getWidth(),
dragitem.getHeight());
dragitem.drag(evt.x, evt.y);
repaint(dragitem.getX(),
dragitem.getY(),
dragitem.getWidth(),
dragitem.getHeight());
}
}
else {
if (evt.id == Event.MOUSE_UP) {
// setting crop zone
if (dragingCropZone || dragingMask) {
endDrag(evt);
}
else if (dragingLine) {
addLineToPicture();
endDrag(evt);
}
}
if (evt.id == Event.MOUSE_DOWN) {
if (getEditMode() == EDTMODE_ALL) {
if (evt.modifiers == Event.CTRL_MASK) {
startDragHighLight(evt);
}
else if (evt.modifiers == Event.ALT_MASK) {
startDragLine(evt);
}
else {
if (clickedOnFocusedItem(evt)) {
startDragMask(evt);
}
}
}
}
}
}
return super.handleEvent(evt); // This passess the mouse click back up to Applet
}
Thank you,
Rather than a single Event class that includes everything, the new (relatively speaking - it's been around since Java 1.1) AWTEvent approach is to have different subclasses of AWTEvent for different purposes. In your case it's the MouseEvent subclass you're interested in, so you would need to call enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK) to enable handling of the relevant events, then override processMouseEvent and processMouseMotionEvent to do the handling.
But the preferred way to handle events is not to override the process* methods but rather to register separate listener objects. In your case you would create another class (possibly an inner class inside your main one) which is a subclass of MouseAdapter, override the relevant event hook methods in that, then register an instance of the adapter class by calling both addMouseListener and addMouseMotionListener on the main component.
There is extensive documentation on the Oracle website (and elsewhere) on how to implement event handling in an AWT or Swing application.

How to check if mediaplayer is playing or stopped?

How can I check whether the mediaplayer is playing or stopped, using Java Media Framework?
You can call getState and check against Controller.Started:
if (mediaPlayer.getState() == Controller.Started)
// Register ControllerListener :
public class myPlayer implements ControllerListener {
// ....
Player player = Manager.createRealizedPlayer(url);
player.addControllerListener(this);
// ....
// And check for EndOfMedia event in the controllerUpdate method:
public void controllerUpdate(ControllerEvent event) {
if (event instanceof EndOfMediaEvent) {
// Take appropriate action
}
}
} // End of class
By checking the state and by listening to EndOfMedia event, one could detect if media is being played or stopped.
It seems like a bit changed since the accepted answer.
The following works for me:
if(this.player.getStatus() == MediaPlayer.Status.STOPPED){
// Do something
}

Categories

Resources