How do you use ticks in bukkit? - java

I understand ticks, 20 ticks to a second etc. but i don't get the syntax. Can someone explain to me the steps of making something with ticks? I have a fireball move here as an example of something i need ticks for; after each time it does the effect, i need it to wait like, 2 ticks. I've looked at other examples but i really don't understand the syntax
#EventHandler
public void onPlayerInteractBlockFireBall(PlayerInteractEvent event) {
Player player = event.getPlayer();
if (player.getItemInHand().getType() == Material.MAGMA_CREAM){
List<Block> targets = player.getLineOfSight((Set)null, 30);
for (Block targetblock : targets){
Location target = targetblock.getLocation();
player.getWorld().playEffect(target, Effect.MOBSPAWNER_FLAMES,5);
}
}
}
I need to know how to add a delay to a loop, timing is really important in this plugin i'm trying to make and i just need to know the syntax.
Anyone help?

To make a timer, you can use
Bukkit.getServer().getScheduler().runTaskLater(plugin, new Runnable(){
public void run(){
//code
}
},ticksToWait);//run code in run() after ticksToWait ticks
So, if you wanted to wait 2 ticks before running the function shootFireball(), for example, you could use
Bukkit.getServer().getScheduler().runTaskLater(plugin, new Runnable(){
public void run(){
shootFireball();
}
},2L);//run code in run() after 2 ticks
plugin will be the instance of your Main class (the one that extends JavaPlugin). So, for example, your onEnable and onDisable functions in your Main class could look like this:
public static Main that; //in your case "plugin" would be "Main.that"
#Override
public void onEnable(){
that = this; //Main.that is now equal to this class
}
#Override
public void onDisable(){
that = null; //Set to null to prevent memory leaks
}
So, your code could look something like this:
#EventHandler
public void onPlayerInteractBlockFireBall(PlayerInteractEvent event) {
Player player = event.getPlayer();
if (player.getItemInHand().getType() == Material.MAGMA_CREAM){
List<Block> targets = player.getLineOfSight((Set)null, 30);
for (int i = 0; i < targets.size(); i++){
//call the spawnFlames with "i * 2" ticks, because
//every time "i" is incremented, there is a new target block
//which means we should wait 2 more ticks than the previous
//iteration before running the task
spawnFlames(player, targets.get(i), i * 2);
}
}
}
public void spawnFlames(final Player player, final Block target, final long ticks){
Bukkit.getServer().getScheduler().runTaskLater(Main.that, new Runnable(){
public void run(){
Location target = targetblock.getLocation();
player.getWorld().playEffect(target, Effect.MOBSPAWNER_FLAMES,5);
}
},ticks);
//run code in run() after "ticks" ticks
//"ticks" will be equal to "i * 2" from
//the onPlayerInteractBlockFireBall() method
}

You will start using Scheduler Programming.
Look carefully at this part of the tutorial.
You need a repeating task for this purpose:
First, create a class that extends BukkitRunnable.
Then override the Runnable.run() method: it will be called once per iteration.
Now start the task with BukkitRunnable.runTaskTimer(Plugin, long, long).
You can stop it at any time using BukkitRunnable.cancel().
You could implement the feature like this:
List<Block> blocks; // The target blocks
BukkitRunnable task = new MagmaEffect(blocks);
Plugin main; // The unique instance of the main class
task.runTaskTimer(main, 0L, 2L);
public class MagmaEffect extends BukkitRunnable {
private List<Block> blocks;
public MagmaEffect(List<Block> blocks) {
this.blocks = blocks;
}
private int index;
#Override
public void run() {
Block block = blocks.get(index);
block.getWorld().playEffect(block.getLocation(), Effect.MOBSPAWNER_FLAMES, 5);
index++;
if (index == blocks.size()) {
cancel();
}
}
}

Related

Set time between two if loops in java

