I am making a minecraft mini game plugin, i need to make a loop that do the minigame, if the game is ended, stop it, but else continue, for making that i just created a boolean that is false and i put a :
while(isEnded) {
//my code
}
But in my code, there is async fuction, so it's repeat, but the async function don't have the time to finish before an other loop start, so all my game is glitched.
Any solution to await the async function ? ( i am using Bukkit.getServer().getScheduler().runTaskTimer(Main.plugin, new Runnable() { )
thanks for the help ;)
I don't really understand where you are stuck, but I will give you some way to do what you are looking for.
Run method from the end of mini-games.
For example, when the game when, you are running a method:
public void endGame() {
// do something
callMethod();
}
Use for another variable.
You can just set a variable, then run a task like that :
public static boolean isEnd = false;
public void runTask() {
Bukkit.getScheduler().runTaskTimer(myPlugin, () -> {
if(isEnd) {
// do something
}
}, 20, 20);
}
Finally, set the variable when it's fine with just MyClass.isEnd = true;
It will run each 20 ticks (so each second, because 20 ticks = 1 second).
If you know the time to wait, you can use the same scheduler as you are using and as I explain in #2 option.
Related
I have this code sample
public static class BlinkMe extends Thread {
int counter = 0;
protected boolean stop = true;
public void run() {
while (stop) {
counter++;
if (counter % 2 == 0) {
jLabel4.setVisible(true);
jLabel7.setVisible(true);
jLabel8.setVisible(true);
counter = 0;
} else {
jLabel4.setVisible(false);
jLabel7.setVisible(false);
jLabel8.setVisible(false);
if (jButton4.isEnabled() == false) {
stop = false;
jLabel4.setVisible(true);
jLabel7.setVisible(true);
jLabel8.setVisible(true);
if (jButton2.isEnabled() == false) {
stop = true;
jButton2.setEnabled(false);
}
}
}
}
}
}
I need to stop this Thread when I press my Stop Button...
Here's the code I'm using for the Button's function but it is not working. ***The Thread is not working at ll*
Here is the Button's function
private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {
BlinkMe b=new BlinkMe();
b.stop(); //here I have even used b.interrupt(); but doesn't stop the
}
There are many, many things wrong in this code.
you're accessing Swing components from a background thread. That's forbidden. Only the event dispatch thread is allowed to access Swing components
You're trying to stop() a thread, although this method is deprecaed and should never, ever be used, as the documentation explains
Instead of stopping the actual thread, you create a new instance of that thread class, and call stop() on that new instance.
You "blink" without any delay between the blink.
Your thread uses a stop variable, but this variable is never modified anywhere. Even if it was, it's not volatile, so you have a big chance of not seeing the modification, and thus not stopping the thread.
Read the Swing tutorial abount concurrency. And use a Swing Timer, which is designed to do that kind of thing, safely.
You are creating a new thread in actionPerformed and trying to stop the same, which was not started so far. Try calling stop in actual thread.
The initial value of your stop is "true". This means that when the thread starts, the run method executes but will not execute the while block because the condition will result to false right away.
First, you need to change your while loop into like this:
while(!stop) { /* the rest of your code */ }
Next, you need to create a method in your BlinkMe thread that would allow other objects in your program that would make it stop. The method would look something like this:
public void stopBlinking() {
stop = true;
}
Calling the above method will stop the infinite loop in the run method.
I don't think you will see a blinking effect when you run your program. It is because the loop executes very fast. I suggest you put a Thread.sleep(1000) somewhere in the loop so that there is time to reflect the blink effect visually.
I am using Bukkit API 1.8 with Java 7.
I have a repeating task that loops through all the players on the server and sets their armor randomly to either leather, chainmail, etc...
When I use the method setHelmet,setChestplate, etc... I update their inventory like usual, but since this task is running every 6 ticks, it runs fast. Therefore, when a player tries to fire a bow, the bow resets its power every time this task runs.
Since I knew it was a problem with updating the inventory, I tried removing the updateInventory method.
After doing this the armor still got put on and changed, but the bow was still being reset every time the task was ran.
How would I keep the bow from resetting while still keeping the task running?
My code:
#SuppressWarnings("deprecation")
public static void repeatEffect()
{
main.getServer().getScheduler().scheduleAsyncRepeatingTask(main, new Runnable()
{
#Override
public void run()
{
for(Player o : Bukkit.getOnlinePlayers())
{
Material M1 = Material.WOOL;
int num = rainbow.get(o.getName());
if(num==1)
{
M1 = Material.LEATHER_HELMET;
}
else if(num==2)
{
M1 = Material.CHAINMAIL_HELMET;
}
else if(num==3)
{
M1 = Material.GOLD_HELMET;
}
else if(num==4)
{
M1 = Material.IRON_HELMET;
}
else if(num==5)
{
M1 = Material.DIAMOND_HELMET;
}
rainbow.put(o.getName(), num+1);
if(rainbow.get(o.getName())>5)
{
rainbow.put(o.getName(), 1);
}
ItemStack rrhelm = createItemStack(M1, 1, "§a§lR§b§la§c§li§d§ln§e§lb§f§lo§a§lw §c§lH§d§le§e§ll§f§lm§a§le§b§lt", "§7Very special piece of armor");
o.getInventory().setHelmet(rrhelm);
}
}
}
, 6, 6);
}
If changing armour resets the players bow, you could work around it by only changing the armour of players who are joining, not wielding a bow or just after an EntityShootBowEvent.
To see if the player is wielding a bow, use:
org.bukkit.Bukkit.entity.Player player = ...;
boolean hasBowEquiped = player.getEquipment().getItemInHand().getData().getItemType().equals(Material.BOW);
After testing this some more, the only way I was able to reproduce the bow complication was by calling the deprecated updateInventory() method which you said you removed. I'm fairly certain that you still have this method somewhere in your code because I can't find anything else that would cause the bow to act this way (I was still able to fire the bow but the animation looks glitchy and the power of the arrow is sometimes incorrect).
The only difference between my code is that I used new ItemStack(M1) instead of your createItemStack() method to instantiate the helmet (also tried changing name, lore and amount). I was still able to shoot a bow just fine. Could the resetting of the bow/inventory have something to do with your createItemStack method?
There's no reason why you should be running this task asynchronously. You're accessing the Bukkit API from an asynchronous task or different thread which is a big no-no and can cause all kinds of tricky problems. Use the scheduleSyncRepeatingTask method to run the task in the same thread.
For simplicity's sake I randomly set a single armor slot (also tried all four) to either leather or iron every 6 ticks. Didn't seem to interfere with the bow. Could we see your code? Here is mine:
public void onEnable() {
this.getServer().getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
public void run() {
for (World world : Bukkit.getWorlds()) {
for (Player player : world.getPlayers()) {
if (Math.random() < 0.5) {
player.getInventory().setBoots(new ItemStack(Material.IRON_BOOTS));
} else {
player.getInventory().setBoots(new ItemStack(Material.LEATHER_BOOTS));
}
}
}
}
}, 0, 6);
}
I am trying to make a simple timer with uneven time intervals after each repetition.
I start as follows:
case R.id.start:
timerRuns = true;
startCycle();
break;
The cycle itself looks like this:
private void startCycle() {
pomodoroLeft = numPomodoro;
while(pomodoroLeft > 0) {
pomodoroLeft--;
actualSeconds = pomodoroLength * ONE_MINUTE;
setTimeAndRun(actualSeconds);
actualSeconds = shortLength * ONE_MINUTE;
setTimeAndRun(actualSeconds);
}
}
Method call:
private void setTimeAndRun(long timePeriod) {
runTime = timePeriod;
runnable.run();
}
And finally runnable itself:
private Runnable runnable = new Runnable()
{
public void run() {
if (timerRuns) {
runTime -= ONE_SECOND;
String str = String.format("%1$02d : %2$02d",
TimeUnit.MILLISECONDS.toMinutes(runTime),
TimeUnit.MILLISECONDS.toSeconds(runTime) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(runTime))
);
timeShown.setText(str);
mHandler.postDelayed(this, 1000);
if(timeShown.getText().toString().contentEquals("00 : 00")) {
stopClock();
//here goes the alarm.
}
}
}
};
My problem is that when I start the timer while loop seems to execute everything despite
incompliete run() of the previous method call. As a consequence timeShown TextView displays this actualSeconds = shortLength * ONE_MINUTE right away and skips 1 second each second because 2 runnables are running at the same time.
I want to achieve sequential execution here. What would be the best way to do so? Maybe implementing non-anonymous subclass and instantiate it every time would help?
Also, if you have any other suggestions that would improve my code I would greatly appreciate.
You should take a look at queues.
Here is a link to a similar question:
How to implement a queue of runnables
You should use the Executors.newSingleThreadExecutor()
http://developer.android.com/reference/java/util/concurrent/Executors.html#newSingleThreadExecutor%28java.util.concurrent.ThreadFactory
And here is a tutorial about the Executor:
http://tutorials.jenkov.com/java-util-concurrent/executorservice.html
here is also something that may help you understanding better multithreading in java:
Understanding multi-threading
hope this helps somehow.
I want to trigger an action after a certain time, I've been googling how I would do this but I have had no luck I guess it's just the way my game is coded.
Anyways I need to make it to where 30 minutes after the code a1 is triggered, the code a2 is triggered.
a1:
if (itemId == 608) {
c.sendMessage("The scroll has brought you to the Revenants.");
c.sendMessage("They are very ghastly, powerful, undead creatures.");
c.sendMessage("If you defeat them, you may receive astounding treasures.");
c.sendMessage("If you donate you may visit the Revenants anytime without a scroll.");
c.getPA().movePlayer(3668, 3497, 0);
c.gfx0(398);
c.getItems().deleteItem(608, 1);
}
a2:
c.getPA().movePlayer(x, y, 0);
There are plenty of ways to do timers in Java but to introduce yourself to a nice framework check out http://quartz-scheduler.org/. Also Spring has quartz integration if you use it.
But more importantly if you are creating a game you will need a core technique of game programming called the event loop
This seems like a decent discussion of how to create a game architecture
Since this code uses Project Insanity, you should use the built-in scheduled event facility provided by server.event.EventManager.
Below is example code:
if (itemId == 608) {
c.sendMessage("The scroll has brought you to the Revenants.");
c.sendMessage("They are very ghastly, powerful, undead creatures.");
c.sendMessage("If you defeat them, you may receive astounding treasures.");
c.sendMessage("If you donate you may visit the Revenants anytime without a scroll.");
c.getPA().movePlayer(3668, 3497, 0);
c.gfx0(398);
c.getItems().deleteItem(608, 1);
/* only if the parameter Client c isn't declared final */
final Client client = c;
/* set these to the location you'd like to teleport to */
final int x = ...;
final int y = ...;
EventManager.getSingleton().addEvent(new Event() {
public void execute(final EventContainer container) {
client.getPA().movePlayer(x, y, 0);
}
}, 1800000); /* 30 min * 60 s/min * 1000 ms/s = 1800000 ms */
}
You can use Thread.sleep(), but it will freeze your application if you call it in your main thread, so, create another thread and put your code in it. Doing this you will not stop the main application.
Here is a simple example.
public class MyThread implements Runnable {
#Override
public void run() {
try {
System.out.println( "executing first part..." );
System.out.println( "Going to sleep ...zzzZZZ" );
// will sleep for at least 5 seconds (5000 miliseconds)
// 30 minutes are 1,800,000 miliseconds
Thread.sleep( 5000L );
System.out.println( "Waking up!" );
System.out.println( "executing second part..." );
} catch ( InterruptedException exc ) {
exc.printStackTrace();
}
}
public static void main( String[] args ) {
new Thread( new MyThread() ).start();
}
}
This will run just one time. To run several times, you will need an infinite loop that encloses the run method body (or a loop controled by a flag).
You have some other options like:
java.util.Timer
javax.swing.Timer
HI.
I want a function in java that automatically called.
for example wen we use Time class like blew
the actionperformerd() function call every 1second.
Timer time = new Time(10,this);
.
.
.
public void actionperformed()
{
timer.run;
//i want move a pic every 1millisecond.
}
my problem is that Timer class only accept int value and it's minimum
value is 1 second and i want call actionperformed every 1 millisecond.
Java Timer accepts milliseconds in parameters. So you can do
new Timer().schedule(new TimerTask() {
public void run() {
// do stuff
}
}, 1, 1);
But to have real-time functionality with milliseconds precision you may need to switch to C.
Try some classes from java.util.concurrent, and ScheduledThreadPoolExecutor can do the thing you want to do:
public static void main(String[] args) throws Exception {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10);
executor.schedule(new Runnable() {
#Override
public void run() {
// Do something here.
}
}, 1, TimeUnit.MILLISECONDS);
}
BTW, the timer class can't run a job periodically accurately, it can only create one thread to run the task.
You could use a separate Thread
class MyThread extends Thread {
public void run() {
while (!interrupted()) {
try {
// move my object, then sleep for a millisecond
sleep(1);
} catch (InterruptedException e) {
}
}
}
}
However, in practice, you will rarely manage to have you move function called every 1 ms because other threads are also consuming processor time. So you need to take into account the actual time between the end of the previous thread loop and the current time.
I suggest you read lots of tutorials about "Game Loops", you'll learn how to organise the functions moving objects, rendering, ...
This one is an interesting article. Made for Android but can be applied to standard Java.
If this happens to be something graphical be aware that you actually update the screen in the EDT (event dispatch thread). The GUI is not multithreaded.
By hammering your EDT with updates in 1 ms intervals (even worse if you do this per pic) you might in effect make the GUI unusable - it is busy redrawing is stead of responding to user input.
I really don't know whether that effect occurs 1 ms intervals, but the single threaded design of the GUI is something to take into account.