简体   繁体   English

随着时间的推移运行任务?

[英]Running a task over time?

So I have an NPC and I want it to change its appearance over a period of 5 minutes, or 10 minutes if you are a special player. 所以我有一个NPC,我希望它在5分钟或10分钟(如果您是特殊玩家)中改变外观。 The NPC changes twice and then completely removes itself. NPC更改两次,然后完全删除。 Once a player dies this NPC is placed in their current position. 玩家死亡后,此NPC将放置在当前位置。 The NPC then starts to degrade over the period of 5 minutes and then eventually removes itself. 然后,NPC在5分钟的时间内开始降解,然后最终将其自身移除。 This NPC allows the player to grab their lost items before the timer runs out. 该NPC允许玩家在计时器用尽之前抢走丢失的物品。 While the NPC is there, other players have the option of making the timer reset so they have more time to get there. 当NPC在那里时,其他玩家可以选择重置计时器,以便他们有更多时间到达那里。 I was able to make it degrade and send them a message saying the time they had left to get their items back. 我能够使它降级,并向他们发送一条消息,告知他们退还物品的时间。 The only problem occurred towards the end, before it destroys itself. 唯一的问题发生在最后,直到它自我毁灭。 It constantly sends the player a message saying the time they had left rather than just once, and it never gets removed. 它不断向玩家发送一条信息,告知他们离开的时间,而不只是一次,并且永远不会消失。 Here is the code I have for it: 这是我的代码:

package com.rs.game.npc.others;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;

import com.rs.game.item.Item;
import com.rs.game.npc.NPC;
import com.rs.game.player.Player;
import com.rs.game.player.Skills;
import com.rs.utils.Logger;

public class Gravestone extends NPC implements Serializable {

    private static final long serialVersionUID = -3293609625562930841L;
    private transient Player player;
    private long BEGIN_TIME;
    private int currentGrave;
    private final CopyOnWriteArrayList<Item> container;
    private int MAX_TIME = 6*60000;//60000ms = 1 min
    private int INTERFACE = 272;
    private long timeLeft = (long) (System.currentTimeMillis() - BEGIN_TIME);
    private int minutes;

    public Gravestone(Player player, CopyOnWriteArrayList<Item> containedItems) {
        super(6601, player, -1, false, false);
        this.player = player;
        this.BEGIN_TIME = System.currentTimeMillis();
        if (player.isDonator())
            this.MAX_TIME *= player.getDonator();

        this.currentGrave = 6601;
        this.container = containedItems;
        setName(player.getDisplayName()+ "'s Gravestone");
        player.sm("A gravestone has been left in the place you died to receive your items click on it.");
    }

    public Gravestone(Player player, CopyOnWriteArrayList<Item> containedItems, long time, int npcId) {
        super(npcId, player, -1, false);
        this.player = player;
        this.container = containedItems;
        setName(player.getDisplayName()+ "'s Gravestone");

    }

    public String getName() {
        return player.getDisplayName()+ "'s Gravestone";
    }
    public void processNPC() {
        if (hasFinished())
            return;
        setName(getName());
        long timeElapsed =  System.currentTimeMillis( ) - BEGIN_TIME;
        int minute = 60000;
        int minutesElapsed = (int) (timeElapsed / minute);
        int maxMinutes = MAX_TIME / minute;
        minutes = maxMinutes - minutesElapsed;
        boolean pause = false;
        if (!pause && (minutes == 5 && getId() == 6601 //first - degrade at 5 minutes stop and wait til unpause
                || minutes == 3 && getId() == 6602 //second - degrade at 3 minutes
                || minutes <= 0 && getId() == 6603)){ //third - degrade at 1 minute
                degradeGraveStone();
                pause = true;
        } else if (pause && (minutes == 4 && getId() == 6602 //second
                    || minutes == 2 && getId() == 6603)) //third
            pause = false;
        Logger.log("GraveStone", "Player "+ player.getDisplayName() +" time elapsed "+ timeElapsed +" minutes left "+ minutes +" Pause? "+pause);
    }

    public void handleOptions(Player p, int id, int npcId) {
        switch (id) {
            case 1:
                sendMemorial(p);
                break;
            case 2:
                if (npcId == 6601)
                    demolishGraveStone(p);
                else 
                    repairGraveStone(p);
                break;
            case 3:
                    blessGraveStone(p);
                break;
            case 4:
                demolishGraveStone(p);
                break;
        }
    }

    private void degradeGraveStone() {
        if (currentGrave < 6603) { 
            graveStoneDegrade(currentGrave + 1);
        } else {
            demolishGraveStone(player);
            return;
        }
        setName(player.getDisplayName()+ "'s Gravestone");
        player.sm("Your gravestone slighlty degrades, you have" + minutes + " minutes to get your items back!");
    }

