0

所以我有一个 NPC,我希望它在 5 分钟内改变外观,如果你是一名特殊玩家,则需要 10 分钟。NPC 变化两次,然后完全移除自己。一旦玩家死亡,这个 NPC 就会被放置在他们当前的位置。然后 NPC 在 5 分钟内开始退化,然后最终自行移除。这个 NPC 允许玩家在计时器用完之前拿走他们丢失的物品。当 NPC 在那里时,其他玩家可以选择重置计时器,以便他们有更多时间到达那里。我能够让它降级并向他们发送一条消息,说明他们还剩多少时间才能取回物品。唯一的问题发生在最后,在它自我毁灭之前。它不断地向玩家发送一条消息,说明他们已经离开的时间,而不仅仅是一次,而且它永远不会被删除。

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;
    }

}
4

1 回答 1

0

我做的又快又容易。随意使用它!

TimerID 用于指示哪个计时器是停止的计时器,以防您希望拥有多个计时器。GameTimerListener 接口有两个方法。

public interface GameTimerListener {

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

这是 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; }
}

这就是你将如何去实现它。在你的墓碑类上,让它实现 GameTimerListener。

   public class Gravestone extends NPC implements Serializable, GameTimeListener {

您将使用的两种方法是 SuccesslStop(int TimerID):void; 和 AbortedStop():void; 在 SuccesslStop 方法中,您将在时间结束时放置代码。现在,假设您要创建一个运行五分钟的新计时器。这就是你的做法。

GameTimer MyTimer = new GameTimer(10,1500);

第一个参数是计时器的 ID。我决定给它 10 作为 ID,因为我喜欢数字 10。第二个参数是它将运行多长时间(以秒为单位)。1500 秒是 5 分钟。

在开始之前,请确保将墓碑类添加为侦听器。

MyTimer.addGameTimerListener(this);

现在,每当您想启动计时器时,只需调用该方法:

MyTimer.start();

这将为您完成所有工作。当计时器达到 0 时,它将调用您的 SuccesslStop() 方法。

现在,如果你要使用两个计时器呢?这就是 TimerID 派上用场的地方。当调用 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.
    }
}

希望我能很好地解释自己。如果您仍有任何疑问,请随时提问!

于 2013-08-08T21:25:07.640 回答