I am working on a plugin that allows players to fly at the cost of a item.
I have this code that works but only if the item is in the first slot of the players inventory (Hotbar) and no where else.
To enable fly I have a command class that checks the players inventory for redstone and if they have it, They are added to an arrayList based on their UUID. Inside of my onEnable I have a TaskTimer that runs continually and checks for players in the arrayList.
Bukkit.getScheduler().runTaskTimerAsynchronously(this, () -> {
for (Player player : Bukkit.getOnlinePlayers()) {
if (Fly.flyingPlayers.contains(player.getUniqueId())) {
for (int i = 0; i < player.getInventory().getSize(); i++) {
ItemStack item = player.getInventory().getItem(i);
if (item !=null && item.getType().equals(Material.REDSTONE)) {
int amount = item.getAmount() -1;
item.setAmount(amount);
player.getInventory().setItem(i, amount > 0 ? item : null);
player.updateInventory();
break;
} else {
Fly.flyingPlayers.remove(player.getUniqueId());
player.setAllowFlight(false);
player.setFlying(false);
player.sendMessage(chatColor("" + this.getConfig().getString("Prefix") + "&4You are out of fuel"));
break;
}
}
}
}
}, 20L, 20L);
The issue comes from the if. If it's redstone, it will remove the item, else it will instantly think that it's finished instead of going to next slots.
You should do something like that:
Bukkit.getScheduler().runTaskTimerAsynchronously(this, () -> {
for (Player player : Bukkit.getOnlinePlayers()) {
if (Fly.flyingPlayers.contains(player.getUniqueId())) {
boolean hasEdited = false;
for (int i = 0; i < player.getInventory().getSize(); i++) {
ItemStack item = player.getInventory().getItem(i);
if (item != null && item.getType().equals(Material.REDSTONE)) {
int amount = item.getAmount() -1;
item.setAmount(amount);
player.getInventory().setItem(i, amount > 0 ? item : null);
player.updateInventory();
hasEdited = true; // save that it have been edited
break; // break the for loop
}
}
if(hasEdited) // edited in for loop
continue; // go to next player
Fly.flyingPlayers.remove(player.getUniqueId());
player.setAllowFlight(false);
player.setFlying(false);
player.sendMessage(chatColor(this.getConfig().getString("Prefix") + "&4You are out of fuel"));
}
}
}, 20L, 20L);
Related
I am coding a game in Java, and must create a method inside an enum type that returns whether the player may fill a bottle with liquid or not. The method checks whether the player's inventory contains a bottle, and whether the player is near a liquid.
In the method declaration, I am getting an error that says I need to put an "AnnotationName" after it. I do not know what an "AnnotationName" is, and on all the other methods I have created in the file there are no such errors.
There is also another error at the bottom of the enum on the closing bracket. It says "Please insert '}' to complete ClassBody". I have checked all the curly brackets in the file and they all have matches. I think this error must be tied to the above "AnnotationName" error. I have included the method below, as well as the enum type the method is a part of.
The method by itself:
//the problematic method
#Override
public boolean isAvailable() {
//create var
boolean bottleInInventory = false;
//loop thru junk sublist
for (int i = 0; i < Data.player.sizeOfSubList(0); i++) {
//if current item is a Bottle, bottleInInventory = true; otherwise do nothing
if (Data.player.getItem(ItemType.JUNK, i).getClass() == Bottle.class) {
//set var to true
bottleInInventory = true;
}
//repeat loop until a Bottle is found (or not found)
}
//check if player is near a liquid AND if they have a Bottle in their inventory
//if they satisfy both conditions, return true
try {
if (Data.nearLiquid.get(0) != null && bottleInInventory) { //if index 0 has nothing in it, there must'nt be anything in the other indexes either.
return true;
}
} catch (IndexOutOfBoundsException e) { //if the player is not near any liquids this will happen during the above if statement.
return false;
}
return false; //if player is near a liquid and not in possesion of a Bottle
}
The whole enum:
FILL_BOTTLE("Fill Bottle") {
//this method is not complete
#Override
public void opCode() {
boolean multipleBottles; //if there is more than one bottle or not
ArrayList<Bottle> bottlesInInventory = new ArrayList<Bottle>(); //output of loop
Item currentItem; //used only inside loop
for (int i = 0; i < Data.player.sizeOfSubList(0); i++) { //loop counts how many bottles you have
currentItem = Data.player.getItem(ItemType.JUNK, i);
if (currentItem.getClass() == Bottle.class) {
bottlesInInventory.add((Bottle) currentItem); /* currentItem will always be assigned to a Bottle here,
* but we still need to cast because the
} * variable type is an Item. */
}
//multipleBottles is set to true if the bottlesInInventory list has more than one item in it
if (bottlesInInventory.size() > 1) {
multipleBottles = true;
}
System.out.println("You are currently able to fill your bottle with " + Data.nearLiquid.size() + " liquids near you");
System.out.println();
System.out.println("Here they are:");
for (int i = 0; i < Data.nearLiquid.size(); i++) {
System.out.println((i + 1) + ") " + Data.nearLiquid.get(i).getName());
}
int liquid = Data.intPrompt("Which liquid would you like to fill your bottle with? ");
}
//the problematic method
#Override
public boolean isAvailable() {
//create var
boolean bottleInInventory = false;
//loop thru junk sublist
for (int i = 0; i < Data.player.sizeOfSubList(0); i++) {
//if current item is a Bottle, bottleInInventory = true; otherwise do nothing
if (Data.player.getItem(ItemType.JUNK, i).getClass() == Bottle.class) {
//set var to true
bottleInInventory = true;
}
//repeat loop until a Bottle is found (or not found)
}
//check if player is near a liquid AND if they have a Bottle in their inventory
//if they satisfy both conditions, return true
try {
if (Data.nearLiquid.get(0) != null && bottleInInventory) { //if index 0 has nothing in it, there must'nt be anything in the other indexes either.
return true;
}
} catch (IndexOutOfBoundsException e) { //if the player is not near any liquids this will happen during the above if statement.
return false;
}
return false; //if player is near a liquid and not in possesion of a Bottle
}
},
I've tried adding curly brackets, annotations (#Override), and researched on AnnotationNames but not had any luck. I can't find any documentation on what an AnnotationName is, and the curly brackets and extra annotations just created more errors.
Edit:
Here is a link to the entire file as well as a link to the github repo with my code.
Option.java
Jump The Volcano
After searching around over the course of a few days, I have not found a solution. I have an ArrayList of collision elements that I want to iterate over and calculate collisions for. I have made several similar attempts, but I am currently stumped.
Collision method (called once a game-tick)
public void iterateCollision()
{
if(iterateBoxes)
{
if(iterateBoxes)
{
for(int i=0;i<boxPool.size();i++)
{
for(int j=i+1;j<boxPool.size();j++)
{
if(!(boxPool.get(i).equals(boxPool.get(j))) && checkCollision(boxPool.get(i), boxPool.get(j)))
{
boxPool.get(i).colliding = true;
boxPool.get(j).colliding = true;
}
}
}
}
}
}
Here is the collision detection method for those of you who would like to review it:
public boolean checkCollision(BaseAABB box1, BaseAABB box2)
{
//This is just to get the center vector of the bounding boxes.
Vector2f c1 = getAABBCenter(box1);
Vector2f c2 = getAABBCenter(box2);
if(Math.abs(c1.x - c2.x) > (box1.width + box2.width)) return false;
if(Math.abs(c1.y - c2.y) > (box1.height + box2.height)) return false;
return true;
}
You forgot to add a condition that i != j
I suspect that you should replace the following condition:
boxPool.get(i) != boxPool.get(j)
with:
!boxPool.get(i).equals(boxPool.get(j))
Further, there's no need to double loop over all the elements, you can always start with j = i + 1 and then you don't have to check that i != j:
for(int i=0;i<boxPool.size();i++)
{
// V
for(int j=i+1;j<boxPool.size();j++) // <-- this line has changed!
{
if(boxPool.get(i) != boxPool.get(j) && checkCollision(boxPool.get(i), boxPool.get(j)))
{
boxPool.get(i).colliding = true;
boxPool.get(j).colliding = true;
}
}
}
I am writing a chunk of program to play Uno with other classes. My Uno project is almost finished, but I need to be sure that the part which checks to make sure that on moves after a Wild Card is played, I play either a legal card or return a -1. Here is my code:
import java.util.*;
public class AlexaL_UnoPlayer implements UnoPlayer
{
public int play(List<Card> hand, Card upCard, Color calledColor, GameState state)
{
int play = -1;
boolean haveWild = false;
boolean matchesWildCall = false;
int indexOfWild = 0;
//turn number of cards all players are holding into ints for later use
int[] array = state.getNumCardsInHandsOfUpcomingPlayers();
int playerNext = array[0];
int playerTwoNext = array[1];
int playerBefore = array[2];
Color upCardColor = upCard.getColor();
for(int i = 0; i < hand.size(); i++)
{
//see if I have any wilds
if(hand.get(i).getRank().equals(Rank.WILD) || hand.get(i).getRank().equals (Rank.WILD_D4))
{
haveWild = true;
indexOfWild = i;
}
//set upCard color to calledColor if wild or wild_d4 are played
if (upCard.getRank().equals(Rank.WILD) || upCard.getRank().equals(Rank.WILD_D4))
{
upCardColor = calledColor;
}
//always play a card matching rank of upCard, if possible, or play the first in hand which matches color
if(hand.get(i).getColor().equals(upCardColor))
{
if(hand.get(i).getNumber() == upCard.getNumber())
{
play = i;
}
}
//if cornered(no matching number or color), play a wild
else if(haveWild == true)
{
play = indexOfWild;
}
//hold reverse cards until person next after me has less cards than person before me
if(hand.get(i).getRank().equals(Rank.REVERSE) && playerNext < playerBefore)
{
play = i;
}
//play skips when person next to me has less cards than me
if((hand.get(i).getRank().equals(Rank.SKIP) || hand.get(i).getRank().equals(Rank.DRAW_TWO)) && playerNext < hand.size())
{
play = i;
}
}
return play;
}
public Color callColor(List<Card> hand)
{
//strategy: change the color to the one i'm holding the most of
Color changeTo = Color.GREEN;
int numBlues = 0;
int numGreens = 0;
int numReds = 0;
int numYellows = 0;
//find out how many of each color i'm holding
for(int i = 0; i < hand.size(); i++)
{
if(hand.get(i).getColor().equals(Color.BLUE))
{
numBlues++;
}
else if(hand.get(i).getColor().equals(Color.RED))
{
numReds++;
}
else if(hand.get(i).getColor().equals(Color.GREEN))
{
numGreens++;
}
else if(hand.get(i).getColor().equals(Color.YELLOW))
{
numYellows++;
}
}
//find out which i'm holding the most of and call that color
//if no majority, return my favorite color(green)
if(numBlues > numReds && numBlues > numGreens && numBlues > numYellows)
{
changeTo = Color.BLUE;
}
else if(numReds > numBlues && numReds > numGreens && numReds > numYellows)
{
changeTo = Color.RED;
}
else if(numGreens > numBlues && numGreens > numYellows && numGreens > numReds)
{
changeTo = Color.GREEN;
}
else if(numYellows > numBlues && numYellows > numGreens && numYellows > numReds)
{
changeTo = Color.YELLOW;
}
else
{
changeTo = Color.GREEN;
}
return changeTo;
}
}
For some reason, my output is telling me this:
You were given this hand:
0. G7
1. G5
2. G+2
and the up card was: W
and the called color was: YELLOW
and you (wrongly) returned 2.
Valid plays would have included: -1
Can anyone provide some insight on why I am getting this error and how to fix it? Much appreciated!
Based on just this code, it is hard to say what is wrong with your implementation.
Did you try step-by-step debugging of your play function?
Alternately, it would be beneficial to instrument your code with more trace statements to better figure out where the issue might be occurring.
For example:
Every where your play variable gets assigned a value, print its value to console with some context of where you are in code.
if(hand.get(i).getNumber() == upCard.getNumber())
{
play = i;
System.out.println("number match step: play = " + play ); // You can add such a line
}
This should give you an idea as to when play's value is getting mutated to 2 unexpectedly.
Just clutching at straws here, but what are the expected values of getColor and getNumber for wild cards.
In case you have them set to Green or 2 respectively, it might explain the output you are seeing because of the following fragment of code.
//always play a card matching rank of upCard, if possible, or play the first in hand which matches color
if(hand.get(i).getNumber() == upCard.getNumber())
{
play = i;
}
else if(hand.get(i).getColor() == upCardColor)
{
play = i;
}
In my program, I have a while loop that will display a list of shops and asks for an input, which corresponds with the shop ID. If the user enters an integer outside the array of shops, created with a Shop class, it will exit the loop and continue. Inside this loop is another while loop which calls the sellItem method of my Shop class below:
public Item sellItem()
{
displayItems();
int indexID = Shop.getInput();
if (indexID <= -1 || indexID >= wares.length)
{
System.out.println("Null"); // Testing purposes
return null;
}
else
{
return wares[indexID];
}
}
private void displayItems()
{
System.out.println("Name\t\t\t\tWeight\t\t\t\tPrice");
System.out.println("0. Return to Shops");
for(int i = 0; i < wares.length; i++)
{
System.out.print(i + 1 + ". ");
System.out.println(wares[i].getName() + "\t\t\t\t" + wares[i].getWeight() + "\t\t\t\t" + wares[i].getPrice());
}
}
private static int getInput()
{
Scanner scanInput = new Scanner(System.in);
int itemID = scanInput.nextInt();
int indexID = itemID - 1;
return indexID;
}
The while loop in my main class method is as follows:
boolean exitAllShops = true;
while(exitAllShops)
{
System.out.println("Where would you like to go?\nEnter the number which corresponds with the shop.\n1. Pete's Produce\n2. Moore's Meats\n3. Howards Hunting\n4. Foster's Farming\n5. Leighton's Liquor\n6. Carter's Clothing\n7. Hill's Household Products\n8. Lewis' Livery, Animals, and Wagon supplies\n9. Dr. Miller's Medicine\n10. Leave Shops (YOU WILL NOT BE ABLE TO RETURN)");
int shopInput = scan.nextInt();
if(shopInput >= 1 && shopInput <= allShops.length)
{
boolean leaveShop = true;
while(leaveShop)
{
allShops[shopInput - 1].sellItem();
if(allShops == null)
{
System.out.println("still null"); // Testing purposes
leaveShop = false;
}
}
}
else
{
System.out.println("Are you sure you want to leave?\n1. Yes\n2. No");
int confirm = scan.nextInt();
if(confirm == 1)
{
exitAllShops = false;
}
}
The problem is here:
boolean leaveShop = true;
while(leaveShop)
{
allShops[shopInput - 1].sellItem();
if(allShops == null)
{
System.out.println("still null"); // Testing purposes
leaveShop = false;
}
}
No matter what I do, I can't get "still null" to print to confirm that I'm correctly calling the return statement of the method sellItem of the class Shop. What am I doing wrong?
After calling allShops[...].sellItem(), allShops is still a valid array reference -- there's no way it could be null! You probably want to test the return value from sellItem:
if(allShops[shopInput-1].sellItem() == null)
Hey im trying to create a random way to pick a team of 4 from a linkedlist and am wondering if this code will work.
heres an example code
public static void enterGame(Client c) {
int n = teamSize;
boolean startNewGame = false;
if(waitingPlayers.size() <= 3) {
return; // not enough players
}
startNewGame = true;
if(startNewGame) {
System.out.println("Starting new game");
for(int i=0; i<n; i++) {
Collections.shuffle(waitingPlayers);
System.out.println("Picking random player");
waitingPlayers.remove(c);
System.out.println("removing from random player list");
players.add(c);
System.out.println("adding player to ingame list");
}
}
}
I would use Collections.shuffle() and a sublist. In order to know if your code works why don't you test it (unit test or just some try)?
Also, this part:
boolean startNewGame = false;
if(waitingPlayers.size() > 3) {
startNewGame = true;
} else {
startNewGame = false;
return;
}
if(startNewGame) {
is over complicated, I would replace it by:
if(waitingPlayers.size() <= 3) {
return; // not enough players
}
Full code:
public static void enterGame(final Client c) {
if(waitingPlayers.size() <= 3) {
return; // not enough players
}
System.out.println("Starting new game");
Collections.shuffle(waitingPlayers);
System.out.println("Picking random players");
// ? to be replaced by the real type of objects inside waitingPlayers
final List<?> picked = waitingPlayers.subList(0, 3);
players.addAll(picked);
waitingPlayers.removeAll(picked);
}
You have a bug - you are picking a number from 0 to n. If n is selected, you will get an out of bounds exception. Other fhan that it seems fine.