I am currently making a plugin from the 1.8 Bukkit API. This question however, has to do with booleans. From the beginning of my class file, I have this declaration of a boolean
public static boolean lockchat = false;
Then I have another boolean in the class file that is used for Bukkit commands:
public boolean onCommand(CommandSender s, Command cmd, String label, String[] args)
This boolean returns true at the end, which I think is making the lockchat boolean return true also. If I return false, I am pretty sure that the command code will not return to the user.
My problem is that in this part of my code:
if(lockchat == true)
{
s.sendMessage("unlocked.")
lockchat = false;
}
else
{
s.sendMessage("locked.");
lockchat = true;
}
The declaration at the beginning does not seem to matter here, because this always sends me the message unlocked.
I have tried to put the declaration inside of the second boolean, but it throws me errors and warnings.
Since the second boolean is returning true, I think that the lockchat boolean is returning too. If I would change it to return false, lockchat would probably return false also, resulting in another problem.
I want to find a way to have the boolean declaration stay false, while having it changed to true/false inside of the second boolean, as shown. How would I do this?
NOTE: This variable is not used anywhere else in my code.
EDIT: I don't think this will make a difference, but I am testing for the label string to be "lockchat", the same as the boolean name. This probably wouldn't change anything, but just giving more information.
FULL CLASS FILE CODE:
package dev.td6.duocraft.commands;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import dev.td6.duocraft.main.Duocraft;
public class DCCommandLockChat implements CommandExecutor, Listener
{
Duocraft plugin;
public DCCommandLockChat(Duocraft instance)
{
plugin = instance;
}
public String colorize(String msg)
{
String coloredMsg = "";
for(int i = 0; i < msg.length(); i++)
{
if(msg.charAt(i) == '&')
coloredMsg += 'ยง';
else
coloredMsg += msg.charAt(i);
}
return coloredMsg;
}
public static boolean lockchat = false;
#SuppressWarnings("deprecation")
public boolean onCommand(CommandSender s, Command cmd, String label, String[] args)
{
if(s instanceof Player)
{
Player p = (Player) s;
if(label.equalsIgnoreCase("lockchat"))
{
if(p.hasPermission("duocraft.lockchat"))
{
if(args.length >= 1)
{
if(args.length >= 2)
{
s.sendMessage("Too many arguments. </lockchat [time]>");
}
else
{
if(lockchat == true)
{
int time = Integer.valueOf(args[0]);
s.sendMessage("locked");
lockchat = true;
plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(plugin, new Runnable()
{
#Override
public void run()
{
Bukkit.broadcastMessage("unlocked.");
lockchat = false;
plugin.getServer().getScheduler().cancelTasks(plugin);
}
}
, time*20, time*20);
}
else
{
int time = Integer.valueOf(args[0]);
s.sendMessage("locked.");
lockchat = true;
plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(plugin, new Runnable()
{
#Override
public void run()
{
Bukkit.broadcastMessage("unlocked.");
lockchat = false;
plugin.getServer().getScheduler().cancelTasks(plugin);
}
}
, time*20, time*20);
}
}
}
else
{
if(lockchat == true)
{
s.sendMessage("unlocked");
lockchat = false;
}
else
{
s.sendMessage("unlocked");
lockchat = true;
}
}
}
else
{
p.sendMessage("no access");
}
}
}
else
{
if(label.equalsIgnoreCase("lockchat"))
{
if(args.length >= 1)
{
if(args.length >= 2)
{
s.sendMessage("Too many args. </lockchat [time]>");
}
else
{
if(lockchat == true)
{
int time = Integer.valueOf(args[0]);
s.sendMessage("locked.");
lockchat = true;
plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(plugin, new Runnable()
{
#Override
public void run()
{
Bukkit.broadcastMessage("unlocked.");
lockchat = false;
plugin.getServer().getScheduler().cancelTasks(plugin);
}
}
, time*20, time*20);
}
else
{
int time = Integer.valueOf(args[0]);
s.sendMessage("locked");
lockchat = true;
plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(plugin, new Runnable()
{
#Override
public void run()
{
Bukkit.broadcastMessage("unlocked");
lockchat = false;
plugin.getServer().getScheduler().cancelTasks(plugin);
}
}
, time*20, time*20);
}
}
}
else
{
if(lockchat == true)
{
s.sendMessage("unlocked");
lockchat = false;
}
else
{
s.sendMessage("unlocked");
lockchat = true;
}
}
}
}
return true;
}
#EventHandler
public void chatLocked(AsyncPlayerChatEvent e)
{
if(lockchat==false)return;
Player p = e.getPlayer();
if(p.hasPermission("duocraft.lockchat.bypass"))return;
p.sendMessage("chat is locked.");
e.setCancelled(true);
}
}
EDIT: Also public static boolean lockchat = false; Is not being modified in any way by any other class files.
EDIT: I am using Java 7 for this.
Just so you know, in your full source you use the following code:
if(lockchat == true)
{
s.sendMessage("unlocked");
lockchat = false;
}
else
{
s.sendMessage("unlocked");
lockchat = true;
}
more specifically, you are sending "unlocked" no matter which path the code follows.
Edit: I reformatted your code to reduce some of the duplication. This version fails fast if the CommandSender is a player without permission or the label is not "lockchat". I inferred that the intention is that executing "/lockchat" without an argument should toggle locking immediately, while executing it with an argument should make it toggle for the specified number of seconds and then toggle back. The code below should do this (at least as far as ensuring lockchat always has the intended value, but I haven't tested it.
Also, I don't know if the Runnable will be called on a different thread, but if it is you should synchronize all accesses to the shared lockchat variable. At the very least, making it volatile (as I do below) may prevent some confusion amongst the threads as to its actual value.
public static volatile boolean lockchat = false;
public boolean onCommand(CommandSender s, Command cmd, String label, String[] args) {
// If this is not the 'lockchat' command, then fail fast
if (!label.equalsIgnoreCase("lockchat")) return true;
// If s is a Player then check the player has permission and fail fast
// if not.
if (s instanceof Player) {
Player p = (Player) s;
if (!p.hasPermission("duocraft.lockchat")) {
p.sendMessage("no access");
return true;
}
}
switch (args.length) {
case 0:
lockchat = !lockchat;
s.sendMessage(lockchatStatus());
break;
case 1:
int ticks = Integer.valueOf(args[0]) * 20;
final boolean originalLockChat = lockchat;
lockchat = !originalLockChat;
s.sendMessage(lockchatStatus());
plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(plugin, new Runnable() {
#Override
public void run() {
lockchat = originalLockChat;
Bukkit.broadcastMessage(lockchatStatus() + ".");
plugin.getServer().getScheduler().cancelTasks(plugin);
}
}, ticks, ticks);
break;
default:
s.sendMessage("Too many arguments. </lockchat [time]>");
break;
}
return true;
}
private String lockchatStatus() {
return lockchat ? "locked" : "unlocked";
}
As stated in Julian's answer, your code is returning unlocked no matter what the value :
if(lockchat == true)
{
s.sendMessage("unlocked");
lockchat = false;
}
else
{
s.sendMessage("unlocked");
lockchat = true;
}
As per your comment regarding as to why it is not blocking the chat, are you sure you registered your listener? To register your listener, put this line in your onEnable() method in your Main class :
getServer().getPluginManager().registerEvents(new DCCommandLockChat(), this);
Where DCCommandLockChat() is your Listener class and 'this' is your class that extends JavaPlugin.
What this basically does is register your listener for your plugin because otherwise, the server wouldn't pass any events to your listener and so your listener wouldn't know what would be happening on the server.
Also, as for the method itself returning true or false, both values will still run the command. As far as I know, the only time the return value of the onCommand method matters is when you're using aliases in your plugin.yml. If the method returns false, then the server will send the player a message with the aliases. Aside from that, it doesn't really matter.
You should give the boolean (lockchat) the value you want in the constructor of your class.
To answer your question:
I want to find a way to have the boolean declaration stay false, while having it changed to true/false inside of the second boolean, as shown. How would I do this?
At the beginning of the body of whichever statement you want, make a temporary variable to store lockChat's value.
boolean lockChatTemp = lockChat;
Then, use and modify that value within your function. This way, lockChat will keep its value throughout.
Also,
if (lockChat == true)
can be replaced with
if (lockChat) since the statement inside the parentheses evaluates to a boolean, and lockChat is already a boolean.
Related
I am trying to find a way to reduce the length and simplify the following repetitive methods :
boolean circleFlag, squareFlag, diamondFlag;
public void shapeButtonPressed(String shapeType) {
if (shapeType.equals("Circle")) {
circlePressed();
} else if (shapeType.equals("Square")) {
squarePressed();
} else if (shapeType.equals("Diamond")) {
diamondPressed();
}
}
public void circlePressed() {
if(!circleFlag){
//set only circleFlag true and the rest false.
circleFlag = true;
squareFlag = false;
diamondFlag = false;
//(... some code)
} else {
//set all flags false.
circleFlag = false;
diamondFlag = false
squareFlag = false;
//(... some different code)
}
}
public void squarePressed() {
if(!squareFlag){
//set only squareFlag true and the rest false.
squareFlag = true;
circleFlag = false;
diamondFlag = false;
//(... some code)
} else {
//set all flags false.
circleFlag = false;
diamondFlag = false
squareFlag = false;
//(... some different code)
}
}
public void diamondPressed() {
if(!diamondFlag){
//set only diamondFlag true and the rest false.
diamondFlag = true;
squareFlag = false;
circleFlag = false;
//(... some code)
} else {
//set all flags false.
circleFlag = false;
diamondFlag = false
squareFlag = false;
//(... some different code)
}
}
Things I have tried
I have tried to set all my values to Boolean type, set them in a ArrayList<Boolean> and change the shapePressed(String shapeType) method to
public void shapePressed(String shapeType) {
Boolean currFlag = false;
if (shapeType.equals("Circle")) {
currFlag = circleFlag;
} else if (shapeType.equals("Square")) {
currFlag = squareFlag;
} else if (shapeType.equals("Diamond")) {
currFlag = diamondFlag;
}
if (!currFlag){
for (Boolean flag : shapeFlag) flag = ( flag == currFlag ) ? true : false;
//(...)
} else {
for (Boolean flag : shapeFlag) flag = false;
//(...)
}
}
but the line ( flag == currFlag ) compares the booleans as values and not as individual objects. So my currFlag is pointless in this above method.
I then though of using a HashMap<String ,Boolean> but whenever I compare the values given a key (String shapeType from the method parameter), I encounter the same problem as above.
What is a way to simplify this code ?
When a given shape is activated, you just invert that flag. Then the other flags get set to false.
So, trivially, you could simplify your circlePressed() logic to:
public void circlePressed() {
circleFlag = !circleFlag;
squareFlag = false;
diamondFlag = false;
}
Of course there's still a lot of repetition. You could refactor this further to an enum and track the state there.
public enum Flag {
CIRCLE( false ),
SQUARE( false ),
DIAMOND( false ); // default state is false for all
private boolean state;
private Flag(boolean state) {
this.state = state;
}
public void flipState() {
this.state = !this.state;
}
public void setState(boolean state) {
this.state = state;
}
}
// notice this method takes the Flag not a string
public void shapeButtonPressed(Flag selected) {
// iterate through all the flags ...
for( Flag flag : Flag.values() ) {
if (flag == selected) {
// invert the "pressed" flag state
flag.flipState();
} else {
// ... and set the rest to false
flag.setState(false);
}
}
}
The built-in values method on enums returns a list of all of the defined enums, so we can just iterate across them.
It's a bit gimmicky, I admit, since it's not really what enums are intended for, but it simplifies your logic quite a bit.
You could use an enum.
public enum Shape {
CIRCLE, SQUARE, DIAMOND
}
Then, use that in your code like so;
Shape shape;
public void shapeButtonPressed(Shape selectedShape) {
shape = selectedShape;
}
If you can't change the method signature of shapeButtonPressed and it has to take a String, you can stil do
Shape shape;
public void shapeButtonPressed(String shapeType) {
if (shapeType.equals("Circle")) {
shape = Shape.CIRCLE;
} else if (shapeType.equals("Square")) {
shape = Shape.SQUARE;
} else if (shapeType.equals("Diamond")) {
shape = Shape.DIAMOND;
}
}
As an alternative to my approach with enums above (that I highly recommend over this one), you can do a more "C-style" solution using a bitmask instead of boolean flags.
A bitmask is essentially a numeric (or binary for that matter) value of which each bit represents a boolean value.
int shapeFlags;
public void shapeButtonPressed(String shapeType) {
if (shapeType.equals("Circle")) {
shapeFlags = 1;
} else if (shapeType.equals("Square")) {
shapeFlags = 2;
} else if (shapeType.equals("Diamond")) {
shapeFlags = 4;
}
}
This still leaves you the option to set more than one shape to true while being able to override all flags in a single operation.
Mappings from numeric values to shapes would look like this:
0 : no shape
1 : circle
2 : square
3 : circle & square
4 : diamond
5 : diamond & circle
6 : diamond & square
7 : all three
Hello friends I am trying to build a class Car for a project. There are many methods inside the following code as well as an if statement that I am having trouble building, consider the following code
public class Car extends Vehicle {
private boolean isDriving;
private final int horsepower;
private boolean needsMaintenance = false;
private int tripsSinceMaintenance = 0;
Car() {
super();
this.horsepower = 0;
this.isDriving = false;
this.needsMaintenance = false;
this.tripsSinceMaintenance = 0;
}
public int getHorsepower() {
return this.horsepower;
}
public boolean getDrive() {
return this.isDriving;
}
public boolean getMain() {
return this.needsMaintenance;
}
public int getTRIP() {
return this.tripsSinceMaintenance;
}
public void drive() {
this.isDriving = true;
}
public void stop() {
this.isDriving = false;
}
public void repair() {
this.needsMaintenance = false;
this.tripsSinceMaintenance = 0;
}
/**
* #param args
*/
public static void main(String[] args) {
Car auto = new Car();
auto.drive();
auto.stop();
if (auto.isDriving == true) {
if (auto.isDriving == false)
auto.tripsSinceMaintenance = auto.tripsSinceMaintenance + 1;
}
if (auto.tripsSinceMaintenance > 100)
auto.needsMaintenance = true;
System.out.println("Drive: " + auto.getDrive());
System.out.println("trip: " + auto.getTRIP());
}
}
What I want to do is whenever the attribute isDriving goes from true to false the tripsSinceMaintenance should increase by 1 and also when tripsSinceMaintenanceis greater than 100,needsMaintenanceshould becometrue`.
here I expected trips to be 1 but the result is the following:
Drive: false
trip: 0
I have tried this.isDriving==true; and basicaly wherever auto is inside the if statement I put this but the following error appears
non static variable cannot be referenced from static context
help me please!
What i want to do is whenever the attribute isDriving goes from true to false the tripsSinceMaintenance should increase by 1 and also when tripsSinceMaintenance is greater than 100 needsMaintenance should become true
Do this inside stop() method
fun stop() {
if (isDriving) {
tripsSinceMaintenance++;
}
if (tripsSinceMaintenance > 100) {
needsMaintenance = true;
}
isDriving = false;
}
You don't need to put == true inside of an if statement, it's doing that already,
if(someCondition) { // <-- this executes if the condition is true.
Also, you have conflicting conditions nested, meaning...
if (thisIsTrue) {
if (!thisIsTrue) {
// <--- unreachable statements
where you should be incrementing your variable is where you're setting "isDriving = true"
So your code would look like this:
public void drive() {
this.isDriving=true;
auto.tripsSinceMaintenance++;
}
So I have this simple boolean method for checking whether my game has ended. In the main method, I then have a big loop that starts with the statement while (isGameEnd() == false) {...}. This loop never seems to break, even when one, two or all of the conditions in the method becomes true. I don't get it.
public static boolean isGameEnd() {
if (lives == 0 || steps == 0 || isMazeCompleted()) { return true; }
else { return false; }
}
The use of static in the function definition is a red flag to me. If a class is defined with default field values, then those default values will be what is checked rather than the particular implementation of the class:
class Game {
int lives = 3;
int steps = 10;
public boolean isMazeCompleted() {
return false;
}
public void doStuff() {
lives--;
}
public static boolean isGameEnd() {
if (lives == 0 || steps == 0 || isMazeCompleted()) {
return true;
} else {
return false;
}
}
}
public static void main(String[] args){
Game a;
while(!a.isGameEnd()){ // check 'isGameEnd' for the static class
a.doStuff(); // This does *not* update the static class
}
}
Most Java editors will complain about the use of static functions in a non-static context, so will suggest Game.isGameEnd() instead of a.isGameEnd(), which makes it a bit more obvious to the programmer where the error is.
I currently have two classes Main and Command.
They are both inside of the package emerica.simple
So the classpath is emerica.simple.Main and emerica.simple.Command
In main I define a Boolean called spyblock
public class Main extends JavaPlugin{
public static boolean spyblock = true;
In command I am trying to access it and change it
public class Command implements CommandExecutor {
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (cmd.getName().equalsIgnoreCase("spyblocks")) {
return true;
if (Main.spyblock == true) {
Main.spyblock = false;
}
else {
Main.spyblock = true;
}
}
else
{
return false;
}
}
Hoe can I change this code so it works? I am trying to toggle main.spyblock this the command "Spyblocks"
Your code for altering spyblock is not reachable because of
if (cmd.getName().equalsIgnoreCase("spyblocks")) {
**return true;**
if (Main.spyblock == true) {
Main.spyblock = false;
}
else {
Main.spyblock = true;
}
}
highlighted line. just move this like
if (cmd.getName().equalsIgnoreCase("spyblocks")) {
if (Main.spyblock == true) {
Main.spyblock = false;
}
else {
Main.spyblock = true;
}
**return true;**
}
Hope this helps
You have unreachable code :
if (cmd.getName().equalsIgnoreCase("spyblocks")) {
return true;
//unreachable code
if (Main.spyblock == true) {
Main.spyblock = false;
}
else {
Main.spyblock = true;
}
}
That's why value of Main.spyblock doesn't change.
You returned your method just above your 2nd if i.e. return true;, that's why your if is not executing, you have to put return true; after your 2nd if-else condition.
If you just want to toggle it do it like this:
if (cmd.getName().equalsIgnoreCase("spyblocks")) {
Main.spyblock = !Main.spyblock;
}
I don't fully understsand what you are trying to do, but currently your code won't compile properly.
Try changing it to the following
public class Command implements CommandExecutor {
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (cmd.getName().equalsIgnoreCase("spyblocks")) {
if (Main.spyblock == true) {
Main.spyblock = false;
}
else {
Main.spyblock = true;
}
return true;
}
return false;
}
You can also change your logic, making it a bit simpler, since you do not have to check for both conditions, since you are always toggling it. Therefore just always set it to the opposite of what it currently is.
Main.spyblock = !Main.spyblock;
I've been researching how to return a random boolean and then use that returned boolean to drive an "if" statement, but I can't figure out how to structure or what syntax to use.
private Random random;
public void mousePressed(MouseEvent e) {
determineHit();
if (random = true) {
//Perform true//
}
else {
//Perform false//
}
private boolean determineHit() {
return random.nextBoolean();
}
How can I get my determineHit method to return the boolean and then plug that back into the main body of the method?
Thanks
private Random random;
public void mousePressed(MouseEvent e) {
boolean hitResult = determineHit();
if (hitResult) {
//Perform true//
}
else {
//Perform false//
}
private boolean determineHit() {
return random.nextBoolean();
}
Since an if () requires a boolean result, the == true is implied, no need to explicitly code it.
Just make sure that you have instantiated random before using it, in a constructor for example.
if (random.nextBoolean()) {
//Perform true//
} else {
//Perform false//
}