I've been trying to create a custom inventory and everything seems fine but in-game when I try to right-click the item that opens the inventory, the inventory doesn't open.
Inventory playerInfoInv = plugin.getServer().createInventory(null, 27, ChatColor.GOLD + "Player Info");
p.openInventory(playerInfoInv);
}
#EventHandler
public void onInteract(PlayerInteractEvent e) {
Player p = e.getPlayer();
Material getItemInHand = e.getItem().getType();
Action a = e.getAction();
if (getItemInHand.equals(SKULL_ITEM)) {
if (a.equals(Action.LEFT_CLICK_AIR))
playerInfoInventory(p);
}
}
This is the skull item meta if it might impact this:
//Player skull
ItemStack pSkull = new ItemStack(SKULL_ITEM,1,(short) SkullType.PLAYER.ordinal());
SkullMeta pMeta = (SkullMeta) pSkull.getItemMeta();
pMeta.setOwner(p.getName());
pMeta.setDisplayName(ChatColor.BLUE + "Player Info");
ArrayList<String> pSkullLore = new ArrayList<String>();
pSkullLore.add(ChatColor.WHITE + "Show Player Stats");
pMeta.setLore(pSkullLore);
pMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
pSkull.setItemMeta(pMeta);
p.getInventory().setItem(0, pSkull);
At first: e.getItem() can be null. So maybe you could get an NullPointer.
The second: ItemStack#getType() returns Material. And you are checking for SKULL_ITEM not Material.SKULL_ITEM (same mistake you made at initializing your variable pSkull).
The Third: Check if your Listener is Registered.
Related
I'm making a simple Player/Session system but I just found a logic error even that it seems to me that everything is in order.
Let me describe my idea, I'm still learning how OOP works, that's why I'm practicing in this project :
First of all I created two classes :
Class Players
Class Session
In the Session's class I have a method named joinSession(Session s);
This method will make the player's object join the session like so :
Session s1 = new Session();
Player p1 = new Player(name : "Jack");
p1.joinSession(s1);
The problem is that in the Session attributes I have a :
public Player firstPlayerToJoin;
public Player lastPlayerToJoin;
Whenever I make a player join a session everything seems to be fine, Jack is firstPlayerToJoin and lastPlayerToJoin. But the real probleem is when another player decides to join for example :
Player p2 = new Player("Rose");
p2.joinSession(s1);
Rose will once again be firstPlayerToJoin and lastPlayerToJoin instead of only being the lastPlayerToJoin.
Here's my code :
First Player class
private static int id;
private Session session;
boolean isOnSession = false;
public static String name;
public static void say(String message){
System.out.println(name + " says " + message);
}
// Player join session
public void joinSession(Session s){
this.session = s;
System.out.println(name + " joined the session : " + this.session.sessionName );
System.out.println("Players ONLINE = " + s.playersOnline);
if( s.playersOnline == 0){
s.firstPlayerToJoin = this;
s.lastPlayerToJoin = this;
} else {
s.lastPlayerToJoin = this;}
s.playersOnline++;
}
public void quitSession(){
this.session = null;
isOnSession = false;
System.out.println(name + " left his session.");
}
Player(String name){
id = id++;
this.name = name;
}
public static void showPlayerInfo(Player n){
System.out.println("========== Player INFO ==========");
System.out.println("ID : " + id + "\nName : " + name );
}
}
Here's Session class :
public class Session {
int id = 0;
int maxConnected = 10;
public int playersOnline = 0;
String[] playersConnected = new String[maxConnected];
public String sessionName;
public Player firstPlayerToJoin;
public Player lastPlayerToJoin;
Session(){
this.id=id++;
this.sessionName = "SESSION"+id;
}
public void sessionInfo(){
System.out.println("======== Session INFO ========");
System.out.println("Session name : " + sessionName);
System.out.println("Players online : " + playersOnline);
System.out.println("First player to join : " + firstPlayerToJoin.name);
System.out.println("Last player to join : " + lastPlayerToJoin.name);
System.out.println("==============================");
}
int getPlayersOnline(){
return this.playersOnline;
}
}
And finally the main class and method :
public class Main {
public static void main(String[] args) {
Player p1 = new Player("Omar");
Session s1 = new Session();
p1.joinSession(s1);
s1.sessionInfo();
Player p2 = new Player("Rick");
p2.joinSession(s1);
s1.sessionInfo();
}
}
If there's any question or confusion about the idea, let me know.
Actual output :
Omar joined the session : SESSION0
Players ONLINE = 0
======== Session INFO ========
Session name : SESSION0
Players online : 1
First player to join : Omar
Last player to join : Omar
==============================
Rick joined the session : SESSION0
Players ONLINE = 1
======== Session INFO ========
Session name : SESSION0
Players online : 2
First player to join : Rick
Last player to join : Rick
==============================
In the line just before the last one we can see : First player to join : Rick
Player's object p1 overrides the attribute even if there's a condition that's not true.
I am going to elaborate on RealSkeptic's comment (which I did not figure out until he said it).
You have your name field as static. Currently, if you were to write (p1 == p2) you would get false, because they are indeed different objects. By making this a static variable, you are setting it for your entire class (Static variables are called class variables). What you intended to do is localize your variable so that your individual players would have their own names.
Therefore:
public static String name;
should be:
public String name;
Your IDE is probably telling you that you are accessing name in an incorrect way right now. When accessing static variables or methods, you access them through the class themselves rather than objects of that class.
e.g.
Player.NAME
rather than
Player p1 = new Player("tom");
p1.NAME;
because, as mentioned, they are for the class themselves rather than local object instantiations of said class. Here is some further reading if you would like:
I want to create a simple reservation application, like when you want to book movie ticket online, except this is a much simplified version.
I have a class names reservation with 8 toggle buttons and 1 button, the user will get to input number of seat they want to book in another class, let's just say 4.
In reservation, after the user choose 4 seats, the rest of the toggle button will be disabled to prevent user from choosing more seats. The user will then click the save button, and the data will then be inputted in the Database. Next time when another user open reservation, all of the toggle buttons will be re-enabled except those 4 seats previous user has booked earlier, obviously.
Everything is working so far except the part that i bold.
Here's my code :
private static final JToggleButton[] btn = new JToggleButton[8];
private int totalrow, a;
java.sql.Connection connection = null;
Statement statement4 = null;
ResultSet resultSet = null;
private void formWindowActivated(java.awt.event.WindowEvent evt) { // This is where i load the information that has been saved in the database before.
try {
connection = DriverManager.getConnection("jdbc:derby:
statement4 = (Statement) connection.createStatement();
resultSet = statement4.executeQuery("SELECT reservationid, seatno, validator FROM reservation WHERE reservationid = '" + time.id + "'");
String seatno, validator, rsid, id;
btn[0] = seat1;
btn[1] = seat2;
btn[2] = seat3;
btn[3] = seat4;
btn[4] = seat5;
btn[5] = seat6;
btn[6] = seat7;
btn[7] = seat8;
int i = 0;
while(resultSet.next()){
seatno = resultSet.getString("seatno");
validator = resultSet.getString("validator");
rsid = resultSet.getString("reservationid");
if(seatno.equals(btn[i].getText()) && validator.equals("reserved")){ //checking if seat i is reserved
btn[i].setSelected(true);
}
else{
btn[i].setSelected(false);
}
i++;
}
} catch (SQLException ex) {
Logger.getLogger(seat.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void actionPerformed(ActionEvent e) { // This actionlistener is used to count, if User has choose 4 seats, the code will disable the rest of the button
try {
connection = DriverManager.getConnection("jdbc:derby://localhost:1527/Project","root","root");
statement = (Statement) connection.createStatement();
btn[0] = seat1;
btn[1] = seat2;
btn[2] = seat3;
btn[3] = seat4;
btn[4] = seat5;
btn[5] = seat6;
btn[6] = seat7;
btn[7] = seat8;
a = 0;
for(JToggleButton btns : btn){
if (btns.isSelected()){
a++;
System.out.println(a);
if (! btns.isSelected()){
System.out.println(a);
a--;
}
}
}
for(JToggleButton btns : btn){
if (a >= Integer.parseInt(BookingUI.passenger)){ // This is number of Passenger taken from another class. In this case is 4.
if(! btns.isSelected()){
btns.setEnabled(false);
}
}
else{
btns.setEnabled(true);
}
}
} catch (SQLException ex) {
Logger.getLogger(seat.class.getName()).log(Level.SEVERE, null, ex);
}
}
Regarding my title, based on my current code and logic, it might not be possible to re-enable the toggle button. So the better way to do it might be to use another logic to disable the toggle button instead.
In the image, seat 1,4,5,8 are chosen by the user. And the rest of the buttons are disabled
Since it's a long implementation, it's difficult to answer with a code solution. There for I will mention my suggestion here.
You have to declare your JToggleButton Array like this btn = new JToggleButton[8]; in a public static context where every class could access it. And when the user reserved a seat you should save the data to DB (or keep in the program memroy, eg : HashMap) on which user reserved the which seat.
After that when you loading the data from the Database you should loop through and get the booked seats which previously inserted and then by accessing that predefined JToggleButton Array and set each booked seat by doing this btns[i].setEnabled(false); (i for the booked index of the seat).
Hope this helps
I want to create a custom Skeleton that has a name, more health and holds other custom items.
I can add a name and setHealth(), but I can't setMaxHealth() and also setting items and armor just won't work.
Thanks for helping, here is my code:
Player p = (Player) sender;
WorldServer world = ((CraftWorld)p.getWorld()).getHandle();
Location loc = p.getLocation();
if (args.length > 0) {
if (args[0].equalsIgnoreCase("define")) {
//get worldedit selection
if (getWorldEdit().getSelection(p) == null) {
p.sendMessage(title + "Please select a region with WorldEdit");
return false;
}
s = getWorldEdit().getSelection(p);
Location min = s.getMinimumPoint();
Location max = s.getMaximumPoint();
//boss mob creation
EntitySkeleton boss = new EntitySkeleton(world);
boss.setHealth(400);
boss.setCustomName("§4§lDAFT BOSS");
boss.setCustomNameVisible(true);
ItemStack weapon = new ItemStack(Material.DIAMOND_SWORD);
weapon.setDurability((short) 0);
weapon.addEnchantment(Enchantment.DAMAGE_ALL, 5);
weapon.addUnsafeEnchantment(Enchantment.KNOCKBACK, 2);
boss.setLocation(max);
world.addEntity(boss);
}
That can be obtained using the Attributable interface, as said in this thread from Spigot.
Example:
For 1.9 and over:
Entity boss;
Attributable bossAttributable = (Attributable) boss;
AttributeInstance ai = bossAttributable.getAttribute(Attribute.GENERIC_MAX_HEALTH);
ai.setValue(400.0);
For 1.8.8 and lower, this must be done another way:
Entity boss;
Damageable bossDamageable = (Damageable) boss;
bossDamageable.setMaxHealth(400.0);
I am trying to make my plugin monitor kills and hp of a player but I am currently getting issues with both health and kills with the same error.
I have even tried using null selection to check if it is null and not use it but that wouldn't work as I need the information to show.
I basically need to set the players hp and name as the scoreboard and the kills as the score. (Thank you in advance).
This sets the players kills when joining:
#EventHandler
public void onPlayerLogin(PlayerJoinEvent e) {
String player = e.getPlayer().getName();
if(!PlayerHandler.GPlayed.containsKey(player)){
PlayerHandler.GPlayed.put(player, 0);
}
if(!PlayerHandler.kills.containsKey(player)){
PlayerHandler.kills.put(player, 0);
}
if(!PlayerHandler.HRound.containsKey(player)){
PlayerHandler.HRound.put(player, 0);
}
}
And here is a debug I tried creating but the same error still shoots with the relevant checks all being correct.
#SuppressWarnings("deprecation")
public void run(String arena){
for(String key : Handler.playerMap.keySet()){
if (Handler.playerMap.get(key).contains(arena)){
Player pt = Bukkit.getPlayer("Nubzz");
String p = pt.getDisplayName();
Player nubzz = Bukkit.getPlayer("Nubzz");
nubzz.sendMessage(key);
nubzz.sendMessage(pt + "");
nubzz.sendMessage(p);
ScoreboardManager manager = Bukkit.getScoreboardManager();
Scoreboard board = manager.getNewScoreboard();
Objective objective = board.registerNewObjective("test", "dummy");
objective.setDisplaySlot(DisplaySlot.SIDEBAR);
objective.setDisplayName(ChatColor.AQUA + "Wave: " );
Score score = objective.getScore(ChatColor.GREEN + "" + pt.getHealth() + ChatColor.WHITE + p + ChatColor.AQUA);
int kills = PlayerHandler.kills.get(p);
score.setScore(kills);
int pcheck = 0;
This shows the debug working and showing the player has kills (Maybe I'm checking the wrong variables values):
https://gyazo.com/35a83b11a1fb384789a15ae54116248d
I'm writing a program to simulate a waiting queue for campus students this program users a linked list to do the queue and I used a button click event to execute the code.
It works only once every time add it only holds one student I think it because the list gets cleared after the button click event. I just want know is there a way to keep the list active till I terminate the main program.
My Code Below:
private void addStd1ActionPerformed(java.awt.event.ActionEvent evt) {
Queue stdQue = new LinkedList(); <-- Create the queue
String stName = addStdName.getText();
int sId;
int stdQuality;
if(!stName.isEmpty()){
// Generate a random number as Id
RanNum tempId = new RanNum();
sId = tempId.genNum();
// Generate a random number as a quality number to be matched later with the apartment
RanNum tempQuality = new RanNum();
stdQuality = tempQuality.genNum();
//StdDetails sTn = new StdDetails(sId, stName, stdQuality);
stdQue.add(sId);
stdQue.add(stdQuality);
stdQue.add(stName);
Object atTop = stdQue.element().toString();
if (!stdQue.isEmpty()){
crntTop.setText("Current top of the list: " + atTop + " Student ID: " + sId);
addStdName.setText("");
}else{
crntTop.setText("Queue list is empty.");
}
}else{
crntTop.setText("Please, enter student name.");
}
if(!stdQue.isEmpty()){
for(Object name : stdQue){
lstQue.setText(name.toString());
}
}
}
The above code functions with out error I just want to find out to keep the queue live until the user terminate the main program.
I think this can be archived in a CLI program using a while loop but this is a GUI program I don;t know how to do that in a this format.
UPDATE
I made changes according to #learninloop when I do that I get an error "Cannot Find Symbol:method addStd1ActionPerformed(evt)". Also like to inform you that I'm using NetBeans 8.0.2 as my java IDE.
addStd1.setText("Add Student");
addStd1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {addStd1ActionPerformed(evt);}
And the changed main code is below:
class stdQueCls{
Queue stdQue;
public stdQueCls(){
stdQue = new LinkedList();
}
private void addStd1ActionPerformed(java.awt.event.ActionEvent evt) {
/*AddStdFrm newWindow = null;
newWindow = new AddStdFrm();
newWindow.setVisible(true);
this.setVisible(false);*/
String stName = addStdName.getText();
if(!stName.isEmpty()){
//StdDetails sTn = new StdDetails(sId, stName, stdQuality);
int sId;
int stdQuality;
RanNum tempId = new RanNum();
sId = tempId.genNum();
RanNum tempQuality = new RanNum();
stdQuality = tempQuality.genNum();
stdQue.add(sId);
stdQue.add(stdQuality);
stdQue.add(stName);
Object atTop = stdQue.element().toString();
if (!stdQue.isEmpty()){
crntTop.setText("Current top of the list: " + atTop + " Student ID: " + sId);
addStdName.setText("");
}else{
crntTop.setText("Queue list is empty.");
}
}else{
crntTop.setText("Please, enter student name.");
}
if(!stdQue.isEmpty()){
for(Object name : stdQue){
lstQue.setText(name.toString());
}
}
}
}
UPDATE
I changed the code and put my linked list in to a class and moved it totally out of the button click event. So the new code as follows,
class stdQueCls{
Queue stdQue;
public stdQueCls(){
stdQue = new LinkedList();
if (!stdQue.isEmpty()){
for(Object all : stdQue){
lstQue.setText(all.toString());
}
}
}
}
public void addStd1ActionPerformed(java.awt.event.ActionEvent evt) {
/*AddStdFrm newWindow = null;
newWindow = new AddStdFrm();
newWindow.setVisible(true);
this.setVisible(false);*/
String stName = addStdName.getText();
if(!stName.isEmpty()){
//StdDetails sTn = new StdDetails(sId, stName, stdQuality);
stdQueCls stdQue1 = new stdQueCls();
int sId;
int stdQuality;
RanNum tempId = new RanNum();
sId = tempId.genNum();
RanNum tempQuality = new RanNum();
stdQuality = tempQuality.genNum();
stdQue1.stdQue.add(sId);
stdQue1.stdQue.add(stdQuality);
stdQue1.stdQue.add(stName);
Object atTop = stdQue1.stdQue.element().toString();
if (!stdQue1.stdQue.isEmpty()){
crntTop.setText("Current top of the list: " + atTop + " Student ID: " + sId);
addStdName.setText("");
}else{
crntTop.setText("Queue list is empty.");
}
}else{
crntTop.setText("Please, enter student name.");
}
}
Now as you see in my class I want to display what ever in the queue in a text area named queLst as you can see I have used a for loop to do it but my issue is it's not displaying the list in the text area and the other thing when it's placed inside the button click event it works but adds what ever I enter at that point can some show me a way or give an idea to how to archive this.
UPDATE
I did some changes to the above code now it working but I don't if I'm doing this wrong one things is when I retrieve the inserted data from the queue it not what I expect to see and I think still my queue linked list is not getting populated.
Can some one please have a look at my code and tell me what I'm doing is write or wrong.
class stdQueCls{
Queue<stdDetailGroup> stdQue;
public stdQueCls(){
stdQue = new LinkedList<stdDetailGroup>();
//lstQue.setText(stdQue.toString());
}
}
class stdDetailGroup{
String stdId;
String stQuality;
String stdName;
public stdDetailGroup(String a, String b, String c){
stdId = a;
stQuality = b;
stdName = c;
}
}
public void addStd1ActionPerformed(java.awt.event.ActionEvent evt) {
/*AddStdFrm newWindow = null;
newWindow = new AddStdFrm();
newWindow.setVisible(true);
this.setVisible(false);*/
String stName = addStdName.getText();
if(!stName.isEmpty()){
//StdDetails sTn = new StdDetails(sId, stName, stdQuality);
stdQueCls stdQue1 = new stdQueCls();
int stdQualityInt;
int sIdInt;
String sId;
String stdQuality;
RanNum tempId = new RanNum();
sIdInt = tempId.genNum();
sId = Integer.toString(sIdInt);
RanNum tempQuality = new RanNum();
stdQualityInt = tempQuality.genNum();
stdQuality = Integer.toString(stdQualityInt);
stdDetailGroup stdDetailsAdd = new stdDetailGroup(sId, stdQuality, stName);
stdQue1.stdQue.add(stdDetailsAdd);
Object atTop = stdQue1.stdQue.toString();
if (!stdQue1.stdQue.isEmpty()){
crntTop.setText("Current top of the list: " + atTop + " Student ID: " + sId);
addStdName.setText("");
}else{
crntTop.setText("Queue list is empty.");
}
}else{
crntTop.setText("Please, enter student name.");
}
}
private void shwQue1ActionPerformed(java.awt.event.ActionEvent evt) {
stdQueCls stdQue2 = new stdQueCls();
lstQue.setText(stdQue2.stdQue.toString());
}
As you are creating the linkedlist object stdQue inside the action performed event of button, the object is getting created and reinitialized every time the button is clicked. To make the data persistent, please take the object creation outside the button click event.
Assuming the class name as StudentManager, you can create the object inside the constructor:
class StudentManager {
Queue stdQue;
public StudentManager() {
stdQue = new LinkedList(); <-- Create the queue
}
private void addStd1ActionPerformed(java.awt.event.ActionEvent evt)
{
.
.
stdQue.add(sId);
stdQue.add(stdQuality);
stdQue.add(stName);
.
.
}
}