Hi i want to set the time interval for few seconds between two if conditions. In my coding first "if" condition executes, control will stop 3 seconds after that only second "if" condition will execute.I dont want to use thread thread concept. I want some other option in java like "Timer" class etc.I tried many times but cant find solution . Please give solution for that
Thanks in advance
Here my code:
package com.example;
public class TimeBetween {
public static void main(String[] args) {
int a=5;
int b=3;
int c;
if(a!=0&&b!=0) {
c=a+b;
System.out.println("Addition:"+c);
}
if(a!=0&&b!=0) {
c=a-b;
System.out.println("Subtraction:"+c);
}
}
}
1) if is not loop, it is like conditional block
2) You may use sleep(milliseconds); after first if() { ...} block.
From oracle documentation:
Thread.sleep causes the current thread to suspend execution for a specified period. This is an efficient means of making processor time available to the other threads of an application or other applications that might be running on a computer system. The sleep method can also be used for pacing, as shown in the example that follows, and waiting for another thread with duties that are understood to have time requirements, as with the SimpleThreads example in a later section.
The most elegant solutions are either Thread.sleep or you could simulate sleep with:
Object o = new Object();
synchronized(o) {
o.wait(3000);
}
If you want to use timer you could do something like this:
But beware that the timer starts a thread in the background.
import java.util.Timer;
import java.util.TimerTask;
public class TimeBetween {
/**
* #param args
*/
public static void main(String[] args) {
final int a = 5;
final int b = 3;
Timer t = new Timer(true);
t.schedule(new TimerTask() {
#Override
public void run() {
int c;
if (a != 0 && b != 0) {
c = a + b;
System.out.println("Addition:" + c);
}
}
}, 0);
t.schedule(new TimerTask() {
#Override
public void run() {
int c;
if (a != 0 && b != 0) {
c = a - b;
System.out.println("Subtraction:" + c);
}
}
}, 3000);
}
}

Listen to certain events (object listener)

Let's say I have a simple code which increments variable "counter" by 1, every 5 seconds. I would like to stop timer, when "counter" reaches 5. I would like to use object listener for this (listens to certain events). Is this possible?
public class CallMe{
static int counter = 0;
public static void main(String[] args) {
// This code increments counter variable by 1, every 5 seconds.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
counter++;
System.out.println(counter);
}
}, 1000, 5000);
}
}
It is very much possible indeed. There are two interfaces in java.util Observer and Observable. You can use these interfaces to implement the Observer Pattern. Just google with "Observable Examples" and you will find plenty of resources.
All you need to do is implement this class as Observable and create another class as Observer. When your counter reach 5, all you need to do is to call the notifyObservers() method and it will fire an event for all the registered observers.
You need to implement an Observer pattern for your variable.
The class containing your counter should maintain a collection of very class that wants to be notified about what counter is. Then when counter reaches 5, you send the notification to all the listeners.
#Override
public void run() {
counter++;
System.out.println(counter);
if(counter == 5) {
notify();
}
}
private void notify() {
for(ChangeListener l : listeners) {
l.stateChanged(new ChangeEvent(counter));
}
}
some other class:
class Obs implements ChangeListener {
#Override
public void stateChanged(ChangeEvent e) {
System.out.println(e);
}
}
You can call the cancel method on your TimerTask :
#Override
public void run() {
counter++;
if(counter == 5) {
this.cancel();
}
System.out.println(counter);
}

How to call function every hour? Also, how can I loop this?