    private void demolishGraveStone(Player p) {
        if (player != p) {
            p.sm("You cannot destroy a grave that isn't yours!");
            return;
        }
        player.sm("Your gravestone has been destroyed.");
        player.sm("Your items have been added to your bank.");
        for (Item item : container)
            player.getBank().addItem(item.getId(), item.getAmount(), true);

        finish();
    }

    private void blessGraveStone(Player p) {
        if (p.getSkills().getLevel(Skills.PRAYER) < 90){
            p.sm("You need a prayer level of at least 90 to bless this Grave Stone.");
            return;
        }

        p.sm("You bless " + player.getDisplayName() + "'s Grave Stone.");
        player.sm(p.getDisplayName() + " has blessed your GraveStone.");
        graveStoneDegrade(6601);
        setName(player.getDisplayName()+ "'s Gravestone");
        BEGIN_TIME = System.currentTimeMillis();
    }

    private void repairGraveStone(Player p) {
        if (p.getSkills().getLevel(Skills.CRAFTING) < 75){
            p.sm("You need a crafting level of at least 75 to repair this Grave Stone.");
            return;
        }
        p.sm("You repair " + player.getDisplayName() + "'s Grave Stone.");
        player.sm(p.getDisplayName() + " has repaired your GraveStone.");
        graveStoneDegrade(this.getId() - 1);
        setName(player.getDisplayName()+ "'s Gravestone");
        BEGIN_TIME = System.currentTimeMillis();
    }

    private void sendMemorial(Player p) {
        p.getInterfaceManager().sendInterface(INTERFACE);
        p.getPackets().sendIComponentText(INTERFACE, 16, getName());
    }

    public Player getPlayer() {
        return player;
    }

}

I made this quick and easy. 我使这个过程变得简单快捷。 Feel free to use it! 随意使用它!

TimerID's are used to indicate which timer was the one that stopped, incase you want to have more than one timer. 如果要使用多个计时器,TimerID用来指示哪个计时器停止了。 The GameTimerListener interface has two methods. GameTimerListener接口有两种方法。

public interface GameTimerListener {

    public void SuccessfullStop(int TimerID);
    public void AbortedStop(int TimerID);
}

This is the GameTimer class. 这是GameTimer类。

public class GameTimer implements Runnable{
private Thread TimerThread = new Thread(this);

private List<GameTimerListener> Listeners = new ArrayList<GameTimerListener>();

public static final int Seconds = 0,Minutes = 1,Hours = 2;

private int TimerID;
private int TimerSeconds;
private int Timeout = -1;

private boolean Ticking;
private boolean Paused;

public GameTimer(int TimerID){ this.TimerID = TimerID; }
public GameTimer(int TimerID,int SecondsToRun){ this.TimerID = TimerID; Timeout = SecondsToRun; }

public void run(){
    long Timer = System.currentTimeMillis();
    long LastTime;

    try{
        while(Ticking){
            LastTime = System.nanoTime();
            if((System.currentTimeMillis() - Timer) >= 1000){
                Timer+= 1000;

                if(!Paused){
                   TimerSeconds++;
                }

                if((Timeout - TimerSeconds) <= 0){
                    SuccessfullStop();
                    break;
                }
            }

            Thread.sleep(10);
        }
    }catch(Exception e){ e.printStackTrace(); }
}
private int[] TimeLeftGetter(){
    int Seconds = (Timeout - TimerSeconds);
    int Minutes = 0;
    int Hours = 0;

    for(int x = 0; x < (Timeout - TimerSeconds); x++){
        if(Seconds > 60){
            Minutes++;
            Seconds -= 60;

            if(Minutes >= 60){
                Hours++;
                Minutes -= 60;
            }
        }
    }

    Seconds = Seconds <= 0 ? 0 : Seconds;

    return new int[]{Seconds,Minutes,Hours};
}
public synchronized void start(){ 
    if(Timeout == 0){ return; }
    if(Ticking){ ForceStop(); }

    TimerSeconds = 0;
    Ticking = true;

    TimerThread = new Thread(this);
    TimerThread.start();
}
public void ForceStop(){
    try{
        Ticking = false;
        TimerThread.join();

        for(GameTimerListener rtl : Listeners)
            rtl.AbortedStop(TimerID);
    }catch(Exception e){ e.printStackTrace(); }
}
public String getTimeLeftByString(){
    String time = "";
    int[] Time = TimeLeftGetter();

    time = Time[Hours] + ":" + Time[Minutes] + ":" + Time[Seconds];

    return time;
}

public boolean TimeOver(){ 
    if((Timeout - TimerSeconds) <= 0) {
        return true;
    }

    return false; 
}   
private void SuccessfullStop(){ 
    Ticking = false; 

    for(GameTimerListener rtl : Listeners)
        rtl.SuccessfullStop(TimerID);
}
public void setTimeToStop(int Seconds){
    Timeout = Seconds;

    if(Ticking){ start(); }
}
public void addGameTimerListener(GameTimerListener rtl){
    if(!Listeners.contains(rtl))
        Listeners.add(rtl);
}
public void Remove(GameTimerListener rtl){
    if(Listeners.contains(rtl))
        Listeners.remove(rtl);
}
public int getTimerID(){ return TimerID; }
public int getSecondsToRun(){ return Timeout; }
public int[] getTimeLeftByInteger(){ return TimeLeftGetter(); }
public boolean NeverStops(){ return Timeout <= -1 ? true : false; }
public boolean Ticking(){ return Ticking; }
public void setPaused(boolean Value){ Paused = Value; }
}