I need a simple way to call a function every 60 minutes. How can I do this? I'm making a MineCraft bukkit plugin, and this is what I have:
package com.webs.playsoulcraft.plazmotech.java.MineRegen;
import java.util.logging.Logger;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.plugin.java.JavaPlugin;
public class Main extends JavaPlugin{
public final Logger log = Logger.getLogger("Minecraft");
#Override
public void onEnable() {
this.log.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
this.log.info("Plaz's Mine Regen is now enabled!");
this.log.info("Copyright 2012 Plazmotech Co. All rights reserved.");
this.log.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
}
#Override
public void onDisable() {
this.log.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
this.log.info("Plaz's Mine Regen is now disabled!");
this.log.info("Copyright 2012 Plazmotech Co. All rights reserved.");
this.log.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
}
public void onPlayerInteract(PlayerInteractEvent event) {
final Action action = event.getAction();
if (action == Action.LEFT_CLICK_BLOCK) {
Location l1 = event.getClickedBlock().getLocation();
} else if (action == Action.RIGHT_CLICK_BLOCK) {
Location l2 = event.getClickedBlock().getLocation();
}
}
}
I need to run a function I will implement every hour, how? Remember: The function will use l1, and l2. Also, how can I loop this to get every block inbetween?
Create a Timer object and give it a TimerTask that performs the code you'd like to perform.
Timer timer = new Timer ();
TimerTask hourlyTask = new TimerTask () {
#Override
public void run () {
// your code here...
}
};
// schedule the task to run starting now and then every hour...
timer.schedule (hourlyTask, 0l, 1000*60*60);
If you declare hourlyTask within your onPlayerInteract function, then you can access l1 and l2. To make that compile, you will need to mark both of them as final.
The advantage of using a Timer object is that it can handle multiple TimerTask objects, each with their own timing, delay, etc. You can also start and stop the timers as long as you hold on to the Timer object by declaring it as a class variable or something.
I don't know how to get every block in between.
Create a thread that will run forever and wakes up every hour to execute your data.
Thread t = new Thread() {
#Override
public void run() {
while(true) {
try {
Thread.sleep(1000*60*60);
//your code here...
} catch (InterruptedException ie) {
}
}
}
};
t.start();
You must use Bukkit Scheduler:
public void Method(){
this.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
#Override
public void run() {
// Your code goes here
Method();
}
}, time * 20L );
}
You must create a method with this and there you must call the same method.
The simplest way (in my opinion) is use Thread (the above comment has mention about it).
You can also use Timer in javax.swing.Timer
But i think - as 101100 said - you can use TimerTask. You can check this link (from IBM)

Why isn't this int incrementing?

I am stuck on probably an easy problem, but I really can't find why it isn't working. I am trying to increase mijnScore with 1 each time the method gets called. But somehow mijnScore goes back to 0 after the method is done.
int mijnScore = 0;
...
public void updateUI() {
System.out.println("updateUI");
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ikWin = true;
while(ikWin) {
mijnScore++;
System.out.println("mijnScore" + mijnScore);
Scoresp1.setText(mijnScore + "");
ikWin = false;
positie = 0;
}
}
});
}
Solved
Making the variable static solved my problem.
static int mijnScore = 0;
Please see the javadoc of the method SwingUtilities.invokeLater(..)
http://download.oracle.com/javase/1.4.2/docs/api/javax/swing/SwingUtilities.html#invokeLater(java.lang.Runnable)
It can be that the thread doing the mijnScore increments is invoked only later and this is why in the parent thread you see still the value 0 for it.
I dont know wheather you are calling with different objects or same.Just as a guess Make the variable mijnScore static then it may be ok.
why did you set ikWin = false; then loop ends in first step
If it works after you made it static, you might actually have a different problem!
Do you call updateUI() on a newly constructed class? If so, only call it on a previously constructed instance as mijnScore is local to that instance!
EDIT:
Do your classes look like this? (Maybe you should have posted more code in the question)
// Score.java
public class Score {
int mijnScore = 0;
JLabel scoreSp1 = new JLabel();
public Score(JDialog dialog) {
dialog.add(scoreSp1);
}
...
public void updateUI() {
// Code from question
}
}
// Window.java
public class Game {
...
public void scoredPoint() {
JDialog dialog = new JDialog("You scored!");
new Score(dialog).updateUI();
dialog.setVisible(true);
}
}
In this silly example, the problem is actually in the second class - you shouldn't create a new Score instance every time. For the example, the code should be written like this:
// Window.java
public class Game {
JDialog dialog = new JDialog("You scored!");
Score score = new Score(dialog);
...
public void scoredPoint() {
score.updateUI();
dialog.setVisible(true);
}
}

Can a thread only execute certain methods in Java?

I'm working on making an interface for a robot. My Robot class has methods that include movement, stopping movement and reading sensor data. If at all possible, I'd like to have certain methods run under a given thread and certain other methods run under another. I'd like to be able to send the command to move to the robot object, have the thread executing it sleep duration milliseconds and then stop movement, but I'd like the stop() method able to be called and interrupt the thread executing the movement. Any help is greatly appreciated.
public class robotTest
{
public static void main(String[] args) throws InterruptedException
{
Robot robot = new Robot(); //Instantiate new Robot object
robot.forward(255, 100, Robot.DIRECTION_RIGHT, 10); //Last argument representing duration
Thread.sleep(5000); //Wait 5 seconds
robot.stop(); //Stop movement prematurely
}
}
I would suggest instantiating your Robot class with an ExecutorService that you can use for moving asynchronusly. Submit the movement request to your service and use the Future returned to 'stop' the move request.
class Robot{
final ExecutorService movingService = Executors.newSingleThreadExecutor();
private volatile Future<?> request; //you can use a Deque or a List for multiple requests
public void forward(int... args){
request = movingService.submit(new Runnable(){
public void run(){
Robot.this.move(args);
}
});
}
public void stop(){
request.cancel(true);
}
}
If I'm understanding you correctly then yes, you can call methods on an object from any given thread. However, for this to work in a bug free fashion the robot class needs to be thread safe.
Make sure all your calls to Robot come from a thread (a class extending Thread that you create) with permissions to make the calls. Add this method to your call.
Note: this code is far from perfect. But it may give you some ideas you can use in your application.
public void stop() throws NoPermissionException {
checkStopPermission(); // throws NoPermissionException
// rest of stop here as normal
}
/**
* Alternatively you could return a boolean for has permission and then throw the NoPermissionException up there.
*/
private void checkStopPermission() throws NoPermissionException() {
try {
Thread t = Thread.currentThread();
RobotRunnableThread rrt = (RobotRunnableThread)t; // may throw cast exception
if(!rrt.hasPermission(RobotRunnableThread.STOP_PERMISSION)) { // assume Permission enum in RobotRunnableThread
throw new NoPermissionExeception();
}
} catch(Exception e) { // perhaps catch the individual exception(s)?
throw new NoPermissionException();
}
}
You have to start a new background thread when you instantiate a Robot that would handle movement. The thread would sit there, waiting for a signal from forward or stop and do the appropriate thing.
You will have to synchronize the threads using either semaphores, wait handles, or other inter thread communication elements.
The least robust solution that wastes the most CPU (this is pseudo code since I have not used Java in a while, might be intermixed with .NET APIs):
public class Robot implements IRunnable {
public Robot() {
new Thread(this).Start();
}
private int direction = 0;
private int duration = 0;
private bool go = false;
public void Run() {
DateTime moveStartedAt;
bool moving = false;
while(true) {
if(go) {
if(moving) {
// we are already moving
if((DateTime.Now - moveStartedAt).Seconds >= duration) {
moving = false;
}
} else {
moveStartedAt = DateTime.Now;
moving = true;
}
} else {
moving = false;
}
}
}
public void forward(int direction, int duration) {
this.direction = direction;
this.duration = duration;
this.go = true;
}
public void stop() {
this.go = false;
}
}
(the above code should be modified to be Java for better answer)
What is wrong with this code:
The Run() method consumes one whole Core (it has no sleeps)
Calling stop() and then forward() right away can result in a race condition (the Run() has not seen the stop yet, but you already gave it another forward)
There is no way for Run() to exit
You can call forward() to redirect the move that is already in progress
Others?

Categories