This is how you would go and implement this. 这就是您执行此操作的方式。 On your gravestone class, let it implement GameTimerListener. 在您的墓碑类上,让它实现GameTimerListener。

   public class Gravestone extends NPC implements Serializable, GameTimeListener {

The two methods you will use are SuccessfullStop(int TimerID):void; 您将使用的两种方法是SuccesslStop(int TimerID):void; and AbortedStop():void; 和AbortedStop():void; In the method SuccessfullStop is where you will put your code for when the time is up. 在方法SuccesslStop中,您将在时间到时放置代码。 Now, lets say you want to create a new Timer that runs for five minutes. 现在,假设您要创建一个运行五分钟的新计时器。 This is how you do it. 这就是你的做法。

GameTimer MyTimer = new GameTimer(10,1500);

The first parameter is the ID of your timer. 第一个参数是您的计时器的ID。 I decided to give it 10 as the ID, because i like the number 10. The second parameter is how long it will run in seconds. 我决定给它10作为ID,因为我喜欢数字10。第二个参数是它将在几秒钟内运行多长时间。 1500 seconds is 5 minutes. 1500秒是5分钟。

Before you start it or anything, be sure to add the gravestone class as a listener. 在开始或进行任何其他操作之前,请确保将墓碑类添加为侦听器。

MyTimer.addGameTimerListener(this);

Now, whenever you want to start the timer, just call the method: 现在,无论何时要启动计时器,都只需调用方法即可:

MyTimer.start();

This will do all the work for you. 这将为您完成所有工作。 When the timer reaches 0, it will call your SuccessfullStop() method. 当计时器达到0时,它将调用您的SuccesslStop()方法。

Now, what if you were to use two timers? 现在,如果您要使用两个计时器怎么办? Thats where the TimerID comes in use. 那就是使用TimerID的地方。 When the SuccessfullStop() method gets called, note the Integer that gets passed as a parameter. 当调用SuccesslStop()方法时,请注意作为参数传递的Integer。

public void SuccessfullStop(int TimerID){
    if(TimerID == MyTimer.getTimerID()){
         //If the timer that stopped was MyTimer..
         //Code goes here for your desired timer.
    }
}

Hope I explained myself well. 希望我能很好地解释自己。 If you still have any questions, feel free to ask! 如果您还有任何疑问,请随时提问!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 android:在UI线程中运行耗时的任务? - android: Running a time consuming task in UI Thread? SWT在运行耗时的UI任务时显示Progressbar - SWT show Progressbar while running time consuming UI task 长时间运行的任务并忽略后续的doGet()调用 - Long-time running task and ignoring subsequent doGet() calls 解决同一任务的两种算法之间的明显运行时间差 - Significant Running time difference between two algorithms solving same task Spring Quartz计划任务在一段时间后停止运行 - Spring Quartz scheduled task stops running after some time 为什么一遍又一遍地运行相同的函数(具有递增的值),我的处理时间会减少吗? - Why does my processing time drop when running the same function over and over again (with incremented values)? 与另一个任务并行运行任务 - Running a task in parallel to another task Spring 3任务调度通过注释在服务器上同时运行多个实例 - Spring 3 Task Scheduling via Annotations running multiple instances at same time on server CompletableFuture长时间运行的任务超时,它是否持有由超时将来组成的给定线程? - CompletableFuture long running task with time out would it hold thread given composed with timeout future? 使用fork-join执行长时间运行的任务几乎与单线程程序花费相同的时间 - Executing a long running task using fork-join taking almost same time as single thread program
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM